1# When no modules are built, the $out/lib/modules directory will not
2# exist. Because the rest of the script assumes it does exist, we
3# handle this special case first.
4if ! test -d "$kernel/lib/modules"; then
5 if test -z "$rootModules" || test -n "$allowMissing"; then
6 mkdir -p "$out"
7 exit 0
8 else
9 echo "Required modules: $rootModules"
10 echo "Can not derive a closure of kernel modules because no modules were provided."
11 exit 1
12 fi
13fi
14
15version=$(cd $kernel/lib/modules && ls -d *)
16
17echo "kernel version is $version"
18
19# Determine the dependencies of each root module.
20mkdir -p $out/lib/modules/"$version"
21touch closure
22for module in $rootModules; do
23 echo "root module: $module"
24 modprobe --config no-config -d $kernel --set-version "$version" --show-depends "$module" \
25 | while read cmd module args; do
26 case "$cmd" in
27 builtin)
28 touch found
29 echo "$module" >>closure
30 echo " builtin dependency: $module";;
31 insmod)
32 touch found
33 if ! test -e "$module"; then
34 echo " dependency not found: $module"
35 exit 1
36 fi
37 target=$(echo "$module" | sed "s^$NIX_STORE.*/lib/modules/^$out/lib/modules/^")
38 if test -e "$target"; then
39 echo " dependency already copied: $module"
40 continue
41 fi
42 echo "$module" >>closure
43 echo " copying dependency: $module"
44 mkdir -p $(dirname $target)
45 cp "$module" "$target"
46 # If the kernel is compiled with coverage instrumentation, it
47 # contains the paths of the *.gcda coverage data output files
48 # (which it doesn't actually use...). Get rid of them to prevent
49 # the whole kernel from being included in the initrd.
50 nuke-refs "$target"
51 echo "$target" >> $out/insmod-list;;
52 *)
53 echo " unexpected modprobe output: $cmd $module"
54 exit 1;;
55 esac
56 done || test -n "$allowMissing"
57 if ! test -e found; then
58 echo " not found"
59 if test -z "$allowMissing"; then
60 exit 1
61 fi
62 else
63 rm found
64 fi
65done
66
67cd "$firmware"
68for module in $(< ~-/closure); do
69 # for builtin modules, modinfo will reply with a wrong output looking like:
70 # $ modinfo -F firmware unix
71 # name: unix
72 #
73 # There is a pending attempt to fix this:
74 # https://github.com/NixOS/nixpkgs/pull/96153
75 # https://lore.kernel.org/linux-modules/20200823215433.j5gc5rnsmahpf43v@blumerang/T/#u
76 #
77 # For now, the workaround is just to filter out the extraneous lines out
78 # of its output.
79 modinfo -b $kernel --set-version "$version" -F firmware $module | grep -v '^name:' | while read -r i; do
80 echo "firmware for $module: $i"
81 for name in "$i" "$i.xz" "$i.zst" ""; do
82 [ -z "$name" ] && echo "WARNING: missing firmware $i for module $module"
83 if cp -v --parents --no-preserve=mode lib/firmware/$name "$out" 2>/dev/null; then
84 break
85 fi
86 done
87 done || :
88done
89
90for path in $extraFirmwarePaths; do
91 mkdir -p $(dirname $out/lib/firmware/$path)
92 for name in "$path" "$path.xz" "$path.zst" ""; do
93 if cp -v --parents --no-preserve=mode lib/firmware/$name "$out" 2>/dev/null; then
94 break
95 fi
96 done
97done
98
99if test -e lib/firmware/edid ; then
100 echo "lib/firmware/edid found, copying."
101 mkdir -p "$out/lib/firmware"
102 cp -v --no-preserve=mode --recursive --dereference --no-target-directory lib/firmware/edid "$out/lib/firmware/edid"
103else
104 echo "lib/firmware/edid not found, skipping."
105fi
106
107# copy module ordering hints for depmod
108cp $kernel/lib/modules/"$version"/modules.order $out/lib/modules/"$version"/.
109cp $kernel/lib/modules/"$version"/modules.builtin $out/lib/modules/"$version"/.
110
111depmod -b $out -a $version
112
113# remove original hints from final derivation
114rm $out/lib/modules/"$version"/modules.order
115rm $out/lib/modules/"$version"/modules.builtin