From 228c0a16688b3194e63f04f035620d79a9f8eb42 Mon Sep 17 00:00:00 2001
From: Daniel Barlow <dan@telent.net>
Date: Mon, 8 Jan 2024 18:54:49 +0000
Subject: [PATCH] pass rootOptions config as rootflags= kernel cmdline opt

---
 examples/rotuer.nix      | 1 +
 modules/base.nix         | 8 +++++++-
 pkgs/preinit/parseopts.c | 9 ++++++++-
 pkgs/preinit/preinit.c   | 2 +-
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/examples/rotuer.nix b/examples/rotuer.nix
index c7890bff..51ce22b5 100644
--- a/examples/rotuer.nix
+++ b/examples/rotuer.nix
@@ -48,6 +48,7 @@ in rec {
   ];
   hostname = "rotuer";
   rootfsType = "btrfs";
+  rootOptions = "subvol=@";
 
   services.hostap = svc.hostapd.build {
     interface = config.hardware.networkInterfaces.wlan;
diff --git a/modules/base.nix b/modules/base.nix
index 0826ce8b..c7e7b49d 100644
--- a/modules/base.nix
+++ b/modules/base.nix
@@ -47,6 +47,11 @@ in {
         "ubifs"
       ];
     };
+    rootOptions =  mkOption {
+      type = types.nullOr types.str;
+      default = null;
+    };
+
     boot = {
       commandLine = mkOption {
         type = types.listOf types.nonEmptyStr;
@@ -95,7 +100,8 @@ in {
       "root=${config.hardware.rootDevice}"
       "rootfstype=${config.rootfsType}"
       "fw_devlink=off"
-    ];
+    ] ++ lib.optional (config.rootOptions != null) "rootflags=${config.rootOptions}";
+
     users.root = {
       uid = 0; gid= 0; gecos = "Root of all evaluation";
       dir = "/home/root/";
diff --git a/pkgs/preinit/parseopts.c b/pkgs/preinit/parseopts.c
index 7dea0321..4aff14bf 100644
--- a/pkgs/preinit/parseopts.c
+++ b/pkgs/preinit/parseopts.c
@@ -95,7 +95,7 @@ int main()
     };
     char *buf;
 
-    // finds root= rootfstype= rootopts= options
+    // finds root= rootfstype= rootflags= options
     buf = strdup("liminix console=ttyS0,115200 panic=10 oops=panic init=/bin/init loglevel=8 root=/dev/ubi0_4 rootfstype=ubifs rootflags=subvol=1 fw_devlink=off mtdparts=phram0:18M(rootfs) phram.phram=phram0,0x40400000,18874368,65536 root=/dev/mtdblock0 foo");
     memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
     expect_equal(opts.device, "/dev/mtdblock0");
@@ -115,6 +115,13 @@ int main()
     expect_equal(opts.device, "/dev/hda1");
     expect_equal(opts.fstype, "ubifs");
 
+    // works when rootflags is the last option
+    buf = strdup("liminix fw_devlink=off root=/dev/hda1 rootfstype=ubifs rootflags=subvol=@");
+    memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
+    expect_equal(opts.device, "/dev/hda1");
+    expect_equal(opts.fstype, "ubifs");
+    expect_equal(opts.mount_opts, "subvol=@");
+
     buf = strdup("liminix rootfstype=ubifs fw_devlink=off root=/dev/hda1 foo");
     memset(&opts, '\0', sizeof opts); parseopts(buf, &opts);
     expect_equal(opts.fstype, "ubifs");
diff --git a/pkgs/preinit/preinit.c b/pkgs/preinit/preinit.c
index 8ad7ca76..076ada56 100644
--- a/pkgs/preinit/preinit.c
+++ b/pkgs/preinit/preinit.c
@@ -85,7 +85,7 @@ int main(int argc, char *argv[], char *envp[])
 	write(1, " (", 2);
 	write(1, opts.fstype, strlen(opts.fstype));
 	if(opts.mount_opts) {
-	    write(1, ", opts=", 6);
+	    write(1, ", opts=", 7);
 	    write(1, opts.mount_opts, strlen(opts.mount_opts));
 	}
 	write(1, ")\n", 2);