Collection of Boot Sector Formats for ISO 9660 Images by Thomas Schmitt - mailto:scdbackup@gmx.net Libburnia project - mailto:libburn-hackers@pykix.org This information is collected from various sources. Some is backed by specifications, some is just rumor which happens to work (maybe not even that). Content EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI. MBR, for PC-BIOS x86 from (pseudo-) hard disk - SYSLINUX isohybrid MBR - GRUB2 grub-mkrescue MBR. MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2. DEC Boot Block, for MIPS Little Endian , e.g. DECstation. ------------------------------------------------------------------------------ EL Torito CD booting for PC-BIOS x86, PowerPC, (old) Mac, EFI Sources: El Torito, Bootable CD-ROM Format Specification, Version 1.0, 1995 which refers to ECMA-119, the standard for ISO 9660 filesystems. libisofs/eltorito.[ch] by Vreixo Formoso. man mkisofs by Joerg Schilling. ECMA-119 prescribes that the first 32 kB of an ISO 9660 image are System Area with arbitrary content. This prescription is obeyed by PC-BIOS systems only if the ISO 9660 image is presented on CD, DVD or BD media. In this case the El Torito Boot record is the starting point of booting. The Boot Record is a ECMA-119 Volume Descriptor which is eventually located at 2 kB block number 17 (decimal). Its content points to the location of the Boot Catalog. The format is described in part by ECMA-119 8.2 "Boot Record" and further specified by El Torito figure 7. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 0 | 0 | Volume Descriptor Type. 0= Boot record 1 - 5 | "CD001" | Standard Identifier 6 - 6 | 1 | Volume Descriptor Version 7 - 38 | el_torito | Boot System Identifier 39 - 70 | 0 | Boot Identifier | | 71 -2047 | ========== | Boot System Use | | 71 - 74 | cataloglba | The 2 kB block number of the Boot Catalog | | as little-endian 32 bit number. | | 75 -2047 | 0 | Unused ---------- | ---------- | ---------------------------------------------------- el_torito is the constant string "EL TORITO SPECIFICATION" padded by 9 zeros. cataloglba has to be provided by the file system generator. The Boot Catalog lists the available boot images which may be prepared for multiple system architectures, called "platforms". It consists of one or more 2 kB blocks. The content is a sequence of fixed format entries, 32 bytes each. The entries are grouped in sections, which assign the entries to a particular system architecture. The booting system will then choose an entry from an appropriate section. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 31 | ========== | Validation Entry | | begins the first section, specifies an architecture 32 - 63 | ========== | Initial/Default Entry | | points to a boot image for given architecture ---------- | ---------- | ---------------------------------------------------- Optional: ---------- | ---------- | ---------------------------------------------------- 64 - 95 | ========== | Section Header entry | | begins new section, specifies an architecture 96 - 127 | ========== | Section Entry | | points to a boot image for given architecture ... | .......... | Optional more Section Entries ... | .......... | Optional more Section Headers and their Section | | Entries ---------- | ---------- | ---------------------------------------------------- An architecture is refered by a Platform Id number. Defined by El Torito are: 0 = "80x86" which is used for standard PCs with Intel x86 or compatible CPU 1 = "PowerPC" (possibly for IBM machines with PowerPC CPU) 2 = "Mac" (possibly for Apple computers with MC68000 or PowerPC CPU) Further in use by GRUB2 is: 0xef = EFI, a competitor resp. successor to PC-BIOS, possibly in use with Intel ia64 Itanium and possibly with newer Apple machines. Words resp. numbers are represented are little-endian. Validation Entry: Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 0 | 1 | Header Id | | 1 - 1 | platform_id| Platform Id. One of: 0, 1, 2, 0xef. See above. | | 2 - 3 | 0 | Reserved 4 - 27 | manuf_dev | ID string identifies the manufacturer/developer | | (no non-zero examples known yet) | | 28 - 29 | checksum | Checksum Word for the Validation Entry. | | The sum of all words in the entry has to be 0. | | 30 - 30 | 0x55 | 31 - 31 | 0xaa | ---------- | ---------- | ---------------------------------------------------- Initial/Default Entry: Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 0 | boot_indct | Boot Indicator: 0x88 = bootable, 0x00 = not bootable | | 1 - 1 | boot_media | Boot Media Type (i.e. media emulated by boot image): | | 0= no emulation , 1= 1.2 MB diskette, 2=1.44 MB, | | 3= 2.88 MB , 4= hard disk | | (About everybody uses 0 = no emulation) | | 2 - 3 | load_seg | Load Segment. (meaning unclear) | | "If this value is 0 the system will use the | | traditional segment of 7C0." | | libisofs default is 0 | | 4 - 4 | sys_type | System Type. | | "Must be a copy of byte 5 from the partition table | | found in the boot image." | | libisofs reads the start the boot image as MBR | | if boot_media == 4. This emulated MBR has a | | partition table from where a byte gets copied. | | Else this byte is 0. | | 5 - 5 | 0 | Unused | | 6 - 7 | sec_count | Sector Count. | | "the number of virtual/emulated sectors the system | | will store at Load Segment during the initial boot | | procedure." | | libisofs stores 1 for emulated boot_media and | | 0 for boot_media == 0. | | 8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot | | image file content is located in the ISO 9660 image. | | 12 - 31 | 0 | Unused ---------- | ---------- | ---------------------------------------------------- Section Header Entry: Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 0 | head_ind | Header Indicator: 0x90 = more headers follow | | 0x91 = final header, last section | | 1 - 1 | platform_id| Platform Id. One of: 0, 1, 2, 0xef. See above. | | 2 - 3 | num_entries| Number of entries to follow in this section | | 4 - 31 | | ID string identifies the manufacturer/developer ---------- | ---------- | ---------------------------------------------------- Section Entry: Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 0 | boot_indct | Boot Indicator: 0x88 = bootable, 0x00 = not bootable | | 1 - 1 | boot_media | Boot Media Type (i.e. media emulated by boot image): | | Bit 0 to 3 govern emulation | | 0= no emulation , 1= 1.2 MB diskette, 2=1.44 MB, | | 3= 2.88 MB , 4= hard disk | | (About everybody uses 0 = no emulation) | | Bit 4 is reserved and must be 0 | | Bit 5 "Continuation entry follows" (meaning unclear) | | Might be the indicator for Extension Entries, | | which are not described here. | | Bit 6 "Image contains an ATAPI driver" | | Bit 7 "Image contains SCSI drivers" | | 2 - 3 | load_seg | Load Segment. (meaning unclear) | | See above Initial/Default Entry | | libisofs default is 0. 4 - 4 | sys_type | System Type. | | See above Initial/Default Entry | | 0 if not emulation == 4. 5 - 5 | 0 | Unused | | 6 - 7 | sec_count | Sector Count. | | See above Initial/Default Entry | | libisofs stores 1 for emulated boot_media and | | 0 for boot_media == 0. | | 8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot | | image file content is located in the ISO 9660 image. | | 12 - 31 | sel_crit | "Vendor unique selection criteria." ---------- | ---------- | ---------------------------------------------------- The boot image file content is mostly opaque to the ISO 9660 image generator. Nevertheless there is a tradition named "Boot Info Table" which prescribes to write information into byte fields of the boot image file content. There are no general means known how a producer of ISO 9660 images could detect the need for Boot Info Table production. It rather needs a hint from the user who has to know whether the boot image expects a Boot Info Table. The Boot Info Table begins at byte 8 of the boot image content. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 8 - 11 | pvd_lba | Block address of the Primary Volume Descriptor | | This is the session start LBA + 16. | | 12 - 15 | file_lba | Block address of the start of the boot image file | | content. | | 16 - 19 | file_len | Number of bytes in boot image file content. | | 20 - 23 | checksum | Little-endian: The sum of all 32-bit words of the | | file content from byte 64 to file end. | | 24 - 63 | 0 | Reserved ---------- | ---------- | ---------------------------------------------------- ------------------------------------------------------------------------------ MBR for PC-BIOS x86 from (pseudo-) hard disk Sources: http://en.wikipedia.org/wiki/Master_boot_record Mailing list conversations with H. Peter Anvin and Vladimir Serbinenko. The candidates for MBR booting will normally use El Torito rather than MBR if the ISO image is presented on CD, DVD, or BD media. The eventual MBR comes into effect it the image is on a media that is interpreted by the BIOS as some kind of hard disk. Usually real hard disks, floppy disks, USB sticks, memory cards. An important part of an MBR is the DOS style partition table. It describes up to four primary partitions. There are two formats used for block address: Cylinder/Head/Sector (C/H/S) and Logical Block Address (LBA). Both are based on units of 512 bytes. So MBR_LBA = ISO_LBA * 4. For C/H/S, the sector address is broken up into whole cylinders, remaining heads, and remaining sectors + 1. The nomenclature seems to stem from antique drum storage. There are two parameters, sectors_per_head and heads_per_cylinder which are not stored in the MBR. So it is more or less arbitray how to convert a LBA into a C/H/S address and vice versa. For maximum range of C/H/S addresses one may use sectors_per_head = 63 , heads_per_cylinder = 255. Words are composed little-endian style. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 439 | = opaque = | Code Area filled with bytes for some boot system, | | typically machine code. | | 440 - 443 | disk_sgntr | Disc signature, an individual disk id of obscure | | usability. | | (The Code Area might extend up to this field.) | | 444 - 445 | 0 | "usually nulls" | | (The Code Area might extend up to this field.) | | 446 - 461 | ========== | Partition Table Entry for partition 1 | | 446 - 446 | status | Governs bootability: | | 0x80 = bootable/active , 0x00 non-bootable/inactive | | 447 - 449 | ========== | C/H/S address of partition start 447 - 447 | start_head | Heads part of start address. 448 - 448 | start_c_s | Bits 0 to 5 : Sectors part of start address. | | Bits 6 to 7 : Bits 8 to 9 of cylinders part. 449 - 449 | start_cyl | Lower 8 bits of cylinders part of start address | | 450 - 450 | part_type | Partition type indicates the purpose or kind of | | filesystem in the partition. | | 451 - 453 | ========== | C/H/S address of last absolute sector in partition 451 - 451 | end_head | Heads part of end address. 452 - 452 | end_c_s | Bits 0 to 5 : Sectors part of end address. | Values: 1 to 63, not 0. | | Bits 6 to 7 : Bits 8 to 9 of cylinders part. 453 - 453 | end_cyl | Lower 8 bits of cylinders part of end address | | 454 - 457 | start_lba | LBA of first absolute sector in partiton. | | Block size is 512. Counting starts at 0. | | 458 - 461 | num_blocks | Number of sectors in partition. | | 462 - 477 | ========== | Partition Table Entry for partition 2 | part_entr2 | 16 bytes. Format as with partition 1. | | All 0 means that partition is unused/undefined. | | 478 - 493 | ========== | Partition Table Entry for partition 3 | part_entr3 | 16 bytes. See above. | | 494 - 509 | ========== | Partition Table Entry for partition 4 | part_entr4 | 16 bytes. See above. | | 510 - 510 | 0x55 | MBR signature 511 - 511 | 0xaa | MBR signature | | ---------- | ---------- | ---------------------------------------------------- By tradition the MBR itself and possibly more blocks are not claimed by any partition. But starting the first partition at a non-zero block address causes on Linux a partition device file (e.g. /dev/sdb1) which cannot be used to mount the ISO filesystem. libisofs is able to produce a second set of trees and meta data which is suitable for being mounted at start block 16 (ISO) resp. 64 (MBR). See for call iso_write_opts_set_part_offset() and http://libburnia-project.org/wiki/PartitionOffset for examples with program xorriso. ------------------------------------------------------------------------------ SYSLINUX Isohybrid MBR Sources: syslinux-3.72/utils/isohybrid , a perl script by H. Peter Anvin = hpa. Mailing list conversations with hpa. An isohybrid MBR directs the booting BIOS to an ISOLINUX boot image which is also the target of an El Torito boot catalog entry. For that purpose one has to take an MBR template and has to set a few bytes to values which sufficiently describe the ISO image and the boot image file. Words are composed little-endian style. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 431 | = opaque = | Syslinux machine code provided by MBR template | | 432 - 439 | hd_bootlba | Address of the ISOLINUX boot image file in the | | ISO image. Counted in 512 byte blocks. | | 440 - 443 | mbr_id | Random number 444 - 445 | 0 | Padding | | 446 - 509 | ========== | Partition table | | 446 - 461 | part_entry | Partition table entry 1 describing ISO image size | | starting at LBA 0. I.e. contrary to tradition. | | See above for partition table entry format. | | 462 - 509 | 0 | Unused partition entries 2 to 4 510 - 511 | 0xaa55 | MBR signature ---------- | ---------- | ---------------------------------------------------- hpa about MBR templates and partition table filesystem types: "[MBR templates] are available in the Syslinux build tree under the names: mbr/isohdp[fp]x*.bin The default probably should be mbr/isohdppx.bin, but it's ultimately up to the user. [...] Note: the filesystem type is largely arbitrary, in theory it can be any value other than 0x00, 0x05, 0x0f, 0x85, 0xee, or 0xef. 0x17 ("Windows IFS Hidden") seems safeish, some people believe 0x83 (Linux) is better. " ------------------------------------------------------------------------------ GRUB2 grub-mkrescue MBR Sources: Mailing list conversations with Vladimir Serbinenko. The MBR file that is used with GRUB2 script grub-mkrescue needs only a partition table entry which describes the image size. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 445 | = opaque = | GRUB2 machine code provided by MBR template | | 446 - 509 | ========== | Partition table | | 446 - 461 | part_entry | Partition table entry 1 describing ISO image size | | Peculiar is the start offset of 1 block. | | This prevents mounting of the partition. | | See above for partition table entry format. | | 462 - 509 | 0 | Unused partition entries 2 to 4 510 - 511 | 0xaa55 | MBR signature ---------- | ---------- | ---------------------------------------------------- Vladimir Serbinenko about the partition table entry: "Currently we use first and not last entry. You need to: 1) Zero-fill 446-510 2) Put 0x55, 0xAA into 510-512 3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd (partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA start in little endian), [LBA end in little endian] at 446-462 " ------------------------------------------------------------------------------ MIPS Volume Header for MIPS Big Endian, e.g. SGI Indigo2 Sources: cdrkit-1.1.10/genisoimage/boot-mips.c by Steve McIntyre which refers to genisovh by Florian Lohoff and Thiemo Seufer who seem to have learned parameter settings from IRIX CD media There are traces in the web which relate this to specs by MIPS Computer Systems, Inc. , 1985 Silicon Graphics Computer Systems, Inc. , 2000 The first 512 bytes of the media constitute the Volume Header. Words are composed big-endian style. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 3 | 0x0be5a941 | Magic number 4 - 5 | 0 | Root partition number 6 - 7 | 0 | Swap partition number 8 - 23 | 0 | Name of file to boot (unclear what this means) | | 24 - 71 | ========== | Device Parameters | | 24 - 24 | 0 | Spiral addressing skew (unclear what this means) 25 - 25 | 0 | Words of 0 before header 26 - 26 | 0 | Words of 0 between hdr and data 27 - 27 | 0 | Spare sectors per cylinder 28 - 29 | num_cyl_l | Number of usable cylinder, lower two bytes | | ((iso_size + BYTES_PER_SECTOR - 1) / | | (SECTORS_PER_TRACK * BYTES_PER_SECTOR)) & 0xffff 30 - 31 | 0 | Starting head of volume 0 32 - 33 | 1 | Number of tracks per cylinder 34 - 34 | 0 | Depth of CTQ queue (unclear what this means) 35 - 35 | num_cyl_h | Number of usable cylinders, high byte | | ((iso_size + BYTES_PER_SECTOR - 1) / | | (SECTORS_PER_TRACK * BYTES_PER_SECTOR)) >> 16 36 - 37 | 0 | unused 38 - 39 | 32 | SECTORS_PER_TRACK 40 - 41 | 512 | BYTES_PER_SECTOR 42 - 43 | 0 | Sector interleave (unclear what this means) 44 - 47 | 0x00000034 | Controller characteristics composed from | | DP_RESEEK 0x00000020 /* recalibrate as last resort */ | | DP_IGNOREERRORS 0x00000010 | | /* transfer data regardless of errors */ | | DP_TRKFWD 0x00000004 | | /* forward to replacement track */ 48 - 51 | 0 | Bytes/sec for kernel stats 52 - 55 | 0 | Max num retries on data error 56 - 59 | 0 | ms per word to xfer, for iostat 60 - 71 | 0 | 6 parameter words for xylogics controllers | | 72 - 311 | ========== | Volume Directory with 15 entries of 16 bytes each | | 72 - 87 | ========== | Volume Directory Entry 1 72 - 79 | boot_name | Boot file basename, eventually padded by 0 to lenght 8 80 - 83 | boot_block | ISO 9660 LBA of boot file * 4, i.e. in blocks of 512 84 - 87 | boot_bytes | File length in bytes | | 88 - 311 | see above | Volume Directory Entries 2 to 15 | | 312 - 504 | ========== | Partition Table with 16 entries of 12 bytes each | | 312 - 407 | 0 | Unused partition entries 1 to 8 | | 408 - 419 | ========== | Partition Table Entry 9 for Volume Header 408 - 411 | part_blks | Number of 512 byte blocks in partition | |(iso_size + (BYTES_PER_SECTOR - 1)) / BYTES_PER_SECTOR 412 - 415 | 0 | Start block of partition 416 - 419 | 0 | PTYPE_VOLHDR = Partition is volume header | | 420 - 431 | 0 | Unused partition entry 10 | | 432 - 443 | ========== | Partition Table Entry 11 for Volume 432 - 435 | part_blks | Number of 512 byte blocks in partition | |(iso_size + (BYTES_PER_SECTOR - 1)) / BYTES_PER_SECTOR 436 - 439 | 0 | Start block of partition 440 - 443 | 6 | PTYPE_VOLUME = Partition is entire volume | | 444 - 503 | 0 | Unused partition entries 12 to 16 | | 504 - 507 | head_chk | Volume header checksum | | The two's complement of bytes 0 to 503 read as big | | endian unsigned 32 bit: sum(words) + head_chk == 0 | | 508 - 511 | 0 | Volume header end padding | | up to 2048 | 0 | ISO 9660 Block end padding ---------- | ---------- | ---------------------------------------------------- Test image produced by genisoimage -o /u/test/mips_boot.iso -mips-boot checksum.c jte which reports Found mips boot image checksum.c, using extent 636 (0x27C), #blocks 14336 (0x3800) xorriso reports as 2048 byte LBA of the boot image dummy file File data lba: 0 , 159 , 7 , 14330 , '/CHECKSUM.C' First 512 bytes in hex: 0 : 0b e5 a9 41 00 00 00 00 00 00 00 00 00 00 00 00 16 : 00 00 00 00 00 00 00 00 00 00 00 00 00 51 00 00 32 : 00 01 00 00 00 00 00 20 02 00 00 00 00 00 00 34 48 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 : 00 00 00 00 00 00 00 00 63 68 65 63 6b 73 75 6d 80 : 00 00 02 7c 00 00 38 00 00 00 00 00 00 00 00 00 ... 0 ... 400 : 00 00 00 00 00 00 00 00 00 00 0a 28 00 00 00 00 416 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 432 : 00 00 0a 28 00 00 00 00 00 00 00 06 00 00 00 00 ... 0 ... 496 : 00 00 00 00 00 00 00 00 22 ec 2c c9 00 00 00 00 The 32 bit two's complement of bytes 0 to 503 is 0x22ec2cc9. In decimal: 0 : 11 229 169 65 0 0 0 0 0 0 0 0 0 0 0 0 16 : 0 0 0 0 0 0 0 0 0 0 0 0 0 81 0 0 32 : 0 1 0 0 0 0 0 32 2 0 0 0 0 0 0 52 48 : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 : 0 0 0 0 0 0 0 0 99 104 101 99 107 115 117 109 80 : 0 0 2 124 0 0 56 0 0 0 0 0 0 0 0 0 ... 0 ... 400 : 0 0 0 0 0 0 0 0 0 0 10 40 0 0 0 0 416 : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 432 : 0 0 10 40 0 0 0 0 0 0 0 6 0 0 0 0 ... 0 ... 496 : 0 0 0 0 0 0 0 0 34 236 44 201 0 0 0 0 Cleartext part: 64 : c h e c k s u m ------------------------------------------------------------------------------ DEC Boot Block for MIPS Little Endian , e.g. DECstation Sources: cdrkit-1.1.10/genisoimage/boot-mipsel.c by Steve McIntyre which refers to delo by Florian Lohoff and Thiemo Seufer cdrkit-1.1.10/include/glibc_elf.h by Steve McIntyre which is based on from GNUC C Library by Free Software Foundation, Inc. There seems to be only one boot file possible. Some information needs to be read out of the ELF headers of this boot file. Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 7 | 0 | Padding | | 8 - 11 | 0x0002757a | Magic number | | 12 - 15 | 1 | Mode /* 0: Single extent, 1: Multi extent boot */ | | 16 - 19 | load_adr | Load address /* Load below kernel */ | | Stems from ELF header of boot file. | | See below Elf32_Phdr field p_vaddr. | | 20 - 23 | exec_adr | Execution address /* And exec there */ | | Stems from ELF header of boot file. | | See below Elf32_Ehdr field e_entry. | | 24 - 31 | ========== | Boot Map Entry 1 | | 24 - 27 | seg_size | Segment size in file. Blocks of 512 bytes. | | Stems from ELF header of boot file. | | (Elf32_Phdr field p_filesz + 511) / 512; | | 28 - 31 | seg_start | Segment file offset. Blocks 512 bytes. | | ISO 9660 LBA of boot file * 4 plus offset | | + offset which stems from ELF header of boot file: | | (Elf32_Phdr field p_offset + 511) / 512; | | 32 - 431 | ========== | Boot Map Entries 2 to 51 | 0 | | | ---------- | ---------- | ---------------------------------------------------- Elf32_Ehdr gets loaded from boot file byte address 0: Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 23 | | ( Magic number, file information ) | | 24 - 27 | e_entry | /* Entry point virtual address */ | = exec_adr | Needed for exec_adr | | 28 - 31 | e_phoff | /* Program header table file offset */ | | Byte address of Elf32_Phdr | | Elf32_Phdr gets loaded from boot file byte_address Elf32_Ehdr.e_phoff : Byte Range | Value | Meaning ---------- | ---------- | ---------------------------------------------------- 0 - 3 | | ( Segment type ) | | 4 - 7 | p_offset | /* Segment file offset */ |-> seg_start| Needed for seg_start | | 8 - 11 | p_vaddr | /* Segment virtual address */ | =load_adr | Needed for load_adr | | 12 - 15 | | (Segment physical address) | | 16 - 19 | p_filesz | /* Segment size in file */ |-> seg_size | Needed for seg_size | | ------------------------------------------------------------------------------ >>> ??? HP-PA ------------------------------------------------------------------------------ >>> ??? DEC Alpha ------------------------------------------------------------------------------