Legacy Bios, UEFI and SecureBoot ready Ubuntu Live image customization

This article will provide you with a core information on how to create boot-able Ubuntu Live customized isohybrid image to get you started with your own Ubuntu distro spin-off. The output image will be amd64 customized Ubuntu live image, capable to boot in all three boot modes: Legacy Bios, UEFI and SecureBoot.

The article will not get into much detail about how to perform the actual squashfs system customization. However, instead it will concentrate on all the steps regarding unpacking the official Ubuntu Iso and putting all parts back together to produce bootable isohybrid image supporting Legacy Bios, UEFI and SecureBoot modes.

Prerequisites

As always we start by prerequisites and optional package installation:

$ sudo apt-get install dumpet xorriso squashfs-tools gddrescue

Downloading Ubuntu ISO image

The first part of creating your own customized Linux distro based on the Ubuntu Linux is to download the official Ubuntu ISO image. Create a new directory custom-ubuntu to hold all files required by this project. EFI and its SecureBoot feature is not supported on i386 architecture so download any amd64 version of the Ubuntu ISO image and store it within custom-ubuntu directory:

$ mkdir custom-ubuntu
$ cd custom-ubuntu/
$ wget http://url/to/ubuntu/image.iso

Extract ISO content

At this stage we need to mount and extract all content from the official Ubuntu ISO image. For this we use xorriso command. The below xorriso command will extract all files from original ISO image into custom-iso directory. Eg.:

$ xorriso -osirrox on -indev ubuntu-16.04-desktop-amd64.iso -extract / custom-iso

Customization Process

At this stage perform a customization within custom-iso directory. As mentioned before, this the process of how you customize your image is up to you. Below you can find few hints to get you started:

    • EFI bootloader menu: custom-iso/boot/grub/grub.cfg
    • non-EFI legacy boot menu: custom-iso/isolinux/txt.cfg
    • squashfs filesystem: custom-iso/casper/filesystem.squashfs

To customize squashfs filesystem first decompress filesystem.squashfs:

$ sudo  unsquashfs custom-iso/casper/filesystem.squashfs
Parallel unsquashfs: Using 8 processors
180141 inodes (192876 blocks) to write

[======================/] 192876/192876 100%
created 138452 files
created 18797 directories
created 41566 symlinks
created 81 devices
created 0 fifos

Enter squashfs using chroot command, make changes and exit:

$ sudo chroot squashfs-root/
# mount none -t proc /proc; mount none -t sysfs /sys; mount none -t devpts /dev/pts

The this point you within chroot environment of your new system. Make changes such as package installation and exit chroot:

# exit
exit
$ sudo umount -f squashfs-root/proc squashfs-root/sys squashfs-root/dev/pts

Compress new squashfs:

$ sudo mksquashfs squashfs-root/ custom-iso/casper/filesystem.squashfs

Creating a boot-able isohybrid ISO image

Obtain isohybrid MBR isohdpfx.bin from the original ubuntu ISO image using dd command :

$ sudo dd if=ubuntu-16.04-desktop-amd64.iso bs=512 count=1 of=custom-iso/isolinux/isohdpfx.bin

Build new isohybrid ISO image from within custom-iso directory using xorriso command. Note the “.” at the end of the the xorriso command:

$ cd custom-iso/
$ sudo xorriso -as mkisofs -isohybrid-mbr isolinux/isohdpfx.bin \ 
-c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 \
-boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot \
-isohybrid-gpt-basdat -o ../custom-ubuntu.iso .

xorriso 1.3.2 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:../custom-ubuntu.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data, 1444g free
Added to ISO image: directory '/'='/home/lubos/custom-ubuntu/custom-iso'
xorriso : UPDATE : 549 files added in 1 seconds
xorriso : UPDATE : 549 files added in 1 seconds
xorriso : NOTE : Copying to System Area: 512 bytes from file '/home/lubos/custom-ubuntu/custom-iso/isolinux/isohdpfx.bin'
libisofs: NOTE : Automatically adjusted MBR geometry to 1017/89/32
libisofs: NOTE : Aligned image size to cylinder size by 367 blocks
xorriso : UPDATE :  100.00% done
ISO image produced: 724104 sectors
Written to medium : 724104 sectors at LBA 0
Writing to 'stdio:../custom-ubuntu.iso' completed successfully.

The above command will result in new ../custom-ubuntu.iso isohybrid image.

Obtaining Image information

If all went well our custom-ubuntu directory should now contain a new isohybrid image custom-ubuntu.iso:

$ ls
custom-iso  custom-ubuntu.iso  orig-iso  squashfs-root  ubuntu-16.04-desktop-amd64.iso

Partition table:

$ sudo fdisk -lu custom-ubuntu.iso

Disk custom-ubuntu.iso: 1.4 GiB, 1482964992 bytes, 2896416 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x751e87f5

Device             Boot Start     End Sectors  Size Id Type
custom-ubuntu.iso1 *        0 2896415 2896416  1.4G  0 Empty
custom-ubuntu.iso2        540    5083    4544  2.2M ef EFI (FAT-12/16/32)

Header and catalog information:

$ sudo dumpet -i custom-ubuntu.iso 
Validation Entry:
        Header Indicator: 0x01 (Validation Entry)
        PlatformId: 0x00 (80x86)
        ID: ""
        Checksum: 0x55aa
        Key bytes: 0x55aa
Boot Catalog Default Entry:
        Entry is bootable
        Boot Media emulation type: no emulation
        Media load segment: 0x0 (0000:7c00)
        System type: 0 (0x00)
        Load Sectors: 4 (0x0004)
        Load LBA: 701876 (0x000ab5b4)
Section Header Entry:
        Header Indicator: 0x91 (Final Section Header Entry)
        PlatformId: 0xef (EFI)
        Section Entries: 1
        ID: ""
Boot Catalog Section Entry:
        Entry is bootable
        Boot Media emulation type: no emulation
        Media load address: 0 (0x0000)
        System type: 0 (0x00)
        Load Sectors: 4544 (0x11c0)
        Load LBA: 135 (0x00000087)

Eltorito validation header:

$ isoinfo -d -i custom-ubuntu.iso 
CD-ROM is in ISO 9660 format
System id: 
Volume id: ISOIMAGE
Volume set id: 
Publisher id: 
Data preparer id: XORRISO-1.3.2 2013.08.07.110001, LIBISOBURN-1.3.2, LIBISOFS-1.3.2, LIBBURN-1.3.2
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: 724104
El Torito VD version 1 found, boot catalog is in sector 117
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 AB5B4 701876

Boot catalog and relevant image paths:

# xorriso -indev custom-ubuntu.iso -toc -pvd_info 
xorriso 1.3.2 : RockRidge filesystem manipulator, libburnia project.

xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE : 549 nodes read in 1 seconds
xorriso : NOTE : Detected El-Torito boot information which currently is set to be discarded
Drive current: -indev 'custom-ubuntu.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record  : El Torito , ISOLINUX isohybrid MBR pointing to boot image
Media summary: 1 session, 724104 data blocks, 1414m data, 1442g free
Volume id    : 'ISOIMAGE'
Drive current: -indev 'custom-ubuntu.iso'
Drive type   : vendor 'YOYODYNE' product 'WARP DRIVE' revision 'FX01'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Media blocks : 724104 readable , 755967444 writable , 756691572 overall
Boot record  : El Torito , ISOLINUX isohybrid MBR pointing to boot image
Boot catalog : '/isolinux/boot.cat'
Boot image   : '/isolinux/isolinux.bin' , boot_info_table=on
Boot image   : '/boot/grub/efi.img' , platform_id=0xEF 
TOC layout   : Idx ,  sbsector ,       Size , Volume Id
ISO session  :   1 ,         0 ,    724104s , ISOIMAGE
Media summary: 1 session, 724104 data blocks, 1414m data, 1442g free
Media nwa    : 724128s
Drive current: -indev 'custom-ubuntu.iso'
PVD address  : 16s
Volume Id    : ISOIMAGE
Volume Set Id: 
Publisher Id : 
Preparer Id  : XORRISO-1.3.2 2013.08.07.110001, LIBISOBURN-1.3.2, LIBISOFS-1.3.2, LIBBURN-1.3.2
App Id       : 
System Id    : 
CopyrightFile: 
Abstract File: 
Biblio File  : 
Creation Time: 2016020823095700
Modif. Time  : 2016020823095700
Expir. Time  : 0000000000000000
Eff. Time    : 0000000000000000

Booting a new custom Ubuntu image

Please note that the new produced custom Ubuntu image is meant to boot in all three modes, that is Legacy BIOS, UEFI only as well as UEFI with SecureBoot option enabled. However, this is not guaranteed and issues may occur due to the hardware firmware bugs etc.

To boot your new custom ubuntu image either burn the result ISO on CD disk or use ddrescue command to clone it to your USB stick:

$ sudo ddrescue custom-ubuntu.iso /dev/sdX --force -D

Your USB stick now contains customized Ubuntu live system. All should be now ready to boot from your USB stick.