#!/bin/bash # Copyright 2021-2024 Stuart Winter, Donostia, Spain. # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ######################################################################### # Script : /load_kernel_modules # Purpose: Load the generic platform modules, and load appropriate # modules for the host hardware at runtime. # Status : ARM LOCAL # Author : Stuart Winter # Date...: 30-Mar-2021 # Version: 1.00 ######################################################################### # This script can be controlled at run time at various key events in # its execution, which should provide adequate user control (using simple # bash shell scripts) over this component of the boot process. # # These scripts constitute the self-service aspects of the Operating # System's generic initial RAM disk ('OS initrd'). # See /boot/local for examples. # /usr/sbin/os-initrd-mgr is the tool to manage the process. # ######################################################################### # # Script Stage # ------------------------------------------------------------------ # /load_kernel_modules.pre Load user-supplied script # prior to setting and loading any Kernel modules. # # This is a chance to run 'demod' if you're testing an initrd # without running depmod on the contents prior to booting. # Typically this will not be used. # # /load_kernel_modules.pre-modload Load a user-supplied script # subsequent to all module variable definitions being finalised, # and prior to loading those Kernel modules. # # This enables you to make minor adjustments to the module lists # that have been set by the provided platform support scripts. # If one of the modules within the base list is causing problems on # your platform, here are the options laid out as examples. # # You could include this type of code within this pre hook script: # USB="${USB/ehci_orion/differentmodule}" # Substitute module 'ehci_orion' with 'differentmodule' # USB="${USB/ehci_orion/}" # Remove the 'ehci_orion' module from the list # USB="${USB} some_other_module" # Add a module to the list # # /load_kernel_modules.post Load a user-supplied script # subsequent to loading the Kernel modules, but prior to restoring # execution control to /init. # # If you are debugging, you may wish to open a shell to examine the # environment before booting the Slackware OS proper. # This was used extensively during the development of Slackware AArch64. ######################################################################### # User serviceable runtime callout: function loadhook() { if [ -s "$1" ]; then echo "Executing user-supplied script: $1" . $1 echo "Completed executing user-supplied script: $1" fi } # Determine whether the Hardware Model function script # has a particular function defined: function fnexists() { local estat=1 type -t $1 >/dev/null && { [ $( type -t $1 ) = "function" ] && estat=0 ;} return $estat } # Only load a module if it's not loaded already. # This prevents repeated messages. function modprobe_once() { awk '{print $1}' /proc/modules | grep -Eq "^${1}$" || modprobe $1 } # Determine the Hardware Model's architecture: ARCH=$( slk-hwm-discover --print-arch ) # Determine whether the preboot shell option has been specified within the # Kernel command line arguments. This allows the user to more easily # access the OS initrd environment at different stages of the module # loading process, to aid with onboarding new ARM devices. # This can also be achieved by using the load hooks (see below) but this # method bypasses the need to re-create the initrd, as you'll only need # to edit the boot loader configuration. This option is aimed at developers, # not users. PREBOOTSHELL=No MODLOAD_STEP=No grep -wq "slkpbs" /proc/cmdline 2> /dev/null && PREBOOTSHELL=Yes grep -wq "slkpbs_modstep" /proc/cmdline 2> /dev/null && MODLOAD_STEP=Yes # Option to open pre-boot shell once all modules have been defined and loaded. # This is to help with input systems (e.g. USB keyboards) that won't come live # at stages 1-2 because the modules have yet to be loaded: grep -wq "slkpbs3" /proc/cmdline 2> /dev/null && PREBOOTSHELL3=Yes # Position /usr/local/sbin ahead of the others so that our 'reboot' wrapper # will be called rather than the binary. # This wrapper calls reboot with the -f(orce) operator, because the OS InitRD # environment is insufficiently initialised to enable a graceful shutdown. export PATH=/usr/local/sbin:$PATH # Load an environment configuration, if present. This shell script is designed # for non-mainline Kernel packages, exemplified by the Raspberry Pi Kernel # build system. # https://docs.slackware.com/slackwarearm:cstmz_kernel_rpi [ -s /.kernel_pkg_settings ] && . /.kernel_pkg_settings # If the token 'slkpbs' is set in the Kernel command line, open a shell: if [ "$PREBOOTSHELL" = "Yes" ]; then echo "Pre-boot Shell stage 1 of 3: Initial boot stage" echo echo "No Kernel modules have been configured nor loaded yet." echo echo "Exit shell to proceed to the next stage in the module loading" echo "process." echo echo "Development shell opening." [ -d /load_kernel_modules.scr/platform/$ARCH ] && { echo echo "The Kernel module loader scripts can be found here:" echo " /load_kernel_modules.scr/platform/$ARCH" echo echo "You may edit these and they will be loaded immediately subsequent to" echo "exiting this stage of the Pre-boot Shell." ;} echo PS1="Pre-boot Shell (1/3): # " /bin/ash fi # User serviceable pre execution load hook: loadhook /load_kernel_modules.pre # # Generic requirements for all platforms # # Note that these are loose classifications and aren't necessarily # in alignment with the Kernel's. # If you can improve the classification for a module, please email # mozes@slackware.com. # Base modules: export MOD_BASE="cqhci drm drm_kms_helper binfmt_misc" # USB core modules including interface devices (USB keyboards etc): export MOD_USB="usbcore roles ehci_orion ehci-hcd uhci_hcd usbhid ohci-platform ohci_hcd hid \ ehci-platform ehci-pci xhci-hcd xhci-pci" # USB hubs and some specific device drivers: MOD_USB+=" ums-cypress ums-usbat ums-freecom ums-isd200 ums-sddr09 ums-sddr55 ums-alauda ums-jumpshot \ ums-onetouch" # Display port adapters running over the USB-C bus: MOD_USB+=" typec_displayport typec tcpm" # Some specific sub drivers for the 'USB-storage' module: export MOD_USBSTORAGESUB="usb-storage uas" # SATA support, generic libata: export MOD_SATA="libata ahci libahci ahci_platform" # For SDHC/MMC: export MOD_CARDS="sdhci sdhci_pltfm armmmci mmc_block" # LVM, RAID, NVME etc: export MOD_STORAGEDEVICELAYERS="jbd2 raid1 dm-snapshot dm-mod md mbcache nvme" # Video modules required to provide visibility of # the Kernel and OS bootup process: export MOD_VIDEO="" # Generic Subsystems/peripherals for System on Chip stuff: # These are for peripherals (or 'IP blocks' as ARM calls them) that are embedded # within the SoC directly. # For some vendors there are particular 'IP blocks' (such as SPI flash controllers) # that are re-used throughout generations of their Hardware Models which could be # defined here. export MOD_SOC="pwm-fan" # Subsystems/peripherals for Hardware Models. # Various Hardware Models may share a SoC but have additional peripherals on the # main board, outside of the SoC. export MOD_HWM="" # Generic modules for the physical layer: export MOD_PHY="" # Generic modules for the GPIO (General Purpose Input/Output): export MOD_GPIO="gpio-fan" # Generic modules for the MFD (Multi Functional Devices): export MOD_MFD="" # Filesystems: export MOD_FS="vfat ext2 ext3 ext4 btrfs reiserfs jfs xfs f2fs bcachefs" # Compression: export MOD_CMP="lz4hc_compress lz4_compress" # Cryptography: export MOD_CRYPTO="crc32_generic algif_skcipher" # Generic SCSI drivers & low-level drivers for discs/media: export MOD_SCSI="sg scsi_mod sd_mod virtio_blk" # cdrom, sr_mod are included because this script is also used # within the Slackware installer where (although it's highly unlikely) # it is possible to install Slackware ARM/AArch64 from a CDROM! # I did test it on ARM years ago for fun, but I'm open to removing # both of these modules out of pragmatism. Let mozes@slackware.com # know if these cause any issues anywhere. # cdrom support is not included within the OS InitRD (Operating System Initial RAM Disk) # since the root filesystem won't reside on optical media, but the Installer may # require it. [ -f /.installer-version ] && { MOD_SCSI+=" cdrom sr_mod" ;} # Network filesystems: export MOD_NETFS="nfs lockd" # Network interface cards: # USB (Mac) dongle export MOD_NET="usbnet" #export MOD_NET="" # Additional stuff such as Netconsole (useful for debugging on machines without a serial cable) #export MOD_ADDITIONS=" netconsole" # RTC (Real Time Clock) drivers: # There is no generic RTC applicable to all platforms: RTCs are set on a per-device basis # within each platform's module loader script (loaded below). export MOD_RTC="" # Select any modules required for specific hardware platforms # that are supported by the Slackware ARM development team or # the community. # To add your device here, follow the instructions at: # https://arm.slackware.com/slackwarearm-devel/ # Developers take note: /sys must be mounted for /proc/device-tree/model # to be accessible. # This information may also be obtained from /sys/devices/soc0/machine # but the /proc entry point is the 'industry standard'. Additionally, # with some devices this author has supported in the past, the /sys # entries were absent where as the /proc entry was always present. # Determine the Hardware Model name: export HWM=$( slk-hwm-discover ) # Load in the Hardware Model helpers/plugin shell scripts: if [ ! -z "$HWM" ]; then unset platform_detected for platformscr in /load_kernel_modules.scr/platform/$ARCH/* ; do . $platformscr ; done else echo "WARNING: unable to detect Hardware Model Type" echo " This may cause your system to not boot or cause instability." echo " This may be because you are running this on an unsupported" echo " Hardware Model." sleep 10 fi if [ -z "$platform_detected" ]; then [ ! -z "$HWM" ] && HWM="(${HWM})" echo "WARNING: Unsupported $ARCH Hardware Model $HWM" echo " This may cause your system to not boot or cause instability." echo echo " If you are a developer and would like to help enable Slackware" echo " on this device, please visit:" echo " https://arm.slackware.com/slackwarearm-devel/" sleep 4 fi # If present, drop a modprobe configuration file for this SoC. # This enables blacklisting and configuring modules. # These are placed here by source/k/kernel.SlackBuild during the Kernel package # and generic OS InitRD/Installer build process. They are not user serviceable. # We need to discriminate at the SoC/Hardware Model level here as we cannot # supply a generic modprobe config that is guaranteed to work on all Hardware Models. # Each modprobe configuration is named _ # e.g. rk3399_pbpro for the Pinebook Pro, which uses the rk3399 SoC. if [ -f /usr/share/hwm-configure/platform/$ARCH/modprobe.d/${SOC_NAME}_${HWM_SHORTNAME}.conf ]; then mkdir -pm755 /{lib,etc}/modprobe.d/ #mkdir -pm755 /lib/modprobe.d # /lib/modprobe.d is supposed to work, but doesn't seem to. Let's populate both locations: install -pm644 /usr/share/hwm-configure/platform/$ARCH/modprobe.d/${SOC_NAME}_${HWM_SHORTNAME}.conf /lib/modprobe.d/ install -pm644 /usr/share/hwm-configure/platform/$ARCH/modprobe.d/${SOC_NAME}_${HWM_SHORTNAME}.conf /etc/modprobe.d/ fi # If the token 'slkpbs' is set in the Kernel command line, open a shell: if [ "$PREBOOTSHELL" = "Yes" ]; then echo "Pre-boot Shell stage 2 of 3: Pre module loading." echo echo "Kernel modules have been configured to load, but have not yet been loaded." echo "Exit shell to proceed to the next stage in the module loading" echo "process." echo echo "Module variables are prefixed with 'MOD_' within the environment." echo "Note: You cannot edit the variables here, only view." echo echo "Development shell opening." echo PS1="Pre-boot Shell (2/3): # " /bin/ash fi # The Pre Boot Shell is forked, so there's no route through which the parent can # be directly affected. This hook enables the user of the PBS to create some bash # shell code to include at this point in the execution process. # For example, one may wish to edit the module lists prior to them being loaded. # One may also wish to edit the variables within 'init' itself (since /load_kernel_modules # is sourced (rather than forked)). [ -s /pbs_stage1.post ] && . /pbs_stage1.post # User serviceable pre module load hook: # loadhook /load_kernel_modules.pre-modload # If one of Hardware Model helper/plugin scripts defined the function # 'hwm_hook_premodload', call it now. # This enables execution of actions prior to loading the defined set of # Linux Kernel modules. fnexists hwm_hook_pre-modload && hwm_hook_pre-modload # If the user created a flag file to step through the modules (rather than using) # the cmdline option, recognise it: [ -f /.modloadstep ] && MODLOAD_STEP=Yes # Load the modules: for mod in $MOD_VIDEO $MOD_BASE $MOD_SOC $MOD_HWM $MOD_MFD $MOD_GPIO $MOD_PHY \ $MOD_SATA $MOD_USB $MOD_USBSTORAGESUB $MOD_SCSI $MOD_CARDS \ $MOD_STORAGEDEVICELAYERS \ $MOD_RTC \ $MOD_CMP \ $MOD_CRYPTO \ $MOD_FS \ $MOD_NETFS $MOD_NET ; do # This is a crude troubleshooting tool: a subsequent module may load # a rejected module as a dependency. However, that's not the case for # all, so it's still useful. [ "$MODLOAD_STEP" = "Yes" ] && read -p "Load module: *** ${mod} *** (ENTER for Yes, 'n' for No) " lyn [ -z "$lyn" ] && modprobe $mod done # User serviceable post module load hook: loadhook /load_kernel_modules.post # If one of Hardware Model helper/plugin scripts defined the function # 'hwm_hook_post-modload', call it now. # This enables the helper scripts to define a series of actions to run # subsequent to loading the Linux Kernel modules. # This is particularly useful to finalise setup for devices such as RTCs # that surface upon loading of the Kernel modules. fnexists hwm_hook_post-modload && hwm_hook_post-modload # If os-initrd-mgr was called with --sync-loaded-kmods, it creates a # script that contains individual 'modprobe' lines for all modules that # were discovered within the running OS. # If this is present, we'll load it now: [ -s /os_synced_kmods_loader ] && . /os_synced_kmods_loader # If the token 'slkpbs' or 'slkpbs3' is set in the Kernel command line, open a shell: if [ "$PREBOOTSHELL" = "Yes" -o "$PREBOOTSHELL3" = "Yes" ]; then echo "Pre-boot Shell stage 3 of 3: Post module loading" echo echo "Kernel modules have been loaded." echo echo "Exit shell to proceed to boot the Slackware OS proper." echo echo "Module variables are prefixed with 'MOD_' within the environment." echo "Note: You cannot edit the variables here, only view." echo echo "Development shell opening." echo PS1="Pre-boot Shell (3/3): # " /bin/ash fi # Load a stage 2 post execution script if the user created it from the PBS: [ -s /pbs_stage2.post ] && . /pbs_stage2.post