commit 1cc0b13b57511b4d094c9dd59070c78b01331385
parent c744ef8c17f39888a2a11c7a304cc6e869e347aa
Author: Daniel Barlow <dan@telent.net>
Date: Sat, 15 Apr 2023 17:15:44 +0100
rewrite systemconfig in C and link statically
systemconfig (a.k.a "activate") is run from the initramfs. Converting
it from a shell script to an executable means it doesn't depend on
there being a shell in the initramfs
Diffstat:
3 files changed, 77 insertions(+), 26 deletions(-)
diff --git a/modules/jffs2.nix b/modules/jffs2.nix
@@ -17,7 +17,7 @@ in
boot.initramfs.enable = true;
outputs = rec {
systemConfiguration =
- pkgs.pkgsBuildBuild.systemconfig config.filesystem.contents;
+ pkgs.systemconfig config.filesystem.contents;
rootfs =
let
inherit (pkgs.pkgsBuildBuild) runCommand mtdutils;
@@ -27,7 +27,8 @@ in
depsBuildBuild = [ mtdutils ];
} ''
mkdir -p $TMPDIR/empty/nix/store/
- cp ${systemConfiguration}/activate $TMPDIR/empty/activate
+ cp ${systemConfiguration}/bin/activate $TMPDIR/empty/activate
+ ln -s ${pkgs.s6-init-bin}/bin/init $TMPDIR/empty/init
pkgClosure=${closureInfo {
rootPaths = [ systemConfiguration ];
}}
diff --git a/pkgs/systemconfig/default.nix b/pkgs/systemconfig/default.nix
@@ -1,13 +1,13 @@
# The ideal is that a Liminix system can boot with only the files in
-# /nix/store. This package generates a script that is run at early
+# /nix/store. This package generates a small program that is run at early
# boot (from the initramfs) to populate directories such as /etc,
# /bin, /home according to whatever the configuration says
# they should contain
{
writeText
-, runCommand
, lib
+, stdenv
}:
let
inherit (lib.attrsets) mapAttrsToList;
@@ -32,33 +32,46 @@ let
assert gid == 0;
let
pathname = "${prefix}/${filename}";
- chmod =
- let m = if mode != null then mode else
- (if type == "d" then "0755" else "0644");
- in (if type == "s"
- then ""
- else "\nchmod ${m} ${pathname}");
+ qpathname = builtins.toJSON pathname;
+ mode' = if mode != null
+ then mode
+ else
+ (if type == "d" then "0755" else "0644");
cmds = {
- "f" = "printf \"${escaped file}\" > ${pathname}";
- "d" = "mkdir ${pathname}\n" +
+ "f" = "PRINTFILE(${qpathname}, ${mode'}, ${builtins.toJSON (escaped file)});";
+ "d" = "MKDIR(${qpathname}, ${mode'});\n" +
(builtins.concatStringsSep "\n"
(visit pathname contents));
- "c" = "mknod ${pathname} c ${major} ${minor}";
- "b" = "mknod ${pathname} b ${major} ${minor}";
- "s" = "ln -s ${target} ${pathname}";
- "l" = "ln ${target} ${pathname}";
- "i" = "mknod ${pathname} p";
+ "c" = "MKNOD_C(${qpathname}, ${mode'}, ${major}, ${minor});";
+ "b" = "MKNOD_B(${qpathname}, ${mode'}, ${major}, ${minor});";
+ "s" = "LN_S(${builtins.toJSON target}, ${qpathname});";
+ "l" = "LN(${builtins.toJSON target}, ${qpathname})";
+ "i" = "MKNOD_P(${qpathname}, ${mode'});";
};
cmd = cmds.${type};
- in "${cmd}${chmod}";
+ in "${cmd}";
in mapAttrsToList (makeFile prefix) attrset;
- activateScript = attrset: writeText "systemConfig" ''
- #!/bin/sh
- t=$1
- ${(builtins.concatStringsSep "\n" (visit "$t" attrset))}
+ activateScript = attrset: writeText "makedevs.c" ''
+ #include "defs.h"
+ int main(int argc, char* argv[]) {
+ chdir(argv[1]);
+ ${(builtins.concatStringsSep "\n" (visit "." attrset))}
+ }
'';
in attrset:
- runCommand "make-stuff" {} ''
- mkdir -p $out
- ln -s ${activateScript attrset} $out/activate
- ''
+ stdenv.mkDerivation {
+ name="make-stuff";
+ src = ./.;
+
+ CFLAGS = "-Os";
+ LDFLAGS = "-static";
+
+ postConfigure = ''
+ cp ${activateScript attrset} makedevs.c
+ '';
+ makeFlags = ["makedevs"];
+ installPhase = ''
+ mkdir -p $out/bin
+ $STRIP --remove-section=.note --remove-section=.comment --strip-all makedevs -o $out/bin/activate
+ '';
+ }
diff --git a/pkgs/systemconfig/defs.h b/pkgs/systemconfig/defs.h
@@ -0,0 +1,37 @@
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/sysmacros.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+void print_file(char * path, mode_t mode, char * text) {
+ int fd = open(path, O_CREAT | O_WRONLY, mode);
+ char *p, *nxt;
+ char b[1];
+ if(fd >=0) {
+ p = text;
+ while(nxt = strchr(p, '\\')) {
+ char upper = nxt[2];
+ char lower = nxt[3];
+ upper = (upper>'9') ? ((upper | 32) - 'a' + 10) : (upper - '0');
+ lower = (lower>'9') ? ((lower | 32) - 'a' + 10) : (lower - '0');
+ b[0] = (upper << 4) + lower;
+ write(fd, p, nxt-p);
+ write(fd, b, 1);
+ p=nxt+4;
+ }
+ write(fd, p, strlen(p));
+ close(fd);
+ }
+}
+
+
+
+#define PRINTFILE(path, mode, text) print_file(path, (mode_t) mode, text)
+#define MKDIR(path, mode) mkdir(path, mode)
+#define MKNOD_C(path, mode, major,minor) mknod(path, mode | S_IFCHR, makedev(major, minor))
+#define MKNOD_B(path, mode, major,minor) mknod(path, mode | S_IFBLK, makedev(major, minor))
+#define LN_S(target, path) (void)symlink(target, path)
+#define LN(target, path) link(target, path)
+#define MKNOD_P(path, mode) mkfifo(path, mode)