Master the fundamental concepts of bios & uefi programming through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksBefore OS PCI drivers exist, the PCI BIOS extensions (INT 0x1A, AX=0xB101) let real-mode code enumerate devices. You supply a bus/device/function triple and a register offset; the call returns configuration dword data. For example, reading offset 0x00 on bus 0 dev 0 fn 0 yields vendor ID 0x8086 for many Intel host bridges.
nasmLoading…
Vendor ID 0xFFFF means no device present at that slot.
Many UEFI-only machines omit PCI BIOS entirely; your code should detect failure via carry and fall back to MMIO ECAM if present. Function numbers above zero appear on multifunction cards like USB controllers. Always enable I/O and memory decode in the command register before expecting BAR accesses to work on real hardware after enumeration.
Underneath INT 0x1A, every config access is a write to the CONFIG_ADDRESS I/O port that packs bus, device, function, and offset into one dword: 0x80000000 | bus<<16 | dev<<11 | func<<8 | (offset & 0xFC). You will build and decode that dword in both directions: the same bit-packing the PCI BIOS performs before pushing the value to port 0xCF8.
Legacy PCI configuration space is reached by writing a 32-bit CONFIG_ADDRESS to I/O port 0xCF8 and then reading or writing the data at 0xCFC. Build and decode that dword:
| Bits | Field |
|---|---|
| 31 | enable, always 1 for a config cycle |
| 23-16 | bus (0-255) |
| 15-11 | device (0-31) |
| 10-8 | function (0-7) |
| 7-2 | register offset, dword-aligned: offset & 0xFC |
One command:
pack BUS DEV FUNC OFFSET: bus, device and function in decimal, the offset in hex (for example 0x3C).unpack ADDRESS: a CONFIG_ADDRESS in hex.pack: CONFIG_ADDRESS 0x80001010 for pack 0 2 0 0x10, as 8 uppercase hex digits.unpack: two lines, for example for unpack 0x8000F818:cLoading…
The offset is printed as 2 uppercase hex digits after masking with 0xFC.