~keith's Web site

Gentoo on Raspberry Pi 4

Caution: Page currently under construction.

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.

Disclaimer: This is probably not the best way to install Gentoo! I'm an idiot, and this is just a page documenting what I did.

Requirements

Creating the disk image

This section is based on the Gentoo Wiki's Pi 3 64-bit install guide.

Note: I did this in a VirtualBox VM running a fresh Gentoo install. If you're doing this on a real PC, some things will be a bit different.

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
Tip: This will take a while, so you should take a break and cuddle a cute boy or something. hugging emoticons

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)
Tip: This also takes a long time to complete. Grab something to eat while you wait.

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
The disk image is now finished, and can be flashed to an SD card and booted! smiling face

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"