Manipulating ISO Images for BIOS/UEFI Boot Support
An example of how to repack a BIOS only ISO image for BIOS/UEFI dual boot
Status: 15 Sept 2020 - Verified with FreeBSD 10.04 ISO
Model x86 machines are now all using UEFI for boot support, typically with the ability to configure legacy (BIOS) boot support. ISO image boot support for BIOS is provided by the "El Torito" extensions and this mechanism has been extended for UEFI boot by using extra Boot Catalog entries.
My example is to allow older FreeBSD ISO to be bootable on a UEFI only VM.
FreeBSD BIOS vs Dual Boot ISO
The starting point for repacking an ISO is to find out the boot image locations. FreeBSD has a utility etdump (El Torito Dump, the Linux equivalent is dumpet) that provides a dump of the El Torito Boot Catalog contents. This provides details required to extract out the required parts from a existing ISO image.
This example uses FreeBSD BIOS (10.4) ISO and Dual Boot FreeBSD (11.4) ISO to compare El Torito Boot Catalog (note this is from FreeBSD machine) and create a Dual Boot 10.04 FreeBSD ISO image.
We start by dumping the boot catalogs (using FreeBSD etdump):
# etdump FreeBSD-10.4-RELEASE-amd64-disc1.iso
Image in FreeBSD-10.4-RELEASE-amd64-disc1.iso
Default entry
System i386
Start LBA 20 (0x14), sector count 4 (0x4)
Media type: no emulation
For 10.4 example there is a single entry image at Block Offset 20 (1 CD Block = 2048 bytes)
# etdump FreeBSD-11.4-RELEASE-amd64-dvd1.iso
Image in FreeBSD-11.4-RELEASE-amd64-dvd1.iso
Default entry
System i386
Start LBA 420 (0x1a4), sector count 4 (0x4)
Media type: no emulation
Section header: efi, final
Section entry
System i386
Start LBA 20 (0x14), sector count 1600 (0x640)
Media type: no emulation
For 11.4 case there are two boot catalog entries, one for BIOS and one for UEFI.
Looking at this from Ubuntu machine for same FreeBSD 11.4 ISO:
$ isoinfo -i FreeBSD-11.4-RELEASE-amd64-dvd1.iso -d
CD-ROM is in ISO 9660 format
System id: FreeBSD
Volume id: 11_4_RELEASE_AMD64_DVD
Volume set id:
Publisher id: THE FREEBSD PROJECT. HTTP://WWW.FREEBSD.ORG/
Data preparer id:
Application id:
Copyright File id:
Abstract File id:
Bibliographic File id:
Volume set size is: 1
Volume set sequence number is: 1
Logical block size is: 2048
Volume size is: 1868279
El Torito VD version 1 found, boot catalog is in sector 19
NO Joliet present
Rock Ridge signatures version 1 found
Eltorito validation header:
Hid 1
Arch 0 (x86)
ID ''
Key 55 AA
Eltorito defaultboot header:
Bootid 88 (bootable)
Boot media 0 (No Emulation Boot)
Load segment 0
Sys type 0
Nsect 4
Bootoff 1A4 420
For 11.4 Dual Boot case there is BIOS entry at Block Offset 420 and UEFI entry at Block Offset 20. To see what the disk structure looks like, lets extract the UEFI image and examine it.
NOTE: isoinfo does not provide the required information to extract the UEFI boot sector, as it is only providing the BIOS boot catalog entry.
Extracting FreeBSD UEFI Image
Using the FreeBSD 11.4 example from above we can extract the UEFI section by using "dd" and see content type using file (all on Ubuntu):
---
--- 1. Copy out the UEFI image by skipping 20 Blocks
---
$ dd if=FreeBSD-11.4-RELEASE-amd64-dvd1.iso of=freebsd-11.4-uefi-part-1.img skip=20 bs=2048 count=1600
1600+0 records in
1600+0 records out
3276800 bytes (3.3 MB, 3.1 MiB) copied, 0.0197891 s, 166 MB/s
---
--- 2. Have a look at Image type..
---
$ file freebsd-11.4-uefi-part.img
freebsd-11.4-uefi-part.img: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "BSD4.4 ", root entries 512, sectors 1600 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 5, sectors/track 63, heads 1, reserved 0x1, serial number 0x25ef1a16, unlabeled, FAT (12 bit)
So we can see that the UEFI sector is a DOS/MBR based image. This is because for UEFI boot the image is first copied to memory and then mounted to get a FAT "/efi/boot" file system containing the bootx64.efi boot program. This is different to the BIOS case which just has the binary boot program stored directly in the MBR boot sector.
Having extracted the 11.4 UEFI part you are ready to reburn your 10.4 ISO as dual boot.
Repacking a BIOS FreeBSD ISO for Dual Boot
The motivation for this was to repack the FreeBSD 10.4 ISO with a UEFI boot entry. Having extracted the UEFI boot image from FreeBSD 11.4 ISO we now need to rebuilt the ISO with this as well as default BIOS boot.
To do this (using Ubuntu) we should:
- Mount the 10.4 CD image
- Copy the 11.04 UEFI sector image into the boot directory
- Use "xorriso" to create new dual boot ISO
- Do test boot
---
--- 0. Create directories
---
mkdir LOOP && mkdir DUAL
---
--- 1. Mount ISO
---
$ sudo mount -t iso9660 -o ro,loop FreeBSD-10.4-RELEASE-amd64-disc1.iso /home/USER/LOOP
---
--- 2. Copy Contents & add the extracted UEFI image
---
$ cd DUAL
$ sudo rsync -a ../LOOP .
---
--- Copy the UEFI sectors we extract above
---
$ sudo cp USER-DIR/freebsd-11.4-uefi-part-1.img LOOP/boot/uefiboot.img
---
--- 3. Create new image
---
$ sudo xorriso -as mkisofs -V "10_4_RELEASE_AMD64_CD" -o /home/USER/freebsd-10.04-alt-dvd.iso -b boot/cdboot -boot-load-size 4 -no-emul-boot -boot-info-table -eltorito-alt-boot -e boot/uefiboot.img -no-emul-boot .
[sudo] password for USER:
xorriso 1.5.2 : RockRidge filesystem manipulator, libburnia project.
Drive current: -outdev 'stdio:/home/USER/freebsd-10.04-alt-dvd.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data, 7853m free
Added to ISO image: directory '/'='/home/USER/DUAL/LOOP'
xorriso : UPDATE : 18050 files added in 1 seconds
xorriso : UPDATE : 18050 files added in 1 seconds
xorriso : UPDATE : 3.81% done
xorriso : UPDATE : 59.02% done
ISO image produced: 332178 sectors
Written to medium : 332178 sectors at LBA 0
Writing to 'stdio:/home/USER/freebsd-10.04-alt-dvd.iso' completed successfully.
Some explanation:
- BIOS Boot - "-b boot/cdboot -boot-load-size 4 -n0-emu-boot -boot-info-table" : provide the directives for the BIOS El Torito entry, where the cdboot image is what was already on the FreeBSD 10.04 to handle the BIOS CD boot (note that the sector size == 4 is as per 10.04 etdump details).
- UEFI Boot - "-eltorito-alt-boot -e boot/uefiboot.img -no-emul-boot" : are the extra boot catalog items for the UEFI boot and reference the UEFI boot image that was extracted from the 11.04 ISO
NOTE: Futher checking of FreeBSD ISO, reveals that the BIOS & UEFI boot sector are on CD here:
- /boot/cdboot - the MBR loader
- /boot/boot1.efifat - the EFI (file systsem) image which contains bootx64.efi loader
So you can use boot1.efifat as the input into xorriso "-elstorito-alt-boot -e IMG" command. See here for additional details here:
---
--- 1. Mount example ISO with BIOS/UEFI boot support
---
$ sudo mount -t iso9660 -o ro,loop FreeBSD-11.4-RELEASE-amd64-dvd1.iso /home/USER/LOOP
$ ls LOOP
bin docbook.css HARDWARE.HTM media proc RELNOTES.TXT sys
boot ERRATA.HTM HARDWARE.TXT mnt README.HTM rescue tmp
COPYRIGHT ERRATA.TXT lib net README.TXT root usr
dev etc libexec packages RELNOTES.HTM sbin var
---
--- 2. Look at the boot directory on FreeBSD iso
---
$ cd LOOP/boot
$ ls -la
total 6183
drwxr-xr-x 9 root root 8192 Jun 13 04:46 .
drwxr-xr-x 19 root root 6144 Jun 13 04:50 ..
-r--r--r-- 1 root root 3554 Jun 13 04:42 beastie.4th
-r--r--r-- 1 root root 8192 Jun 13 04:42 boot
-r--r--r-- 1 root root 512 Jun 13 04:42 boot0
-r--r--r-- 1 root root 512 Jun 13 04:42 boot0sio
-r--r--r-- 1 root root 512 Jun 13 04:42 boot1
-r-xr-xr-x 1 root root 81408 Jun 13 04:42 boot1.efi
-r--r--r-- 1 root root 819200 Jun 13 04:42 boot1.efifat
-r--r--r-- 1 root root 7680 Jun 13 04:42 boot2
-r--r--r-- 1 root root 2806 Jun 13 04:42 brand.4th
-r--r--r-- 1 root root 2126 Jun 13 04:42 brand-fbsd.4th
-r--r--r-- 1 root root 1185 Jun 13 04:42 cdboot
-r--r--r-- 1 root root 6277 Jun 13 04:42 check-password.4th
-r--r--r-- 1 root root 2111 Jun 13 04:42 color.4th
drwxr-xr-x 2 root root 2048 Jun 13 04:42 defaults
-r--r--r-- 1 root root 4053 Jun 13 04:42 delay.4th
-r--r--r-- 1 root root 829 Jun 13 04:44 device.hints
drwxr-xr-x 3 root root 2048 Jun 13 04:40 dtb
drwxr-xr-x 2 root root 2048 Jun 13 04:40 firmware
-r--r--r-- 1 root root 4176 Jun 13 04:42 frames.4th
-r--r--r-- 1 root root 58582 Jun 13 04:42 gptboot
-r--r--r-- 1 root root 100582 Jun 13 04:42 gptzfsboot
-r--r--r-- 1 root root 14659 Jun 13 04:42 isoboot
drwxr-xr-x 2 root root 122880 Jun 13 04:40 kernel
-r-xr-xr-x 3 root root 335872 Jun 13 04:42 loader
-r--r--r-- 1 root root 7490 Jun 13 04:42 loader.4th
-r-xr-xr-x 3 root root 335872 Jun 13 04:42 loader_4th
-r-xr-xr-x 2 root root 391168 Jun 13 04:42 loader_4th.efi
-rw-r--r-- 1 root root 27 Jun 13 04:46 loader.conf
-r-xr-xr-x 2 root root 391168 Jun 13 04:42 loader.efi
-r-xr-xr-x 1 root root 380928 Jun 13 04:42 loader_lua
-r-xr-xr-x 1 root root 454144 Jun 13 04:42 loader_lua.efi
-r--r--r-- 1 root root 427 Jun 13 04:42 loader.rc
-r-xr-xr-x 1 root root 282624 Jun 13 04:42 loader_simp
-r-xr-xr-x 1 root root 331264 Jun 13 04:42 loader_simp.efi
-r--r--r-- 1 root root 3110 Jun 13 04:42 logo-beastie.4th
-r--r--r-- 1 root root 2636 Jun 13 04:42 logo-beastiebw.4th
-r--r--r-- 1 root root 2214 Jun 13 04:42 logo-fbsdbw.4th
-r--r--r-- 1 root root 2631 Jun 13 04:42 logo-orb.4th
-r--r--r-- 1 root root 2354 Jun 13 04:42 logo-orbbw.4th
drwxr-xr-x 2 root root 4096 Jun 13 04:42 lua
-r--r--r-- 1 root root 512 Jun 13 04:42 mbr
-r--r--r-- 1 root root 36016 Jun 13 04:42 menu.4th
-r--r--r-- 1 root root 9260 Jun 13 04:42 menu-commands.4th
-r--r--r-- 1 root root 6328 Jun 13 04:42 menu.rc
-r--r--r-- 1 root root 18597 Jun 13 04:42 menusets.4th
drwxr-xr-x 2 root root 2048 Jun 13 04:40 modules
-r--r--r-- 1 root root 512 Jun 13 04:42 pmbr
-r--r--r-- 1 root root 337920 Jun 13 04:42 pxeboot
-r--r--r-- 1 root root 2738 Jun 13 04:42 screen.4th
-r--r--r-- 1 root root 2613 Jun 13 04:42 shortcuts.4th
-r--r--r-- 1 root root 36285 Jun 13 04:42 support.4th
-r--r--r-- 2 root root 335992 Jun 13 04:42 userboot_4th.so
-r--r--r-- 1 root root 402936 Jun 13 04:42 userboot_lua.so
-r--r--r-- 2 root root 335992 Jun 13 04:42 userboot.so
-r--r--r-- 1 root root 3065 Jun 13 04:42 version.4th
drwxr-xr-x 2 root root 2048 Jun 13 04:40 zfs
-r--r--r-- 1 root root 262656 Jun 13 04:42 zfsboot
-r-xr-xr-x 3 root root 335872 Jun 13 04:42 zfsloader
---
--- 3. Lets look at boot1.efifat
---
$ file boot1.efifat
boot1.efifat: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "BSD4.4 ", root entries 512, sectors 1600 (volumes <=32 mb), sectors fat 5, track 63, heads 1, serial number 0xbd4111ee, label: "efisys ", (12 bit), followed by --- 4. lets verify that this is a valid uefi image file $ mkdir ~ loop2 sudo mount -o loop boot1.efifat home user [sudo] password for user: ls -r loop2: efi efi: boot boot: bootx64.efi startup.nsh < code>=32>
References & Links:
ISO Image Extract - Provides a simple explanation of how ISO image is structured and getting the El Torito details from the image, but does not solve the UEFI/BIOS problem
Debian Repacking Bootable ISO - provides information on what is required to repack a BIOS bootable CD with UEFI extension for dual boot support
etdump - FreeBSD tool that provides dump of El Torito boot catalog (Linux equivalent is "dumpet")
Fedora - Bootable CDs - a simper explanation but specific to Fedora tools
Setup, and create a custom FreeBSD ISO - article provides the FreeBSD way of achieving some of this, again with passing reference to "cdboot"
FreeBSD CD Creation - does not use xorriso but does have passing reference to "cdboot" which is the BIOS CD boot loader
xorriso - only GNU has tools with command lines a complicated this ;-), I think you could likely do the required extract/rewrite just using this, but this will require some time to read all of the options available
Image/Photo - So whats with "Salt-n-Pepa" ? The answer is, "They have a member "Spinderella" and we are doing some CD spinning".
Ubuntu Boot Catalog Example
Here is example from Linux (Ubuntu) Desktop 20-04 (FreeBSD - etdump & Ubuntu/Linux - isoinfo)
$ etdump ubuntu-20.04-desktop-amd64.iso
Image in ubuntu-20.04-desktop-amd64.iso
Default entry
System i386
Start LBA 1050673 (0x100831), sector count 4 (0x4)
Media type: no emulation
Section header: efi, final
Section entry
System i386
Start LBA 1055660 (0x101bac), sector count 7936 (0x1f00)
Media type: no emulation
This shows that there are two boot catalog entries, the default (BIOS) and extra (UEFI). The layout has BIOS boot ahead of EFI (with sector count 4 (x 512 Blocks = 2,048 Bytes == 1 CD Block), and UEFI (with sector cound 7,936 (x 512 Blocks = 4,063,232 Byes == 1,984 CD Blocks)
$ isoinfo -i ubuntu-20.04-desktop-amd64.iso -d
CD-ROM is in ISO 9660 format
System id:
Volume id: Ubuntu 20.04 LTS amd64
Volume set id:
Publisher id:
Data preparer id: XORRISO-1.2.4 2012.07.20.130001, LIBISOBURN-1.2.4, LIBISOFS-1.2.4, LIBBURN-1.2.4
Application id:
Copyright File id:
Abstract File id:
Bibliographic File id:
Volume set size is: 1
Volume set sequence number is: 1
Logical block size is: 2048
Volume size is: 1325808
El Torito VD version 1 found, boot catalog is in sector 335
Joliet with UCS level 3 found
Rock Ridge signatures version 1 found
Eltorito validation header:
Hid 1
Arch 0 (x86)
ID ''
Key 55 AA
Eltorito defaultboot header:
Bootid 88 (bootable)
Boot media 0 (No Emulation Boot)
Load segment 0
Sys type 0
Nsect 4
Bootoff 100831 1050673
The isoinfo "Bootoff" (Boot Offset) 1,050,673 corresponds to the boot catalog "Default Entry - Start LBA" of 1,050,673. The HEX / Decimal representations are flipped with the two tools.