B03 — The Complete Boot Flow: From Pressing Power to Handing Control to the Kernel

Key Insight: Every boot is a precision relay race. Every handoff must be flawless.


Overview of the Complete Boot Flow

After pressing the power button, the computer goes through a series of stages before finally handing control to the OS kernel:

Bash
完整的 Boot 流程:

[硬件上电] → CPU Reset → BIOS/UEFI → Bootloader → Kernel

详细阶段:
1. 硬件上电(Power-On)
2. CPU 复位(Reset Vector)
3. BIOS/UEFI 初始化(PEI)
4. 固件驱动和内存初始化(DXE)
5. 系统启动设备选择(BDS)
6. Bootloader 加载(GRUB/SYSTEMD-BOOT)
7. 内核解压和执行(Linux Kernel)

Phase 1: Power-On and CPU Reset

Bash
按下电源键后:

1. 电源启动 → 供电稳定(约 100~500ms)
2. VR(Voltage Regulator)输出稳定电压
3. CPU 的 RESET# 引脚被释放
4. CPU 内部寄存器初始化(x86: CR3, CR4, EFLAGS = 05. CPU 开始执行第一条指令

第一条指令在哪里:

x86 架构:
  CS:IP = 0xF000:0xFFF0(CS = 0xF000, IP = 0xFFF0)
  这个地址在 BIOS ROM 里
  → CPU 执行的第一条指令是 JMP 到 BIOS 入口点

ARM 架构:
  PC = 0x00000000(复位向量)
  在 ARM 设计中,这个地址通常映射到 BootROM(SoC 内置)
  → 第一条指令可能是固化在 ROM 中的 Bootloader

Phase 2: BIOS/UEFI Initialization (PEI)

Bash
UEFI 的 Boot 阶段(UEFI PI Architecture):

PEI(Pre-EFI Initialization):
  - CPU 微码加载(Microcode Patch)
  - 最小硬件初始化(栈、指针)
  - 内存初始化(读取 SPD,开始 Training)
  - 固件卷(FV)发现和解密

SEC(Security)→ PEI→ DXE→ BDS→ TSL→ RT→ AL:

  SEC(Security):CPU 初始化的第一步,信任根
  PEI:内存初始化,固件卷加载
  DXE(Driver Execution Environment):设备驱动初始化,PCIe 枚举
  BDS(Boot Device Selection):选择启动设备
  TSL(Transient System Load):加载 Short Boot Loader
  RT(Runtime):操作系统运行
  AL(After Life):关机后清理

Phase 3: Memory Initialization (SPD Read + Training)

Bash
BIOS 内存初始化(在 PEI 阶段):

1. I2C 总线扫描
   → 探测每个通道的 DIMM(地址 0x50/0x51/0x52)
   → 读取 SPD,存储容量/频率/时序

2. 内存控制器配置
   → 基于 SPD 配置时序(CL/tRCD/tRP/tRAS)
   → 配置频率(优先 XMP,否则 JEDEC)
   → 配置电压(1.2V 或 1.35V)

3. Memory Training(内存培训)
   - Write Leveling:校准 DQS 和 CK 的相位
   - Read Gate Training:找到读数据的最佳采样点
   - Write DQ Calibration:校准每个 DQ 引脚
   - Per-DQS Training:精细校准每个 DQS

4. 内存测试
   - BIOS 写一小段测试数据,读出验证
   - 如果失败,显示"Memory error"并停机

5. 构建 e820 表
   → 已知物理内存分布
   → 加上 MMIO 区域
   → 操作系统将收到这份完整的内存地图

Phase 4: Bootloader Loading

Bash
BIOS 找到启动设备后,执行 Bootloader:

1. BIOS 遍历启动设备顺序(UEFI Boot Order)
   → 检查第一个设备的 Bootable Flag
   → 如果是 MBR:读取 0扇区(512B),跳转到 Bootloader 代码
   → 如果是 GPT/UEFI:读取 EFI 分区,加载 .efi 文件

2. GRUB(Grand Unified Bootloader)加载:
   阶段 1.5(可选):读取 MBR 后的扇区(GRUB Stage 1.5)
   阶段 2:加载 GRUB 配置文件(/boot/grub/grub.cfg)
   → 显示启动菜单(Kernel 选择、恢复模式等)
   → 用户选择后,加载 Kernel

3. UEFI 直接启动(无 GRUB):
   → UEFI Shell 或 SYSTEMD-BOOT
   → 从 ESP(EFI System Partition)读取 .efi 文件
   → 直接跳转到 Kernel(跳过 GRUB)

Phase 5: Kernel Loading and Execution

Bash
GRUB 加载 Linux Kernel 的过程:

1. GRUB 读取 vmlinuz(压缩 Kernel 镜像)
2. GRUB 读取 initramfs(初始 RAM 文件系统)
3. GRUB 把控制权交给 Kernel

Kernel 启动(arch/x86/boot/):

  0x100000:Kernel 代码开始(解压前的位置)
  解压:从 0x100000 解压到更高的地址

  arch/x86/boot/header.S:
    入口点:start_of_setup
    → 设置临时 GDT(Global Descriptor Table)
    → 设置临时 IDT(Interrupt Descriptor Table)
    → 切换到 32-bit 保护模式(CR0.PE=1)
    → 跳转到 32-bit 入口点(compressed/head.o)

  arch/x86/boot/compressed/:
    decompress: 解压 vmlinuz
    → 调用 startup_32 或 startup_64

  跳转到真正内核入口:
    → 内核入口点:startup_64(x86_64)
    → 内存管理初始化(paging_setup)
    → 系统数据结构初始化(kmem_cache)

Memory Initialization During Kernel Boot

Bash
Linux Kernel 的内存初始化顺序(startup_64):

1. early_fixmap_init():
   - 建立早期固定映射(用于 early console, ACPI 等)

2. setup_arch():
   - 读取 e820(从 BIOS 传递的参数)
   - 调用 e820__memory_setup() → 构建内核内存映射
   - 调用 e820__reserve_memory() → 保留特殊区域

3. paging_init():
   - 初始化页表(PGDIR)
   - 开启分页机制(CR0.PG=1)
   - 虚拟地址空间开始工作

4. mem_init():
   - 释放未使用的内存(bootmem → buddy system)
   - 计算实际可用内存
   - 输出:Memory: 32768MB available

5. kmem_cache_init():
   - SLAB/SLUB 分配器初始化
   - 用于内核对象分配

6. 启动用户空间:
   → init 进程(PID 1)开始执行
   → 用户空间程序开始运行

Summary

  • Complete Boot Flow: Power-on → CPU Reset (0xF000:0xFFF0) → BIOS/UEFI → Bootloader (GRUB) → Kernel
  • BIOS Phases: SEC → PEI (SPD read + training) → DXE (drivers) → BDS (boot device selection)
  • Memory Initialization: Read SPD → Configure controller → Write Leveling / Read Gate Training → Build e820 table
  • Bootloader: MBR read → GRUB Stage 1.5/2 → load vmlinuz + initramfs
  • Kernel Boot: Decompress → setup_arch(e820) → paging_init (enable paging) → mem_init (buddy system) → kmem_cache

Next (B04): After CPU reset, how does it switch from Real Mode to Protected Mode? GDT table, segment selectors, and CR0 register setup.


Last modified: 2024年10月9日

Author

Comments

Write a Reply or Comment

Your email address will not be published.