创建 flat 格式磁盘——OS 开发最常用的镜像格式手把手
flat 格式是什么
flat 格式是最简单的磁盘镜像——就是一个线性的二进制文件,没有头部、没有元数据、没有描述信息。文件大小 = 磁盘容量,文件的第 N 字节就是磁盘的第 N 字节。
这种"极致简单"带来的代价是:没有元数据就不知道 C/H/S 几何参数——Bochs 无法自动推断,必须在 bochsrc 里手动指定 cylinders / heads / spt。
创建步骤
第一步:用 bximage 创建
bximage -q -create -mode flat -size 60M -filename hd60M.img
输出(关键是 CHS 三参数):
CHS=121/16/63 (cylinders/heads/sectors)
total sectors = 122208
第二步:把 CHS 抄到 bochsrc
ata0-master: type=disk, path="hd60M.img", mode=flat, cylinders=121, heads=16, spt=63
第三步:可选——写入引导扇区
OS 开发需要在磁盘首扇区写入 Bootloader。有两种方式:
方式 A:用 dd 写入
Linux/macOS:
dd if=bootloader.bin of=hd60M.img bs=512 count=1 conv=notrunc
bs=512 count=1:只写 512 字节(一个扇区)conv=notrunc:不要截断文件(否则 flat 磁盘文件会被缩小!)
Windows 上可以用 HxD、OSFMount 或在 Bochs 里用调试器写。
方式 B:在 bochsdbg 里用调试器写入
bochs:1> w /512bx 0x7c00 0x00 # 先清空
bochs:2> # 或者直接用 asm / db 命令汇编引导代码进去
对于 512 字节的 Bootloader,直接在调试器里逐字节写也是可行的——MIT 6.828 就这么教。
flat 磁盘的容量和 CHS 关系
总扇区数计算公式:
总扇区数 = cylinders × heads × spt
bximage 输出总扇区数和 CHS 值,两者应该相等或接近。如果 bximage 输出的 CHS 和你抄的 bochsrc 对不上,BIOS 枚举磁盘后报告的容量会和真实容量有差异。
标准 CHS 参数速查:
| 磁盘大小 | cylinders | heads | spt | 总扇区数 |
|---|---|---|---|---|
| 10 MB | 306 | 4 | 17 | 20808 |
| 20 MB | 612 | 4 | 17 | 41616 |
| 30 MB | 615 | 6 | 17 | 62730 |
| 40 MB | 977 | 5 | 17 | 83045 |
| 60 MB | 121 | 16 | 63 | 122208 |
| 80 MB | 162 | 16 | 63 | 163296 |
| 100 MB | 1040 | 16 | 63 | 1048320 |
| 1 GB | 521 | 255 | 63 | 8384385 |
也可以算:文件大小(字节)÷ 512 = 总扇区数。然后找一组合理的 CHS(让乘积最接近总扇区数且不超过)。
flat 磁盘可以被其他工具读写
因为 flat 格式就是原始数据,任何能读块设备的工具都能直接读写它:
- Linux loop 设备:
losetup /dev/loop0 hd60M.img→mount /dev/loop0 /mnt/disk - OSFMount(Windows):直接挂载 flat 磁盘
- qemu-img:
qemu-img convert hd60M.img -O raw hd60M-qemu.img - Bochs 调试器:
xp 0x7c00直接看引导扇区
这是 flat 格式最大的优势——没有任何锁定或专有格式,想怎么处理就怎么处理。
常见问题
bochsrc 忘记写 C/H/S
Bochs 会报:
ata0-0: cannot have zero cylinders, heads, or sectors/tracks
原因:flat 格式无法自动推断几何参数。加上就行:
ata0-master: type=disk, path="hd60M.img", mode=flat, cylinders=121, heads=16, spt=63
dd 写入后磁盘文件缩小了
dd 默认会截断输出文件(of=hd60M.img 时)。加 conv=notrunc 就能防止:
dd if=bootloader.bin of=hd60M.img bs=512 count=1 conv=notrunc
flat 磁盘文件大小必须和 bochsrc 里的 C/H/S 匹配——文件缩小了,BIOS 报告的磁盘就会比实际小。
想用 flat 磁盘但不想手动算 C/H/S
改用 sparse 格式——它带元数据能自动推断:
bximage -q -create -mode sparse -size 60M -filename hd60M.img
# bochsrc 里不需要写 C/H/S
ata0-master: type=disk, path="hd60M.img", mode=sparse
但 OS 开发场景建议坚持 flat——学习价值更大(你必须理解 BIOS 枚举磁盘的整个过程)。