How to manually create a bootable Debian 11 USB Installer w/ Firmware (UEFI)

Author: Jonathan Vasquez <jon@xyinn.org>
Last Updated: 2021-08-17-0900
Tested On: Thinkpad X1 Carbon Gen 8 / UEFI / Debian 11

Hey all,

I spent some time tinkering with manually creating a Debian 11 (Bullseye) USB w/ Firmware. I know that there is an "unofficial" image that already has the firmware built in, but I wanted to see if I could make a more flexible layout so that I can still use the "official" image but add my random stuff (firmware), in addition to just being able to use the remaining space on the USB. Originally I experimented with using the Debian documentation's recommendation to use the cp command to get the image over, after that I manually created a partition using the remaining space on the disk (Which isn't so easily visible with partitioning tools), and then proceeded to create a vfat part and then extract the firmware files into the iso. Long story short, I was able to get this working only when I made that partition an ext4 partition (This worked although I haven't reproed it - just mentioning it here), but if I also made it vfat, it ended up breaking the whole layout and I was only seeing a broken grub bootloader. After spending some time just investigating, I decided to proceed with Debian's other recommendation of using a more "flexible" approach. This ultimately ended up working but my instructions are a bit different. The original Debian instructions can be looked at here. I also tested this on my main comp which is a Thinkpad X1 Carbon Gen 8. The installer was able to boot properly from my UEFI firmware / GRUB, and the installer started up, detected my wireless card properly (using the firmware), and was able to connect to fine.

Assumptions / Disclaimers

Steps

Download the Installer + Firmware

  1. Download the Official Debian Installer for Debian 11 (Bullseye).
  2. Download the firmware package for Debian 11 (Bullseye).
    • Specifically the firmware.tar.gz.

Clear out existing USB partition structures

We will start with a completely fresh USB layout so let's go ahead and wipe everything that's existing. You may need to reboot your machine if your kernel partition tables are stale.

# sgdisk -Z /dev/sda
# wipefs -a /dev/sda

Create the FAT 16 partition on the USB

We will now create our FAT 16 partition on the USB. This will just be a single big partition that will contain the entire Debian image + our firmware files later on. You can also add whatever else you want as well. I'll be using fdisk for this. If any of the below steps are empty, it's because I just used the default values and continued by pressing [Enter].

# fdisk /dev/sda

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x3db46391.

Command (m for help): p
Disk /dev/sda: 14.76 GiB, 15846080512 bytes, 30949376 sectors
Disk model: USB DISK 3.0    
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: 0x3db46391

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-30949375, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-30949375, default 30949375): 

Created a new partition 1 of type 'Linux' and of size 14.8 GiB.

Command (m for help): p
Disk /dev/sda: 14.76 GiB, 15846080512 bytes, 30949376 sectors
Disk model: USB DISK 3.0    
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: 0x3db46391

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        2048 30949375 30947328 14.8G 83 Linux

Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): ef
Changed type of partition 'Linux' to 'EFI (FAT-12/16/32)'.

Command (m for help): p
Disk /dev/sda: 14.76 GiB, 15846080512 bytes, 30949376 sectors
Disk model: USB DISK 3.0    
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: 0x3db46391

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        2048 30949375 30947328 14.8G ef EFI (FAT-12/16/32)

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Format the partition for FAT 16

# mkdosfs /dev/sda1

Mount the partition and Debian Installer image

We will now mount our partition and the Debian installer image so we can copy over the files.

# mkdir /tmp/{source,target}
# mount -o loop,ro /home/jon/Downloads/debian-11.0.0-amd64-netinst.iso /tmp/source
# mount /dev/sda1 /tmp/target

Copy the Debian installer and firmware files.

We will be using rsync for this to easily include the hidden directories (There's only one hidden directory at the time of writing, but why have a second command ;D?):

# rsync -avP /tmp/source/ /tmp/target/

Now copy the firmware files.

# cd /tmp/target/firmware
# tar xvf /home/jon/Downloads/firmware.tar.gz

Flush data and test out the USB

Let's flush the remaining data (if any) and go ahead and test out the USB.

# cd
# sync
# umount /tmp/target

Your UEFI system should detect everything properly and GRUB should start up. Proceeding to the installer should allow your firmware to be automatically detected and used by the installer.

Have fun!