ArchLinux on an Android TV Box

From old Android TV Box to server: teardown, device tree extraction and ArchLinuxARM install.

ArchLinux on an Android TV Box

I needed a mini PC running Linux, with an ethernet port and low power consumption. I had an old TV Box (Mecool BB2 Pro) that is the perfect candidate while also being completely silent. There are tons of use for this kind of systems: NVR, 3D printing server, homemade VPN, NAS etc. Moreover, Linux replaces the default Android OS that comes preinstalled which is old, no longer updated, insecure and/or infected.

Some of the main OS to install on this kind of devices are Armbian and LibreELEC. The latter is focused on media consumption so it takes specific care to make media-related thing work (hardware acceleration, video/sound, …), while Armbian is a port of Debian for ARM devices. Since my end goal was an ArchLinuxARM system, I based my work converting a working Armbian install into an Arch one.

Armbian
Linux for custom hardware
LibreELEC
Just enough OS for KODI
Arch Linux ARM

On the board we have:

  • Amlogic S912 SOC, under the heatsink
  • Female SMA antenna connector
  • G2401SG, 1 GBit Ethernet controller, top right
  • RTL8211F, Ethernet transceiver, top center-right
  • K4A4G165WE-BCRC, RAM, center left
  • THGBMBG7D2KBAIL, 16 GB eMMC, bottom right
  • KM63350504, WiFi/BT controller, bottom left (AP6335-compatible?)
  • K4A8G165WB-BCRC, RAM, bottom side

If you prefer skipping all the explanations, jump to the Image Creation section at the end.

Armbian Install

The following procedure is specific for my TV Box's CPU but can be adapted easily. Follow the instructions reported here to get to a bootable Armbian system installed on an USB (in my case) or an SD card (/dev/sdb for me):

# The download link will change!
set IMAGE 'Armbian_23.11.1_Aml-s9xx-box_bookworm_current_6.1.63.img'
wget https://redirect.armbian.com/aml-s9xx-box/archive/$IMAGE.xz
unxz $IMAGE.xz

sudo dd if=$IMAGE of=/dev/sdb status=progress

sudo mkdir -pv /mnt/TVBOX/{B,R}OOT/
sudo mount /dev/sdb1 /mnt/TVBOX/BOOT/
sudo mount /dev/sdb2 /mnt/TVBOX/ROOT/

In my case the box has a S912 CPU so I selected the correct u-boot file and renamed it: sudo cp /mnt/TVBOX/BOOT/u-boot-s905x-s912 /mnt/TVBOX/BOOT/u-boot.ext

Device Tree

The dtb is a file that tells the kernel where the different component are located since it contains information about the board and the peripherals. There is no dtb (Device Tree Blob) specific for my box so I used one from a similar model (/dtb/amlogic/meson-gxm-mecool-kiii-pro.dtb in the Armbian image). The two box are indeed very similar, here is a Kiii Pro model teardown. The Linux kernel contains several dts files, you can browse them here. They can be compiled from source (with some gcc command and then using device-tree-compiler with the command dtc -@ -O dtb -o mecool_bb2_pro_v1.dtb mecool_bb2_pro_extracted.dts) or extracted from the ArchLinuxARM tarball. Additionally, I saved the dtb file from the installed Android ROM (located at /dev/dtb while booted) which should contain all the necessary information to write one for Linux. I also extracted it by using a dtc binary that I statically compiled on an aarch64/arm64 system (git clone https://android.googlesource.com/platform/external/dtc; cd dtc; make STATIC_BUILD=1 NO_YAML=1), uploaded to the TVBox running Android and, as the root user, running the command ./dtc -I fs /proc/device-tree -O dts -o fs_extracted.dts to extract it from memory. The Android dtb files however can not be used directly since Android use a (really) old kernel and drivers name are different.

I also had to modify the extlinux bootloader configuration file to convert to uppercase some keywords (like APPEND) and remove the splash option (to read the boot log process). The final /boot/extlinux/extlinux.conf is this one:

LABEL Armbian
LINUX /Image
INITRD /uInitrd

FDT /dtb/amlogic/meson-gxm-mecool-kiii-pro.dtb
APPEND root=UUID=a6cf29bd-49ae-4d3b-bf22-800408ae1fba rootflags=data=writeback console=ttyAML0,115200n8 console=tty0 rw no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 plymouth.ignore-serial-consoles

Note that the UUID may depend on the specific Armbian version. Now Armbian should be bootable with a working ethernet port. To boot the new OS from the external media (USB/SD card), plug in the power while pressing the reset button, then release it after a few seconds. At this point the TV Box runs a Linux distro, based on Debian, but we can take it even further and install Arch on it.

ArchLinuxARM from Armbian

To convert the Armbian to ArchLinuxARM we basically need to convert the root partition (/dev/sdb2 mounted on /mnt/TVBOX/ROOT/ in my case) and update the bootloader configuration file to boot from the new kernel.

wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
sudo rm -r /mnt/TVBOX/ROOT/*
sudo tar -xf ArchLinuxARM-aarch64-latest.tar.gz -C /mnt/TVBOX/ROOT/

At this point the TV Box boots ArchLinuxARM but with the old kernel:

[root@alarm ~]# head -n4 /etc/os-release
NAME="Arch Linux ARM"
PRETTY_NAME="Arch Linux ARM"
ID=archarm
ID_LIKE=arch
[root@alarm ~]# uname -a
Linux alarm 6.1.11-meson64 #23.02.2 SMP PREEMPT Sat Feb 18 00:07:55 UTC 2023 aarch64 GNU/Linux

Now we need to tell the bootloader to boot the new kernel image and add the correct mount options for the boot partition. To do so shut down the box, plug the USB/SD back in the PC, mount again the two partition and update the content of the boot partition (/dev/sdb1 mounted on /mnt/TVBOX/BOOT/ in my case) with the boot folder present in ROOT:

sudo mv /mnt/TVBOX/ROOT/boot/* /mnt/TVBOX/BOOT/

Note that some of the old (Armbian) files are required to boot, so don't delete them. They are the bootloader (U-Boot) files. Some information on how to build the bootloader can be found here (archived). Update /mnt/TVBOX/ROOT/etc/fstab to mount the two partitions and since we are at it reduce the number of writes made to the disk to increase the USB/SD longevity:

echo '/dev/sda1  /boot  vfat  defaults  0  2
/dev/sda2  /  ext4  defaults,noatime,commit=4780,barrier=0,data=writeback,nobarrier,max_batch_time=0  0  1' \
    | sudo tee -a /mnt/TVBOX/ROOT/etc/fstab

Now create the new extlinux config file /mnt/TVBOX/BOOT/extlinux/extlinux.conf with the following content:

LABEL ArchLinuxARM
LINUX /Image
INITRD /initramfs-linux.img

FDT /dtbs/amlogic/meson-gxm-mecool-kiii-pro.dtb
APPEND root=LABEL=armbi_root rootflags=data=writeback console=ttyAML0,115200n8 console=tty0 rw no_console_suspend consoleblank=0 fsck.fix=yes fsck.repair=yes net.ifnames=0 plymouth.ignore-serial-consoles

If you want to (temporary) enable SSH login for the root user using password (for configuration purposes) modify /mnt/TVBOX/ROOT/etc/ssh/sshd_config to add the line PermitRootLogin yes. Remember to later change it back to PermitRootLogin prohibit-password. Now boot the system and verify that it's booting the ArchLinuxARM kernel. Finally tweak a couple of system's parameters to further reduce the number of writes to the disk:

echo 'Storage=volatile' | sudo tee -a /etc/journald.conf
echo 'vm.dirty_background_ratio = 20
vm.dirty_expire_centisecs = 360000
vm.dirty_writeback_centisecs = 360000' | sudo tee -a /etc/sysctl.conf

Note that Armbian deploys other measures to optimize the device performance, they are shortly described in the documentation here. From now on follow the ArchLinux Wiki to finish installing the OS (vconsole, locale, hostname, networking …).

Additional Tinkering

Since the default brcm firmware present in ArchLinuxARM doesn't seem to support my wireless (WiFi and Bluetooth) chip, it needs to be replaced with the LibreELEC version (archived). There is also an Armbian version (archived) but it does not seem to work out of the box (probably some files with a specific name need to be symlinked in the firmware folder). In Arch, the content of /usr/lib/firmware/brcm/ must be replaced by content of the downloaded brcm folder.

If you want to expand the filesystem and partition to fill all the SD Card/USB, use either gparted on the PC or the script armbian-resize-filesystem to be adapted for non-Armbian installations (remove sourcing of other files, define missing variables i.e. $Log, remove systemd stuff, …). The parted program is needed to run it. If you plan on installing the OS on eMMC resize it later (better to do it manually).

After ensuring that the system is fully configured and working, you can even install the OS on the integrated eMMC (16GB for my box). However this is strongly discouraged for (at least some) Amlogic boards due to a proprietary partitioning scheme (LibreELEC short explanation, S905 thread). If you still want do so, utilize the script provided by Armbian located in /root/install-aml.sh of the Armbian installation or on the GitHub repo (archived). If you already converted the installation to ArchLinuxARM, you can retrive the file by mounting the Armbian image as a loop device:

sudo losetup --find --show Armbian_*.img
sudo fdisk -l /dev/loop*
sudo mount /dev/loop0p2 /mnt/TVBOX/ROOT
ls -l /mnt/TVBOX/ROOT/root/install-aml.sh

The Infra Red receiver should be functional by default (e.g. the ON/OFF switch on the remote is fully working, even if the box is off) and can be customized by installing and configuring LIRC. In my case also the physical ON/OFF button is working.

Image Creation

To quickly make changes, I later created an image that can directly be flashed on the SD/USB and booted with Arch.

# Image Creation
fallocate -l 5G TVBox.img
sudo losetup --find --show TVBox.img
sudo dd if=Armbian_23.11.1_Aml-s9xx-box_bookworm_current_6.1.63.img of=/dev/loop0 status=progress

sudo parted /dev/loop0 resizepart 2 100%
tune2fs -O extents,uninit_bg,dir_index,has_journal,flex_bg,huge_file,extra_isize,dir_nlink,uninit_bg /dev/loop0p2
sudo e2fsck -f /dev/loop0p2
sudo resize2fs /dev/loop0p2
sudo fatlabel /dev/loop0p1 BOOT
sudo e2label /dev/loop0p2 root

sudo fdisk -l
sudo mount /dev/loop0p1 mnt/boot/
sudo mount /dev/loop0p2 mnt/root/

# /boot partition changes
sudo cp -v mnt/boot/u-boot-s905x-s912 mnt/boot/u-boot.ext
echo 'LABEL ArchLinuxARM
LINUX /Image
INITRD /initramfs-linux.img
# use the Arch dtb file
FDT /dtbs/amlogic/meson-gxm-mecool-kiii-pro.dtb
APPEND root=UUID=a6cf29bd-49ae-4d3b-bf22-800408ae1fba rootflags=data=writeback console=ttyAML0,115200n8 console=tty0 rw no_console_suspend consoleblank=0 net.ifnames=0 fsck.fix=yes fsck.repair=yes plymouth.ignore-serial-consoles' \
| sudo tee mnt/boot/extlinux/extlinux.conf

# /root from Armbian To ArchLinuxARM
sudo rm -r mnt/root/*
sudo tar -xf ArchLinuxARM-aarch64-latest.tar.gz -C mnt/root/
sudo mv -v mnt/root/boot/* mnt/boot/
sudo umount mnt/boot
sudo mount /dev/loop0p1 mnt/root/boot/

# Wireless driver fix
# another version, from Armbian: https://github.com/armbian/firmware/tree/master/brcm
wget -qO- https://github.com/LibreELEC/brcmfmac_sdio-firmware/archive/refs/heads/master.tar.gz | tar -xzf -
sudo rm mnt/root/usr/lib/firmware/brcm/*
sudo cp -v brcmfmac_sdio-firmware-master/* mnt/root/usr/lib/firmware/brcm/

echo '/dev/sda1  /boot  vfat  defaults  0  2
/dev/sda2  /  ext4  defaults,noatime,commit=4780,barrier=0,data=writeback,nobarrier,max_batch_time=0  0  1' \
| sudo tee -a mnt/root/etc/fstab

# Script (adapted from /usr/bin/armbian/armbian-resize-filesystem)
sudo cp resize-filesystem mnt/root/root/

sudo arch-chroot mnt/root/
  pacman-key --init
  pacman-key --populate archlinuxarm
  pacman --noconfirm -Sy parted # needed for the resize-filesystem script
  

Future Works

  • Armbian performance tweaks in Arch
  • eMMC installation
  • IR remote as automation triggers in HomeAssistant

Notes

(Re)booting may take a long time (~1 min), depends on how fast is the disk on which the system has been installed (USB, SD, eMMC) since on shutdown all the files cached in RAM must be synced to the disk.

A display (or an HDMI capture card) and a keyboard to connect to the Box are strongly suggested. The display output is required to read possible boot error.


Resources

Installation Instructions for TV Boxes with Amlogic CPUs
These instructions are for Amlogic CPUs for TV Boxes. Note: If you have previously run other distributions on the box such as coreelec the below installation will not work. You will need to restore the original android firmware before attempting the install. coreelec changes the boot environment…
Run ArchLinux on Amlogic S905x S912 S905w Android TV Box
Run ArchLinux on Amlogic S905x S912 S905w Android TV Box
Review of Mecool BB2 Pro TV Box with DDR4 Memory - Part 1: Specs, Unboxing and Teardown - CNX Software
Mecool BB2 Pro is yet another Amlogic S912 Android 6.0 TV box, but after Eweat R9 Plus, it’s my second TV box with DDR4 memory that should deliver much