From e907d0d3d35c08b4ba4353f1f3a788feddd2ad99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lars=20Sj=C3=B6strom?= <lars@radicore.se>
Date: Fri, 7 Mar 2025 15:18:51 +0100
Subject: [PATCH] fix: rootfs now with verity and A/B prep

---
 pkgs/image/default.nix  |  4 +-
 pkgs/image/mkimage.sh   | 84 ++++++++++++++++++++++++++++++++++-------
 pkgs/rootfs/mkrootfs.sh | 29 +++++++++++++-
 3 files changed, 100 insertions(+), 17 deletions(-)

diff --git a/pkgs/image/default.nix b/pkgs/image/default.nix
index 4da5187..0fcaf3f 100644
--- a/pkgs/image/default.nix
+++ b/pkgs/image/default.nix
@@ -19,6 +19,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
     dosfstools
     mtools
     e2fsprogs
+    jq
   ];
 
   env = {
@@ -32,8 +33,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
   initrd = patosPkgs.initrd.out;
   rootfs = patosPkgs.rootfs.out;
 
-  #FIXME: use roothash instead of device.
-  kernelCmdLine = "root=/dev/sda2 console=ttyS0";
+  kernelCmdLine = "console=ttyS0";
 
   builder = ./mkimage.sh;
 })
diff --git a/pkgs/image/mkimage.sh b/pkgs/image/mkimage.sh
index c08f0d8..78e55f8 100644
--- a/pkgs/image/mkimage.sh
+++ b/pkgs/image/mkimage.sh
@@ -1,6 +1,6 @@
 set -ex -o pipefail
 
-mkdir -p $out/repart.d $out/boot
+mkdir -p $out/init.repart.d $out/final.repart.d $out/boot
 pushd $out
 
 # Don't seem to work just to create a symlink to rootfs derivation?
@@ -34,46 +34,102 @@ CREDENTIALS_DIRECTORY=$PWD/creds SYSTEMD_CRYPT_PREFIX='$6$' $systemd/usr/bin/sys
 chmod 600 rootfs/etc/shadow
 rm -rf creds
 
+# Initial partitioning
+cat <<EOF > init.repart.d/10-root.conf
+[Partition]
+Type=root
+Format=erofs
+Minimize=best
+CopyFiles=/rootfs:/
+Verity=data
+VerityMatchKey=root
+SplitName=root
+EOF
+
+cat <<EOF > init.repart.d/20-root-verity.conf
+[Partition]
+Type=root-verity
+Verity=hash
+VerityMatchKey=root
+Minimize=best
+SplitName=verity
+EOF
+
+#TODO: Add verity signature partition
+
+$systemd/usr/bin/systemd-repart \
+  --no-pager \
+  --empty=create \
+  --size=auto \
+  --definitions=./init.repart.d \
+  --split=true \
+  --json=pretty \
+  --root=$out \
+  patos-$version.raw > init-repart-output.json
+rm -f patos-$version.raw
+
+roothash=$(jq -r '.[0].roothash' init-repart-output.json)
+rootPart=$(jq -r '.[0].split_path' init-repart-output.json)
+rootUuid=$(jq -r '.[0].uuid' init-repart-output.json)
+
+verityPart=$(jq -r '.[1].split_path' init-repart-output.json)
+verityUuid=$(jq -r '.[1].uuid' init-repart-output.json)
+
 $systemd/usr/bin/ukify build \
   --linux $kernel/bzImage \
   --initrd $initrd/initrd.xz \
   --os-release @rootfs/etc/os-release \
-  --cmdline "$kernelCmdLine" \
-  -o boot/patos.efi
+  --cmdline "$kernelCmdLine roothash=$roothash" \
+  -o patos_${version}.efi
+rm -rf rootfs
 
+cp patos_${version}.efi boot/
 cp ${systemd}/usr/lib/systemd/boot/efi/systemd-bootx64.efi boot/
-
 echo "timeout 1" > boot/loader.conf
 
-cat <<EOF > repart.d/10-esp.conf
+# Final partitioning
+cat <<EOF > final.repart.d/10-esp.conf
 [Partition]
 Type=esp
 Format=vfat
 SizeMinBytes=96M
 SizeMaxBytes=96M
 CopyFiles=/boot/systemd-bootx64.efi:/EFI/BOOT/BOOTX64.EFI
-CopyFiles=/boot/patos.efi:/EFI/Linux/patos.efi
+CopyFiles=/boot/patos_${version}.efi:/EFI/Linux/patos_${version}.efi
 CopyFiles=/boot/loader.conf:/loader/loader.conf
 EOF
 
-cat <<EOF > repart.d/10-root.conf
+cat <<EOF > final.repart.d/20-root.conf
 [Partition]
 Type=root
-Format=erofs
-Minimize=best
-CopyFiles=/rootfs:/
-SplitName=root
+Label=root-${version}
+CopyBlocks=/${rootPart}
+UUID=${rootUuid}
+SizeMinBytes=256M
+SizeMaxBytes=256M
+ReadOnly=1
 EOF
 
+cat <<EOF > final.repart.d/22-root-verity.conf
+[Partition]
+Type=root-verity
+Label=verity-${version}
+CopyBlocks=/${verityPart}
+UUID=${verityUuid}
+SizeMinBytes=10M
+SizeMaxBytes=10M
+ReadOnly=1
+EOF
+
+# finalize image ready for boot
 $systemd/usr/bin/systemd-repart \
   --no-pager \
   --empty=create \
   --size=auto \
-  --definitions=./repart.d \
+  --definitions=./final.repart.d \
   --root=$out \
-  patos-$version.raw
+  patos-$version.raw > final-repart-output.json
 
-rm -rf rootfs
 rm -rf boot
 
 popd
diff --git a/pkgs/rootfs/mkrootfs.sh b/pkgs/rootfs/mkrootfs.sh
index a9f16d9..05a613b 100644
--- a/pkgs/rootfs/mkrootfs.sh
+++ b/pkgs/rootfs/mkrootfs.sh
@@ -52,11 +52,38 @@ cat <<EOF > $out/etc/repart.d/10-esp.conf
 [Partition]
 Type=esp
 Format=vfat
+SizeMaxBytes=96M
+SizeMinBytes=96M
 EOF
 
-cat <<EOF > $out/etc/repart.d/22-root.conf
+cat <<EOF > $out/etc/repart.d/20-root-a.conf
 [Partition]
 Type=root
+SizeMaxBytes=256M
+SizeMinBytes=256M
+EOF
+cat <<EOF > $out/etc/repart.d/22-root-verify-a.conf
+[Partition]
+Type=root-verity
+SizeMaxBytes=10M
+SizeMinBytes=10M
+EOF
+
+cat <<EOF > $out/etc/repart.d/30-root-b.conf
+[Partition]
+Type=root
+Label=_empty
+SizeMaxBytes=256M
+SizeMinBytes=256M
+ReadOnly=1
+EOF
+cat <<EOF > $out/etc/repart.d/32-root-verity-b.conf
+[Partition]
+Type=root-verity
+Label=_empty
+SizeMaxBytes=10M
+SizeMinBytes=10M
+ReadOnly=1
 EOF
 
 cat <<EOF > $out/etc/repart.d/40-var.conf