当我运行efibootmgr
列出所有启动选项时,输出如下:
$ efibootmgr
BootCurrent: 0003
Timeout: 1 seconds
BootOrder: 0000,0002,0003,0001
Boot0000* (my linux distro grub boot)
Boot0001* file
Boot0002* Windows Boot Manager
Boot0003* (my linux distro systemd-boot)
当我想查看更详细的输出时,我得到:
$ efibootmgr -v
BootCurrent: 0003
Timeout: 1 seconds
BootOrder: 0000,0002,0003,0001
Boot0000* (my linux distro grub boot) HD(1,GPT,3e1eXXXX-f3XX-40XX-b1XX-569aXXXXXXXX,0x800,0x82000)/File(\EFI\DISTRONAME-GRUB\GRUBX64.EFI)
Boot0001* file VenHw(99e2XXXX-75XX-4bXX-a2XX-c538XXXXXXXX)
Boot0002* Windows Boot Manager HD(1,GPT,3e1eXXXX-f3XX-40XX-b1XX-569aXXXXXXXX,0x800,0x82000)/File(\EFI\MICROSOFT\BOOT\BOOTMGFW.EFI)WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.X.X.X.X.-.5.c.X.X.-.4.e.X.X.-.a.c.X.X.-.f.3.2.b.X.X.X.X.X.X.X.X.}....................
Boot0003* (my linux distro systemd-boot) HD(1,GPT,3e1eXXXX-f3XX-40XX-b1XX-569aXXXX,0x800,0x82000)/File(\EFI\DISTRONAME-SYSTEMDBOOT\systemd-bootx64.efi)
根据我的推理和手册页中的快速搜索(https://linux.die.net/man/8/efibootmgr),输出的格式为:
BootNNNNA NAME WHATTOBOOT
在哪里:
NNNN = boot number (0000 until maybe 9999)
A = * if active, no asterisk if not active
NAME = string label that will be shown on vendor/motherboard BIOS (UEFI)
WHATTOBOOT = can be
- HD({NUMBER},{GPT/MBR},{UUID-from-blkid-PARTUUID})/File({\PATH\TO\EFI})
- PXE ((I have no such boot option in this PC))
efibootmgr -v
现在我很好奇的是输出的含义Windows boot manager
显示为:
Boot0002* Windows Boot Manager HD(1,GPT,3e1eXXXX-f3XX-40XX-b1XX-569aXXXXXXXX,0x800,0x82000)/File(\EFI\MICROSOFT\BOOT\BOOTMGFW.EFI)WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.X.X.X.X.-.5.c.X.X.-.4.e.X.X.-.a.c.X.X.-.f.3.2.b.X.X.X.X.X.X.X.X.}....................
- 根据它的 PARTUUID,它位于我的 EFI 分区上(与我的其他启动选项相同)
- 那么它的EFI文件位于\EFI\MICROSOFT\BOOT\BOOTMGFW.EFI
- 最后,下面是一个字符串(或者可能是二进制):
WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.X.X.X.X.-.5.c.X.X.-.4.e.X.X.-.a.c.X.X.-.f.3.2.b.X.X.X.X.X.X.X.X.}....................
我想问的是:这个字符串是什么意思?如果我删除之间的所有点 (.) 字符(这将使它变成xBCOBJECT=9deaXXXX-5cXX-4eXX-acXX-f32bXXXXXXXX
我也很好奇第二个启动选项是什么意思:Boot0001* file
或详细版本Boot0001* file VenHw(99e2XXXX-75XX-4bXX-a2XX-c538XXXXXXXX)
- 我怀疑这是几年前我忘记删除的闪存驱动器/拇指驱动器启动,这是正确的吗?或者是别的什么?
附加信息:
版本:
$ efibootmgr --version
version 17
我的设置:Windows+linux 双启动,在 linux 上我安装了这些启动管理器:grub 和 systemd-boot
答案1
长话短说:
传递到加载图像的二进制数据缓冲区。
搜索过程的详细描述
efibootmgr 源包含一个输出 EFI 启动变量的函数(文件 efibootmgr.c):
static void
show_vars(const char *prefix)
{
list_t *pos;
var_entry_t *boot;
const unsigned char *description;
efi_load_option *load_option;
list_for_each(pos, &entry_list) {
boot = list_entry(pos, var_entry_t, list);
load_option = (efi_load_option *)boot->data;
description = efi_loadopt_desc(load_option, boot->data_size);
if (boot->name)
printf("%s", boot->name);
else
printf("%s%04X", prefix, boot->num);
printf("%c ", (efi_loadopt_attrs(load_option)
⁞ & LOAD_OPTION_ACTIVE) ? '*' : ' ');
printf("%s", description);
show_var_path(load_option, boot->data_size);
fflush(stdout);
}
}
感兴趣的是这条线
description = efi_loadopt_desc(load_option, boot->data_size);
所以,我们需要找到一个函数efi_loadopt_desc
。它不包含在 efibootmgr 本身中。在 /usr/include 中搜索包含文件给出:
$ grep -ri efi_loadopt_desc /usr/include
/usr/include/efivar/efiboot-loadopt.h:extern const unsigned char * efi_loadopt_desc(efi_load_option *opt,
如果我们查看文件 /usr/include/efivar/efiboot-loadopt.h 的内部状态:
/*
* libefiboot - library for the manipulation of EFI boot variables
* Copyright 2012-2015 Red Hat, Inc.
* Copyright (C) 2001 Dell Computer Corporation <[email protected]>
*
...
*/
进一步调查导致efivar 存储库efi_loadopt_desc
,其中包含文件 src/loadopt.c 中的函数。它只是返回opt->description
a 的字段struct efi_load_option_s
:
last_desc = ucs2_to_utf8(opt->description, limit);
该结构定义为
typedef struct efi_load_option_s {
uint32_t attributes;
uint16_t file_path_list_length;
uint16_t description[];
// uint8_t file_path_list[];
// uint8_t optional_data[];
} PACKED efi_load_option;
因此,在加载选项文件路径之后输出的部分称为“可选数据”。进一步调查发现该文件src/efivarfs.c
和函数efivarfs_get_variable
显示它读取通常位于/sys/firmware/efi/efivarfs下的efivarfs(EFI var文件系统),并公开许多虚拟“文件”。名称以 开头的文件Boot000
包含有关引导选项的信息以及其他数据,此“可选数据”描述了特定的引导条目。似乎只有当启动名称、启动项文件路径和“可选数据”的组合信息不超过时,才会加载“可选数据” opt_size
。
更多信息:
https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#Services
可变服务
UEFI 变量提供了一种存储数据的方法,特别是非易失性数据。一些 UEFI 变量在平台固件和操作系统之间共享。变量命名空间由 GUID 标识,变量是键/值对。例如,UEFI 变量可用于在崩溃后将崩溃消息保留在 NVRAM 中,以便操作系统在重新启动后检索。[45]
https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#UEFI_booting
引导配置由存储在 NVRAM 中的变量定义,包括指示操作系统加载程序或操作系统内核的文件系统路径的变量。
笔记:UEFI 规范对“可选数据”有这样的规定:
https://uefi.org/specifications
https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf
(第 72 页)
可选数据
加载选项描述符中的剩余字节是传递给加载图像的二进制数据缓冲区。如果该字段长度为零字节,则将 NULL 指针传递给加载图像。可以通过从 EFI_LOAD_OPTION 的总字节大小中减去 OptionalData 的起始偏移量来计算 OptionalData 中的字节数。