diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 2f386617187..2e9deebbb74 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -171,6 +171,11 @@ let mv etc/udev/hwdb.bin $out ''; + compressFirmware = if config.boot.kernelPackages.kernelAtLeast "5.3" then + pkgs.compressFirmwareXz + else + id; + # Udev has a 512-character limit for ENV{PATH}, so create a symlink # tree to work around this. udevPath = pkgs.buildEnv { @@ -267,7 +272,7 @@ in ''; apply = list: pkgs.buildEnv { name = "firmware"; - paths = list; + paths = map compressFirmware list; pathsToLink = [ "/lib/firmware" ]; ignoreCollisions = true; }; diff --git a/pkgs/build-support/kernel/compress-firmware-xz.nix b/pkgs/build-support/kernel/compress-firmware-xz.nix new file mode 100644 index 00000000000..56595131c89 --- /dev/null +++ b/pkgs/build-support/kernel/compress-firmware-xz.nix @@ -0,0 +1,16 @@ +{ runCommand }: + +firmware: + +runCommand "${firmware.name}-xz" {} '' + mkdir -p $out/lib + (cd ${firmware} && find lib/firmware -type d -print0) | + (cd $out && xargs -0 mkdir -v --) + (cd ${firmware} && find lib/firmware -type f -print0) | + (cd $out && xargs -0tP "$NIX_BUILD_CORES" -n1 \ + sh -c 'xz -9c -T1 -C crc32 --lzma2=dict=2MiB "${firmware}/$1" > "$1.xz"' --) + (cd ${firmware} && find lib/firmware -type l) | while read link; do + target="$(readlink "${firmware}/$link")" + ln -vs -- "''${target/^${firmware}/$out}.xz" "$out/$link.xz" + done +'' diff --git a/pkgs/build-support/kernel/modules-closure.sh b/pkgs/build-support/kernel/modules-closure.sh index 3b3a38ea1d3..74bc490eb15 100644 --- a/pkgs/build-support/kernel/modules-closure.sh +++ b/pkgs/build-support/kernel/modules-closure.sh @@ -81,8 +81,12 @@ for module in $(cat closure); do for i in $(modinfo -b $kernel --set-version "$version" -F firmware $module | grep -v '^name:'); do mkdir -p "$out/lib/firmware/$(dirname "$i")" echo "firmware for $module: $i" - cp "$firmware/lib/firmware/$i" "$out/lib/firmware/$i" 2>/dev/null \ - || echo "WARNING: missing firmware $i for module $module" + for name in "$i" "$i.xz" ""; do + [ -z "$name" ] && echo "WARNING: missing firmware $i for module $module" + if cp "$firmware/lib/firmware/$name" "$out/lib/firmware/$name" 2>/dev/null; then + break + fi + done done done diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index e89aa5c04a8..f1170aae20d 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -808,6 +808,8 @@ with pkgs; sanitizers = [ ]; }; + compressFirmwareXz = callPackage ../build-support/kernel/compress-firmware-xz.nix { }; + makeModulesClosure = { kernel, firmware, rootModules, allowMissing ? false }: callPackage ../build-support/kernel/modules-closure.nix { inherit kernel firmware rootModules allowMissing;