Skip to content

Python UEFI Samples

Jayaprakash Nevara edited this page Sep 12, 2024 · 10 revisions

This wiki page provides sample code to use Python UEFI provided capabilities to interact with the underlying UEFI platform. Use Python UEFI to read certain platform registers such as PCIe configuration space, Module Specific Registers (MSRs), IO Port registers, MMIO registers, CPUIDinstructions execution and etc.

You may follow this wiki page to build and deploy Python UEFI interpreter. You may also use the pre-built Python UEFI interpreter available here

Executing CPUID Instructions:

Python UEFI has a built in module known as edk2 module which provides APIs to perform the basic register read/write operations.

Signature of cpuid function: cpuid(eax, ecx) -> (eax, ebx, ecx, edx) Depending on the input values EAX and ECX the cpuid function returns different information about the processor.

  1. The following code snippet demonstrates how to read the CPUID of the given platform from UEFI shell using Python script.
import edk2

# eax=0x1 and ecx=0 => result in getting the CPUID of the platform
eax=0x01
ecx=0x00
x=edk2.cpuid(eax, ecx)
print(hex(x[0]))
  1. The following code snippet demonstrates how to read vendor id string of the given platform from UEFI shell using Python script.
import edk2

# utility function to convert 32 bit hexadecimal data into bytes data type
def hex2bytes(data):
    b=bytearray()
    for count in range(4):
        d = data & 0xff
        b.append(d)
        data = data >> 8
    return b

# eax=0 and ecx=0 => result in getting the CPU vendor id string
eax=0x00
ecx=0x00
x=edk2.cpuid(eax, ecx)

# x[1] is EBX value
data = hex2bytes(x[1])

# x[3] is EDX value
data += hex2bytes(x[3])

# x[2] is ECX value
data += hex2bytes(x[2])

print(data)
vendor_string = [chr(item) for item in data]

print("Vendor String = {}".format(vendor_string))

Working with PCI/PCIe configuration spaces:

This section provides sample code snippets to read / write the PCI/PCIe configuration space registers. The edk2 module provides the necessary APIs to perform these operations.

  • readpci - This function can be used to read the PCI / PCIe extended configuration space. function signature: readpci(bus, dev, func, addr, size) -> (int)

  • writepci - This function can be used to write the PCI/PCIe extended configuration space.

  1. The following code snippet demonstrates how to read vendor id and device id values from a specific PCI device by using the bus, device, function, offset and the size of the data to read as input parameters to readpci function.
import edk2

# Read the vendor id and device id from B:D:F (0:2:0) this is the typical BDF value
# for the Integrated graphics device on Intel platforms.
data = edk2.readpci(0, 2, 0, 0, 4)
vendor_id = data & 0xFFFF
device_id = (data >> 16) & 0xFFFF

print('Vendor Id : {:#x}'.format(vendor_id))
print('Device Id : {:#x}'.format(device_id))

Working MSR - Module Specific Registers:

edk2 module provides APIs to read and write the MSR registers. This section provides some sample code snippets to read / write the MSR registers rdmsr - Function to read the MSR value rdmsr(msr) -> (lower_32bits, higher_32bits) This function takes msr value as input and returns the lower & higher 32 bits data as a tuple. MSRs are 64 bit registers.

wrmsr - Function to write the MSR value wrmsr(msr, lower_32bits, higher_32bits) -> None This function takes msr, lower and higher 32 bit data of the msr as input. Writes combined 64 bit value generated from lower and higher 32 bit data into the msr register.

  1. The code snippet below demonstrates reading of the IA32_APERF (0xE8) an architectural MSR from UEFI shell
import edk2

# 0xE8 is a performance counter MSR
data = edk2.rdmsr(0xE8)
print("Lower 32 bit data {:#x}".format(data[0]))
print("Higher 32 bit data {:#x}".format(data[1]))

Using Chipsec Open Source Tool from UEFI shell

chipsec is a framework for analyzing the security of PC platforms including hardware, system firmware (BIOS/UEFI), and platform components. Chipsec is supported on UEFI shell with the help of Python UEFI interpreter.

chipsec tool provides a lot of utilities to work with SMBIOS, ACPI, Platform registers and etc. You may go through the chipsec tool's user manual to learn more about the commands supported and their usage.

You may download the latest version of chipsec code from open source git repo

This page will be updated with more sample code