Bare-metal 与程序员的约定

Bare-metal 与厂商的约定

  • CPU Reset 后的状态 (寄存器值)
    • 厂商自由处理这个地址上的值
    • Memory-mapped I/O

厂商为操作系统开发者提供 Firmware

  • 管理硬件和系统配置
  • 把存储设备上的代码加载到内存
    • 例如存储介质上的第二级 loader (加载器)
    • 或者直接加载操作系统 (嵌入式系统)

x86 Family: CPU Reset

CPU Reset (Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A/3B)

  • 寄存器会有确定的初始状态
    • EIP = 0x0000fff0
    • CR0 = 0x60000010
      • 处理器处于 16-bit 模式
    • EFLAGS = 0x00000002
      • Interrupt disabled
  • TFM (5,000 页+)
    • 最需要的 Volume 3A 只有 ~400 页 (我们更需要 AI)

其他平台上的 CPU Reset

Reset 后处理器都从固定地址 (Reset Vector) 启动

  • MIPS: 0xbfc00000
    • Specification 规定
  • ARM: 0x00000000
    • Specification 规定
    • 允许配置 Reset Vector Base Address Register
  • RISC-V: Implementation defined
    • 给厂商最大程度的自由

Firmware 负责加载操作系统

  • 开发板:直接把加载器写入 ROM
  • QEMU:-kernel 可以绕过 Firmware 直接加载内核 (RTFM)

x86 CPU Reset 之后:到底执行了什么?

状态机 (初始状态) 开始执行

  • 从 PC 取指令、译码、执行……
  • 开始执行厂商 “安排好” 的 Firmware 代码
    • x86 Reset Vector 是一条向 Firmware 跳转的 jmp 指令

Firmware: BIOS vs. UEFI

  • 一个小 “操作系统”
    • 管理、配置硬件;加载操作系统
  • Legacy BIOS (Basic I/O System)
    • IBM PC 所有设备/BIOS 中断是有 specification 的 (成就了 “兼容机”)
  • UEFI (Unified Extensible Firmware Interface)

为什么需要 UEFI?

今天的 Firmware 面临麻烦得多的硬件:

  • 指纹锁、USB 转接器上的 Linux-to-Go 优盘、山寨网卡上的 PXE 网络启动、USB 蓝牙转接器连接的蓝牙键盘、……
    • 这些设备都需要 “驱动程序” 才能访问
    • 解决 BIOS 逐渐碎片化的问题

回到 Legacy BIOS: 约定

BIOS 提供机制,将程序员的代码载入内存

  • Legacy BIOS 把第一个可引导设备的第一个 512 字节加载到物理内存的 7c00 位置
    • 此时处理器处于 16-bit 模式
    • 规定 CS:IP = 0x7c00, (R[CS] << 4) | R[IP] == 0x7c00
      • 可能性1:CS = 0x07c0, IP = 0
      • 可能性2:CS = 0, IP = 0x7c00
    • 其他没有任何约束

虽然最多只有 446 字节代码 (64B 分区表 + 2B 标识)

  • 但控制权已经回到程序员手中了!
  • 你甚至可以让 ChatGPT 给你写一个 Hello World
    • 当然,他是抄作业的 (而且是有些小问题的)

能不能看一下代码?

Talk is cheap. Show me the code. ——Linus Torvalds

有没有可能我们真的去看从 CPU Reset 以后每一条指令的执行?


计算机系统公理:你想到的就一定有人做到

  • 模拟方案:QEMU
  • 真机方案:JTAG (Joint Test Action Group) debugger
    • 一系列 (物理) 调试寄存器,可以实现 gdb 接口 (!!!)

️🌶️ UEFI 上的操作系统加载

标准化的加载流程

  • 磁盘必须按 GPT (GUID Partition Table) 方式格式化
  • 预留一个 FAT32 分区 (lsblk/fdisk 可以看到)
  • Firmware 能够加载任意大小的 PE 可执行文件 .efi
    • 没有 legacy boot 512 字节限制
    • EFI 应用可以返回 firmware

更好的程序支持

  • 设备驱动框架
  • 更多的功能,例如 Secure Boot,只能启动 “信任” 的操作系统

小插曲:Hacking Firmware (1998)

Firmware 通常是只读的 (当然……)

  • Intel 430TX (Pentium) 芯片组允许写入 Flash ROM
    • 只要向 Flash BIOS 写入特定序列,Flash ROM 就变为可写
      • 留给 Firmware 更新的通道
    • 要得到这个序列其实并不困难
      • 似乎文档里就有 🤔 Boom……

CIH 病毒的作者陈盈豪被逮捕,但并未被定罪