diff --git a/modules/outputs/tftpbootlz.nix b/modules/outputs/tftpbootlz.nix index 12fc997..d8fb449 100644 --- a/modules/outputs/tftpbootlz.nix +++ b/modules/outputs/tftpbootlz.nix @@ -10,34 +10,52 @@ let o = config.system.outputs; cmdline = concatStringsSep " " config.boot.commandLine; cfg = config.boot.tftp; - boot-scr = - pkgs.buildPackages.runCommand "boot-scr" { nativeBuildInputs = [ pkgs.pkgsBuildBuild.dtc ]; } '' - uimageSize=$(($(stat -L -c %s ${o.zimage}) + 0x1000 &(~0xfff))) - rootfsStart=0x$(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,''${rootfsStart},''${rootfsBytes},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0"; + 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; } - dtbStart=$(printf %x $((${toString cfg.loadAddress} + $rootfsBytes + 0x100000 + $uimageSize ))) - - mkdir $out + 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 - fdtput -p -t lx $out/dtb /reserved-memory/phram-rootfs reg 0 $rootfsStart 0 $(printf %x $rootfsBytes) + # 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 + dtbStart=$(($kernelStart + $kernelSize)) + dtbSize=$(binsize $out/dtb) + rootfsOrigSize=$(binsize64k ${o.rootfs}) + lzma -z9cv ${o.rootfs} > $out/rootfs.lz - dtbBytes=$(($(stat -L -c %s $out/dtb) + 0x1000 &(~0xfff))) + 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) + # dtc -I dtb -O dts -o /dev/stdout $out/dtb ; exit 1 - cat > $out/script << EOF + cmd="mtdparts=phram0:''${rootfsOrigSize}(rootfs) phram.phram=phram0,''${rootfsOrigStart},''${rootfsOrigSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0"; + + (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} - setenv bootargs 'liminix ${cmdline} $cmd' - tftpboot 0x${lib.toHexString cfg.loadAddress} result/zImage; tftpboot 0x$(printf %x $rootfsStart) result/rootfs ; tftpboot 0x$dtbStart result/dtb - setexpr bootaddr 0x$dtbStart + \$filesize - # lzmadec 0x${lib.toHexString cfg.loadAddress} \$bootaddr - # bootz \$bootaddr - 0x$dtbStart - bootz 0x${lib.toHexString cfg.loadAddress} - 0x$dtbStart + setenv bootargs "liminix ${cmdline} $cmd" + 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 ]; @@ -53,35 +71,20 @@ in { ********** This is a variant of the tftpboot output intended for the - Turris Omnia. It builds a uimage containing an uncompressed - kernel, then compresses the resulting image to be decompressed - using the u-boot lzmadec command. This is a workaround for an - awkwardly low CONFIG_SYS_BOOTM_LEN setting in the U-Boot build - for the device, which means that the regular tftpboot output - would only work for very small kernels. + 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 = { - tftpbootlz = - let - o = config.system.outputs; in - pkgs.runCommand "tftpboot" { - depsBuildBuild = [ pkgs.pkgsBuildBuild.lzma ]; - } '' - mkdir $out - cd $out - ln -s ${o.rootfs} rootfs - ln -s ${o.zimage} zImage - ln -s ${o.manifest} manifest - ln -s ${o.kernel.headers} build - # lzma -c -z -9 < {uimage} > uimage.lz - ln -s ${boot-scr}/dtb dtb - ln -s ${boot-scr}/script boot.scr - ''; + inherit tftpbootlz; }; }; }