Create a hybrid USB Image

The goal is to create an image file which can be copied onto a USB stick and booted both via legacy BIOS as well as UEFI.

This document assumes
  • a local loop device is used (much faster than directly on USB stick)
  • the target USB device is /dev/sdb
  • locally, the new system will be mounted under /mnt

Environment variables:
export USB_DEV=/dev/sdb
# note the trailing 'p'!
export TARGET=/dev/loop0p
export MNT_TGT=/mnt

Please be extra careful setting those and ensure these are set at every step, as otherwise this may render the host system unusable.

Preparation

  1. Create an empty file slightly smaller than the minimal USB stick size supported, e.g. 7GiB:
    apt-get --yes install pv
    pv --stop-at-size --size 7G /dev/zero > /tmp/usb.img
    
  2. make image available as block device
    losetup -fP /tmp/usb.img
    
  3. Check the correct loop device is enabled:
    losetup -a
    
  4. Create an initial partition table with enough room for MBR/!BIOS, (U)EFI and system, e.g.
    parted --script --align optimal ${TARGET%p} -- mktable gpt
    parted --script --align optimal ${TARGET%p} -- mkpart biosgrub fat32 1MiB 4MiB
    parted --script --align optimal ${TARGET%p} -- mkpart efi fat32 4MiB 512MiB
    parted --script --align optimal ${TARGET%p} -- mkpart linux ext4 512MiB 1024MiB
    parted --script --align optimal ${TARGET%p} -- mkpart linux ext4 1024MiB -1
    parted --script --align optimal ${TARGET%p} -- set 1 bios_grub on
    parted --script --align optimal ${TARGET%p} -- set 2 esp on
    
  5. Check layout
    parted ${TARGET%p} -- print
    should show
             
    Model: Loopback device (loopback)
    Disk /dev/loop0: 7516MB
    Sector size (logical/physical): 512B/512B
    Partition Table: gpt
    Disk Flags: 
    
    Number  Start   End     Size    File system  Name      Flags
     1      1049kB  4194kB  3146kB               biosgrub  bios_grub
     2      4194kB  537MB   533MB                efi       boot, esp
     3      537MB   1074MB  537MB                linux
     4      1074MB  7515MB  6441MB               linux
    
  6. Create file systems
    mkfs -t vfat -n EFIGRUB ${TARGET}2
    mkfs -t ext4 -L BOOT ${TARGET}3
    mkfs -t ext4 -L SYSTEM ${TARGET}4
    
  7. Create first backup image in case something goes wrong
    apt install pigz pv
    pv ${TARGET%p} | pigz -c > /tmp/bootimage.rescue.gz
  8. Mount file systems
    mkdir -p $MNT_TGT/
    mount ${TARGET}4 $MNT_TGT
    mkdir -p $MNT_TGT/boot
    mount ${TARGET}3 $MNT_TGT/boot
    mkdir -p $MNT_TGT/boot/efi
    mount ${TARGET}2 $MNT_TGT/boot/efi
    

Installing Debian

  1. Bootstrap Debian
    debootstrap buster $MNT_TGT
    
  2. Create various mounts/bind-mounts
    mount -t sysfs sys $MNT_TGT/sys
    mount -t proc proc $MNT_TGT/proc
    mount --bind /dev $MNT_TGT/dev
    mount --bind /dev/pts $MNT_TGT/dev/pts
    
  3. log into chroot
    chroot $MNT_TGT /bin/bash
  4. change hostname
    echo atlastender > /etc/hostname
    
  5. add password for root, e.g. bench
    echo "root:bench" | chpasswd --crypt-method SHA512
  6. setup /etc/fstab
    (
    echo -e "UUID=\"$(blkid -s UUID -o value ${TARGET}4)\"\t/\text4\terrors=remount-ro\t0\t1"
    echo -e "UUID=\"$(blkid -s UUID -o value ${TARGET}3)\"\t/boot\text4\terrors=remount-ro\t0\t2"
    echo -e "UUID=\"$(blkid -s UUID -o value ${TARGET}2)\"\t/boot/efi\tvfat\tdefaults\t0\t2"
    echo -e "tmpfs\t\t/tmp\ttmpfs\tdefaults,nodev,nosuid,size=2500m\t0\t0" ) > /etc/fstab
    
  7. install kernel and BIOS grub (when asked where to install do not install it)
    apt-get --yes --no-install-recommends install linux-image-amd64
    DEBIAN_FRONTEND=noninteractive apt-get --yes --no-install-recommends install grub-pc
    
  8. install EFI grub resulting in removal of grub-pc
    apt-get --yes install grub-efi
    sed -i 's/main$/main contrib non-free/' /etc/apt/sources.list
    apt-get update
    apt-get --yes install firmware-linux firmware-linux-free firmware-linux-nonfree
    
  9. ensure grub is really installed
    grub-install --removable --no-nvram --no-uefi-secure-boot --target=x86_64-efi
    grub-install --removable --target=i386-pc ${TARGET%p}
    update-grub
    

Install software into image

Now install any software wanted into the chroot

Finishing steps

  1. leave the chroot with exit
  2. umount everything
    umount $MNT_TGT/boot/efi
    umount $MNT_TGT/boot
    umount $MNT_TGT/dev/pts
    umount $MNT_TGT/dev
    umount $MNT_TGT/proc
    umount $MNT_TGT/sys
    umount $MNT_TGT
    
  3. remove loop back device, e.g.
    losetup -D
  4. copy image to USB stick
    pv /tmp/usb.img > $USB_DEV
    

-- CarstenAulbert - 03 Jun 2019

This topic: ATLAS > WebHome > CreateHybridUSBImage
Topic revision: 05 Jun 2019, CarstenAulbert
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback