May 3, 2020
Installing solyste on a Turris Omnia
Four years ago, CZ.NIC launched a campaign on Indiegogo to create what they called "The open-source center of your home". The idea sounded kinda interesting to me. I was not really thrilled about the software, I was excited about the hardware. As you can see, the listed features were quite good. Therefore, I decided to pre-order a board. My primary idea was to port my personal Linux distribution called solyste, to it.
Unfortunately, embedded hardware often use custom U-Boot
and also heavily patched Linux kernel. No surprise, it was the
same here. I dislike having to build custom kernels from obscure
and sometimes unmaintained trees, because it is not a long-term
solution. What can we do when manufacturers decide to (silently)
drop the hardware ? We become stuck with old, buggy and flawed
software. For those reasons, I had to wait for patches in
upstream / mainline Linux
As I write these lines, front LEDs are not really supported by
5.4.x and we can't control them. It seems to work
with OpenWrt and LEDE, though (I didn't test by myself).
Upstreaming support took a long time, but eventually it came later. Even if a few bits are still missing, I knew I could try to boot on the board. Due to the Covid-19 crisis, I had to stay at home like many people across the globe. After all those years, it was the occasion to work on solyste and Omnia, in my spare time.
Booting a kernel on the default system was not really hard.
I had to compile it with
it went surprisingly fine. The device tree file is mandatory too.
The kernel (without loadable modules) will be meticulously tuned
later. Make sure you can access U-Boot prompt with
connection preliminarily. Then, using TFTP I could "send" it to
the board, with the following commands :
tftpboot 0x01000000 zImage tftpboot 0x02000000 armada-385-turris-omnia.dtb bootz 0x01000000 - 0x02000000
You only need to make sure that your kernel supports Btrfs, to be able to mount the first partition (and to avoid a kernel panic). That's what the vanilla system uses.
Few years ago, I embraced
musl libc for my own
projects and I never looked back. Rich, by any chance, if you
read these lines, you are truly awesome.
The repository musl-cross-make provides a makefile to build the musl cross-compiler. That's what I use in solyste (before, I was also building the cross-compiler with my own scripts). Boosted by the previous success, I wrote the proper code to cross-compile the softwares for
was is the scary part. Managing the eMMC is
sometimes extremely difficult. An innocent tiny mistake can
brick your device for good. What a harsh reward. Turris Omnia
has 8Go NAND flash. It would be very sad to not use all that
space. Anyway, at the moment we simply CAN'T boot from both
USB3, because of U-Boot version. mSATA SSD or mPCIe to USB boot
but it requires you to buy something else, one more time.
Luckily, in addition to the default operating system, a
rescue system is installed in SPI flash. We can exploit it to
install solyste. To switch to rescue, follow this
It is based on a
busybox and a few other tools.
There is a script called
/bin directory to reflash the router, as described
We won't use it because it supports
/ # ls bin/ [ date head mktemp rmdir tr [[ dd hostid mount sed traceroute ash df hostname mv seq true awk dirname id nc setsid umount basename dmesg ipcalc netmsg sh uname bunzip2 du kill nice sha256sum uniq busybox echo killall nslookup sleep unxz bzcat egrep less pgrep sort uptime bzip2 expr ln pidof strings vi cat false lock ping stty wc chgrp fgrep logger ping6 sync wget chmod find ls printf tail which chown free lspci ps tar xargs clear fsync lsusb pwd tee xz cmp ftpget md5sum readlink test yes cp grep mkdir rescue.sh tftp zcat cttyhack gunzip mkfifo reset time cut gzip mknod rm touch
fdisk binary is present in
but we still lack
e2fsprogs to create
ext4 is perfect for
me (my systems are read-only anyway). Not a problem here as
e2fsprogs is included in
base group in
solyste. That means I can easily build a static
mke2fs binary. That's neat, isn't it ?
$ file mke2fs mke2fs: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
mke2fs binary could be also very useful
in the future. I decided to copy it in
we should ask CZ.NIC to do it, but I feel it would be too much
hassle, as they are focusing on Btrfs. Now, we create the
/ # fdisk /dev/mmcblk0 / # mke2fs -t ext4 /dev/mmcblk0p1
We are (very) good so far.
solyste is finally ready to be deployed in eMMC. Let's
extract the archive stored on an external USB drive, with
/ # mount -t ext4 /dev/mmcblk0p1 /mnt / # tar xvf SOLYSTE-OMNIA.tar.gz -C /mnt / # chown -R 0:0 /mnt/* / # sync / # umount /mnt
Press the reset button to reboot. Before we edit U-Boot
environment variables, we verify if the
partition is correctly listed :
=> ext4ls mmc 0:1 / <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found <DIR> 4096 bin <DIR> 0 boot <DIR> 0 dev <DIR> 0 etc <DIR> 0 mnt <DIR> 0 proc <DIR> 0 root <DIR> 0 sys <DIR> 0 tmp <DIR> 0 var
Hum, it does not seem to be very good… The directories were simply empty and the files inside them were missing :
=> ext4ls mmc 0:1 /boot ** Can not find directory. **
At this point, I thought there was a problem with the eMMC, even if I didn't do something wrong. But it was still correctly detected :
=> mmcinfo Device: mv_sdh Manufacturer ID: 90 OEM: 14a Name: H8G4a Tran Speed: 52000000 Rd Block Len: 512 MMC version 4.0 High Capacity: Yes Capacity: 7.3 GiB Bus Width: 8-bit Erase Group Size: 512 KiB
Thanks to TFTP, I could boot on my kernel and the main
partition was totally fine. Something was bad with U-Boot.
ext4 implementation is too simple.
In embedded world, filesystems in 64-bit mode can lead to erratic behavior. I decided to boot once again in rescue mode to create the
ext4 filesystem, in 32-bit this time.
Do you remember when I told you earlier that
could be necessary ? So, here we go again :
/ # mke2fs -t ext4 -O ^64bit /dev/mmcblk0p1
Then, after extracting the archive and rebooting, the
ext4ls command was more realistic :
=> ext4ls mmc 0:1 / <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found <DIR> 4096 bin <DIR> 4096 boot <DIR> 4096 dev <DIR> 4096 etc <DIR> 4096 mnt <DIR> 4096 proc <DIR> 4096 root <DIR> 4096 sys <DIR> 4096 tmp <DIR> 4096 var => ext4ls mmc 0:1 /boot <DIR> 4096 . <DIR> 4096 .. 17506 armada-385-turris-omnia.dtb 3793992 zImage
VICTORY ! As the main
ext4 filesystem is
completely detected by U-Boot, we can now setup the boot
The default environment variables can be listed with
printenv. Here the default
mmcboot variables. We will modify them :
bootargs=earlyprintk console=ttyS0,115200 rootfstype=btrfs rootdelay=2 root=b301 rootflags=subvol=@,commit=5 rw mmcboot=setenv bootargs "$bootargs cfg80211.freg=$regdomain"; btrload mmc 0 0x01000000 boot/zImage @; btrload mmc 0 0x02000000 boot/dtb @; bootz 0x01000000 - 0x02000000
First, we will replace
setenv. I tried the following, but I had many
kernel panics :
setenv bootargs rootfstype=ext4 root=/dev/mmcblk0p1 rw console=ttyS0,115200
The kernel was booting too fast and the eMMC was not
discovered in time. It's also quite common. Let's add
rootdelay. Even default variable has it. I appended
setenv bootargs rootfstype=ext4 root=/dev/mmcblk0p1 rootdelay=2 rw console=ttyS0,115200 quiet
mmcboot variable is similar to
tftpboot command. Defining
cfg80211.freg makes no sense here, because my board
do not have WiFi. Secondly,
btrload is for
ext4 counterpart is
ext4load. With those parameters, we can compose
the variable :
setenv mmcboot "ext4load mmc 0:1 0x01000000 boot/zImage ; ext4load mmc 0:1 0x02000000 boot/armada-385-turris-omnia.dtb ; bootz 0x01000000 - 0x02000000"
Do not get fooled by my words, I had to try four or five
times to find the correct value. Once
mmcboot variables are setup, we save them with
saveenv command and… we are done ! You can either
push the reset button on the back or directly launch
run mmcboot command.
Usually, when the Omnia was unplugged from electrical source or after a reset, the DDR3 RAM will fail to initialize. Here the output :
Memory config in EEPROM: 0x01 ddr3_tip_pbs_rx failure CS #0 Title: I/F# , Tj, Calibration_n0, Calibration_p0, Calibration_n1, Calibration_p1, Calibration_n2, Calibration_p2,CS0 , VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref, PBSTx-Pad0,PBSTx-Pad1,PBSTx-Pad2,PBSTx-Pad3,PBSTx-Pad4,PBSTx-Pad5,PBSTx-Pad6,PBSTx-Pa d7,PBSTx-Pad8,PBSTx-Pad9,PBSTx-Pad10, PBSRx-Pad0,PBSRx-Pad1,PBSRx-Pad2,PBSRx-Pad3,PBSRx-Pad4,PBSRx-Pad5,PBSRx-Pad6,PBSRx-Pad7,PBSRx-Pad8,PBSRx-Pad9,PBSRx-Pad10, Data: 0,72,19,15,19,15,20,20,CS0 , 0,0,10,10,0,423,7,1,6,23,10,4,0, 63,63,63,63,31,31,63,63,63,63,63, 0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0, 0,0,6,6,0,422,6,1,6,19,10,4,0, 63,63,63,63,31,31,63,63,63,63,63, 0,0,0,0,0,0,0,0,0,0,0, 0,4,2,8,0,0,3,8,8,10,0, 0,0,6,6,0,421,5,1,6,19,10,4,0, 63,63,63,63,31,31,63,63,63,63,63, 0,0,0,0,0,0,0,0,0,0,0, 2,0,0,6,0,0,0,2,6,3,0, 0,0,10,10,0,423,7,1,6,23,10,4,0, 63,63,63,63,31,31,63,63,63,63,63, 0,0,0,0,0,0,0,0,0,0,0, 1,2,1,5,0,0,2,0,4,1,0, Run_alg: tuning failed 0 DDR3 run algorithm - FAILED 0x1 DDR3 Training Sequence - FAILED
I share it to you in case you noticed it on your board. I do not know if my unit is defective or not. I just hope it will not happen when it's deployed, in a remote location. I would be unable to access it.
solyste on Turris Omnia
After the previous steps, solyste is now perfectly booting. The board is ready to be used. Needless to say, I'm quite happy. Maybe it's time to brag a little bit…
solyste armv7l on 5.4.33-SOLYSTE (/dev/ttyS0) solyste-omnia login: root Password: Welcome to your solyste box! [solyste-omnia] /root # cat /proc/version Linux version 5.4.33-SOLYSTE (ypnose@solyste) (gcc version 9.2.0 (GCC)) #1 SMP Sat May 2 13:46:17 CEST 2020 [solyste-omnia] /root # uname -a Linux solyste-omnia 5.4.33-SOLYSTE #1 SMP Sat May 2 13:46:17 CEST 2020 armv7l GNU/Linux [solyste-omnia] /root # du -h /boot/zImage 3.6M /boot/zImage [solyste-omnia] /root # zcat /proc/config.gz | grep CONFIG_MODULES # CONFIG_MODULES is not set
[solyste-omnia] /root # cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 1 (v7l) BogoMIPS : 1600.00 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 processor : 1 model name : ARMv7 Processor rev 1 (v7l) BogoMIPS : 1600.00 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 Hardware : Marvell Armada 380/385 (Device Tree) Revision : 0000 Serial : 0000000000000000
Daemons / services :
[solyste-omnia] /root # perpls -G [+ +++ +++] crond uptime: 107s/107s pids: 147/146 [+ +++ ---] getty-ttyS0 uptime: 107s/-s pids: 145/- [+ +++ ---] klogd uptime: 107s/-s pids: 155/- [- --- ---] monit (service not activated) [- --- ---] openntpd (service not activated) [+ +++ +++] sshd uptime: 107s/107s pids: 152/150 [+ +++ ---] syslogd uptime: 107s/-s pids: 144/- [- --- ---] unbound (service not activated) [- --- ---] vnstatd (service not activated) [+ +++ ---] watchdog uptime: 107s/-s pids: 148/- [solyste-omnia] /root # pstree init---rc.intro---perpboot-+-perpd-+-crond | |-klogd | |-mksh---pstree | |-sshd | |-syslogd | |-2*[tinylog] | `-watchdog `-tinylog [solyste-omnia] /root # print $KSH_VERSION @(#)MIRBSD KSH R59 2020/04/14
Even if I plan to write an article explaining why solyste is different and how it works, you can visit my "Projects" page in the meantime. Have a nice day and take care of you.