BITS supports scripting via Python, and includes Python APIs to access various low-level functionality of the hardware platform, including ACPI, CPU and chipset registers, PCI, and PCI Express. You can write scripts to explore and test platform functionality, using the full power of Python in 32-bit ring 0, without an OS in the way, and without recompiling BITS or writing custom C code.

This guide provides an introduction to scripting BITS with Python. For more information on Python itself, see the Python documentation. BITS includes a substantial subset of the Python standard library, focusing on modules which make sense in the BITS pre-OS environment. This subset increases with new BITS releases; if you run into something that isn't included, and which seems like it could work in the BITS pre-OS environment, let us know.

Basic Python

You can run simple Python statements from the BITS command-line using the py command. (Hit 'c' from any BITS menu to reach the command line.) For example, you can use Python as a calculator:

Using Python as a calculator

Note that py runs a Python statement but does not print values automatically, so you have to write print explicitly if you want to see the result.

Also note that statements run via py use the same persistent Python environment, so you can set variables in one call to py and read them in a later call.

From Python, you have access to various high-level data structures, including tuples, lists, and dictionaries (associative arrays):

Data structures in Python

Importing modules

For more complex scripts, you can import a Python module and invoke functions from it. The BITS initialization will add /boot/python to the Python path, and you can put your Python scripts there. You can then import them from a py statement (or another imported module) and run functions from them.

Importing Python modules

The bits module

BITS provides a built-in Python module bits which provides access to low-level platform functionality. You can import bits and access functions such as cpus, cpuid, or rdmsr:

Using the bits module

You can combine this low-level access with high-level Python functionality, such as the struct module to pack and unpack data structures in memory buffers:

Example of the struct module: decoding GenuineIntel

ACPI

The bits module also provides access to ACPI, and the acpi module includes functions for decoding common ACPI constructs:

ACPI decoding example: showing the header of the DSDT

You can also find arbitrary ACPI objects by path, and evaluate arbitrary ACPI methods, with the return value decoded into a Python object:

ACPI example: finding objects and evaluating methods