summaryrefslogtreecommitdiffstats
path: root/modules.d/90kernel-modules-extra/module-setup.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xmodules.d/90kernel-modules-extra/module-setup.sh186
1 files changed, 186 insertions, 0 deletions
diff --git a/modules.d/90kernel-modules-extra/module-setup.sh b/modules.d/90kernel-modules-extra/module-setup.sh
new file mode 100755
index 0000000..85e2e0a
--- /dev/null
+++ b/modules.d/90kernel-modules-extra/module-setup.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+
+# called by dracut
+#
+# Parses depmod configuration and calls instmods for out-of-tree kernel
+# modules found. Specifically, kernel modules inside directories that
+# come from the following places are included (if these kernel modules
+# are present in modules.dep):
+# - "search" configuration option;
+# - "override" configuration option (matching an exact file name constructed
+# by concatenating the provided directory and the kernel module name);
+# - "external" configuration option (if "external" is a part of "search"
+# configuration).
+# (See depmod.d(5) for details.)
+#
+# This module has the following variables available for configuration:
+# - "depmod_modules_dep" - Path to the modules.dep file
+# ("$srcmods/modules.dep" by default);
+# - "depmod_module_dir" - Directory containing kernel modules ("$srcmods"
+# by default);
+# - "depmod_configs" - array of depmod configuration paths to parse
+# (as supplied to depmod -C, ("/run/depmod.d/"
+# "/etc/depmod.d/" "/lib/depmod.d/") by default).
+installkernel() {
+ : "${depmod_modules_dep:=$srcmods/modules.dep}"
+ : "${depmod_module_dir:=$srcmods}"
+
+ [[ -f ${depmod_modules_dep} ]] || return 0
+
+ # Message printers with custom prefix
+ local mod_name="kernel-modules-extra"
+ prinfo() { dinfo " ${mod_name}: $*"; }
+ prdebug() { ddebug " ${mod_name}: $*"; }
+
+ # Escape a string for usage as a part of extended regular expression.
+ # $1 - string to escape
+ re_escape() {
+ printf "%s" "$1" | sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/'
+ }
+
+ local cfg
+ local cfgs=()
+ local search_list=""
+ local overrides=()
+ local external_dirs=()
+ local e f
+
+ ## Gathering and sorting configuration file list
+
+ [ -n "${depmod_configs[*]-}" ] \
+ || depmod_configs=(/run/depmod.d /etc/depmod.d /lib/depmod.d)
+
+ for cfg in "${depmod_configs[@]}"; do
+ [ -e "$cfg" ] || {
+ prdebug "configuration source \"$cfg\" does not exist"
+ continue
+ }
+
+ # '/' is used as a separator between configuration name and
+ # configuration path
+ if [ -d "$cfg" ]; then
+ for f in "$cfg/"*.conf; do
+ [[ -e $f && ! -d $f ]] || {
+ prdebug "configuration source" \
+ "\"$cfg\" is ignored" \
+ "(directory or doesn't exist)"
+ continue
+ }
+ cfgs+=("${f##*/}/$f")
+ done
+ else
+ cfgs+=("${cfg##*/}/$cfg")
+ fi
+ done
+
+ if ((${#cfgs[@]} > 0)); then
+ mapfile -t cfgs < <(printf '%s\n' "${cfgs[@]}" | LANG=C sort -u -k1,1 -t '/' | cut -f 2- -d '/')
+ fi
+
+ ## Parse configurations
+
+ for cfg in "${cfgs[@]}"; do
+ prdebug "parsing configuration file \"$cfg\""
+
+ local k v mod kverpat path
+ while read -r k v; do
+ case "$k" in
+ search)
+ search_list="$search_list $v"
+ prdebug "$cfg: added \"$v\" to the list of" \
+ "search directories"
+ ;;
+ override) # module_name kver_pattern dir
+ read -r mod kverpat path <<< "$v"
+
+ if [[ ! $mod || ! $kverpat || ! $path ]]; then
+ prinfo "$cfg: ignoring incorrect" \
+ "override option: \"$k $v\""
+ continue
+ fi
+
+ if [[ '*' == "$kverpat" ]] \
+ || [[ $kernel =~ $kverpat ]]; then
+ overrides+=("${path}/${mod}")
+
+ prdebug "$cfg: added override" \
+ "\"${path}/${mod}\""
+ else
+ prdebug "$cfg: override \"$v\" is" \
+ "ignored since \"$kverpat\"" \
+ "doesn't match \"$kernel\""
+ fi
+ ;;
+ external) # kverpat dir
+ read -r kverpat path <<< "$v"
+
+ if [[ ! $kverpat || ! $path ]]; then
+ prinfo "$cfg: ignoring incorrect" \
+ "external option: \"$k $v\""
+ continue
+ fi
+
+ if [[ '*' == "$kverpat" ]] \
+ || [[ $kernel =~ $kverpat ]]; then
+ external_dirs+=("$path")
+
+ prdebug "$cfg: added external" \
+ "directory \"$path\""
+ else
+ prdebug "$cfg: external directory" \
+ "\"$path\" is ignored since" \
+ "\"$kverpat\" doesn't match " \
+ "\"$kernel\""
+ fi
+ ;;
+ '#'* | '') # comments and empty strings
+ ;;
+ include | make_map_files) # ignored by depmod
+ ;;
+ *)
+ prinfo "$cfg: unknown depmod configuration" \
+ "option \"$k $v\""
+ ;;
+ esac
+ done < "$cfg"
+ done
+
+ # "updates built-in" is the default search list
+ : "${search_list:=updates}"
+
+ ## Build a list of regular expressions for grepping modules.dep
+
+ local pathlist=()
+ for f in "${overrides[@]}"; do
+ pathlist+=("^$(re_escape "$f")")
+ done
+
+ for f in $(printf "%s" "$search_list"); do
+ # Ignoring builtin modules
+ [[ $f == "built-in" ]] && continue
+
+ if [[ $f == "external" ]]; then
+ for e in "${external_dirs[@]}"; do
+ pathlist+=("$(re_escape "${e%/}")/[^:]+")
+ done
+ fi
+
+ pathlist+=("$(re_escape "${f%/}")/[^:]+")
+ done
+
+ ## Filter modules.dep, canonicalise the resulting filenames and supply
+ ## them to instmods.
+
+ ((${#pathlist[@]} > 0)) || return 0
+
+ printf "^%s\.ko(\.gz|\.bz2|\.xz|\.zst)?:\n" "${pathlist[@]}" \
+ | (LANG=C grep -E -o -f - -- "$depmod_modules_dep" || exit 0) \
+ | tr -d ':' \
+ | (
+ cd "$depmod_module_dir" || exit
+ xargs -r realpath -se --
+ ) \
+ | instmods || return 1
+
+ return 0
+}