Motivation
Andy (RattusRattus) and I have been formalising instructions for using Pete Batard's version of Tianocore (and therefore UEFI booting) for the Raspberry Pi 4 together with a Debian arm64 netinst to make a modified Debian installer on a USB stick which "just works" for a Raspberry Pi 4.
Thanks also to Steve McIntyre for initial notes that got this working for us and also to Emmanuele Rocca for putting up some useful instructions for copying.
Recipe
Plug in a USB stick - use dmesg or your favourite method to see how it is identified.
Make a couple of mount points under /mnt - /mnt/data and /mnt/cdrom
1. Grab a USB stick, Partition using MBR. Make a single VFAT
partition, type 0xEF (i.e. EFI System Partition)
For a USB stick (identified as sdX) below:
$ sudo parted --script /dev/sdX mklabel msdos
$ sudo parted --script /dev/sdX mkpart primary fat32 0% 100%
$ sudo mkfs.vfat /dev/sdX1
$ sudo mount /dev/sdX1 /mnt/data/
Download an arm64 netinst.iso
https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-12.2.0-arm64-netinst.iso
2. Copy the complete contents of partition *1* from a Debian arm64
installer image into the filesystem (partition 1 is the installer
stuff itself) on the USB stick, in /
$ sudo kpartx -v -a debian-12.2.0-arm64-netinst.iso
# Mount the first partition on the ISO and copy its contents to the stick
$ sudo mount /dev/mapper/loop0p1 /mnt/cdrom/
$ sudo rsync -av /mnt/cdrom/ /mnt/data/
$ sudo umount /mnt/cdrom
3. Copy the complete contents of partition *2* from that Debian arm64
installer image into that filesystem (partition 2 is the ESP) on
the USB stick, in /
# Same story with the second partition on the ISO
$ sudo mount /dev/mapper/loop0p2 /mnt/cdrom/
$ sudo rsync -av /mnt/cdrom/ /mnt/data/ $ sudo umount /mnt/cdrom
$ sudo kpartx -d debian-testing-amd64-netinst.iso $ sudo umount /mnt/data
4. Grab the rpi edk2 build from https://github.com/pftf/RPi4/releases
(I used 1.35) and extract it. I copied the files there into *2*
places for now on the USB stick:
/ (so the Pi will boot using it)
/rpi4 (so we can find the files again later)
5. Add the preseed.cfg file (attached) into *both* of the two initrd
files on the USB stick
- /install.a64/initrd.gz and
- /install.a64/gtk/initrd.gz
cpio is an awful tool to use :-(. In each case:
$ cp /path/to/initrd.gz .
$ gunzip initrd.gz
$ echo preseed.cfg | cpio -H newc -o -A -F initrd
$ gzip -9v initrd
$ cp initrd.gz /path/to/initrd.gz
If you look at the preseed file, it will do a few things:
- Use an early_command to unmount /media (to work around Debian bug
#1051964)
- Register a late_command call for /cdrom/finish-rpi (the next
file - see below) to run at the end of the installation.
- Force grub installation also to the EFI removable media path,
needed as the rpi doesn't store EFI boot variables.
- Stop the installer asking for firmware from removable media (as
the rpi4 will ask for broadcom bluetooth fw that we can't
ship. Can be ignored safely.)
6. Copy the finish-rpi script (attached) into / on the USB stick. It
will be run at the end of the installation, triggered via the
preseed. It does a couple of things:
- Copy the edk2 firmware files into the ESP on the system that's
just been installer
- Remove shim-signed from the installed systems, as there's a bug
that causes it to fail on rpi4. I need to dig into this to see
what the issue is.
That's it! Run the installer as normal, all should Just Work (TM).
BlueTooth didn't quite work : raspberrypi-firmware didn't install until adding a symlink for boot/efi to /boot/firmware
20231127 - This may not be necessary because raspberrypi-firmware path has been fixed
Preseed.cfg
# The preseed file itself causes a problem - the installer medium is
# left mounted on /medis so things break in cdrom-detect. Let's see if
# we can fix that!
d-i preseed/early_command string umount /media || true
# Run our command to do rpi setup before reboot
d-i preseed/late_command string /cdrom/finish-rpi
# Force grub installation to the RM path
grub-efi-arm64 grub2/force_efi_extra_removable boolean true
# Don't prompt for missing firmware from removable media,
# e.g. broadcom bluetooth on the rpi.
d-i hw-detect/load_firmware boolean false
Finish.rpi
!/bin/sh
set -x
grep -q -a RPI4 /sys/firmware/acpi/tables/CSRT
if [ $? -ne 0 ]; then
echo "Not running on a Pi 4, exit!"
exit 0
fi
# Copy the rpi4 firmware binaries onto the installed system.
# Assumes the installer media is mounted on /cdrom.
cp -vr /cdrom/rpi4/. /target/boot/efi/.
# shim-signed doesn't seem happy on rpi4, so remove it
mount --bind /sys /target/sys
mount --bind /proc /target/proc
mount --bind /dev /target/dev
in-target apt-get remove --purge --autoremove -y shim-signed