2023年11月28日发(作者:)

ubuntu20.04win7UEFI+GPT双启动修复

⽼笔记本,⼀直⽤的ubuntu14.04win7双系统。因为怕折腾,⼀直没有升级ubuntu,毕竟⾥⾯有数年常⽤的数据、软件,升级的话不折腾⼏天是搞不定的。不过

ubuntu14.04的⽀持基本到头了,趁着ubuntu20.04 LTS新鲜出炉,决定尝试⼀下。

这⼀尝试,⾸先出现的问题就是引导挂了。只进⼊了grub shell,然后我进⼊LiveCDboot-repair⼀顿操作,把win7的启动也弄挂了,这。。。只能⼿动慢慢修了。要修就

得先知道UEFI是怎么⼯作的,这⾥先简单说下UEFI的启动过程。

⽀持UEFI的主板上都有NVRAM(Non-Volatile Ram即掉电也不丢失数据的存储空间),安装操作系统的时候,通常都会在NVRAM写⼊引导项,这个列表除了安装操作系统时

写⼊的引导项,还有⼀些固定的硬件引导项,⽐如硬盘、U盘、⽹络启动)。在开机的时候,进⼊BIOS应该是能看到这个列表的,不同的主板操作不⼀样,我机⼦上的NVRAM

表看起来是这样的:

ubuntu是安装ubuntu时写⼊的引导项,IPV4Boot From EFI File则是⼀些固定的硬件引导项。

实现UEFI启动,硬盘上还需要有⼀个ESP分区(EFI system partition),然后安装操作系统时,会在ESP分区写⼊引导⽂件。我机⼦上的ESP分区⼤概是这样的:

~$ sudo tree /boot/efi/EFI -L 3

/boot/efi/EFI

├── Boot

├──

├──

├──

├──

├──

└──

├── Microsoft

└── Boot

├── BCD

├──

├── 1

├── 2

├──

├──

├──

├── cs-CZ

├── da-DK

├── de-DE

├── el-GR

├── en-US

├── es-ES

├── fi-FI

├── Fonts

├── fr-FR

├── hu-HU

├── it-IT

├── ja-JP

├── ko-KR

├──

├── nb-NO

├── nl-NL

├── pl-PL

├── pt-BR

├── pt-PT

├── ru-RU

├── sv-SE

├── tr-TR

├── zh-CN

├── zh-HK

└── zh-TW

└── ubuntu

├──

├──

├──

├──

└──

28 directories, 19 files

其中,Boot⽬录是ESP分区的默认⽬录,Microsoftwin7的引导⽬录,ubuntu则是ubuntu的引导⽬录,注意,ESP分区是fat格式,这些⽬录及⽂件名不区分⼤⼩写。

当开机时,主板加电,会从NVRAM中读取引导列表,按顺序⼀个个去尝试引导启动,如果成功,就会进⼊对应的操作系统。例如,我的机⼦在开机时选择ubuntu的话,则

主板会根据NVRAMubuntu这个项中的信息,直接加载ESP分区中的ubuntu/,然后ubuntu/会启动grub,接着由grub启动ubuntu,完成ubuntu的启动。

如果选择从硬盘启动(我机⼦的BIOS中没显⽰这个项,后⾯会说到),那就会在硬盘中查找ESP分区(ESP分区在同⼀个硬盘可以有多个,会⼀个个去试),如果ESP分区中存

/Boot/,就运⾏这个⽂件,完成引导,所以Boot⽬录称为ESP的默认⽬录。

回到之前的问题,我安装ubuntu后,没能引导进系统,⽽是挂在grub shell了,说明UEFI已经正确加载了ubuntu/,但在grub那⼀步,grub没能成功启动ubuntu

这可能是配置错误,⽐如错误。但我的系统是全新安装的,grub的配置不⼤可能会出问题,可能是⼀些环境变量不对,尝试⼿动加载。我的硬盘是gpt模式,ubuntu

装在第7个区分,没有使⽤独⽴的boot分区,因此boot⽬录是在ubuntu分区的boot⽬录下,即(hd0,gpt7)/boot/grub。如果不记得安装在哪个分区,可以⽤ls (hd0,gpt7)这样⼀个个

去试,会打印⼀些分区信息

grub > ls

(hd0), (hd0,gpt8),(hd0,gpt7),(hd0,gpt6),(hd0,gpt5),(hd0,gpt4),(hd0,gpt3),(hd0,gpt2),(hd0,gpt1)

grub > set root=(hd0,gpt7)

grub > set prefix=(hd0,gpt7)/boot/grub

grub > insmod normal

grub > normal

如果成功,会出现后⾯那个grub菜单,即可进⼊系统。如果失败,或者⽆法引导进⼊系统,那么说明grub已经没救了(⾄少以我的⽔平救不了了),你需要⼀个LiveCD之类的盘

了。进⼊系统后,就需要修复⼀下grub

sudo update-grub

Sourcing file `/etc/default/grub'

Sourcing file `/etc/default/grub.d/init-select.cfg'

正在⽣成 grub 配置⽂件 ...

找到 Linux 镜像:/boot/vmlinuz-5.4.0-26-generic

找到 initrd 镜像:/boot/-5.4.0-26-generic

Adding boot menu entry for UEFI Firmware Settings

完成

update-grub会搜索当前系统,查找各种启动,然后完成修复。按我的理解,update-grub只是修复grub引导,即对应/boot/grub⽬录下的东西,并不会修改ESP分区以及NVRAM

的东西,但Adding boot menu entry for UEFI Firmwre Settings实在让⼈困惑,这个像是往NVRAM添加引导项。

如果进⼊的是LiveCD,那么当前系统并不是你想要修复的系统,你想修复的系统还在硬盘上,那么⼿动修复就复杂多了,我没这样操作过。在LiveCD可以使⽤boot-repair来修

sudo add-apt-repository ppa:yannubuntu/boot-repair && sudo apt-get update

sudo apt-get install -y boot-repair && boot-repair

boot-repair是⼀个带UI的程序,在菜单⾥找到它直接按提⽰操作就好。我的机⼦修复好以后,ubuntu能进了,但是win7的导引没了。⽽且,出现了新的问题

每次启动时,都会提⽰

System BootOrder not found. Initializing defaults.

Creating boot entry "Boot0001" with label "ubuntu" for file ""

⽽且这个Boot0001会依次增加为Boot0001Boot0002Boot0003,这样⼀直加下去,但是能正常进⼊ubuntu系统。根据上⾯UEFI的启动过程,可以推断,提⽰这个的时候,

主板还没加载任何efi⽂件,⽽是在尝试引导某个NVRAM中的启动项时失败,然后主板在ESP分区找到了这个⽂件,并⽤这个⽂件引导ubuntu。我的直觉

NVRAM列表有问题,需要修复下。在ubuntu下,可以⽤efibootmgr来管理NVRAM列表

~$ efibootmgr

BootCurrent: 0002

Timeout: 0 seconds

BootOrder: 0002

Boot0000* ubuntu

Boot0001* ubuntu

Boot0002* ubuntu

$ efibootmgr -v

BootCurrent: 0002

Timeout: 0 seconds

BootOrder: 0002

Boot0000* ubuntu HD(1,GPT,2b776bfe-665b-4a9a-995f-4c74e11712a4,0x800,0x95800)/File()

Boot0001* ubuntu HD(1,GPT,2b776bfe-665b-4a9a-995f-4c74e11712a4,0x800,0x95800)/File()

Boot0002* ubuntu HD(1,GPT,2b776bfe-665b-4a9a-995f-4c74e11712a4,0x800,0x95800)/File()

sudo efibootmgr -b 0001 -B

sudo efibootmgr -b 0002 -B

sudo efibootmgr -o 0000

sudo efibootmgr -b 0000 -a

通过efibootmgr指令可以看到主板已经给NVRAM列表添加了⼏个ubuntu,通过efibootmgr -v可以查看他们的参数(当选择NVRAM的⼀个启动项时,主板知道去哪个分区运⾏哪

efi⽂件,就是根据这些参数来的)。但是并没有看出什么问题,似乎⼀切正常。于是我把多余的删除了

sudo efibootmgr -b 0001 -B # 把启动项0001删了

sudo efibootmgr -b 0002 -B # 0002删了

sudo efibootmgr -o 0000 # 设置0000为第⼀启动顺序

sudo efibootmgr -b 0000 -a #设置0000为活动启动项

重启,结果发现还是⼀样,主板⼜⾃动加了⼀个0001回来,参数还是⼀模⼀样。我怀疑是哪⾥操作错误,没修改到NVRAM列表,于是把它们⼜删了,还故意创建了⼀个win的引

导项

~$ sudo efibootmgr -c -d /dev/sda -p 1 -L "Windows Boot Manager" -l ""

BootCurrent: 0002

Timeout: 0 seconds

BootOrder: 0001,0000

Boot0000* ubuntu

Boot0001* Windows Boot Manager

重启,发现NVRAM列表确实有修改到,多了Windows Boot Manager,不过问题依然存在。

⾄此,NVRAM像是没有问题的,那么我就怀疑ESP分区了。于是我直接把ESP分区给格了。然后重新安装

:~$ sudo update-grub

Sourcing file `/etc/default/grub'

Sourcing file `/etc/default/grub.d/init-select.cfg'

正在⽣成 grub 配置⽂件 ...

找到 Linux 镜像:/boot/vmlinuz-5.4.0-26-generic

找到 initrd 镜像:/boot/-5.4.0-26-generic

Adding boot menu entry for UEFI Firmware Settings

完成

:~$ sudo grub-install /dev/sda

正在为 x86_64-efi 平台进⾏安装。

安装完成。没有报告错误。

update-grub是修复/boot/grub的,我这⾥并没修改,其实是不需要运⾏的,不过为了保险再修复⼀次。grub-install是把当前系统的启动信息安装到ESP分区,会在ESP分区⽣成

ubuntu⽬录和Boot⽬录,并且在NVRAM添加引导项。然后检测ESP分区(ubuntu20.04⾥,已挂载到/boot/efi/EFI⽬录,ls就能看到⽂件)的各个⽂件,确认Bootubuntu⽬录确

实存在,并且各⽂件的⽇期也是刚更新的,然后重启,问题依然存在。

到了这⾥,我已经技穷了,实在想不出来有啥可以操作的了。甚⾄还试了下在LiveCD下修复

mkdir /mnt/sda7

mount /dev/sda7 /mnt/sda7

grub-install --boot-directory=/mnt/sda7 /dev/sda

# 由于LiveCD不是要修复的系统,需要把要修复的系统mount到当前系统

# 然后修复的时候指定启动⽬录为需要修复的系统⽬录

然⽽并没有什么区别。疯狂地google "System BootOrder not found"这些关键字,发现有不少例⼦,都没能说明⽩啥原因造成,不过我也尝试了他们的⼀些做法:

1. BIOS设置中把ubuntu放到第⼀项,但是我的BIOS没有这个选项,尝试失败

2. 尝试创建⼀个启动项,⼿动指定到ESP分区的/ubuntu/。我机⼦的BIOS确实有⼀个Customized Boot,不过不管我输⼊啥,在NVRAM列表中都不会出现这个选项,

只能放弃了

3. 直接使⽤Boot From EFI FileESP分区的/boot/启动,能进⼊系统,但问题依旧

4. 直接从NVRAM中选择ubuntu进⼊,问题解决,但我机⼦的BIOS⽆法设置ubuntu为第⼀启动项,所以这个不是办法

5. 接使⽤Boot From EFI FileESP分区的/ubuntu/启动,问题解决,但是这个只能⼿动启动

6. ESP分区⾥的/ubuntu/覆盖/Boot/,问题依然

7. ESP分区Boot⽬录⾥的⽂件全删了,复制ubuntu⽬录中的所有⽂件到Boot⽬录,然后把改名,问题解决

现在,"System BootOrder not found"这个问题是如何出现的,没法知道原因。google得到的结果⾥,多数也归为BIOS固件和UEFI的兼容问题,并且不少都提到hp笔记本的

固件,我的刚好就是hp笔记本。没办法解决这个问题,只能绕过它。从结果上看,这有⼏个问题。第⼀,grub-installESP分区⽣成的Boot/,在我的笔记本上⽆法正

常引导ubuntu;第⼆,hpBIOS没有按UEFI标准来引导系统,NVRAM列表上⼀直有ubuntu,但是没有硬盘的选项,⽽启动的时候,却直接从硬盘启动,然后执

/Boot/,正常应该是先尝试NVRAM中设定的选项;第三,hp这个BIOS很坑,不仅不能像别的那样设定NVRAM的启动顺序,它⼀直有⼀个OS Boot Manager,这个

OS Boot Managerefibootmgr看不到,改不了,选中的时候主是从硬盘启动,我怀疑直接从硬盘启动就是这个隐藏选项的问题

ubuntu的启动问题总算解决了,下⼀步,就是要修复win7的启动。windows系统启动时,加载ESP分区的EFI/Microsoft/⽂件,读取⽬录下的BCD

⽂件(boot configuration data),BCD保存了win的启动信息,⽐如在哪个分区。如果是多个win系统,也是在这⾥配置。根据BCD,加载对应分区

“”,之后加载windows内核,启动完成。

win也提供了启动修复⼯具:。进⼊PE,确保win系统分区和ESP分区已挂载,我这⾥刚好是CH盘,和bcdboot的帮助⽂档⼀致

执⾏

bcdboot c:windows /s h: /f UEFI /l zh-cn

:: 表⽰c:windows为系统⽬录

:: hESP分区

:: 启动⽅式为UEFI

:: 启动语⾔为中⽂简体

执⾏完后,检查ESP分区,正确创建了Microsoft⽬录。PS:看⽹上有些⼈说bcdboot修复会覆盖ESP分区⾥的Boot⽬录,我试了下,在我机⼦并不会出现这种情况,如果出现了

再⽤ubuntu的启动⽂件重新覆盖⼀次。

重启,我发现在BIOS⾥并没有windows的引导项。但是,我⽤efibootmgr来检查,win7引导项是有在NVRAM列表中的,⽽我的ubuntu反⽽不见了。。。也不知道是bcdboot

给清了,还是主板BIOS的问题,不过反正ubuntu那个引导项从来不会排在第⼀启动项,所以我也不纠结这个,直接默认从硬盘启动就好。

:~$ efibootmgr -v

BootCurrent: 0000

Timeout: 0 seconds

No BootOrder is set; firmware will attempt recovery

Boot0000* Notebook Hard Drive BBS(HD,,0x0).......................................................................

Boot0001* SD Card BBS(7,,0xa0).......................................................................

Boot0002* Windows Boot Manager HD(1,GPT,2b776bfe-665b-4a9a-995f-4c74e11712a4,0x800,0x95800)/File()B.C.D.O.B.J.E.C.T.=.{.a.8.-.5.c.d.d.-.4.e.7.0.-.1.-.f.3.2.b.3.4.4.d.

UEFI模式下,Linux + Win双系统引导只有两种⽅式,⼀是由BIOS引导,在NVRAM列表⾥直接选择启动哪个系统,不过我这⾥在BIOS⾥没有出现win的引导项,⽽且没法设

置默认ubuntu启动,所以不考虑;⼆是由Linuxgrub来引导win系统。不存在win引导linux的选项,因为到⽬前为⽌,⼀旦加载ESP分区的/Microsoft/Boot/。它就会

读取BCD中的配置,如果有多个系统,就会出现⼀个选择菜单,如果这⾥加了⼀个linux系统,它是不认linux系统的数据,引导不成功的,所以它可以引导多个windows,但不能

引导linux系统。

进⼊ubuntu,⽤update-grub来更新grub配置

~$ sudo update-grub

Sourcing file `/etc/default/grub'

Sourcing file `/etc/default/grub.d/init-select.cfg'

正在⽣成 grub 配置⽂件 ...

找到 Linux 镜像:/boot/vmlinuz-5.4.0-26-generic

找到 initrd 镜像:/boot/-5.4.0-26-generic

找到 Windows Boot Manager 位于 /dev/sda1@/EFI/Microsoft/Boot/

Adding boot menu entry for UEFI Firmware Settings

完成

如果win的启动配置正确,update-grub应该是能够分析到win的引导并加⼊到grub中,如果不⾏,那得⼿动编辑/boot/grub/来⼿动添加⼊⼝。由于grub配置和ESP分区⽆

关,因此不需要grub-install,重启,应该能在grub选择菜单中看到win7了。

关于SecureBoot,安全启动,是说在整个启动过程中,所调⽤的⽂件都是经过签名的。⽐如启动⽤的,还有系统启动时⼀些驱动等。ubuntu官⽅的⽂件是有签名

的,因此⽀持安全启动,但是有⼀些驱动是私有的,⽐如AMDNVIDIA的显卡驱动,是没有经过签名的,如果有⽤这类的驱动,就得关闭安全启动。

关于UEFI CSM(Compatibility Support Module)UEFI的兼容模块,允许操作系统以旧的BIOS-MBR模式启动。win7必须得开启CSM才能正常启动,部分⼈以为是win7需要

MBR模式引导,这个是错误的。关闭CSM,⽤UEFI GPT的⽅式win7⼀样能引导,只是卡在启动中,⼀般是在windows那个图标的位置就花屏了。UEFI不仅仅是从NVRAM

取引导项,去ESP分区加载引导程序这么简单的,这只是它⼀⼩部分的功能。它的另⼀个功能,是定义了UEFI下的⼀些显⽰规则,所以UEFI的主板,启动过程可以做得很炫

酷。UEFI引导win7是没问题的,但是win7的驱动不⽀持UEFI的显⽰,因此完成引导后,就跑不下去了。有传闻说,只要愿意启动过程⿊屏,win7也是可以纯UEFI启动的(我没

试过,尝试的话后果⾃负)

设置启动过程⿊屏

/store S:efiMicrosoftbootbcd /set {default} novesa on

然后删掉

C:WindowsSystem32drivers,把

ubuntu20.04是两者都⽀持的,但在CSM模式下,明显驱动没写好,OEM logo被拉伸了,正常情况下,hp这个应该是圆的