计算机的启动方式有哪些计算机启动知识系列UEFI/GPT计算机的启动方式有哪三种




计算机的启动方式有哪些计算机启动知识系列UEFI/GPT计算机的启动方式有哪三种

2022-07-20 19:59:53 网络知识 官方管理员

这一章我们主要介绍UEFI固件和GPT分区格式,通过上面文章我们也知道BIOS所存在的缺点,而UEFI就是为了解决这些问题。UEFI除了提供BIOS解决的问题外,它同时也提供了更加丰富的图形界面,对用户更加的友好,而且EFI程序支持C语言编写,提升了工作效率。但相对了,我们的工作都是在重复一个步骤,就是简单,发现简单无法解决更多的问题,而引入了复杂化,而UEFI就存在这个问题,UEFI的引入使得设计更加的复杂。也许,以后为了简单性,由出现了新的固件技术也说不定。

UFEI与GPT

在这里我们不会介绍UEFI的历史,我们重点关注UEFI的角色,如何编写UEFI程序以及支持UEFI的计算机如何启动的。我们关于UEFI的文章主要围绕这些问题展开,首先我们需要了解UEFI,UEFI是为了解决BIOS所存在的问题而从新设计的一套固件系统,它不是BIOS,虽然UEFI也引入了兼容模式,兼容模式可以让我们像BIOS那样启动系统,但记住UEFI不是BIOS

在概述中,我们知道支持UEFI引导的计算机启动后交给UEFI固件,后续由UEFI进行后续的工作,在这里我们重点关注UEFI的引导功能,同时为了解决MBR分区格式无法支持更大的磁盘空间引入了GPT分区,GPT分区也是UEFI规范中的内容。UEFI会根据设置的启动顺序,查找GPT分区表中GUID为C12A7328-F81F-11D2-BA4B-00A0C93EC93B的EFI分区表。找到EFI分区表后,UEFI将会把系统权限交给对应的引导程序,后续的引导程序负责引导操作系统启动。这里GPT分区是什么?C12A7328-F81F-11D2-BA4B-00A0C93EC93B这串莫名其妙的数据又是什么?EFI分区表又是什么?下面我们来揭开这些面纱吧!

GPT

GPT全称GUIDPartitionTable,它是为了替代MBR分区表,使得能够支持更大空间的磁盘而设计的分区方案。现代的操作系统基本上都支持GPT分区表。UEFI规范明确使用GPT分区表的EFI系统分区进行系统引导工作。我们先看一下GPT的全景图

计算机的启动方式有哪些(计算机启动知识系列UEFI/GPT)(1)

GPT分区同样使用LBA寻址,正如在图上显示的磁盘中的第一个LBA0中保存的是保护性MBR(protectiveMBR),这个扇区是磁盘的第一个扇区,早期为了向前兼容,通常保留不用,但现在也为了防止基于MBR的工具错误识别从而导致破坏GPT分区的作用,而且这个扇区的类型设置为0xEE来表示它是一个保护性的MBR。LBA1(第二个扇区)保存的是GPT分区头,这个分区中包含了有关GPT分区详细的特征数据。对于扇区大小为512字节的硬盘,从LBA2-LBA33保存的是分区表数据,一个分区项占用128个字节。而对于4096字节大小的扇区只需要4个扇区保留分区表就可以。磁盘的最后保存了分区表的一个备份,这个备份包含了全部的分区表和分区头信息。

对于LBA1的GPT头的详细数据如下

偏移量

长度

描述

0(0x00)

8bytes

签名("EFIPART",45h46h49h20h50h41h52h54h/0x5452415020494645ULL[a]小端序)

8(0x08)

4bytes

版本1.0(00h00h01h00h)forUEFI2.8

12(0x0C)

4bytes

以小端序的头大小(二进制5Ch00h00h00h或者92字节)

16(0x10)

4bytes

以小端序头的CRC32

20(0x14)

4bytes

保留,设置为0

24(0x18)

8bytes

头的位置

32(0x20)

8bytes

头的备份位置

40(0x28)

8bytes

第一个可用的LBA

48(0x30)

8bytes

最后一个可用的LBA

56(0x38)

16bytes

混合字节序的GUID

72(0x48)

8bytes

分区表的起始位置

80(0x50)

4bytes

有多少个分区项

84(0x54)

4bytes

每个分区项的大小

88(0x58)

4bytes

分区项的CRC32

92(0x5C)

*

保留,后面的直接设置为0

分区表项中的详细数据

偏移量

长度

描述

0(0x00)

16bytes

具有特殊含义的混合字节序GUID,表明分区类型

16(0x10)

16bytes

混合字节序的GUID,标志这个分区

32(0x20)

8bytes

此分区第一个LBA,小段序

40(0x28)

8bytes

此分区最后

48(0x30)

8bytes

属性字段

56(0x38)

72bytes

分区名称

这个表主要重点关注的是第一项和第二项,第一项由预定义的值,这些值表明不同的含义,比如C12A7328-F81F-11D2-BA4B-00A0C93EC93B就表示EFI系统分区,是EFI专用的分区。而第二个是可以随机生成的,标志这个分区。

一个GPT的例子

在这里我们使用的系统是使用efi方式安装的ubuntu虚拟机,首先我们先使用fdisk工具打印磁盘的一些信息

$sudofdisk-l/dev/sdaDisk/dev/sda:50GiB,53687091200bytes,104857600sectorsDiskmodel:VBOXHARDDISKUnits:sectorsof1*512=512bytesSectorsize(logical/physical):512bytes/512bytesI/Osize(minimum/optimal):512bytes/512bytesDisklabeltype:gptDiskidentifier:2A7B0333-1C74-443D-8BA2-162A6F4733F7DeviceStartEndSectorsSizeType/dev/sda1204810506231048576512MEFISystem/dev/sda2105062410485555110380492849.5GLinuxfilesystem

从这个信息中,我们知道这个虚拟机使用了两个分区,sda1是EFI系统分区的类型,sda2是Linux文件系统的分区。下面我们将使用gpt分析磁盘中的真实数据是否如fdisk中显示的一致。

和在MBR中一样我们使用的还是gpt工具,首先我们需要先获取第一个lba,即lba0

$pipinstallgpt#pip我一般通过virtualenv使用$sudoddif=/dev/sbabs=512count=1skip=0>lba.0

这个命令将会将sda设备中的第一个扇区读取出来并且保存到lba.0中,然后我们使用gpt工具进行

$catlba.0|print_mbr<<<MBR>>>BootCode:0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000UniqueMBRDiskSignature:0x00000000Unknown:0x0000PartitionRecord:0x00000200eeffffff01000000ffff3f06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Signature:0xAA55<<<MBRPartition#0>>>#0.BootIndicator:0x0#0.IsBootable?(syn):No#0.StartingCHS:0,0,2#0.OSType:0xEE#0.OSType(syn):GPTProtective#0.EndingCHS:255,255,255#0.StartingLBA:1#0.SizeInLBA:104857599<<<MBRPartition#1>>>#1.BootIndicator:0x0#1.IsBootable?(syn):No#1.StartingCHS:0,0,0#1.OSType:0x0#1.OSType(syn):Empty#1.EndingCHS:0,0,0#1.StartingLBA:0#1.SizeInLBA:0<<<MBRPartition#2>>>#2.BootIndicator:0x0#2.IsBootable?(syn):No#2.StartingCHS:0,0,0#2.OSType:0x0#2.OSType(syn):Empty#2.EndingCHS:0,0,0#2.StartingLBA:0#2.SizeInLBA:0<<<MBRPartition#3>>>#3.BootIndicator:0x0#3.IsBootable?(syn):No#3.StartingCHS:0,0,0#3.OSType:0x0#3.OSType(syn):Empty#3.EndingCHS:0,0,0#3.StartingLBA:0#3.SizeInLBA:0

0xAA55的签名显示这个一个有效的MBR,它的446个字节的引导代码都是0,并且类型显示是0xEE说明它是GPT的保护性MBR,GPT的实际分区以LBA1开始,下面打印lba1的数据

$sudoddif=/dev/sdbbs=512count=1skip=1>lba.1$catlba.1|print_gpt_headerWarning:Usingonlythefirst92bytesofinput<<<GPTHeader>>>Signature:0x4546492050415254Revision:0x00000100HeaderSize:92HeaderCRC32:0xad41c4b0HeaderCRC32(calculated):0xad41c4b0Reserved:0x00000000MyLBA:1AlternateLBA:104857599FirstUsableLBA:34LastUsableLBA:104857566PartitionEntryLBA:2NumberOfPartitionEntries:128SizeOfPartitionEntry:128PartitionEntryArrayCRC32:0x1bc39ab0

LBA1是GPT的头信息,这个头显示了一些详细的信息

  • 首先头位于LBA1

  • 备份信息位于104857599(AlternateLBA)

  • 第一个可用的扇区位于LBA-34(FirstUsableLBA),和我们之前说的一致,512字节扇区需要33个扇区包含分区信息,实际数据从34开始

  • 最后一个可用的扇区位于LBA-104857566(LastUsableLBA)

  • 分区表信息从LBA-2开始(PartitionEntryLBA)

  • 这个分区表有128项(NumberOfPartitionEntries),每一项都有128个字节(SizeOfPartitionEntry)

然后,我们按照AlternateLBA找到对应的备份数据

$catlba.104857599|print_gpt_headerWarning:Usingonlythefirst92bytesofinput<<<GPTHeader>>>Signature:0x4546492050415254Revision:0x00000100HeaderSize:92HeaderCRC32:0x4d7ce45aHeaderCRC32(calculated):0x4d7ce45aReserved:0x00000000MyLBA:104857599AlternateLBA:1FirstUsableLBA:34LastUsableLBA:104857566PartitionEntryLBA:104857567NumberOfPartitionEntries:128SizeOfPartitionEntry:128PartitionEntryArrayCRC32:0x1bc39ab0

需要注意的是这里的AlternateLBA和MyLBA和主gpt头正好相反。GPT中提供了校验数据HeaderCRC32和PartitionEntryArrayCRC32用于计算分区表数据是否有错误。这个机制在MBR中是没有的。下面这个图来自UEFI规范

计算机的启动方式有哪些(计算机启动知识系列UEFI/GPT)(2)

这个图非常详细展示了一个磁盘的空间布局,开始是一个保护MBR,后面跟着的是主分区表然后就是各个分区,最后保存了分区表的一个备份。

那么,分区表中是什么样的呢,我们还是使用GPT,GPT的分区表在512字节的扇区保存在LBA2到LBA33中。找到对应的分区表数据

$sudoddif=/dev/sdabs=512count=32skip=2>lba.2-34$catlba.2-34|print_gpt_partition_entry_array<<<GPTPartitionEntry#0>>>#0.PartitionTypeGUID:0x28732ac11ff8d211ba4b00a0c93ec93b#0.PartitionTypeGUID(syn):c12a7328-f81f-11d2-ba4b-00a0c93ec93b#0.PartitionType(syn):EFISystemPartition#0.UniquePartitionGUID:0xa724ee6de04f6f46b6f8546e2048aceb#0.UniquePartitionGUID(syn):6dee24a7-4fe0-466f-b6f8-546e2048aceb#0.StartingLBA:2048#0.EndingLBA:1050623#0.Attributes:0x0#0.Attributes(syn):[]#0.PartitionName:0x4500460049002000530079007300740065006d00200050006100720074006900740069006f006e000000000000000000000000000000000000000000000000000000000000000000#0.PartitionName(syn):EFISystemPartition<<<GPTPartitionEntry#1>>>#1.PartitionTypeGUID:0xaf3dc60f838472478e793d69d8477de4#1.PartitionTypeGUID(syn):0fc63daf-8483-4772-8e79-3d69d8477de4#1.PartitionType(syn):Linuxfilesystemdata#1.UniquePartitionGUID:0xc070b4b9e4c6b94ba06df0ed5791f322#1.UniquePartitionGUID(syn):b9b470c0-c6e4-4bb9-a06d-f0ed5791f322#1.StartingLBA:1050624#1.EndingLBA:104855551#1.Attributes:0x0#1.Attributes(syn):[]#1.PartitionName:0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#1.PartitionName(syn):<<<Calculated>>>PartitionEntryArrayCRC32(calculated):0x1bc39ab0

这里显示了2个有效的分区数据,其中第一分区

  • 开始于LBA2048,结束于1050623扇区

  • 由于PartitionTypeGUID的值为c12a7328-f81f-11d2-ba4b-00a0c93ec93b它是一个EFI系统分区

第二个分区

  • 开始于LBA1050624,结束于104855551

  • 它是一个普通的数据分区

这两个分区显示的和fdisk显示的是一致的。需要注意的是数据分区开始于2048,而不是34,这说明中间还有一块没有使用的间隙。在GPT规范中有一段描述说明了这个原因:"avoidtheneedtodeterminethephysicalblocksizeandtheoptim altransferlengthgranularity,softwaremayalignGPTpartitionsatsignificantlylargerboundaries.Forexample,assuminglogicalblock0isaligned,itmayuseLBAsthataremultiplesof2,048toalignto1,048,576byte(1MiB)boundaries,whichsupportsmostcommonphysicalblocksizesandRAIDstripesizes."

UEFI

UEFI通常有一个固件策略引擎,它可以通过efibootmgr进行配置,而且UEFI还支持安全启动,这里不会介绍关于安全的。使用efibootmgr来配置启动项,也可以在UEFI的GUI中配置,每个厂商进入UEFI配置界面的方式也不一样。

efibootmgr

我们可以使用efibootmgr-v查看引导顺序

$sudoefibootmgr-vBootCurrent:0005Timeout:0secondsBootOrder:0005,0000,0001,0002,0003,0004Boot0000*UiAppFvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)Boot0001*UEFIVBOXCD-ROMVB0-01f003f6PciRoot(0x0)/Pci(0x1,0x1)/Ata(0,0,0)N.....YM....R,Y.Boot0002*UEFIVBOXCD-ROMVB2-01700376PciRoot(0x0)/Pci(0x1,0x1)/Ata(1,0,0)N.....YM....R,Y.Boot0003*UEFIVBOXHARDDISKVBf5cb0757-31383519PciRoot(0x0)/Pci(0xd,0x0)/Sata(0,65535,0)N.....YM....R,Y.Boot0004*EFIInternalShellFvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)Boot0005*ubuntuHD(1,GPT,6dee24a7-4fe0-466f-b6f8-546e2048aceb,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)

这个显示默认从编号0005进行引导(BootCurrent:0005),而Boot0005对应的是Boot0005*ubuntuHD(1,GPT,6dee24a7-4fe0-466f-b6f8-546e2048aceb,0x800,0x100000)/File(\EFI\ubuntu\shimx64.efi)

这里我们不会详细的介绍EFI对Linux的操作系统的引导,后面会有一个详细的介绍UEFI在linux引导中的使用。

总结

通过这篇文章我们了解EFI的工作机制,它使用一个固件策略引擎来根据配置来初始化计算机,引导操作系统启动,它通常和GPT分区一起使用,虽然BIOS也支持GPT中启动,我们这里不关心这种场景。这个章节我们也详细了解GPT的分区格式。

发表评论:

最近发表
网站分类
标签列表