Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does processor read BIOS from SPI flash?

A typical x86 systems has firmware (aka BIOS or UEFI) stored in a SPI based Flash chip. When the power-on happens, the processor starts executing at Reset Vector which is pointing to memory-mapped SPI chip where BIOS is stored. From here onwards, the bootstrapping happens when the BIOS finishes initalization of platform, loads the bootloader, which then loads the kernel.

However, how does the processor know how to read from the SPI chip? I mean, at that point processor will not be knowing about SPI protocol, which registers of chip to write command and which register to find the data read. How does the read happen at such low level?

like image 280
Naveen Avatar asked Feb 13 '20 05:02

Naveen


1 Answers

The first thing a Haswell+ CPU does on power-up (after the BIST - Built-In Self Test) is executing a microcoded routine, part of Intel TXT technology, to fetch the FIT at 4GiB-40h and executes the BIOS ACM (Authenticated Code Module), and eventually continue the measured boot, or the fallback to the legacy reset vector at 4GiB - 10h.

Either way, the CPU needs to fetch instructions from a memory window a few MiB just below 4GiB.
The CPU doesn't have SPI interface, requests to this window are always redirected to the DMI interface, for security reasons.
You can find the following map on Chapter 2.6 of the 8th-9th generation datasheet Vol. 2 (it is true even in previous generations, AFAIK):

Memory map

which is relevant due to this paragraph:

For security reasons, the processor will positively decode this [High BIOS] range to DMI. This positive decode ensures any overlapping ranges will be ignored. This ensures that the boot vector and BIOS execute off the PCH.

So the CPU boots off the DMI interface, and hence the PCH (Platform Controller Hub) handles the requests.
Note that even in older systems, where that near-4GiB window was subtractively decoded to the DMI interface (i.e. send to the DMI interface only if no other device claimed it), the boot was almost always from the DMI interface itself.
The new positively decoded behavior is a security measure against boot attacks.

If you look at the datasheet of a relatively modern PCH, i.e. series 200, you see that it supports a Flash ROM behind either the LPC bridge or the SPI interfaces.

We will restrict ourselves to the latter.
In that chipset the SPI bridge is the PCI device 31, function 15.
In its PCI configuration space there are the standard registers and:

  • A BAR (Base Address Register) to map a 4 KiB window of MMIO register to control the SPI interface itself.
  • A BIOS Decode Enable register that enables or disables the reclaiming of the memory access in specific windows.
  • A control register to enable various security features (including if the boot is off the SPI or LPC interface).

Let's focus on the second point:

BIOS Decode Enable Register

Two things to note: first this register either enable or disable sending the memory accesses from the CPU, in the region of 4MiB below 4GiB and others, to the SPI.
The second is that the default value is 0ffcfh, meaning that by default all the windows are mapped to the SPI.
The BIOS Control Register also selects the SPI as the default boot interface but this is also configurable with softstrap/bootstrap pins, IIRC.

Last but not least, when the PCH sees an access to an address like 4GiB-10h it cannot send it as it to the Flash ROM as it would be out of range for the Flash ROM itself.
It must first decode it, subtracting an offset. However, this offset depends on the size of the Flash ROM.

Before the PCH (I think around the ICH8 chipset and in some non-too-recent Atom chipsets) the Flash ROM was used without descriptors.
The chipset simply mapped the ROM from the 4GiB down to 4GiB-16MiB with alias, meaning that the address 4GiB - X would be mapped to Flash Size - (X % Flash size).
The effect was that, e.g., a 2 MiB flash appeared mapped 8 times in the 16MiB windows below the 4 GiB limit.
In those chipsets there were bootstrap pins to configure the Flash Size.

Today Flash ROMs for the PCH use descriptors, where the flash is divided into regions (The BIOS, the ME, the GbE, etc.).
Only the BIOS region is mapped in CPU's address space. There is a system of security descriptors based on the id of the requester (given by its PCI identity).
For an introduction to this topic see this or better this for a more complete description (a bit outdated but still relevant).
Regions are relevant here because they are listed in the Flash descriptor with their offset and size, so the PCH can know how to translate the CPU addresses into the Flash Linear Addresses.

Finally, the MMIO registers of SPI interface allow for raw access to the Flash ROM. It is possible to synthesize commands to send down the SPI bus, making it possible to reprogram the Flash ROM (for example).
They are still subject to various security countermeasures that should be listed in the datasheet, IIRC.

like image 147
Margaret Bloom Avatar answered Oct 13 '22 09:10

Margaret Bloom