liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

tftpboot.nix (4633B)


      1 {
      2   config
      3 , pkgs
      4 , lib
      5 , ...
      6 }:
      7 let
      8   inherit (lib) mkOption types concatStringsSep;
      9   cfg = config.boot.tftp;
     10 in {
     11   imports = [ ../ramdisk.nix ];
     12   options.boot.tftp = {
     13     freeSpaceBytes = mkOption {
     14       type = types.int;
     15       default = 0;
     16     };
     17     kernelFormat = mkOption {
     18       type = types.enum [ "zimage" "uimage" ];
     19       default = "uimage";
     20     };
     21     compressRoot = mkOption {
     22       type = types.bool;
     23       default = false;
     24     };
     25   };
     26   options.system.outputs = {
     27     tftpboot = mkOption {
     28       type = types.package;
     29       description = ''
     30         tftpboot
     31         ********
     32 
     33         This output is intended for developing on a new device.
     34         It assumes you have a serial connection and a
     35         network connection to the device and that your
     36         build machine is running a TFTP server.
     37 
     38         The output is a directory containing kernel and
     39         root filesystem image, and a script :file:`boot.scr` of U-Boot
     40         commands that will load the images into memory and
     41         run them directly,
     42         instead of first writing them to flash. This saves
     43         time and erase cycles.
     44 
     45         It uses the Linux `phram <https://github.com/torvalds/linux/blob/master/drivers/mtd/devices/phram.c>`_ driver to emulate a flash device using a segment of physical RAM.
     46       '';
     47     };
     48   };
     49   config = {
     50     boot.ramdisk.enable = true;
     51 
     52     system.outputs = rec {
     53       tftpboot =
     54         let
     55           inherit (pkgs.lib.trivial) toHexString;
     56           o = config.system.outputs;
     57           image = let choices = {
     58             uimage = o.uimage;
     59             zimage = o.zimage;
     60           }; in choices.${cfg.kernelFormat};
     61           bootCommand = let choices = {
     62             uimage = "bootm";
     63             zimage = "bootz";
     64           }; in choices.${cfg.kernelFormat};
     65           cmdline = concatStringsSep " " config.boot.commandLine;
     66         in
     67           pkgs.runCommand "tftpboot" { nativeBuildInputs = with pkgs.pkgsBuildBuild; [ lzma dtc ];  } ''
     68             mkdir $out
     69             cd $out
     70             binsize() { local s=$(stat -L -c %s $1); echo $(($s + 0x1000 &(~0xfff))); }
     71             binsize64k() { local s=$(stat -L -c %s $1); echo $(($s + 0x10000 &(~0xffff))); }
     72             hex() { printf "0x%x" $1; }
     73             rootfsStart=${toString cfg.loadAddress}
     74             rootfsSize=$(binsize64k ${o.rootfs} )
     75             dtbStart=$(($rootfsStart + $rootfsSize))
     76             dtbSize=$(binsize ${o.dtb} )
     77             imageStart=$(($dtbStart + $dtbSize))
     78             imageSize=$(binsize ${image})
     79 
     80             ln -s ${o.manifest} manifest
     81             ln -s ${image} image
     82             ln -s ${o.kernel} vmlinux  # handy for gdb
     83 
     84             ${if cfg.compressRoot
     85               then ''
     86                 lzma -z9cv ${o.rootfs} > rootfs.lz
     87                 rootfsLzStart=$(($imageStart + $imageSize))
     88                 rootfsLzSize=$(binsize rootfs.lz)
     89               ''
     90               else "ln -s ${o.rootfs} rootfs"
     91              }
     92             cat ${o.dtb} > dtb
     93             address_cells=$(fdtget dtb / '#address-cells')
     94             size_cells=$(fdtget dtb / '#size-cells')
     95             if [ $address_cells -gt 1 ]; then ac_prefix=0; fi
     96             if [ $size_cells -gt 1 ]; then sz_prefix=0; fi
     97 
     98             fdtput -p dtb /reserved-memory '#address-cells' $address_cells
     99             fdtput -p dtb /reserved-memory '#size-cells' $size_cells
    100             fdtput -p dtb /reserved-memory ranges
    101             node=$(printf "phram-rootfs@%x" $rootfsStart)
    102             fdtput -p -t s dtb /reserved-memory/$node compatible phram
    103             fdtput -p -t lx dtb /reserved-memory/$node reg $ac_prefix $(hex $rootfsStart) $sz_prefix $(hex $rootfsSize)
    104 
    105             cmd="liminix ${cmdline} mtdparts=phram0:''${rootfsSize}(rootfs) phram.phram=phram0,''${rootfsStart},''${rootfsSize},${toString config.hardware.flash.eraseBlockSize} root=/dev/mtdblock0";
    106             fdtput -t s dtb /chosen bootargs "$cmd"
    107 
    108             # dtc -I dtb -O dts -o /dev/stdout dtb | grep -A10 chosen ; exit 1
    109 
    110             cat > boot.scr << EOF
    111             setenv serverip ${cfg.serverip}
    112             setenv ipaddr ${cfg.ipaddr}
    113             tftpboot $(hex $imageStart) result/image ; ${
    114               if cfg.compressRoot
    115               then "tftpboot $(hex $rootfsLzStart) result/rootfs.lz"
    116               else "tftpboot $(hex $rootfsStart) result/rootfs"
    117             }; tftpboot $(hex $dtbStart) result/dtb
    118             ${if cfg.compressRoot
    119               then "lzmadec $(hex $rootfsLzStart)  $(hex $rootfsStart); "
    120               else ""
    121              } ${bootCommand} $(hex $imageStart) - $(hex $dtbStart)
    122             EOF
    123          '';
    124 
    125     };
    126   };
    127 }