Ondrej Famera - top logo

Gentoo on Odroid-M1 (aarch64)

Few moths ago I got Odroid-M1 board (8GB version) in order to get some hand-on experience with ARM platform. As long term Gentoo user that couldn’t find manual for Odroid-M1 board I have prepared short Gentoo installation guide here - while simple it gets the system to boot from SD card into minimal environment.

Update 2023-03: Check the new guide for Odroid M1 board with upstream 6.1.x kernel, LVM and LUKS.

Requirements

  • Odroid-M1 board - I have used 8GB version, but I believe that 4GB should work too
  • Linux system on Odroid-M1 - eMMC that comes with board comes with pre-installed Ubuntu is good enough or as alternative you can boot live Linux from USB (how to do that is not part of this guide)
  • Internet connection - for getting files to install Gentoo and packages
  • approximately 3 hours of time :) - there are 2 steps where you have to wait for compilation to finish (first ~22 minutes for packages and later ~81 minutes for kernel compilation)
  • 16GB SD card (or bigger)

Installation

  • boot into pre-installed Ubuntu on eMMC or into some other Linux - this OS should NOT be running from SD card to which Gentoo will get installed (as partitioning will be changed)
  • partition the SD card (this manual will assume the SD card is /dev/mmcblk1) - GPT is used here
    • p1 - reservation for future use (custom u-boot)- not used in this manual
    • p2 - /boot to hold kernel, initramfs, DTB and boot.scr files
    • p3 - Gentoo /
    # parted /dev/mmcblk1 mklabel gpt
    # parted /dev/mmcblk1 mkpart primary 2M 6M
    # parted /dev/mmcblk1 mkpart primary 6M 206M
    # parted /dev/mmcblk1 mkpart primary 206M 100%
    
    # lsblk /dev/mmcblk1
    NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
    mmcblk1     179:0    0 14.8G  0 disk
    ├─mmcblk1p1 179:1    0    4M  0 part
    ├─mmcblk1p2 179:2    0  190M  0 part
    └─mmcblk1p3 179:3    0 14.6G  0 part
    
  • create file systems
    • petitboot on Odroid-M1 cannot read XFS, but can read EXT2/3/4
    • using EXT4 for Gentoo / for simplicity
    # mkfs.ext2 /dev/mmcblk1p2
    # mkfs.ext4 /dev/mmcblk1p3
    
  • mount (future) Gentoo /, download stage3 and unpack it there - I will use systemd variant of stage3 from nearby mirror
    # mount /dev/mmcblk1p3 /mnt
    # cd /mnt
    # wget http://gentoo.osuosl.org/releases/arm64/autobuilds/20220731T233142Z/stage3-arm64-systemd-20220731T233142Z.tar.xz
    # tar xvf stage3-arm64-systemd-20220731T233142Z.tar.xz
    
  • mount /boot and other virtual file systems
    # mount /dev/mmcblk1p2 /mnt/boot
    # mount -t proc none /mnt/proc
    # mount --rbind /sys /mnt/sys
    # mount --rbind /dev /mnt/dev
    
    # df -h /mnt /mnt/boot /mnt/proc /mnt/sys /mnt/dev
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/mmcblk1p3   15G  1.2G   13G   9% /mnt
    /dev/mmcblk1p2  177M   14K  168M   1% /mnt/boot
    none               0     0     0    - /mnt/proc
    sysfs              0     0     0    - /mnt/sys
    udev             10M     0   10M   0% /mnt/dev
    
  • chroot into Gentoo /
    # cp -L /etc/resolv.conf /mnt/etc
    # chroot /mnt /bin/bash
    # env-update
    # source /etc/profile
    
  • configure /etc/fstab - use the UUIDs from your outputs (NOTE: UUID is not same thing as PARTUUID)
    # blkid |grep -E '(mmcblk1p2|mmcblk1p3)'
    /dev/mmcblk1p3: UUID="bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="primary" PARTUUID=
    "bbbbbbbb-0000-0000-0000-000000000000"
    /dev/mmcblk1p2: UUID="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" BLOCK_SIZE="1024" TYPE="ext2" PARTLABEL="primary" PARTUUID="aaaaaaaa-1111-1111-1111-111111111111"
    # echo 'UUID=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb / ext4 defaults 0 0' >> /etc/fstab
    # echo 'UUID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa /boot ext2 noauto,noatime 0 0' >> /etc/fstab
    
  • get portage tree
    # emerge-webrsync
    
  • configure timezone (adjust to your needs)
    # echo "Asia/Seoul" > /etc/timezone
    # emerge --config sys-libs/timezone-data
    
  • configure CPU flags for CPU (you can get these flags from app-portage/cpuid2cpuflags)
    # echo '*/* CPU_FLAGS_ARM: edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2' > /etc/portage/package.use/00cpuflags
    
  • configure /etc/portage/make.conf
    • set architecture matching the CPU (you can also use -march=native)
    • set concurency so we utilize all (4) CPU cores
    # nano /etc/portage/make.conf
    ...
    COMMON_FLAGS="-O2 -pipe -march=armv8.2-a+crypto+fp16+rcpc+dotprod"
    ...
    MAKEOPTS="-j5"
    
  • emerge tools needed for building kernel (18pkgs at time of writing, compilation time ~22 minutes)
    • to boot Gentoo sys-kernel/linux-firmware is not needed therefore lets disable firmware USE flag to save some space
    • to generate kernel and initramfs I will use sys-kernel/genkernel
    • bc is typically needed for kernel compilation
    • dev-vcs/git will be used later to obtain kernel sources
    # echo 'sys-kernel/genkernel -firmware' > /etc/portage/package.use/01_basic_os
    # emerge -av dev-vcs/git genkernel bc dev-embedded/u-boot-tools
    
  • get Odroid’s Linux kernel source - it contains significant changes compared to mainline Linux kernel (plain gentoo-sources will NOT work)
    # git clone --depth 1 https://github.com/hardkernel/linux.git -b odroidm1-4.19.y /usr/src/linux-4.19-odroid-m1
    # eselect kernel list
    Available kernel symlink targets:
    [1]   linux-4.19-odroid-m1
    # eselect kernel set 1
    
  • get some reasonable .config to start with for kernel compilation. For this guide I will use my minimized kernel config
    # curl -o /root/2022-08-odroid-m1-config.cfg https://www.famera.cz/blog/assets/files/gentoo-odroid-m1/2022-08-odroid-m1-config.cfg
    
  • configure genkernel
    • disable microcode loading as there is no support for it on ARM CPUs
    • add callback that will compile DTB file for the Odroid-M1 board that is needed to boot system and that will be copied into /boot/ automatically same way as kernel and initramfs
    # nano /etc/genkernel.conf
    ...
    CMD_CALLBACK="make dtbs; copy_image_with_preserve gentoo.dtb arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dtb gentoo.dtb"
    MICROCODE="no"
    
  • compile the kernel (~81 minutes)
    • you can customize kernel config by adding --menuconfig option
    • subsequent compilations are faster (around 45-50 minutes) as genkernel caches binaries for initramfs
    # genkernel --kernel-config=/root/2022-08-odroid-m1-config.cfg all
    
  • create /boot/boot.scr file
    • get text version of boot.scr (boot.txt) - this guide will use the minimized version of boot.scr based on one that came from Odroid’s Ubuntu
    • edit UUID of Gentoo / in the downloaded file to match your system
    • generate the binary version (boot.scr) that is recognized by petitboot (mkimage is part of dev-embedded/u-boot-tools package)
    # cd /boot
    # curl -o /boot/boot.txt https://www.famera.cz/blog/assets/files/gentoo-odroid-m1/2022-08-boot.txt
    # nano boot.txt
    ...
    setenv bootargs " ${bootargs} root=UUID=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
    ...
    # mkimage -A arm64 -T script -O linux -n 'boot script' -C none -d boot.txt boot.scr
    
    # ls -l /boot/
    total 26294
    -rw-r--r-- 1 root root  4214054 Aug  7 22:46 System.map-4.19.219-arm64
    -rw-r--r-- 1 root root     2284 Aug  7 23:53 boot.scr
    -rw-r--r-- 1 root root     2212 Aug  7 23:53 boot.txt
    -rw-r--r-- 1 root root   127813 Aug  7 23:01 gentoo.dtb
    -rw-r--r-- 1 root root  3335684 Aug  7 23:23 initramfs-4.19.219-arm64.img
    drwx------ 2 root root    12288 Aug  7 21:27 lost+found
    -rwxr-xr-x 1 root root 19181576 Aug  7 22:46 vmlinuz-4.19.219-arm64
    
    # df -h
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/mmcblk1p3   15G  6.5G  7.2G  48% /
    /dev/mmcblk1p2  177M   26M  142M  16% /boot
    udev             10M     0   10M   0% /dev
    tmpfs           3.7G     0  3.7G   0% /dev/shm
    
  • configure root password, exit chroot and REBOOT
    # passwd root
    # exit
    # reboot
    
  • once the system starts booting you should be able to see the Gentoo SD card EXT4 entry from which you can boot the Gentoo
    Petitboot (dev.20220424)                   Hardkernel ODROID-M1
    ---------------------------------------------------------------
    [Disk: mmcblk1p2 / bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb]         <===
    Gentoo SD card EXT4                                              <===
    [Disk: mmcblk0p1 / abcdabcd-abcd-abcd-abcd-abcdabcdabcd]
    Ubuntu 20.04.4 LTS
    ...
    
  • once system boots you should be able to login via console. From this point you can configure the Gentoo systems the usual way.

Lessons learned

  • Petitboot:
    • is a small Linux that takes role of “bootloader” on Odroid-M1 and has a specific requirement for what it can boot
    • Format of /boot/boot.scr is based on U-boot and needs to be prepared with mkimage to be recognized
  • Device-tree:
    • unlike x86_64 the ARM platform requires the Device-tree file to boot and function properly
    • Device-tree binary file can be created from Linux source tree with make dtbs

Additional resources and future plans

  • Odroid-M1 wiki: https://wiki.odroid.com/odroid-m1/odroid-m1
  • Gentoo Odroid-XU4 wiki: https://wiki.gentoo.org/wiki/Odroid-XU4 - NOTE that Odroid-XU4 is 32bit ARM while Odroid-M1 is 64bit ARM

  • replicating my other setup - Gentoo on LUKS+LVM - I have so-far tested LVM part, but not yet LUKS one on this board
  • trying to extract patches from Odroid’s Linux kernel directory and make them work with 4.19.x kernel from gentoo-sources - if this works I would make it available via some overlay
  • getting wayland to work on this - main challenge seems to be the graphical drivers that are compiled for Ubuntu’s version of X11 and wayland - from some past testing this was not playing very well together, more testing needed
  • building custom petitboot that can boot from XFS
  • making genkernel compile DTB file automatically (without need to use callback_cmd)

Final thoughts

This is my first ARM system and I’m still learning a lot on it (which was the point of getting it). It is refreshing experience from mature platform such as x86_64 as even look into dmesg output from boot gives idea that there are many things that could be unique to systems like this.

In case you got stuck in the above procedure at some point feel free to drop me an email.

Last change .