I recently upgraded to gigabit fiber internet. Turns out my firewall only supports 100 mbps, which is a bit disappointing. I primarily upgraded to fiber because it was cheaper and I wanted a symmetric connection, so download speed isn't all that important to me, but it would still be nice to get what I'm paying for. After some shopping around for a new firewall, I realized I already had an espressobin ultra box that should support gigabit speeds (I bought it awhile ago to make some custom home network equipment and it's sat in its box ever since).
The obvious answer here is to save a few hundred dollars by dumping countless hours into building myself the perfect firewall.
My strategy:
Install guix
(my distro of choice) using marvell's kernel.
Upgrade to an upstream kernel.
Set up a NAT firewall using nftables
.
Optimize until I'm happy with the speed.
First I've got to figure out how this is set up. I haven't touched any
of the software yet, it's just running whatever the vendor put on
there. Booting attached to the serial console, it looks like it's
using u-boot
(full boot log here) and Ubuntu
18.04 running a 5.4 kernel:
$ uname --all
Linux ebinx003606 5.4.53-00023-gb67cb8815786 #3 SMP PREEMPT \
Thu Mar 4 16:52:46 CST 2021 aarch64 aarch64 aarch64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04 LTS"
The commit b67cb8815786
points at linux-5.4.53-gti
branch in
Globalscale's kernel repo,
so I'll start there. Newer 5.4.163, 5.10.166, and 5.16.y branches
exist, but I'll be upgrading to an upstream kernel anyways, so I'll
just ignore those and get something working first.
Where do kernel and device tree get loaded from? I see a bunch of
files in /boot
, so I'd guess that kernel and device tree are loaded
from this location in the rootfs:
$ find /boot
/boot/
/boot/armada-3720-espressobin_ultra.dtb
/boot/Image
/boot/bootloader
/boot/bootloader/... [omitted for brevity]
/boot/armada-3720-ccpe.dtb
There are a bunch of files in /boot/bootloader
as well, but those
are not referenced by u-boot
and don't seem important, so I'm
ignoring them. Then checking the u-boot
environment (with some
extraneous fields removed (full u-boot
environment)):
Marvell>> printenv
board=mvebu_armada-37xx
board_name=mvebu_armada-37xx
bootcmd=mmc dev 0; ext4load mmc 0:1 $kernel_addr_r $image_name; \
ext4load mmc 0:1 $fdt_addr_r $fdt_name;setenv bootargs \
$console root=PARTUUID=89708921-01 rw rootwait net.ifnames=0 \
biosdevname=0; booti $kernel_addr_r - $fdt_addr_r
fdt_name=boot/armada-3720-ccpe.dtb
image_name=boot/Image
Notably bootcmd
and image_name
agree with my guess. fdt_name
points at armada-3720-ccpe.dtb
. I should be able to build a new
kernel and device tree, stick it in /boot
, and make sure that it
works. Starting with defining the kernel package for guix:
(define-public linux-espressobin-ultra
(package
(inherit
(customize-linux
#:name "linux-espressobin-ultra"
#:source
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/globalscaletechnologies/linux.git")
(commit "linux-5.4.53-gti")))
(file-name (git-file-name "linux-espressobin-ultra" "5.4.53-gti"))
(sha256
(base32 "1pwpn6wrz6ydx62gp9g2drapg126lwihcr0yhhcqilc1cxy7m02q")))
#:defconfig "gti_ccpe-88f3720_defconfig"
#:extra-version "guix"))
(version "5.4.53-gti")
(home-page "https://github.com/globalscaletechnologies/linux")
(synopsis "Linux kernel with patches from globalscale technologies")
(description "Linux kernel build from globalscale technologies sources,
including nonfree binary blobs.")))
Then trying to build:
$ guix build --target=aarch64-linux-gnu --load-path=. linux-espressobin-ultra
I immediately hit a basic configuration error:
Mismatching configurations in .config and arch/arm64/configs/guix_defconfig \
(("CONFIG_ARM_IMX_CPUFREQ_DT" (#f "m")) ...
Looking at VERIFY-CONFIG
in guix/build/kconfig.scm
, this compares
.config
with the original defconfig file, checking for
differences. This appears to be looking for malformed configs
(e.g. some options are enabled without their dependencies). Looking at
the first one ARM_IMX_CPUFREQ_DT
is set to "m"
in
gti_ccpe-88f3720_defconfig
; this depends on ARCH_MXC
, which is not
set. We can also see that ARM_IMX_CPUFREQ_DT
is not set in
/proc/config.gz
on the board, confirming that the defconfig is
incorrect.
Situations like this are pretty common in vendor kernel trees where
defconfigs are edited manually and/or not updated properly when
upgrading kernel sources. The fix is pretty easy: make ARCH=arm64 gti_ccpe-88f3720_defconfig && make ARCH=arm64 savedefconfig
to
"re-normalize" the malformed config. The resulting diff is
here.
We can use local-file
to use this new config in the kernel build,
which should still be identical to the running kernel. With this, the
build succeeds (conveniently giving us device trees as well).
For now, I'd like to avoid trampling the existing kernel to make
recovery easier if I fail. I'll just install the new kernel, modules,
and device tree at different paths in the rootfs and then just toggle
this on/off with u-boot variables (via fw_setenv
).
With the kernel image at /boot/guix/Image
and device tree at
/boot/guix/armada-3720-ccpe.dtb
(modules are already a different
path due to the different extraversion
string), I can point u-boot
at the new images and then boot into the new system:
$ fw_setenv image_name boot/guix/Image
$ fw_setenv fdt_name boot/guix/armada-3720-ccpe.dtb
$ reboot
...
$ uname --all
Linux ebinx003606 5.4.53-guix #1 SMP PREEMPT 1 aarch64 aarch64 aarch64 GNU/Linux
The kernel/device tree are working, but modules are not:
# modprobe btrfs
modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() \
could not open moddep file '/lib/modules/5.4.53-guix/modules.dep.bin'
modprobe: FATAL: Module btrfs not found in directory /lib/modules/5.4.53-guix
The modules.dep.bin
file is indeed not built by guix in the kernel
and is instead handled in linux-module-database
as part of the
system profile. I'd guess this is done to allow building and loading
modules outside of the kernel tree. Checking gnu/packages/linux.scm
confirms this:
Disable depmod because the Guix system's module directory is an union of potentially multiple packages. It is not possible to use depmod to usefully calculate a dependency graph while building only one of them.
This doesn't really matter yet since I don't quite need modules (and I've at least verified the kernel boots), so I'll defer this for now. Let's set the kernel and device-tree paths back:
# fw_setenv image_name boot/Image
# fw_setenv fdt_name boot/armada-3720-ccpe.dtb
The next step is to build a guix system image to flash to the
eMMC. Since u-boot
is in QSPI (and difficult to upgrade), I'd like
to leave it alone and manage just the rootfs and kernel via guix
.
Guix's u-boot
bootloader will generate extlinux.conf
, and I can
then modify u-boot
's boot command (via fw_setenv
) to load this
using sysboot
. I'd just have to change the u-boot
variables once,
then reconfiguring the guix system will generate a new extlinux.conf
and get picked up automatically by u-boot
.
Let's start by testing this out with a fake /boot/extlinux/extlinux.conf
:
LABEL prebuilt ubuntu
MENU LABEL ubuntu 18.04
KERNEL /boot/Image
FDT /boot/armada-3720-ccpe.dtb
APPEND root=PARTUUID=89708921-01 rw rootwait console=ttyMV0,115200
Then rebooting into u-boot
, I need to figure out the correct
sysboot
invocation to load this configuration. The usage message is:
sysboot [-p] <interface> <dev[:part]> <ext2|fat|any> [addr] [filename]
- load and parse syslinux menu file 'filename' from ext2, fat
or any filesystem on 'dev' on 'interface' to address 'addr'
What to use for the interface and device? In the ext4load
in the
boot command, it looks like it's currently using mmc 0:1
. Checking
the usage for ext4load
:
ext4load <interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext4 filesystem
So mmc 0:1
is definitely what we want. For the address, I'll just
pick something random that doesn't seem to be in use based on the
environment variables.
Marvell>> sysboot mmc 0:1 any 0x4000000 /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
"Synchronous Abort" handler, esr 0x96000046
Attempt to access RT service or TEE region (addr: 0x4000000, el2)
Do not use address range 0x4000000-0x5400000
elr: 0000000000062e18 lr : 000000000004da20 (reloc)
elr: 000000003ff9ee18 lr : 000000003ff89a20
x0 : 0000000004000000 x1 : 000000003f628700
x2 : 00000000000000c3 x3 : 0000000000000000
x4 : 0000000000000018 x5 : 00000000000000c0
x6 : 7270204c4542414c x7 : 0000000000000020
x8 : 000000003ffc06f0 x9 : 0000000000000008
x10: 000000003f6b4560 x11: 0000000000000001
x12: 000000003f6b4560 x13: 0000000000538811
x14: 000000003f62903c x15: 0000000000000002
x16: 000000003ffbc4d0 x17: 000000003ffbc4d0
x18: 000000003f62bdb0 x19: 00000000000000c3
x20: 000000003f62d640 x21: 0000000004000000
x22: 000000003f628700 x23: 000000003f628940
x24: 000000003f628940 x25: 000000003ffdbca0
x26: 0000000004001000 x27: 0000000000000000
x28: 0000000000000009 x29: 000000003f628b80
Resetting CPU ...
Ok, so maybe I'll pick something a different address...
Marvell>> sysboot mmc 0:1 any 0x5400000 /boot/extlinux/extlinux.conf
After that the system boots as expected. In the booted system,
/proc/cmdline
shows the command-line args are pulled from the
extlinux.conf
instead of u-boot
, so it definitely worked.
Now that I know how to boot an extlinux.conf
, let's set up
guix. Guix's base services already include a tty on the console and I
don't need anything else to start with.
(define espressobin-ultra-barebones-os
(operating-system
(kernel linux-espressobin-ultra)
(initrd-modules '())
(host-name "ebinx")
(timezone "US/Pacific")
(locale "en_US.utf8")
(bootloader (bootloader-configuration
(bootloader u-boot-bootloader)
(targets '("/dev/mmcblk0"))))
(file-systems (cons
(file-system
(device "/dev/mmcblk0p1")
(mount-point "/")
(type "ext4"))
%base-file-systems))))
Then build it with:
$ guix system image --target=aarch64-linux-gnu ebinx.scm
The resulting image is 1.6G, I'll want to trim that down a bit in the future. Examining the image:
$ sudo kpartx -a -r /gnu/store/...-disk-image
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 1.6G 1 loop
└─loop0p1 253:1 0 1.6G 1 part
...
$ sudo mount /dev/mapper/loop0p1 /mnt -o ro
$ cd /mnt
$ cat boot/extlinux/extlinux.conf
# This file was generated from your Guix configuration. Any changes
# will be lost upon reconfiguration.
UI menu.c32
MENU TITLE GNU Guix Boot Options
PROMPT 1
TIMEOUT 50
LABEL GNU with Linux-Espressobin-Ultra 5.4.53-gti
MENU LABEL GNU with Linux-Espressobin-Ultra 5.4.53-gti
KERNEL /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/Image
FDTDIR /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/lib/dtbs
INITRD /gnu/store/...-raw-initrd/initrd.cpio.gz
APPEND root=38af4c98-4625-3523-b285-334638af4c98 \
gnu.system=/gnu/store/...-system \
gnu.load=/gnu/store/...-system/boot \
modprobe.blacklist=usbmouse,usbkbd quiet
That's mostly correct. The two issues I see:
I'll want to add the console to the command-line as well.
I don't think FDTDIR
alone will be enough to find the device tree
during boot.
To fix (1), I can just add a kernel-arguments
field to the
operating-system
definition:
(kernel-arguments
(cons* "console=ttyMV0,115200"
"earlycon=ar3700_uart,0xd0012000"
%default-kernel-arguments))
For (2), I'll ignore this for now and fix it when the system fails to
boot. I'm not yet sure whether I should change this in guix
or
u-boot
. It's also important to note that guix
adds quiet
as part
of %default-kernel-arguments
, which may interfere with debugging
boot issues. Unwinding everything:
$ cd ~/
$ sudo umount /mnt
$ sudo kpartx -d /dev/loop0
$ sudo losetup -d /dev/loop0
After modifying kernel-arguments
(and re-mounting):
# This file was generated from your Guix configuration. Any changes
# will be lost upon reconfiguration.
UI menu.c32
MENU TITLE GNU Guix Boot Options
PROMPT 1
TIMEOUT 50
LABEL GNU with Linux-Espressobin-Ultra 5.4.53-gti
MENU LABEL GNU with Linux-Espressobin-Ultra 5.4.53-gti
KERNEL /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/Image
FDTDIR /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/lib/dtbs
INITRD /gnu/store/...-raw-initrd/initrd.cpio.gz
APPEND root=38af4c98-4625-3523-b285-334638af4c98 \
gnu.system=/gnu/store/...-system \
gnu.load=/gnu/store/...-system/boot \
console=ttyMV0,115200 \
earlycon=ar3700_uart,0xd0012000 \
modprobe.blacklist=usbmouse,usbkbd quiet
That's better.
Now that I've got the disk image building, I've got to figure out how to get it installed.
Recovery using a usb are listed here: https://espressobin.net/espressobin-ultra-build-instruction/
GTI's instructions suggest booting into a recovery initramfs and flashing from there. Unfortunately, they don't seem to actually link to the recovery image and I can't find where it's built.
We've got a couple of options:
Flash using u-boot
.
Build a bootable USB with guix
(doesn't seem like there are any
pre-built arm64
images) and flash from there.
I'm going to attempt (1). This is a little tricky since the u-boot
that is running doesn't have read/write commands for flashing
images. Also, the image itself is larger than RAM, so it's going to be
tricky to flash from memory.
Skimming through u-boot
's command list, there is a gzwrite
command
that decompresses a chunk from memory and writes it to a disk. This is
convenient, since my disk image is only 382 MB when gzip
'd, which
will fit in RAM. After compressing the disk image and copying it to a
USB drive, I'm back in u-boot
:
Marvell>> usb start
starting USB...
USB0: Register 2000104 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB1: USB EHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning usb for storage devices... 1 Storage Device(s) found
Marvell>> usb storage
Device 0: Vendor: Lexar Rev: 1100 Prod: USB Flash Drive
Type: Removable Hard Disk
Capacity: 15276.0 MB = 14.9 GB (31285248 x 512)
Marvell>> ls usb 0:1
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
400313016 disk-image.gz
Marvell>> load usb 0:1 0x5400000 disk-image.gz
400313016 bytes read in 9954 ms (38.4 MiB/s)
Marvell>> gzwrite mmc 0 0x5400000 400313016
gzwrite: weird termination with result 0
uncompressed 36453026 of 4007447747
crcs == 0xbdcd4917/0x19d71fd0
The "weird termination" is weird; checking eMMC shows that it definitely didn't work:
Marvell>> ls mmc 0:1
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
<DIR> 4096 bin
<DIR> 4096 boot
<DIR> 4096 etc
<DIR> 4096 gnu
<DIR> 4096 home
<DIR> 4096 mnt
<DIR> 4096 run
<DIR> 4096 tmp
<DIR> 4096 var
Marvell>> ls mmc 0:1 /gnu/store
invalid extent block
A quick google search doesn't uncover anyone who's hit this issue either.
Checking the error message again, the stated length of the image
(4007447747) is incorrect. For a gzip
'd file, this length should
come from the last 4 bytes of the image. disk-image.gz
correctly
ends in 0x68e34000
, but u-boot
is showing 0xeedcccc3
.
Checking the source, the length in the gzwrite
command is parsed
using simple_strtoul(argv[4], NULL, 16)
(i.e. base 16). Fixing that:
Marvell>> gzwrite mmc 0 0x5400000 0x17dc4ab8
1758461952/1759723520
uncompressed 1759726190 of 1759723520
crcs == 0x5226e262/0x0b1fff17
Marvell>> ls mmc 0:1 /gnu/store
invalid extent block
The length is correct now, but it still didn't decompress/flash the whole image. It's possible this is some odd transient error in the eMMC writes. I'm going to power cycle and try again:
Marvell>> usb start
starting USB...
USB0: Register 2000104 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB1: USB EHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning usb for storage devices... 1 Storage Device(s) found
Marvell>> load usb 0:1 0x5400000 disk-image.gz
400313016 bytes read in 10034 ms (38 MiB/s)
Marvell>> gzwrite mmc 0 0x5400000 0x17dc4ab8
1758461952/1759723520
1759723520 bytes, crc 0x5226e262
Marvell>> ls mmc 0:1 /gnu/store
<DIR> 24576 .
<DIR> 4096 ..
<DIR> 4096 05wh5f68g081ghzfyraa2a3s18a915b5-libxdmcp-1.1.3
1053 06blr7hwq5hhj045rw7r1z97rc94p1s4-shepherd-host-name.scm
<DIR> 4096 06v7rs8h8i86zzkpa89byx039w20g1i1-tar-1.34
...
Awesome! Let's try booting the new image:
Marvell>> sysboot mmc 0:1 any 0x5400000 /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
822 bytes read in 15 ms (52.7 KiB/s)
Ignoring unknown command: UI
GNU Guix Boot Options
1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Enter choice: 1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Retrieving file: /gnu/store/...-raw-initrd/initrd.cpio.gz
13341025 bytes read in 2108 ms (6 MiB/s)
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/Image
18061824 bytes read in 16751 ms (1 MiB/s)
append: root=38af4c98-70f0-62ac-b285-334638af4c98 \
gnu.system=/gnu/store/...-system \
gnu.load=/gnu/store/...-system/boot \
console=ttyMV0,115200 \
earlycon=ar3700_uart,0xd0012000 \
modprobe.blacklist=usbmouse,usbkbd quiet
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/ \
lib/dtbs/mvebu-mvebu_armada-37xx.dtb
** File not found /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/ \
lib/dtbs/mvebu-mvebu_armada-37xx.dtb **
Skipping GNU with Linux-Espressobin-Ultra 5.4.53-gti for failure retrieving fdt
As expected, setting FDTDIR
isn't enough for u-boot
. But now I can
see what it's actually doing: if fdtfile
isn't in the environment,
u-boot
defaults to ${soc}-${board}.dtb
. Let's just set fdtfile
so it can find the device tree correctly:
Marvell>> setenv fdtfile marvell/armada-3720-ccpe.dtb
Marvell>> sysboot mmc 0:1 any 0x5400000 /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
822 bytes read in 16 ms (49.8 KiB/s)
Ignoring unknown command: UI
GNU Guix Boot Options
1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Enter choice: 1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Retrieving file: /gnu/store/...-raw-initrd/initrd.cpio.gz
13341025 bytes read in 2108 ms (6 MiB/s)
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/Image
18061824 bytes read in 16752 ms (1 MiB/s)
append: root=38af4c98-70f0-62ac-b285-334638af4c98 \
gnu.system=/gnu/store/...-system \
gnu.load=/gnu/store/...-system/boot \
console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 \
modprobe.blacklist=usbmouse,usbkbd quiet
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/ \
lib/dtbs/marvell/armada-3720-ccpe.dtb
12427 bytes read in 1695 ms (6.8 KiB/s)
## Flattened Device Tree blob at 06f00000
Booting using the fdt blob at 0x6f00000
Loading Ramdisk to 3e96e000, end 3f627161 ... OK
Using Device Tree in place at 0000000006f00000, end 0000000006f0608a
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[ 0.000000] Linux version 5.4.53-guix (guix@guix) \
(gcc version 11.3.0 (GCC)) #1 SMP PREEMPT 1
[ 0.000000] Machine model: gti cellular cpe board
[ 0.000000] earlycon: ar3700_uart0 at MMIO 0x00000000d0012000 (options '')
[ 0.000000] printk: bootconsole [ar3700_uart0] enabled
[ 0.393819] orion-mdio d0032004.mdio: IRQ index 0 not found
[ 0.689733] Kernel panic - not syncing: VFS: \
Unable to mount root fs on unknown-block(0,0)
[ 0.695396] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.4.53-guix #1
[ 0.701931] Hardware name: gti cellular cpe board (DT)
[ 0.707218] Call trace:
[ 0.709736] dump_backtrace+0x0/0x130
[ 0.713492] show_stack+0x14/0x20
[ 0.716898] dump_stack+0xb4/0x11c
[ 0.720392] panic+0x158/0x324
[ 0.723530] mount_block_root+0x1cc/0x284
[ 0.727648] mount_root+0x11c/0x150
[ 0.731232] prepare_namespace+0x15c/0x1c0
[ 0.735444] kernel_init_freeable+0x210/0x23c
[ 0.739925] kernel_init+0x10/0x100
[ 0.743509] ret_from_fork+0x10/0x24
[ 0.747186] SMP: stopping secondary CPUs
[ 0.751216] Kernel Offset: disabled
[ 0.754797] CPU features: 0x0002,2000200c
[ 0.758917] Memory Limit: none
[ 0.762061] ---[ end Kernel panic - not syncing: VFS: \
Unable to mount root fs on unknown-block(0,0) ]---
It appears to be attempting to mount the root device instead of
loading the initrd
. After reading around the code, the initrd
is
supposed to be passed to the kernel using the linux,initrd-start
and
linux,initrd-end
nodes in the device tree. u-boot
should set these
nodes automatically when using sysboot
.
Let's get some more information. After rebuilding the image with the
quiet
kernel command-line removed (full boot
log here):
[ 0.517697] Trying to unpack rootfs image as initramfs...
[ 0.523339] rootfs image is not initramfs (invalid magic at start \
of compressed archive); looks like an initrd
[ 0.567843] Freeing initrd memory: 13020K
This is interesting: my initramfs is ~13 MB, so the device tree nodes are getting set correctly. But for some reason, the magic is incorrect and the kernel doesn't know how to unpack it. Somehow, the kernel doesn't recognize the gzip header and is skipping decompression.
The magic bytes look correct on the archive in my store, so maybe the kernel is loading it wrong? After adding some debug prints to the kernel (and re-flashing):
[ 0.523092] initrd at 3e96f000 (13336045)
[ 0.527213] Compressed data magic: 0x70 0xb4
[ 0.531600] Detected (null) compressed data
Odd since hexdump /gnu/store/...-raw-initrd/initrd.cpio.gz | head -n1
shows:
0000000 8b1f 0008 0000 0000 0302 5aec 707d e51b
Which is the correct gzip header.
The astute reader may have noticed the problem already. We're loading kernel into 0x7000000 and initramfs into 0x8000000, but the kernel is 18MB—it will overwrite the first part of the initramfs.
Let's fix that:
Marvell>> setenv fdtfile marvell/armada-3720-ccpe.dtb
Marvell>> setenv ramdisk_addr_r 0x9000000
Marvell>> sysboot mmc 0:1 any 0x5400000 /boot/extlinux/extlinux.conf
Retrieving file: /boot/extlinux/extlinux.conf
790 bytes read in 15 ms (50.8 KiB/s)
Ignoring unknown command: UI
GNU Guix Boot Options
1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Enter choice: 1
1: GNU with Linux-Espressobin-Ultra 5.4.53-gti
Retrieving file: /gnu/store/...-raw-initrd/initrd.cpio.gz
13341022 bytes read in 2243 ms (5.7 MiB/s)
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/Image
18061824 bytes read in 16666 ms (1 MiB/s)
append: root=38af4c98-7edc-4925-d4b2-17f038af4c98 \
gnu.system=/gnu/store/...-system \
gnu.load=/gnu/store/...-system/boot \
console=ttyMV0,115200 modprobe.blacklist=usbmouse,usbkbd quiet
Retrieving file: /gnu/store/...-linux-espressobin-ultra-5.4.53-gti/ \
lib/dtbs/marvell/armada-3720-ccpe.dtb
12427 bytes read in 1699 ms (6.8 KiB/s)
## Flattened Device Tree blob at 06f00000
Booting using the fdt blob at 0x6f00000
Loading Ramdisk to 3e96e000, end 3f62715e ... OK
Using Device Tree in place at 0000000006f00000, end 0000000006f0608a
Starting kernel ...
[ 1.045516] orion-mdio d0032004.mdio: IRQ index 0 not found
GC Warning: pthread_getattr_np or pthread_attr_getstack failed for main thread
GC Warning: Could not open /proc/stat
Welcome, this is GNU's early boot Guile.
Use 'gnu.repl' for an initrd REPL.
loading kernel modules...
Guix_image: clean, 44113/107520 files, 364895/429342 blocks
loading '/gnu/store/...-system/boot'...
making '/gnu/store/...-system' the current system...
setting up setuid programs in '/run/setuid-programs'...
populating /etc from /gnu/store/...-etc...
[ 2.852542] sd 1:0:0:0: [sda] No Caching mode page found
[ 2.855506] sd 1:0:0:0: [sda] Assuming drive cache: write through
Please wait while gathering entropy to generate the key pair;
this may take time...
[ 7.615962] udevd[134]: no sender credentials received, message ignored
This is the GNU system. Welcome.
ebinx login:
Success!
Two more things to fix:
Use the full disk for the rootfs.
Make the boot changes permanent.
Let's start by building a new image:
$ guix system image --target=aarch64-linux-gnu ebinx.scm --image-size=7818182656
And then trying to flash:
...
Marvell>> gzwrite mmc 0 0x5400000 1868327C
MMC: block number 0xe90800 exceeds max(0xe90000)
uncompressed 7819231232 of 3524263936
crcs == 0xe484ca13/0xe484ca13
The image is a little bit too large, I probably computed the block count incorrectly. Regardless, nothing important is at the end of the image, so I'll just ignore that.
Making the changes permanent:
Marvell>> setenv fdtfile marvell/armada-3720-ccpe.dtb
Marvell>> setenv ramdisk_addr_r 0x9000000
Marvell>> setenv bootcmd sysboot mmc 0:1 any 0x5400000 /boot/extlinux/extlinux.conf
Marvell>> saveenv
Saving Environment to SPI Flash... SF: Detected mx25u3235f with \
page size 256 Bytes, erase size 64 KiB, total 4 MiB
Erasing SPI flash...Writing to SPI flash...done
OK
Then power cycle. It now boots automatically into guix
and the disk
size is correct:
root@ebinx ~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 1 14.9G 0 disk
└─sda1 8:1 1 14.9G 0 part
mtdblock0 31:0 0 3.9M 0 disk
mtdblock1 31:1 0 64K 1 disk
mtdblock2 31:2 0 64K 0 disk
mmcblk0 179:0 0 7.3G 0 disk
└─mmcblk0p1 179:1 0 7.3G 0 part /gnu/store
/
mmcblk0boot0 179:32 0 4M 1 disk
mmcblk0boot1 179:64 0 4M 1 disk