為什麼光盤需要使用 ISO 9660 文件系統,而不使用硬盤已有的文件系統?

因為光盤只能寫入一次,不能擦除,所以需要為光盤定製專用的文件系統 ISO 9660;
ISO 9660 規定,文件系統從第 16 個扇區開始,前 16 個扇區保留,通常每個扇區為 2048 字節;

系統啓動方式

如果是從光驅啓動:

  1. BIOS/UEFI 固件會忽略前 16 個扇區;
  2. 識別 ISO 9660 文件系統的頭,找到 El Torito Boot Catalog,這裏記錄了引導程序所在的扇區起點、大小、程序類型;

而現代傳統的光驅已經消失,取而代之的是 USB 啓動,這是一個類似於硬盤的設備,通常使用傳統的硬盤啓動方式。

如果是通過 Legacy BIOS 啓動:

  1. BIOS 固件識別 MBR 扇區的啓動代碼,加載 GRUB

如果是通過 UEFI 啓動:

  1. UEFI 固件識別 GPT 分區表
  2. 尋找 EFI 分區,從分區中加載 GRUB

以 Ubuntu 的 ISO 為例驗證 Hybrid ISO 的數據分佈

Ubuntu 的 ISO 正是集成了上述三種啓動方式,合成了 Hybrid ISO:

  1. 在第 1 個扇區寫入 MBR 啓動腳本
  2. 在第 2-64 個扇區寫入 GPT 分區,並格式化一個 FAT32 格式的 EFI 分區,用於 UEFI 固件識別加載 GRUB
  3. 在第 64 個扇區開始,是一個 ISO 9660 格式的文件系統,並在元數據中記錄了 El Torito:這是一個 EFI 鏡像,起始扇區與大小;UEFI 固件可以通過加載這個 EFI 鏡像,達到類似第 2 點的效果。

通過 fdisk 查看 Ubuntu ISO 的分區,可以看到其使用 GPT 分區別,有三個分區:

$ fdisk ubuntu-25.04-desktop-amd64.iso
Command (m for help): p

Disk ubuntu-25.04-desktop-amd64.iso: 5.85 GiB, 6278520832 bytes, 12262736 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: D18ABFB2-FF4D-49E5-9075-9C1556AA882C

Device                             Start      End  Sectors  Size Type
ubuntu-25.04-desktop-amd64.iso1       64 12251911 12251848  5.8G Microsoft basic data
ubuntu-25.04-desktop-amd64.iso2 12251912 12262071    10160    5M EFI System
ubuntu-25.04-desktop-amd64.iso3 12262072 12262671      600  300K Microsoft basic data

解析第一個分區,是一個 ISO 9660 文件系統:

$ dd if=ubuntu-25.04-desktop-amd64.iso bs=512 skip=64 | file -
/dev/stdin: ISO 9660 CD-ROM filesystem data 'Ubuntu 25.04 amd64'

解析第二個分區,是一個 FAT32 文件系統:

$ dd if=ubuntu-25.04-desktop-amd64.iso bs=512 skip=12251912 | file -
/dev/stdin: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, reserved sectors 4, root entries 512, sectors 10144 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 8, sectors/track 32, serial number 0x8f891bfd, label: "ESP        ", FAT (12 bit)

解析第二個分區,只是一個數據分區:

$ dd if=ubuntu-25.04-desktop-amd64.iso bs=512 skip=12262072 | file -
/dev/stdin: data

對於以光驅模式啓動,查詢 El Torito:

$ xorriso -indev ubuntu-25.04-desktop-amd64.iso
xorriso 1.5.6 : RockRidge filesystem manipulator, libburnia project.

xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE :    1082 nodes read in 1 seconds
libisofs: NOTE : Found hidden El-Torito image for EFI.
libisofs: NOTE : EFI image start and size: 3062978 * 2048 , 10160 * 512
xorriso : NOTE : Detected El-Torito boot information which currently is set to be discarded
Drive current: -indev 'ubuntu-25.04-desktop-amd64.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record  : El Torito , MBR protective-msdos-label grub2-mbr cyl-align-off GPT
Media summary: 1 session, 3065684 data blocks, 5988m data,  416g free
Volume id    : 'Ubuntu 25.04 amd64'

它記錄有一個 EFI 鏡像,位於 3062978 * 2048,大小為 10160 * 512;可以嘗試提取出來:

$ dd if=ubuntu-25.04-desktop-amd64.iso of=efi.img bs=2048 skip=3062978 count=5201920
$ mkdir efi
$ sudo mount efi.img efi
$ tree efi/
efi
└── EFI
    └── boot
        ├── bootx64.efi
        ├── grubx64.efi
        └── mmx64.efi

其實這個 EFI 鏡像就是 Ubuntu ISO 的第 2 個 FAT32 的 EFI 分區。

以 Windows 的 ISO 為例驗證 Hybrid ISO 的數據分佈

查看分區,這是一個 DOS/MBR 分區,並且沒有創建分區:

$ fdisk Win11_25H2_Chinese_Simplified_x64.iso 
Command (m for help): p
Disk Win11_25H2_Chinese_Simplified_x64.iso: 7.24 GiB, 7774558208 bytes, 15184684 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xfc048f24

查看 ISO 9660 文件系統元數據:

$ xorriso -indev Win11_25H2_Chinese_Simplified_x64.iso 
xorriso 1.5.6 : RockRidge filesystem manipulator, libburnia project.

xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE :       1 nodes read in 1 seconds
libisofs: WARNING : Found hidden El-Torito image. Its size could not be figured out, so image modify or boot image patching may lead to bad results.
libisofs: NOTE : Found hidden El-Torito image for EFI.
libisofs: NOTE : EFI image start and size: 555 * 2048 , 1 * 512
xorriso : NOTE : Detected El-Torito boot information which currently is set to be discarded
Drive current: -indev 'Win11_25H2_Chinese_Simplified_x64.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record  : El Torito
Media summary: 1 session, 3796171 data blocks, 7414m data,  416g free
Volume id    : 'CCCOMA_X64FRE_ZH-CN_DV9'

它記錄有一個 EFI 鏡像,位於 555 * 2048,大小為 1 * 512;可以嘗試提取出來:

$ dd if=Win11_25H2_Chinese_Simplified_x64.iso of=efi.img bs=2048 skip=555 count=512
$ mkdir efi
$ sudo mount efi.img efi
$ tree efi
efi
└── EFI
    └── BOOT
        └── BOOTX64.EFI

由於 Windows 的 ISO 沒有專門的 FAT32 分區,所以需要 UEFI 固件能支持識別 ISO 9660 的頭,並根據頭加載 EFI image。或者只能使用 Legacy BIOS 模式啓動。所以不是 Windows ISO 不能 dd,只是 dd 後的 USB 啓動盤兼容性沒有 Ubuntu 那麼好。