x86 - 今天的 BIOS 怎么能大于 64KB?

标签 x86 bios

AFAIK,BIOS 大小限制为段大小(0xFFFF)。但是今天许多 BIOS 大于 64KB,通常超过 10MB。它怎么能做到这一点?

最佳答案

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

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

Core --[QPI/UPI]--> System Agent --[DMI]--> PCH --[SPI/LPC]--> FLASH ROM

较旧的是:
CPU --[FSB]--> North Bridge/MCH --[DMI/Proprietary]--> South Bridge/ICH --[LPC] --> FLASH ROM

更老的一个是:
CPU --[BUS]--> System Controller --> FLASH ROM

注意:Flash ROM 通常通过 SuperIO 芯片或嵌入式 Controller 连接到 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 中“原型(prototype)化”的,具有 24 位地址空间,机会来了。

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

固件窗口大小对 4GiB 地址空间的影响不如 1MiB 地址空间,因此 4GiB 的窗口更大。
这个窗口的大小可以根据需要做大(与其他系统设备兼容),但有一个问题(实际上是两个)。
  • 在 4GiB-18MiB 有一个由 LAPIC(CPU 内部 block )遮蔽的非始终可访问区域,该区域是可移动的并且可以禁用,但默认情况下它是 4GiB-18MiB。
    因此,例如 30MiB 的 Flash ROM 将部分无法访问。
  • PCH SPI 模块最多支持 8MiB 的窗口。

  • 固件怎么可能是 20MiB?
    今天,固件主要由四个组件组成:
  • UEFI/BIOS
  • 英特尔 ME
  • 1Gbs 以太网
  • RAID Controller

  • 上面讨论的窗口仅适用于 UEFI/BIOS。
    ME固件有自己的窗口,以太网和raid Controller 是PCIe设备,可以利用任何PCI窗口。

    在综合中,固件被分割成多个组件,其中大部分遵循 PCI(e) 设计。其余的有足够大的特殊内存窗口。

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

    关于x86 - 今天的 BIOS 怎么能大于 64KB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56216128/

    相关文章:

    assembly - 在 x86 程序集中制作鼠标处理程序

    我们可以在程序集中将局部变量压入堆栈吗

    c - 禁用算术优化的 gcc 标志

    assembly - 如何在 nasm os 中填满屏幕

    windows - 如何安全地删除 Ubuntu EFI 分区并将 Windows EFI 分区移动到我在全新 Windows 安装期间创建的可用空间?

    linux - 使用 GNU AS (GAS) .intel_syntax 将静态地址放入寄存器中?

    linux - 带有 cx 寄存器的 NASM 汇编器无限循环

    bootstrapping - 引导硬盘访问

    windows - 强制机器从 live CD 启动

    ubuntu - umount -f pc 无法识别grub2