首页 > 解决方案 > 处理器如何从 SPI 闪存读取 BIOS?

问题描述

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

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

标签: x86spibiosfirmwareuefi

解决方案


Haswell+ CPU 在上电时(在 BIST - 内置自检之后)执行的第一件事是执行微编码例程,它是Intel TXT技术的一部分,以获取 4GiB-40h 的FIT并执行 BIOS ACM(Authenticated Code模块),并最终继续测量启动,或回退到 4GiB - 10h 的旧重置向量。

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

内存映射

由于本段,这是相关的:

出于安全原因,处理器会将此 [High BIOS] 范围积极解码为 DMI。这种正解码可确保忽略任何重叠范围。这确保了引导向量和 BIOS 在 PCH 之外执行。

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

如果您查看相对现代的 PCH(即200 系列)的数据表,您会发现它支持 LPC 桥接器或 SPI 接口后面的 Flash ROM。

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

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

让我们关注第二点:

BIOS 解码启用寄存器

有两点需要注意:首先,该寄存器启用或禁用从 CPU 向 SPI 发送内存访问,在 4GiB 以下的 4MiB 和其他区域内。
第二个是默认值为 0ffcfh,这意味着默认情况下所有窗口都映射到 SPIBIOS 控制寄存器
还选择 SPI 作为默认引导接口 ,但这也可以通过软带/引导引脚 IIRC 进行配置。

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

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

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

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


推荐阅读