From 2894de6b457342e760c669b20462c017620b5f90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lars=20Sj=C3=B6strom?= <lars@radicore.se>
Date: Fri, 28 Mar 2025 18:58:21 +0100
Subject: [PATCH] WIP: feat(linux-firmware): initial packaging of linux
 firmware

---
 flake.nix                           | 151 ++++++++++++++++++++++------
 foo.sh                              |  22 ++++
 pkgs/linux-firmware/default.nix     |  38 +++++++
 pkgs/linux-firmware/post-install.sh |  59 +++++++++++
 4 files changed, 241 insertions(+), 29 deletions(-)
 create mode 100755 foo.sh
 create mode 100644 pkgs/linux-firmware/default.nix
 create mode 100755 pkgs/linux-firmware/post-install.sh

diff --git a/flake.nix b/flake.nix
index 99fce5b..15a9152 100644
--- a/flake.nix
+++ b/flake.nix
@@ -25,10 +25,19 @@
       {
         packages = {
           default = patosPkgs.image;
-          image = pkgs.callPackage ./pkgs/image { inherit patosPkgs version updateUrl cpuArch secureBoot; };
+          image = pkgs.callPackage ./pkgs/image {
+            inherit
+              patosPkgs
+              version
+              updateUrl
+              cpuArch
+              secureBoot
+              ;
+          };
           rootfs = pkgs.callPackage ./pkgs/rootfs/mkrootfs.nix { inherit patosPkgs version; };
           initrd = pkgs.callPackage ./pkgs/rootfs/mkinitrd.nix { inherit patosPkgs version; };
           kernel = pkgs.callPackage ./pkgs/kernel { };
+          linux-firmware = pkgs.callPackage ./pkgs/linux-firmware { };
           glibc = pkgs.callPackage ./pkgs/glibc { };
           busybox = pkgs.callPackage ./pkgs/busybox { };
           openssl = pkgs.callPackage ./pkgs/openssl { };
@@ -46,38 +55,122 @@
             name = "debug-tools";
             version = "0.0.1";
             packages = [
-              { drv = pkgs.curl; path = "bin/curl"; }
-              { drv = pkgs.bash; path = "bin/bash"; }
-              { drv = patosPkgs.glibc; path = "bin/ldd"; }
-              { drv = pkgs.keyutils; path = "bin/keyctl"; }
-              { drv = pkgs.gnutar; path = "bin/tar"; }
-              { drv = pkgs.binutils-unwrapped; path = "bin/strings"; }
-              { drv = pkgs.strace; path = "bin/strace"; }
-              { drv = patosPkgs.tpm2-tools; path = "bin/tpm2"; }
-              { drv = patosPkgs.openssl; path = "bin/openssl"; }
-              { drv = pkgs.cryptsetup; path = "bin/cryptsetup"; }
-              { drv = pkgs.cryptsetup; path = "bin/veritysetup"; }
-              { drv = pkgs.erofs-utils; path = "bin/mkfs.erofs"; }
+              {
+                drv = pkgs.curl;
+                path = "bin/curl";
+              }
+              {
+                drv = pkgs.bash;
+                path = "bin/bash";
+              }
+              {
+                drv = patosPkgs.glibc;
+                path = "bin/ldd";
+              }
+              {
+                drv = pkgs.keyutils;
+                path = "bin/keyctl";
+              }
+              {
+                drv = pkgs.gnutar;
+                path = "bin/tar";
+              }
+              {
+                drv = pkgs.binutils-unwrapped;
+                path = "bin/strings";
+              }
+              {
+                drv = pkgs.strace;
+                path = "bin/strace";
+              }
+              {
+                drv = patosPkgs.tpm2-tools;
+                path = "bin/tpm2";
+              }
+              {
+                drv = patosPkgs.openssl;
+                path = "bin/openssl";
+              }
+              {
+                drv = pkgs.cryptsetup;
+                path = "bin/cryptsetup";
+              }
+              {
+                drv = pkgs.cryptsetup;
+                path = "bin/veritysetup";
+              }
+              {
+                drv = pkgs.erofs-utils;
+                path = "bin/mkfs.erofs";
+              }
               # shared lib required for cryptsetup
-              { drv = pkgs.popt; path = "lib/libpopt.so.0.0.2"; }
-              { drv = pkgs.popt; path = "lib/libpopt.so.0"; }
-              { drv = pkgs.popt; path = "lib/libpopt.so"; }
+              {
+                drv = pkgs.popt;
+                path = "lib/libpopt.so.0.0.2";
+              }
+              {
+                drv = pkgs.popt;
+                path = "lib/libpopt.so.0";
+              }
+              {
+                drv = pkgs.popt;
+                path = "lib/libpopt.so";
+              }
               # shared lib required for mkfs.erofs
-              { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1.10.0"; }
-              { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1"; }
-              { drv = pkgs.lz4.lib; path = "lib/liblz4.so"; }
+              {
+                drv = pkgs.lz4.lib;
+                path = "lib/liblz4.so.1.10.0";
+              }
+              {
+                drv = pkgs.lz4.lib;
+                path = "lib/liblz4.so.1";
+              }
+              {
+                drv = pkgs.lz4.lib;
+                path = "lib/liblz4.so";
+              }
               # shared lib required for binutils
-              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1.0.0"; }
-              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1"; }
-              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd-2.43.1.so"; }
-              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd.so"; }
+              {
+                drv = pkgs.binutils-unwrapped.lib;
+                path = "lib/libsframe.so.1.0.0";
+              }
+              {
+                drv = pkgs.binutils-unwrapped.lib;
+                path = "lib/libsframe.so.1";
+              }
+              {
+                drv = pkgs.binutils-unwrapped.lib;
+                path = "lib/libbfd-2.43.1.so";
+              }
+              {
+                drv = pkgs.binutils-unwrapped.lib;
+                path = "lib/libbfd.so";
+              }
               # shared lib required for strace
-              { drv = pkgs.elfutils.out; path = "lib/libdw-0.192.so"; }
-              { drv = pkgs.elfutils.out; path = "lib/libdw.so.1"; }
-              { drv = pkgs.elfutils.out; path = "lib/libdw.so"; }
-              { drv = pkgs.elfutils.out; path = "lib/libelf-0.192.so"; }
-              { drv = pkgs.elfutils.out; path = "lib/libelf.so.1"; }
-              { drv = pkgs.elfutils.out; path = "lib/libelf.so"; }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libdw-0.192.so";
+              }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libdw.so.1";
+              }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libdw.so";
+              }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libelf-0.192.so";
+              }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libelf.so.1";
+              }
+              {
+                drv = pkgs.elfutils.out;
+                path = "lib/libelf.so";
+              }
             ];
           };
         };
diff --git a/foo.sh b/foo.sh
new file mode 100755
index 0000000..aefb5d5
--- /dev/null
+++ b/foo.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+out=/tmp/build
+_pick() {
+  local p="$1" f d; shift
+  for f; do
+    d="$out/$p/${f#$out/}"
+    echo mkdir -p "$(dirname "$d")"
+    echo mv "$f" "$d"
+    echo rm -rf "$f"
+
+    echo mkfs.erofs --all-root -Efragments,dedupe,ztailpacking $out/$p.raw $p
+    echo veritysetup format --root-hash-file $out/$p.roothash $out/$p.raw $out/$p.verity
+  done
+}
+
+# _pick amd-ucode usr/lib/firmware/amd-ucode
+
+# _pick linux-firmware-nfp usr/lib/firmware/netronome
+# _pick linux-firmware-marvell usr/lib/firmware/{libertas,mwl8k,mwlwifi,mrvl}
+_pick linux-firmware-qlogic usr/lib/firmware/{qlogic,qed,ql2???_*,c{b,t,t2}fw-*}
+
+# _pick linux-firmware-base usr/lib/firmware
diff --git a/pkgs/linux-firmware/default.nix b/pkgs/linux-firmware/default.nix
new file mode 100644
index 0000000..161b2e4
--- /dev/null
+++ b/pkgs/linux-firmware/default.nix
@@ -0,0 +1,38 @@
+{
+  stdenv,
+  pkgs,
+}:
+
+stdenv.mkDerivation {
+  pname = pkgs.linux-firmware.name;
+  version = pkgs.linux-firmware.version;
+  src = pkgs.linux-firmware.src;
+
+  buildInputs = with pkgs; [
+    erofs-utils
+    cryptsetup
+  ];
+
+  nativeBuildInputs = with pkgs; [
+    python3
+    rdfind
+    which
+    zstd
+  ];
+
+  noBrokenSymlinks = true;
+
+  installTargets = [
+    "install-zst"
+    "dedup"
+  ];
+
+  # inspo: https://gitlab.archlinux.org/archlinux/packaging/packages/linux-firmware/-/blob/main/PKGBUILD?ref_type=heads#L93
+  makeFlags = [
+    "DESTDIR=$(out)"
+    "ZSTD_CLEVEL=19"
+    "FIRMWAREDIR=/usr/lib/firmware"
+  ];
+
+  postInstall = ./post-install.sh;
+}
diff --git a/pkgs/linux-firmware/post-install.sh b/pkgs/linux-firmware/post-install.sh
new file mode 100755
index 0000000..2dbe3ca
--- /dev/null
+++ b/pkgs/linux-firmware/post-install.sh
@@ -0,0 +1,59 @@
+set -ex -uo pipefail
+
+_pick() {
+  local p="$1" f d; shift
+  for f; do
+    d="$out/$p/${f#$out/}"
+    mkdir -p "$(dirname "$d")"
+    mv $out/"$f" "$d"
+    rm -rf $out/"$f"
+  done
+}
+
+_package() {
+  local p="$1"
+  mkdir -p $out/$p/usr/lib/extension-release.d
+  cat << EOF > $out/$p/usr/lib/extension-release.d/extension-release.$p
+ID=patos
+IMAGE_ID=$p
+IMAGE_VERSION=$version
+VERSION_ID=patos
+EOF
+
+  mkfs.erofs --all-root -Efragments,dedupe,ztailpacking $out/$p.raw $out/$p
+  veritysetup format --root-hash-file $out/$p.roothash $out/$p.raw $out/$p.verity
+}
+
+# remove arm64 firmware https://bugs.archlinux.org/task/76583
+rm $out/usr/lib/firmware/mrvl/prestera/mvsw_prestera_fw_arm64-v4.1.img.zst
+
+_pick amd-ucode usr/lib/firmware/amd-ucode
+_package amd-ucode
+
+_pick linux-firmware-nfp usr/lib/firmware/netronome
+_package linux-firmware-nfp
+
+_pick linux-firmware-mellanox usr/lib/firmware/mellanox
+_package linux-firmware-mellanox
+
+_pick linux-firmware-marvell usr/lib/firmware/{libertas,mwl8k,mwlwifi,mrvl}
+_package linux-firmware-marvell
+
+_pick linux-firmware-qcom usr/lib/firmware/qcom
+_package linux-firmware-qcom
+
+_pick linux-firmware-liquidio usr/lib/firmware/liquidio
+_package linux-firmware-liquidio
+
+# _pick linux-firmware-qlogic usr/lib/firmware/{qlogic,qed,ql2???_*,c{b,t,t2}fw-*}
+# _package linux-firmware-qlogic
+
+# _pick linux-firmware-bnx2x usr/lib/firmware/bnx2x*
+# _package linux-firmware-bnx2x
+
+# and the rest is base firmware
+_pick linux-firmware usr/lib/firmware
+_package linux-firmware
+
+# clean up
+# rm -rf $out/usr
-- 
2.49.0