U盘安装多个操作系统——理论

Posted by wsxq2 on 2019-03-24
TAGS:  多系统UEFIU盘启动盘

本文最后一次编辑时间:2019-04-16 18:43:53 +0800

本文和U盘安装多个操作系统——实践原为一篇文章,分为预备知识和实际操作,后来发现预备知识过于庞杂,故而分成两篇文章,一为理论,二为实践,本文即为理论。实践部分参见 U盘安装多个操作系统——实践

因为笔者经常安装各种各样的操作系统。所以经常遇到一些关键词语,比如 BIOS,UEFI,MBR,GPT等等,常常感到困惑,趁着这次要制作多启动U盘的机会,便打算将它们一网打尽,全部总结到一篇文章中。

在不断总结,不断学习的过程中,发现真是学无止境,越是深入越是复杂。几乎每一个关键词都有一本书的知识,所以本文只是浅述,且因为自己理解得不够深刻,所以大量引用了别人的表述,尤其是维基百科和Arch wiki,在这里深表感谢。此外对于每个小节,都提供了可供深入学习的参考链接

本文将从 BIOS 和 MBR 开始。期间会大量引用维基百科的内容,如果觉得看着不舒服的可以直接点击引用结尾的链接跳转至维基百科查看

BIOS

简介

  BIOS(Basic Input/Output System的缩写、中文:基本输入输出系统),在IBM PC兼容系统上,是一种业界标准的固件接口。[1]。BIOS这个字眼是在1975年第一次在CP/M操作系统中出现。BIOS是个人计算机启动时加载的第一个软件(实际上自Intel Haswell平台以后,UEFI并不是系统引导时第一个被加载的软件)。

  BIOS用于计算机/PC平台引导时运行系统各部分的自我检测(Power On Self Test),并加载引导程序(IPL)或存储在存储设备(Storage Device)上的操作系统。在MS-DOS等旧式16位操作系统中,DOS及DOS程序通过BIOS提供的BIOS中断调用以控制硬件。现代操作系统会忽略BIOS提供的BIOS中断调用并直接控制硬件。

——引用自 BIOS - 维基百科,自由的百科全书

引导计算机原理

  当计算机的电源打开,BIOS就会由主板上的闪存(flash memory)运行,并将芯片组和存储器子系统初始化。BIOS会把自己从闪存中,解压缩到系统的主存;并且从那边开始运行。PC的BIOS代码也包含诊断功能,以保证某些重要硬件组件,像是键盘、磁盘(BIOS在引导时会侦测硬盘的S.M.A.R.T.状态)、输出输入端口等等,可以正常运作且正确地初始化。几乎所有的BIOS都包含设置程序(BIOS Setup),可以进行BIOS的设置,如设置系统时间,设置引导设备顺序,激活/禁用计算机的某些周边设备。主板的CMOS芯片(UEFI多使用NVRAM存储UEFI设置值/硬件侦测信息)用于存储BIOS设置值及硬件侦测信息。主板上的钮扣电池用于让CMOS芯片存储BIOS设置值,以及计算机在断电时依然可以让系统时钟运作。CMOS在没有电力供应(CMOS所需电力由主板上的钮扣电池提供)的情况下会丢失存储的数据,而NVRAM则不会。

——引用自 BIOS - 维基百科,自由的百科全书

与CMOS的联系和区别

BIOS与CMOS的关系

  CMOS是计算机上另一个重要的存储器。之所以提到它,是因为BIOS程序的设置值、硬件参数侦测值就保存在CMOS中。而且,在BIOS程序引导计算机时,需要加载CMOS中的设置值。CMOS通常被集成在南桥芯片组中。UEFI系统则多用NVRAM存储设置。

BIOS与CMOS的区别

  二者的区别是,BIOS是存储在唯读记忆体(EEPROM),而CMOS为随机存储器(RAM);BIOS中存储的是程序,而CMOS中存储的是普通信息。

  CMOS的内容在断电会消失。所以,把主板的电池拆出,便可重置其内容。另外,拆出电池也会重置时间。UEFI使用NVRAM存储数据,主板电池没有电量会导致时间不正确,可能不会导致UEFI设置值丢失。可通过主板的有关Jumper重置UEFI设置。

——引用自 BIOS - 维基百科,自由的百科全书

MBR

简介

  主引导记录(Master Boot Record,缩写:MBR),又叫做主引导扇区,是计算机开机后访问硬盘时所必须要读取的首个扇区,它在硬盘上的三维地址为(柱面,磁头,扇区)=(0,0,1)。在深入讨论主引导扇区内部结构的时候,有时也将其开头的446字节内容特指为“主引导记录”(MBR),其后是4个16字节的“磁盘分区表”(DPT),以及2字节的结束标志(55AA)。因此,在使用“主引导记录”(MBR)这个术语的时候,需要根据具体情况判断其到底是指整个主引导扇区,还是主引导扇区的前446字节。

  主引导扇区记录着硬盘本身的相关信息以及硬盘各个分区的大小及位置信息,是数据信息的重要入口。如果它受到破坏,硬盘上的基本数据结构信息将会丢失,需要用繁琐的方式试探性的重建数据结构信息后才可能重新访问原先的数据。主引导扇区内的信息可以通过任何一种基于某种操作系统的分区工具软件写入,但和某种操作系统没有特定的关系,即只要创建了有效的主引导记录就可以引导任意一种操作系统(操作系统是创建在高级格式化的硬盘分区之上,是和一定的文件系统相联系的)。

  对于硬盘而言,一个扇区可能的字节数为128×2n(n=0,1,2,3)。大多情况下,取n=2,即一个扇区(sector)的大小为512字节。

——引用自 主引导记录 - 维基百科,自由的百科全书

组成

标准MBR结构
地址 描述 长度
字节
Hex Oct Dec
0000 0000 0 代码区 440
(最大446)
01B8 0670 440 选用磁盘标志 4
01BC 0674 444 一般为空值; 0x0000 2
01BE 0676 446 标准MBR分区表规划
(四个16 byte的主分区表入口)
64
01FE 0776 510 55h MBR有效标志:
0x55AA
2
01FF 0777 511 AAh
MBR,总大小:446 + 64 + 2 = 512

——引用自 主引导记录 - 维基百科,自由的百科全书

其中 16bytes 的主分区表的信息如下:

硬盘分区结构信息
偏移 长度(字节) 意义
00H 1 分区状态:00-->非活动分区;80-->活动分区;
其它数值没有意义
01H 1 分区起始磁头号(HEAD),用到全部8位
02H 2 分区起始扇区号(SECTOR),占据02H的位0-5;
该分区的起始磁柱号(CYLINDER),占据
02H的位6-7和03H的全部8位
04H 1 文件系统标志位
05H 1 分区结束磁头号(HEAD),用到全部8位
06H 2 分区结束扇区号(SECTOR),占据06H的位0-5;
该分区的结束磁柱号(CYLINDER),占据
06H的位6-7和07H的全部8位
08H 4 分区起始相对扇区号
0CH 4 分区总的扇区数

——引用自 主引导记录 - 维基百科,自由的百科全书

可以通过 Linux 下的file命令获取 MBR (第一个扇区)的分区信息:

1
2
3
4
5
root@master:_posts# ls -sh temp.img
512 temp.img
root@master:_posts# file temp.img
temp.img: x86 boot sector; partition 1: ID=0x83, active, starthead 32, startsector 2048, 2097152 sectors; partition 2: ID=0x83, starthead 170, startsector 2099200, 60813312 sectors; partition 3: ID=0x82, starthead 254, startsector 62912512, 4196352 sectors, code offset 0x63
root@master:_posts#

硬盘驱动器物理寻址“柱面-磁头-扇区(英语:Cylinder-head-sector,简称为CHS)”法: 先找到磁头位置(因为磁头决定一个盘面)->再找到柱面(磁道)->最后找到扇区(即一条磁道上的一段圆弧)

主引导扇区的读取流程

  • 系统开机或者重启。
    1. BIOS加电(台湾用语:引导)自检(Power On Self Test – POST)。BIOS执行内存地址为FFFF:0000H处的跳转指令,跳转到固化在ROM中的自检程序处,对系统硬件(包括内存)进行检查。
    2. 读取主引导记录(MBR)。当BIOS检查到硬件正常并与CMOS中的设置相符后,按照CMOS中对启动设备的设置顺序检测可用的启动设备。BIOS将相应启动设备的第一个扇区(也就是MBR扇区)读入内存地址为0000:7C00H处。
    3. 检查0000:7DFEH-0000:7DFFH(MBR的结束标志位)是否等于55AAH,若不等于则转去尝试其他启动设备,如果没有启动设备满足要求则显示”NO ROM BASIC”然后死机。
    4. 当检测到有启动设备满足要求后,BIOS将控制权交给相应启动设备。启动设备的MBR将自己复制到0000:0600H处,然后继续执行。
    5. 根据MBR中的引导代码启动引导程序。
  • 事实上,BIOS不仅检查0000:7DFEH-0000:7DFFH(MBR的结束标志位)是否等于55AAH,往往还对磁盘是否有写保护、主引导扇区中是否存在活动分区等进行检查。如果发现磁盘有写保护,则显示磁盘写保护出错信息;如果发现磁盘中不存在活动分区,则显示类似如下的信息“Remove disk or other media Press any key to restart”。

——引用自 主引导记录 - 维基百科,自由的百科全书

UEFI

简介

  统一可扩展固件接口(英语:Unified Extensible Firmware Interface,缩写UEFI)是一种个人计算机系统规格,用来定义操作系统与系统固件之间的软件界面,作为BIOS的替代方案[1]。可扩展固件接口负责加电自检(POST)、联系操作系统以及提供连接操作系统与硬件的接口。

  UEFI的前身是Intel在1998年开始开发的Intel Boot Initiative,后来被重命名为可扩展固件接口(Extensible Firmware Interface,缩写EFI)。Intel在2005年将其交由统一可扩展固件接口论坛(Unified EFI Forum)来推广与发展,为了凸显这一点,EFI也更名为UEFI(Unified EFI)。UEFI论坛的创始者是11家知名计算机公司,包括Intel、IBM等硬件厂商,软件厂商Microsoft,及BIOS厂商AMI、Insyde及Phoenix。

——引用自 统一可扩展固件接口 - 维基百科,自由的百科全书

UEFI 的产生

  EFI最早是Intel为Intel Itanium处理器设计的固件规范。自从IBM PC兼容机厂商(如COMPAQ)和BIOS提供商(如Phoenix)通过净室的方式复制出第一套BIOS源程序,BIOS就以16位汇编代码,寄存器参数调用方式,静态链接,以及1MB以下内存固定编址的形式存在十几年。虽然由于各大BIOS厂商近年来的努力,有许多新元素添加到产品中,如PnP BIOS、ACPI、USB等等,但BIOS的根本性质没有得到任何改变。虽然x86处理器已经由16位先后升级到32位、64位(x86-64),但是BIOS仍然以16位实模式运行。基于16位实模式的BIOS具有许多缺点,如扩展性差,系统引导缓慢,开发困难,用户界面不友好等。

  英特尔将EFI定义为一个可扩展的,标准化的固件接口规范,不同于开发困难,缺乏文件的传统BIOS。2005年,英特尔等公司成立统一可扩展固件接口论坛,EFI也更名为UEFI。2011年,UEFI已经在x86平台上得到普及。

——引用自 统一可扩展固件接口 - 维基百科,自由的百科全书

UEFI vs BIOS

  二者显著的区别就是UEFI是模块化、规范化的,大部分代码使用C语言编写,较BIOS而言更易于实现,容错和纠错特性更强,缩短了系统研发的时间。它可以运行于x86-64、ARM等架构上(在现在的x86计算机/x86服务器上通常是x86-64),直接以64位模式运行,突破传统16位实模式只能寻址1MB内存的限制。UEFI使用EFI驱动程序(EFI Driver)的形式,识别及操作硬件,不同于BIOS使用实模式中断调用的方式操作硬件。UEFI使用EFI驱动程序的形式扩展UEFI固件的功能(如显卡、RAID卡等),BIOS使用加载16位Option ROM的方式扩展功能,由于BIOS最多只能寻址1MB内存,所以BIOS的扩展性有限。另外,BIOS的中断调用服务程序都以16位实模式代码的形式存在,这就给运行于保护模式/长模式的操作系统访问其服务造成了困难。因此BIOS提供的实模式服务(如BIOS中断调用)在现实中只能提供给操作系统引导程序或MS-DOS类操作系统使用。UEFI系统下的EFI驱动程序可以由EFI Byte Code(EBC)编写而成,EFI Byte Code是一组专用于EFI驱动程序的虚拟机器语言,必须在EFI驱动程序运行环境(Driver Execution Environment,或DXE)下被解释运行。采用EBC编写的EFI驱动程序拥有平台无关性,打个比方说,一个带有EBC EFI驱动程序的PCIe设备,既可以将其安装于采用x64 UEFI固件的服务器中,也可以将其安装到采用UEFI固件的ARM系统中,而它的EFI驱动程序不需要重新编写。基于UEFI的固件,在操作系统运行以前浏览万维网站,实现图形化、多语言的BIOS设置界面,或者无需运行操作系统即可在线更新BIOS等等不再是天方夜谭,实现起来远比BIOS简单。这对基于传统BIOS的系统来说是件难以实现的任务,在BIOS中添加几个简单的USB设备支持都曾使很多BIOS设计师痛苦万分,更何况除了添加对无数网络硬件的支持外,还得凭空构建一个16位模式下的TCP/IP协议栈。

  BIOS多使用CMOS保存BIOS设置值与硬件侦测数据,CMOS保存数据需要电力供应,如果主板上的CMOS电池已没有电量,那么在计算机断电后,CMOS中存储的数据会丢失,且系统时钟会被重置。UEFI多采用NVRAM存储固件设置及硬件侦测数据。

  一些人认为BIOS只不过是由于兼容性问题遗留下来的无足轻重的部分,不值得为它花费太大的升级努力。而反对者认为,当BIOS的出现约制了PC技术的发展时,必须有人对它作必要的改变。

——引用自 统一可扩展固件接口 - 维基百科,自由的百科全书

系统分类

  • 类别0,这类系统使用x86 BIOS固件,只支持传统操作系统。
  • 类别1,这类系统采用支持UEFI和Pi规范的固件,激活CSM层功能,只支持传统操作系统。
  • 类别2,这类系统采用支持UEFI和Pi规范的固件,激活CSM层功能,同时支持传统和UEFI引导的操作系统。
  • 类别3,这类系统采用支持UEFI和Pi规范的固件,不再提供或完全关闭CSM层功能,只支持由UEFI引导的操作系统。
  • 类别3+,在类别3的系统基础上提供并激活Secure Boot功能。

  微软公司的Windows 8及之后的操作系统适用于上述所有类别的计算机,之前支持UEFI固件的操作系统适用于类别0至类别2型计算机,不支持UEFI固件的操作系统仅可用于类别0和类别1的计算机。所有支持UEFI引导的Linux操作系统适用于类别0至类别3型计算机,多数现行分发版也支持类别3+中的Secure Boot功能,譬如Ubuntu等。 Intel计划将于2020年推出的UEFI Class 3规范中,将Legacy BIOS界面完全舍弃,Intel旗下的所有产品将使用UEFI Class 3(有一部分产品可能是3+)[4]。

——引用自 统一可扩展固件接口 - 维基百科,自由的百科全书

引导原理

与 BIOS 不同, UEFI 不依赖于引导扇区(MBR),而是将引导管理器定义为 UEFI 规范的一部分。当计算机启动时,引导管理器会检查启动配置并根据其设置加载到内存中,然后执行指定的OS loaderOS kernel。引导配置由存储在 NVRAM 中的变量定义,包括指示OS loaderOS kernel的文件系统路径的变量。

UEFI 可以自动检测OS loader,从而可以从 USB 闪存驱动器等可移动设备轻松启动。这种自动检测依赖于到OS loader的标准化文件路径,路径根据计算机体系结构而变化。文件路径的格式定义为<EFI_SYSTEM_PARTITION>\EFI\BOOT\BOOT<MACHINE_TYPE_SHORT_NAME>.EFI; 例如,对于x86-64的系统而言,到OS loader的文件路径是ESP\EFI\BOOT\BOOTX64.EFI,而对于 ARM64 架构而言,相应的路径则为esp\efi\boot\bootaa64.efi(注意:EFI系统分区的文件系统通常为FAT32FAT16,对于这两种文件系统而言,其文件夹名和文件名不区分大小写,详情参见 Comparison of file systems - Wikipedia

总之,对于 UEFI 而言,启动时分为两种情况:

  1. 从指定磁盘启动。在用户选择了启动磁盘后,UEFI 会在这个磁盘中寻找 EFI 分区(通常 label 为ESP),然后找这个分区下的/EFI/Boot/bootx64.efi,由这个文件进行下一步操作(引导操作系统)。这个文件通常由操作系统给出,在光盘/EFI/BOOT目录下
  2. 从已经创建的启动项启动。这个启动项记录了引导文件(*.efi)所在的磁盘和分区以及文件路径,直接执行这个 efi 文件即可开始进行下一步操作(引导操作系统)

可通过启动菜单验证。对于联想笔记本,启动时按住F12出现启动菜单。详情参考 UEFI启动分析 UEFI设置启动项 - 简书

EFI 文件说明

efi 文件即以*.efi格式命名的文件,它是 UEFI 下的可执行文件(可类比 Windows 中的 exe 文件)。通过在 EFI Shell 中使用命令lsdir,你会发现 efi 文件是唯一绿色的文件(即说明其确实为可执行文件)。*.efi文件有很多用处。比如用于启动 EFI Shell、用于引导操作系统、用于加载驱动程序等等。

ESP\EFI\BOOT\BOOTX64.EFI是该分区所在磁盘的默认的引导文件, 其中ESP代表的是 UEFI 中的启动分区(通常文件系统为FAT32FAT16,LABEL 为 ESP,因而常常使用ESP来表示它),\EFI\BOOT\BOOTX64.EFI则为默认的启动加载器路径。比如对于 64 位的系统(近几年生产的个人计算机大多都是 64 位,32位已经近乎淘汰),你可以从edk2/ShellBinPkg/UefiShell/X64 at master · tianocore/edk2下载一个后文所述的 UEFI Shell(通常文件名为shell.efi),然后将其更名为bootx64.efi,放置于esp\efi\boot\目录中,那么下次从 ESP 分区所在的磁盘启动时就会启动到你下载的 UEFI Shell 中。与此类似,如果你将后文所述的 rEFInd 下载并更名且放置到相应位置后再从相应磁盘启动将会启动到 rEFInd 管理器。

对于我们常用的 Windows10 系统,也有一个用于启动 Windows10 系统的 efi 文件bootmgfw.efi,它的标准路径是esp\efi\microsoft\boot\bootmgfw.efi,该文件只能用于启动 Windows。当然,如果你希望对于某个磁盘,默认启动的操作系统就是 Windows,那么你可以像上文所述的那样将bootmgfw.efi复制到esp\efi\boot\目录中,并重命名为bootx64.efi

与此类似,Linux 系统中也有个常用的用于 Linux 系统的 efi 文件grubx64.efi,它的标准路径是esp\efi\Ubuntu\grubx64.efi(以 Ubuntu 为例)。此外,在esp\efi\Ubuntu目录下通常还会有一个shimx64.efi文件,该文件和Secure Boot相关,它提供了一种可以在不关闭Secure Boot的情况下启动 Ubuntu 的方法,更多内容参见 dual boot - What is the difference between grubx64 and shimx64? - Ask Ubuntu

对于 UEFI,还有一个不得不讲解的东东,那就是 UEFI Shell。下面将简要介绍一下 UEFI Shell

UEFI Shell

以下内容主要参考 Unified Extensible Firmware Interface (简体中文) - ArchWiki

UEFI Shell 是固件的终端,可用于启动包括引导器的 UEFI 程序。除此之外, Shell也可用于采集固件和系统的各种信息,例如内存映射 (memmap), 修改启动管理器变量 (bcfg), 运行分区程序 (diskpart), 加载 UEFI 驱动,编辑文本文件 (edit), 十六进制编辑等等。

获取 UEFI Shell

官方最新版:edk2/ShellBinPkg/UefiShell/X64 at master · tianocore/edk2

启动 UEFI Shell

3个方法:

  1. 固件内嵌。Phoenix SecureCore Tiano UEFI 固件已内嵌 UEFI Shell, 可按F6,F11F12键来启动。
  2. 主板支持。部分基于 AMI Aptio x86_64 UEFI 固件的主板 (从 Sandy Bridge 起,尤其是华硕) 提供了一个叫做 “Launch EFI Shell from filesystem device” 的选项。对于这些主板,下载 x86_64 UEFI Shell ,复制进某个磁盘的 EFI 系统分区,命名为<EFI_SYSTEM_PARTITION>/shellx64.efi(对于 Linux 而言,相应的文件路径通常是/boot/efi/shellx64.efi,因为 EFI 分区通常挂载在/boot/efi目录下).
  3. 手动启动。创建一个FAT32格式的 USB 并把Shell.efi复制到(USB)/efi/boot/bootx64.efi. 这个 USB 会出现在固件的启动菜单里。启动它就会启动到 UEFI Shell.

重要的 UEFI Shell 命令

UEFI Shell 命令通常支持-b选项,它在输出的每页末尾暂停. 运行help -b来列出所有可用命令。

更多信息参见 Intel 技术文章-EFI Shells and ScriptingUEFI_Shell_Spec_2_0.pdf

help

查看命令的使用帮助

1
2
3
help -b
help bcfg -b
help map
bcfg

bcfg 命令用于修改 UEFI NVRAM 条目,它能让用户改变启动条目或驱动器选项。在UEFI_Shell_Spec_2_0.pdf PDF 文档的 83 页(Section 5.3) 有详细说明。

注意:

  • 仅当efibootmgr无法创建启动条目时才推荐尝试bcfg.
  • UEFI Shell v1 官方二进制文件不支持bcfg命令。你可以下载一个modified UEFI Shell v2 二进制文件,它在 UEFI 2.3前的固件有效。

例子:

  1. 输出当前启动条目:
    1
    
    Shell> bcfg boot dump -v
    
  2. rEFInd(作为例子) 添加一个启动菜单条目,在启动菜单里是第4个 (从0开始计数) 选项:
    1
    
    Shell> bcfg boot add 3 fs0:\EFI\refind\refind_x64.efi "rEFInd"
    

    fs0:映射到 EFI 系统分区,fs0:\EFI\refind\refind_x64.efi是要启动的文件。

  3. To add an entry to boot directly into your system without a bootloader, configure a boot option using your kernel as an EFISTUB:
    1
    2
    
    Shell> bcfg boot add N fsV:\vmlinuz-linux "Arch Linux"
    Shell> bcfg boot -opt N "root=/dev/sdX# initrd=\initramfs-linux.img"
    

    where N is the priority, V is the volume number of your EFI partition, and /dev/sdX# is your root partition.

  4. 删除第4个启动选项:
    1
    
    Shell> bcfg boot rm 3
    
  5. 把第3个启动选项移动到第0 (也就是说第1个是 UEFI 启动菜单的默认启动选项):
    1
    
    Shell> bcfg boot mv 3 0
    
  6. bcfg 帮助文档:
    1
    
    Shell> help bcfg -v -b
    

    或:

    1
    
    Shell> bcfg -? -v -b
    
map

map displays a list of device mappings i.e. the names of available file systems (fs0) and storage devices (blk0).

Before running file system commands such as cd or ls, you need to change the shell to the appropriate file system by typing its name:

1
2
3
Shell> map
Shell> fs0:
fs0:\> cd EFI/
edit

EDIT命令提供了类似于nano界面的基本编辑器,但是功能略少一点。它以UTF-8编码并且行尾结束符兼容LFCRLF.

本例中,编辑在固件 EFI 系统分区 (fs0:中 rEFInd 的refind.conf

1
Shell> edit FS0:\EFI\refind\refind.conf

输入Ctrl-E以获得帮助。

UEFI启动顺序编辑

进入BIOS设置以编辑

注意此处的BIOS和前述的略有不同,这里指的是每个电脑的基本设置界面。

几乎每个电脑的 BIOS 设置都支持编辑 EFI 启动顺序,甚至有的还支持手动添加 EFI 启动条目、删除 EFI 启动条目等等。在我的联想笔记本中,通过按 F2键进入BIOS设置界面,然后在BOOT版块中按F5(F6)升高(降低)启动顺序。

UEFI Shell bcfg

在UEFI Shell 中可以使用bcfg命令进行启动顺序的编辑。详情参见上一节中的 bcfg

Windows

bootice

bootice是Windows下极好的用于EFI启动管理的工具(有图形界面),缺点在于好久没有更新了,但是依然能用。强烈推荐。建议在 PE 环境中运行(因为在 Windows10 系统本身中运行有时会保存设置失败)

  1. 下载:2019-03-29 时谷歌到的最新版是 2016-06-17 发行的 1.3.4.0 版本,下载地址为: bootice 1.3.4.0下载链接-百度云分享。提取码: raax
  2. 用法:打开BOOTICEx64.exe,点击UEFI,点击修改启动序列,剩下的很简单,自己捣鼓吧^_^
bcdboot

Windows 官方的命令行工具,Bcd 启动文件创建和修复工具。通过bcdedit /?查看帮助。使用起来比较简单:

1
bcdboot c:\windows /v
bcdedit

这一部分主要参考了官方帮助文档:Adding Boot Entries - Windows drivers | Microsoft Docs

该命令并不仅仅用于EFI启动管理,它主要用于 Windows 启动管理,所以使用起来比较复杂,不建议使用。好在它的帮助文档相当全,使用bcdedit /?查看命令使用帮助

注意:以管理员身份运行 Powershell 或 CMD,否则会提示拒绝访问

  1. 备份与恢复当前系统BCD
    1
    2
    
    bcdedit /export d:\backup.bcd
    bcdedit /import d:\backup.bcd
    

    简要解释一下:第一个命令是用来导出当前系统BCD到D:\backup.bcd的;而第二个命令相反,用来将D:\backup.bcd中的数据导入到系统中并覆盖系统BCD。这两个用法非常重要,因为你一不小心就会把系统搞得启动不了了,所以把它放在了最前面。做好备份工作总是好的

  2. 显示已有的EFI启动条目
    1
    2
    3
    4
    5
    6
    7
    
    bcdedit
    bcdedit /enum /?
    bcdedit /enum all
    bcdedit /enum firmware
    bcdedit /enum '{fwbootmgr}'
    bcdedit /enum bootmgr
    bcdedit /enum osloader
    

    其中,firmware显示 NVRAM(保存EFI启动信息的存储器)中保存的所有EFI启动信息;bootmgr是Windows 启动管理器,后面新建EFI启动条目的时候就是复制的它;osloader是 Windows 启动加载器,默认只有两个,一个是 Windows10 本身,另一个是 WinRE。

  3. 添加新的EFI启动条目
    1
    
    bcdedit /copy "{bootmgr}" /d "DebugEntry"
    

    注意这里的{bootmgr}不建议换成其它的。我本来想使用/create参数创建新的EFI启动条目,但始终没有成功

  4. 设置已有的EFI启动条目
    1. 最常用设置
      1
      2
      3
      4
      
      bcdedit /set "{newid}" path \EFI\refind\refind_x64.efi
      bcdedit /set "{newid}" description "rEFInd description"
      bcdedit /displayorder {current} {49916baf-0e08-11db-9af4-000bdbd316a0}
      bcdedit /displayorder {49916baf-0e08-11db-9af4-000bdbd316a0} /addlast
      

      其中{newid}是新建的启动条目的标识符,在这里建议使用新建的练手,不要随便改已有的。

    2. 修改默认启动条目
      1
      
      bcdedit /default {cbd971bf-b7b8-4885-951a-fa03044f5d71}
      
    3. 修改 timeout
      1
      
      bcdedit /timeout 15
      

      对于这个 timeout,我不知道有什么用。但是看起来很重要的样子

    4. 修改启动参数
      1
      2
      
      bcdedit /set {802d5e32-0784-11da-bd33-000476eba25f} pae forceenable
      bcdedit /debug {49916baf-0e08-11db-9af4-000bdbd316a0} on
      

      这一块的内容也相当丰富,可查看帮助文档bcdedit /? /set

  5. 删除已有的EFI启动条目
    1
    2
    
    bcdedit /displayorder {49916baf-0e08-11db-9af4-000bdbd316a0} /remove
    bcdedit /delete {49916baf-0e08-11db-9af4-000bdbd316a0}
    

Linux efibootmgr

相比于 Windows,Linux下的 efibootmgr 工具就简单得多了,因为它目标明确,只做好一件事——UEFI启动管理。使用efibootmgr --helpman efibootmgr查看帮助。尤其是man efibootmgr后面的 EXAMPLES 示例,通俗易懂。下面我将做一个无名的搬运工

  1. 显示当前的EFI启动条目

    [root@localhost ~]# efibootmgr
    BootCurrent: 0004
    BootNext: 0003
    BootOrder: 0004,0000,0001,0002,0003
    Timeout: 30 seconds
    Boot0000* Diskette Drive(device:0)
    Boot0001* CD-ROM Drive(device:FF)
    Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233)
    Boot0003* PXE Boot: MAC(00D0B7C15D91)
    Boot0004* Linux
    
  2. 创建新的启动选项
    1
    
    efibootmgr -c
    

    该命令假设/boot/efi是你的 EFI 系统分区,且挂载在/dev/sda1。执行后它会创建一个新的启动选项,名为”Linux”,并且会将它放在启动顺序列表的第一位,且默认的 OS Loader 是elilo.efi。可以通过传入 Options 修改默认行为。

  3. 改变启动顺序
    1
    
    efibootmgr -o 3,4
    

    该命令指定 PXE Boot 为第一启动选项,Linux 为第二启动选项

  4. 只改变下一次启动的启动顺序
    1
    
    efibootmgr -n 4
    
  5. 删除一个启动选项
    1
    
    efibootmgr -b 4 -B
    
  6. 启用/禁用启动项
    1
    2
    
    efibootmgr -a -b X # 启用标号为X的启动项
    efibootmgr -A -b X # 禁用标号为X的启动项
    

GPT

简介

  全局唯一标识分区表(GUID Partition Table,缩写:GPT)是一个实体硬盘的分区表的结构布局的标准。它是可扩展固件接口(EFI)标准(被Intel用于替代个人计算机的BIOS)的一部分,被用于替代BIOS系统中的一32bits来存储逻辑块地址和大小信息的主引导记录(MBR)分区表。对于那些扇区为512字节的磁盘,MBR分区表不支持容量大于2.2TB(2.2×1012字节)[1]的分区,然而,一些硬盘制造商(诸如希捷和西部数据)注意到这个局限性,并且将他们的容量较大的磁盘升级到4KB的扇区,这意味着MBR的有效容量上限提升到16 TiB。 这个看似“正确的”解决方案,在临时地降低人们对改进磁盘分配表的需求的同时,也给市场带来关于在有较大的块(block)的设备上从BIOS启动时,如何最佳的划分磁盘分区的困惑。GPT分配64bits给逻辑块地址,因而使得最大分区大小在264-1个扇区成为可能。对于每个扇区大小为512字节的磁盘,那意味着可以有9.4ZB(9.4×1021字节)或8 ZiB个512字节(9,444,732,965,739,290,426,880字节或18,446,744,073,709,551,615(264-1)个扇区×512(29)字节每扇区)。

  截止至2010年,大多数操作系统对GPT均有所支持,尽管包括Mac OS X和Windows在内的一些仅支持在EFI基础上自GPT分区启动,见#操作系统支持。

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

特点

  在MBR硬盘中,分区信息直接存储于主引导记录(MBR)中(主引导记录中还存储着系统的引导程序)。但在GPT硬盘中,分区表的位置信息储存在GPT头中。但出于兼容性考虑,硬盘的第一个扇区仍然用作MBR,之后才是GPT头。

  跟现代的MBR一样,GPT也使用逻辑区块地址(LBA)取代了早期的CHS寻址方式。传统MBR信息存储于LBA 0,GPT头存储于LBA 1,接下来才是分区表本身。64位Windows操作系统使用16,384字节(或32扇区)作为GPT分区表,接下来的LBA 34是硬盘上第一个分区的开始。

  苹果公司曾经警告说:[3]“不要假定所有设备的块大小都是512字节。”一些现代的存储设备如固态硬盘可能使用1024字节的块,一些磁光盘(MO)可能使用2048字节的扇区(但是磁光盘通常是不进行分区的)。一些硬盘生产商在计划生产4096字节一个扇区的硬盘,但截至2010年初,这种新硬盘使用固件对操作系统伪装成512字节一个扇区。[4]

  使用英特尔架构的苹果机也使用GPT。

  为了减少分区表损坏的风险,GPT在硬盘最后保存了一份分区表的副本。

GUID_Partition_Table_Scheme.svg

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

传统MBR (LBA 0)

  在GPT分区表的最开头,出于兼容性考虑仍然存储了一份传统的MBR,用来防止不支持GPT的硬盘管理工具错误识别并破坏硬盘中的数据,这个MBR也叫做保护MBR。在支持从GPT启动的操作系统中,这里也用于存储第一阶段的启动代码。在这个MBR中,只有一个标识为0xEE的分区,以此来表示这块硬盘使用GPT分区表。不能识别GPT硬盘的操作系统通常会识别出一个未知类型的分区,并且拒绝对硬盘进行操作,除非用户特别要求删除这个分区。这就避免了意外删除分区的危险。另外,能够识别GPT分区表的操作系统会检查保护MBR中的分区表,如果分区类型不是0xEE或者MBR分区表中有多个项,也会拒绝对硬盘进行操作。

  在使用MBR/GPT混合分区表的硬盘中,这部分存储了GPT分区表的一部分分区(通常是前四个分区),可以使不支持从GPT启动的操作系统从这个MBR启动,启动后只能操作MBR分区表中的分区。如Boot Camp就是使用这种方式启动Windows。

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

分区表头(LBA 1)

  分区表头定义了硬盘的可用空间以及组成分区表的项的大小和数量。在使用64位Windows Server 2003的机器上,最多可以创建128个分区,即分区表中保留了128个项,其中每个都是128字节。(EFI标准要求分区表最小要有16,384字节,即128个分区项的大小)

  分区表头还记录了这块硬盘的GUID,记录了分区表头本身的位置和大小(位置总是在LBA 1)以及备份分区表头和分区表的位置和大小(在硬盘的最后)。它还储存着它本身和分区表的CRC32校验。固件、引导程序和操作系统在启动时可以根据这个校验值来判断分区表是否出错,如果出错了,可以使用软件从硬盘最后的备份GPT中恢复整个分区表,如果备份GPT也校验错误,硬盘将不可使用。所以GPT硬盘的分区表不可以直接使用16进制编辑器修改。

分区表头的格式
起始字节 长度 内容
0 8字节 签名("EFI PART", 45 46 49 20 50 41 52 54)
8 4字节 修订(在1.0版中,值是00 00 01 00)
12 4字节 分区表头的大小(单位是字节,通常是92字节,即5C 00 00 00)
16 4字节 分区表头(第0-91字节)的CRC32校验,在计算时,把这个字段作为0处理,需要计算出分区序列的CRC32校验后再计算本字段
20 4字节 保留,必须是0
24 8字节 当前LBA(这个分区表头的位置)
32 8字节 备份LBA(另一个分区表头的位置)
40 8字节 第一个可用于分区的LBA(主分区表的最后一个LBA + 1)
48 8字节 最后一个可用于分区的LBA(备份分区表的第一个LBA − 1)
56 16字节 硬盘GUID(在类UNIX系统中也叫UUID
72 8字节 分区表项的起始LBA(在主分区表中是2)
80 4字节 分区表项的数量
84 4字节 一个分区表项的大小(通常是128)
88 4字节 分区序列的CRC32校验
92 * 保留,剩余的字节必须是0(对于512字节LBA的硬盘即是420个字节)

  主分区表和备份分区表的头分别位于硬盘的第二个扇区(LBA 1)以及硬盘的最后一个扇区。备份分区表头中的信息是关于备份分区表的。

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

分区表项(LBA 2–33)

  GPT分区表使用简单而直接的方式表示分区。一个分区表项的前16字节是分区类型GUID。例如,EFI系统分区的GUID类型是{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}。接下来的16字节是该分区唯一的GUID(这个GUID指的是该分区本身,而之前的GUID指的是该分区的类型)。再接下来是分区起始和末尾的64位LBA编号,以及分区的名字和属性。

GPT分区表项的格式
起始字节 长度 内容
0 16字节 分区类型GUID
16 16字节 分区GUID
32 8字节 起始LBA(小端序
40 8字节 末尾LBA
48 8字节 属性标签(如:60表示“只读”)
56 72字节 分区名(可以包括36个UTF-16(小端序)字符)

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

分区类型GUID

相关操作系统 分区类型 GUID[1]
(None) 未使用 00000000-0000-0000-0000-000000000000
MBR分区表 024DEE41-33E7-11D3-9D69-0008C781F39F
EFI系统分区 C12A7328-F81F-11D2-BA4B-00A0C93EC93B
BIOS引导分区 21686148-6449-6E6F-744E-656564454649
Windows 微软保留分区 E3C9E316-0B5C-4DB8-817D-F92DF00215AE
基本数据分区[2] EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
逻辑软盘管理工具元数据分区 5808C8AA-7E8F-42E0-85D2-E1E90434CFB3
逻辑软盘管理工具数据分区 AF9B60A0-1431-4F62-BC68-3311714A69AD
Windows恢复环境 DE94BBA4-06D1-4D40-A16A-BFD50179D6AC
IBM通用并行文件系统(GPFS)分区 37AFFC90-EF7D-4e96-91C3-2D7AE055B174
Linux 数据分区[2] EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
RAID分区 A19D880F-05FC-4D3B-A006-743F0F84911E
交换分区 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
逻辑卷管理员(LVM)分区 E6D6D379-F507-44C2-A23C-238F2A3DF928
保留 8DA63339-0007-60C0-C436-083AC8230908
Mac OS X HFS(HFS+)分区 48465300-0000-11AA-AA11-00306543ECAC
苹果公司UFS 55465300-0000-11AA-AA11-00306543ECAC
ZFS[3] 6A898CC3-1DD2-11B2-99A6-080020736631
苹果RAID分区 52414944-0000-11AA-AA11-00306543ECAC
苹果RAID分区,下线 52414944-5F4F-11AA-AA11-00306543ECAC
苹果启动分区 426F6F74-0000-11AA-AA11-00306543ECAC
Apple Label 4C616265-6C00-11AA-AA11-00306543ECAC
Apple TV恢复分区 5265636F-7665-11AA-AA11-00306543ECAC
  1. ^ 本表中的GUID使用小端序表示。例如,EFI系统分区的GUID在这里写成C12A7328-F81F-11D2-BA4B-00A0C93EC93B但实际上它对应的16字节的序列是28 73 2A C1 1F F8 D2 11 BA 4B 00 A0 C9 3E C9 3B——只有前3部分的字节序被交换了。
  2. a b Linux和Windows的数据分区使用相同的GUID。
  3. a b Solaris系统中/usr分区的GUID在Mac OS X上被用作普通的ZFS分区。
  4. ^ 具体定义见src/sys/sys/disklabel_gpt.h。NetBSD的GUID在单独定义之前曾经使用过FreeBSD的GUID。

——引用自 全局唯一标识分区表 - 维基百科,自由的百科全书

rEFInd

简介

rEFInd是一个精致的启动菜单和维护工具包,适用于基于UEFI的计算机,如Windows 8+ PC和Intel Mac。它可用于引导安装在单个非易失性设备上的多个操作系统。它还提供了一种使用交互式shell进入和探索EFI预引导环境的方法,例如shellx64_v2.efi

rEFInd是现已废弃的rEFIt的活动分支,是TrueOS的默认统一可扩展固件接口(EFI)启动管理器。

GNU efi适合在C语言中编写二进制efi应用程序,以便从rEFIndGUI菜单启动。EFI应用程序的典型用途是修复引导问题并以编程方式修改设置,否则这些设置将在个人计算机(PC)的固件BIOS中修改。

其官方网站为:The rEFInd Boot Manager。本文的相关内容均参考官方网站

特点

rEFInd 是 rEFIt 启动管理器的一个分支。因此,它与 rEFIt 有许多共同特征。它的主要特点有:

  • 支持文本模式和图形操作。
  • 用户可配置的图形和图标 - 您可以设置自己的背景,设置新图标等。
  • 启动外部 EFI shell 或磁盘分区程序的选项。
  • 为固件本身不支持的文件系统或硬件设备加载 EFI 驱动程序。
  • 用户可配置的检测引导加载程序的方法:
    • 自动检测 EFI 引导加载程序,独立于内部硬盘,外部硬盘,光盘和网络引导加载程序。
    • 自动检测传统 BIOS 引导加载程序,独立于内部硬盘,外部硬盘和光盘。
    • 手动通过配置文件

    您可以选择使用这些方法中的哪一种来构造rEFInd主启动菜单。虽然rEFIt支持自动检测,但它不支持手动配置。

  • 支持在具有适当 CSM 支持的 UEFI PC 上启动传统 BIOS 引导加载程序(从版本0.4.6开始,版本0.8.0有显着改进)。请注意,某些 UEFI PC(例如具有 Gigabyte 混合 EFI 的 PC )缺少可用的 CSM。
  • 对于 Mac 用户而言,rEFInd配备了比rEFIt更复杂的 Mac 安装工具,支持更多与操作系统无关的打包。

安装

基本安装

安装方法有很多,针对不同的操作系统略有区别,详情参考 The rEFInd Boot Manager: Installing rEFInd。在这里我只简要讲述 Windows10 中手动将 rEFInd 安装到U盘中的方法

  1. 下载 rEFInd: rEFInd - Browse Files at SourceForge.net
  2. 解压下载的refind-bin-0.11.4.zip
  3. 将U盘格式改为GPT(有的也叫GUID/UUID),分一个文件系统为FAT32的ESP分区。(推荐使用 Disk Genius)
  4. refind-bin-0.11.4.zip中的refind目录复制到ESP分区的EFI目录(即ESP\EFI\,如果没有则新建)中,并将refind.conf-sample文件重命名为refind.conf,再将refind_x64.efi复制到ESP\EFI\BOOT\目录中,并重命名为bootx64.efi
  5. 重新启动并在启动选项中选择U盘。可以在 Windows10 中点击关机图标(按Win出现),在出现睡眠关机重启三个选项后按住Shift键的同时单击重启就会进入WIN RE界面,在那里可以选择启动介质

安装额外组件

UEFI Shell

按前文所述的获取 UEFI Shell方法获取 EFI Shell,放在 ESP 分区的EFI/tools目录后将提供从 rEFInd 启用 EFI Shell 的能力

详情参考 The rEFInd Boot Manager: Installing rEFInd

使用

常用快捷键

Keystroke Explanation
left arrow Moves the selection one icon to the left (or up the list in text mode)
right arrow Moves the selection one icon to the right (or down the list in text mode)
up arrow Moves the selection from the utilities row to the OS row (in text mode, moves up one entry)
down arrow Moves the selection from the OS row to the utilities row (in text mode, moves down one entry)
Page Up Scrolls the visible set of tags to the left (or up in text mode)
Page Down Scrolls the visible set of tags to the right (or down in text mode)
Home Moves the selection to the first item on the OS row
End Moves the selection to the last item on the utilities row
Esc or Backspace (Delete on Mac keyboards) Returns from a sub-menu; on the main screen, re-reads the configuration file and re-scans for boot loaders
Delete (on PCs) or minus (-) (Delete on Mac keyboards is Backspace on PC keyboards, and will not work for this) Hides a menu tag. The tag is remembered via the computer’s on-board NVRAM.
Insert, F2, Tab, or + From the main menu, opens the selection’s submenu, which is most useful with Mac OS X, ELILO, and Linux kernels with EFI stub loader support; in a submenu, opens a line editor enabling editing of boot options
F10 Saves an image of the current screen in the file screenshot_##.bmp, where ### is a sequence number starting with 001, in the EFI System Partition’s (ESP’s) root directory
F12 or (on some keyboards) Eject Ejects removable media. This feature only works on some Macs, not on UEFI-based PCs.
Enter or spacebar Launches the currently-selected OS, utility, or built-in feature
1 through 9 Launches the specified boot loader by number
A Displays the “About rEFInd” information
E Launches the first instance of ELILO in the boot list
G Launches the first instance of GRUB in the boot list
L Launches the first Linux kernel in the boot list
M Launches the first Mac OS boot loader in the boot list
P Launches gptsync
S Launches an EFI shell, if available
U Shuts down the computer (but note that this is buggy and reboots most UEFI-based PCs)
W Launches the first Windows boot loader
Other letters Launch OSes whose names begin with those letters, as described below

——引用自 The rEFInd Boot Manager: Using rEFInd

修改配置文件 refind.conf

隐藏与显示 EFI 启动加载器

以下内容翻译自官网:

rEFInd用户常见的抱怨是rEFInd显示太多启动选项。可用如下方法隐藏不希望显示的选项:

  • 动态隐藏。选中一个启动选项后按-号即可。rEFInd使用HiddenTags变量存储隐藏在 NVRAM 或磁盘上的EFI OS标记列表(由refind.conf中的use_nvram标记确定)。如果要恢复已隐藏的标记,可以使用隐藏标记维护功能,该功能显示在 rEFInd 菜单的第二行(一个回收图标)。

  • 移动,删除,或重命名文件。默认情况下, rEFInd 会扫描它可以读取的所有文件系统以用于引导加载程序。它扫描 EFI 目录的大多数子目录,它们可以访问名称以.efi结尾的文件访问的每个文件系统。 ( rEFInd 对tools子目录给予特殊处理,它寻找系统工具而不是引导加载器。)因此,您可以删除 EFI 程序文件,将它们移出 rEFInd 扫描的目录树,或者重命名它们以便它们不会有.efi扩展名。请注意,rEFInd不扫描其自己的目录或EFI/tools目录,因此这些可以是隐藏很少使用的 EFI 二进制文件的好地方

  • dont_scan_volumes: refind.conf中的此标记指定 rEFInd 将不扫描的卷。对于 EFI 引导加载程序,您可以通过其文件系统标签,分区名称或分区唯一 GUID 值来标识卷。在 Mac 上,您可以通过指定 rEFInd 主菜单中显示的 OS 标记描述的任何唯一子集来识别要隐藏的 BIOS/CSM/Legacy 操作系统。在任何一种情况下,此标记都采用逗号分隔的列表,如dont_scan_volumes ESP7,BadVolume将 ESP7 和 BadVolume 分区列入黑名单。此令牌不能用于隐藏基于 UEFI 的 PC 上的 BIOS/CSM/Legacy 加载器。

  • dont_scan_dirs: 此令牌提供比前一个更精细的控制;使用此选项识别目录。例如,您可以指定dont_scan_dirs EFI/ignore, BigDisk:/EFI/OldOS以忽略所有卷上的EFI/ignore目录以及BigDisk卷上的EFI/OldOS目录。此令牌不能用于隐藏 BIOS/CSM/Legacy 加载器。

  • dont_scan_files: 您可以隐藏单个文件。有了这个标记。可以单独指定文件,使用前导目录路径,也可以使用前导目录路径和卷名称或 GUID 指定文件。例如,dont_scan_files badloader.efi,EFI/ignoreme/boring.efi,MyDisk:/EFI/someos/grubx64.efi导致忽略任何位置上的badloader.efi,在任何磁盘上的EFI/ignoreme/boring.efi和在MyDisk上的EFI/someos/grubx64.efi。与前面的项目一样,您可以按文件系统标签(Label),分区名称(Name)或分区唯一GUID标识磁盘。

  • also_scan_dirs-此令牌与前面的令牌相反:它将一个目录添加到扫描列表中,以便 rEFInd 可以找到存储在异常位置的引导加载程序。 此令牌采用目录路径,并且可选地采用名称(文件系统或分区),但当前不能将GUID值作为卷标识符。

  • scanfor-此标记标识 rEFInd 扫描的操作系统类型以及扫描的设备类型。在 Mac 上,BIOS/CSM/Legacy 扫描启用默认; 但您可能希望通过取消注释scanfor行并确保不存在hdbiosbiosexternalcd来禁用此支持。默认情况下,在基于UEFI的PC上禁用这些选项,因此,如果要引导BIOS模式操作系统,则必须取消注释scanfor并添加适当的选项。

修改全局设置

rEFInd 通常在ESP分区的EFI/refind目录中,有时位于EFI/BOOT或其他地方。因此,rEFInd配置文件可能在/boot/efi/EFI/refind/refind.conf(Linux上),/boot/EFI/BOOT/refind.conf(Linux上),/Volumes/ESP/EFI/refind/refind.conf(mac OS上),S:\EFI\refind\refind.conf(Windows上,假设挂载ESP 分区在S:)或其他地方,具体取决于您的操作系统和挂载点。

例子:

1
2
3
4
5
6
# Sample refind.conf file
timeout 5
banner custom.bmp
scan_driver_dirs drivers,EFI/tools/drivers
scanfor manual,external,optical
default_selection elilo

配置详情参见: The rEFInd Boot Manager: Configuring the Boot Manager - table1

创建手动启动选项

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
menuentry "Ubuntu" {
    loader /EFI/ubuntu/grubx64.efi
    disabled
}

menuentry Arch {
    icon /EFI/refind/icons/os_arch.png
    volume ARCHBOOT
    loader /vmlinuz-linux
    initrd /initramfs-linux.img
    options "root=/dev/sda3 ro"
}

menuentry "Windows via shell script" {
    icon \EFI\refind\icons\os_win.png
    loader \EFI\tools\shell.efi
    options "fs0:\EFI\tools\launch_windows.nsh"
}

配置详情参见: The rEFInd Boot Manager: Configuring the Boot Manager - table2

创建子菜单条目

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
menuentry Arch {
    icon /EFI/refind/icons/os_arch.png
    loader /vmlinuz-linux
    initrd /initramfs-linux.img
    options "root=/dev/sda3 ro"
    submenuentry "single-user mode" {
        add_options "single"
    }
    submenuentry "Use fallback initrd" {
        initrd /initramfs-linux-fallback.img
    }
    submenuentry "boot via SYSLINUX" {
        loader \EFI\syslinux\syslinux.efi
	initrd
	options
    }
}

配置详情参见: The rEFInd Boot Manager: Configuring the Boot Manager - table3

GRUB

本部分大量参考了 GRUB (简体中文) - ArchWiki。另有如下重要链接以供参考:

简介

GNU GRUB(简称“GRUB”)是一个来自GNU项目的启动引导程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数。

GNU GRUB的前身为Grand Unified Bootloader。它主要用于类Unix系统;同大多Linux发行版一样,GNU系统也采用GNU GRUB作为它的启动器。Solaris从10 1/06版开始在x86系统上也采用GNU GRUB作为启动器。

现在我们看到的 GRUB , 是下一代 GRand Unified Bootloader, 请不要和 GRUB Legacy  混淆了。它来自下一代 GRUB 研究项目 PUPA,代码全部重写,实现了模块化和增强了移植性。

特点

GRUB最大的优势在于既能用于传统的BIOS/MBR,又能用于新型的 UEFI/GPT。它历史悠久,稳定可靠。其它突出的特点如下:

  • GRUB可动态配置;它在启动时加载配置信息,并允许在启动时修改,如选择不同的内核和initrd。为此目的,GRUB提供了一个简单的类似Bash的命令行界面,它允许用户编写新的启动顺序。
  • GRUB具有多种用户界面。多数Linux发行版利用GRUB对图形界面的支持,提供了定制的带有背景图案的启动菜单,有时也支持鼠标。GRUB可通过GFX支持更美观的引导画面和引导菜单。通过对GRUB的文字界面的设定,可以通过串口实现远程终端启动。
  • 与其它启动器不同,GRUB可以通过GRUB提示符直接与用户进行交互。加载操作系统前,在GRUB文本模式屏幕下键入c键可以进入GRUB命令行。在没有作业系统或者有作业系统而没有”menu.lst”(或grub.cfg)配置文件的系统上,同样可以进入GRUB提示符。通过类似bash的命令,GRUB提示符允许用户手工启动任何操作系统。把合适的命令记录在”menu.lst”(或grub.cfg)文件里,可以自动启动一个操作系统。
  • GRUB拥有丰富的终端命令,在命令行下使用这些命令,用户可以查看硬盘分区的细节,修改分区设置,临时重新映射磁盘顺序,从任何用户定义的配置文件启动,以及查看GRUB所支持的文件系统上的其它启动器的配置。因此,即便不知道一台计算机上安装了什么,也可以从外部设备启动一个操作系统。
  • 通过链式启动,一个启动器可以启动另一个启动器。GRUB通过2到3行的命令就可以从DOS、Windows、Linux、BSD和Solaris系统启动。
  • 新的GRUB2(GRUB第二版)为GRUB的重写版本,它是GRUB的大革新。GRUB2对Linux系统做了更多的优化,支持更多的功能,如动态的加载模块(而在之前的GRUB中,新增或删除模块要重新编译GRUB)等。GRUB2的版本号为0.98或更高;旧的GRUB的版本号则为0.97或更低,也被称为“GRUB Legacy”或“GRUB1”等。GRUB2的配置、命令等较GRUB Legacy有一定的不同。

启动过程

计算机启动后,BIOS将寻找第一个可启动的设备(通常为硬盘),而后从MBR中加载启动程序,然后把控制交给这段代码。MBR位于硬盘的前512字节内。

GRUB第一版本

GRUB的步骤1包含在MBR中。由于受MBR的大小限制,步骤一所做的几乎只是装载GRUB的下一步骤(存放在硬盘的其它位置)。步骤1既可以直接装载步骤2,也可以装载步骤1.5:GRUB的步骤1.5包含在MBR后面的30千字节中。步骤1.5加载步骤2。

当步骤2启动后,它将呈现一个界面来让用户选择启动的操作系统。这步通常采用的是图形菜单的形式,如果图形方式不可用或者用户需要更高级的控制,可以使用GRUB的命令行提示,通过它,用户可以手工指定启动参数。GRUB还可以设置超时后自动从某一个内核启动。

GRUB第二版本

与GRUB第一版相似的是,boot.img像步骤1一样在MBR或在启动分区中,但是,它可以从任何LBA48地址的一个扇区中读取,它(boot.img)将读取core.img(产生于diskboot.img)的第一个扇区以用来后面读取core.img的剩余部分。core.img正常情况下跟步骤1.5储存在同一地方并且有着同样的问题,可是,当他被移动到一个文件系统或一个纯粹的分区时会比在步骤1.5移动或删除引起更少的麻烦。一旦完成读取,core.img会读取默认的配置文件和其他需要的模块。

当GRUB启动后

一旦选择了启动选项,GRUB把选择的内核加载内存并把控制交给内核。在此步骤中,对于Windows之类不支持多启动标准的操作系统,GRUB也可以通过链式启动把控制传给其它启动器。在这种情况下,其它操作系统的启动程序被GRUB保存了下来;与内核不同,其它操作系统如同直接自MBR启动。类似Windows的启动菜单,也许是另一个启动管理器,它允许在多个不支持多启动的操作系统中做进一步的选择。(在已有Windows的系统上面,或者包含多个Windows版本的系统上安装现代的Linux而不修改原操作系统,即属于这类情况。)

引用自 GNU GRUB - 维基百科,自由的百科全书

安装

GRUB的一个重要的特性是安装它不需依附一个操作系统;但是,这种安装需要一个Linux/Windows副本。由于单独工作,GRUB实质上是一个微型系统,通过链式启动的方式,它可以启动所有安装的主流操作系统。

与LILO不同,修改GRUB的配置文件后,不必把GRUB重新安装到MBR或者某个分区中。

在Linux中,“grub-install”命令是用来把GRUB的步骤1安装到MBR或者分区中的。GRUB的配置文件、步骤2以及其它文件必须安装到某个可用的分区中。如果这些文件或者分区不可用,步骤1将把用户留在命令行界面。

GRUB配置文件的文件名和位置随系统的不同而不同;如在Debian(GRUB Legacy)和OpenSUSE中,这个文件为/boot/grub/menu.lst,而在Fedora和Gentoo中为/boot/grub/grub.conf。Fedora、Gentoo Linux和Debian(GRUB 2)使用/boot/grub/grub.conf Fedora为了兼容文件系统层次结构标准提供了一个从/etc/grub.conf到/boot/grub/grub.conf的符号链接。

除了硬盘外,GRUB也可安装到光盘、软盘和闪存盘等移动介质中,这样就可以引导一台无法从硬盘启动的系统。

引用自 GNU GRUB - 维基百科,自由的百科全书

具体而言,可以在 Linux 中直接使用如下命令进行安装:

1
grub-install --target=x86_64-efi --efi-directory=esp_mount --bootloader-id=grub

上述命令用于安装 GRUB UEFI 程序到esp/EFI/grub中, 安装其模块到/boot/grub/x86_64-efi, 然后将可以启动的grubx64.efi复制到esp/EFI/grub。其中的esp_mount即 ESP 分区的挂载点;--bootloader-id是启动项中用来识别 GRUB EFI 的标记(即esp/EFI/grub中的grub

上述安装完成后 GRUB 的主目录将位于/boot/grub/

使用

生成主配置文件

安装后或/etc/default/grub变更后或/etc/grub.d/中的配置文件变更后,需要生成真正使用的配置文件grub.cfg。配置文件的生成过程受到/etc/default/grub/etc/grub.d/下脚本的影响。

使用下面命令生成grub.cfg:

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

或者

1
update-grub

真正被使用的配置文件的默认路径是/boot/grub/grub.cfg,但不推荐直接修改该文件,而应如上所述,修改/etc/default/grub/etc/grub.d/中的文件后使用grub-mkconfig命令生成grub.cfg

/etc/default/grub

该文件通过设置各种变量来改变 GRUB 的外观和行为。详情参见 Grub2/Setup - Community Help Wiki

默认情况下配置如下(以 CentOS7 为例):

1
2
3
4
5
6
7
GRUB_TIMEOUT=0 # 超时,0 表示不显示 GRUB 菜单,直接进入默认系统
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" # Linux 发行版,这里的值为`CentOS Linux`
GRUB_DEFAULT=saved # 默认启动项,这里设为上次启动的启动项
GRUB_DISABLE_SUBMENU=true # 关闭子菜单
GRUB_TERMINAL_OUTPUT="console" # 设置终端输出为 console
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet" # 向 Linux 镜像传递额外的参数
GRUB_DISABLE_RECOVERY="true" # 取消生成 GRUB recovery 启动项

更新了该文件后,记得运行下面命令更新grub.cfg:

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

下面将讲几个常用的变量。

GRUB_CMDLINE_LINUX[_DEFAULT]

/etc/default/grub中设置GRUB_CMDLINE_LINUXGRUB_CMDLINE_LINUX_DEFAULT变量可以向 Linux 镜像传递额外的参数. 生成普通启动项时,这两个参数的值会合并在一起加入, 对于recovery启动项, 则添加 GRUB_CMDLINE_LINUX参数的值.

GRUB_DISABLE_LINUX_UUID

grub-mkconfig默认使用根文件系统的UUID。要禁用此设置,取消GRUB_DISABLE_LINUX_UUID=true前的注释.

GRUB_DISABLE_RECOVERY

要生成 GRUB recovery 启动项,需要在/etc/default/grub中将GRUB_DISABLE_RECOVERY=true注释掉.

/etc/grub.d/40_custom

该文件用于自定义启动项(官方推荐使用该文件)。详情参考 Grub2/CustomMenus - Community Help Wiki

更新了该文件后,同样记得运行下面命令更新grub.cfg:

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

典型示例文件:

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
34
35
36
etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.

menuentry "Microsoft Windows 8.1" {
	echo "Loading Microsoft Windows 8.1..."
	insmod part_gpt
	insmod fat
	insmod search_fs_uuid
	insmod chain
	search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6
	chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}

menuentry "Microsoft Control Center" {
	echo "Loading Microsoft Control Center..."
	insmod part_gpt
	insmod fat
	insmod search_fs_uuid
	insmod chain
	search --fs-uuid --no-floppy --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 763A-9CB6
	chainloader /EFI/HP/boot/bootmgfw.efi
}

menuentry "System shutdown" {
	echo "System shutting down..."
	halt
}

menuentry "System restart" {
	echo "System rebooting..."
	reboot
}
GNU/Linux 启动项
1
2
3
4
5
menuentry "Other Linux" {
	set root=(hd0,2)
	linux /boot/vmlinuz (add other options here as required)
	initrd /boot/initrd.img (if the other kernel uses/needs one)
}

或者让 grub 根据 UUID 或 label 查找启动项:

1
2
3
4
5
6
7
8
9
10
menuentry "Other Linux" {
        # assuming that UUID is 763A-9CB6
	search --set=root --fs-uuid 763A-9CB6

        # search by label OTHER_LINUX (make sure that partition label is unambiguous)
        #search --set=root --label OTHER_LINUX

	linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)
	initrd /boot/initrd.img (if the other kernel uses/needs one)
}

带有 LVM 支持的示例如下:

1
2
3
4
5
6
7
8
# (0) Arch Linux
menuentry "Arch Linux" {
  insmod lvm
  set root=lvm/VolumeGroup-lv_boot
  # you can only set following two lines
  linux /vmlinuz-linux root=/dev/mapper/VolumeGroup-root ro
  initrd /initramfs-linux.img
}
UEFI-GPT 模式下安装的Windows的启动项
1
2
3
4
5
6
7
8
9
10
if [ "${grub_platform}" == "efi" ]; then
	menuentry "Microsoft Windows Vista/7/8/8.1 UEFI-GPT" {
		insmod part_gpt
		insmod fat
		insmod search_fs_uuid
		insmod chain
		search --fs-uuid --set=root $hints_string $fs_uuid
		chainloader /EFI/Microsoft/Boot/bootmgfw.efi
	}
fi

$hints_string$uuid可以通过以下命令获取。

  1. $uuid:

    1
    2
    
    # grub-probe --target=fs_uuid $esp/EFI/Microsoft/Boot/bootmgfw.efi
    1ce5-7f28
    
  2. $hints_string:

    1
    2
    
    # grub-probe --target=hints_string $esp/EFI/Microsoft/Boot/bootmgfw.efi
    --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
    

这两个命令都是假设ESP挂载在$esp

“Shutdown” 启动项
1
2
3
4
menuentry "System shutdown" {
	echo "System shutting down..."
	halt
}
“Restart” 启动项
1
2
3
4
menuentry "System restart" {
	echo "System rebooting..."
	reboot
}
ISO 文件启动项
  1. 对于 Ubuntu:
    1
    2
    3
    4
    5
    6
    
    menuentry "ubuntu-13.04-desktop-amd64.iso" {
      set isofile="/archives/ubuntu-13.04-desktop-amd64.iso"
      loopback loop (hd0,6)/$isofile
      linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=$isofile quiet noeject noprompt splash --
      initrd (loop)/casper/initrd.lz
    }
    
  2. 对于 Fedora:
    1
    2
    3
    4
    5
    6
    7
    8
    
    menuentry "Fedora 15 (DVD)" {
     insmod loopback
     insmod iso9660
     set isofile="/Fedora-15-x86_64-DVD.iso"
     loopback loop (hd0,2)$isofile
     linux (loop)/isolinux/vmlinuz rootfstype=auto  root=live:UUID=:$isofile ro quiet
     initrd (loop)/isolinux/initrd.img
    }
    

    注意:从iso启动是一个必须由发行版支持的功能,而iso-scan/filename=选项在Fedora或其他版本中不起作用。它们可能具有此功能的其他内核选项,或者根本不支持该功能。

    详情参考: grub2 - How to boot from non-Ubuntu live ISO images like Fedora or CentOS? - Ask Ubuntu

GRUB 命令行

GRUB 命令行在紧急情况下非常有用。在 GRUB 命令行中可以手动加载 OS Loader,正常进入操作系统后就可以使用update-grub修复引导问题。对于 GRUB 命令行中可以使用的所有命令,可以参考 GNU GRUB Manual 2.02

MBR太小,所以不足以存储所有的 GRUB 模组。MBR 里面只有启动目录配置和一些很基本的命令。GRUB的主要功能通过/boot/grub里的模组实现,而且可以按需加载。出现错误时,GRUB可能不能引导启动(比如,磁盘分区发生了变化)。这时候,一般会出现命令行界面。

GRUB不止提供一个shell.如果GRUB不能读取到启动目录配置,但是能找到磁盘,你很可能需要进入normal shell:

1
sh:grub>

如果有更严重的问题(比如,GRUB找不到必须的文件了),你就可能需要进入rescue shell:

1
grub rescue>

rescue shellnormal shell的一个子集,其支持的功能更少.如果不幸进入了rescue shell里,首先加载normal.mod,然后启动normal shell:

1
2
3
grub rescue> set prefix=(hdX,Y)/boot/grub
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod
rescue:grub> normal

下面将列举常用命令

set
1
set [envvar=value]

将环境变量envvar设置为value。如果在没有参数的情况下调用,则打印所有环境变量及其值。

pager

GRUB支持对长输出进行分页(比如运行 help 的输出).不过只有normal shell支持分页,而rescue shell不支持.开启分页支持的方法如下:

1
grub> set pager=1
root

用于将指定分区设置为临时 root 分区。如:

1
grub>set root=hd0,msdos1
ls
1
ls [arg …]

列出设备或文件。不带参数时,打印 GRUB 已知的所有设备。如果参数是括在括号中的设备名,则打印该设备文件系统的名称。如果参数是由绝对路径给定的目录,则列出该目录的内容。常用用法如下:

  1. 列出所有磁盘及分区信息。如
    1
    2
    
    grub> ls
    (hd0),(hd0,msdos5),(hd0,msdos1)
    

    其中hdX指明磁盘,msdosX指明分区。注意,msdos表示磁盘为传统的MBR格式,对于较新的GPT格式,使用gpt来表示,如(hd0,gpt1)即表示第一个磁盘的第一个分区。可以看到,磁盘下标从 0 开始,而分区下标从 1 开始。关于如何指定一个设备的更多信息,请参见 GNU GRUB Manual 2.02 - Device-syntax

  2. 列出指定目录下的文件。如:
    1
    2
    
    ls (hd0,X)/boot/grub
    ls (hd0,X)/grub2
    

    关于如何指定一个文件(文件夹)的更多信息,请参见 GNU GRUB Manual 2.02 - File-name-syntax

insmod
1
insmod module

插入名为module的动态 GRUB 模块.

linux
1
linux file ...

file加载一个 Linux 内核镜像。例如:

1
linux /boot/vmlinuz-linux root=/dev/sda5
initrd
1
initrd file

为 Linux 内核映像加载初始ramdisk,并在内存的 Linux 设置区域中设置适当的参数。只有在运行linux命令(请参见 linux)之后才能使用此命令。例如:

1
initrd /boot/initramfs-linux.img
boot

启动已加载的操作系统或chain-loader

chainloader
1
chainloader [--force] file

将文件加载为链式加载器。与文件系统代码加载的任何其他文件一样,它可以使用blocklist表示法(请参阅 blocklist语法)来抓取当前root分区的第一个扇区(+1)。如果指定选项--force,将会强行加载文件,无论它是否有正确的签名。当您要加载有缺陷的引导加载程序(例如SCO UnixWare 7.1)时,--force选项是必需的。

例如:

1
chainloader +1
使用命令行引导操作系统

可以使用GRUB命令行引导操作系统,一个典型的应用场景是通过chainloader来引导另一个WindowsLinux

chainLoader的意思是用当前的bootloader去载入另一个bootloader,所以叫做链式加载.这个bootloader可能位于MBR,也可能在另一个分区的引导扇区上.

链式加载一个分区
1
2
3
set root=(hdX,Y)
chainloader +1
boot

X=0,1,2… Y=1,2,3…

比如链式加载一个位于首磁盘,首分区上的Windows:

1
2
3
set root=(hd0,1)
chainloader +1
boot

也可以使用GRUB链式加载另一个分区引导扇区上的GRUB.

链式加载一个磁盘
1
2
3
set root=hdX
chainloader +1
boot
正常载入
1
2
3
4
set root=(hd0,5)
linux /boot/vmlinuz-linux root=/dev/sda5
initrd /boot/initramfs-linux.img
boot

成功启动操作系统后,用户可以修正配置的错误或者重新安装GRUB.

使用应急命令行

建议使用GRUB 命令行中说的方法加载normal.mod,然后启动normal shell。如果失败,使用下述方法从应急命令行引导操作系统

GRUB应急命令行里可用的命令有insmod, ls, set, unset.可以使用set/unset修改变量,使用insmod来载入模组.

正常载入前导入linux.mod:

set prefix=(hdX,Y)/boot/grub
insmod (hdX,Y)/boot/grub/linux.mod

之后和正常载入的步骤一致

总结

对于传统的 BIOS/MBR 方式,分区时需要分一个主分区(它只能分4个主分区),并激活它作为启动分区,用作C盘;此外,还需要分一个扩展分区,再从扩展分区中分出其它分区,用作D、E……盘

对于 UEFI/GPT 方式,需要分一个文件系统为FAT32FAT16的 ESP 分区,用作启动分区,里面主要放置用于引导启动的.efi文件;此外对于 GPT 格式的硬盘,不再支持拓展分区,因为它可以分的分区数理论上为无限个(事实上会依然会受到限制,如受到操作系统本身的限制),所以,可以分出任意个主分区用作C、D、E、F、……盘

UEFI/GPT有个极大的好处在于可以通过UEFI Shell直接启动任意操作系统,这对于多操作系统而言是极为方便的

rEFInd 是一个极好的 UEFI 多启动管理器,且图表界面友好。与之类似且大量使用的是 GRUB,GRUB 的优势在于既能用于传统的 BIOS/MBR,又能用于新型的 UEFI/GPT。

链接

下面总结了本文中使用的所有链接: