非 UEFI BIOS 选项 ROM 通常没有那么大并且有大小限制,但 UEFI 驱动程序可以更大,并且在 UEFI BIOS 中放置在 1MiB 以上,在 SEC 阶段切换出实模式。您可以禁用某些您不想在下次启动时被隐藏到空间的选项 ROM。
之所以使用这个小范围,是因为非 UEFI BIOS 在实模式下运行(中断表(IVT 与 IDT 相对)从 0h 开始,作为选项 ROM 的保证),因此只能访问前 1MiB 的内存并需要内存来做其他事情(BIOS 数据、BIOS、BIOS 的堆栈/堆和选项 ROM)。虽然,大多数 BIOS 最终使用虚拟 8086 的虚幻模式或保护模式,因此它们可以同时使用 IVT 和 32 位地址,因此没有什么可以阻止 BIOS 隐藏 RAM 中其他地方的选项 ROM 以及 BIOS 扫描该区域(我已经读过,如果 BIOS 只有 64KiB,也可以使用 E0000–EFFFF),但如果选项 ROM 本身寻找其他选项 ROM(如 UNDI ROM)在 PxE NIC 上寻找 BC ROM,这会变得复杂。他们还使用了 PMM分配 16/32 位堆地址的服务。UEFI 不再使用 BIOS 中断服务;它使用 EFI 功能。
板载显卡的选项 ROM 在 BIOS 本身中,并且它的地址是已知的。它经过经典的硬编码以移动到 C0000h(实模式分段表示法中的 C000:0000h),或者实际上是它想要的任何位置。BIOS 至少确保它是第一个执行的选项 ROM,但如果它知道它已将其移至 D0000h,例如,它就知道将控制权传递给何处。如果允许它位于可变地址而不是固定地址,那么如果其他 PCIe 卡首先被遮蔽,它最终可能无法适应该范围。此外,它必须首先扫描 VGA BIOS 类代码,然后再次扫描范围或保留选项 ROM 所在位置的内部表,这比线性迭代空间和视频 BIOS 的简单例程更加复杂恰好先执行。
PAM 不再位于北桥(现代 Intel CPU 上不存在),它们被用作 L3 缓存片中 SAD 配置的一部分,它解码地址并向内存发送请求控制器、DMI、PCIe 链路或处理器图形。BIOS 可以设置 PAM,以便将特定范围的读取发送到 DMI,并将写入发送到内存控制器。这样,BIOS 可以对其自身进行映射,并且 PCI(e) XROMBAR 可以设置为它们将被映射到的相同地址。
在我的系统上(Kaby Lake + C230 系列 PCH + UEFI 安全启动已禁用),在 C0000h–DFFFFh 区域中有 3 个选项 ROM。
显卡BIOS
Option ROM Header: 0x000C0000
55 AA 80 E9 91 F9 30 30 30 30 30 30 30 30 30 30 U.....0000000000
30 30 A8 2F E9 B1 2E AF 40 00 90 0B 00./....@...
Signature 0xAA55
Length 0x80 (65536 bytes)
Initialization entry 0x30F991E9 //software read this wrong it's actually 0xF991E9, which is a 16 bit relative jump 0xF991; -1647
Reserved 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30
Reserved 0x30 0xA8 0x2F 0xE9 0xB1 0x2E 0xAF
PCI Data Offset 0x0040 //offset is from start of OpROM header
Expansion Header Offset 0x0B90
PCI Data Structure: 0x000C0040
50 43 49 52 86 80 06 04 1C 00 1C 00 03 00 00 03 PCIR............
80 00 00 00 00 80 80 00 ........
Signature PCIR
Vendor ID 0x8086 - Intel Corporation
Device ID 0x0406
Product Data 0x001C
Structure Length 0x001C
Structure Revision 0x03
Class Code 0x00 0x00 0x03
Image Length 0x0080
Revision Level 0x0000
Code Type 0x00
Indicator 0x80
Reserved 0x0080
SATA 控制器(每个磁盘的 PnP 扩展接头)
Option ROM Header: 0x000D0000
55 AA 4D B8 00 01 CB 00 00 00 00 00 00 00 00 00 U.M.............
00 00 00 00 00 00 00 15 A0 00 9A 01 ............
Signature 0xAA55
Length 0x4D (39424 bytes)
Initialization entry 0xCB0100B8 //mov ax, 0x100 retf
Reserved 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Reserved 0x00 0x00 0x00 0x00 0x00 0x00 0x15
PCI Data Offset 0x00A0
Expansion Header Offset 0x019A
PCI Data Structure: 0x000D00A0
50 43 49 52 86 80 2A 28 1C 00 1C 00 03 00 04 01 PCIR..*(........
4D 00 02 0F 00 80 4D 00 M.....M.
Signature PCIR
Vendor ID 0x8086 - Intel Corporation
Device ID 0x282A
Product Data 0x001C
Structure Length 0x001C
Structure Revision 0x03
Class Code 0x00 0x04 0x01
Image Length 0x004D
Revision Level 0x0F02
Code Type 0x00
Indicator 0x80
Reserved 0x004D
PnP Expansion Header: 0x000D019A
24 50 6E 50 01 02 BA 01 01 06 00 00 00 00 C2 00 $PnP............
D4 00 00 04 01 C4 90 1A 00 00 00 00 00 00 00 00 ................
Signature $PnP
Revision 0x01
Length 0x02 (32 bytes)
Next Header 0x01BA
Reserved 0x01
Checksum 0x06
Device ID 0x00000000
Manufacturer 0x00C2 - Intel Corporation //location 0xD00C2
Product Name 0x00D4 - SanDisk X400 M.2 2280 256GB //location 0xD00D4
Device Type Code 0x00 0x04 0x01
Device Indicators 0xC4
Boot Connection Vector 0x1A90
Disconnect Vector 0x0000
Bootstrap Entry Vector 0x0000
Reserved 0x0000
Resource info. vector 0x0000
PnP Expansion Header: 0x000D01BA
24 50 6E 50 01 02 00 00 02 9B 00 00 00 00 C2 00 $PnP............
F5 00 00 04 01 C4 94 1A 00 00 00 00 00 00 00 00 ................
Signature $PnP
Revision 0x01
Length 0x02 (32 bytes)
Next Header 0x0000 //next PnP expansion header contains nothing useful
Reserved 0x02
Checksum 0x9B
Device ID 0x00000000
Manufacturer 0x00C2 - Intel Corporation
Product Name 0x00F5 - ST1000LM035-1RK172
Device Type Code 0x00 0x04 0x01
Device Indicators 0xC4
Boot Connection Vector 0x1A94
Disconnect Vector 0x0000
Bootstrap Entry Vector 0x0000
Reserved 0x0000
Resource info. vector 0x0000
以太网控制器
Option ROM Header: 0x000DA000
55 AA 08 E8 76 10 CB 55 BC 01 00 00 00 00 00 00 U...v..U........
00 00 00 00 00 00 20 00 40 00 60 00 ...... .@.`.
Signature 0xAA55
Length 0x08 (4096 bytes)
Initialization entry 0xCB1076E8 //call then far return
Reserved 0x55 0xBC 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Reserved 0x00 0x00 0x00 0x00 0x00
PXEROMID Offset 0x0020 //RWEverything didn't pick it up as a separate field and made it part of the reserved section so I separated it.
PCI Data Offset 0x0040
Expansion Header Offset 0x0060
UNDI ROM ID Structure: 0x000DA020 //not recognised by RW Everything so I parsed it myself
55 4E 44 49 16 08 00 00 01 02 32 0D 00 08 B0 C4 UNDI......2...
80 46 50 43 49 52 ¦-ÇFPCIR
Signature UNDI
StructLength 0x16
Checksum 0x08
StructRev 0x00
UNDIRev 0x00 0x01 0x02
UNDI Loader Offset 0x0D32
StackSize 0x0800
DataSize 0xC4B0
CodeSize 0x4680
BusType PCIR
PCI Data Structure: 0x000DA040
50 43 49 52 EC 10 68 81 00 00 1C 00 03 00 00 02 PCIR..h.........
08 00 01 02 00 80 08 00 ........
Signature PCIR
Vendor ID 0x10EC - Realtek Semiconductor
Device ID 0x8168
Product Data 0x0000
Structure Length 0x001C
Structure Revision 0x03
Class Code 0x00 0x00 0x02
Image Length 0x0008
Revision Level 0x0201
Code Type 0x00
Indicator 0x80
Reserved 0x0008
PnP Expansion Header: 0x000DA060
24 50 6E 50 01 02 00 00 00 D7 00 00 00 00 AF 00 $PnP............
92 01 02 00 00 E4 00 00 00 00 C1 0B 00 00 00 00 ................
Signature $PnP
Revision 0x01
Length 0x02 (32 bytes)
Next Header 0x0000
Reserved 0x00
Checksum 0xD7
Device ID 0x00000000
Manufacturer 0x00AF - Intel Corporation
Product Name 0x0192 - Realtek PXE B02 D00
Device Type Code 0x02 0x00 0x00
Device Indicators 0xE4
Boot Connection Vector 0x0000
Disconnect Vector 0x0000
Bootstrap Entry Vector 0x0BC1 // will be at 0xDABC1
Reserved 0x0000
Resource info. vector 0x0000
在具有旧版 BIOS 的另一台计算机上,仅 VGA 选项 ROM 出现在该区域的扫描中,并且位于 0xC0000。没有 EHCI,也没有 SATA。这表明它嵌入在 BIOS 中,但它是 BIOS 代码的一部分,而不是作为选项 ROM,在 BBS 中称为 BAID;初始化控制器和扫描引导设备并将它们的信息输入 IPL 表并挂钩 int 13h 以便 MBR/VBR 可以访问磁盘的代码在 BIOS 中是硬编码的。此外,BCV 挂钩顺序优先级不再重要,因为它们现在都作为 BAID 输入到 IPL 表中,而不仅仅是磁盘 80h 是可引导的(通过从 BDA 中的当前磁盘枚举号读取然后填充那么多条目及其从 int 13h 调用中获取的各自详细信息)。想必,IPL 表包含要从中引导的磁盘编号,并将其传递给条目中的向量,该向量将是所有 BAID 共享的代码,该代码使用 int 13h 从磁盘加载第一个扇区到 0x7c00 检查有效的 MBR,然后传递控制. 然后 MBR 将自己从 0x7c00 移开并将活动分区的第一个扇区(即 VBR)加载到 0x7c00 并将控制权传递给它,这将是 JMP 指令(如果它是默认窗口指令。如果它是 GRUB,它将加载并传递控制从扇区 1-65 到 core.img)。然后,VBR 将使用 VBR 中 BPB 中的 HiddenSectors 值将 IPL 加载到它在磁盘上定位的扇区 1-15 中,并将控制权传递给它。有关从这一点开始 Windows 启动的更多详细信息,请参阅我的回答 然后 MBR 将自己从 0x7c00 移开并将活动分区的第一个扇区(即 VBR)加载到 0x7c00 并将控制权传递给它,这将是 JMP 指令(如果它是默认窗口指令。如果它是 GRUB,它将加载并传递控制从扇区 1-65 到 core.img)。然后,VBR 将使用 VBR 中 BPB 中的 HiddenSectors 值将 IPL 加载到它在磁盘上定位的扇区 1-15 中,并将控制权传递给它。有关从这一点开始 Windows 启动的更多详细信息,请参阅我的回答 然后 MBR 将自己从 0x7c00 移开并将活动分区的第一个扇区(即 VBR)加载到 0x7c00 并将控制权传递给它,这将是 JMP 指令(如果它是默认窗口指令。如果它是 GRUB,它将加载并传递控制从扇区 1-65 到 core.img)。然后,VBR 将使用 VBR 中 BPB 中的 HiddenSectors 值将 IPL 加载到它在磁盘上定位的扇区 1-15 中,并将控制权传递给它。有关从这一点开始 Windows 启动的更多详细信息,请参阅我的回答 然后,VBR 将使用 VBR 中 BPB 中的 HiddenSectors 值将 IPL 加载到它在磁盘上定位的扇区 1-15 中,并将控制权传递给它。有关从这一点开始 Windows 启动的更多详细信息,请参阅我的回答 然后,VBR 将使用 VBR 中 BPB 中的 HiddenSectors 值将 IPL 加载到它在磁盘上定位的扇区 1-15 中,并将控制权传递给它。有关从这一点开始 Windows 启动的更多详细信息,请参阅我的回答在这里。
SATA 控制器上的初始化条目中的代码是远返回 0x100 的代码。这似乎已在初始化发生后由 BIOS 或选项 ROM 本身修改,或者可能只是一个错误,因为它是在 BIOS 其他地方初始化的嵌入式设备。根据定义,初始化代码现在是无用的,并且遵循 DDIM 的选项 ROM 可以在初始化后从 RAM 中删除初始化代码并重新计算长度和校验和。视频 BIOS 甚至做了一些负面的相对跳跃。这表明 BIOS 将其视频 BIOS 隐藏到 C0000h 之前的位置,部分覆盖 VGA VRAM 区域,因此选项 ROM 标头出现在 C0000h。
“长度”似乎描述了在初始化选项 ROM 后它占用的传统选项 ROM 影子 RAM 区域中的空间量。
以下是拆分 PXE 选项 ROM 的示例内存映射:

与一次性设置所有 XROMBAR 以使其包含预初始化长度不同,BIOS 可能一次加载并初始化一个。它不能覆盖/删除选项 ROM,因为选项 ROM 中与 IPL 代码分开的例程仍可能被 BCV 调用以与硬件交互。例如,在视频 BIOS 初始化代码运行后,PCI 配置空间被扫描,第一个返回长度的 XROMBAR 将被设置到视频 BIOS 的末尾。然后将读取定向到 DMI,并将写入定向到内存。然后它将其映射到内存,将读取重定向到 RAM,并对初始化条目执行远调用。然后,IPL 代码通过删除初始化代码来缩小自身。BIOS 检查选项 ROM 的新大小以及 PnP 扩展头和寄存器 BEV/BCV。然后它将负载重定向回 DMI 并加载下一个 XROMBAR。BIOS 一次构建 BCV 表条目,然后按照 BCV 优先级的顺序执行 BCV。
选项 ROM 可以将 BEV/BCV 移动到扩展内存中的 PMM 分配,在 BEV/BCV 偏移处留下跳转指令,但这会将 BCV/BEV 中跳转的相对寻址分解为选项 ROM 其余部分中的函数。因此,它可以将整个自身重新定位到 PMM 分配并将大小减小到仅标题,但显然大多数选项 ROM 并非如此。不过,BEV 确实会重新定位 UNDI 驱动程序。