I recently tried to make a bootable ISO using Buildroot, and encountered some difficulty. In that process, I realized that I don’t actually know what all goes into a bootable Linux ISO. So this is my collection of notes that I made while trying to answer that question.
Starting out, the ISOLINUX documentation is going to be my guide, along with a Core Linux ISO. I was originally going to use an Ubuntu ISO, but I had a hard time getting the Ubuntu ISO to boot in qemu without having a graphic display attached to it (the box I’m running this all on is headless).
Loopback mount of the ISO
1 2 3 4 5 6 7 8 9 10 11 12 13 14
This is a nice simple looking ISO.
What’s in the isolinux.cfg?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
And booting it is pretty simple too:
Note that I’m using the
-curses option because I don’t have a
display on this machine. Drop that if you’re running from desktop
Linux. If you do run with
-curses, note that you can press
to get into the QEMU monitor mode and type
quit to exit.
What else is on here?
So that’s a standard
bzImage kernel, renamed to
vmlinuz for some
reason. Good enough!
initrd referenced above. Together, those are the only
real files that the
Can I repack this?
A good test to see if I get how an image like this works is to figure out how to recreate it from the files. One important thing here is that this is a bootable ISO:
Which is likely an extra wrinkle.
Going off the instructions, you can get a binary version of
going to use 6.03.
For a little bit of an added challenge, I’m going to make the directory layout different - I’m just going to stick all the files in the root of the new ISO.
1 2 3
Next, the instructions say to copy
And now, I’m supposed to create
isolinux.cfg. Here’s what I put in it:
1 2 3 4 5 6 7
One thing that isn’t clear to me in all of this is how
knows where to find these files. Anyway, I’ll keep following the
instructions for now. Next up is creating the actual ISO:
1 2 3 4 5 6 7 8 9 10
Alright, that seemed to work. Let’s try booting it!
This boots it successfully!
What do the -b and -c flags do in mkisofs?
The man page for mkisofs is actually called genisoimage, for some
mkisofs --help reveals this.
-b eltorito_boot_image Specifies the path and filename of the boot image to be used when making an El Torito bootable CD for x86 PCs. The pathname must be relative to the source path specified to genisoimage. This option is required to make an El Torito bootable CD. The boot image must be exactly 1200 kB, 1440 kB or 2880 kB, and genisoimage will use this size when creating the output ISO9660 filesystem. The PC BIOS will use the image to emulate a floppy disk, so the first 512-byte sector should contain PC boot code. This will work, for example, if the boot image is a LILO-based boot floppy. If the boot image is not an image of a floppy, you need to add either -hard-disk-boot or -no-emul-boot. If the system should not boot off the emulated disk, use -no-boot.
So this is useful! It says that the argument passed to
-b is going
to be used as the boot image. So what the heck is
It is, apparently, a standard for how PCs should search for boot code
on a CD-ROM. If you’re really curious, you can have a look at the
Intel and Phoenix. Section
5.3 describes “No Emulation Booting”, which goes into some awesome x86
history describing interrupts that you can use to retrieve more boot
One thing that the standard mentions is the “boot catalog”. The man
page confirms that
-c is used to specify the filename to be used for
the boot catalog. What is the boot catalog? According to section 2.0,
it’s a “collection of [0x]20-byte entries, packed [0x]40 entries to
the sector”. Section 2.5 explains that these contain a Header ID, a
platform ID (x86/PowerPC/Mac), an ID string, a checksum, and two key
bytes. These also have a bit more information about what kind of boot
media it is, how many sectors should be loaded, etc. I’m personally
quite happy that
mkisofs makes this for me and I don’t really have
to think much about what’s going on here.
So how does isolinux know where to find isolinux.cfg?
txt/syslinux.cfg.txt in the
syslinux source directory
explains the answer to this:
*ISOLINUX* (before 4.02) used the configuration filename of isolinux.cfg, searching /boot/isolinux (starting 2.00), then /isolinux and /. As of 4.02, *ISOLINUX* will search for isolinux.cfg then syslinux.cfg in /boot/isolinux before searching for the same files in /isolinux, /boot/syslinux, /syslinux, and /.
So, basically, I got lucky that it searches for it in the root, since I didn’t read those docs ahead of time.
Looks like the process of making a bootable Linux ISO is pretty
straight-forward. You take the
isolinux.bin and make an
isolinux.cfg, put them in the right place, and tell
to find them. Awesome! Now I’m going to go back to figuring out why
the ISO I’m making using buildroot isn’t booting right.