make tftpboot work on devices with old u-boot
Some devices have a U-boot variant that does not accept a third parameter on the "bootm" command, meaning we can't override the dtb in the bootloader so have to smush it back into the kernel image This doesn't work in QEMU but I think the problem is with the U-Boot configuration for QEMU. It does work on at least one hardware device so I'm pushing it anyway Based on https://gti.telent.net/raboof/liminix/src/branch/tftp-old-uboot Co-authored-by: Arnout Engelen <arnout@bzzt.net>
This commit is contained in:
parent
7e7171556f
commit
c373152673
2 changed files with 61 additions and 20 deletions
|
@ -7,6 +7,8 @@
|
||||||
let
|
let
|
||||||
inherit (lib) mkOption types concatStringsSep;
|
inherit (lib) mkOption types concatStringsSep;
|
||||||
cfg = config.boot.tftp;
|
cfg = config.boot.tftp;
|
||||||
|
hw = config.hardware;
|
||||||
|
arch = pkgs.stdenv.hostPlatform.linuxArch;
|
||||||
in {
|
in {
|
||||||
imports = [ ../ramdisk.nix ];
|
imports = [ ../ramdisk.nix ];
|
||||||
options.boot.tftp = {
|
options.boot.tftp = {
|
||||||
|
@ -22,6 +24,10 @@ in {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
};
|
};
|
||||||
|
appendDTB = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
options.system.outputs = {
|
options.system.outputs = {
|
||||||
tftpboot = mkOption {
|
tftpboot = mkOption {
|
||||||
|
@ -62,24 +68,46 @@ in {
|
||||||
uimage = "bootm";
|
uimage = "bootm";
|
||||||
zimage = "bootz";
|
zimage = "bootz";
|
||||||
}; in choices.${cfg.kernelFormat};
|
}; in choices.${cfg.kernelFormat};
|
||||||
|
|
||||||
cmdline = concatStringsSep " " config.boot.commandLine;
|
cmdline = concatStringsSep " " config.boot.commandLine;
|
||||||
|
objcopy = "${pkgs.stdenv.cc.bintools.targetPrefix}objcopy";
|
||||||
|
stripAndZip = ''
|
||||||
|
${objcopy} -O binary -R .reginfo -R .notes -R .note -R .comment -R .mdebug -R .note.gnu.build-id -S vmlinux.elf vmlinux.bin
|
||||||
|
rm -f vmlinux.bin.lzma ; lzma -k -z vmlinux.bin
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc ]; } ''
|
pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc pkgs.stdenv.cc ubootTools ]; } ''
|
||||||
mkdir $out
|
mkdir $out
|
||||||
cd $out
|
cd $out
|
||||||
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
|
binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
|
||||||
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
|
binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
|
||||||
hex() { printf "0x%x" $1; }
|
hex() { printf "0x%x" $1; }
|
||||||
|
|
||||||
rootfsStart=${toString cfg.loadAddress}
|
rootfsStart=${toString cfg.loadAddress}
|
||||||
rootfsSize=$(binsize64k ${o.rootfs} )
|
rootfsSize=$(binsize64k ${o.rootfs} )
|
||||||
rootfsSize=$(($rootfsSize + ${toString cfg.freeSpaceBytes} ))
|
rootfsSize=$(($rootfsSize + ${toString cfg.freeSpaceBytes} ))
|
||||||
dtbStart=$(($rootfsStart + $rootfsSize))
|
|
||||||
imageSize=$(binsize ${image})
|
|
||||||
|
|
||||||
ln -s ${o.manifest} manifest
|
ln -s ${o.manifest} manifest
|
||||||
ln -s ${image} image
|
|
||||||
ln -s ${o.kernel} vmlinux # handy for gdb
|
ln -s ${o.kernel} vmlinux # handy for gdb
|
||||||
|
|
||||||
|
# if we are transferring kernel and dtb separately, the
|
||||||
|
# dtb has to precede the kernel in ram, because zimage
|
||||||
|
# decompression code will assume that any memory after the
|
||||||
|
# end of the kernel is free
|
||||||
|
|
||||||
|
dtbStart=$(($rootfsStart + $rootfsSize))
|
||||||
|
${if cfg.compressRoot
|
||||||
|
then ''
|
||||||
|
lzma -z9cv ${o.rootfs} > rootfs.lz
|
||||||
|
rootfsLzStart=$dtbStart
|
||||||
|
rootfsLzSize=$(binsize rootfs.lz)
|
||||||
|
dtbStart=$(($dtbStart + $rootfsLzSize))
|
||||||
|
''
|
||||||
|
else ''
|
||||||
|
ln -s ${o.rootfs} rootfs
|
||||||
|
''
|
||||||
|
}
|
||||||
|
|
||||||
cat ${o.dtb} > dtb
|
cat ${o.dtb} > dtb
|
||||||
address_cells=$(fdtget dtb / '#address-cells')
|
address_cells=$(fdtget dtb / '#address-cells')
|
||||||
size_cells=$(fdtget dtb / '#size-cells')
|
size_cells=$(fdtget dtb / '#size-cells')
|
||||||
|
@ -93,34 +121,40 @@ in {
|
||||||
fdtput -p -t s dtb /reserved-memory/$node compatible phram
|
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)
|
fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
|
||||||
|
|
||||||
dtbSize=$(binsize ./dtb )
|
|
||||||
imageStart=$(($dtbStart + $dtbSize))
|
|
||||||
${if cfg.compressRoot
|
|
||||||
then ''
|
|
||||||
lzma -z9cv ${o.rootfs} > rootfs.lz
|
|
||||||
rootfsLzStart=$(($imageStart + $imageSize))
|
|
||||||
rootfsLzSize=$(binsize rootfs.lz)
|
|
||||||
''
|
|
||||||
else "ln -s ${o.rootfs} rootfs"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
|
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"
|
fdtput -t s dtb /chosen bootargs "$cmd"
|
||||||
|
|
||||||
|
dtbSize=$(binsize ./dtb )
|
||||||
|
|
||||||
|
${if cfg.appendDTB then ''
|
||||||
|
imageStart=$dtbStart
|
||||||
|
# re-package image with updated dtb
|
||||||
|
cat ${o.kernel} > vmlinux.elf
|
||||||
|
${objcopy} --update-section .appended_dtb=dtb vmlinux.elf
|
||||||
|
${stripAndZip}
|
||||||
|
mkimage -A ${arch} -O linux -T kernel -C lzma -a $(hex ${toString hw.loadAddress}) -e $(hex ${toString hw.entryPoint}) -n '${lib.toUpper arch} Liminix Linux tftpboot' -d vmlinux.bin.lzma image
|
||||||
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
|
# dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
|
||||||
|
tftpcmd="tftpboot $(hex $imageStart) result/image "
|
||||||
|
bootcmd="bootm $(hex $imageStart)"
|
||||||
|
'' else ''
|
||||||
|
imageStart=$(($dtbStart + $dtbSize))
|
||||||
|
tftpcmd="tftpboot $(hex $imageStart) result/image; tftpboot $(hex $dtbStart) result/dtb "
|
||||||
|
ln -s ${image} image
|
||||||
|
bootcmd="${bootCommand} $(hex $imageStart) - $(hex $dtbStart)"
|
||||||
|
''}
|
||||||
|
|
||||||
cat > boot.scr << EOF
|
cat > boot.scr << EOF
|
||||||
setenv serverip ${cfg.serverip}
|
setenv serverip ${cfg.serverip}
|
||||||
setenv ipaddr ${cfg.ipaddr}
|
setenv ipaddr ${cfg.ipaddr}
|
||||||
tftpboot $(hex $imageStart) result/image ; ${
|
${
|
||||||
if cfg.compressRoot
|
if cfg.compressRoot
|
||||||
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
|
then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
|
||||||
else "tftpboot $(hex $rootfsStart) result/rootfs"
|
else "tftpboot $(hex $rootfsStart) result/rootfs"
|
||||||
}; tftpboot $(hex $dtbStart) result/dtb
|
}; $tftpcmd
|
||||||
${if cfg.compressRoot
|
${if cfg.compressRoot
|
||||||
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
|
then "lzmadec $(hex $rootfsLzStart) $(hex $rootfsStart); "
|
||||||
else ""
|
else ""
|
||||||
} ${bootCommand} $(hex $imageStart) - $(hex $dtbStart)
|
} $bootcmd
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ let derivation = (import liminix {
|
||||||
img = derivation.outputs.tftpboot;
|
img = derivation.outputs.tftpboot;
|
||||||
uboot = derivation.outputs.u-boot;
|
uboot = derivation.outputs.u-boot;
|
||||||
pkgsBuild = derivation.pkgs.pkgsBuildBuild;
|
pkgsBuild = derivation.pkgs.pkgsBuildBuild;
|
||||||
in pkgsBuild.runCommand "check" {
|
in pkgsBuild.runCommand "check-${deviceName}" {
|
||||||
nativeBuildInputs = with pkgsBuild; [
|
nativeBuildInputs = with pkgsBuild; [
|
||||||
expect
|
expect
|
||||||
socat
|
socat
|
||||||
|
@ -44,4 +44,11 @@ in {
|
||||||
mipsLz = check "qemu" {
|
mipsLz = check "qemu" {
|
||||||
boot.tftp.compressRoot = true;
|
boot.tftp.compressRoot = true;
|
||||||
};
|
};
|
||||||
|
# this works on real hardware but I haven't figured out how
|
||||||
|
# to make it work on qemu: it says
|
||||||
|
# "OF: fdt: No chosen node found, continuing without"
|
||||||
|
|
||||||
|
# mipsOldUboot = check "qemu" {
|
||||||
|
# boot.tftp.appendDTB = true;
|
||||||
|
# };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue