# 操作系统引导


<!--more-->


## 传统BIOS
{{< timeline animation=true placement=top >}}
events:
  - timestamp: "阶段 01：加电复位"
    content: |
      按下电源后，CPU 复位，寄存器进入初始状态。
      从 CPU 视角看：CPU 马上要去固定位置取第一条指令。

  - timestamp: "阶段 02：CPU 执行 BIOS 固件代码"
    content: |
      传统 BIOS 启动中，CPU 会从固定的复位入口开始执行。
      这个入口通常映射到主板 ROM/Flash 中的 BIOS 固件代码。

  - timestamp: "阶段 03：POST 加电自检"
    content: |
  
      它会检查 CPU、内存、显卡、键盘、磁盘控制器等硬件是否基本正常。
      此时 CPU 仍然执行 BIOS 的自检代码。

  - timestamp: "阶段 04：初始化 BIOS 中断服务和 IVT"
    content: |
      POST 完成后，BIOS 会准备传统实模式下的 BIOS 中断服务。
      
      内存低地址区域会建立中断向量表 IVT，用来保存各种 BIOS 中断服务程序的入口地址。
      
      例如 INT 13h 用于磁盘服务，INT 10h 用于显示服务。
      
      此时 CPU 仍然执行 BIOS 代码，内存中已经有 BIOS 需要的数据结构。

  - timestamp: "阶段 05：读取 CMOS / BIOS 设置"
    content: |
      BIOS 会读取 CMOS 中保存的传统 BIOS 设置。
      
      例如系统时间、硬盘参数、启动顺序等。
      
      CMOS 是老式 BIOS 体系中的说法，现代 UEFI 更多使用 NVRAM 保存启动项和固件设置。

  - timestamp: "阶段 06：选择启动设备"
    content: |
      BIOS 根据启动顺序检查硬盘、U 盘、光盘或网络启动设备。
      
      如果选择的是传统硬盘启动，BIOS 会尝试读取该磁盘的第 0 号扇区。
      
      这个第 0 号扇区就是 MBR。

  - timestamp: "阶段 07：BIOS 加载 MBR 到内存"
    content: |
      BIOS 会把启动磁盘的第 0 号扇区读入内存，经典位置是 0x7C00。
      
      MBR 大小为 512 字节，主要包括三部分：
      
      1. 一小段引导代码；
      2. 磁盘分区表；
      3. 结束标志 0x55AA。
      
      此时 MBR 已经进入内存，但 CPU 还在执行 BIOS 代码。

  - timestamp: "阶段 08：BIOS 跳转到 MBR"
    content: |
      BIOS 读取 MBR 后，会跳转到 0x7C00 执行。
      
      从这一刻开始，CPU 控制权交给 MBR。
      
      更准确地说，是 CPU 的指令指针跳到了 MBR 所在的内存地址，开始执行 MBR 中的机器指令。

  - timestamp: "阶段 09：MBR 查找活动分区"
    content: |
      MBR 会检查自己携带的分区表，寻找被标记为活动分区的分区。
      
      找到活动分区后，MBR 会把该分区的第一个扇区加载到内存。
      
      这个分区的第一个扇区叫 PBR，也叫 VBR，即分区引导记录。
      
      注意：查找活动分区是 MBR 的工作，不是 PBR 的工作。

  - timestamp: "阶段 10：MBR 跳转到 PBR"
    content: |
      MBR 加载 PBR 后，会跳转到 PBR 执行。
      
      此时 CPU 执行的是 PBR 中的代码。
      
      PBR 不再检查分区表，它只负责在当前分区中寻找更高级的引导文件。

  - timestamp: "阶段 11：Windows 分支：PBR 加载 bootmgr"
    content: |
      如果是 Windows 的 Legacy BIOS 启动，PBR 会尝试在当前分区中找到 bootmgr 文件。
      
      这一步不是简单读一个固定扇区，因为 PBR 需要具备最小的文件系统识别能力。
      
      bootmgr 被加载到内存后，CPU 控制权转交给 bootmgr。

  - timestamp: "阶段 12：Windows 分支：bootmgr 加载 winload"
    content: |
      bootmgr 会读取 BCD 启动配置数据库。
      
      BCD 中保存着 Windows 启动项，例如启动哪个系统、内核路径、启动参数等。
      
      bootmgr 根据 BCD 找到 winload.exe，并把控制权交给 winload.exe。
      
      此时 CPU 执行的是 Windows 启动管理器相关代码。

  - timestamp: "阶段 13：Windows 分支：winload 加载内核"
    content: |
      winload.exe 会加载 Windows 内核 ntoskrnl.exe、HAL、启动驱动程序和必要的注册表配置。
      
      此时 Windows 内核已经被加载进内存，但还没有完全接管整个系统。
      
      CPU 仍然在执行启动加载器代码，为进入内核做准备。

  - timestamp: "阶段 14：Linux 分支：MBR/PBR 加载 GRUB 前置阶段"
    content: |
      如果是 Linux 的 Legacy BIOS 启动，MBR 或 PBR 中通常只放很小的 GRUB 前置代码。
      
      这段代码非常小，无法包含完整的文件系统驱动。
      
      它的主要任务是找到并加载 GRUB 的 core.img。

  - timestamp: "阶段 15：Linux 分支：GRUB core.img 加载完整 GRUB"
    content: |
      GRUB 的 core.img 被加载后，才具备更强的能力。
      
      它可以识别文件系统，读取 /boot/grub 中的配置文件，并显示启动菜单。
      
      此时 CPU 执行的是 GRUB 代码，GRUB 会继续加载 Linux 内核 vmlinuz 和 initramfs。

  - timestamp: "阶段 16：CPU 工作模式切换"
    content: |
      Legacy BIOS 初始环境通常是实模式。
      
      但是现代操作系统不能长期运行在实模式下，所以引导程序会在合适阶段切换 CPU 工作模式。
      
      例如 BOOTMGR、GRUB 或后续加载器会进入保护模式，64 位系统最终还会进入长模式。
      
      注意：模式切换不一定等到内核入口才发生，很多引导程序在加载内核前就已经完成了部分切换。

  - timestamp: "阶段 17：操作系统内核接管 CPU"
    content: |
      当引导程序完成内核加载和运行环境准备后，会跳转到操作系统内核入口。
      
      从这一刻开始，CPU 执行的是操作系统内核代码。
      
      内核开始初始化内存管理、进程管理、中断管理、文件系统、设备驱动等核心模块。

  - timestamp: "阶段 18：启动第一个用户态进程"
    content: |
      内核初始化完成后，会启动第一个用户态进程。
      
      Linux 中通常是 init 或 systemd。
      
      Windows 中会启动会话管理器、服务控制管理器、登录管理器等系统进程。
      
      到这里，操作系统引导结束，系统进入正常运行状态。
{{< /timeline >}}



## 现代UEFI + GPT 启动时间线
{{< timeline animation=true placement=top  >}}
events:
  - timestamp: "阶段 01：加电复位"
    content: |
      按下电源后，CPU 复位，寄存器进入初始状态。
      
      现代计算机多数采用 UEFI + GPT 启动，而不是传统 BIOS + MBR。

  - timestamp: "阶段 02：CPU 执行 UEFI 固件代码"
    content: |
      CPU 从固件入口开始执行。
      
      此时 CPU 执行的是主板 Flash 中的 UEFI 固件代码。
      
      UEFI 不依赖 MBR 中的 446 字节引导代码来启动系统。

  - timestamp: "阶段 03：SEC 阶段"
    content: |
      UEFI 启动早期会进入 SEC 阶段，也就是 Security Phase。
      
      这一阶段会建立最小运行环境。
      
      有些平台会使用 CPU Cache 作为临时内存，也就是 Cache-as-RAM。
      
      此时普通内存可能还没有完全可用，CPU 执行的是 UEFI 最早期固件代码。

  - timestamp: "阶段 04：PEI 阶段"
    content: |
      PEI 阶段负责早期硬件初始化。
      
      其中最重要的任务是初始化内存控制器和 DRAM。
      
      一旦内存初始化完成，后续固件模块和数据结构就可以被加载到真正的内存中。
      
      此时 CPU 仍然执行 UEFI 固件代码。

  - timestamp: "阶段 05：DXE 阶段"
    content: |
      DXE 阶段会加载大量 UEFI 驱动程序。
      
      例如磁盘驱动、USB 驱动、文件系统驱动、显卡输出驱动等。
      
      这一步很关键，因为 UEFI 需要能够识别 EFI 系统分区，并从 FAT 文件系统中读取 .efi 文件。
      
      此时 CPU 执行的是 UEFI DXE 驱动和固件服务代码。

  - timestamp: "阶段 06：BDS 阶段选择启动项"
    content: |
      BDS 阶段负责启动设备选择。
      
      UEFI 会读取 NVRAM 中保存的启动项，例如 BootOrder 和 Boot#### 变量。
      
      每个启动项可以指向 EFI 系统分区中的某个 .efi 文件。
      
      这一步相当于 UEFI 版本的“选择从哪个系统启动”。

  - timestamp: "阶段 07：定位 EFI 系统分区"
    content: |
      UEFI 会根据启动项找到 EFI 系统分区，也就是 ESP。
      
      ESP 通常是一个 FAT 格式的小分区，里面存放各种操作系统的 EFI 启动程序。
      
      例如 Windows、Linux、U 盘启动工具都可以在 ESP 中放置自己的 .efi 文件。
      
      此时 .efi 启动文件还没有接管 CPU，CPU 仍然执行 UEFI 固件代码。

  - timestamp: "阶段 08：Secure Boot 签名验证"
    content: |
      如果开启了 Secure Boot，UEFI 会在执行 .efi 文件之前验证它的数字签名。
      
      如果签名可信，UEFI 允许它执行。
      
      如果签名不可信，UEFI 会拒绝执行，系统可能无法继续启动。
      
      此时 CPU 仍然执行 UEFI 固件代码，操作系统内核还没有接管。

  - timestamp: "阶段 09：UEFI 加载 .efi 启动程序"
    content: |
      UEFI 会把目标 .efi 启动程序加载到内存中，然后跳转执行。
      
      Windows 常见路径是：
      \EFI\Microsoft\Boot\bootmgfw.efi
      
      Linux GRUB 常见路径可能是：
      \EFI\ubuntu\grubx64.efi
      \EFI\fedora\grubx64.efi
      
      U 盘或可移动设备常见兜底路径是：
      \EFI\BOOT\BOOTX64.EFI
      
      从这一刻开始，CPU 控制权从 UEFI 固件转交给 .efi 启动程序。

  - timestamp: "阶段 10：Windows UEFI 分支：bootmgfw.efi"
    content: |
      如果启动的是 Windows，UEFI 通常会加载 bootmgfw.efi。
      
      bootmgfw.efi 是 UEFI 模式下的 Windows Boot Manager。
      
      它会读取 BCD 启动配置数据库，判断要启动哪个 Windows 系统。
      
      此时 CPU 执行的是 Windows Boot Manager 的代码。

  - timestamp: "阶段 11：Windows UEFI 分支：winload.efi"
    content: |
      bootmgfw.efi 会加载 winload.efi。
      
      winload.efi 继续加载 Windows 内核 ntoskrnl.exe、HAL、启动驱动程序和必要的注册表配置。
      
      此时 Windows 内核已经进入内存，但还没有完全接管 CPU。

  - timestamp: "阶段 12：Linux UEFI 分支：shimx64.efi / grubx64.efi"
    content: |
      如果启动的是 Linux，UEFI 通常会加载 grubx64.efi。
      
      如果开启了 Secure Boot，常见做法是先加载 shimx64.efi，再由 shim 验证并加载 grubx64.efi。
      
      注意：UEFI 模式下的 Linux 启动不经过 MBR 和 PBR。
      
      此时 CPU 执行的是 shim 或 GRUB 的 EFI 程序代码。

  - timestamp: "阶段 13：Linux UEFI 分支：GRUB 加载内核"
    content: |
      GRUB 运行后，会读取自己的配置文件，显示启动菜单。
      
      然后 GRUB 找到 Linux 内核文件 vmlinuz 和临时根文件系统 initramfs，并把它们加载到内存中。
      
      此时内存中已经有 GRUB、Linux 内核和 initramfs。
      
      CPU 仍然执行 GRUB 代码，正在准备把控制权交给 Linux 内核。

  - timestamp: "阶段 14：ExitBootServices"
    content: |
      操作系统启动程序在准备把控制权交给内核前，会调用 UEFI 的 ExitBootServices。
      
      这表示 UEFI Boot Services 结束。
      
      从这一步开始，固件不再负责常规启动服务，操作系统准备正式接管机器。
      
      此时 CPU 即将从启动程序代码跳转到操作系统内核代码。

  - timestamp: "阶段 15：操作系统内核接管 CPU"
    content: |
      启动程序跳转到操作系统内核入口。
      
      从这一刻开始，CPU 执行的是操作系统内核代码。
      
      内核会初始化页表、调度器、中断机制、文件系统和设备驱动。
      
      此时操作系统真正开始接管整台计算机。

  - timestamp: "阶段 16：启动第一个用户态进程"
    content: |
      内核初始化完成后，系统开始进入用户态。
      
      Linux 中通常启动 init 或 systemd。
      
      Windows 中会启动会话管理器、服务控制管理器和登录相关进程。
      
      到这里，UEFI + GPT 启动流程结束，系统进入正常运行状态。
{{< /timeline >}}

---

> 作者: 房子  
> URL: https://fzcy.net/posts/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%BC%95%E5%AF%BC/  

