Given the traction our previous post got, we thought we should jot down the steps to build a 64-bit bootable image for a RPi4. The distro we’re most familiar with is Debian, so we’ll go with a debian-like distro like Ubuntu. If you don’t feel like playing with kernel compilation and FS images, just grab the binary and dd it to an SD card!
First step, download the 64-bit ubuntu server distro for the RPi3:
Then make sure you follow the instructions from these posts which help us build the kernel and update the boot firmware. The steps from these posts are summarized below:
Build the toolchain Link to heading
1mkdir -p toolchains/aarch64
2cd toolchains/aarch64
3export TOOLCHAIN=`pwd` # Used later to reference the toolchain location
4
5cd "$TOOLCHAIN"
6wget https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.bz2
7tar -xf binutils-2.32.tar.bz2
8mkdir binutils-2.32-build
9cd binutils-2.32-build
10../binutils-2.32/configure --prefix="$TOOLCHAIN" --target=aarch64-linux-gnu --disable-nls
11make -j4
12make install
1cd "$TOOLCHAIN"
2wget https://ftp.gnu.org/gnu/gcc/gcc-9.1.0/gcc-9.1.0.tar.gz
3tar -xf gcc-9.1.0.tar.gz
4mkdir gcc-9.1.0-build
5cd gcc-9.1.0-build
1../gcc-9.1.0/configure --prefix="$TOOLCHAIN" --target=aarch64-linux-gnu --with-newlib --without-headers --disable-nls --disable-shared --disable-threads --disable-libssp --disable-decimal-float --disable-libquadmath --disable-libvtv --disable-libgomp --disable-libatomic --enable-languages=c
2make all-gcc -j4
3make install-gcc
Build the Raspberry Pi kernel Link to heading
1apt-get install bison flex
2git clone https://github.com/raspberrypi/linux.git rpi-linux
3cd rpi-linux
4git checkout origin/rpi-4.19.y # change the branch name for newer versions
5mkdir kernel-build
6PATH=$PATH:$TOOLCHAIN/bin make O=./kernel-build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
7PATH=$PATH:$TOOLCHAIN/bin make -j4 O=./kernel-build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
8export KERNEL_VERSION=`cat ./kernel-build/include/generated/utsrelease.h | sed -e 's/.*"\(.*\)".*/\1/'`
9make -j4 O=./kernel-build/ DEPMOD=echo MODLIB=./kernel-install/lib/modules/${KERNEL_VERSION} INSTALL_FW_PATH=./kernel-install/lib/firmware modules_install
1git clone https://github.com/raspberrypi/tools.git rpi-tools
2cd rpi-tools/armstubs
3git checkout 7f4a937e1bacbc111a22552169bc890b4bb26a94
4PATH=$PATH:$TOOLCHAIN/bin make armstub8-gic.bin
1echo "armstub=armstub8-gic.bin" >> config-extra.txt
2echo "enable_gic=1" >> config-extra.txt
3echo "arm_64bit=1" >> config-extra.txt
4echo "total_mem=1024" >> config-extra.txt
We now have all the necessary files to create the boot partition and boot into the ubuntu-preinstalled image. Specifically:
Kernel: rpi-linux/kernel-build/arch/arm64/boot/Image
Bootstub: rpi-tools/armstubs/armstub8-gic.bin
Modules: rpi-linux/kernel-build/kernel-install/lib/modules/${KERNEL_VERSION}
Firmware: https://github.com/RPi-Distro/firmware-nonfree
So, first thing to do after we have finished building the above is to de-compress and loop mount the ubuntu-preinstalled image we downloaded:
1xzcat ubuntu-18.04.2-preinstalled-server-arm64+raspi3.img.xz > ubuntu-18.04.2-preinstalled-server-arm64+raspi4.img
2kpartx -av ubuntu-18.04.2-preinstalled-server-arm64+raspi4.img
You should end up with 2 device files:
1/dev/mapper/loop0p1
2/dev/mapper/loop0p2
Mount them under /mnt like this:
1mount /dev/mapper/loop0p2 /mnt
2mount /dev/mapper/loop0p1 /mnt/boot/firmware
Then copy in the kernel/stub, modules and firmware:
1cp rpi-linux/kernel-build/arch/arm64/boot/Image /mnt/boot/firmware/kernel8.img
2cp rpi-tools/armstubs/armstub8-gic.bin /mnt/boot/firmware/armstub8-gic.bin
3cp -avf rpi-linux/kernel-build/kernel-install/lib/modules/${KERNEL_VERSION} /mnt/lib/modules/
4git clone https://github.com/RPi-Distro/firmware-nonfree firmware-nonfree
5cp -avf firmware-nonfree/* /mnt/lib/firmware
Append config-extra.txt to config.txt:
1cat config-extra.txt >> /mnt/boot/firmware/config.txt
and we’re done! Unmount / detach the loop device, dd it to an sdcard, plug it into a RPi4 and party!
1umount /mnt/boot/firmware
2umount /mnt
3kpartx -dv ubuntu-18.04.2-preinstalled-server-arm64+raspi4.img
4losetup -d /dev/loop0
5dd if=ubuntu-18.04.2-preinstalled-server-arm64+raspi4.img of=/dev/sdXX
If you’re too lazy to do the above, feel free to grab our image built using the above steps:
https://cloudkernels.net/ubuntu-18.04.2-preinstalled-server-arm64+raspi4+kvm.img.xz
(sha1sum: 0b1d8b72ea5410fb7928925fd76dd0218b4f7a94)
UPDATE
Links to the previous images were removed, so here’s the new ones: http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/ubuntu-18.04.3-preinstalled-server-arm64+raspi3.img.xz https://cloudkernels.net/ubuntu-18.04.3-preinstalled-server-arm64+raspi4+kvm.img.xz