Making an Ubuntu 20.04 ISO that will boot on UEFI systems
As part of our overall install process,
for years we've used customized Ubuntu server install images (ie,
ISOs, often burned on to actual DVDs) that were set up with preseed
files for the Debian installer and a few other things we wanted on
our servers from the start. These ISOs have been built in the
traditional way with mkisofs
and so booted with isolinux
. This was
fine for a long time because pretty much all of our servers used
traditional MBR BIOS booting, which is what ISOs use isolinux for.
However, for or reasons outside the scope of this entry, today we
wanted to make our 20.04 ISO image also boot on systems using UEFI
boot. This turned out to be more complicated than I expected.
(For basic background on this, see my earlier entry on setting up a 20.04 ISO image to auto-install a server.)
First, as my co-workers had already discovered long ago, Linux ISOs do UEFI booting using GRUB2, not isolinux, which means that you need to customize the grub.cfg file in order to add the special command line parameters to tell the installer about your 20.04 installer data. We provide the installer data in the ISO image, which means that our kernel command line arguments contain a ';'. In GRUB2, I discovered that this must be quoted:
menuentry "..." { [...] linux /casper/vmlinuz quiet "ds=nocloud;s=/cdrom/cslab/inst/" --- [...] }
(I advise you to modify the title of the menu entries in the ISO's grub.cfg so that you know it's using your modified version. It's a useful reassurance.)
If you don't do this quoting, all the kernel (and the installer)
see is a 'ds=nocloud
' argument. Your installer data will be ignored
(despite being on the ISO image) and you may get confused about
what's wrong.
The way ISOs are made bootable is that they have at least one El
Torito boot
section (see also the OsDev Wiki).
A conventional BIOS bootable ISO has one section; one that can also
be booted through UEFI has a second one that is more intricate. You
can examine various information about El Torito boot sections with
dumpet
, which is in the
standard Ubuntu repositories.
In theory I believe mkisofs
can be used to add a suitable extra
ET boot section. In practice, everyone has switched to building ISO
images with xorriso
,
for good reason. The easiest to follow guide on using xorriso
for
this is the Debian Wiki page on Repacking a Debian ISO, which not only has
plenty of examples but goes the extra distance to explain what the
many xorriso
arguments mean and do (and why they matter).
This is extremely useful since xorriso
has a large and complicated
manpage and other documentation.
Important update: The details of much of the rest of this entry turns out to not be right, because I had a corrupted ISO tree with altered files. For a better procedure and more details, see The better way to make an Ubuntu 20.04 ISO that will boot on UEFI systems. The broad overview of UEFI requiring a GRUB2 EFI image is accurate, though.
However, Ubuntu has a surprise for us (of course). UEFI bootable
Linux ISOs need a GRUB2 EFI image that is embedded into the ISO.
Many examples, including the Debian wiki page, get this image from a
file in the ISO image called boot/grub/efi.img
. The Ubuntu 20.04.1
ISO image has such a file, but it is not actually the correct file
to use. If you build an ISO using this efi.img as the El Torito EFI
boot image, it will fail on at least some UEFI systems. The file
you actually want to use turns out to be '[BOOT]/2-Boot-NoEmul.img
'
in the ISO image.
(Although the 20.04.1 ISO image's isolinux/isolinux.bin
works fine
as the El Torito BIOS boot image, it also appears to not be what
the original 20.04.1 ISO was built with. The authentic thing seems
to be '[BOOT]/1-Boot-NoEmul.img
'. I'm just thankful that Ubuntu
put both in the ISO image, even if it sort of hid them.)
Update: These '[BOOT]
' files aren't in the normal ISO image
itself, but are added by 7z
(likely from the El Torito boot
sections) when it extracts the ISO image into a directory tree for
me. The isolinux.bin
difference is from a boot info table that
contains the block offsets of isolinux.bin
in the ISO. The efi.img
differences are currently more mysterious.
The resulting xorriso
command line I'm using right now
is more or less:
xorriso -as mkisofs -r \ -V 'Our Ubuntu 20.04 UEFI enabled' \ -o cslab_ubuntu_20.04.iso \ -isohybrid-mbr isohdpfx.bin \ -J -joliet-long \ -b isolinux/isolinux.bin -c isolinux/boot.cat \ -boot-load-size 4 -boot-info-table -no-emul-boot \ -eltorito-alt-boot -e '[BOOT]/2-Boot-NoEmul.img' -no-emul-boot \ -isohybrid-gpt-basdat \ SCRATCH-DIRECTORY
(assuming that SCRATCH-DIRECTORY
is your unpacked and modified
version of the 20.04.1 ISO image, and isohdpfx.bin
is generated
following the instructions in the Debian wiki page.)
The ISO created through this definitely boots in VMWare in both UEFI and BIOS mode (and installs afterward). I haven't tried it in UEFI mode on real hardware yet and probably won't for a while.
PS: If you use the Debian wiki's suggested xorriso
command line
to analyze the 20.04.1 ISO image, it will claim that the El Torito
EFI boot image is 'boot/grub/efi.img'. This is definitely not the
case, which you can verify by using dumpet
to extract both of
the actual boot images from the ISO and then cmp
to see what they
match up with.
|
|