引导总结

今天帮同学改引导,原本打算改为开机grub引导的,没想到后来把他引导给搞没了233,特记这文章留念(误)

既然要讲grub,我们先把系统的启动流程说一下(注:现在基本都用efi,不讲mbr)

UEFI

EFI(Extensible Firmware Interface,可扩展硬件接口)有英特尔主导开发,是用模块化,高级语言(主要是C)构建的一个小型化系统,它和BIOS一样,主要在启动过程中完成硬件初始化

EFI发展至2.0时,英特尔将其转交给一个叫做Unified EFI Form的国际组织,并改称为UEFI

或许比起UEFI,我们应该更熟悉BIOS这个名词.事实上,UEFI可以理解为BIOS的升级版

UEFI往往与GPT相配合使用,UEFI会寻找GPT硬盘中的ESP分区,并加载里面的efi文件,从而把控制权转交给bootloader

总的来说,UEFI为我们提供了这样的规范:

  1. 读取分区表(GPT或MBR)
  2. 访问某些特定文件系统中的文件(FAT系列文件系统,/EFI/SYSTEMNAME/XXX.efi文件)
  3. 执行特定格式的代码(efi文件固定规范的代码)

UEFI启动管理器

UEFI规范定义了名为UEFI启动管理器的一项功能,它的定义如下:”UEFI启动管理器是一种固件策略引擎,可通过修改固件架构中定义的全局NVRAM变量来进行配置.启动管理器将尝试按全局NVRAM变量定义的顺序依次加载UEFI驱动和UEFI应用程序(包括UEFI操作系统启动装载程序).”

简单来说,UEFI启动管理器可以管理UEFI的启动菜单,例如调整顺序,删除,添加.它最大的优点就是可以从上层系统修改UEFI的行为.在Linux中UEFI启动管理器叫做efibootmgr

例如:查看当前启动顺序

1
2
3
4
5
6
7
8
9
# zhanghuidinah @ study in /boot/EFI [23:41:34] 
$ efibootmgr
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0001,3001,0002,2001,2002,2004
Boot0001* grub
Boot0002* Windows Boot Manager
Boot2001* EFI USB Device
Boot3001* Internal Hard Disk or Solid State Disk

如上,可以看出启动顺序从前到后分别是:grub,Windows Boot Manager,USB等等

我的同学的情况是Windows Boot Manager的启动顺序先于grub,因此他的电脑一开机就直接进入Windows.如果想要默认进入grub的话,那么可以禁用Windows Boot Manager,或者调整grub优先于Windows Boot Manager

例:暂时禁用Windows Boot Manager:

1
2
3
4
5
6
7
8
9
# zhanghuidinah @ study in /boot/EFI [23:41:39] 
$ sudo efibootmgr -A -b0002
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0001,3001,0002,2001,2002,2004
Boot0001* grub
Boot0002 Windows Boot Manager
Boot2001* EFI USB Device
Boot3001* Internal Hard Disk or Solid State Disk

例:调整Windows Boot Manager优先于grub

1
2
3
4
5
6
7
8
$ sudo efibootmgr -o 0002,0001,3001,2001
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0002,0001,3001,2001
Boot0001* grub
Boot0002 Windows Boot Manager
Boot2001* EFI USB Device
Boot3001* Internal Hard Disk or Solid State Disk

GPT

GPT(GUID Partition Table,全局唯一标识磁盘分区表)是一个实体硬盘的分区表的结构布局的标准.它是可扩展固件接口(EFI)标准的一部分,被用于替代BIOS系统中的(MBR)分区表.UEFI规范要求UEFI兼容固件必须能识别GPT

GPT按LBA(逻辑区块地址,即扇区)划分,一般分为保护MBR部分和EFI部分;而EFI部分又可以分为4个区域:EFI信息区(GPT头),分区表,GPT分区,备份区域

ESP

MBR分区表使用前446个字节来存放bootloader,而GPT分区表则使用一个单独的分区,即ESP(EFI System Partition)分区

ESP是一个有着FAT文件系统的物理分区.支持EFI的电脑可以从ESP启动系统,EFI固件能从ESP中加载EFI启动程序

ESP分区有一个特殊的GUID号,EFI借此识别引导分区并使用此分区的bootloader引导系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# zhanghuidinah @ study in /boot/EFI [23:20:02] 
$ sudo gdisk /dev/nvme0n1
GPT fdisk (gdisk) version 1.0.4

Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p
Disk /dev/nvme0n1: 500118192 sectors, 238.5 GiB
Model: SAMSUNG MZVLW256HEHP-00000
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): EAF8EAEA-1222-4893-94CF-F701E0A56415
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 500118158
Partitions will be aligned on 2048-sector boundaries
Total free space is 57815576 sectors (27.6 GiB)

Number Start (sector) End (sector) Size Code Name
1 2048 1023999 499.0 MiB 2700 Basic data partition
2 1024000 1226751 99.0 MiB EF00 EFI System Partition
3 1226752 1259519 16.0 MiB 0C01 Microsoft reserved ...
4 1259520 359237061 170.7 GiB 0700 Basic data partition
6 417050624 500118158 39.6 GiB 8300 Linux filesystem

可以看到,第2个分区就是ESP.因此,成为ESP有两个条件:

  1. code号为EF00
  2. 分区格式为FAT相关(这里是FAT32)

grub

grub(GRand Unified Bootloader)是一个GNU项目的多操作系统启动程序,也是目前使用最广泛的bootloader.注:bootloader的根本目的是启动内核

grub有grub和grub2两个版本,grub2是grub的重写改进版,已广泛应用于各类计算机,现在只能手机,嵌入式设备等小型计算机还在使用grub.以下grub即代指grub2

UEFI会在/EFI文件夹中查找所有文件夹,并搜寻efi文件:

1
2
3
# zhanghuidinah @ study in /boot/EFI [23:57:00] 
$ ls
Boot grub Microsoft

如上,除了Boot文件夹,还有grub文件夹和Microsoft文件夹,这也是开机启动顺序所显示的名称.而这两个文件夹则分别存放着grub和Windows Boot Manager这两个bootloader的efi文件:/EFI/grub/grubx64.efi/EFI/Miscosoft/Boot/bootmgfw.efi

grubx64.efi把grub程序加载至内存后,计算机将显示grub的主界面

安装grub

安装grub首先要确定有ESP,并将其挂载到一个目录中,例如/efi

然后,使用grub-install命令生成grubx64.efi文件,并将grub的模块放在/boot/grub/x86_64-efi/:

1
]# grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=grub_dir

如上,将会生成/efi/EFI/grub_dir/grubx64.efi文件

在安装后,还需要生成grub.cfg文件.注意生成的行为实际上是综合了/etc/default/grub的选项和/etc/grub.d/里的脚本:

1
]# grub-mkconfig -o /boot/grub/grub.cfg

往往不需要自己手动更新Windows的引导,grub-mkconfig会执行/etc/grub.d/30_os-prober脚本文件,该文件会搜寻所有可加载的内核,并生成启动项

小结

这次复习了一遍操作系统启动相关的知识,下次配置引导时应该不会失败了吧orz

最后用一张图总结一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
                  +-----+
| 开机 |
+-----+
|
v
+------+
| UEFI |
+------+
|
v
硬件初始化
|
v
查找ESP
|
v
查找/EFI/XXX文件夹下的.efi文件(grub是grubx64.efi)
|
v
+------+
| grub |
+------+
|
v
加载/boot/grub/的模块以及配置文件
|
v
根据配置加载操作系统内核
+
v
+----+----+
| 操作系统 |
+---------+

补充

后来发现UEFI并非一定要需要/EFI/Boot/bootx64.efi文件.当出现开机启动顺序时,可以看到一个叫做Internal Hard Disk or Solid State Disk的选项,也就是从硬盘启动.如果选择从硬盘启动的话,那么UEFI才会加载该文件.它是计算机默认引导文件

事实上,bootx64.efi是通用名,任何其他的引导文件都可以改成这个名称,放在/EFI/Boot目录下,从而成为计算机默认引导文件.由于我的电脑最初安装的是Windows,所以bootx64.efi就是bootmgfw.efi

1
2
3
4
5
6
7
8
9
10
11
# zhanghuidinah @ study in /boot/EFI [8:10:00] 
$ md5sum Boot/bootx64.efi
abbeaff26e8180a1ef28a9bf20e12547 Boot/bootx64.efi

# zhanghuidinah @ study in /boot/EFI [8:10:07]
$ md5sum Microsoft/Boot/bootmgfw.efi
abbeaff26e8180a1ef28a9bf20e12547 Microsoft/Boot/bootmgfw.efi

# zhanghuidinah @ study in /boot/EFI [8:10:22]
$ md5sum grub/grubx64.efi
e5143715e7f96bf03548757c9a876994 grub/grubx64.efi

如果是在U盘上写入grub的话,在使用grub-install时需要添加--removable选项(将grubx64.efi文件改名为bootx64.efi);如果之前已经安装过grub需要重装时,则需要添加--recheck选项(删除原有grub相关的所有文件,再安装)


grub-install默认生成的grub文件夹在/boot目录下.又由于grub文件夹必须在esp中,这样esp就只能是/boot目录

如果想要esp和/boot目录相互独立,需要在使用grub-install命令时添加--boot-directory=DIR参数,将grub文件夹指定于DIR/grub目录

参考文档

Linux公社:GRUB2手动引导Ubuntu

archlinux wiki:GRUB

金步国:GRUB2配置文件”grub.cfg”详解(GRUB2实战手册)

0%