This package contains an implementation of MicroPython for UEFI. MicroPython is an implementation of Python 3 optimized to run in constrained environments.
The MicroPython interpreter is a major component of the MicroPython Test Framework for UEFI.
This package contains three main components:
- MicroPython driver
- The core MicroPython interpreter implemented as a DXE protocol.
- Source code folder:
MicroPythonDxe - Binary file:
MicroPythonDxe.efi
- MicroPython application
- User interactive interface (wrapper) of the MicroPython interpreter, which can be launched as a UEFI Shell application or Shell-Independent UEFI application (via BDS Boot Option, similar to launching an OS loader).
- Source code folder:
MicroPythonApp - Binary file:
micropython.efi
- Virtual console driver
- Implement an emulated console device, used to simulate user interaction in test scripts.
All official MicroPython features are implemented, with the following exceptions:
- Floating point (including math)
- Inline assembly code
- Compiled Python bytecode
- Some hardware feature modules (pulse, i2c, ...)
- Some external libraries (select, ssl, socket, libffi, ...)
Note that MicroPython does not implement 100% of CPython syntax. Please refer to MicroPython differences from CPython for more information.
- Asynchronous execution mode (run in the background of UEFI firmware)
- Full UEFI services support (via
uefimodule) - Direct physical memory access (including memory allocation)
- Enhanced regular expression (via
_remodule)
The MicroPython Interpreter for UEFI (MicroPythonPkg) must be built in an EDK II build environment. Please refer to Getting Started with EDK II for information on setting up an EDK II build environment.
C:\edk2> edksetup.bat
C:\edk2> build -p MicroPythonPkg\MicroPythonPkg.dsc -a X64 -t VS2017 -b DEBUG
Once the build is completed, three binary files generated under the build output folder: Build\MicroPythonPkg\DEBUG_VS2017\X64
micropython.efi: main application used to launch the MicroPython interpreter.MicroPythonDxe.efi: a driver which is the actual implementation of MicroPython interpreter and will be loaded automatically bymicropython.efi.VirtualConsoleDxe.efi: virtual console driver used only for test interaction, must be loaded manually in advance.
VS2013/VS2013x86VS2015/VS2015x86VS2017
Additional toolchains will be supported in future releases.
Normally micropython.efi and MicroPythonDxe.efi must be used together and run from the same folder. micropython.efi is used as the entry application for launching the MicroPython interpreter in a UEFI environment. It will try locate and load MicroPythonDxe.efi automatically. It is not necessary to load MicroPythonDxe.efi manually in advance.
micropython.efi \[ -a | -c | -i \] \[<path_to_python_script_file> | "<single_line_python_script>"\]
-a Launch the MicroPython interpreter and then exit.
Let it run in the background
-c Execute the Python script passed on command line and then exit
-i Launch the REPL (after executing the Python script, if given)
If no option is specified on the command line, the application will enter REPL mode.
UEFI services are provided by module uefi (Lib/Uefi/uefi.py). The user must import this module before using any UEFI services in a Python script.
This module provides following global types and objects:
- `uefi.mem("c_type_string" [, <memory_address>] [, <alloc_page>] [, <read_only>])``
- A Python type used to access physical memory, including a ctypes+struct-like mechanism which can be used to describe the memory type and layout (C data type/structure/function).
uefi.efistatus- Exception corresponding to error code of
EFI_STATUS
- Exception corresponding to error code of
uefi.bs- A
uefi.memobject used to wrapgBS (EFI_BOOT_SERVICES). Users can use it to access all fields ingBS.
- A
uefi.rt- A
uefi.memobject used to wrapgRT (EFI_RUNTIME_SERVICES). Users can use it to access all fields ingRT.
- A
uefi.ds- A
uefi.memobject used to wrapgDS (EFI_DXE_SERVICES). Users can use it to access all fields ingDS.
- A
uefi.st(System Table Object)- A
uefi.memobject used to wrapgST (EFI_SYSTEM_TABLE). Users can use it to access all fields ingST.
- A
uefi.VariableStorage- A Pythonic wrapper of all variable services provided in
gRT.
- A Pythonic wrapper of all variable services provided in
The following example utilizes UEFI services:
python
import Lib.Uefi.uefi as uefi
# Reserve 8-byte memory
count = uefi.mem("Q")
try:
uefi.bs.GetNextMonotonicCount(count.REF())
print("Next monotoinc number:", count.VALUE)
except efistatus as status:
print("ERROR: cannot get next monotonic count")
# Access variable "LangCodes"
vars = uefi.VariableStorage("8BE4DF61-93CA-11D2-AA0D-00E098032B8C")
print(vars["LangCodes"])
Basic data types:
'b' : INT8
'B' : UINT8
'h' : INT16
'H' : UINT16
'l' : INT32
'L' : UINT32
'q' : INT64
'Q' : UINT64
'i' : int
'I' : unsigned int
'n' : INTN
'N' : UINTN
'G' : EFI_GUID
'P' : VOID*
'a' : CHAR8[]
'u' : CHAR16[]
'F' : (VOID*)(...)
'E' : EFI_STATUS
'T' : EFI_HANDLE
'O' : <struct>
All other complex data types (C structures) must be defined via ucollections.OrderedDict and referenced by form of O#<struct_def_variable_name>. The following example describes a C structure in Python code:
c
typedef struct {
EFI_HANDLE AgentHandle;
EFI_HANDLE ControllerHandle;
UINT32 Attributes;
UINT32 OpenCount;
} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY;
This example is a Pythonic equivalent:
python
import uefi
from ucollections import OrderedDict
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY = OrderedDict([
("AgentHandle", "T"),
("ControllerHandle", "T"),
("Attributes", "L"),
("OpenCount", "L"),
])
InfoEntry = uefi.mem("O#EFI_OPEN_PROTOCOL_INFORMATION_ENTRY")
InfoEntry.AgentHandle = uefi.null
InfoEntry.ControllerHandle = 0x12345678 # just for example
InfoEntry.Attributes = 0x80000001
InfoEntry.OpenCount = 0