在 Win10 中bcdedit /?
,帮助文本说它将把启动配置参数存储在非易失性 RAM (NVRAM) 条目中。
这太荒谬了吧?据我所知,bcdedit 将配置存储在磁盘文件中。
具体来说……
※ 如果典型的 x64 PC 的 BIOS 确定它应该以传统 BIOS 模式启动 PC,
- 它将第一个磁盘扇区(MBR 扇区)加载到 RAM 中并执行。
- 该 MBR 代码依次将活动分区的第一个扇区(OS 引导扇区)加载到 RAM 中并执行。
- 操作系统引导扇区依次将
\bootmgr
文件(无文件扩展名)加载到 RAM 中并执行。 - 代码
bootmgr
发现\Boot\BCD
(再次没有文件扩展名)以获取[我们之前通过运行设置的启动配置bcdedit
]。
※ 如果典型的 x64 PC 的 BIOS 确定它应该以 UEFI 模式启动 PC,
- 它找到一个 EFI 系统分区并加载
\EFI\Boot\bootx64.efi
到 RAM 中并执行。 - 然后 bootx64.efi 读取
\EFI\Microsoft\Boot\BCD
启动配置参数。
似乎与 NVRAM 无关。它是否意味着(在 bcdedit 上下文中)硬盘上不存在但某些 PC 主板芯片上存在的东西(我称之为 BIOS 区域)?
如果bcdedit
真的可以在 BIOS 区域存储/更改某些数据,请举个例子。我的意思是,什么样的bcdedit
参数会导致 BIOS 区域数据被更改?
答案1
您跳过了 UEFI 模式的很多步骤。您说得对,“它找到 EFI 系统分区并加载 \EFI\Boot\bootx64.efi”是其中之一,但它是倒退行为(正式的说法是“可移动磁盘”行为)——在达到这一点之前,有一两步涉及主板的 NVRAM。
首先,正如UEFI 规范(PDF),固件提供了广泛的“启动”和“运行时”服务(原理上类似于 BIOS 中断),其中包括“变量服务”(第8.2节) 允许操作系统在系统 NVRAM 中保存各种键值对。(通常,它是固件用于其自身设置的同一闪存,又称“CMOS”,许多系统实际上存储全部固件设置作为 EFI 变量。
通常操作系统会以某种方式将变量服务 API 暴露给用户空间程序,例如 Windows 提供设置固件环境变量()而Linux有一个虚拟文件系统/sys/firmware/efi/efivars
。
此外,正如第2.1节和第3节,固件有自己的启动管理器它“将尝试按照全局 NVRAM 变量定义的顺序加载 UEFI 驱动程序和 UEFI 应用程序(包括 UEFI OS 引导加载程序)。”固件引导管理器基本上与您可能使用过的 F8 或 F10“引导菜单”相同,但除了列出整个磁盘外,现在它还列出了操作系统的单个 .efi 文件。
(这个功能实际上早于 UEFI相当多——你引用的“以前”指的是阿尔法AXP和/或 Itanium IA64 EFI,两者都运行 Windows;两者都与 Boot.ini 同时存在(即在 BCD 之前);并且两者都有固件启动管理器。不过,我都没有两者的规格链接。)
EFI“启动管理器”主要使用 NVRAM 变量命名Boot####
(4 位数字)BootOrder
和BootNext
列出已安装的操作系统。每当 Windows 安装自己的 BOOTMGR(可以使用 手动完成bcdboot.exe
)时,它还会使用 EFI 变量服务(通过 Windows 提供的 API)创建指向 的 Boot0000 条目\EFI\Microsoft\Boot\Bootmgfw.efi
,标题为“Windows 启动管理器”。
实际上,你可以通过 查看这些条目bcdedit /enum firmware
,尽管它们将被大量转换为类似 Windows BCD 的格式(因为同一个工具可以处理两个都efibootmgr [-v]
EFI 和 BCD 条目),或者在 Linux 或 FreeBSD 内部运行:
BootCurrent: 0003
Timeout: 0 seconds
BootOrder: 0003,0005,2003,0002,2001,2002
Boot0000* UEFI Onboard LAN IPv4 PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)/MAC(3417eb7eda76,0)/IPv4(0.0.0.00.0.0.0,0,0)RC
Boot0001* UEFI Onboard LAN IPv6 PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)/MAC(3417eb7eda76,0)/IPv6([::]:<->[::]:,0,0)RC
Boot0002* HDD1-1 (Samsung SSD 860) PciRoot(0x0)/Pci(0x1f,0x2)/Sata(0,0,0)/HD(1,GPT,b7245b9a-d13f-4d97-8bff-901255bfd7ad,0x1000,0x100000)RC
Boot0003* Linux Boot Manager HD(1,GPT,b7245b9a-d13f-4d97-8bff-901255bfd7ad,0x1000,0x80000)/File(\EFI\systemd\systemd-bootx64.efi)
Boot0004* Arch Linux LTS HD(1,GPT,b7245b9a-d13f-4d97-8bff-901255bfd7ad,0x1000,0x100000)/File(\EFI\Linux\vmlinuz-linux-lts.efi)
Boot0005* EFI Shell HD(1,GPT,b7245b9a-d13f-4d97-8bff-901255bfd7ad,0x1000,0x80000)/File(\shellx64.efi)
因此,UEFI 固件的真正步骤(再次描述在第3节) 是:
Boot####
它从 BootNext 或 BootOrder 指示的变量中读取 EFI 文件系统路径,然后尝试按指定顺序将每个文件作为 .efi 可执行文件加载和运行。(BootOrder 中未列出的启动项处于非活动状态。)如果任何活动的 Boot#### 变量都无法执行,则通常回到“可移动磁盘”扫描所有磁盘以查找包含 EFI 系统分区
\EFI\Boot\Boot[cpuarch].efi
并执行该分区的行为。如果您从固件的启动菜单中手动选择整个磁盘,也会发生这种情况。(实际上我见过的所有系统也都将其应用于固定内部磁盘。这样,当磁盘移动到另一个主板或 NVRAM 数据由于某种原因丢失时,就可以启动已安装的操作系统,以及为 EFI 安装操作系统,即使安装介质由于某种原因无法在 EFI 模式下启动,因此可变服务不可用。)
(作为最后的手段,一些固件(主要是基于 EDK2 构建的固件)将运行 EFI Shell 的嵌入式副本,这是一个与 MS-DOS 有点类似的交互式 CLI,可让您手动运行 .efi 文件。其他一些固件将打开文件浏览器 GUI,您可以在其中选择要运行哪个 .efi 文件。其他固件则直接进入固件设置屏幕。)
这个 EFI 启动过程很大程度上受到了以下启发:在 Alpha 中发现的(这是 x86 之前的主要 WinNT 平台)。在某种程度上,Windows NT/2000/XP 中的 NTLDR 和 Boot.ini 模仿了 Alpha AXP基于固件的启动项,甚至包括系统磁盘使用 ARC 路径。
类似地,Windows XP 也可用于 Itanium IA64 上的 EFI,它完全依赖于 EFI 启动管理器(据我所知,它没有自己的启动菜单),因此“这些参数以前在......”很可能是指 XP 使用本机 EFI 启动管理器功能以及使用 Boot.ini 的 x86 版本。
(因此我怀疑当前的 Windows 启动管理器及其 BCD 的创建是因为微软一直发现 AXP 和 EFI 提供的接口不够充分,但它仍然在某种程度上模仿 EFI 风格的启动,例如,即使 BIOS 安装现在也有专用的“系统分区”并且不再将 BOOTMGR 直接放在 C:\ 上。)
也许是因为后者,该bcdedit
工具通过统一的界面管理两种类型的启动条目 - EFI 固件以及 Windows BCD。例如,默认情况下bcdedit
将列出 BOOTMGR 使用的 Windows BCD 条目,但如果您指定该/enum firmware
选项,则它将列出固件启动菜单使用的 EFI NVRAM 条目(尽管格式与真实格式非常不同)。