简介
记录一下UEFI如何启动,以后引导挂了起码有个头绪。
启动过程
UEFI对应的分区表格式是GPT,而不是Legacy BIOS的MBR。
找到ESP分区
启动的时候,UEFI需要先找到GPT分区表中的EFI分区(EFI System Partition),简称ESP分区,分区里面存储了各个系统的启动文件,如果你的电脑装了多个系统,一般来说操作系统安装的时候都会放一份启动文件到这个分区中。
那如何确定哪个是ESP分区呢?
答案是通过分区类型确定。
在GPT分区表中,一个分区项的结构如下:
Offset | Length (bytes) | Description |
---|---|---|
0x0 | 16 | Partition Type GUID (zero means unused entry) |
0x10 | 16 | Unique Partition GUID |
0x20 | 8 | StartingLBA |
0x28 | 8 | EndingLBA |
0x30 | 8 | Attributes |
0x38 | 72 | Partition Name |
从上面的表中可以看出,分区的类型由一个16byte的GUID来表示。ESP分区对应的类型GUID是C12A7328-F81F-11D2-BA4B-00A0C93EC93B
注意:这个类型GUID没有一个统一的标准,不过不同的系统内部使用的GUID还是有规定的,具体参见各个系统的文档。
在Linux中可以通过下面的命令查看分区的类型GUID:
❯ lsblk -o NAME,PARTTYPE
NAME PARTTYPE
loop0
loop1
sda
├─sda1 0fc63daf-8483-4772-8e79-3d69d8477de4
├─sda2 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
├─sda3 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
└─sda4 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
nvme0n1
├─nvme0n1p1 0fc63daf-8483-4772-8e79-3d69d8477de4
├─nvme0n1p2 0fc63daf-8483-4772-8e79-3d69d8477de4
├─nvme0n1p3 0fc63daf-8483-4772-8e79-3d69d8477de4
├─nvme0n1p4 de94bba4-06d1-4d40-a16a-bfd50179d6ac
├─nvme0n1p5 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
├─nvme0n1p6 e3c9e316-0b5c-4db8-817d-f92df00215ae
├─nvme0n1p7 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
├─nvme0n1p8 de94bba4-06d1-4d40-a16a-bfd50179d6ac
├─nvme0n1p9 c12a7328-f81f-11d2-ba4b-00a0c93ec93b #可以看到,这个就是ESP分区
├─nvme0n1p10 0fc63daf-8483-4772-8e79-3d69d8477de4
└─nvme0n1p11 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
当然你肯定记不住这串GUID,还有一个更方便的找到ESP分区的方法:
❯ sudo parted -l
[sudo] password for z:
Model: ATA WDC WD10EZEX-22M (scsi)
Disk /dev/sda: 1000GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 215GB 215GB ntfs
2 215GB 433GB 218GB ntfs msftdata
3 433GB 540GB 107GB ntfs job msftdata
4 540GB 750GB 210GB ntfs msftdata
Model: Colorful CN600 512GB (nvme)
Disk /dev/nvme0n1: 512GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 107GB 107GB ext4
2 107GB 193GB 85.9GB ext4
3 193GB 279GB 85.9GB ext4
4 279GB 280GB 555MB ntfs Basic data partition hidden, diag
5 280GB 280GB 105MB fat32 Old EFI system partition msftdata #### 别看这啊,你以为取个名字就是ESP分区了
6 280GB 280GB 16.8MB Microsoft reserved partition msftres
7 280GB 440GB 160GB ntfs Basic data partition msftdata
8 440GB 440GB 607MB ntfs hidden, diag
9 440GB 441GB 537MB fat32 boot, esp ##### 看这里!esp看见没有
10 441GB 504GB 63.1GB ext4
11 504GB 512GB 8191MB linux-swap(v1) swap
确定启动顺序
前文已经说过ESP分区中,可以存在多个系统的启动文件,多个系统的启动文件一般都放在对应的目录下面,下面来看一下一个ESP分区示例:
~ via 🐍 v3.9.7
❯ sudo ls /boot/efi/EFI/
boot Manjaro Microsoft ubuntu
~ via 🐍 v3.9.7
❯ sudo ls /boot/efi/EFI/Manjaro
grub.cfg grubx64.efi
在ESP分区中,有一个/EFI
目录,目录里面各个系统有各个系统的子目录,如Manjaro, ubuntu, Microsoft
等,子目录里面存储了各个系统的启动文件,如/EFI/Manjaro/grubx64.efi
。此外,/EFI
目录下还有一个boot
目录,这个目录下存放的是默认的启动文件。
那么问题来了,这么多系统的启动文件都存放在同一个ESP分区中,先启动哪一个呢?
这就涉及到“BBS优先级”了。
Note: BBS = BIOS Boot Specification
折腾BIOS的时候都在主板配置里面看到过一个东西叫“BBS优先级”,这是一个列表,里面存储了各个系统的启动优先级。
所以,同一个ESP分区中,先启动哪一个系统,是由BBS优先级决定的。
那优先级文件在哪呢?
没有文件,BBS优先级被存储在主板的NVRAM中。
NVRAM是指Non-Volatile RAM,即非易失RAM,这个NVRAM在主板中,并不在磁盘上。仔细想想这样也很正常,因为一个系统可以有很多块硬盘,如果BBS优先级都存储在硬盘上,那拔掉那块存储启动顺序的硬盘岂不是乱套了。
需要注意的是,一般来说,在系统安装的时候,都会往NVRAM中写入新安装系统的启动项,但是如果由于某种原因没有添加成功,或者不小心被自己删除了,可以通过Linux下的efibootmgr
命令添加BBS启动项。
加载
找到了ESP分区、确定了启动顺序之后,那就要加载启动文件了。说是启动文件,其实准确地说是OS的引导文件,这篇文章主要想记录的是UEFI的启动流程,而不是Bootloader,所以之后的过程就不写了。
总结
UEFI启动顺序:
- 找到ESP分区
- 从NVRAM中读取BBS优先级,确定启动哪个OS
- 加载对应OS的bootloader
参考资料
- https://harddrivetalk.com/what-are-hard-drive-bbs-priorities-and-how-are-they-useful/
- https://wiki.osdev.org/EFI_System_Partition
- https://wiki.osdev.org/GPT