处理器如何从 SPI 闪存读取 BIOS?

How does processor read BIOS from SPI flash?

典型的 x86 系统将固件(也称为 BIOS 或 UEFI)存储在基于 SPI 的闪存芯片中。上电时,处理器开始执行复位向量,该向量指向存储 BIOS 的内存映射 SPI 芯片。从这里开始,引导发生在 BIOS 完成平台初始化、加载引导加载程序、然后加载内核时。

但是,处理器如何知道如何从SPI芯片读取数据呢?我的意思是,此时处理器将不知道 SPI 协议,芯片的哪些寄存器写入命令以及读取数据的寄存器。读取如何发生在如此低的水平?

Haswell+ CPU 上电时(在 BIST - 内置自检之后)做的第一件事是执行微码例程,Intel TXT technology, to fetch the FIT at 4GiB-40h and executes the BIOS ACM (Authenticated Code Module), and eventually continue the measured boot 的一部分,或者回退到4GiB 的传统重置向量 - 10h。

无论哪种方式,CPU 都需要从内存中获取指令 window 几个 MiB,刚好低于 4GiB。
CPU 没有 SPI 接口,出于安全原因,对此 window 的请求总是重定向到 DMI 接口。
您可以在8th-9th generation datasheet Vol. 2的第2.6章找到以下地图(即使在前几代也是如此,AFAIK):

由于本段而相关:

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.

因此 CPU 从 DMI 接口启动 ,因此 PCH(平台控制器中心)处理请求。
请注意,即使在较旧的系统中,接近 4GiB window 被减法解码到 DMI 接口(即仅当没有其他设备声明它时才发送到 DMI 接口),引导几乎总是来自 DMI 接口本身.
新的正向解码行为是一种针对引导攻击的安全措施。

如果您查看相对现代的 PCH 的数据表,即 series 200,您会发现它支持 LPC 桥或 SPI 接口后面的闪存 ROM。

我们将仅限于后者。
在该芯片组中,SPI 桥是 PCI 设备 31,功能 15。
在其 PCI 配置中 space 有标准寄存器和:

  • 一个 BAR(基地址寄存器)映射一个 4 KiB window 的 MMIO 寄存器来控制 SPI 接口本身。
  • 一个 BIOS 解码启用 寄存器,用于启用或禁用特定 windows 中内存访问的回收。
  • 用于启用各种安全功能的控制寄存器(包括启动是否关闭 SPI 或 LPC 接口)。

我们重点说第二点:

需要注意两点:首先,此寄存器启用或禁用从 CPU、低于 4GiB 的 4MiB 区域和其他区域向 SPI 发送内存访问。
第二个是默认值为0ffcfh,意味着默认所有windows都映射到SPI
BIOS 控制寄存器 也选择 SPI 作为默认引导接口,但这也可以使用 softstrap/bootstrap 引脚 IIRC 进行配置。

最后但并非最不重要的一点是,当 PCH 看到对 4GiB-10h 这样的地址的访问时,它无法将其原样发送到闪存 ROM,因为它超出了闪存 ROM 本身的范围。
它必须首先解码它,减去一个偏移量。但是,此偏移量取决于闪存 ROM 的大小。

在 PCH 之前(我认为在 ICH8 芯片组和一些不太新的 Atom 芯片组中)使用的闪存 ROM 没有 描述符
芯片组简单地将 ROM 从 4GiB 映射到 4GiB-16MiB 并使用别名,这意味着地址 4GiB - X 将映射到 闪存大小 -(X % 闪存大小).
结果是,例如,2 MiB 闪存在 16 MiB windows 中出现 8 次映射,低于 4 GiB 限制。
在这些芯片组中,有 bootstrap 个引脚用于配置闪存大小。

今天的 PCH 闪存 ROM use descriptors,其中闪存分为多个区域(BIOS、ME、GbE 等)。
只有 BIOS 区域映射到 CPU 的地址 space。有一个基于请求者 ID 的安全描述符系统(由其 PCI 身份给出)。
有关此主题的介绍,请参阅 this or better this 以获得更完整的描述(有点过时但仍然相关)。
区域在这里是相关的,因为它们在闪存描述符中列出了它们的偏移量和大小,因此 PCH 可以知道如何将 CPU 地址转换为闪存线性地址。

最后,SPI 接口的 MMIO 寄存器允许对 Flash ROM 进行原始访问。可以合成命令向下发送 SPI 总线,从而可以重新编程闪存 ROM(例如)。
它们仍然受到应列在数据表 IIRC 中的各种安全对策的约束。