Skip to content

ACPI

Firmware knows things about a machine that guesswork can’t recover: how many CPUs it has, where the I/O APICs live, which PCI segment owns which bus range. ACPI is the format firmware uses to hand that knowledge to an operating system, a set of tables sitting somewhere in physical memory, waiting to be found and parsed.

Everything starts with the RSDP, the Root System Description Pointer. Firmware plants it somewhere in the first megabyte, or reports its address through the UEFI configuration table on machines that boot that way. A kernel finds the legacy copy by scanning memory in 16-byte steps for the signature string "RSD PTR ", checking a checksum, and stopping at the first match. The signature is eight bytes long on purpose, chosen to be unlikely to occur by accident in ordinary memory contents.

The RSDP itself is small. Its job is pointing at something bigger: the RSDT under the older 32-bit scheme, or the XSDT once 64-bit pointers became standard. Both are arrays of further pointers, one per table, each leading to a structure identified by its own four-byte signature: APIC for the MADT, MCFG for PCI Express configuration space, FACP for the Fixed ACPI Description Table. A kernel walks this array looking for the signatures it needs and skips the rest.

The RSDP pointing at the RSDT/XSDT, whose pointer array fans out to the MADT, MCFG, and FADT tables by signatureRSDP”RSD PTR “RSDT / XSDT→ APIC→ MCFG→ FACPACPI tablesMADT (“APIC”)CPUs, I/O APICsMCFGPCIe config spaceFADT (“FACP”)power mgmt regs

Every ACPI table, whatever it describes, opens with the same 36-byte header: signature, length, revision, a checksum, an OEM ID string, and a few other identifying fields. Two things matter here. The length field is authoritative: a table is exactly as long as it says it is, and reading past that boundary reads memory belonging to the next table or to something else. And the checksum covers the whole table, header included; every byte in it sums to zero mod 256. A kernel that skips this check risks trusting a table firmware itself would consider invalid.

The Multiple APIC Description Table answers two questions from PIC & APIC: how many CPU cores exist, and how the I/O APICs connect to legacy interrupt lines. Past its own fixed fields, the table is a sequence of variable-length entries, each tagged with a type byte. Type 0 describes a Local APIC and the CPU it belongs to. Type 1 describes an I/O APIC, its base address, and the range of interrupt inputs it covers. Type 2 is an interrupt source override, telling a kernel that some legacy IRQ number doesn’t map to the I/O APIC input a naive kernel would assume, a detail that matters more than it should on real hardware, where BIOS vendors have quietly remapped things for reasons that rarely make it into any changelog.

PCI Express’s memory-mapped configuration space needs a base address from somewhere, and MCFG is where it comes from. Each entry names a base address, a PCI segment number, and the bus range that segment covers. A desktop with one host bridge has one entry. A server with several might have more, one per segment. Nothing about MCFG is optional if memory-mapped configuration access matters to a kernel: without it, the legacy I/O ports are the only path in.

Not every ACPI table is a flat array of fixed structures. The DSDT, and any SSDTs alongside it, contain AML: ACPI Machine Language, a compact bytecode describing devices, methods, and power states in a form firmware expects an interpreter to execute at runtime. _PRT, the interrupt routing method mentioned under Interrupt delivery, lives here. So does _ADR.

Writing an AML interpreter is a project of its own, closer in scope to a small language runtime than to a table parser. Most hobby kernels never attempt it, and get by parsing the fixed tables (MADT and MCFG above all) while leaving AML alone until suspend, resume, or dynamic device discovery actually demand it.

  1. ^ ACPI Specification: the full definition of the table formats summarized above.
  • PIC & APIC: the interrupt hardware the MADT describes.
  • PCI: the configuration space MCFG makes memory-mapped.
  • Resetting and Shutting Down: the FADT reset register and the _S5 AML dependency this article’s AML section already flags.