#!/bin/bash

# Copyright 2021  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 <mozes@slackware.com>
# 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.
#########################################################################
# 
# This script has been modified by the SARPi Project.
#
# Exaga - sarpi.penthux.net - 20 Feb 2024
#
######

# Quit if user configurable flag file is present
[ ! -f /.norun-os-initrd-mgr ] && exit 0;

# 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
}

# Collapse all 32bit ARM & x86 variants of 'i?86' into a single
# platform: 'x86' and 'arm' respectively.
ARCH=$( uname -m | sed -e 's%i[0-9]86%x86%g' -e 's?arm.*?arm?g' )

# 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
grep -iq "slkpbs" /proc/cmdline 2> /dev/null && PREBOOTSHELL=Yes

# 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_hcd hid \
          ehci-platform ehci-pci xhci-hcd xhci-pci"

# USB hubs and some specific device drivers:
export MOD_USB="$MOD_USB ums-cypress ums-usbat ums-freecom \
          ums-isd200 ums-sddr09 ums-sddr55 ums-alauda ums-jumpshot \
          ums-onetouch"

# 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"

# 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 for System on Chip stuff:
export MOD_SOC=""

# Generic modules for the physical layer:
export MOD_PHY=""

# Filesystems:
export MOD_FS="vfat ext2 ext3 ext4 btrfs reiserfs jfs xfs fscache"

# Generic SCSI drivers & low-level drivers for discs/media:
# 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.
export MOD_SCSI="sg scsi_mod sd_mod cdrom sr_mod virtio_blk"

# Network filesystems:
export MOD_NETFS="nfs lockd"

# Network interface cards:
# USB (Mac) dongle
export MOD_NETDEV="usbnet"
#export MOD_NETDEV=""

# 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:
# http://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.

if [ -f /proc/device-tree/model ]; then
   export DEVTYPE=$( strings /proc/device-tree/model 2>/dev/null )
   unset platform_detected
   for platformscr in /load_kernel_modules.scr/platform/$ARCH/* ; do
      . $platformscr ;
   done
 else
   echo "WARNING: unable to detect system type from /proc/device-tree/model"
   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 4
fi

if [ -z "$platform_detected" ]; then
   [ ! -z "$DEVTYPE" ] && DEVTYPE="(${DEVTYPE})"
   echo "WARNING: Unsupported $ARCH Hardware Model $DEVTYPE"
   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 "          http://arm.slackware.com/slackwarearm-devel/"
   sleep 4
fi

# If the token 'slkpbs' is set in the Kernel command line, open a shell:
if [ "$PREBOOTSHELL" = "Yes" ]; then
   echo "Stage 1 of 2: Pre module loading."
   echo "Development shell opening."
   echo "Exit shell to proceed to the next stage in the module loading"
   echo "process."
   echo
   echo "Module variables are prefixed with 'MOD_'"
   echo "Note: You cannot edit the variables here, only view."
   echo
   PS1="Pre-boot shell: # " /bin/ash
fi

# User serviceable pre module load hook:
#
loadhook /load_kernel_modules.pre-modload

# Load the modules:
for mod in $MOD_BASE $MOD_SOC $MOD_PHY \
           $MOD_SATA $MOD_USB $MOD_USBSTORAGESUB $MOD_SCSI $MOD_CARDS \
           $MOD_STORAGEDEVICELAYERS \
           $MOD_RTC $MOD_VIDEO \
           $MOD_FS \
           $MOD_NETFS $MOD_NETDEV ; do
   modprobe $mod
done

# If the token 'slkpbs' is set in the Kernel command line, open a shell:
if [ "$PREBOOTSHELL" = "Yes" ]; then
   echo "Stage 2 of 2: Post module loading"
   echo "Development shell opening."
   echo "Exit shell to proceed to the next stage in the module loading"
   echo "process."
   echo
   echo "Development shell opening"
   echo "Module variables are prefixed with 'MOD_'"
   echo "Note: You cannot edit the variables here, only view."
   echo
   PS1="Pre-boot shell: # " /bin/ash
fi

# User serviceable post module load hook:
loadhook /load_kernel_modules.post
