我花了四天的时间尝试在普通的 debian buster 上安装 OpenZFS 2.0.0 并从它启动。长话短说,OpenZFS 2.0.0 运行,buster 从中启动,但只需要一点手动帮助:
每次重新引导后,grub 都会进入命令行。显然,它并没有执行grub.cfg。如果我手动执行 grub.cfg,系统就会启动。
请注意,我已经阅读了无数其他线程和问答,它们都涉及重新启动后命令行中的 grub。但是,我还没有找到与我类似的问题 - 我相信到目前为止我已经找到了问题,我的问题非常具体:
当我set
在 grub 的命令提示符下发出命令时,会出现(当然还有其他)以下行:
prefix=(hd0,gpt2)/EFI/debian
我不是 Linux 专家,更不是 grub 专家。所以我可能是错的,但我相信这是罪魁祸首,因为引导加载程序(分别为grubx64.efi
和shimx64.efi
)以及配置文件(grub.cfg
)实际上位于(hd0,gpt2)/EFI/debian-hdd1
(请注意尾随-hdd1
,其值prefix
缺少),而不是(hd0,gpt2)/EFI/debian
。
因此,当我normal
在命令行发出时,没有任何反应(嗯,屏幕似乎刷新了,但没有其他反应)。但当我第一次打字时
set prefix=(hd0,gpt2)/EFI/debian-hdd1
然后输入normal
,就会出现正常的 grub 启动菜单。
这让我认为prefix
在这种特殊情况下该变量是错误的。显然,当到达命令提示符时,grub 还没有执行任何脚本。因此, 的值prefix
必须是默认值。
问题:
grub 从哪里获取这个默认值?它是一个编译时选项,还是我可以在某个地方设置它?也就是说,如何设置 grub 变量的默认值prefix
(即尚未运行脚本时这些变量的值)?
题外话旁注:
我知道我可能可以通过安装grub.cfg
而.../debian
不是安装来解决问题.../debian-hdd1
。我还没有尝试过,原因有两个:
我真的很想学习如何更改 grub 的默认值
prefix
(称之为好奇心或迂腐)。我正在安装 grub by
grub-install
,它显然使用 UEFI 启动项名称(通过提供选项设置--bootloader-id=debian-hdd1
)作为它创建的目录名称。我需要这种形式的启动项名称,因为系统启动的 rpool 由两个磁盘的镜像组成,如果其中一个磁盘出现故障,我希望能够从另一个磁盘启动。因此,我需要能够在 UEFI BIOS 设置中区分这两个磁盘。
答案1
我们可以
我找到了一个解决方案,如何永久更改前缀。但是,它有以下警告:我们必须直接在 grubx64.efi 二进制文件中更改它,并且必须保持文件相同的长度。给你多少空间可能取决于你的分布。请继续阅读以获得进一步的解释。
免责声明
- 如果你想这样做,你必须关闭安全启动因为哈希值将发生变化并且二进制文件将被拒绝。不确定是否可以通过安装您自己的哈希值来解决此问题(搜索 MOK)。
- 始终做好备份您正在更改的文件的数量。如果您像我一样操作,您将能够通过可启动 U 盘。如果您手头没有其他系统,请立即创建一个可启动 USB 并测试是否可以启动它。
首先是问题:
基本上,整个问题是安全启动的限制。为了让安全启动接受 grubx64.efi 文件,它必须签名由公认的权威机构。因此,该 grub 可执行文件已签名并且预烤的。当前设置此前缀的标准似乎是/EFI/$(lsb_release -i -s)
.这当然也意味着 - 无论您在创建新的引导选项时指定哪个加载程序路径(例如efibootmgr--loader \\EFI\\other\\SSHIMX64.efi
),它都不会影响 grub 引导加载程序中的前缀变量。
解决方案:
假设我们的发行版是ubuntu
,出于某种原因我们想将其重命名为longubuntu
,我们可以按照以下步骤进行操作:
# List contents of EFI directory
find /boot/efi/EFI;
# Rename the directory
mv /boot/efi/EFI/ubuntu /boot/efi/EFI/longubuntu;
# List contents of EFI/longubuntu for easy access
find /boot/efi/EFI/longubuntu;
# Always make a copy of the original
cp /boot/efi/EFI/longubuntu/BOOTX64.CSV /boot/efi/EFI/longubuntu/BOOTX64.CSV.bak
# Inside the .csv-file change 'ubuntu' to 'longubuntu'
nano /boot/efi/EFI/longubuntu/BOOTX64.CSV
在继续之前:
检查是否有有足够的空字符可用在二进制文件中。重要的是要保持总长度相同。如果你不这样做,它会抛出一个错误 - 如果这种情况发生在你身上,那么复制回原来的grubx64.efi然后再试一次。什么时候使用 VS Code 检查我的 grubx64.efi-binary我确实有足够的可用空间来更改我心中内容的前缀:
现在到有趣和关键的部分:
正如我已经说过的,我们需要确保二进制文件保持相同的长度。我们可以通过用 nul-chars ( ) 填充新前缀\0
或用 nul-chars 填充文本来替换。
因此,如果您想指定更长的前缀(如我的情况),您可以这样做:
# Parameter -pi.bak will create a backup for you
perl -pi.perlbak -e 's/EFI\/ubuntu\0\0\0\0/EFI\/longubuntu/g' /boot/efi/EFI/longubuntu/grubx64.efi
如果您选择较短的前缀(例如bent
),则用 填充新值\0
:
# Parameter -pi.bak will create a backup for you
perl -pi.perlbak -e 's/EFI\/ubuntu/EFI\/bent\0\0/g' /boot/efi/EFI/longubuntu/grubx64.efi
您可以检查操作结果,它将打印包含前缀的行。
$~: grep -a 'EFI\/longubuntu' /boot/efi/EFI/longubuntu/grubx64.efi
不要忘记添加新的启动选项!
我会用efibootmgr
。我们efibootmgr
可以删除旧的启动选项并添加新的启动选项。
# Print current boot options
:~# efibootmgr -v
BootCurrent: 0000
Timeout: 1 seconds
BootOrder: 0000
Boot0000* ubuntu HD(1,GPT,28bd5547-5802-4f9c-97da-22ddd968dea6,0x800,0x100000)/File(\EFI\UBUNTU\SHIMX64.EFI)
# Delete current
:~# efibootmgr -b 0 -B
# List disks
:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
[...]
nvme0n1 259:0 0 238.5G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
└─nvme0n1p2 259:2 0 238G 0 part /
# Create new boot option
:~# efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Long Ubuntu Name" --loader \\EFI\\longubuntu\\shimx64.efi
享受:
当你现在重新启动时。您仍然应该像以前一样启动到您的发行版。
如果没有,则引导至 USB 记忆棒并安装 EFI 分区。然后撤消更改或复制回原始文件。在我的设备上,我像这样安装 EFI 分区:
:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
[...]
nvme0n1 259:0 0 238.5G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
└─nvme0n1p2 259:2 0 238G 0 part /
:~# mkdir -p /media/efi; mount /dev/nvme0n1p1 /media/efi
答案2
当您运行 grub-install 时,它会创建/boot/grub/x86_64-efi/grubx64.efi
该引用/boot/grub/grub.cfg
那么问题是,它不是将其复制到/EFI/$GRUB_DISTRIBUTOR/grubx64.efi
,而是复制/usr/lib/grub/x86_64-efi/monolithic/grubx64.efi
或/usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed
。
它们是 deb 包和参考中预构建的二进制文件/EFI/ubuntu/grub.cfg
。
我知道如果您想要签名,这是必要的grubx64.efi
,但如果我们不关心安全启动,我们应该能够正确实施。
我可以找到一个设置来说明grubx64.efi
要采用哪个。也许它是由替代方案处理的,我会检查一下。
但我发现的最简单的解决方案是手动复制/boot/grub/x86_64-efi/grubx64.efi
然后/EFI/$GRUB_DISTRIBUTOR/grubx64.efi
安装,reFind
它将自动扫描 EFI 文件夹并创建图形菜单条目。
您还可以创建菜单项,/EFI/ubuntu/grub.cfg
例如
set timeout=5
set default=0
menuentry '@gorilla configfile' {
search.fs_uuid c9708fd5-155c-4459-abbe-3a08930cfd05 root lvmid/GkCLQl-oP2y-Op1F-o5Tc-TT8P-0tjW-iV2yTe/SlCPLV-S3jd-
set prefix=($root)'/@gorilla/boot/grub'
configfile $prefix/grub.cfg
}
menuentry '@gorilla chainload' {
search.fs_uuid c9708fd5-155c-4459-abbe-3a08930cfd05 root lvmid/GkCLQl-oP2y-Op1F-o5Tc-TT8P-0tjW-iV2yTe/SlCPLV-S3jd-
set prefix=($root)'/@gorilla/boot/grub'
chainloader $prefix/x86_64-efi/core.efi
}
当旧的 grub 二进制文件无法加载更新的配置时,我遇到了一次 grub-bios 问题,/boot/grub/grub.cfg
因此我认为最好是链式加载core.efi
以避免出现该问题,而不是使用配置文件。
答案3
我仍然无法回答我的问题,即我仍然不知道如何更改prefix
grub-efi 中的默认值。不过,我已经找到了解决问题的办法——efibootmgr
来救援,直到现在我还不太清楚。
--bootloader-id=
我在执行此操作时首先放弃了该选项grub-install
,结果与以下效果相同--bootloader-id=debian
:引导加载程序文件现在位于EFI\debian
而不是EFI\debian-hdd1
.
当然,现在 UEFI BIOS 设置中的启动菜单项也是debian
,这是我必须避免的。幸运的是,在阅读手册页后,很明显 efibootmgr 是解决该情况的正确工具。
首先,我删除了名称错误的 UEFI BIOS 启动菜单项:
efibootmgr -b 0001 -B
然后我创建了一个具有正确名称的新 UEFI BIOS 启动菜单项:
efibootmgr -c -d /dev/sda -p 2 -w -L debian-hdd1 -l '\EFI\debian\shimx64.efi'
请注意,此命令不会触及实际的引导加载程序安装,无论是 EFI 分区中的引导加载程序还是/boot/grub
.相反,它实际上只是在 UEFI 固件中创建一个启动菜单条目。
这正是我所需要的。实际上,我并不关心EFI引导加载程序是在EFI\debian
还是EFI\something-else
.但是,我做我关心 UEFI 设置中引导加载程序条目的名称,而我的问题之所以出现,是因为在此之前我认为这--bootloader-id
是grub-install
在 UEFI 设置中正确命名引导加载程序条目的唯一舒适方法。
现在系统启动没有任何问题,因为初始的grub.cfg
now 位于 中EFI\debian
,因此 grub 可以找到它。