Content is under CC-BY-SA 3.0.

Gentoo (64 bit; arm64) on Raspberry Pi 4

This is a guide to setting up Gentoo (arm64) on a Raspberry Pi 4.

We will bootstrap the Gentoo install from a stage3 provided by gentoo.org, via Raspbian.

You do not need a Gentoo system already or to cross-compile.

Misc

Notes

Prerequisites

Nice-to-haves

Guide

  1. Prep:

    1. Flash with latest Raspbian (September 2019 here)

    2. Easiest way to avoid filesystem mess is to modify cmdline.txt to change init=/usr/lib/raspi-config/init_resize.sh to init=/sbin/init.

    3. Edit config.txt and tell the bootloader to use the 64 bit kernel (kernel8.img). arm_64bit=1

    4. Place a file in /boot called ssh, e.g. touch /boot/ssh. This enables sshd on the next boot.

    5. Setup WiFi if appropriate.

  2. Boot. Verify that you’re running 64bit by looking for aarch64 in uname -a, e.g.

$ uname -a
Linux raspberrypi 4.19.75-v8+ #1270 SMP PREEMPT Tue Sep 24 18:59:17 BST 2019 aarch64 GNU/Linux
  1. sudo apt update && sudo apt upgrade to get the latest bootloader, kernel, etc.

  2. Reboot.

  3. Filesystem setup (I’m using f2fs for the Gentoo partition)

    1. Install f2fs-tools for mkfs.f2fs and resize.f2fs;

    2. Create an f2fs partition. I had to create a partition inbetween the main ext4 one and my f2fs one to get the right size. Couldn’t figure out why at the time.

    3. Mount it at /mnt/gentoo and cd there..

    4. Unmount /boot from Raspbian (so we can mount it in the chroot): umount /boot

  4. Fetch the stage3:

(Please check for a newer one on the site linked above).
wget https://gentoo.osuosl.org/releases/arm64/autobuilds/current-stage3-arm64/stage3-arm64-20210905T230622Z.tar.xz -O /mnt/gentoo/
  1. Untar as usual:
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
  1. Start customising make.conf, set these:

    # Different to default
    COMMON_FLAGS="-O2 -pipe -march=native"
    MAKEOPTS="-j4"
    # Default
    CFLAGS="${COMMON_FLAGS}"
    CXXFLAGS="${COMMON_FLAGS}"
    FCFLAGS="${COMMON_FLAGS}"
    FFLAGS="${COMMON_FLAGS}"

    Note that you can set -march etc appropriately to use distcc, but still get the benefits.

  2. Enter chroot as usual (copy DNS settings first, then mount, then chroot):

    # Copy over some firmware for WiFi and Bluetooth from Raspbian
    mkdir /mnt/gentoo/lib/firmware/
    cp -rv /lib/firmware/brcm/ /mnt/gentoo/lib/firmware/
    
    # Standard Gentoo chroot setup
    cp --dereference /etc/resolv.conf /mnt/gentoo/etc/resolv.conf
    mount --types proc /proc /mnt/gentoo/proc
    mount --rbind /sys /mnt/gentoo/sys
    mount --make-rslave /mnt/gentoo/sys
    mount --rbind /dev /mnt/gentoo/dev
    mount --make-rslave /mnt/gentoo/dev
    chroot /mnt/gentoo /bin/bash
    source /etc/profile
    export PS1="(chroot) ${PS1}"
  3. Sync emerge so we can install packages: emerge --sync

  4. Build the (RPi, not upstream) kernel:

    1. Prerequisites:

      • emerge -a -uvDU @world is likely needed to avoid e.g. bindist conflicts! You may be able to for now --exclude gcc though.
      • emerge -av dev-vcs/git to fetch the sources.
      • emerge -av sys-devel/bc for the kernel (build requirement)
    2. Get the sources:

      cd /opt
      git clone --depth 1 https://github.com/raspberrypi/linux.git
      # so e.g. emerge knows what kernel we're running
      ln -s /opt/linux /usr/src/linux
    3. Configure:

      # Generate base configs
      # Pi 4: bcm2711
      make bcm2711_defconfig
      
      # menuconfig to customise
      make menuconfig
    4. Modify arch/arm64/Makefile (optional, probably not very useful):

      KBUILD_CFLAGS   += -march=native
    5. Start compiling:

      time make -j4 Image modules dtbs

      For me, this took:

      real    66m55.242s
      user    234m46.421s
      sys     27m24.339s

      … but I was quite generous with the modules I chose to compile in for fun, e.g. KVM.

    6. Mount /boot inside the chroot this time:

      mount /dev/mmcblk0p1 /boot
    7. Take a backup of the old kernel, just in case:

      # kernel8 is for arm64
      mv /boot/kernel8.img /boot/kernel8.img.bak
    8. Install modules, etc:

      make modules_install dtbs_install
      scripts/mkknlimg arch/arm64/boot/Image /boot/kernel8.img
  5. Tasks before reboot:

    1. emerge -a -uvDN @world

    2. Create /etc/fstab:

      proc                  /proc           proc    defaults          0       0
      PARTUUID=6c586e13-01  /boot           vfat    defaults          0       2
      /dev/mmcblk0p4        /               f2fs    defaults,noatime  0       1
      # a swapfile is not a swap partition, no line here
      #   use  dphys-swapfile swap[on|off]  for that
    3. Modify two parameters (root, rootfstype) in /boot/cmdline.txt:

      root=/dev/mmcblk0p4 rootfstype=f2fs
  6. Optional extras before reboot:

    1. Set up network and SSH

      # Needed for WiFi / network
      emerge -av dhcpcd wpa_supplicant
      
      # Create wpa_supplicant.conf as appropriate
      # https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md
      
      # Tell wpa_supplicant, sshd to start on boot
      rc-update add wpa_supplicant default
      rc-update add sshd default
      
      # Setup the network scripts
      # https://wiki.gentoo.org/wiki/Wpa_supplicant#Setup_for_Gentoo_net..2A_scripts
    2. Create a user with sudo rights

      # Create a user
      useradd -m gentoo -G wheel,video,users,audio,usb
      
      # Set a password (optional)
      passwd gentoo
      
      # Add in an SSH key (optional)
      su gentoo
      mkdir ~/.ssh
      # Put your public ssh key in ~/.ssh/authorized_keys
      
      # Install sudo
      emerge -av sudo
    3. rng-tools to use the built-in RNG:

      emerge -av rng-tools
      mkdir /etc/modules-load.d/
      echo 'bcm2835-rng' > /etc/modules-load.d/random.conf
      
      rc-update add rngd
    4. # Useful tools like equery, eix (optional)
      emerge -av gentoolkit eix htop
      
      # Time sync
      emerge -av openntpd
      
      # Start on boot
      rc-update add ntpd
      
      # Set up swclock to save last clock on shutdown, restore on boot
      rc-update add swclock boot
  7. Reboot and hope for the best!

  8. Post-boot:

    1. If your time is wrong, force a manual sync:

      # Stop running ntpd
      /etc/init.d/ntpd stop
      
      # Manual sync
      ntpd -s -d
      
      # Wait a few seconds for it to sync
      # Then CTRL-C (quit)
      
      # Run date to check time is now accurate
      date
      
      # Start up ntpd again
      /etc/init.d/ntpd start
    2. Set CPU_FLAGS_ARM:

      emerge -av cpuid2cpuflags
      
      mkdir /etc/portage/package.use
      echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpuflags
      
      emerge -c cpuid2cpuflags
    3. Raspberry Pi specific utilities:

      1. Installing Raspberry Pi userland:

        emerge -av cmake git
        mkdir -p ~/git/build/ && cd ~/git/build
        git clone https://github.com/raspberrypi/userland
        cd userland
        ./buildme
        
        # Now it's installed, we need to make it accessible
        echo 'export PATH="/opt/vc/bin:${PATH}"' >> ~/.bashrc
        echo '/opt/vc/lib' > /etc/ld.so.conf.d/06-rpi.conf
        . ~/.bashrc
        
        # Regenerate ld cache
        sudo env-update
        
        # Happily use vcgencmd and friends!
      2. Update the firmware (Pi 4):

        # For convenience, add a dir to PATH
        # Only run this part the first time you update
        mkdir ~/bin
        echo 'export PATH="$HOME/bin:${PATH}"' >> ~/.bashrc
        . ~/.bashrc
        
        cd ~/git/build
        # Run `git clone ...` the first time
        # Run `git pull` in future to check for updates
        git clone https://github.com/raspberrypi/rpi-eeprom
        cd rpi-eeprom
        
        # Copy the firmware files to where tool wants
        sudo mkdir /lib/firmware/raspberrypi/bootloader/
        sudo cp -rv firmware/* /lib/firmware/raspberrypi/bootloader
        
        # Copy vl805 to your bin
        cp firmware/vl805 ~/bin
        
        # Run the actual update
        sudo --preserve-env=PATH env ./rpi-eeprom-update
    4. Install dosfsutils for vfat fsck:

      emerge -av sys-fs/dosfstools