The other day, I decided to dust off my Raspberry Pi 4 and make something with it. I was recently introduced to Gentoo and quite liked it, so I wanted to use it for whatever project I was going to do. However, I couldn't find any disk images or even install guides for the Pi 4!
This page documents my journey getting a functional Gentoo system up and running on a Raspberry Pi 4.
Requirements
- Raspberry Pi 4 (I used a 4GB model)
- 8GB+ microSD card (I recommend 32GB or more)
- A VM or computer running Gentoo
- Time, patience, and compute
Creating the disk image
This section is based on the Gentoo Wiki's Pi 3 64-bit install guide.
Setting up the build environment
First, you'll need to install crossdev and git:
# emerge --ask sys-devel/crossdev dev-vcs/git
Crossdev needed its own overlay when I first tried to run it, so create one like this:
# mkdir -p /var/db/repos/localrepo-crossdev/{profiles,metadata}
# echo 'crossdev' > /var/db/repos/localrepo-crossdev/profiles/repo_name
# echo 'masters = gentoo' > /var/db/repos/localrepo-crossdev/metadata/layout.conf
# chown -R portage:portage /var/db/repos/localrepo-crossdev
# tee /etc/portage/repos.conf/crossdev.conf <<EOF
> [crossdev]
> location = /var/db/repos/localrepo-crossdev
> priority = 10
> masters = gentoo
> auto-sync = no
> EOF
Now build the ARM64 compiler toolchain:
# crossdev -t aarch64-unknown-linux-gnu
Compiling the kernel
As a regular user, clone the Raspberry Pi Foundation's repositories:
$ mkdir rpi && cd rpi
$ git clone -b stable --depth=1 https://github.com/raspberrypi/firmware
$ git clone https://github.com/raspberrypi/linux
Navigate to the kernel source and configure the kernel:
$ cd linux
$ ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make bcm2711_defconfig
$ ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make menuconfig
You can make whatever changes you want if you know what you're doing. I don't, so I just enabled F2FS support and changed the frequency governor:
File systems --->
<*> F2FS filesystem support
[*] F2FS Status information
[*] F2FS Access Control Lists
[*] F2FS Security Labels
CPU Power Management --->
CPU Frequency scaling --->
Default CPUFreq governor --->
(X) ondemand
Next, compile the kernel:
$ ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make -j$(nproc)
Preparing the virtual disk
Make a blank disk image and convince Linux that it's a block device. I was using VirtualBox, so I just attached a 4GB VDI to the machine, but you can also use dd and losetup if you're a nerd.
Run fdisk and create the Pi's FAT32 boot partition. 128MB should be enough:
# fdisk /dev/sdb (replace /dev/sdb with whatever device your disk image is mounted at)
Command (m for help): o (format the partition table as DOS)
Command (m for help): n (new partition)
Select: p
Partition number: [Enter]
First sector: [Enter]
Last sector, +sectors or +size{K,M,G,T,P}: +128M
Command (m for help): a (mark it as bootable)
Command (m for help): t (change the partition type)
Partition type: c (FAT32)
You can partition the rest of the disk however you want, but I just made one root partition:
Command (m for help): n
Select: p
Partition number: [Enter]
First sector: [Enter]
Last sector, +sectors or +size{K,M,G,T,P}: [Enter] (fill all available space)
Save and exit fdisk, then format the boot partition as FAT32:
Command (m for help): w
# mkfs.vfat -F 32 /dev/sdb1
Format the rest of the partitions. I used F2FS with the following options:
# mkfs.f2fs -O extra_attr,inode_checksum,sb_checksum /dev/sdb2
Copying the files
Mount the root partition, then all the additional partitions:
# mkdir /mnt/gentoo
# mount /dev/sdb2 /mnt/gentoo
# mkdir /mnt/gentoo/boot
# mount /dev/sdb1 /mnt/gentoo/boot
Download and extract the ARM64 stage3 tarball:
# cd /mnt/gentoo
# links https://gentoo.org/downloads
# tar -xpvf stage3-* --xattrs-include='*.*' --numeric-owner
And the latest repository snapshot:
# wget http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2
# tar -xpvf portage-latest.tar.bz2 --strip-components=1 -C /mnt/gentoo/var/db/repos/gentoo
Copy the boot files from the Raspberry Pi firmware repository:
# cp -rv ~user/rpi/firmware/boot/* /mnt/gentoo/boot
Copy the kernel we compiled to the boot partition:
# cp ~user/rpi/linux/arch/arm64/boot/Image /mnt/gentoo/boot/kernel8.img
Move the Pi 4's 32-bit DTB out of the way and copy in the 64-bit one:
# cd /mnt/gentoo/boot
# mv bcm2711-rpi-4-b.dtb bcm2711-rpi-4-b.dtb_32
# cp ~user/rpi/linux/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dtb ./
Install the kernel modules:
# cd ~user/rpi/linux
# ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- make modules_install INSTALL_MOD_PATH=/mnt/gentoo
The Raspberry Pi 3 guide asks you to write a massive udev rule, but I'm lazy, so I just made a pastebin:
# cd /mnt/gentoo/etc/udev/rules.d
# wget https://pastebin.com/wP6yzSpu -O 99-com.rules
Download the Pi 4's Wi-Fi firmware:
# mkdir -p /mnt/gentoo/lib/firmware/brcm && cd /mnt/gentoo/lib/firmware/brcm
# wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt
# wget https://github.com/armbian/firmware/raw/master/brcm/brcmfmac43455-sdio.bin
The Pi 3B+ and 4 use the same Bluetooth chip as far as I can tell, so this should be the right firmware for it:
# wget https://raw.githubusercontent.com/RPi-Distro/bluez-firmware/master/broadcom/BCM4345C0.hcd
Set the root password manually (passwd -R didn't work for me):
# cd /mnt/gentoo/etc
# cat shadow | awk -F: -v p="$(openssl passwd -6 raspberry)" '$1=="root" {OFS=":";$2=p} {print $0}' > shadow
I also used awk shenanigans to disable the serial console on /dev/ttyAMA0 (which apparently conflicts with Bluetooth):
# cat inittab | awk '$3=="ttyAMA0" {$1 = "#" $1} {print $0}' > inittab
Update /etc/fstab to match the partitions on the SD card. Mine looks like this:
/dev/mmcblk0p1 /boot vfat noauto,noatime 1 2
/dev/mmcblk0p2 / f2fs noatime 0 0
Create /boot/cmdline.txt:
# cd /mnt/gentoo/boot
# echo 'root=/dev/mmcblk0p2 rootfstype=f2fs rootwait' > cmdline.txt
The Pi also needs a /boot/config.txt file. I just created it with the same options as the Pi 3 guide:
disable_overscan=1
dtoverlay=vc4-fkms-v3d
hdmi_drive=2
dtparam=audio=on
gpu_mem=16
arm_64bit=1
First boot
The disk image I built boots on my Pi 4, but it took the entire day to create it and document my process, so I haven't been able to test anything yet. I'll update this page tomorrow.
CFLAGS (I think)
This should be the right CFLAGS setup for the Pi 4:
CFLAGS="-march=armv8-a+crc+simd -mtune=cortex-a72 -ftree-vectorize -O2"