典型的x86系统将固件(aka BIOS或UEFI)存储在基于SPI的闪存芯片中。上电时,处理器从复位向量开始执行,该向量指向存储BIOS的内存映射SPI芯片。从这里开始,引导将在BIOS完成平台的初始化,加载引导加载程序,然后加载内核时发生。
但是,处理器如何知道如何从SPI芯片读取?我的意思是,那时处理器将不了解SPI协议,哪些芯片要写入命令的寄存器以及哪个寄存器要找到读取的数据。如此低的读数如何发生?
[Haswell + CPU上电时做的第一件事(在BIST-内置自检之后)正在执行Intel TXT技术的一部分的微代码例程,以在4GiB-18h处获取FIT并执行BIOS ACM(认证代码模块),并最终在4GiB-10h处继续执行measured boot或回退到旧版重置向量的方法。
不管哪种方式,CPU都需要从内存窗口中的4GiB以下的几个MiB中获取指令。CPU没有SPI接口,出于安全原因,对此窗口的请求始终重定向到DMI接口。您可以在8th-9th generation datasheet Vol. 2的2.6章中找到以下映射(即使在前几代中也是如此,AFAIK):
由于本段而相关:
出于安全原因,处理器将积极地将此[High BIOS]范围解码为DMI。这个正解码确保任何重叠范围都将被忽略。这样可以确保引导向量和BIOS在PCH上执行。
因此,CPU将从DMI接口中启动,因此PCH(平台控制器中枢)将处理请求。请注意,即使在较旧的系统中,该近4GiB窗口也被减法解码到DMI接口(即仅在没有其他设备要求的情况下才发送到DMI接口),引导几乎总是从DMI接口本身进行。新的可靠解码行为是针对引导攻击的安全措施。
[如果您查看相对较新的PCH的数据表,即series 200,您会看到它在LPC桥或SPI接口后面支持Flash ROM。
我们将仅限于后者。在该芯片组中,SPI桥是PCI设备31,功能15。在其PCI配置空间中,有标准寄存器和:
让我们关注第二点:
需要注意的两件事:首先,该寄存器启用或禁用将来自CPU的内存访问(位于4GiB以下的4MiB区域和其他区域)发送到SPI。第二个是默认值为0ffcfh,表示默认情况下所有窗口都映射到SPI
。BIOS控制寄存器还选择SPI作为默认的引导接口,但这也可以通过softstrap / bootstrap引脚IIRC进行配置。最后但并非最不重要的一点是,当PCH看到对4GiB-10h之类的地址的访问时,它无法将其原样发送给Flash ROM,因为它超出了Flash ROM本身的范围。它必须首先对其进行解码,减去一个偏移量。但是,此偏移量取决于Flash ROM的大小。
[在PCH之前(我认为是在ICH8芯片组和某些不太新的Atom芯片组中考虑),Flash ROM的使用没有descriptor
。芯片组仅用别名映射ROM 从4GiB向下到4GiB-16MiB,这意味着地址4GiB-X将被映射为Flash Size-(X%Flash size)。结果是,例如,在4 GiB限制以下的16 MiB窗口中出现了2次MiB闪存映射8次。在那些芯片集中,有用于配置闪存大小的自举引脚。PCH use descriptors的当今Flash ROM,其中闪存分为多个区域(BIOS,ME,GbE等)。仅BIOS区域映射在CPU的地址空间中。有一个基于请求者ID(由其PCI标识提供)的安全描述符系统。有关此主题的介绍,请参见this或更好的this,以获取更完整的描述(有些过时,但仍然有意义)。区域是相关的,因为它们在Flash描述符中列出了它们的偏移量和大小,因此PCH可以知道如何将CPU地址转换为Flash线性地址。
最后,SPI接口的MMIO寄存器允许原始访问Flash ROM。可以综合命令向下发送SPI总线,从而可以对Flash ROM进行重新编程(例如)。它们仍然受到各种安全对策的约束,这些对策应在数据表IIRC中列出。