Khorina · 3月13日

一文让你搞懂 UEFI

Hi!早哦。今天又是宠读者的一天,应允聊聊 UEFI。

前言

很难用一篇文章去完全的了解 UEFI,这篇文章的目标是希望能让不了解的朋友看完后达到下面几个目标:

  • UEFI 是什么:概念
  • UFEI 用来干什么:应用
  • UEFI 有些什么东西:架构
  • UEFI 重点场景:启动
  • UEFI 学习资料:推荐

通过这几个部分,咱们能一起搭建起一个关于 UEFI 简要知识框架。那么以后对哪些方面感兴趣,让我知道,咱们再一起学习一下,去继续丰富关于 UEFI。

话不多说,上菜!

UEFI 是什么?

这就不得不提提 BIOS。

传统 BIOS

为了更好地理解 UEFI,我们首先需要回顾一下历史。自 20 世纪 80 年代以来,计算机一直在使用 BIOS。

当我们提到 BIOS 时,根据上下文的不同,它可能代表不同的含义:

  1. BIOS 标准:这是一个广泛的概念,指的是一种在计算机启动时初始化硬件并加载操作系统引导程序的标准接口。
  2. 具体的 BIOS 实现——即特定于主板的固件(“ASUS $motherboard_name BIOS”):
  • 这是由主板制造商编写或授权的代码。
  • 当计算机开机时,硬件被设置为开始执行 BIOS。这是 CPU 需要知道的全部内容,即 CPU 不需要了解驱动器、文件系统或操作系统。BIOS 负责初始化硬件,加载引导加载程序(如 GRUB 或 Windows Boot Manager),然后引导加载程序负责加载并启动操作系统。

简而言之,BIOS 是计算机启动过程中的一个重要环节,它负责在操作系统加载之前初始化硬件,并为操作系统的启动提供必要的环境。而 UEFI(统一可扩展固件接口)是 BIOS 的现代替代品,提供了更多的功能和更好的安全性。

BIOS 作为标准

作为一个标准,BIOS 定义了以下内容:

  1. 一个硬编码的内存位置,计算机在开机时 CPU 将从该位置开始执行 BIOS 代码。
  2. 磁盘位置,操作系统制造商可以在这些位置放置其引导加载程序以启动其操作系统。
  • 从硬盘和软盘读写数据(因此不是所有程序都需要直接处理 IDE/SATA 等总线)
  • 读取键盘按键 => BIOS 是一个硬件抽象层。
  1. 应用程序接口(APIs)用于:
  2. 其他许多功能

通过这些方式,BIOS 为以下对象提供了 API:

  1. 操作系统制造商
  2. CPU 制造商
  • 开发人员与操作系统的硬件抽象 API 进行交互,甚至操作系统本身也不使用太多的 BIOS API(因为它们直接控制硬件以获得更高级别的访问权限,这样就很不安全了)
  • 即使在 DOS 时代,应用程序开发人员也可能使用 DOS API 进行抽象,而不是直接使用 BIOS。
  1. 应用程序开发人员。不过,现在这些 API 的使用已经不多了,因为:

BIOS 作为实现

你可能熟悉更新主板 BIOS 的过程。待刷新的 BIOS 是特定于主板的(即不存在适用于所有主板的单一 BIOS),因为 BIOS 的实现是特定于主板的。

我并不完全了解制造商特有的所有内容,但我猜测不同主板的芯片组会有所不同,比如内存控制器的初始化和处理、内置图形处理器等。

BIOS 的工作原理

x86 CPU 被设计为从一个硬编码的内存位置(0xFFFFFFF0)开始执行代码。这个内存位置由主板的 BIOS 代码 ROM 提供支持。在电气上,很容易将不同的地址空间分开,其中某些位置从 RAM 读取,而某些位置则从 BIOS ROM 等读取。要更深入地了解这一概念在电气上的实现,请观看此视频。

以下是一个过于简化的视图:

image.png

BIOS 负责实际启动你的操作系统。

在 BIOS 设置中,你通常可以配置启动顺序,如 CD-ROM、硬盘 1、硬盘 2 等,以及它们的任何组合。BIOS 会根据你的启动顺序偏好找到第一个可启动项。

传统 BIOS 的局限性

由于引导加载程序大小的限制,大多数操作系统不得不使用复杂的链式启动过程。

传统 BIOS 启动过程

对于硬盘来说,存在一个引导扇区。引导扇区,或者更具体地说,是主引导记录(MBR),它包含引导加载程序,并且其大小限制实际上是 440 字节,因此仅凭这个大小的引导加载程序绝对无法加载现代操作系统。

通常,MBR 中的引导加载程序会将控制权传递给活动分区的引导加载程序(VBR,卷引导记录),但它也有相同的大小限制。

加载操作系统至少意味着引导加载程序必须从磁盘读取内核(Linux/Windows 等)并将其控制权交给它。内核更加智能,能够理解各种文件系统,如 NTFS/FAT 等。

但是,为了让引导加载程序从磁盘读取内核,它必须知道如何遍历文件系统以访问内核。因此,引导加载程序会从文件系统的根目录读取并链式加载一个“第二阶段”(这是一个更简单的任务)——一个可以更大、因此可以包含更复杂代码的文件。

在 Windows 中,这个第二阶段过去被称为 NTLDR(“NT 加载程序”),它位于你的 C:驱动器的根目录下。

Image以下是关于传统 BIOS 和旧版 Windows 版本的启动过程:

Image

如你所见,有很多箭头——引导加载程序组件分布在各个地方。有三个不同的特定于 Windows 的位置用于开始加载实际的内核。只要其中一个组件出错,你就会得到一个无法启动的系统。

Linux(链式 GRUB)的情况也大致相同。

搞了这么多的 BIOS?你的标题是 UEFI 欸,你别着急,继续看。

BIOS VS UEFI

其实大家对 BIOS 不陌生,到这里呢,我们来对通过一个对比引出我们的主角 UEFI。

BIOS 代表基本输入输出系统(Basic Input/Output System),是我们在上述启动过程中提到的固件。

它存储在可擦除可编程只读存储器(EPROM, Erasable Programmable Read-Only Memory)中,这使得制造商可以轻松地推送更新。

Image

BIOS 提供了许多辅助功能,这些功能允许读取附加存储设备的引导扇区并在屏幕上打印信息。您可以在启动过程的初始阶段通过按 Del、F2 或 F10 键来访问 BIOS。

UEFI 代表统一可扩展固件接口(Unified Extensible Firmware Interface)。它与 BIOS 执行相同的任务,但有一个基本区别:它将所有关于初始化和启动的数据存储在 .efi 文件中,而不是存储在固件上。

Image

这个 .efi 文件存储在硬盘上一个名为 EFI 系统分区(EFI System Partition, ESP)的特殊分区中。这个 ESP 分区还包含引导加载程序。

UEFI 被设计用来克服旧版 BIOS 的许多限制,包括:

  • UEFI 支持高达 9 泽它字节(Zettabytes)的驱动器大小,而 BIOS 仅支持 2.2 太字节(Terabytes)。
  • UEFI 提供更快的启动时间。
  • UEFI 具有独立的驱动程序支持,而 BIOS 的驱动程序支持存储在 ROM 中,因此更新 BIOS 固件有点困难。
  • UEFI 提供类似“安全启动”(Secure Boot)的安全功能,这可以防止计算机从未经授权/未签名的应用程序启动。这有助于防止 rootkit,但也会妨碍双系统启动,因为它将其他操作系统视为未签名的应用程序。目前,只有 Windows 和 Ubuntu 是已签名的操作系统(如果我有误,请告诉我)。
  • UEFI 以 32 位或 64 位模式运行,而 BIOS 以 16 位模式运行。因此,UEFI 能够提供图形用户界面(GUI, Graphical User Interface),允许使用鼠标进行导航,而 BIOS 仅允许使用键盘进行导航。

当然您可能不需要 UEFI

尽管所有现代计算机都默认配备了 UEFI,但您可能选择使用 BIOS 而不是 UEFI 的原因有几个:

  • 如果您是初学者,并且不关心与任何类型的固件打交道,那么 BIOS 适合您。
  • 如果您每个硬盘或分区的容量小于 2TB,那么您可以使用 BIOS。
  • BIOS 允许在不更改任何设置的情况下运行多个操作系统。从现代的角度来看,这可能是一个安全问题,但对用户来说没有麻烦。
  • BIOS 向操作系统提供系统信息。因此,如果您的操作系统以 16 位模式运行,它不需要编写与硬件交互的代码。它可以直接使用 BIOS 提供的方法。否则,如果操作系统切换到 32 位或 64 位模式,则需要提供自己的与硬件交互的子程序。
  • 如果您更喜欢使用键盘和基于文本的界面而不是使用鼠标和图形用户界面的导航,那么 BIOS 适合您。

UEFI 考虑到了这些限制,并提供了传统模式(Legacy mode)。在该模式下,您可以像拥有 BIOS 固件一样运行所有内容。但请记住,英特尔已宣布从 2020 年起将不再支持传统 BIOS。

以下是一个简化的表格,展示了 UEFI 和 BIOS 之间的主要对比结果:

image.png

请注意,这个表格是对 UEFI 和 BIOS 之间主要区别的简化概述,并未涵盖所有细节。在实际应用中,两者之间可能还存在其他差异和特性。

是时候进入正题了!

UEFI?

前面我们知道了由于传统 BIOS 的局限性,人们开发了一种新标准,称为 UEFI(通常简称为“EFI”)。UEFI 执行传统 BIOS 曾经执行过的相同任务(以及更多任务),但接口(标准,“API”)不同。

我们现在有了一个专用的分区,它足够大,可以包含整个操作系统的引导加载程序,因此我们不必将多个部分连接在一起,而无需使用微小的引导扇区。

UEFI 还为我们提供了网络引导、安全启动等安全功能。

UEFI 不是 BIOS

有时使用的术语“UEFI BIOS”是不正确的(即使我的主板制造商华硕也使用它),因为 UEFI 和 BIOS 都是固件的子类型——即它们是独立、不同、独立的固件标准:

Image

UEFI 概念

统一可扩展固件接口(UEFI)是一种现代固件接口,它取代了个人计算机上的传统 BIOS(基本输入输出系统)。UEFI 作为操作系统与计算机硬件组件之间的关键纽带,促进了初始化过程,并为操作系统与系统固件之间的交互提供了标准化方式。

与旧版 BIOS 相比,UEFI 提供了多项优势,包括支持更大容量的存储设备、更快的启动速度、增强的安全功能和更友好的用户界面。开发 UEFI 的主要动机之一是克服 BIOS 的局限性,并为固件开发提供一个更加灵活和可扩展的平台。

Image

为了更好地理解 UEFI,我们可以考虑一个涉及计算机启动过程的例子。在配备 UEFI 固件的系统中,当计算机通电时,启动过程开始。UEFI 固件控制系统并启动加电自检(POST),这是一个诊断过程,用于检查硬件组件的完整性。POST 成功完成后,UEFI 固件会查找可启动设备。

在 UEFI 系统中,固件与 UEFI 启动管理器交互,后者是一个负责加载操作系统的软件组件。启动管理器会查阅 UEFI 启动变量,这些变量包含有关可用启动选项及其优先级的信息。这些变量存储在非易失性存储器中,用户或系统管理员可以对其进行修改以自定义启动配置。

假设计算机在固态硬盘(SSD)上安装了操作系统。UEFI 固件在启动管理器的帮助下,定位 SSD 上 EFI 系统分区(ESP)中存储的 UEFI 引导加载程序。UEFI 引导加载程序是一个小程序,它了解文件系统并知道如何将操作系统内核加载到内存中。

一旦 UEFI 引导加载程序加载了操作系统内核,控制权便转移给操作系统,并向用户呈现用户界面。在整个过程中,UEFI 促进了硬件与软件之间的通信,确保了顺畅且高效的启动体验。

因此,UEFI 是一种关键的固件接口,为固件开发提供了标准化和可扩展的框架,从而实现了性能提升、对大容量存储设备的支持以及增强的安全功能。从 BIOS 到 UEFI 的转变标志着系统固件发展的一次重大进步。

EFI 系统分区

作为 Windows 用户,您可能已经注意到有一个神秘的“系统保留”分区:

Image

这是 ESP(EFI 系统分区)——一个用于启动符合 EFI 的系统的分区。

ESP 通常是一个采用 FAT32 格式化的分区,最小空间为 100MB,一些指南建议为 512MB。

该分区包含 EFI 应用程序,这些应用程序通常位于自己的目录中。可能包含多个 EFI 应用程序,因为您可能安装了多个操作系统。在我的思维模型中,我将这些目录视为每个操作系统的“插槽”。

如果您想的话,可以使用基本的 Linux 内置工具(如 、 mkfs.fat -F 32)从头开始创建此分区。只需确保将分区类型设置为 EFI 系统即可!

幸运的是,ESP 并不神奇——它只是一个包含文件的分区,并且某些文件路径具有特殊含义(如果未指示启动选择,则默认启动的 EFI 应用程序)。

EFI 变量

EFI(Extensible Firmware Interface,可扩展固件接口)是现代计算机系统中用来替代传统 BIOS 的一种新标准。在 EFI 的世界里,有一些特别的“变量”被存储在主板的非易失性随机访问存储器(NVRAM)中。这些变量就像是电脑的小记事本,存储着一些重要的设置和信息。

其中,有一个特别重要的变量叫做“默认启动项”(“BootCurrent”),它就像是一个指针或者地址,指向了另一个变量。这个被指向的变量呢,其实就是一个具体的启动项,里面包含了要启动的 EFI 应用程序(比如操作系统)的完整路径,就像是你手机上的某个 APP 的存储位置一样。

不仅如此,这些启动项变量还很贴心,它们还能额外存储一些参数,就像是你打开 APP 时可以设置的一些选项。对于 Linux 系统来说,有一个特别的 EFI 应用程序叫做 EFI stub,它可以直接从 EFI 环境启动 Linux 内核,而不需要传统的引导加载程序(如 GRUB)。在这个场景下,EFI 变量里就会包含 Linux 内核启动时需要的一些命令行参数,比如指定根文件系统所在的分区。而如果使用 GRUB 这样的引导加载程序,这些参数就会写在 GRUB 的配置文件中,而不是 EFI 变量里。

最棒的是,这些 EFI 变量是可以从操作系统内部直接修改的,这意味着,如果你想改变启动顺序或者添加新的启动项,不再需要像以前那样重启电脑,然后进入 BIOS 设置界面去操作了。你只需要在操作系统里找到相应的工具或命令,就可以轻松完成这些任务,大大简化了操作过程。

EFI 的启动过程

Image

主板的固件基本上总是存储在闪存中(这样它就可以被升级)。EFI 变量的存储也需要闪存,因为如果它们不能被更改,那么它们就称不上是真正的“变量”。

EFI 变量的影响

让我们用更简单的语言来解释关于 EFI 变量的一些关键点:

EFI 变量是什么?

EFI(现在常被称为 UEFI,即统一可扩展固件接口)变量是存储在计算机中的小数据块,它们包含了一些重要的设置和信息,比如启动时的配置参数、操作系统需要的特殊指令等。这些变量对于确保计算机和操作系统能够顺利启动和运行非常重要。

为什么 EFI 变量会影响驱动器和新主板的兼容性?

当你把一个硬盘(我们称之为驱动器)从一台电脑换到另一台时,可能会遇到问题。这是因为每台电脑的主板(负责计算机启动和硬件交互的核心部件)上都有自己的 EFI 变量。这些变量里可能包含了一些特定的设置或参数,是启动操作系统时必需的。如果新主板没有这些特定的设置,那么系统可能无法正常工作。

Linux EFI stub 是个啥?

Linux EFI stub 是一个特殊的启动方式,它允许 Linux 内核直接作为 EFI 应用程序来启动,而不需要传统的启动加载器(如 GRUB)。虽然这听起来很酷,但它需要一些额外的参数来告诉内核如何启动,这些参数就存储在 EFI 变量中。

你可能会想,为什么不把所有的 EFI 变量都放在驱动器上的一个地方(比如 ESP)呢?这样换电脑时不是更方便吗?但实际上,这样做会有安全风险,因为驱动器可以被随意更换,如果它决定了计算机的启动方式,那就可能被恶意利用。所以,EFI 变量大部分还是存储在主板上的一个特殊区域(NVRAM),这样更安全。

不同的主板制造商可能会用不同的方式来存储 EFI 变量,这意味着它们的格式可能不同。对于大多数用户来说,这不是问题,因为操作系统和 EFI 固件会处理这些细节。但是,如果你在虚拟机或特殊环境中工作,并需要手动设置这些变量,那就可能会遇到麻烦,因为你需要知道如何与特定主板的 EFI 固件交互。

EFI 变量是计算机启动过程中的重要部分,它们包含了启动系统所需的关键信息和设置。由于这些变量可能依赖于特定的主板和固件,所以在更换硬件或进行特殊配置时需要格外注意。对于大多数用户来说,这些变量是自动管理的,但了解它们的工作原理可以帮助你更好地理解和解决启动问题。

UEFI 的架构

UEFI 的设计是建立在几个关键概念之上的:

  1. 利用现有的“表格式”接口:为了节省大家在操作系统和固件上已经投入的时间和资源,UEFI 采用了许多现有的标准。这些标准在支持特定处理器的平台上很常见。如果你想要你的平台符合 UEFI 的标准,那么你就需要实现这些标准。简单来说,UEFI 没有从头开始创造新的东西,而是把大家已经熟悉的、好用的东西整合了进来。(更多细节,你可以查看参考资料。)
  2. 系统分区:系统分区就像是一个特殊的区域,它有一个特别的文件系统。这个区域可以让不同的公司或组织安全地共享数据,同时满足不同的需求。有了这个系统分区,我们可以在不增加太多额外存储空间需求的情况下,让平台变得更加强大和灵活。
  3. 启动服务:启动服务就像是在启动电脑时提供的一些工具和接口,它们可以帮助我们更好地使用设备和系统功能。这些服务通过“句柄”和“协议”来与设备交互,这样我们就可以更容易地使用现有的 BIOS 代码,而不需要担心具体的实现细节。
  4. 运行时服务:这些服务是在电脑正常运行时提供的。它们确保操作系统可以轻松地访问和使用平台的基本硬件资源。这些服务被设计成非常基础且必要的,以确保操作系统的稳定运行。

下面的图表展示了 UEFI 的主要部分,以及它们与平台硬件和操作系统软件之间的关系。

Image

本图展示了符合 UEFI 规范的系统各组件之间的交互,这些组件用于完成平台和操作系统的启动。

平台固件能够从系统分区中获取操作系统加载程序映像。该规范支持多种大容量存储设备类型,包括磁盘、CD-ROM 和 DVD,以及通过网络进行远程启动。通过可扩展的协议接口,可以添加其他启动媒体类型。

一旦启动,操作系统加载程序将继续引导完整的操作系统。

Image

第一段:UEFI 让平台固件变得更加强大,方法是通过加载 UEFI 驱动程序和应用程序。一旦这些驱动程序和应用程序被加载,它们就可以使用 UEFI 提供的所有运行时和启动服务。这就像给你的电脑平台固件增加了很多新功能,而这些新功能都是按照 UEFI 的规则来运行的。你可以看看上面的启动顺序图,它展示了这一切是如何工作的。

第二段:UEFI 还做了一件很酷的事情,它把操作系统加载程序和平台固件的启动菜单合并成了一个统一的平台固件菜单。这样,你就可以在这个菜单里选择任何支持 UEFI 启动服务的启动介质上的任何分区上的 UEFI 操作系统加载程序。UEFI 操作系统加载程序还可以在用户界面上显示多个选项,让你有更多的选择。而且,如果你还想用老式的启动方式(比如从 A 盘或 C 盘启动),UEFI 也支持在平台固件启动菜单中加入这些选项。

第三段:UEFI 支持从包含 UEFI 操作系统加载程序或 UEFI 定义的系统分区的介质启动。如果你想从硬盘这样的块设备启动,那么 UEFI 要求必须有一个 UEFI 定义的系统分区。不过,UEFI 并不会改变分区的第一个扇区,这意味着你可以创建一种既能在老式架构上启动,又能在 UEFI 平台上启动的介质。这样,无论你的电脑支持哪种启动方式,你都可以轻松地使用它。

都到这里了,那就再好好多聊聊启动。

UEFI 启动

Image

UEFI 包含六个主要的启动步骤,这些步骤在平台的启动和初始化过程中都扮演着至关重要的角色。所有这些步骤加在一起,我们通常称之为“平台初始化”(Platform Initialization,简称 PI)。

下面我会简要介绍每个阶段,希望能帮助您对这个过程有一个基本的了解。

DXE 和 RT 这两个阶段,对于初学者比较重要。

非常抱歉,我之前的翻译中可能存在一些不够准确的地方。让我再次尝试,确保每个阶段的描述都更加准确:

安全阶段(SEC)这是 UEFI 启动流程的首要阶段,主要用于:初始化一个临时的内存存储区域,作为系统信任链的起点,并向 Pre-EFI 初始化(PEI)阶段提供必要的信息。这个信任链的起点确保了在平台初始化(PI)过程中执行的任何代码都经过加密验证(即数字签名),从而建立一个“安全启动”的环境。

Pre-EFI 初始化阶段(PEI)这是启动流程的第二阶段,它仅利用 CPU 当前的资源来调度 Pre-EFI 初始化模块(PEIM)。这些模块负责执行关键的启动操作初始化,如内存初始化,同时也允许将控制权传递给驱动程序执行环境(DXE)。

驱动程序执行环境(DXE)在 DXE 阶段,系统的大部分初始化工作都会发生。在 PEI 阶段,DXE 操作所需的内存已经被分配和初始化。当控制权传递给 DXE 时,DXE 调度器会被激活。调度器负责加载和执行硬件驱动程序、运行时服务和任何操作系统启动所需的启动服务。

启动设备选择(BDS)一旦 DXE 调度器完成了所有 DXE 驱动程序的执行,控制权就会传递给 BDS。这个阶段负责初始化控制台设备和任何剩余的必需设备。然后,它会加载并执行选定的启动项,为瞬态系统加载(TSL)阶段做准备。

瞬态系统加载(TSL)在这个阶段,PI 流程处于启动设备选择和将控制权移交给主操作系统之间的过渡阶段。此时,可能会调用一个应用程序(如 UEFI shell),或者(更常见的是)运行一个引导加载程序来准备最终的操作系统环境。引导加载程序通常负责通过调用 ExitBootServices()来终止 UEFI 启动服务。但是,操作系统本身也可以执行这一操作,比如带有 CONFIG_EFI_STUB 的 Linux 内核。

运行时(RT)这是最后的阶段,也是操作系统接管系统的时刻。尽管此时 UEFI 的启动服务已经不再可用,但 UEFI 的运行时服务仍然保留给操作系统使用,例如用于查询和写入 NVRAM 中的变量。

系统管理模式(SMM)SMM 是一个与运行时阶段分开存在的模式,它可以在 SMI(系统管理中断)被触发时进入。然而,在这个介绍中,我们不会深入讨论 SMM。

UEFI 启动 Flow (Windos)

Image

以下是 Windows 计算机启动的顺序阶段:

  1. 预启动(PreBoot)

计算机的固件启动加电自检(POST),并加载固件设置。当检测到有效的系统磁盘时,此预启动过程结束。固件读取主引导记录(MBR),然后启动 Windows 启动管理器。

  1. Windows 启动管理器

Windows 启动管理器在 Windows 启动分区上查找并启动 Windows 加载程序(Winload.exe)。

  1. Windows 操作系统加载程序

加载启动 Windows 内核所必需的基本驱动程序,然后内核开始运行。

  1. Windows NT 操作系统内核

内核将系统注册表配置单元和标记为 BOOT_START 的其他驱动程序加载到内存中。

内核将控制权传递给会话管理器进程(Smss.exe),该进程初始化系统会话,并加载和启动未标记为 BOOT_START 的设备和驱动程序。

Image

从内核(ntoskrnl.exe)到执行 LogonUi.exe(提示用户交互的进程)的 Windows 启动过程的简化版本。它被分为五个步骤。

  1. 加载操作系统内核
  2. 初始化内核
  3. 启动子系统
  4. 启动会话 0
  5. 启动会话 1
就不详细展开了。想了解,点个赞,下次咱们聊。

UEFI 启动 Flow (Linux)

Image你是否曾经好奇过,当你按下 Linux 机器的电源按钮时,背后发生了什么?

1.BIOS + UEFI

  • 基本输入输出系统(BIOS)或统一可扩展固件接口(UEFI)是计算机开机时首先运行的程序,负责硬件的初始化以及从选定的启动设备加载引导加载程序。

2.主引导记录(Master Boot Loader, MBR)

  • MBR 是硬盘的第一个扇区,包含了用于加载操作系统引导加载程序(如 GRUB)的指令。

MBR(主引导记录)是硬盘的初始(主要)扇区,它标识了操作系统的位置,以完成启动过程。

MBR 的位置取决于您的硬件,它可能位于/dev/hda 或/dev/sda。

它是一个 512 字节的映像,包含代码以及一个简短的分区表,这些都有助于加载/执行 GRUB(引导加载程序)。

3.引导加载程序(Boot Loader)

  • 引导加载程序(如 GRUB)负责加载操作系统内核到内存中。它允许用户选择启动哪个操作系统(如果安装了多个的话)。

Linux 有多个引导加载程序,其中最常见的是 GRUB 和 LILO,而 GRUB2 是最新版本之一。

当你启动计算机时,通常首先看到的是 GRand Unified Boot loader(GRUB)。

它由一个简单的菜单组成,该菜单使用键盘显示选项,以便你选择要启动的内核(如果你安装了多个内核映像)。

在双系统启动时,GRUB2 允许你选择要启动的操作系统。

Image

4.内核(Kernel)

  • 内核是操作系统的核心,负责管理硬件、提供基本服务(如进程调度、内存管理等),并作为用户程序与硬件之间的桥梁。

Image内核完全控制你系统中的一切,因此被称为操作系统的核心。

内核是自解压的,并以压缩格式存储以节省空间。

一旦选定的内核被加载到内存中并开始执行,它会在执行任何有用任务之前先解压自己。

一旦由引导加载程序加载,内核会挂载根文件系统并初始化/sbin/init 程序,该程序通常被称为 init。

5.初始 RAM 磁盘-initramfs 镜像

  • initramfs 是一个在内核启动过程中被挂载为根文件系统的临时内存文件系统。它包含了启动过程中内核所需的驱动程序和脚本。

初始 RAM 磁盘是一个初始/临时的根文件系统,它在真正的根文件系统可用之前被挂载。

这个 initramfs 映像嵌入在内核中,并包含挂载真正根文件系统所需的最小二进制文件、模块和程序。

6./sbin/init(也称为 init)[父进程]

  • init 是系统启动后运行的第一个用户空间程序,它是所有其他用户空间进程的父进程。它负责启动系统上的其他进程,并根据配置文件(如/etc/inittab 或 systemd 的配置)设置运行级别。

一旦加载,init 是内核首先执行的命令之一。

这个程序管理剩余的启动过程,并为用户设置环境。

基本上,在这个阶段,系统会执行在系统初始化期间所需的一切操作:检查文件系统、配置时钟、初始化串行端口等。

除了启动系统外,init 命令还有助于保持系统正常运行并正确关闭系统。

7.使用 Getty 的命令行界面

  • Getty 是一个用于打开文本登录会话的程序。在系统启动后,它会为每个终端或虚拟控制台启动一个登录会话。

Getty 是“get tty”(tty-电传打字机)的缩写,它是一个在主机上运行的 UNIX 程序,用于管理物理或虚拟终端。

Getty 会打开 TTY 行,设置它们的模式,打印登录提示符,获取用户名,然后为用户启动登录过程。

之后,用户在通过身份验证后可以开始使用系统。

8.systemd

  • systemd 是现代 Linux 系统上的系统和服务管理器,负责初始化系统、管理系统服务、启动守护进程等。它取代了传统的 init 系统,并提供了更丰富的功能和更好的性能。

上述提到的顺序启动方法相当传统,属于 UNIX 的 System V 变体,之后发生了用 systemd 替代 systemv 这一有争议的事件。

一方面,SysVinit(传统的 init 系统-System V)遵循顺序过程;另一方面,systemd 则利用了现代多处理器/多核计算机的并行处理能力。

注意:systemd 在加载后由内核初始化,之后 systemd 启动所需的依赖项并处理其余部分。

systemd 通过同时/并行启动多个进程来简化启动过程并缩短启动时间。

9.X Windows 系统

  • X Windows 系统(现在通常被称为 X.org Server)是 Linux 上广泛使用的图形服务器,它负责显示图形用户界面(GUI)。在 X Windows 系统启动后,用户可以运行图形应用程序,并通过鼠标和键盘与系统进行交互。

X Windows 系统是一个开源的客户端-服务器系统,它实现了窗口化的图形用户界面(GUI)。

它也被称为 X;它为 GUI 环境提供了基本结构,包括在显示设备上绘制和移动窗口的能力,以及与鼠标和键盘通信的能力。

Linux 的启动过程非常灵活且不断改进,支持广泛的处理器和硬件平台。上述列出的所有内容并不一定完全准确地描述了您机器的启动过程;有些阶段甚至可以通过一些调整来跳过。

到这里,你说我们这搞安全的不聊几句关于安全启动的,好像说不过去。

UEFI 安全启动

安全启动、Windows 与密钥管理

UEFI(统一可扩展固件接口)规范核心定义了一个称为安全启动的固件执行认证流程。作为行业标准,安全启动详细规定了平台固件如何管理证书、验证固件,以及操作系统如何与此验证过程进行交互。

安全启动基于公钥基础设施(PKI)流程,在允许任何模块执行前,先对其进行严格认证。这些模块广泛包括固件驱动程序、选项 ROM、磁盘上的 UEFI 驱动程序、UEFI 应用程序或 UEFI 引导加载程序。通过执行前的镜像认证机制,安全启动有效降低了如 rootkit 等预启动恶意软件攻击的风险。在 Windows 8 及更高版本中,微软依赖于 UEFI 安全启动作为其可信启动安全架构的关键组成部分,旨在为客户提升平台安全性。

对于 Windows 8 及更高版本的客户端 PC,以及 Windows Server 2016,安全启动是强制要求的,这一规定明确体现在 Windows 硬件兼容性要求中。

安全启动流程的工作原理简述如下(如图 1 所示):

  1. 固件启动组件:固件首先验证操作系统加载程序(如 Windows 或其他受信任的操作系统)的可信度。
  2. Windows 启动组件:包括 BootMgr、WinLoad 及 Windows 内核启动过程。这些组件会逐一验证各自组件的签名。任何未通过验证的组件将被阻止加载,并触发安全启动修复机制。
  3. 防病毒与反恶意软件软件初始化:此阶段会检查这些软件是否拥有微软颁发的特殊签名,以确保其为受信任的关键启动驱动程序,并在启动过程中尽早启动。
  4. 关键启动驱动程序初始化:WinLoad 在执行安全启动验证时,会检查所有关键启动驱动程序的签名。
  5. 其他操作系统初始化
  6. Windows 登录屏幕

Image

UEFI 安全启动的实施是微软自 Windows 8.1 以来引入的可信启动架构的重要一环。随着恶意软件漏洞利用技术的不断发展,将启动路径作为首选攻击向量的趋势日益明显。

由于恶意软件能够阻止防病毒产品完全加载,从而使其失效,因此这类攻击尤为难以防范。然而,通过 Windows 可信启动架构及其与安全启动共同建立的信任根,客户可以确保在操作系统本身加载之前,仅有经过签名和认证的“已知良好”代码及引导加载程序能够执行,从而有效防止启动路径中的恶意代码执行。

UEFI 的资料

最后分享一点资料。资料太多,反而会选择困难症状,所以我就各推荐一个吧,用于系统学习、小部分了解、以及实际 操作。

文档

博客

  • 知乎:老狼

实操

Image英特尔最初发布了原始 EFI 规范的开源实现,即 EFI 开发工具包(EDK)。在 UEFI 和 PI 的开发过程中,这个开源项目继续发展为 EDK2。该项目的主要目标是针对固件开发人员开发、测试和调试 UEFI 驱动程序、可选 ROM 和应用程序。

推荐的开发工具的简短列表:

  • EDK2

首先是 EDK2 项目,它被描述为“一个现代的、功能丰富的、跨平台的固件开发环境,用于[www.uefi.org]的UEFI和PI规范。”EDK2项目由许多同样为UEFI规范做出贡献的同一批人(以及社区志愿者)开发和维护。

这非常有帮助,因为 EDK2 保证包含最新的 UEFI 协议(假设您使用的是主分支)。除此之外,还有无数高质量的项目供您参考。一个例子是开放虚拟机固件(OVMF)。这是一个旨在为虚拟机提供 UEFI 支持的项目,它的文档非常齐全。

EDK2 的一个主要缺点是第一次设置构建环境的过程——这是一个漫长而艰巨的过程,即使他们有“开始使用 EDK2”指南尽可能简化这个过程,对于新手来说仍然可能感到困惑。

  • VisualUefi

VisualUefi 项目旨在允许在 Visual Studio 内部进行 EDK2 开发。我们建议您开始开发时,使用 EDK2 命令行中的构建工具而不是这个项目,以让您熟悉平台。

此外,VisualUefi 提供的头文件和库是完整 EDK2 库的一个子集,因此您可能会发现您需要的不是所有东西都容易获取。然而,与 EDK2 相比,它的设置要简单得多,因此通常受到热衷于使用 Visual Studio 的用户的青睐。

  • 调试

关于调试,有几个选项可供您选择,每个选项都有其优缺点。这些将在下面列出,您最喜欢哪一个由您自己决定。在本系列的第二部分中,我们将向您展示如何调试一个示例驱动程序,所以在此之前,您可能想要安装所有这些(或者一个也不安装!)以帮助您做出明智的决定:+ QEMU - 一个多平台模拟器(尽管在 Linux 上最好),由于它是一个模拟器而不是虚拟机,因此提供了最好的调试设施。它的设置相当复杂,而且与它的同类相比,它也相当慢。+ VirtualBox - 一个好的多平台解决方案,除了由于非易失性随机存取存储器(NVRAM)仿真相当差劲而遭受内存丢失的问题。+ VMware - 提供良好的性能和正确工作的 NVRAM 仿真。如果客户机和主机都是 Windows,它与 WinDbg 配合使用进行 TSL 和 RT 阶段的调试效果非常好。


写长文的缺点就是,有时候一个点聊的尽兴了,那部分就容易变得臃肿。不过都知道缺点了,改正应该就不远了。如有错误麻烦评论区纠正一下。

AnyWay,下次聊!

END

作者:Hcoco
文章来源:TrustZone

推荐阅读

更多物联网安全,PSA 等技术干货请关注平台安全架构(PSA)专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入PSA 技术交流群,请备注研究方向。
推荐阅读
关注数
4574
内容数
210
Arm发布的PSA旨在为物联网安全提供一套全面的安全指导方针,使从芯片制造商到设备开发商等价值链中的每位成员都能成功实现安全运行。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息