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:
1
|
|
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 ESC 2
to get into the QEMU monitor mode and type quit
to exit.
What else is on here?
1 2 |
|
So that’s a standard bzImage
kernel, renamed to vmlinuz
for some
reason. Good enough!
1 2 |
|
That’s the initrd
referenced above. Together, those are the only
real files that the isolinux.cfg
references.
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:
1 2 |
|
Which is likely an extra wrinkle.
Going off the instructions, you can get a binary version of
syslinux
from
kernel.org. I’m
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 isolinux.bin
and ldlinux.c32
:
1 2 |
|
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 isolinux
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!
1
|
|
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
reason. Doing 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
El Torito?
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
specification from
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
information.
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?
The file 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.
Conclusion
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 mkisofs
where
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.