These are very rough instructions still. It is possible to script this rather nicely, taking advantage of debian’s preseeding to automate the install. The following has been written for armhf, but you can easily adapt it for arm64.
First download the latest kernel packages from Launchpad https://launchpad.net/ubuntu/+source/linux-raspi2/ e.g.
wget https://launchpad.net/~canonical-kernel-security-team/+archive/ubuntu/ppa/+build/15482714/+files/linux-image-4.15.0-1024-raspi2_4.15.0-1024.26_armhf.deb
wget https://launchpad.net/~canonical-kernel-security-team/+archive/ubuntu/ppa/+build/15482714/+files/linux-modules-4.15.0-1024-raspi2_4.15.0-1024.26_armhf.deb
Next, create a working directory and extract vmlinuz and the dtb files
dpkg-deb -x linux-image-[0-9]*raspi2*.deb /tmp/pi-kernel
dpkg-deb -x linux-modules-[0-9]*raspi2*.deb /tmp/pi-kernel
mkdir pi-installer
cd pi-installer
RASPI_VER="$(ls /tmp/pi-kernel/boot/vmlinuz* | sed 's,^\/tmp\/pi-kernel\/boot\/vmlinuz-,,g')"
# Note, in arm64 device tree files are in a broadcom folder
cp /tmp/pi-kernel/lib/firmware/$RASPI_VER/device-tree/bcm2710*.dtb .
cp /tmp/pi-kernel/boot/vmlinuz-$RASPI_VER vmlinuz
# Copy the device-tree overlays too if you need them
Download the Pi’s bootloader files - https://wiki.ubuntu.com/ARM/RaspberryPi#Updating_the_Pi_GPU_firmware_and_bootloader_files - and save to pi-installer
Create a cmdline.txt with your favourite text editor. Paste in:
grub-installer/skip=true partman-swapfile/size=1024 partman-swapfile/percentage=10 --- quiet net.ifnames=0 dwc_otg.lpm_enable=0 modprobe.blacklist=sdhci_iproc
Create a config.txt with the contents:
# boot in AArch64 (64-bit) mode
#arm_64bit=1
# Kernel and initramfs
kernel=vmlinuz
initramfs initrd.img followkernel
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
Download the initrd for the mini/netboot installer
wget http://ports.ubuntu.com/dists/bionic/main/installer-armhf/current/images/generic-lpae/netboot/initrd.gz
I’ll assume you have an Ethernet connection you can use, but if you want to do this over wifi then you need the files for your machine https://wiki.ubuntu.com/ARM/RaspberryPi#WiFi and follow https://help.ubuntu.com/lts/installation-guide/armhf/ch06s04.html or maybe https://wiki.debian.org/DebianInstaller/NetbootFirmware
This is enough to get the installer started since the raspi2 kernel has a lot of modules built in. However, you’ll probably find you get stuck at the detecting disks stage. I’m guessing this is due to missing modules.
The debian-installer doesn’t use standard deb packages, but expects everything to be packaged up as udebs. This includes lots of kernel udebs that include the modules. Unfortunately the raspi2 kernel doesn’t have any udeb module packages. A way around this is to copy all the kernel modules into the initrd:
# evbug spams the logs, get rid
rm /tmp/pi-kernel/lib/modules/$RASPI_VER/kernel/drivers/input/evbug.ko
# Generate modules.dep etc files
depmod -a -b /tmp/pi-kernel -F /tmp/pi-kernel/boot/System.map-$RASPI_VER $RASPI_VER
# Remove unneeded files
rm -r /tmp/pi-kernel/lib/modules/$RASPI_VER/initrd
rm -r /tmp/pi-kernel/boot
rm -r /tmp/pi-kernel/usr
rm -r /tmp/pi-kernel/lib/firmware/$RASPI_VER
# Add raspi2 modules to the initrd and compress
gunzip initrd.gz
find /tmp/pi-kernel/. | sed 's,^/tmp/pi-kernel\/,,g'| cpio -D /tmp/pi-kernel -R +0:+0 -H newc -o -A -F initrd
gzip initrd
We can save a few future steps if we change the name of initrd.gz to initrd.img
mv initrd.gz initrd.img
Format an SD card with MBR/msdos partition table. Create fat partition as partition 1. Create Linux partition as partition 2.
Copy everything you have in pi-installer to the fat partition. Stick it in the pi and turn on! There is a very long pause at the rainbow screen because the initrd is huge with all the kernel modules. You should eventually see the debian installer.
There will be a warning message about the lack of kernel modules. Skip it. Choose manual partitioning and give partition 1 the mount point /boot/firmware. Don’t format it. Give partitition 2 the mount point /
If I’m installing a desktop then I choose the “no automatic updates” option.
Eventually the installer will hit an error at the “Make system bootable” stage. Drop to a shell using the menu option.
Create a new cmdline.txt
# if you are installing to a usb drive use root=/dev/sda2
echo "root=/dev/mmcblk0p2 $(echo $(user-params)) elevator=deadline rootwait ro" > /target/boot/firmware/cmdline.txt
If you have a 3B+ then you need to add an entry to the flash-kernel database. See https://wiki.ubuntu.com/ARM/RaspberryPi#Update_flash-kernel_database for more details.
nano /target/etc/flash-kernel/db
Remove the installer initrd.img and vmlinuz just in case the fat partition is on the small side
rm /target/boot/firmware/initrd.img
rm /target/boot/firmware/vmlinuz
Currently the generic-lpae kernel is installed on the target system. We need to install the raspi2 kernel:
mount -o bind /dev /target/dev
#This next command turns the screen black. Wait for the cursor to appear in the bottom left of the screen.
#Install linux-raspi2 if you need the header packages
apt-install linux-image-raspi2
umount /target/dev
If the above was successful there should be an initrd.img and vmlinuz on the fat partition:
ls /target/boot/firmware
Return to the menu by typing exit. Select the “Skip bootloader” option. Finish the install and reboot!
Once in the installed system, the final thing we need to do is remove the generic kernel:
OLD_KERNEL="$(readlink /boot/vmlinuz.old | sed 's,^vmlinuz-,,g')"
sudo apt-get --autoremove purge linux-generic-lpae linux-image-generic-lpae linux-headers-generic-lpae linux-image-$OLD_KERNEL linux-headers-$OLD_KERNEL linux-modules-$OLD_KERNEL linux-modules-extra-$OLD_KERNEL
That’s it! Phew!