我的系统是 64 位 openSUSE Tumbleweed 与 预装的 Windows 10 双启动。感觉应该是开启了 UEFI 的 Secure Boot 的(结果真是)。今天尝试着在 BIOS 里恢复默认设置,结果玩坏了,丢了 OpenSUSE 启动项。开机只能从硬盘启动直接进入 Windows。只好尝试着使用恢复光盘恢复一下。虽然不算特别顺利,终于还是很快就搞定了。
这种不常见的操作,如果不记下来,下次肯定又要再摸索一遍。下面是详细步骤。参考了三个网页。
- https://forums.opensuse.org/showthread.php/492039
- https://superuser.com/questions/376470/
- https://forums.opensuse.org/showthread.php/509813-Install-Grub2-in-UEFI
一点背景知识¶
有必要先了解一下 UEFI 与 GRUB 2 的关系,可以参考 openSUSE 上的这篇文档。
简单来说就是,EFI 相当于开机后运行的一个小型嵌入式系统,该系统的作用就是检查并启动我们需要的目标操作系统。EFI 的内部引导管理器管理着一个所有引导项的列表。可在开机加电后按 F12 键打开引导设备管理器查看列表。设置了默认启动项之后,开机 EFI 做相应检查后就直接交接给该默认启动项,比如 Windows 启动管理器或者 GRUB 启动菜单。在 Linux 上还可以通过命令行应用 efibootmgr
来访问和有限操作 EFI 内部引导管理器。
安装操作系统的时候系统需要为自己准备加载项,都需要将系统引导工具(或叫「引导加载器(boot loader)」如 Windows 启动管理器和 Grub 2 启动加载器)安装到 EFI 分区(ESP)。默认情况下,Windows 和 openSUSE 分别是 /EFI/Microsoft/Boot/BCD.efi
和 /EFI/opensuse/grubx64.efi
(启用 Secure Boot 的话则是 shim.efi
)。安装完了之后还需要向 EFI 注册成为内部引导管理器中的一个引导项后才会被 EFI 在用户开机后按 F12 键时展示给用户。如果设为默认,EFI 则会直接将后续的引导权交给该默认启动项而不会展示所有启动项列表。
启动 U 盘¶
先下载系统对应的 rescue CD:https://en.opensuse.org/openSUSE:Tumbleweed_installation
然后根据「T470s 上安装 Linux 滚动发行版 openSUSE Tumbleweed」里烧录光盘镜像到 U 盘的方法制作启动 U 盘。
从 U 盘启动系统,自动进入 rescue 模式的选择菜单。注意必须是 UEFI 模式(只要 BIOS 设置为 UEFI only 那就只能从 UEFI 模式启动),否则进入的恢复系统看不到 /boot/efi
分区。
恢复光盘的启动菜单第一项是 Live 模式,进入之后是 openSUSE Tumbleweed Xfce 桌面环境;第二项是 Failsafe 模式,进入后只有命令行界面。
恢复过程¶
登录恢复系统¶
如果进入 Live 模式,可以从开始菜单 -> 「System」 -> 「XTerm」启动命令行界面,直接在命令行输入 su
就可以切换到 root 身份(无密码)。
如果是 Failsafe 模式,等待系统进入命令行要求登录的时候,输入 root
,密码为空,即是 root 身份。
[可选]修改字体大小¶
**此小节内容在 Failsafe 模式下试过。
如果命令行字体太小,可以临时修改命令行终端的字体。
查看所有可用字体,
# ls -al /usr/share/kbd/consolefonts/
我选用了 suse12x22.psfu
,这个对我的 2560×1440 的 14″ 显示器算是非常合适,
# setfont /usr/share/kbd/consolefonts/suse12x22.psfu
分区位置
先确认至少以下几个分区的位置,
/boot/efi /boot / /home
以及所在的磁盘路径,比如 /dev/sdaX
或者 /dev/nvme0n1pX
其中 X
代表分区号,X
前面的部分是磁盘设备路径(两块硬盘则一般情况下分别是 /dev/sda
和 /dev/sdb
或类似的 NVMe 磁盘标识)。
如果不记得,可以使用,
# fdisk -l
以及,
# parted -l
查看所有可用磁盘设备来帮助回忆。其中带 loop
的设备是光盘启动造成的;另外可能还包括 U 盘的部分分区(根据不同制作启动 U 盘的方式有所不同)。
作为参考,下面是我的分区及设备路径(不相关的没放上来):
/dev/nvme0n1p1 EFI System /dev/nvme0n1p7 / /dev/nvme0n1p8 /home
/boot
在 /
中。为了避免误导——因为不同安装环境和设备具体情况不同,这些指令不能直接复制粘贴使用——下面用 X
、Y
、Z
指代分区(p, partition)编号,如这里的 1
、7
、8
。
开始重建 GRUB2 引导项¶
根据本文最开头介绍的基本知识,重建/恢复 GRUB 2 引导项要分成两种情况:
A. 在 EFI 中注册 GRUB。/boot/efi
中还保存了原来的 opensuse 文件夹,其中的内容也都还在。那么就不需要重新安装 GRUB2 引导项,只需要将其加入(注册)到 EFI 启动项列表中即可;
B. 重建 GRUB 并将其注册到 EFI 中。/boot/efi
中原来的 opensuse 文件夹里的内容不可用了,那么就需要重新安装了。
可以将 /boot/efi
挂载之后查看其内容来确定。但是个人觉得比较简单的方法是,直接按情况 A 来操作,然后尝试重新启动,可以正确引导就结束,不行再重新从恢复光盘启动然后按照 B 的方法来重建 GRUB2 启动项。
情形 A:在 EFI 中注册 GRUB
仅仅是注册话就很简单了, efibootmgr
可以很方便地完成这个工作,
# efibootmgr -c -d /dev/nvme0n1 -p X -l \\EFI\\opensuse\\shim.efi -L opensuse-secure
其中,
-c
表示生成一个新的启动项;-d /dev/nvme0n1
表示该启动项对应的文件在磁盘/dev/nvme0n1
中,如果有多个磁盘,可能后面结尾的数字就不是1
;-p X
表示启动项对应的文件在上述磁盘的第X
个分区中;-l \\EFI\\opensuse\\shim.efi
表示该启动项对应的启动文件,其中路径是相对于 ESP 分区的根目录(/
)的,使用\\
这样的分隔符,如果不是 Secure Boot,则需要将上面的shim.efi
改成grubx64.efi
;-L opensuse-secure
表示新建启动项在EFI 内部启动管理器中的标签(名称)为opensuse-secure
。
完成后 efibootmgr
会列出内部启动管理器的当前配置,类似于,
$ sudo efibootmgr -v
的结果,如,
BootCurrent: 0001 Timeout: 2 seconds BootOrder: 0001,0000,0010,0011,0012,0013,0017,0018,0019,001A,001B,001C,001D,001E,0023 Boot0000* Windows Boot Manager HD(1,GPT,...,0x800,0x82000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)... Boot0001* opensuse-secure HD(1,GPT,...,0x800,0x82000)/File(\EFI\opensuse\shim.efi) Boot0010 Setup FvFile... ... ... ...
这里(省略了很多内容)显示当前启动的是 0001 号启动项;Timeout
超时等待时间是 2s;启动顺序(BootOrer
)是 0001 第 1,0000 第 2。下面还列出了 Boot0000
是 Windows,Boot0001
可以看到是 opensuse-secure。所以默认情况下会直接使用 Secure Boot 扩展启动 openSUSE。
现在重启系统试试看,
# reboot
如果没有出现启动项菜单,那么估计得进行下面的安装了。
情形 B:重新安装 GRUB 2
**以下操作未经测试**
这个稍微麻烦些。
创建 mount 位置,
# mkdir /mounts # mkdir /mounts/root
挂载原来的分区到新建的挂载点,
# mount /dev/nvme0n1pY /mounts/root # mount /dev/nvme0n1pX /mounts/root/boot/efi
还有更多需要挂载的,
# mount --bind /dev /mounts/root/dev # mount --bind /proc /mounts/root/proc # mount --bind /sys /mounts/root/sys
激活刚挂载的原来的 /
分区,
# chroot /mounts/root
重建 GRUB2,
# grub2-install --target=x86_64-efi
如果是 Secure Boot,还需要下面这行指令,
# shim-install
再然后就是重建 GRUB 菜单项了(也许不需要,但是没有什么坏处,反正每次更新内核都会重建一次的),
# grub2-mkconfig -o /boot/grub2/grub.cfg
**不太确定这里是否需要注册该启动程序到 EFI 内部启动管理器作为启动项的操作(见情形 A 中的 efibootmgr 指令)**
然后按 Ctrl+D
退出挂载的 root 分区(退出 chroot
),
# exit
再取消挂载刚才挂载的那些设备,
# umount /sys # umount /proc # umount /dev # umount /mounts/root/boot/efi # umount /mounts/root
最后重启系统,
# reboot
幸运的话重启之后应该直接会进入 GRUB 启动菜单了,至少按 F12 调出的内部启动项里面应该会有 openSUSE 的启动项。
感觉一般情况下只需要走到情形 A 而不至于到情形 B 的程度。©
本文发表于水景一页。永久链接:<https://cnzhx.net/blog/restore-grub2-boot-menu-with-uefi/>。转载请保留此信息及相应链接。
引用通告: T470s 上安装 Linux 滚动发行版 openSUSE Tumbleweed | 水景一页
引用通告: Linux Grub2 必须安装到第一磁盘吗? | 水景一页
引用通告: Manjaro Linux 踩坑调教记录 | 演道网