Extracting a bootable disk image from an ISO image (El Torito)

The El Torito Bootable CD Specification was introduced in the 90's to make it possible to boot a system from a CD. This specification is used till today for bootable ISO images. There are different ways to embed disk images into El Torito ISO images. One way is called hard disk emulation. With this the bootable disk image comes with a DOS/MBR boot record and can be booted by the BIOS/UEFI directly. Unfortunately if you want to boot such an ISO from an USB stick, that won't work out of the box, you need to extract the disk image from the ISO first. This article is about how you can do that easily under Linux.

What again is this good for?

A typical use case are BIOS/UEFI updates under Linux. Such updates often come either packed in Windows executables (which you can't use because you run Linux) or as an ISO image. You could now burn a CD and boot your machine from that in order to update the BIOS. But we don't want to waste resources and use a USB drive instead. That's there the following comes into play. You need to extract the embedded disk image from the ISO image and then flash it to a USB drive in order to boot from it.

Only dd and isoinfo are needed...

There is actually a tool called geteltorito to extract such images from El Torito ISO images, but you can do the same with dd. All we need to do is to find out where the bootable disk image actually sits at the ISO. For this we can use the tool isoinfo which comes with the package cdrtools (ArchLinux) or genisoimage (Debian derivates).

Once you have isoinfo installed, is it as easy as running the following command to get some info regarding the ISO image:

$ isoinfo -i my.iso -d
The output should look similar to that:
Setting input-charset to 'UTF-8' from locale.
CD-ROM is in ISO 9660 format
System id: 
Volume id: R0DET96U
Volume set id: 
Publisher id: 
Data preparer id: 
Application id: NERO BURNING ROM VER 12,5,5,0
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: 8374
El Torito VD version 1 found, boot catalog is in sector 20

Joliet with UCS level 3 found.
No SUSP/Rock Ridge present
Eltorito validation header:
    Hid 1
    Arch 0 (x86)
    ID 'NERO BURNING ROM VER 12'
    Cksum D3 22 OK
    Key 55 AA
    Eltorito defaultboot header:
        Bootid 88 (bootable)
        Boot media 4 (Hard Disk Emulation)
        Load segment 7C0
        Sys type 6
        Nsect 1
        Bootoff 1B 27

Note the last 7 lines. In this case the ISO embeds one bootable disk image which is located at offset 0x1b (27 decimal). Now it is important to know that this is not the offset in bytes, but the sector offset. Since the sector size of CD ISO images is 2048 bytes (see also this article), one actually needs to multiply 27 * 2048 to get the right byte offset where the bootable disk image actually resides.

Now we can just use dd to extract the image by just skipping the first 27 2048 byte sectors.

# dd if=my.iso of=out.img skip=27 bs=2048
8347+0 records in
8347+0 records out
17094656 bytes (17 MB, 16 MiB) copied, 0.0984178 s, 174 MB/s

Some verification...

That's it, the image is now stored in out.img. You can actually use the file command in order to verify that this is really a bootable disk image. The file command should tell us that the image starts with a boot sector:

$ file out.img 
out.img: DOS/MBR boot sector; partition 1 : ID=0x1, active, start-CHS (0x0,1,1), end-CHS (0xf,63,32), startsector 32, 32736 sectors

...and final flashing.

You can now write the image to your USB flash device and boot from it. Just replace /dev/sdX with the right block device. Be warned that dd won't ask again when you overwrite the wrong block device! We run sync after that to make sure any I/O buffers are flushed.

# dd if=test.img of=/dev/sdX bs=2048
# sync

That's it.

comments (2) - add comment

mw
@bart: You're welcome! :)
Thanks for the explanation, maybe this time I can remember this nonsense