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"
- set architecture matching the CPU (you can also use
- 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 disablefirmware
USE flag to save some space - to generate kernel and initramfs I will use
sys-kernel/genkernel
bc
is typically needed for kernel compilationdev-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
- to boot Gentoo
- 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
- you can customize kernel config by adding
- create
/boot/boot.scr
file- get text version of
boot.scr
(boot.txt
) - this guide will use the minimized version ofboot.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 ofdev-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
- get text version of
- 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 withmkimage
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.