diff options
Diffstat (limited to '')
-rwxr-xr-x | modules.d/90kernel-modules-extra/module-setup.sh | 186 | ||||
-rwxr-xr-x | modules.d/90kernel-modules/insmodpost.sh | 12 | ||||
-rwxr-xr-x | modules.d/90kernel-modules/module-setup.sh | 154 | ||||
-rwxr-xr-x | modules.d/90kernel-modules/parse-kernel.sh | 38 |
4 files changed, 390 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 +} diff --git a/modules.d/90kernel-modules/insmodpost.sh b/modules.d/90kernel-modules/insmodpost.sh new file mode 100755 index 0000000..a7ab05b --- /dev/null +++ b/modules.d/90kernel-modules/insmodpost.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +. /lib/dracut-lib.sh + +for modlist in $(getargs rd.driver.post -d rdinsmodpost=); do + ( + IFS=, + for m in $modlist; do + modprobe "$m" + done + ) +done diff --git a/modules.d/90kernel-modules/module-setup.sh b/modules.d/90kernel-modules/module-setup.sh new file mode 100755 index 0000000..e217512 --- /dev/null +++ b/modules.d/90kernel-modules/module-setup.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +# called by dracut +installkernel() { + local _blockfuncs='ahci_platform_get_resources|ata_scsi_ioctl|scsi_add_host|blk_cleanup_queue|register_mtd_blktrans|scsi_esp_register|register_virtio_device|usb_stor_disconnect|mmc_add_host|sdhci_add_host|scsi_add_host_with_dma|blk_mq_alloc_disk|blk_mq_alloc_request|blk_mq_destroy_queue|blk_cleanup_disk' + local -A _hostonly_drvs + + record_block_dev_drv() { + + for _mod in $(get_dev_module /dev/block/"$1"); do + _hostonly_drvs["$_mod"]="$_mod" + done + + for _mod in $(get_blockdev_drv_through_sys "/sys/dev/block/$1"); do + _hostonly_drvs["$_mod"]="$_mod" + done + + ((${#_hostonly_drvs[@]} > 0)) && return 0 + return 1 + } + + install_block_modules_strict() { + hostonly='' instmods "${_hostonly_drvs[@]}" + } + + install_block_modules() { + instmods \ + scsi_dh_rdac scsi_dh_emc scsi_dh_alua \ + =drivers/usb/storage \ + =ide nvme vmd \ + virtio_blk virtio_scsi \ + =drivers/ufs + + dracut_instmods -o -s "${_blockfuncs}" "=drivers" + } + + if [[ -z $drivers ]]; then + hostonly='' instmods \ + hid_generic unix + + hostonly=$(optional_hostonly) instmods \ + ehci-hcd ehci-pci ehci-platform \ + ohci-hcd ohci-pci \ + uhci-hcd \ + usbhid \ + xhci-hcd xhci-pci xhci-plat-hcd \ + "=drivers/hid" \ + "=drivers/tty/serial" \ + "=drivers/input/serio" \ + "=drivers/input/keyboard" \ + "=drivers/pci/host" \ + "=drivers/pci/controller" \ + "=drivers/pinctrl" \ + "=drivers/usb/typec" \ + "=drivers/watchdog" + + instmods \ + yenta_socket spi_pxa2xx_platform \ + atkbd i8042 firewire-ohci pcmcia hv-vmbus \ + virtio virtio_ring virtio_pci pci_hyperv \ + "=drivers/pcmcia" + + if [[ ${DRACUT_ARCH:-$(uname -m)} == arm* || ${DRACUT_ARCH:-$(uname -m)} == aarch64 || ${DRACUT_ARCH:-$(uname -m)} == riscv* ]]; then + # arm/aarch64 specific modules + _blockfuncs+='|dw_mc_probe|dw_mci_pltfm_register|nvme_init_ctrl' + instmods \ + "=drivers/clk" \ + "=drivers/devfreq" \ + "=drivers/dma" \ + "=drivers/extcon" \ + "=drivers/gpio" \ + "=drivers/hwmon" \ + "=drivers/hwspinlock" \ + "=drivers/interconnect" \ + "=drivers/i2c/busses" \ + "=drivers/mailbox" \ + "=drivers/memory" \ + "=drivers/mfd" \ + "=drivers/mmc/core" \ + "=drivers/mmc/host" \ + "=drivers/nvmem" \ + "=drivers/phy" \ + "=drivers/power" \ + "=drivers/regulator" \ + "=drivers/reset" \ + "=drivers/rpmsg" \ + "=drivers/rtc" \ + "=drivers/soc" \ + "=drivers/spi" \ + "=drivers/usb/chipidea" \ + "=drivers/usb/dwc2" \ + "=drivers/usb/dwc3" \ + "=drivers/usb/host" \ + "=drivers/usb/isp1760" \ + "=drivers/usb/misc" \ + "=drivers/usb/musb" \ + "=drivers/usb/phy" \ + "=drivers/scsi/hisi_sas" + fi + + awk -F: '/^\// {print $1}' "$srcmods/modules.dep" 2> /dev/null | instmods + + # if not on hostonly mode, or there are hostonly block device + # install block drivers + if ! [[ $hostonly ]] \ + || for_each_host_dev_and_slaves_all record_block_dev_drv; then + hostonly='' instmods sg sr_mod sd_mod scsi_dh ata_piix + + if [[ $hostonly_mode == "strict" ]]; then + install_block_modules_strict + else + install_block_modules + fi + fi + + # if not on hostonly mode, install all known filesystems, + # if the required list is not set via the filesystems variable + if ! [[ $hostonly ]]; then + if [[ -z $filesystems ]]; then + dracut_instmods -o -P ".*/(kernel/fs/nfs|kernel/fs/nfsd|kernel/fs/lockd)/.*" '=fs' + fi + elif [[ "${host_fs_types[*]}" ]]; then + hostonly='' instmods "${host_fs_types[@]}" + fi + + arch=${DRACUT_ARCH:-$(uname -m)} + + # We don't want to play catch up with hash and encryption algorithms. + # To be safe, just use the hammer and include all crypto. + [[ $arch == x86_64 ]] && arch=x86 + [[ $arch == s390x ]] && arch=s390 + [[ $arch == aarch64 ]] && arch=arm64 + hostonly='' instmods "=crypto" + instmods "=arch/$arch/crypto" "=drivers/crypto" + fi + + inst_multiple -o "$depmodd/*.conf" + if [[ $hostonly ]]; then + inst_multiple -H -o "$depmodconfdir/*.conf" + fi + : +} + +# called by dracut +install() { + [[ -d /lib/modprobe.d ]] && inst_multiple -o "/lib/modprobe.d/*.conf" + [[ -d /usr/lib/modprobe.d ]] && inst_multiple -o "/usr/lib/modprobe.d/*.conf" + [[ $hostonly ]] && inst_multiple -H -o /etc/modprobe.d/*.conf /etc/modprobe.conf + if ! dracut_module_included "systemd"; then + inst_hook cmdline 01 "$moddir/parse-kernel.sh" + fi + inst_simple "$moddir/insmodpost.sh" /sbin/insmodpost.sh + inst_multiple -o sysctl +} diff --git a/modules.d/90kernel-modules/parse-kernel.sh b/modules.d/90kernel-modules/parse-kernel.sh new file mode 100755 index 0000000..d14f912 --- /dev/null +++ b/modules.d/90kernel-modules/parse-kernel.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +_modprobe_d=/etc/modprobe.d +if [ -d /usr/lib/modprobe.d ]; then + _modprobe_d=/usr/lib/modprobe.d +elif [ -d /lib/modprobe.d ]; then + _modprobe_d=/lib/modprobe.d +elif [ ! -d $_modprobe_d ]; then + mkdir -p $_modprobe_d +fi + +for i in $(getargs rd.driver.pre -d rdloaddriver=); do + ( + IFS=, + for p in $i; do + modprobe "$p" 2>&1 | vinfo + done + ) +done + +[ -d /etc/modprobe.d ] || mkdir -p /etc/modprobe.d + +for i in $(getargs rd.driver.blacklist -d rdblacklist=); do + ( + IFS=, + for p in $i; do + echo "blacklist $p" >> $_modprobe_d/initramfsblacklist.conf + done + ) +done + +for p in $(getargs rd.driver.post -d rdinsmodpost=); do + echo "blacklist $p" >> $_modprobe_d/initramfsblacklist.conf + _do_insmodpost=1 +done + +[ -n "$_do_insmodpost" ] && initqueue --settled --unique --onetime insmodpost.sh +unset _do_insmodpost _modprobe_d |