Compare commits

...

9 Commits

Author SHA1 Message Date
Daniel Barlow dbf1ecdcb7 swap zimage and dtb in ram
kernel uncompression code creates a stack directly
after the compressed payload, which was trashing the dtb
2023-12-23 15:38:32 +00:00
Daniel Barlow aecc44aaa0 run-liminix-vm: --flag parameter passes arg straight to qemu 2023-12-23 15:32:59 +00:00
Daniel Barlow 1042be912c turris omnia: switch to regular tftpboot output
now it does zimage and rootfs compression
2023-12-23 00:05:34 +00:00
Daniel Barlow c931d84828 tftproot: put command line in dtb 2023-12-23 00:05:34 +00:00
Daniel Barlow 64a3f50248 tftpboot: support compressed root 2023-12-23 00:05:34 +00:00
Daniel Barlow c5e9fcecc7 uninit var 2023-12-23 00:05:34 +00:00
Daniel Barlow f25c41b4d2 tftpboot: move things around in memory
new layout has rootfs followed by kernel and dtb, so that we
know the rootfs start and size to embed them into the dtb instead
of having to use dummy values and fill them in afterwards
2023-12-23 00:05:34 +00:00
Daniel Barlow bfa68d9c55 remove unused variable 2023-12-23 00:05:34 +00:00
Daniel Barlow ff0ef825a6 tftpboot: add option for kernel image format 2023-12-23 00:05:34 +00:00
5 changed files with 102 additions and 141 deletions

View File

@ -11,14 +11,15 @@
};
module = {pkgs, config, lib, lim, ... }:
let openwrt = pkgs.openwrt; in {
imports = [
../../modules/arch/arm.nix
../../modules/outputs/tftpbootlz.nix
../../modules/outputs/ext4fs.nix
../../modules/outputs/mbrimage.nix
../../modules/outputs/extlinux.nix
];
let openwrt = pkgs.openwrt;
in {
imports = [
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/ext4fs.nix
../../modules/outputs/mbrimage.nix
../../modules/outputs/extlinux.nix
];
kernel = {
src = pkgs.pkgsBuildBuild.fetchurl {
name = "linux.tar.gz";
@ -116,7 +117,11 @@
};
};
boot.tftp.loadAddress = lim.parseInt "0x1000000";
boot.tftp = {
loadAddress = lim.parseInt "0x1000000";
kernelFormat = "zimage";
compressRoot = true;
};
hardware = let
mac80211 = pkgs.mac80211.override {

View File

@ -9,9 +9,19 @@ let
cfg = config.boot.tftp;
in {
imports = [ ../ramdisk.nix ];
options.boot.tftp.freeSpaceBytes = mkOption {
type = types.int;
default = 0;
options.boot.tftp = {
freeSpaceBytes = mkOption {
type = types.int;
default = 0;
};
kernelFormat = mkOption {
type = types.enum [ "zimage" "uimage" ];
default = "uimage";
};
compressRoot = mkOption {
type = types.bool;
default = false;
};
};
options.system.outputs = {
tftpboot = mkOption {
@ -44,46 +54,72 @@ in {
let
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
image = let choices = {
uimage = o.uimage;
zimage = o.zimage;
}; in choices.${cfg.kernelFormat};
bootCommand = let choices = {
uimage = "bootm";
zimage = "bootz";
}; in choices.${cfg.kernelFormat};
cmdline = concatStringsSep " " config.boot.commandLine;
in
pkgs.runCommand "tftpboot" { nativeBuildInputs = [ pkgs.pkgsBuildBuild.dtc ]; } ''
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc ]; } ''
mkdir $out
cd $out
ln -s ${o.rootfs} rootfs
ln -s ${o.kernel} vmlinux
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
hex() { printf "0x%x" $1; }
rootfsStart=${toString cfg.loadAddress}
rootfsSize=$(binsize64k ${o.rootfs} )
dtbStart=$(($rootfsStart + $rootfsSize))
dtbSize=$(binsize ${o.dtb} )
imageStart=$(($dtbStart + $dtbSize))
imageSize=$(binsize ${image})
ln -s ${o.manifest} manifest
ln -s ${o.kernel.headers} build
ln -s ${o.uimage} uimage
uimageSize=$(($(stat -L -c %s ${o.uimage}) + 0x1000 &(~0xfff)))
rootfsStart=$(printf %x $((${toString cfg.loadAddress} + 0x100000 + $uimageSize &(~0xfffff) )))
rootfsBytes=$(($(stat -L -c %s ${o.rootfs}) + 0x100000 &(~0xfffff)))
rootfsBytes=$(($rootfsBytes + ${toString cfg.freeSpaceBytes} ))
rootfsMb=$(($rootfsBytes >> 20))
cmd="mtdparts=phram0:''${rootfsMb}M(rootfs) phram.phram=phram0,0x''${rootfsStart},''${rootfsBytes},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
ln -s ${image} image
ln -s ${o.kernel} vmlinux # handy for gdb
dtbStart=$(printf %x $((${toString cfg.loadAddress} + $rootfsBytes + 0x100000 + $uimageSize )))
cat ${o.dtb} > $out/dtb
address_cells=$(fdtget $out/dtb / '#address-cells')
size_cells=$(fdtget $out/dtb / '#size-cells')
${if cfg.compressRoot
then ''
lzma -z9cv ${o.rootfs} > rootfs.lz
rootfsLzStart=$(($imageStart + $imageSize))
rootfsLzSize=$(binsize rootfs.lz)
''
else "ln -s ${o.rootfs} rootfs"
}
cat ${o.dtb} > dtb
address_cells=$(fdtget dtb / '#address-cells')
size_cells=$(fdtget dtb / '#size-cells')
if [ $address_cells -gt 1 ]; then ac_prefix=0; fi
if [ $size_cells -gt 1 ]; then sz_prefix=0; fi
fdtput -p $out/dtb /reserved-memory '#address-cells' $address_cells
fdtput -p $out/dtb /reserved-memory '#size-cells' $size_cells
fdtput -p $out/dtb /reserved-memory ranges
fdtput -p -t s $out/dtb /reserved-memory/phram-rootfs@$rootfsStart compatible phram
fdtput -p -t lx $out/dtb /reserved-memory/phram-rootfs@$rootfsStart reg $ac_prefix 0x$rootfsStart $sz_prefix $(printf %x $rootfsBytes)
fdtput -p dtb /reserved-memory '#address-cells' $address_cells
fdtput -p dtb /reserved-memory '#size-cells' $size_cells
fdtput -p dtb /reserved-memory ranges
node=$(printf "phram-rootfs@%x" $rootfsStart)
fdtput -p -t s dtb /reserved-memory/$node compatible phram
fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
# dtc -I dtb -O dts -o /dev/stdout $out/dtb | grep -A10 reserved-mem ; exit 1
dtbBytes=$(($(stat -L -c %s $out/dtb) + 0x1000 &(~0xfff)))
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s dtb /chosen bootargs "$cmd"
cat > $out/boot.scr << EOF
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
cat > boot.scr << EOF
setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr}
setenv bootargs 'liminix ${cmdline} $cmd'
tftpboot 0x${lib.toHexString cfg.loadAddress} result/uimage ; tftpboot 0x$rootfsStart result/rootfs ; tftpboot 0x$dtbStart result/dtb
bootm 0x${lib.toHexString cfg.loadAddress} - 0x$dtbStart
tftpboot $(hex $imageStart) result/image ; ${
if cfg.compressRoot
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
else "tftpboot $(hex $rootfsStart) result/rootfs"
}; tftpboot $(hex $dtbStart) result/dtb
${if cfg.compressRoot
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart)"
else ""
}
${bootCommand} $(hex $imageStart) - $(hex $dtbStart)
EOF
'';

View File

@ -1,94 +0,0 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkOption types concatStringsSep;
inherit (pkgs.lib.trivial) toHexString;
o = config.system.outputs;
cmdline = concatStringsSep " " config.boot.commandLine;
cfg = config.boot.tftp;
tftpbootlz =
pkgs.buildPackages.runCommand "tftpbootlz" {
nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc ];
} ''
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
hex() { printf "0x%x" $1; }
kernelStart=${toString cfg.loadAddress}
kernelSize=$(binsize ${o.zimage})
mkdir -p $out
cat ${o.dtb} > $out/dtb
fdtput -p -t lx $out/dtb /reserved-memory '#address-cells' 1
fdtput -t lx $out/dtb /reserved-memory '#size-cells' 1
fdtput $out/dtb /reserved-memory ranges
fdtput -p -t s $out/dtb /reserved-memory/phram-rootfs compatible phram
# can't calculate the actual address here until we know how
# big the dtb will be
fdtput -t lx $out/dtb /reserved-memory/phram-rootfs reg 0xdead 0xcafe
cmd="liminix ${cmdline} mtdparts=phram0:999999999999(rootfs) phram.phram=phram0,999999999999,999999999999,${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s $out/dtb /chosen bootargs "$cmd"
dtbStart=$(($kernelStart + $kernelSize))
dtbSize=$(binsize $out/dtb)
rootfsOrigSize=$(binsize64k ${o.rootfs})
lzma -z9cv ${o.rootfs} > $out/rootfs.lz
rootfsLzSize=$(binsize $out/rootfs.lz)
rootfsLzStart=$(($dtbStart + $dtbSize))
rootfsOrigStart=$(($rootfsLzStart + $rootfsLzSize))
fdtput -t lx $out/dtb /reserved-memory/phram-rootfs reg $(printf "%x" $rootfsOrigStart) $(printf "%x" $rootfsOrigSize)
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsOrigSize}(rootfs) phram.phram=phram0,''${rootfsOrigStart},''${rootfsOrigSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
fdtput -t s $out/dtb /chosen bootargs "$cmd"
# dtc -I dtb -O dts -o /dev/stdout $out/dtb | grep -A10 reserved-memory; exit 1
(cd $out;
ln -s ${o.zimage} zImage
ln -s ${o.manifest} manifest
ln -s ${o.kernel.headers} build)
cat > $out/boot.scr << EOF
setenv serverip ${cfg.serverip}
setenv ipaddr ${cfg.ipaddr}
tftpboot $(hex $kernelStart) result/zImage; tftpboot $(hex $dtbStart) result/dtb ; tftpboot $(hex $rootfsLzStart) result/rootfs.lz
lzmadec $(hex $rootfsLzStart) $(hex $rootfsOrigStart)
bootz $(hex $kernelStart) - $(hex $dtbStart)
EOF
'';
in {
imports = [ ../ramdisk.nix ];
options.boot.tftp.freeSpaceBytes = mkOption {
type = types.int;
default = 0;
};
options.system.outputs = {
tftpbootlz = mkOption {
type = types.package;
description = ''
tftpbootlz
**********
This is a variant of the tftpboot output intended for the
Turris Omnia. It uses a zImage instead of a uimage, as a
workaround for an awkwardly low CONFIG_SYS_BOOTM_LEN setting
in the U-Boot build for the device which means it won't boot
uimages unless they're teeny tiny.
As a bonus, it also uses lzma compression on the rootfs,
which reduces a 20MB ext4 image to around 4MB
'';
};
};
config = {
boot.ramdisk.enable = true;
system.outputs = {
inherit tftpbootlz;
};
};
}

View File

@ -44,8 +44,10 @@
["--lan" spec & rest] (assoc (parse-args rest) :lan spec)
["--wan" spec & rest] (assoc (parse-args rest) :wan spec)
["--command-line" cmd & rest] (assoc (parse-args rest) :command-line cmd)
["--flag" flag & rest] (let [o (parse-args rest)]
(assoc o :flags (doto o.flags (table.insert flag))))
[kernel rootfsimg]
{ :kernel kernel :rootfs (pad-file rootfsimg (* 16 1024)) }
{ :flags [] :kernel kernel :rootfs (pad-file rootfsimg (* 16 1024)) }
))
(fn pad-u-boot [options]
@ -114,6 +116,7 @@
(-> []
(appendm (. bin options.arch))
(appendm ["-echr" "16"])
(appendm options.flags)
(appendm (if options.phram-address
[
"-m" "272"

View File

@ -1,10 +1,13 @@
{
liminix
}:
let check = deviceName : ubootName :
let check = deviceName : ubootName : config :
let derivation = (import liminix {
device = import "${liminix}/devices/${deviceName}/";
liminix-config = ./configuration.nix;
liminix-config = { pkgs, ... } : {
imports = [./configuration.nix];
inherit config;
};
});
img = derivation.outputs.tftpboot;
uboot = derivation.pkgs.${ubootName};
@ -19,18 +22,26 @@ in pkgsBuild.runCommand "check" {
mkdir vm
ln -s ${img} result
touch empty empty2
run-liminix-vm \
--background ./vm \
--u-boot ${uboot}/u-boot.bin \
--arch ${derivation.pkgs.stdenv.hostPlatform.qemuArch} \
--wan "user,tftp=`pwd`" \
--disk-image result/rootfs \
result/uimage result/rootfs
--disk-image empty2 \
empty empty2
expect ${./script.expect} 2>&1 |tee $out
'';
in {
aarch64 = check "qemu-aarch64" "ubootQemuAarch64";
arm = check "qemu-armv7l" "ubootQemuArm";
mips = check "qemu" "ubootQemuMips";
aarch64 = check "qemu-aarch64" "ubootQemuAarch64" {};
arm = check "qemu-armv7l" "ubootQemuArm" {};
armZimage = check "qemu-armv7l" "ubootQemuArm" {
boot.tftp.kernelFormat = "zimage";
};
mips = check "qemu" "ubootQemuMips" {};
mipsLz = check "qemu" "ubootQemuMips" {
boot.tftp.compressRoot = true;
};
}