bits-1081 released with these changes:
The "ctypes. ctypes run. run types run" release.
This release introduces preliminary support for the Python ctypes module in EFI builds. This includes the initial infrastructure to compile libffi as part of BITS.
ctypes data types, ctypes structures, and read/write access to memory
work. This replaces many uses of
struct.unpack, and the BITS
unpack module. In particular, the use
of ctypes data types and structures allows round-trip conversions from
structures in memory to Python data types and back, generally without
This initial implementation provides enough support for all the data structures in the efi module, which has now completely switched over to ctypes-based data types and structures.
- No support for non-EFI builds yet, because GRUB uses stdcall and regparm=3 for PC BIOS builds, which libffi does not support on non-Windows systems.
- Function calls to EFI functions still require
efi.call; the ctypes-based FFI does not yet work, as it does not understand the EFI calling convention.
dlopendoes not work, so there's no way to obtain pointers to existing C functions to call.
Note that to support this change, the version of Python built into BITS
now internally uses UTF-16 (2-byte characters) rather than UCS-4 (4-byte
characters), to match EFI. This allows the use of the ctypes functions
for the C
wchar_t type, rather than hand-rolled functions for two-byte
Unicode. Python still has full support for all of Unicode, including
characters outside the Basic Multilingual Plane; this just changes the
internal representation. However, attempting to use characters outside
the BMP in EFI calls may or may not work, depending on your firmware;
your mileage may vary.
This release also introduces support for reading and writing files using
EFI. On EFI systems, BITS now has full support for writing arbitrary
files to a FAT filesystem. The new
efi.get_boot_fs() function will
retrieve the filesystem BITS booted from, as an
efi_file, a new Python
file-like object. In addition to the usual file methods, an
provides methods to open and create files and directories. For example:
import efi root = efi.get_boot_fs() newdir = root.mkdir("newdir") newfile = newdir.create("newfile") newfile.write("Hello world!\n")
Or, chaining the calls together (convenient for command-line usage):
The new functions
this new filesystem write capability to save copies of ACPI and EFI
tables, for later inspection.
Note that EFI firmware typically only supports FAT filesystems, not
iso9660 (the filesystem used on optical media). The BITS .iso images,
even when imaged to a USB disk, keep most of their files in an iso9660
filesystem, with the exception of a small FAT filesystem used to store
GRUB itself as an EFI binary. Thus,
get_boot_fs() will not produce
the expected results when booting from an optical disc or from a disk
created from a BITS .iso; for full read/write support, create a
FAT-based BITS disk, following the procedure in INSTALL.txt.
This release adds support for many new EFI protocols:
efi: Add read/write file support using FileProtocol, including a file-like object
efi_filewrapper includes the standard Python file-like methods (
flush), EFI-specific properties (
volume_label) and methods (
delete), and methods to create or open another
efi_filerelative to a directory (
Also add a definition of the EFI SimpleFileSystemProtocol to open a block device, with a
rootproperty to get the root directory as an
get_boot_fs()function to return the filesystem BITS booted from, obtained via the DeviceHandle of the LoadedImageProtocol on the image handle. Useful as the root for writing files.
efi: Add DevicePathProtocol and DevicePathToTextProtocol
DevicePathToTextProtocol includes helpers to transform the returned paths into Python unicode strings, and then free the original memory.
efi: Add LoadedImageProtocol
Other changes in this release:
python: Support the zlib module
bits.present, mkpresent: Use zlib to compress and decompress slide images
Provides an order of magnitude improvement to disk usage and load time.
acpi: Add an
efi_save_tablesutility function to save ACPI tables to files
As the name suggests, this function only works on EFI, since it uses the EFI file write support.
In addition to the binary dumps, this also includes text decodes of selected structures, and enough address information to recreate the tables in memory.
efi: Add a function
efi.save_tables()to save the core EFI tables to files
efi: As a workaround for limitations in the internal EFI function call interface, add a compatibility layer for 64-bit arguments on 32-bit platforms. Wrap 64-bit arguments in
efi.split64(), and they will automatically be split into pairs of 32-bit arguments on 32-bit platforms, for compatibility with the current
Add EFI tests. The first round of tests verifies the CRCs of the core EFI tables.
efi: Add a base class for EFI protocols
Protocols are ctypes structures with an associated GUID; they provide a
.from_handleclassmethod to get the protocol from an EFI handle (via OpenProtocol) and wrap it in the protocol class.
efi: Add more known UUIDs
efi: When printing structures, format pointers and unsigned types as hex, and list out the contents of arrays.
efi: Various new helper functions:
- Add a helper function
check_statusto throw an exception for !=
- Add a helper check_error_value to handle non-status return values.
Some EFI functions return a non-status return value, but still use
EFI_ERRORbit to indicate an error. Add a helper that checks only that bit, and otherwise returns the value for subsequent use.
- Add a
locate_handleshelper to call LocateHandle with a given GUID. This helper handles the two-pass memory allocation, and returns a ctypes array of handles.
- Add helper functions to compute table CRC32 values. These compute the CRC32 as if the table's CRC32 field is 0, and then compare the result to the table's actual CRC32 field.
- Add a helper function
efi.to_bytesto convert a ctypes structure to raw bytes
- Add a helper function
README.Developers.txt: Document Python patches for ctypes and libffi