今天的BIOS如何超过64KB?

noi*_*put 2 x86 bios

AFAIK,BIOS大小限制为段大小(0xFFFF)。但是,如今许多BIOS都超过了64KB,通常超过10MB。它怎么做呢?

Mar*_*oom 6

64KiB限制一直是硬件限制,而不是软件限制。重点是重新控制从内存到固件Flash ROM的内存访问。
这是允许更大的Flash ROM所要做的,但是历史很复杂。


CPU通过至少一个外部芯片访问固件(用于获取指令或数据)。
现代的层次结构就是这样的:

Core --[QPI/UPI]--> System Agent --[DMI]--> PCH --[SPI/LPC]--> FLASH ROM
Run Code Online (Sandbox Code Playgroud)

较老的是:

CPU --[FSB]--> North Bridge/MCH --[DMI/Proprietary]--> South Bridge/ICH --[LPC] --> FLASH ROM
Run Code Online (Sandbox Code Playgroud)

一个更老的是:

CPU --[BUS]--> System Controller --> FLASH ROM
Run Code Online (Sandbox Code Playgroud)

注意:Flash ROM通常通过SuperIO芯片或嵌入式控制器连接到LPC。

为了使CPU能够访问固件,一些内存地址被盗并重定向到Flash ROM。
这是通过配置CPU和Flash ROM之间的所有中间节点来完成的。

该窗口的大小设置为64KiB或128KiB(对应于0xf0000-0xfffff0xe0000-0xfffff),但这是设计决定(允许具有640KiB的RAM和320 / 256KiB的扩展ROM)。
可以将窗口设计为512KiB或更高(尽管RAM会受到限制)。

无论如何,窗口设置为64KiB并进行更改会破坏该软件,因此它没有(并且没有)扩展。
当386出现时,CPU可以寻址超过1MiB(+ 64KiB-16B),实际上这是在286中使用24位地址空间“原型化”的,机会来了。

上电后,CPU开始从处获取指令CS:IP = 0xf000:0x0fff,例如16位CPU,但是(由于段寄存器的内部工作方式),此逻辑地址不会转换为0xffff0(16位CPU就是这种情况),而是转换为0xfffffff0(16字节数低于4GiB限制)。
这样做是为了向后兼容(CS:IP对软件可见的一对不变),同时允许映射更大的Flash ROM。
当然,也需要将4GiB附近的地址重定向(窃取)到Flash ROM。

固件窗口的大小不会像1MiB地址空间那样影响4GiB地址空间,因此4GiB处的窗口更大。
该窗口的大小可以根据需要设置为大(与其他系统设备兼容),但是有一个陷阱(实际上是两个)。

  1. 在4GiB-18MiB处,有一个始终无法访问的区域,被LAPIC(CPU内部块)遮盖了,该区域是可移动的,可以禁用,但默认情况下为4GiB-18MiB。
    因此,例如30MiB的Flash ROM将部分无法访问。
  2. PCH SPI模块最多支持8MiB的窗口。

固件如何成为20MiB?如今,固件主要由四个组件组成:

  • UEFI / BIOS
  • 英特尔ME
  • 1Gbs以太网
  • RAID控制器

上面讨论的窗口仅适用于UEFI / BIOS。
ME固件具有其自己的窗口,以太网和RAID控制器是PCIe设备,可以利用任何PCI窗口。


综合而言,固件分为多个组件,其中大多数遵循PCI(e)设计。其余的具有足够大的特殊内存窗口。

那么,为什么仍然要说BIOS限于段大小呢?
因为当CPU从0xfffffff0它引导时实际上是在16位/ 32位混合模式下,所以它在“内存结束”之前(在4GiB限制之前)只有16个字节,但是任何远跳转都CS将由16位重新加载规则,将CPU限制在1MiB下限。
因此旧的64KiB / 128KiB窗口仍然存在,并且已映射到闪存的同一区域。
这使固件大于16B并根据需要配置系统(例如,仅将16位服务映射到下部窗口)。