Files
ssmithxandClaude Opus 5.5 36b1464a18 MT6000: Guix boots from eMMC with Ethernet and WiFi
Four board fixes, in mt7986a-glinet-gl-mt6000-guix.dtsi (appended to
OpenWrt's DTS, replacing the FIT script's fdtput edits) and the system:

- secmon: GL's BL31 uses 256 KiB, not mainline's 192 KiB.
- WED off and mainline's wo-ilm/wo-dlm/wo-boot no-map regions removed:
  with them the kernel resets within seconds under GL's firmware.
- eMMC partitions in mainline's binding (gpt-partitions under card@0):
  OpenWrt's card@0/block/partitions isn't read by 6.13+, so `factory'
  had no NVMEM cells -- no WiFi calibration, and mtk_eth_soc deferred
  forever for its MAC address.
- clk_ignore_unused: mtk_eth_soc, a module, loads after unused clocks
  are turned off, and its MDIO bus timed out.

ramoops is built in, with a console record, so a failed boot's kernel
log survives a warm reset.  docs/PITFALLS.md #49-#52: these, GL U-Boot's
TFTP recovery, and the image system's root UUID.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:02:03 -04:00

115 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build the FIT image GL.iNet's U-Boot boots from the GL-MT6000's `kernel'
# partition (p6, 32 MiB), for one Guix system generation:
# kernel-1 the system's Image, LZMA-compressed, loaded at 0x48000000
# fdt-1 mt7986a-glinet-gl-mt6000.dtb with the Guix command line in
# /chosen/bootargs-append (GL's U-Boot passes empty bootargs;
# linux-mt6000 carries OpenWrt's bootargs-append patch)
# initrd-1 the system's initrd
# Same layout as OpenWrt's MT6000 FIT (kernel-1, fdt-1, config-1), plus the
# ramdisk OpenWrt's initramfs image also carries.
#
# Usage: scripts/mt6000-fit.sh /gnu/store/...-system OUTPUT.itb
set -euo pipefail
sys=${1:?usage: $0 SYSTEM OUTPUT.itb}
out=$(realpath -m "${2:?usage: $0 SYSTEM OUTPUT.itb}")
limit=$((32 * 1024 * 1024))
export PATH=$HOME/.local/bin:$PATH
# The package's main output: name-version, no -static/-doc suffix.
tool() { guix build "$1" 2>/dev/null | grep -E -- "-$1-[0-9][^-]*\$"; }
mkimage=$(tool u-boot-tools)/bin/mkimage
dtc=$(tool dtc)/bin
fdtput=$dtc/fdtput
xz=$(tool xz)/bin/xz
params=$(cat "$sys/parameters")
# root=LABEL or root=UUID, as Guix's bootloader configurations do. (`guix
# system image' gives the image's system its root partition's UUID.)
root=$(sed -n 's/.*(root-device (file-system-label "\([^"]*\)")).*/\1/p' <<<"$params")
if [ -z "$root" ]; then
bytes=$(sed -n 's/.*(root-device (uuid [a-z0-9]* #vu8(\([0-9 ]*\)))).*/\1/p' <<<"$params")
[ -n "$bytes" ] || { echo "$0: no label or UUID root in $sys/parameters" >&2; exit 1; }
hex=$(printf '%02x' $bytes)
root=${hex:0:8}-${hex:8:4}-${hex:12:4}-${hex:16:4}-${hex:20:12}
fi
kargs=$(sed -n 's/.*(kernel-arguments (\([^)]*\))).*/\1/p' <<<"$params" | tr -d '"')
cmdline="root=$root gnu.system=$sys gnu.load=$sys/boot $kargs"
kernel=$(readlink -f "$sys/kernel")
initrd=$(readlink -f "$sys/initrd")
dtb=$kernel/lib/dtbs/mediatek/mt7986a-glinet-gl-mt6000.dtb
[ -f "$dtb" ] || { echo "$0: $dtb missing" >&2; exit 1; }
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
"$xz" --format=lzma -9 -c "$kernel/Image" > "$work/Image.lzma"
cp "$dtb" "$work/board.dtb"
chmod u+w "$work/board.dtb"
# Leading space: appended to whatever U-Boot passes (nothing, here).
"$fdtput" -t s "$work/board.dtb" /chosen bootargs-append " $cmdline"
# (Board fixes for GL's firmware and this kernel: in the DTB, from
# mt7986a-glinet-gl-mt6000-guix.dtsi.)
cp "$initrd" "$work/initrd"
cat > "$work/image.its" <<EOF
/dts-v1/;
/ {
description = "Guix System for the GL-MT6000";
#address-cells = <1>;
images {
kernel-1 {
description = "Linux ($(basename "$kernel"))";
data = /incbin/("Image.lzma");
type = "kernel";
arch = "arm64";
os = "linux";
compression = "lzma";
load = <0x48000000>;
entry = <0x48000000>;
hash-1 { algo = "crc32"; };
hash-2 { algo = "sha1"; };
};
fdt-1 {
description = "mt7986a-glinet-gl-mt6000";
data = /incbin/("board.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
hash-1 { algo = "crc32"; };
};
initrd-1 {
description = "Guix initrd";
data = /incbin/("initrd");
type = "ramdisk";
arch = "arm64";
os = "linux";
compression = "none";
hash-1 { algo = "crc32"; };
};
};
configurations {
default = "config-1";
config-1 {
description = "$(basename "$sys")";
kernel = "kernel-1";
fdt = "fdt-1";
ramdisk = "initrd-1";
};
};
};
EOF
# mkimage runs dtc; /incbin paths are relative to the work directory.
(cd "$work" && PATH=$dtc:$PATH "$mkimage" -f image.its "$out" >/dev/null)
size=$(stat -c %s "$out")
if [ "$size" -gt "$limit" ]; then
echo "$0: $out is $size bytes, over the 32 MiB kernel partition" >&2
exit 1
fi
echo "$out: $size bytes; command line: $cmdline"