Linux and SBC devices
The following explains how Linux can be used with SBCs (Single Board Computers).
The boot process of Linux
A simplified representation of the boot process is shown in the figure below:
The following briefly explains, in a simplistic manner, the boot process of a device running the Linux operating system.
BIOS/UEFI/PPL
The BIOS (an acronym for 'Basic Input - Output System') initializes the hardware and ensures through a power-on self-test (POST) that all hardware is ready. The main task of the BIOS is to load the bootloader.
UEFI (short for Unified Extensible Firmware Interface) is the newer version that replaces the BIOS with greater capabilities and, among other things, aims to load the bootloader.
Embedded devices such as SBCs, like the Odroid N2, generally do not have a BIOS or UEFI; these are replaced by a microprocessor that has a primary boot program (PPL - Primary Program Loader) in ROM, whose purpose is to search for a secondary boot program (SPL - Secondary Program Loader) called U-Boot SPL whose goal is to initialize the memory so that it can load the U-Boot bootloader.
Some devices still have an SPI memory in which a special distribution Petitboot is installed, which includes the U-Boot distribution that acts as a more advanced bootloader, with multiple boot capabilities.
Bootloader
The bootloader loads the kernel into memory and then starts the kernel with a set of kernel parameters.
Kernel
When the kernel is loaded, it immediately initializes the devices and memory. The main task of the kernel is to load the initialization process (init).
INIT
The init process is the first process that is started; init starts and stops essential processes in the system. This usually represents a symbolic link from the main system initialization service, for example systemd, called init and located in the directory /usr/sbin/ or /sbin/init.
florin@odroid-n2:~$ ps -p 1
PID TTY TIME CMD
1 ? 00:00:04 systemd
florin@odroid-n2:~$ ls -la /sbin/init
lrwxrwxrwx 1 root root 20 dec 1 15:28 /sbin/init -> /lib/systemd/systemd
florin@odroid-n2:~$ ls -la /usr/sbin/init
lrwxrwxrwx 1 root root 20 dec 1 15:28 /usr/sbin/init -> /lib/systemd/systemd
florin@odroid-n2:~$ ls -la /sbin
lrwxrwxrwx 1 root root 8 feb 9 04:35 /sbin -> usr/sbin
florin@odroid-n2:~$ ps -ax
PID TTY STAT TIME COMMAND
1 ? Ss 0:04 /sbin/init d:
...
The name init comes from SysV init, also known as System V init, which was among the first used in the UNIX-LINUX world.
A non-exhaustive list of such init services is as follows:
- SysVinit - in this case, /sbin/init will not be a symbolic link;
- OpenRC - used by Gentoo Linux;
- Runit - used by Void Linux;
- Systemd - used by most Linux distributions: Red Hat, Debian, Ubuntu, etc.
Installing the Linux operating system on Odroid N2
For the installation, the Odroid N2 board was used. It has the advantage of being equipped with SPI Flash memory. Inside this memory, there is another mini Linux distribution called Petitboot that will perform the loading process of Linux distributions; it will essentially be the BOOTLOADER in the boot process explained above. It has the advantage of eliminating the need for a U-boot type bootloader on the environment where we want to install Linux and also allows loading multiple kernels and distributions from different media, even over the network.
Preparing the installation environment
Since the board also has USB3 ports, which ensure a higher transfer speed than SDMMC or eMMC devices, one of these USB3 ports will be used with an NVME2 SSD to USB3 adapter. The partitioning used is as follows:
florin@odroid-n2:~$ sudo fdisk -l /dev/sda
Disk /dev/sda: 931,51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: X900 1TB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 334C2C9E-6346-C54C-AB4D-521EEB3EE059
Device Start End Sectors Size Type
/dev/sda1 8192 622591 614400 300M Linux filesystem
/dev/sda2 622592 629768191 629145600 300G Linux filesystem
/dev/sda3 629768192 1049198591 419430400 200G Linux filesystem
/dev/sda4 1049198592 1468628991 419430400 200G Linux filesystem
/dev/sda5 1468628992 1888059391 419430400 200G Linux filesystem
/dev/sda6 1888059392 1904836607 16777216 8G Linux swap
In GParted, the partitioning of the SSD is presented in the form of:
After partitioning, formatting is performed with mkfs.ext4 for the file partitions and with mkswap for the swap partition. For convenience, GParted can be used.
Six partitions have been created:
- /dev/sda1 - 300MiB used for files utilized in the boot process;
- /dev/sda2 - 300GiB used for the Armbian distribution;
- /dev/sda3 - 200GiB used for the Void Linux distribution;
- /dev/sda4 - 200GiB used for the CentOS Stream 10 distribution;
- /dev/sda4 - 200GiB used for the EndeavourOS distribution;
- /dev/sda5 - 8GiB used for swap.
Installing Armbian
For the installation of the Armbian distribution, version 25.2.1 , Debian 12 variant, with Cinnamon and MESA/VPU extensions and kernel 6.12 was used.
After downloading the file with the archived image, it is extracted:
florin@odroid-n2:~/Descărcări$ unxz Armbian_25.2.1_Odroidn2_bookworm_current_6.12.13_cinnamon-backported-mesa_desktop.img.xz
Following the extraction, we will have the image of the distribution that is normally written to an eMMC or SDMMC disk, but in this case, it will be mounted in the directory /mnt/armbian:
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/armbian
florin@odroid-n2:~/Descărcări$ sudo fdisk -l Armbian_25.2.1_Odroidn2_bookworm_current_6.12.13_cinnamon-backported-mesa_desktop.img
Disk Armbian_25.2.1_Odroidn2_bookworm_current_6.12.13_cinnamon-backported-mesa_desktop.img: 7,2 GiB, 7730102272 bytes, 15097856 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3b4ad264
Device Boot Start End Sectors Size Id Type
Armbian_25.2.1_Odroidn2_bookworm_current_6.12.13_cinnamon-backported-mesa_desktop.img1 8192 15097855 15089664 7,2G 83 Linux
florin@odroid-n2:~/Descărcări$ sudo mount -o loop,offset=$((512*8192)) Armbian_25.2.1_Odroidn2_bookworm_current_6.12.13_cinnamon-backported-mesa_desktop.img /mnt/armbian/
florin@odroid-n2:~/Descărcări$ ls /mnt/armbian/
bin boot dev etc home initrd.img initrd.img.old lib lost+found media mnt opt proc root run sbin selinux srv sys tmp usr var vmlinuz vmlinuz.old
A working directory, /mnt/work, is created, in which the partition /dev/sda2, created for the purpose of installing the Armbian distribution, is mounted:
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/work
Then, the partition /dev/sda2 is mounted in /mnt/work:
florin@odroid-n2:~/Descărcări$ sudo mount /dev/sda2 /mnt/work
A boot directory is created in /mnt/work, where the partition /dev/sda1 will be mounted:
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/work/boot
We mount the partition /dev/sda1 in /mnt/work/boot:
florin@odroid-n2:~/Descărcări$ sudo mount /dev/sda1 /mnt/work/boot
After which all directories and files will be copied, preserving attributes, from /mnt/armbian to /mnt/work:
florin@odroid-n2:~/Descărcări$ sudo cp -rp /mnt/armbian/* /mnt/work/
Since Petitboot is used for booting, we will need to create a directory grub in /dev/sda1, which is already mounted at /mnt/work/boot, and in that directory, we will edit a file named grub.cfg, used by Petitboot during the boot process:
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/work/boot/grub
florin@odroid-n2:~/Descărcări$ sudo nano /mnt/work/boot/grub/grub.cfg
The file read by Petitboot with the parameters that will be retrieved at boot will be in the form:
#/boot/grub.cfg
set UUID=3131c377-66a0-45d0-bde5-d13295d7fb41
menuentry "Armbian 25.2.1 (6.12.13-current-meson64)" {
linux /Image root=UUID=$UUID rootwait rootfstype=ext4 console=ttyAML0,115200 console=tty1 consoleblank=0 coherent_pool=2M
initrd /uInitrd
devicetree /dtb/amlogic/meson-g12b-odroid-n2.dtb
}
Grub.cfg here does not require the installation of the grub or grub2 bootloader; it is merely a file used by Petitboot that searches the disks for the boot.scr or boot.ini files associated with U-boot and grub.cfg in the grub or grub2 directories to retrieve the boot parameters.
As can be seen, we will need to know the UUID of the partition /dev/sda2 and also that of /dev/sda1 used for /boot, which must also be written in the /etc/fstab file, and this can be obtained with GParted or blkid:
florin@odroid-n2:~$ sudo blkid
/dev/sda1: LABEL="boot" UUID="13c60d7c-1b1c-4d58-b9fe-f9262ebc2174" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot" PARTUUID="1a8cf7ef-9bf5-4c56-ac00-d0b95e8b8284"
/dev/sda2: LABEL="armbian" UUID="3131c377-66a0-45d0-bde5-d13295d7fb41" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="armbian" PARTUUID="d7c80cb3-3217-41ba-a5de-b7a5e1d8f3f3"
/dev/sda3: LABEL="voidlinux" UUID="2dc3f400-b644-4998-b77c-665b630bc6f3" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="voidlinux" PARTUUID="efadaf32-c3fd-454f-b13b-98353033e661"
/dev/sda4: LABEL="centos" UUID="11bb4148-3733-422f-a2ae-0ad7c5ceb422" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="centos" PARTUUID="39bce778-f381-4807-8485-d9f72e0c5556"
/dev/sda5: LABEL="archlinux" UUID="9cbc45a5-81d5-49f3-90d8-dce710f90fd1" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="archlinux" PARTUUID="25031d65-5c7d-4e40-bf68-d7fdfb17be19"
/dev/sda6: LABEL="swap" UUID="f8d67fd5-0a7f-45b3-877c-2dcf04aec10a" TYPE="swap" PARTLABEL="swap" PARTUUID="c04500c6-2af8-4b0b-81d0-f73b7ec8c0ed"
/dev/zram1: LABEL="log2ram" UUID="2d080a5b-e763-46ad-8906-3ff9c3f5165b" BLOCK_SIZE="4096" TYPE="ext4"
/dev/loop0: LABEL="armbi_root" UUID="ba88db95-be25-4496-8028-64ba53ef82ac" BLOCK_SIZE="4096" TYPE="ext4"
/dev/zram0: UUID="a5a5ef56-c926-416e-8023-481464490b32" TYPE="swap"
Since Petitboot first reads the boot.scr file, we will need to delete the file created by Armbian, as well as boot.bmp and boot.cmd, which are not useful; the system administrator must also take care of any potential updates to these files that may be restored.
The fstab file will have a content of the form:
#/etc/fstab
UUID=13c60d7c-1b1c-4d58-b9fe-f9262ebc2174 /boot ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=3131c377-66a0-45d0-bde5-d13295d7fb41 / ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=f8d67fd5-0a7f-45b3-877c-2dcf04aec10a none swap defaults 0 0
tmpfs /tmp tmpfs defaults,nosuid 0 0
And the directory structure of /boot will be as follows:
florin@odroid-n2:~$ ls /boot/
config-6.12.16-current-meson64 lost+found
dtb System.map-6.12.16-current-meson64
dtb-6.12.16-current-meson64 uInitrd
grub uInitrd-6.12.16-current-meson64
Image vmlinuz-6.12.16-current-meson64
initrd.img-6.12.16-current-meson64
florin@odroid-n2:~$ ls /boot/grub/
grub.cfg
Finally, after booting, the user will be greeted by the classic installation messages of the Armbian distribution, for entering the root password, creating a user, and selecting the desired language for use. After logging into the system, it will look like this:
After startup, the Petitboot screen will appear as shown in the image below:
Installing CentOS Stream 10
For convenience, a trial and installation iso image of the CentOS Stream 10 distribution is used, which already includes KDE and Gnome, specifically at the time of writing this article CentOS-Stream-Image-MAX-Live.aarch64-10-202501222202.iso:
florin@odroid-n2:~/Descărcări$ ls -lah CentOS-Stream-Image-MAX-Live.aarch64-10-202501222202.iso
-rw-r--r-- 1 florin florin 2,7G mar 1 20:45 CentOS-Stream-Image-MAX-Live.aarch64-10-202501222202.iso
To begin with, it is checked whether the partition /dev/sda4/ where we want to install CentOS is mounted (in use):
florin@odroid-n2:~$ sudo mount | grep sda4
/dev/sda4 on /media/florin/centos type ext4 (rw,nosuid,nodev,relatime,errors=remount-ro,stripe=2,uhelper=udisks2)
As we can see, it is in use, but to mount it in /mnt/work, it will need to be unmounted from /media/florin/centos and mounted in /mnt/work:
florin@odroid-n2:~$ mount | grep sda4
/dev/sda4 on /media/florin/centos type ext4 (rw,nosuid,nodev,relatime,errors=remount-ro,stripe=2,uhelper=udisks2)
florin@odroid-n2:~$ sudo umount /media/florin/centos
florin@odroid-n2:~$ sudo mount /dev/sda4 /mnt/work/
florin@odroid-n2:~$ mount | grep sda4
/dev/sda4 on /mnt/work type ext4 (rw,relatime,stripe=2)
The rootfs structure will be extracted, just like during the installation of Armbian, but this time from the iso image:
WARNING
The image squasfs.img is of type "erofs" and Armbian and other distributions cannot mount it as there is no kernel support for this. In CentOS Stream 10 x86_84, there is support to extract the rootfs from the iso image:
florin@florin-pc:~/Descărcări$ sudo mount -o loop CentOS-Stream-Image-MAX-Live.aarch64-10-202501222202.iso /mnt/iso/
[sudo] parola pentru florin:
mount: /mnt/iso: WARNING: source write-protected, mounted read-only.
florin@florin-pc:~/Descărcări$ sudo losetup -Pf /mnt/iso/LiveOS/squashfs.img
florin@florin-pc:~/Descărcări$ sudo mount /dev/loop1 /mnt/centos/
mount: /mnt/centos: WARNING: source write-protected, mounted read-only.
florin@florin-pc:~/Descărcări$ ls /mnt/centos/
afs boot etc image lib64 mnt proc run srv tmp var
bin dev home lib media opt root sbin sys usr
florin@florin-pc:~/Descărcări$ sudo mount /dev/sdc4 /mnt/work/
florin@florin-pc:~/Descărcări$ sudo cp -rp /mnt/centos/* /mnt/work/
florin@florin-pc:~/Descărcări$ ls /mnt/work/
afs boot etc image lib64 media opt root sbin sys usr
bin dev home lib lost+found mnt proc run srv tmp var
florin@florin-pc:~/Descărcări$ sudo umount /mnt/work
florin@florin-pc:~/Descărcări$ sudo umount /mnt/centos
florin@florin-pc:~/Descărcări$ sudo losetup -d /dev/loop1
florin@florin-pc:~/Descărcări$ sudo umount /mnt/iso
After obtaining the rootfs, the SSD can be moved from the PC to the Odroid N2 and work can continue in Armbian.
The image used in Live for testing and installation will require us to perform a chroot in it where unnecessary packages will be removed, others will be added, and the user who will use the CentOS Stream 10 distribution that already contains KDE and Gnome pre-installed will be created.
Since we will also be working with chroot on other occasions, it is good to create a script:
#!/bin/bash
#chroot_work.sh
DIR="/mnt/work"
mount -o rbind /dev $DIR/dev
mount -t proc none $DIR/proc
mount -o bind /sys $DIR/sys
mount -o bind /tmp $DIR/tmp
cp /etc/resolv.conf $DIR/etc/
chroot $DIR /bin/bash
It is marked as executable:
florin@odroid-n2:~$ chmod +x chroot_work.sh
It checks if the partition /dev/sda4, where we have established that we will install CentOS Stream 10, is mounted; if it is in use, we unmount it and mount it in the working directory:
florin@odroid-n2:~$ mount | grep /dev/sda4
florin@odroid-n2:~$ sudo mount /dev/sda4 /mnt/work/
florin@odroid-n2:~$ ls /mnt/work/
afs boot etc image lib64 media opt root sbin sys usr
bin dev home lib lost+found mnt proc run srv tmp var
After which we run the script for chroot:
florin@odroid-n2:~$ sudo ./chroot_work.sh
[sudo] parola pentru florin:
root@odroid-n2:/#
It is observed that the console name has changed, then the profile corresponding to CentOS is loaded, and for safety, the console name is also changed:
root@odroid-n2:/# source /etc/profile
root@odroid-n2:/# export PS1="(chroot) $PS1"
(chroot) root@odroid-n2:/#
As a result of using the kernel from Armbian, it will be necessary to remove everything related to kernel and grub since these are located in /boot, where later the partition /dev/sda1 will be mounted:
(chroot) root@odroid-n2:/# rpm -qa | grep kernel
kernel-modules-core-6.12.0-43.el10.aarch64
kernel-core-6.12.0-43.el10.aarch64
kernel-modules-6.12.0-43.el10.aarch64
kernel-modules-extra-6.12.0-43.el10.aarch64
kernel-tools-libs-6.12.0-43.el10.aarch64
kernel-tools-6.12.0-43.el10.aarch64
kernel-6.12.0-43.el10.aarch64
(chroot) root@odroid-n2:/# rpm -qa | grep grub
grub2-common-2.12-5.el10.noarch
grub2-tools-minimal-2.12-5.el10.aarch64
grubby-8.40-77.el10.aarch64
grub2-tools-2.12-5.el10.aarch64
grub2-tools-extra-2.12-5.el10.aarch64
grub2-efi-aa64-modules-2.12-5.el10.noarch
grub2-efi-aa64-cdboot-2.12-5.el10.aarch64
grub2-efi-aa64-2.12-5.el10.aarch64
(chroot) root@odroid-n2:/# ls /boot/
config-6.12.0-43.el10.aarch64 initramfs-6.12.0-43.el10.aarch64.img
dtb loader
dtb-6.12.0-43.el10.aarch64 symvers-6.12.0-43.el10.aarch64.xz
efi System.map-6.12.0-43.el10.aarch64
grub2 vmlinuz-6.12.0-43.el10.aarch64
(chroot) root@odroid-n2:/#
Later on, perhaps in another article, a custom kernel will be compiled.
(chroot) root@odroid-n2:/# dnf remove kernel-modules-core kernel-core kernel-modules kernel-modules-extra kernel-tools-libs kernel-tools kernel -y
To remove grub, you will need to comment out the lines (add a hash # in front of the line) in the following files because grub is protected from removal from the system:
(chroot) root@odroid-n2:/# nano /etc/yum/protected.d/grub2-efi-aa64.conf
(chroot) root@odroid-n2:/# nano /etc/yum/protected.d/grub2-tools-minimal.conf
After making the above modifications, grub can be removed:
(chroot) root@odroid-n2:/# dnf remove grub2-common grub2-tools-minimal grubby grub2-tools grub2-tools-extra grub2-efi-aa64-modules grub2-efi-aa64-cdboot grub2-efi-aa64-cdboot -y
Checking what remains in /boot:
(chroot) root@odroid-n2:/# ls /boot
dtb efi loader
The remaining items will be deleted:
(chroot) root@odroid-n2:/# rm -r /boot/*
rm: eliminați '/boot/dtb' de tipul legătură simbolică? y
rm: descindeți în directorul '/boot/efi'? y
rm: descindeți în directorul '/boot/efi/EFI'? y
rm: descindeți în directorul '/boot/efi/EFI/BOOT'? y
rm: eliminați '/boot/efi/EFI/BOOT/fbaa64.efi' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/BOOT/BOOTAA64.EFI' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/BOOT' de tipul director? y
rm: descindeți în directorul '/boot/efi/EFI/centos'? y
rm: eliminați '/boot/efi/EFI/centos/BOOTAA64.CSV' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/centos/shim.efi' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/centos/shimaa64-centos.efi' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/centos/shimaa64.efi' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/centos/mmaa64.efi' de tipul fișier obișnuit? y
rm: eliminați '/boot/efi/EFI/centos' de tipul director? y
rm: eliminați '/boot/efi/EFI' de tipul director? y
rm: eliminați '/boot/efi' de tipul director? y
rm: descindeți în directorul '/boot/loader'? y
rm: descindeți în directorul '/boot/loader/entries'? y
rm: eliminați '/boot/loader/entries/dc9647167e9240308687296b9211acb7-6.12.0-43.el10.aarch64.conf' de tipul fișier obișnuit? y
rm: eliminați '/boot/loader/entries' de tipul director? y
rm: eliminați '/boot/loader' de tipul director? y
(chroot) root@odroid-n2:/# ls /boot/
(chroot) root@odroid-n2:/#
Next, modify the /etc/fstab file according to the SSD disk:
(chroot) root@odroid-n2:/# nano /etc/fstab
In fstab, edit according to the hardware and the preparations made earlier:
#/etc/fstab
UUID=13c60d7c-1b1c-4d58-b9fe-f9262ebc2174 /boot ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=11bb4148-3733-422f-a2ae-0ad7c5ceb422 / ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=f8d67fd5-0a7f-45b3-877c-2dcf04aec10a none swap defaults 0 0
tmpfs /tmp tmpfs defaults,nosuid 0 0
You will need to add the directory with the kernel modules from Armbian, specifically from the /usr/lib/modules/ directory to /mnt/work/usr/lib/modules/:
florin@odroid-n2:~$ sudo cp -rp /usr/lib/modules/* /mnt/work/usr/lib/modules/
florin@odroid-n2:~$ sudo cp -r /usr/lib/linux-image-6.12.16-current-meson64 /mnt/work/usr/lib/
Return to chroot and temporarily disable the firewalld service:
(chroot) root@odroid-n2:/# systemctl disable firewalld
Removed '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'.
Removed '/etc/systemd/system/multi-user.target.wants/firewalld.service'.
Then, a user will be added for login:
(chroot) root@odroid-n2:/# useradd -G wheel,dialout,video,audio -s /bin/bash -c 'Florin Tanasă' florin
(chroot) root@odroid-n2:/# ls /home/
florin
A password will be set for the user:
(chroot) root@odroid-n2:/# passwd florin
Parolă nouă:
Rescrieți parola nouă:
passwd: parolă actualizată cu succes
The system language can be changed if desired:
(chroot) root@odroid-n2:/# cat /etc/locale.conf
LANG=en_US.UTF-8
(chroot) root@odroid-n2:/# nano /etc/locale.conf
(chroot) root@odroid-n2:/# cat /etc/locale.conf
LANG=ro_RO.UTF-8
Then an option with the new distribution will be added to /boot/grub/grub.cfg to be available at boot:
florin@odroid-n2:~$ sudo nano /boot/grub/grub.cfg
After modification, the grub.cfg file will look like this:
set UUID1=3131c377-66a0-45d0-bde5-d13295d7fb41
set UUID2=11bb4148-3733-422f-a2ae-0ad7c5ceb422
menuentry "Armbian 25.2.1 (6.12.16-current-meson64)" {
linux /Image root=UUID=$UUID1 rootwait rootfstype=ext4 console=ttyAML0,115200 console=tty1 consoleblank=0 coherent_pool=2M
initrd /uInitrd
devicetree /dtb/amlogic/meson-g12b-odroid-n2.dtb
}
menuentry "CentOS Stream 10 (6.12.16-current-meson64)" {
linux /Image root=UUID=$UUID2 rootwait rootfstype=ext4 console=ttyAML0,115200 console=tty1 consoleblank=0 coherent_pool=2M
initrd /uInitrd
devicetree /dtb/amlogic/meson-g12b-odroid-n2.dtb
}
After rebooting, the user will be able to log into the system using the Desktop Manager sddm:
To use classic Gnome:
To use Gnome:
To use KDE:
EndeavourOS Installation
From the category of Arch Linux-based distributions, EndeavorOS will be used, which provides a specially prepared image for the Odroid N2 SBC and also offers a kernel compiled for Amlogic devices.
Downloading the image file
The file with the distribution image is downloaded using the command:
florin@odroid-n2:~/Descărcări$ wget https://github.com/endeavouros-arm/images/releases/download/odroid-n2-image/enosLinuxARM-odroid-n2-latest.img.xz
The downloaded file is extracted:
florin@odroid-n2:~/Descărcări$ unxz enosLinuxARM-odroid-n2-latest.img.xz
Obtaining information related to the image
Next, it is checked whether the image has multiple partitions:
lorin@odroid-n2:~/Descărcări$ sudo fdisk -l enosLinuxARM-odroid-n2-latest.img
Disk enosLinuxARM-odroid-n2-latest.img: 8,5 GiB, 9126805504 bytes, 17825792 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3b835c24
Device Boot Start End Sectors Size Id Type
enosLinuxARM-odroid-n2-latest.img1 4096 1052671 1048576 512M c W95 FAT32 (LBA)
enosLinuxARM-odroid-n2-latest.img2 1052672 16777215 15724544 7,5G 83 Linux
From the result, it is found that there are two partitions and information regarding which sector the partitions start from and how many units are in a sector:
- 512M - used for boot, starting from sector 4096;
- 7.5G - used for rootfs, starting from sector 1052672;
- 1 sector has 512 units.
The information above will be useful for mounting in order to extract information.
Adding a new boot partition
Since the distribution image has two partitions, one for boot and one for rootfs, it is necessary to create a new partition for boot. For this purpose, we will use GParted from Armbian installed earlier, and we will make the boot partition larger and of a different type.
We will create a partition named boot_arch of 1G of type linux formatted ext4:
It will then be finalized by pressing the Apply all operations button:
It can be observed that the partition /dev/sda7 has been created, which will be used for /boot, while the partition /dev/sda5, created from the beginning, will be used for rootfs, respectively for /.
Mounting the image and extracting the data
First, we create the directory where we will mount the partitions from within the image in order to extract the data to the SSD partitions:
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/endeavouros
We will mount the boot partition from the downloaded image in /mnt/eandeavouros/, then we will mount the partition /dev/sda7 in /mnt/work/, and finally, we will copy the data and unmount the partitions:
florin@odroid-n2:~/Descărcări$ sudo mount -o loop,offset=$((512*4096)) enosLinuxARM-odroid-n2-latest.img /mnt/endeavouros/
florin@odroid-n2:~/Descărcări$ ls /mnt/endeavouros/
boot.ini dtbs initramfs-linux.img sd_fusing.sh
boot.ini.orig Image initramfs-linux.uimg u-boot.bin
florin@odroid-n2:~/Descărcări$ sudo mount /dev/sda7 /mnt/work/
florin@odroid-n2:~/Descărcări$ ls /mnt/work/
lost+found
florin@odroid-n2:~/Descărcări$ sudo cp -rp /mnt/endeavouros/* /mnt/work/
florin@odroid-n2:~/Descărcări$ ls /mnt/work/
boot.ini dtbs initramfs-linux.img lost+found u-boot.bin
boot.ini.orig Image initramfs-linux.uimg sd_fusing.sh
florin@odroid-n2:~/Descărcări$ sudo umount /mnt/endeavouros
florin@odroid-n2:~/Descărcări$ sudo umount /mnt/work
Then the rootfs partition from the downloaded image will be mounted in /mnt/endeavouros/, after which the /dev/sda5 partition will be mounted in /mnt/work, and finally, the data will be copied and the partitions will be unmounted:
florin@odroid-n2:~/Descărcări$ sudo mount -o loop,offset=$((512*1052672)) enosLinuxARM-odroid-n2-latest.img /mnt/endeavouros/
florin@odroid-n2:~/Descărcări$ ls /mnt/endeavouros/
bin dev home lost+found opt root sbin sys usr
boot etc lib mnt proc run srv tmp var
florin@odroid-n2:~/Descărcări$ sudo mount /dev/sda5 /mnt/work/
florin@odroid-n2:~/Descărcări$ ls /mnt/work/
lost+found
florin@odroid-n2:~/Descărcări$ sudo cp -rp /mnt/endeavouros/* /mnt/work/
florin@odroid-n2:~/Descărcări$ ls /mnt/work/
bin dev home lost+found opt root sbin sys usr
boot etc lib mnt proc run srv tmp var
florin@odroid-n2:~/Descărcări$ sudo umount /mnt/endeavouros
florin@odroid-n2:~/Descărcări$ sudo umount /mnt/work
Using the blkid command, the UUID value of the /dev/sda5 and /dev/sda7 partitions can be identified:
florin@odroid-n2:~/Descărcări$ sudo blkid
/dev/sda1: LABEL="boot" UUID="13c60d7c-1b1c-4d58-b9fe-f9262ebc2174" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot" PARTUUID="1a8cf7ef-9bf5-4c56-ac00-d0b95e8b8284"
/dev/sda2: LABEL="armbian" UUID="3131c377-66a0-45d0-bde5-d13295d7fb41" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="armbian" PARTUUID="d7c80cb3-3217-41ba-a5de-b7a5e1d8f3f3"
/dev/sda3: LABEL="voidlinux" UUID="2dc3f400-b644-4998-b77c-665b630bc6f3" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="voidlinux" PARTUUID="efadaf32-c3fd-454f-b13b-98353033e661"
/dev/sda4: LABEL="centos" UUID="11bb4148-3733-422f-a2ae-0ad7c5ceb422" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="centos" PARTUUID="39bce778-f381-4807-8485-d9f72e0c5556"
/dev/sda5: LABEL="archlinux" UUID="9cbc45a5-81d5-49f3-90d8-dce710f90fd1" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="archlinux" PARTUUID="25031d65-5c7d-4e40-bf68-d7fdfb17be19"
/dev/sda6: LABEL="swap" UUID="f8d67fd5-0a7f-45b3-877c-2dcf04aec10a" TYPE="swap" PARTLABEL="swap" PARTUUID="c04500c6-2af8-4b0b-81d0-f73b7ec8c0ed"
/dev/sda7: LABEL="boot_arch" UUID="5c430bbe-17c5-4570-af18-c9f3bef1b22c" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot_arch" PARTUUID="c1dbebea-3729-4ab0-9636-7de8ffe3afb8"
/dev/zram1: LABEL="log2ram" UUID="8ff0f59c-0e89-499e-a9c5-0190ae6be290" BLOCK_SIZE="4096" TYPE="ext4"
/dev/zram0: UUID="dc52859c-3820-46b0-86c5-71989bc3abe4" TYPE="swap"
It is observed that the relevant data has the following values:
- /dev/sda5: LABEL="archlinux" UUID="9cbc45a5-81d5-49f3-90d8-dce710f90fd1";
- /dev/sda7: LABEL="boot_arch" UUID="5c430bbe-17c5-4570-af18-c9f3bef1b22c".
With this, the parameter for the UUID corresponding to the partition /dev/sda5 for root will be modified in the boot.ini file used during booting, as both will be used in the /etc/fstab file:
florin@odroid-n2:~/Descărcări$ sudo mount /dev/sda7 /mnt/work/
florin@odroid-n2:~/Descărcări$ sudo nano /mnt/work/boot.ini
The file is modified according to our data:
ODROIDN2-UBOOT-CONFIG
# DO Not Edit this line: KERNEL: mainline
setenv board "odroidn2"
# Show logo as soon as possible
showlogo
# System Label
setenv bootlabel "ArchLinux"
# Default Console Device Setting
setenv condev "console=ttyAML0,115200n8 console=tty1"
# Video Output
## preferred_resolution
## set to your preferred resolution using the format:
## {width}x{height}@{hertz}
## example: 1920x1080@60
## or
## Set to an empty string to let the kernel automatically
## choose a resolution for you.
setenv preferred_resolution ""
## petitboot_edid
## if you experience issues of display not showing any
## image when using petitboot you can use this setting
## to overwrite the default display edid information.
##
## A valid value for this option can be:
## 800x600, 1024x768, 1280x720, 1280x1024, 1600x1200,
## 1680x1050, 1920x1080, 2560x1440, 2880x1800, 3840x2160
## or
## Set to an empty string to use the display provided
## edid information.
setenv petitboot_edid ""
## Uncomment to force petitboot to always be set as
## active to always force the edid overwrite.
#setenv petitboot_active "1"
if test "${petitboot_edid}" != "" && test "${petitboot_active}" = "1"; then
setenv voutput "drm_kms_helper.edid_firmware=HDMI-A-1:edid/${petitboot_edid}.bin"
elif test "${preferred_resolution}" != ""; then
setenv voutput "video=HDMI-A-1:${preferred_resolution}"
fi
# Boot Args
setenv bootargs "root=UUID=9cbc45a5-81d5-49f3-90d8-dce710f90fd1 rootwait rw fsck.repair=yes"
setenv bootargs "${bootargs} mitigations=off ${condev}"
setenv bootargs "${bootargs} logo=osd0,loaded no_console_suspend"
setenv bootargs "${bootargs} net.ifnames=0 cma=800M"
setenv bootargs "${bootargs} clk_ignore_unused ${voutput}"
# Set load addresses
setenv dtb_loadaddr "0x20000000"
setenv loadaddr "0x1080000"
setenv initrd_loadaddr "0x4080000"
# Load kernel, dtb and initrd
ext4load usb ${devno}:7 ${loadaddr} /Image
if test "${variant}" = "n2_plus"; then
ext4load usb ${devno}:7 ${dtb_loadaddr} /dtbs/amlogic/meson-g12b-odroid-n2-plus.dtb
else
ext4load usb ${devno}:7 ${dtb_loadaddr} /dtbs/amlogic/meson-g12b-odroid-n2.dtb
fi
ext4load usb ${devno}:7 ${initrd_loadaddr} /initramfs-linux.uimg
# boot
booti ${loadaddr} ${initrd_loadaddr} ${dtb_loadaddr}
WARNING
The UUID parameter will be given importance, which will inform the kernel where the root partition is located, and the load mmc ${devno}:1 parameter will be replaced with ext4load usb ${devno}:7; essentially, we will inform the bootloader where the boot partition is located from which it will load the kernel (we recall how Linux starts, briefly described at the beginning of the article).
The fstab file will be edited after the /dev/sda7/ partition is unmounted from /mnt/work:
florin@odroid-n2:~$ sudo umount /mnt/work
florin@odroid-n2:~$ sudo mount /dev/sda5 /mnt/work/
florin@odroid-n2:~$ sudo nano /mnt/work/etc/fstab
In the fstab file, the following parameters used by the kernel during boot will be defined for mounting:
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a device; this may
# be used with UUID= as a more robust way to name devices that works even if
# disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=5c430bbe-17c5-4570-af18-c9f3bef1b22c /boot ext4 defaults >
UUID=3131c377-66a0-45d0-bde5-d13295d7fb41 / ext4 defaults,noatim>
UUID=f8d67fd5-0a7f-45b3-877c-2dcf04aec10a none swap defaults >
tmpfs /tmp tmpfs defaults,nosuid>
Finally, after saving, the partition will be unmounted and the SBC Odroid N2 device will be restarted:
florin@odroid-n2:~$ sudo umount /mnt/work
florin@odroid-n2:~$ sudo reboot
After rebooting, Petitboot will detect the new configuration from /dev/sda7, specifically it will retrieve the data from the previously modified boot.ini file, and after selecting the ArchLinux option from the menu, the kernel will be loaded along with the parameters, and the system will greet us with some prompts for configuration, specifically for the installation of EndevourOS. Finally, after logging in, we will enjoy the new distribution:
Other information related to KDE:
KDE was preferred because it works well in Wayland and its resource consumption is not very significant.
Installing Void Linux
Void Linux is one of the independently developed distributions and does not depend on other distributions, featuring its own package manager called xbps, which is one of the fastest in package management.
For ease of installation, we will use the Live image with XFCE prepared for the pinebook-pro laptop, and later we will modify the boot sequence according to our meson platform, as the kernel is compiled with support for this platform (the image from CentOS Stream 10 did not provide a kernel that offers support for meson).
Next, we will download the image and perform successive mounts until we reach rootfs for the purpose of extracting it into the partitions on the SSD created for this purpose:
florin@odroid-n2:~$ cd Descărcări/
florin@odroid-n2:~/Descărcări$ wget https://repo-default.voidlinux.org/live/current/void-live-aarch64-20250202-xfce.iso
florin@odroid-n2:~/Descărcări$ sudo mount void-live-aarch64-20250202-xfce.iso /mnt/iso/
florin@odroid-n2:~/Descărcări$ sudo mount /mnt/iso/LiveOS/squashfs.img /mnt/work/
florin@odroid-n2:~/Descărcări$ sudo mkdir /mnt/voidlinux
florin@odroid-n2:~/Descărcări$ sudo mount /mnt/work/LiveOS/ext3fs.img /mnt/voidlinux/
florin@odroid-n2:~/Descărcări$ ls /mnt/voidlinux/
bin dev home lib32 lost+found mnt proc run sys usr
boot etc lib lib64 media opt root sbin tmp var
As with the installation of EndeavourOS, a 1G partition will be created with the ext4 file system for the boot partition:
After applying the changes to the SSD disk, it will look like the one below:
Next, a directory will be created where we will mount the previously created partition /dev/sda8 and copy the data from /mnt/voidlinux/boot:
florin@odroid-n2:~$ sudo mkdir /mnt/boot_void
[sudo] parola pentru florin:
florin@odroid-n2:~$ mount | grep sda8
florin@odroid-n2:~$ sudo mount /dev/sda8 /mnt/boot_void/
florin@odroid-n2:~$ sudo cp -rp /mnt/voidlinux/boot/* /mnt/boot_void/
florin@odroid-n2:~$ ls /mnt/boot_void/
boot.scr config-6.12.11_1 initramfs-6.12.11_1.img vmlinux-6.12.11_1
boot.txt dtbs lost+found
florin@odroid-n2:~$ sudo umount /mnt/boot_void
After unmounting the partition /dev/sda8, we will create a directory /mnt/root_void, where we will mount the partition for rootfs created from the beginning /dev/sda3 and where we will copy the relevant rootfs data from the iso image, specifically from /mnt/root_void, after which we will delete the data from /mnt/root_void/boot, and finally, we will mount the boot partition /dev/sda8 in /mnt/root_void/boot:
florin@odroid-n2:~/Descărcări$ cd ~
florin@odroid-n2:~$ sudo mkdir /mnt/root_void
florin@odroid-n2:~$ sudo mount /dev/sda3 /mnt/root_void/
florin@odroid-n2:~$ ls /mnt/root_void/
lost+found
florin@odroid-n2:~$ sudo cp -rp /mnt/voidlinux/* /mnt/root_void/
florin@odroid-n2:~$ sudo rm -r /mnt/root_void/boot/*
florin@odroid-n2:~$ ls /mnt/root_void/boot/
florin@odroid-n2:~$ sudo mount /dev/sda8 /mnt/root_void/boot/
florin@odroid-n2:~$ sudo ls /mnt/root_void/boot/
boot.scr config-6.12.11_1 initramfs-6.12.11_1.img vmlinux-6.12.11_1
boot.txt dtbs lost+found
To determine the partitions, run blkid:
florin@odroid-n2:~$ sudo blkid
/dev/sda1: LABEL="boot" UUID="13c60d7c-1b1c-4d58-b9fe-f9262ebc2174" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot" PARTUUID="1a8cf7ef-9bf5-4c56-ac00-d0b95e8b8284"
/dev/sda2: LABEL="armbian" UUID="3131c377-66a0-45d0-bde5-d13295d7fb41" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="armbian" PARTUUID="d7c80cb3-3217-41ba-a5de-b7a5e1d8f3f3"
/dev/sda4: LABEL="centos" UUID="11bb4148-3733-422f-a2ae-0ad7c5ceb422" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="centos" PARTUUID="39bce778-f381-4807-8485-d9f72e0c5556"
/dev/sda5: LABEL="archlinux" UUID="9cbc45a5-81d5-49f3-90d8-dce710f90fd1" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="archlinux" PARTUUID="25031d65-5c7d-4e40-bf68-d7fdfb17be19"
/dev/sda6: LABEL="swap" UUID="f8d67fd5-0a7f-45b3-877c-2dcf04aec10a" TYPE="swap" PARTLABEL="swap" PARTUUID="c04500c6-2af8-4b0b-81d0-f73b7ec8c0ed"
/dev/sda7: LABEL="boot_arch" UUID="5c430bbe-17c5-4570-af18-c9f3bef1b22c" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot_arch" PARTUUID="c1dbebea-3729-4ab0-9636-7de8ffe3afb8"
/dev/sda3: LABEL="voidlinux" UUID="f0cc6ce1-37af-4865-9347-24f30edcd042" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="voidlinux" PARTUUID="efadaf32-c3fd-454f-b13b-98353033e661"
/dev/sda8: LABEL="boot_void" UUID="7e62a9a8-46c7-4824-ae08-c2c95151e313" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="boot_void" PARTUUID="f779f881-f461-467b-8803-c10e1313643f"
/dev/loop1: TYPE="squashfs"
/dev/zram1: LABEL="log2ram" UUID="4b9e4e87-e8e5-4837-b56c-e6ef79607e58" BLOCK_SIZE="4096" TYPE="ext4"
/dev/loop2: UUID="3007f301-c2c1-40b3-9dbc-68844f4f1fe6" SEC_TYPE="ext2" BLOCK_SIZE="4096" TYPE="ext3"
/dev/loop0: BLOCK_SIZE="2048" UUID="2025-02-02-00-21-58-00" LABEL="VOID_LIVE" TYPE="iso9660"
/dev/zram0: UUID="4a5c516d-e7e0-4f76-9fb2-4eab60a52d17" TYPE="swap"
WARNING
When reformatting a partition, the UUID is modified.
From which the relevant data is extracted:
- /dev/sda3: LABEL="voidlinux" UUID="f0cc6ce1-37af-4865-9347-24f30edcd042";
- /dev/sda8: LABEL="boot_void" UUID="7e62a9a8-46c7-4824-ae08-c2c95151e313"
Data that will be used to edit the fstab file:
florin@odroid-n2:~$ sudo nano /mnt/root_void/etc/fstab
And the file will look like this:
#
# See fstab(5).
#
# <file system> <dir> <type> <options> <dump> <pass>
UUID=7e62a9a8-46c7-4824-ae08-c2c95151e313 /boot ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=f0cc6ce1-37af-4865-9347-24f30edcd042 / ext4 defaults,noatime,commit=120,errors=remount-ro 0 1
UUID=f8d67fd5-0a7f-45b3-877c-2dcf04aec10a none swap defaults 0 0
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0
The process will continue by performing a chroot in the directory /mnt/root_void. The previous script can be modified or a new one can be created, in the form:
florin@odroid-n2:~$ cat chroot_work.sh
#!/bin/bash
#chroot_work.sh
DIR="/mnt/root_void/"
mount -o rbind /dev $DIR/dev
mount -t proc none $DIR/proc
mount -o bind /sys $DIR/sys
mount -o bind /tmp $DIR/tmp
cp /etc/resolv.conf $DIR/etc/
chroot $DIR /bin/bash
Next, the script runs entering chroot mode, the profile is retrieved, the console name is modified, an update and upgrade of packages is performed, the boot startup of the desktop manager - lightdm service will be blocked, and finally, a number of utilities will be installed and the kernel will be uninstalled, etc.:
florin@odroid-n2:~$ sudo ./chroot_work.sh
bash: warning: setlocale: LC_ALL: cannot change locale (ro_RO.UTF-8)
bash-5.2# source /etc/profile
bash-5.2# export PS1="(chroot) $PS1"
(chroot) bash-5.2# ping google.ro
PING google.ro (142.250.180.227) 56(84) bytes of data.
64 bytes from bud02s34-in-f3.1e100.net (142.250.180.227): icmp_seq=1 ttl=57 time=21.7 ms
64 bytes from bud02s34-in-f3.1e100.net (142.250.180.227): icmp_seq=2 ttl=57 time=21.2 ms
^C
--- google.ro ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 21.220/21.463/21.707/0.243 ms
(chroot) bash-5.2# xbps-install -Su
(chroot) bash-5.2# xbps-query -l | grep linux
ii liblastlog2-2.40.2_1 Lastlog replacement library from util-linux
ii libsmartcols-2.40.2_1 Table or Tree library from util-linux
ii linux-6.12_1 Linux kernel meta package
ii linux-base-2023.05.29_1 Linux kernel base dependencies
ii linux-firmware-amd-20250211_1 Binary firmware blobs for the Linux kernel - AMD CPU/GPU microcode
ii linux-firmware-broadcom-20250211_1 Binary firmware blobs for the Linux kernel - Broadcom network blobs
ii linux-firmware-network-20250211_1 Binary firmware blobs for the Linux kernel - network
ii linux-firmware-nvidia-20250211_1 Binary firmware blobs for the Linux kernel NVIDIA GPU microcode
ii linux-firmware-qualcomm-20250211_1 Binary firmware blobs for the Linux kernel - Qualcomm SoC blobs
ii linux6.12-6.12.16_1 Linux kernel and modules (6.12 series)
ii util-linux-2.40.2_1 Miscellaneous linux utilities
ii util-linux-common-2.40.2_1 Miscellaneous linux utilities - common files
(chroot) bash-5.2# xbps-query -l | grep grub
ii grub-2.12_2 GRand Unified Bootloader 2
ii grub-arm64-efi-2.12_2 GRand Unified Bootloader 2 - arm64 EFI support
(chroot) bash-5.2# xbps-remove grub-arm64-efi-2.12_2 grub-2.12_2
Name Action Version New version Download size
grub-arm64-efi remove 2.12_2 - -
grub remove 2.12_2 - -
Size freed on disk: 33MB
Space available on disk: 192GB
Do you want to continue? [Y/n] y
Removing `grub-arm64-efi-2.12_2' ...
Removed `grub-arm64-efi-2.12_2' successfully.
Removing `grub-2.12_2' ...
Removed `grub-2.12_2' successfully.
0 downloaded, 0 installed, 0 updated, 0 configured, 2 removed.
(chroot) bash-5.2# xbps-query -l | grep pinebookpro
ii pinebookpro-base-0.6_1 Void Linux Pinebook Pro platform package
ii pinebookpro-firmware-0.0.20201114_1 Firmware files for the Pinebook Pro
ii pinebookpro-uboot-2022.04_2 U-Boot for Pinebook Pro
(chroot) bash-5.2# xbps-query -l | grep x13
ii x13s-base-3_1 Void Linux Thinkpad X13s platform package
(chroot) bash-5.2# xbps-remove pinebookpro-uboot-2022.04_2 pinebookpro-firmware-0.0.20201114_1 pinebookpro-base-0.6_1
Name Action Version New version Download size
pinebookpro-uboot remove 2022.04_2 - -
pinebookpro-firmware remove 0.0.20201114_1 - -
pinebookpro-base remove 0.6_1 - -
Size freed on disk: 1792KB
Space available on disk: 192GB
Do you want to continue? [Y/n] y
Removing `pinebookpro-uboot-2022.04_2' ...
Removed `pinebookpro-uboot-2022.04_2' successfully.
Removing `pinebookpro-firmware-0.0.20201114_1' ...
Removed `pinebookpro-firmware-0.0.20201114_1' successfully.
Removing `pinebookpro-base-0.6_1' ...
Updating udev hardware database ...
Removed `pinebookpro-base-0.6_1' successfully.
0 downloaded, 0 installed, 0 updated, 0 configured, 3 removed.
(chroot) bash-5.2# xbps-remove x13s-base-3_1
Name Action Version New version Download size
x13s-base remove 3_1 - -
Size freed on disk: 1524B
Space available on disk: 192GB
Do you want to continue? [Y/n] y
Removing `x13s-base-3_1' ...
Removed `x13s-base-3_1' successfully.
0 downloaded, 0 installed, 0 updated, 0 configured, 1 removed.
(chroot) bash-5.2# xbps-remove linux6.12-6.12.16_1 linux-6.12_1
Name Action Version New version Download size
linux6.12 remove 6.12.16_1 - -
linux remove 6.12_1 - -
Size freed on disk: 231MB
Space available on disk: 192GB
Do you want to continue? [Y/n] y
Removing `linux6.12-6.12.16_1' ...
Executing post-remove kernel hook: 20-initramfs ...
Executing post-remove kernel hook: 50-efibootmgr ...
Removed `linux6.12-6.12.16_1' successfully.
Removing `linux-6.12_1' ...
Removed `linux-6.12_1' successfully.
0 downloaded, 0 installed, 0 updated, 0 configured, 2 removed.
(chroot) bash-5.2# xbps-install nano
(chroot) bash-5.2# xbps-install mc
(chroot) bash-5.2# ls /boot/
boot.scr boot.txt config-6.12.11_1 dtbs initramfs-6.12.11_1.img lost+found vmlinux-6.12.11_1
(chroot) bash-5.2# rm -r /boot/dtbs
(chroot) bash-5.2# rm -f /boot/*
rm: cannot remove '/boot/lost+found': Is a directory
(chroot) bash-5.2# ls /boot/
lost+found
Since the kernel and its modules have been uninstalled, the kernel and modules from the EndeavourOS distribution will be used within the rootfs of VoidLinux. For this purpose, a new console is started in which the following commands will be executed:
florin@odroid-n2:~$ sudo mkdir /mnt/boot_endeavouros
florin@odroid-n2:~$ sudo mount /dev/sda7 /mnt/boot_endeavouros/
florin@odroid-n2:~$ ls /mnt/boot_endeavouros/
boot.ini boot.ini.orig dtbs Image initramfs-linux.img initramfs-linux.uimg lost+found sd_fusing.sh u-boot.bin
florin@odroid-n2:~$ sudo cp -rp /mnt/boot_endeavouros/dtbs /mnt/root_void/boot/
florin@odroid-n2:~$ sudo cp -fp /mnt/boot_endeavouros/boot.ini /mnt/root_void/boot/
florin@odroid-n2:~$ sudo cp -fp /mnt/boot_endeavouros/Image /mnt/root_void/boot/
florin@odroid-n2:~$ sudo cp -fp /mnt/boot_endeavouros/initramfs-linux.uimg /mnt/root_void/boot/
florin@odroid-n2:~$ ls /mnt/root_void/boot/
boot.ini dtbs Image initramfs-linux.uimg lost+found
florin@odroid-n2:~$ sudo umount /mnt/boot_endeavouros/
florin@odroid-n2:~$ sudo mount /dev/sda5 /mnt/endeavouros/
florin@odroid-n2:~$ ls /mnt/endeavouros/
bin boot dev etc home lib lost+found mnt opt proc root run sbin srv sys tmp usr var
florin@odroid-n2:~$ ls /mnt/endeavouros/usr/lib/modules/
6.13.5-1-eos-arm extramodules-6.13
Return to the chroot console and modify the /boot/boot.ini file according to the new parameters:
(chroot) bash-5.2# nano /boot/boot.ini
The boot.ini file, after modification, will have a content of the form:
# DO Not Edit this line: KERNEL: mainline
setenv board "odroidn2"
# Show logo as soon as possible
showlogo
# System Label
setenv bootlabel "VoidLinux"
# Default Console Device Setting
setenv condev "console=ttyAML0,115200n8 console=tty1"
# Video Output
## preferred_resolution
## set to your preferred resolution using the format:
## {width}x{height}@{hertz}
## example: 1920x1080@60
## or
## Set to an empty string to let the kernel automatically
## choose a resolution for you.
setenv preferred_resolution ""
## petitboot_edid
## if you experience issues of display not showing any
## image when using petitboot you can use this setting
## to overwrite the default display edid information.
##
## A valid value for this option can be:
## 800x600, 1024x768, 1280x720, 1280x1024, 1600x1200,
## 1680x1050, 1920x1080, 2560x1440, 2880x1800, 3840x2160
## or
## Set to an empty string to use the display provided
## edid information.
setenv petitboot_edid ""
## Uncomment to force petitboot to always be set as
## active to always force the edid overwrite.
#setenv petitboot_active "1"
if test "${petitboot_edid}" != "" && test "${petitboot_active}" = "1"; then
setenv voutput "drm_kms_helper.edid_firmware=HDMI-A-1:edid/${petitboot_edid}.bin"
elif test "${preferred_resolution}" != ""; then
setenv voutput "video=HDMI-A-1:${preferred_resolution}"
fi
# Boot Args
setenv bootargs "root=UUID=f0cc6ce1-37af-4865-9347-24f30edcd042 rootwait rw fsck.repair=yes"
setenv bootargs "${bootargs} mitigations=off ${condev}"
setenv bootargs "${bootargs} logo=osd0,loaded no_console_suspend"
setenv bootargs "${bootargs} net.ifnames=0 cma=800M"
setenv bootargs "${bootargs} clk_ignore_unused ${voutput}"
# Set load addresses
setenv dtb_loadaddr "0x20000000"
setenv loadaddr "0x1080000"
setenv initrd_loadaddr "0x4080000"
# Load kernel, dtb and initrd
ext4load usb ${devno}:8 ${loadaddr} /Image
if test "${variant}" = "n2_plus"; then
ext4load usb ${devno}:8 ${dtb_loadaddr} /dtbs/amlogic/meson-g12b-odroid-n2-plus.dtb
else
ext4load usb ${devno}:8 ${dtb_loadaddr} /dtbs/amlogic/meson-g12b-odroid-n2.dtb
fi
ext4load usb ${devno}:8 ${initrd_loadaddr} /initramfs-linux.uimg
# boot
booti ${loadaddr} ${initrd_loadaddr} ${dtb_loadaddr}
Upon reboot, Petitboot will take the boot parameters from the modified file.
Then a password is added for the root user, a working user will be created, and the lightdm service is stopped for the first boot:
(chroot) bash-5.2# passwd
New password:
Retype new password:
passwd: password updated successfully
(chroot) bash-5.2#
(chroot) bash-5.2# useradd -G wheel,dialout,video,plugdev -s /bin/bash -c 'Florin Tanasa' florin
(chroot) bash-5.2# ls /home/
florin
(chroot) bash-5.2# passwd florin
New password:
Retype new password:
passwd: password updated successfully
(chroot) bash-5.2#
(chroot) bash-5.2# touch /etc/sv/lightdm/down
Finally, the consoles are closed and the system is rebooted.
Upon reboot, Petitboot will detect the boot.ini file on the boot partition and will include the VoidLinux option in the menu with the corresponding boot parameters and arguments:
After booting, the user will be greeted by a console where they will log in as the root user, and then the lightdm service will be started using the command:
sv up lightdm
After executing the command, the lightdm service (Window Manager) will start, and after logging into the VoidLinux system, it will appear as follows (the system in the image was set to use the Romanian language from the console at the first boot):
Conclusions
SBC boards equipped with ARM processors are versatile and can be successfully used for various applications (desktop, various services: web, ftp, ssh, files, etc.), have low power consumption, and are generally fanless, making them practically silent, etc.
As a distribution, VoidLinux is very fast and it is worth compiling a custom kernel for the Odroid N2 board, but it is not for beginners.