From dd8c8edd9cedf0fa792a28ee4f4c46e0874ea2d0 Mon Sep 17 00:00:00 2001
From: Daniel Barlow <dan@telent.net>
Date: Sat, 11 Feb 2023 13:10:38 +0000
Subject: [PATCH] rewrite phram boot to use correct sizes and offsets

---
 default.nix                      |  2 --
 devices/gl-ar750/default.nix     |  8 +++--
 devices/gl-mt300a/default.nix    |  2 +-
 devices/gl-mt300n-v2/default.nix |  2 +-
 devices/qemu/default.nix         |  2 +-
 modules/outputs.nix              | 25 ++--------------
 modules/phram.nix                | 50 +++++++++++++++++++++++++++++++-
 vanilla-configuration.nix        |  3 ++
 8 files changed, 64 insertions(+), 30 deletions(-)

diff --git a/default.nix b/default.nix
index 841aa45f6..26b326f91 100644
--- a/default.nix
+++ b/default.nix
@@ -1,7 +1,6 @@
 {
   device
 , liminix-config ? <liminix-config>
-, phram ? false
 , nixpkgs ? <nixpkgs>
 }:
 
@@ -18,7 +17,6 @@ let
     liminix-config
     ./modules/s6
     ./modules/users.nix
-    (if phram then  ./modules/phram.nix else (args: {}))
     ./modules/outputs.nix
   ] pkgs;
 
diff --git a/devices/gl-ar750/default.nix b/devices/gl-ar750/default.nix
index 6ef1cddb0..262ead130 100644
--- a/devices/gl-ar750/default.nix
+++ b/devices/gl-ar750/default.nix
@@ -35,11 +35,15 @@
       };
     in {
       device = {
-        defaultOutput = "directory";
+        defaultOutput = "tftproot";
         loadAddress = "0x80060000";
         entryPoint  = "0x80060000";
       };
-
+      boot.tftp = {
+        loadAddress = "0x00A00000";
+        serverip = "192.168.8.148";
+        ipaddr = "192.168.8.251";
+      };
       kernel = {
         src = pkgs.pkgsBuildBuild.fetchurl {
           name = "linux.tar.gz";
diff --git a/devices/gl-mt300a/default.nix b/devices/gl-mt300a/default.nix
index 9dd0b5e23..61ac10f6c 100644
--- a/devices/gl-mt300a/default.nix
+++ b/devices/gl-mt300a/default.nix
@@ -22,7 +22,7 @@
       };
     in {
       device = {
-        defaultOutput = "directory";
+        defaultOutput = "tftproot";
         loadAddress = "0x80000000";
         entryPoint  = "0x80000000";
       };
diff --git a/devices/gl-mt300n-v2/default.nix b/devices/gl-mt300n-v2/default.nix
index 44a2e9b2b..5b907a09c 100644
--- a/devices/gl-mt300n-v2/default.nix
+++ b/devices/gl-mt300n-v2/default.nix
@@ -22,7 +22,7 @@
       };
     in {
       device = {
-        defaultOutput = "directory";
+        defaultOutput = "tftproot";
         loadAddress = "0x80000000";
         entryPoint  = "0x80000000";
       };
diff --git a/devices/qemu/default.nix b/devices/qemu/default.nix
index e616910fe..d6dd3c003 100644
--- a/devices/qemu/default.nix
+++ b/devices/qemu/default.nix
@@ -41,6 +41,6 @@
         SERIAL_8250_CONSOLE= "y";
       };
     };
-    device.defaultOutput = "directory";
+    device.defaultOutput = "vmroot";
   };
 }
diff --git a/modules/outputs.nix b/modules/outputs.nix
index 2cd92cb31..85fcc5ff3 100644
--- a/modules/outputs.nix
+++ b/modules/outputs.nix
@@ -41,35 +41,16 @@ in
         dd if=${uimage} of=$out/firmware.bin bs=128k conv=sync
         dd if=${squashfs} of=$out/firmware.bin bs=128k conv=sync,nocreat,notrunc oflag=append
       '';
-      boot-scr =
-        let
-          inherit (pkgs.lib.trivial) toHexString;
-          uimageStart = 10485760; # 0xa00000
-          squashfsStart = uimageStart + 4 * 1024 * 1024;
-          squashfsSize = 8;
-          cmd = "mtdparts=phram0:${toString squashfsSize}M(nix) phram.phram=phram0,0x${toHexString squashfsStart},${toString squashfsSize}Mi memmap=${toString squashfsSize}M\$0x${toHexString squashfsStart} root=1f00";
-        in
-          pkgs.buildPackages.writeScript "firmware.bin" ''
-            setenv serverip 192.168.8.148
-            setenv ipaddr 192.168.8.251
-            setenv bootargs '${concatStringsSep " " config.boot.commandLine} ${cmd}'
-            tftp 0x8${toHexString uimageStart} result/uimage ; tftp 0x8${toHexString squashfsStart} result/squashfs
-            bootm 0x${toHexString uimageStart}
-          '';
 
-      directory = pkgs.runCommand "liminix" {} (''
+      vmroot = pkgs.runCommand "qemu" {} ''
         mkdir $out
         cd $out
         ln -s ${squashfs} squashfs
         ln -s ${kernel} vmlinux
         ln -s ${manifest} manifest
         ln -s ${kernel.headers} build
-      '' +
-        (if config.device.loadAddress != null  then
-          ''
-            ln -s ${uimage} uimage
-            ln -s ${boot-scr} flash.scr
-          '' else ""));
+      '';
+
       # this exists so that you can run "nix-store -q --tree" on it and find
       # out what's in the image, which is nice if it's unexpectedly huge
       manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents);
diff --git a/modules/phram.nix b/modules/phram.nix
index e98f22789..3cf8060a5 100644
--- a/modules/phram.nix
+++ b/modules/phram.nix
@@ -1,8 +1,24 @@
 {
   config
+, pkgs
+, lib
 , ...
 }:
-{
+let
+  inherit (lib) mkOption types concatStringsSep;
+  cfg = config.boot.tftp;
+in {
+  options = {
+    boot = {
+      tftp = {
+        loadAddress = mkOption { type = types.str; };
+        # These names match the uboot environment variables. I reserve
+        # the right to change them if I think of better ones.
+        ipaddr =  mkOption { type = types.str; };
+        serverip =  mkOption { type = types.str; };
+      };
+    };
+  };
   config = {
     kernel = {
       config = {
@@ -25,5 +41,37 @@
       };
 
     };
+    outputs.tftproot =
+      let o = config.outputs; in
+      pkgs.runCommand "tftproot" {} ''
+        mkdir $out
+        cd $out
+        ln -s ${o.squashfs} squashfs
+        ln -s ${o.kernel} vmlinux
+        ln -s ${o.manifest} manifest
+        ln -s ${o.kernel.headers} build
+        ln -s ${o.uimage} uimage
+        ln -s ${o.boot-scr} flash.scr
+     '';
+
+    outputs.boot-scr =
+      let
+        inherit (pkgs.lib.trivial) toHexString;
+      in
+        pkgs.buildPackages.runCommand "" {} ''
+          uimageSize=$(($(stat -L -c %s ${config.outputs.uimage}) + 0x1000 &(~0xfff)))
+          squashfsStart=0x$(printf %x $((${cfg.loadAddress} + $uimageSize)))
+          squashfsBytes=$(($(stat -L -c %s ${config.outputs.squashfs}) + 0x100000 &(~0xfffff)))
+          squashfsMb=$(($squashfsBytes >> 20))
+          cmd="mtdparts=phram0:''${squashfsMb}M(nix) phram.phram=phram0,''${squashfsStart},''${squashfsMb}Mi memmap=''${squashfsMb}M\$''${squashfsStart} root=1f00";
+          cat > $out << EOF
+          setenv serverip ${cfg.serverip}
+          setenv ipaddr ${cfg.ipaddr}
+          setenv bootargs '${concatStringsSep " " config.boot.commandLine} $cmd'
+          tftp 0x$(printf %x ${cfg.loadAddress}) result/uimage ; tftp 0x$(printf %x $squashfsStart) result/squashfs
+          bootm 0x$(printf %x ${cfg.loadAddress})
+          EOF
+        '';
+
   };
 }
diff --git a/vanilla-configuration.nix b/vanilla-configuration.nix
index 9eab4a2cb..e42baeceb 100644
--- a/vanilla-configuration.nix
+++ b/vanilla-configuration.nix
@@ -3,6 +3,9 @@ let
   inherit (pkgs.liminix.networking) interface address udhcpc odhcpc route;
   inherit (pkgs.liminix.services) oneshot longrun bundle target;
 in rec {
+  imports = [
+    ./modules/phram.nix
+  ];
   services.loopback =
     let iface = interface { type = "loopback"; device = "lo";};
     in bundle {