导引:点亮什么、为什么需要它
mini kernel 从 004 诞生起,它的终极使命就一件事:把那个功能完整的 big kernel 从磁盘弄进内存、交权给它。前面几章我们给它配齐了输出、内存、异常——现在,是时候造"读盘"和"解析内核镜像"这两件家伙了。这一章我们写出 ATA PIO 磁盘驱动和 ELF64 加载器,把它们串成一条加载流水线。不过有个诚实的边界:big kernel 本身要到 001 才登场,所以这一章我们用两个 demo 验证这套流水线能干活,真正的加载+跳转留给下一章。
这一章我们要点亮什么
我们要造两样东西,再合成第三样。
一样是 ATA PIO 磁盘驱动:让 mini kernel 能直接对硬盘控制器下"读这几个扇区"的命令,把原始字节读进内存。PIO(Programmed I/O)意味着 CPU 亲自一个字一个字地从数据端口搬数据,不用 DMA、不用中断——最简单直接的法子。
另一样是 ELF64 加载器:内核镜像是标准的 ELF 可执行文件,带头部和若干"可加载段"(PT_LOAD)。加载器要读懂这个头部,把每个段从镜像里的位置搬到它该去的物理地址,多出来的 BSS 部分清零。
第三样是把它们串起来的 big_kernel_loader:先让 ATA 把整份内核镜像读到一个中转缓冲区(staging),再让 ELF 加载器解析它、把段各就各位,最后吐出入口地址。调用者拿到入口地址,理论上 jmp 过去就完成了接力。
但这一章 main 不会真去 jmp——因为 big kernel 还不存在。main 只用两个 demo 验证这套家伙是好的:读主引导扇区(MBR)看它的 0xAA55 签名对不对、读 mini kernel 所在的 LBA 16 试试 ELF 头解析(预期失败,因为 mini kernel 是裸二进制不是 ELF)。看到 MBR 签名 VALID、ELF 解析能正确判出"这不是 ELF",就说明读盘和解析这两条路都通了。
为什么现在需要它
mini kernel 自己其实不需要读盘——它已经被 bootloader 读进内存了。它会读盘,完全是为了伺候 big kernel。整个 004–008 这一段,mini kernel 的角色就是个"二传手":bootloader 把它弄起来,它把自己收拾利索(输出、内存、异常),然后要把 big kernel 也弄起来、交权。这最后一步"弄起来",就要求它能读磁盘、能解析 ELF。
为什么现在写、而不是等到 009 big kernel 出现了再写?因为这套加载流水线本身是个独立、可测的子系统。ATA 驱动的命令编码、ELF 头的字段解析,全是和"具体哪个内核"无关的纯逻辑,正好用 001 搭好的双轨测试狠狠磨一遍(host 单测验编码、QEMU 验真读盘)。等 009 big kernel 真的到来,这套已经验证过的流水线直接 load_big_kernel() 一调用就行,不用在"内核本身还没稳"的时候同时调试加载器。先把工具打牢,再上战场。
外部依据:OSDev 的 ATA PIO Mode 页详细描述了 ATA 控制器的 I/O 端口、状态位(BSY/DRQ/RDY/ERR)、LBA28/LBA48 寻址与 PIO 读扇区的时序(含 400ns 延时约定);ELF 页与 TIS ELF 规范定义了 Elf64_Ehdr/Elf64_Phdr 字段和 PT_LOAD 段语义。