#!/bin/bash
set +o posix
shopt -s extglob

##########################################################################
# Script : kernel.SlackBuild
# Purpose: Natively build and package the Linux Kernel for Slackware ARM
# Author : Stuart Winter <mozes@slackware.com>
# Date...: 10-Feb-2022
##########################################################################
# Changelog
############
# 10-Feb-22:
#  Build a/kernel-modules & d/kernel-headers package to reduce build time
#  for Kernel packages, and ease maintenance of stable releases.
# 20-Apr-21:
#  Updated for AArch64.
#  Removed legacy ARM initrd creation code.
# 01-Apr-2018:
#  * Handle building Kernels in /patches
#  * Simplify and remove duplication of code.
# 20-Sep-2005
#  * First version for Linux 2.6.13.1 on the StrongARM RiscPC
# 31-Dec-2005
#   * Linux 2.6.14.5
##########################################################################
#
# Copyright 2005-2022  Stuart Winter, Surrey, England, UK.
# 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.
#

# Record toolchain & other info for the build log:
slackbuildinfo

# Paths to skeleton port's source & real Slackware source tree:
export CWD=$PWD

# Detect whether we're building for /patches:  This function sets the variable 'SLACKPATCHING'
slack_findpkgstore_is_stablerelease
echo "Building in /patches/? $SLACKPATCHING"

# Temporary build locations:
export TMPBUILD=$TMP/build-$PKGNAM
export PKG=$TMP/package-$PKGNAM
# Delete & re-create temporary directories then cd into $TMPBUILD
mkpkgdirs

# When using xz with tar, set the options:
export XZ_OPTS="--threads $(( $(nproc) -1 )) -ze9f -C crc32"

# Extract the kernel source:
echo -n "Extracting Kernel source... "
tar xf $CWD/sources/linux-*.tar.xz || exit 1
echo "done"
# Make the source tree dir name match $VERSION (useful for rc releases)
mv -fv linux-* linux-$VERSION
cd linux-*/ || exit 1
slackhousekeeping

# Install the appropriate Kernel config file:
install -vpm644 $CWD/configs/config-$SLKKERNELARCH .config

# Remove any hyphen from the EXTRAVERSION name.
sed -i '/EXTRAVERSION *=/s/-//g' Makefile

# Ensure that the Kernel version reported in the Makefile matches
# the version in the package name that we plan to use.
#
# If we're doing builds of RC kernels, we can ignore this check and assume we performed the
# necessary due dilligence.  Non-RC releases have no 'EXTRAVERSION' value set.
#
if ! echo "$VERSION" | egrep "rc|next" ; then
   if [ "$( echo "$(sed -ne's/^VERSION *= *//p' Makefile).$(sed -ne's/^PATCHLEVEL *= *//p' Makefile).$(sed -ne's/^SUBLEVEL *= *//p' Makefile)" )" != $VERSION ]; then
      echo "**** Package name vs Kernel version mismatch ****"
      echo "*** Slackware Packaging Version: $VERSION"
      echo "*** Kernel versions (From files): $( sed -ne's/^VERSION *= *//p' Makefile).$(sed -ne's/^PATCHLEVEL *= *//p' Makefile).$(sed -ne's/^SUBLEVEL *= *//p' Makefile )"
      exit 1
   fi
fi

echo "Kernel Slackware package version: $VERSION"

# Apply patches:
for i in $CWD/sources/patches/!(*debian*|*no-autopatch*)xz ; do
   auto_apply_patch $i || exit 1
done
#for i in $CWD/sources/patches/H3/* ; do xzcat $i | patch --verbose -p1 ; done
#[ "$SLKPORTARCH" = "aarch64" ] && { auto_apply_patch $CWD/sources/patches/0103-futex-no-autopatch.patch.xz || failpatch ;}

# For GCC-10:
sed -i "s/--param=allow-store-data-races=0/-fno-allow-store-data-races/g" Makefile

#tar xvvf $CWD/sources/patches/linux*debian*z
#for i in debian/patches/features/arm/* ; do
#   auto_apply_patch $i || exit 1
#done
#for i in debian/patches/bugfix/arm/* ; do
#   auto_apply_patch $i || exit 1
#done

# Build Kernel
echo "Cleaning Kernel.."
make clean
echo "******************************"
echo "*** Building kernel Image  ***"
echo "******************************"

[ "$SLKPORTARCH" = "arm" ] && \
   { make $NUMJOBS ARCH=$LINUXKERNELARCH CONFIG_DEBUG_SECTION_MISMATCH=y zImage || failmake ;}
[ "$SLKPORTARCH" = "aarch64" ] && \
  { make $NUMJOBS ARCH=$LINUXKERNELARCH CONFIG_DEBUG_SECTION_MISMATCH=y Image || failmake ;}

# Build modules:
echo "************************"
echo "*** Building modules ***"
echo "************************"
make $NUMJOBS ARCH=$LINUXKERNELARCH CONFIG_DEBUG_SECTION_MISMATCH=y modules || failmake

# Archive the compiled kernel source - this is used to create the kernel-source package.
# The reason why we check the architecture is because with the soft float port we had
# multiple kernels, but there was no need to have multiple Kernel sources.
# With the hard float and aarch64 port, we have just one Kernel; but in case we end up with
# more than one Kernel in the future, we'll keep this check in place.
# "SLKKERNELARCH" is the _package_ name architecture not the OS architecture - e.g. it'd be "armv5", "armv7", "armv8"
# e.g. the ARM port's packages are named "foo-1.0-arm-1.txz", but this particular _package_ will only run
# on armv7 or greater, so its specific package architecture is "armv7".
# If there is a case to require >1 kernel per arch again, there should be
# a kernel-source package for it, since it would be required to build modules that we don't ship, but
# that can easily be added by the user.
#
# The kernel-source package is now built at the end of this process rather than
# from a separate build script.
#if [[ "${SLKKERNELARCH}" =~ (armv7|armv8) ]]; then
#   echo "Archiving compiled source for kernel-source package..."
#   # This takes far too long on ARM. I'll let the Distro polishing script pack this one:
#   # ( cd .. && tar -Ixz -pcf $CWD/compiled-sources/$SLKKERNELARCH-kernel-$VERSION-compiled.tar.xz linux-$VERSION )
#   ( cd .. && tar pcf $CWD/compiled-sources/$SLKKERNELARCH-kernel-$VERSION-compiled.tar linux-$VERSION )
#fi

echo "Installing Kernel includes for package d/kernel-headers..."
# Create package structure:
mkdir -vpm755 $TMPBUILD/package-kernel-headers/{install,usr}
# Install 'sanitised' headers:
make ARCH=$LINUXKERNELARCH \
     INSTALL_HDR_PATH=$TMPBUILD/package-kernel-headers/usr \
     headers_install || failinstall
( cd $TMPBUILD/package-kernel-headers || exit 1
  # Wipe these '.install' and '..install.cmd' files
  find . -iname '.*' -type f -print0 | xargs -0 rm -f )
# Not anymore - the glibc build uses the Kernel package headers.
#  echo "Archiving kernel-headers for use with glibc"
#  mkdir -vpm755 $CWD/sources/kernel-headers
#  time tar -Ixz -pcf $CWD/sources/kernel-headers/$SLKKERNELARCH-kernel-headers-$VERSION.tar.xz . )

# Install modules into the package:
make ARCH=$LINUXKERNELARCH modules_install INSTALL_MOD_PATH=$PKG || exit 1

# We'll install the Kernel modules to the OS once they have been
# compressed within $PKG:
rm -rf /lib/modules/$VERSION-$SLKKERNELARCH
# Needed for mkinitrd to find the modules, but we'll install
# the compressed versions from $PKG since it cuts down on build time.
#make ARCH=$LINUXKERNELARCH modules_install || exit 1

# Wipe the firmware from the package since it's included in the a/kernel-firmware package
# and dealt with above:
echo "Wiping /lib/firmware from the current package contents so that"
echo "it won't be included in the a/kernel-modules package ..."
rm -rf $PKG/lib/firmware

# Compress the Kernel modules that have been installed into the
# package:
echo "Compressing package's Kernel modules with xz -e9 -- this will take 10-15 mins.."
pushd $PKG
   time find ./lib/modules -type f -name "*.ko" -exec xz $XZ_OPTS {} \;
   # Fix symlinks now that the Kernel modules have a .xz suffix:
   for i in $(find ./lib/modules -type l -name "*.ko") ; do ln -vfs $( readlink $i ).xz $i.xz ; rm -fv $i ; done

   # Install the newly-compressed Kernel modules into the OS:
   echo "Installing compressed Kernel modules into /lib/modules for the running OS"
   time cp -fa ./lib/modules/$VERSION-$SLKKERNELARCH /lib/modules/
popd

# Compress OS's copy of the Linux kernel modules to reduce the size of the initrd.
#echo "Compressing Host OS' Kernel modules (for $SLKKERNELARCH) with xz -e9 -- this will take 10-15 mins.."
##find /lib/modules/$VERSION-$SLKKERNELARCH -type f -name "*.ko" -exec gzip -9f {} \;
#time find /lib/modules -type f -name "*.ko" -exec xz $XZ_OPTS \;
#for i in $(find /lib/modules/$VERSION-$SLKKERNELARCH -type l -name "*.ko") ; do ln -vfs $( readlink $i ).xz $i.xz ; rm -fv $i ; done

# Archive the Kernel modules for the Slackware 'a/kernel-modules'
# package:
# To be removed - we create the kernel-modules package from this
# build script.
#if [ "$SLACKPATCHING" = "no" ]; then
##   ( cd $PKG && tar -Ixz -pcf $CWD/../a/kernel-modules/sources/$SLKKERNELARCH-kernel-modules-$VERSION.tar.xz lib/ )
#   # We don't create a compressed archive here since the only contents are Kernel modules
#   # which are already LZMA compressed:
#   time ( cd $PKG && tar pcf $CWD/../a/kernel-modules/sources/$SLKKERNELARCH-kernel-modules-$VERSION.tar lib/ )
# else
##   ( cd $PKG && tar -Ixz -pcf $CWD/../kernel-modules/sources/$SLKKERNELARCH-kernel-modules-$VERSION.tar.xz lib/ )
#   time ( cd $PKG && tar pcf $CWD/../kernel-modules/sources/$SLKKERNELARCH-kernel-modules-$VERSION.tar lib/ )
#fi

## Usually we'd do this inside the resulting package but we need the modules
## to be up to date on the live system so that mkinitrd can grab what it needs:
( cd /
  echo "Updating host OS' module dependencies for $VERSION-$SLKKERNELARCH"
  find lib/modules -name $VERSION-$SLKKERNELARCH -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b. )

# Install the kernel image and system map:
mkdir -vpm755 $PKG/{install,boot}

# Building zImage for ARM creates Image, and subsequently
# compresses it.  Since we don't ship the uncompressed version
# for ARM, we'll delete it so that it doesn't get included
# by the search code below.
[ "$SLKPORTARCH" = "arm" ] && rm -f arch/$LINUXKERNELARCH/boot/Image

#gzip -f9cv System.map > $PKG/boot/System.map-$SLKKERNELARCH-$VERSION.gz
# These are named after their respective architectures so that you
# can have more than 1 Kernel package installed on the system
# at any one time, and configure your boot loader to boot, say
# "/uImage-", and not then have to maintain Kernel version
# numbers.
# We'll wipe the ones we don't need for this architecture a bit
# further down.
install -vpm644 System.map $PKG/boot/System.map-$SLKKERNELARCH-$VERSION
for imgtype in {,z,u}Image ; do
   [ -f arch/$LINUXKERNELARCH/boot/$imgtype ] && \
   install -vpm644 arch/$LINUXKERNELARCH/boot/$imgtype $PKG/boot/$imgtype-$SLKKERNELARCH-$VERSION
done
# Make symlinks:
( cd $PKG/boot
  ln -vfs System.map-$SLKKERNELARCH-$VERSION System.map-$SLKKERNELARCH
  for imgtype in {,z,u}Image ; do
     [ -f $imgtype-$SLKKERNELARCH-$VERSION ] && \
     ln -vfs $imgtype-$SLKKERNELARCH-$VERSION $imgtype-$SLKKERNELARCH
  done )

# The Kernel config file used (following the Slackware standard):
install -pvm644 .config $PKG/boot/config-$SLKKERNELARCH-$VERSION

# The package description:
install -pvm644 $CWD/slack-descs/$SLKKERNELARCH-kernel $PKG/install/slack-desc
# The script to handle appending DTB files to systems that have the
# 'dtb=' kernel paramater specified:
# Not needed for hard float port since all of the U-Boot versions are new enough
# to handle loading a DTB, but we'll leave this in here and let it error out.
install -pvm644 $CWD/sources/doinst.sh $PKG/install/

# Copy the Kernel into our tree's 'kernels' directory:
# If you want to keep these, move the old one out of the way first
# otherwise it gets clobbered.
if [ "$SLACKPATCHING" = "no" ]; then
   mkdir -vpm755 $PKGSTORE/../kernels/$SLKKERNELARCH

   for imgtype in {,z,u}Image ; do
        [ -f arch/$LINUXKERNELARCH/boot/$imgtype ] && \
        install -vpm644 arch/$LINUXKERNELARCH/boot/$imgtype \
                       $PKGSTORE/../kernels/$SLKKERNELARCH/$imgtype-$SLKKERNELARCH
   done

   # This is really for the installer build script:
   gzip -f9cv System.map  > $PKGSTORE/../kernels/$SLKKERNELARCH/System.map.gz

   # And because Slackware includes the kernel config, let's do it too!
   install -vpm644 .config $PKGSTORE/../kernels/$SLKKERNELARCH/config
fi

# Make an initrd for the architecture.
# Unpack the generic Slackware Initial RAM disk ('OS initrd') tree:
rm -rf $TMPBUILD/initrd-tree
mkdir -vpm755 $TMPBUILD/initrd-tree
tar xf /usr/share/mkinitrd/initrd-tree.tar.gz -C $TMPBUILD/initrd-tree

# Unpack bash, ncurses, jfsutils and xfsprogs as we need a few
# components:
mkdir -p $TMPBUILD/pkg-extract
pushd $TMPBUILD/pkg-extract
   explodepkg $PKGSTORE/a/bash-+([^-])-+([^-])-+([^-]).t[gblx]z
   explodepkg $PKGSTORE/l/ncurses-+([^-])-+([^-])-+([^-]).t[gblx]z
   sh install/doinst.sh # set up symlinks for ncurses
   explodepkg $PKGSTORE/a/jfsutils-+([^-])-+([^-])-+([^-]).t[gblx]z
   explodepkg $PKGSTORE/a/xfsprogs-+([^-])-+([^-])-+([^-]).t[gblx]z
   explodepkg $PKGSTORE/a/util-linux-+([^-])-+([^-])-+([^-]).t[gblx]z
   sh install/doinst.sh # set up symlinks for util-linux

   # Install libtinfo from ncurses:
   mkdir -vpm755 $TMPBUILD/initrd-tree/lib${LIBDIRSUFFIX}
   cp -fav lib${LIBDIRSUFFIX}/libtinfo.so* $TMPBUILD/initrd-tree/lib${LIBDIRSUFFIX}/

   # Install lsblk and its dependencies from the a/util-linux package:
   # This is used by the 'await_device' to find labeled file systems.
   cp -fav bin/lsblk $TMPBUILD/initrd-tree/bin/
   cp -fav lib${LIBDIRSUFFIX}/libmount.so.* $TMPBUILD/initrd-tree/lib${LIBDIRSUFFIX}/
   cp -fav lib${LIBDIRSUFFIX}/libsmartcols.so.* $TMPBUILD/initrd-tree/lib${LIBDIRSUFFIX}/

   # Support custom keymaps:
   install -vpm644 /usr/share/mkinitrd/keymaps.tar.gz $TMPBUILD/initrd-tree/etc/

   # These are added by Slackware's 'mkinitrd' if these modules are required.
   # We'll add them as standard, since we bundle the modules in the generic
   # initrd.
   install -Dvpm755 sbin/{xfs_repair,jfs_fsck} -t $TMPBUILD/initrd-tree/sbin/

   # Use the 'bash' shell instead of busybox, as Slackware ARM uses the
   # richer feature set to make the module loader scripts more succinct:
   rm -f $TMPBUILD/initrd-tree/bin/bash # is a symlink to busybox
   # /init needs to use bash as we use some of the extended features:
   sed -i 's?#!/bin/ash?#!/bin/bash?g' $TMPBUILD/initrd-tree/init
   install -vpm755 bin/bash* $TMPBUILD/initrd-tree/bin/bash

   # Helper to wait for the root device to become available:
   sed -i '\?^sleep \$WAIT*? a\. /await_device' $TMPBUILD/initrd-tree/init || exit 1
   install -vpm755 $CWD/SlkOS-initrd-overlay/await_device $TMPBUILD/initrd-tree/

   # Support execution of a function prior to switching into the OS proper:
   # This could be defined within a Hardware Model's Kernel Module Loader helper
   # script, or perhaps within the /boot/local/load_kernel_modules.post.
   # This is the last chance before the OS proper boots, and it's post software RAID
   # et al initialisation.
   sed -i '\?exec switch_root ?i\fnexists hwm_hook_pre_switch_root && hwm_hook_pre_switch_root' $TMPBUILD/initrd-tree/init || exit 1
   sed -i '\?exec switch_root ?i\fnexists hook_pre_switch_root && hook_pre_switch_root' $TMPBUILD/initrd-tree/init || exit 1

   # Wrap reboot to call the reboot binary with -f(orce).  This is required because the
   # OS environment isn't fully established:
   # This wraps the binary because /usr/local/sbin is ahead of /sbin in $PATH
   mkdir -vpm755 $TMPBUILD/initrd-tree/usr/local/sbin
   echo "/sbin/reboot -f" > $TMPBUILD/initrd-tree/usr/local/sbin/reboot
   chmod 755 $TMPBUILD/initrd-tree/usr/local/sbin/reboot
popd

# Use mkinitrd to create a default environment:
cd $TMPBUILD

echo "Calling mkinitrd: creating a default Slackware initrd environment"
MKINITRD_ALLOWEXEC=yes mkinitrd \
  -R \
  -L \
  -u \
  -k $VERSION-$SLKKERNELARCH \
  -s $TMPBUILD/initrd-tree \
  -o $TMPBUILD/initrdtmp.gz

# Sanity check that mkinitrd created some output:
[ ! -f $TMPBUILD/initrdtmp.gz ] && {
   read -p "ERROR: creation of temporary Initial RAM disk failed"
   exit 1 ;}

# Switch to that new environment.
# At this stage, we've
# 1. Unpacked the standard Slackware initrd environment that's packaged
#    within the a/mkinitrd package
# 2. Added 'bash' and a library from 'ncurses' to that environment
# 3. Used the mkinitrd tool to populate that enviromnemt with the default
#    set of runtime libraries, taken from the host build system.
# 4. Now we're going to switch to that new environment and continue
#    populating it to become the generic ARM OS InitRD.
mv -fv $TMPBUILD/initrd-tree{,.orig}
mkdir -vpm755 $TMPBUILD/initrd-tree
cd $TMPBUILD/initrd-tree
# Unpack the newly built initrd image into the fresh initrd root fs:
zcat $TMPBUILD/initrdtmp.gz | cpio -di

echo "Copying packaged Kernel modules into OS initrd"
rm -rf lib/modules/ # clean what the mkinitrd populated here
mkdir -vpm755 lib/modules/
cp -fa $PKG/lib/modules/* lib/modules/

# Slim down the modules within the initrd by removing unnecessary
# major sub systems or drivers for hardware that is not required during
# the initial boot.
# There will be far more that are also surplus to requirements but I'm
# trying to strike a balance between size and enabling the community to
# more easily light up Slackware AArch64 onto new platforms.
#
pushd lib/modules/*/kernel
   rm -rfv sound
   rm -rfv drivers/{bluetooth,interconnect,mailbox}
   rm -rfv drivers/{perf,ptp,soundwire,thermal}
   rm -rfv drivers/net/{wireless,can,ipa}
   rm -rfv fs/{ntfs}
   rm -rfv net/{802,8021q,bluetooth,bridge,can,dsa,mac80211,netfilter,nfc,wireless}
popd

echo "Compressing initrd's Kernel modules with xz -e9 -- this will take 10-15 mins.."
#time find ./lib/modules -type f -name "*.ko" -exec xz --threads $(( $(nproc) -1 )) -ze9f -C crc32 {} \;
time find ./lib/modules -type f -name "*.ko" -exec xz $XZ_OPTS {} \;
# Fix any broken symlinks post compression:
for i in $(find ./lib/modules -type l -name "*.ko") ; do ln -vfs $( readlink $i ).xz $i.xz ; rm -fv $i ; done

# Kernel Module loader for Slackware AArch64.  This loads a base set of
# platform modules generally useful on all SoCs, and at boot time
# loads specific SoC modules for the host platform.
# If you want to add support for a new platform, please look at this
# script and give mozes@slackware.com a diff.
install -vpm755 $CWD/SlkOS-initrd-overlay/load_kernel_modules .
# Install the board support scripts:
mkdir -vpm755 load_kernel_modules.scr/platform/$SLKPORTARCH
install -vpm755 $CWD/SlkOS-initrd-overlay/load_kernel_modules.scr/platform/$SLKPORTARCH/* \
                load_kernel_modules.scr/platform/$SLKPORTARCH/

# Walk the host architecture, calling the helper scripts to
# perform any Hardware Model specific actions.
if [ -d  $CWD/platform/$SLKPORTARCH ]; then
   for helper in $( find $CWD/platform/$SLKPORTARCH -type f -mindepth 1 -maxdepth 1 ) ; do
      echo "Executing Kernel Build helper for ${helper##*/}"
      . $helper
   done
fi

# Generic initrd configuration:
> rootdev # both are controlled by the Kernel cmdline parameters since
> rootfs  # this is a generic platform initrd.
echo 4 > wait-for-root # media spinup delay
echo "/boot/initrd-$SLKKERNELARCH.gz" > initrd-name
rm -f command_line # it was a temporary build - useless info

# Shipping the Software RAID configuration of a build machine
# doesn't make sense.  /init tries to set up Software RAID itself
# but users can also use the os-initrd-mgr tool to manage the
# addition and removal of the OS's /etc/mdadm.conf.
rm -f etc/mdadm.conf

# Update the indexes so we can boot this baby:
echo "Updating linker cache and Kernel module maps...."
ldconfig -r.
depmod -b. $VERSION-$SLKKERNELARCH

# Pack into initramfs format:
# The kernel panics when I pack this with XZ, despite having support
# compiled in.
#find . | cpio -o -H newc | xz -ze9 > /boot/initrd-armv8
# So we'll use gzip:
find . | cpio -o -H newc | gzip -9 > $TMPBUILD/initrd-$SLKKERNELARCH.gz

# Store the size of the initrd uncompressed, so that the
# /usr/sbin/os-initrd-mgr knows how much temp space to allocate
# when repacking the OS initrd to include any user local additions:
cat << EOF > $PKG/boot/.boot_details
# This file was created originally by source/k/kernel.SlackBuild
# during the Kernel package build process, and potentially updated
# by /usr/sbin/os-initrd-mgr.
#
#
# Do not edit this file by hand!
#
#
# Size of the OS InitRD in bytes.  This is used for os-initrd-mgr to
# determine whether it can safely unpack the initrd.
initrdsize=$( du -sb . | awk '{print $1}' )
# ARM architecture version.  This allows os-initrd-mgr to rebuild
# the initrd via the symlink /boot/initrd-armvN.
# armv7 = "Slackware ARM"
# armv8 = "Slackware AArch64"
platform=$SLKKERNELARCH
EOF
# Add the sample scripts:
install -Dvpm644 $CWD/boot-skeleton/local/* -t $PKG/boot/local/
# Add the Hardware Model post Kernel package installation helper scripts.
# There aren't any for ARM presently:
[ "$SLKPORTARCH" = "aarch64" ] && {
   install -Dvpm644 $CWD/boot-skeleton/platform/aarch64/helper/README.txt -t $PKG/boot/platform/aarch64/helper/
   # We may store other types of helper scripts here in the future, so
   # we'll take only our 'kernel' helpers:
   install -Dvpm755 $CWD/boot-skeleton/platform/aarch64/helper/pkg-kernel-* -t $PKG/boot/platform/aarch64/helper/
}

# Add the initrd manager:
install -Dvpm755 $CWD/sources/os-initrd-mgr -t $PKG/usr/sbin/
mkdir -vpm755 $PKG/usr/man/man8
pod2man \
   --section=8  \
   --release="$( grep -E ' Date.*:' $CWD/sources/os-initrd-mgr | awk -F: '{ print $2 }' )" \
   --center=' ' \
   --date="os-initrd-mgr Version $( grep -E ' Version.*: ' $CWD/sources/os-initrd-mgr | awk -F: '{ print $2 }' )" \
   $CWD/sources/os-initrd-mgr.pod 2>&1 | gzip -9f > $PKG/usr/man/man8/os-initrd-mgr.8.gz

# Store the standard gzipped initial RAM disk, plus its U-Boot format counterpart:
#
# 1. Within the 'slackware-current/kernels' directory.
#
# When building patch packages, we never provide an updated version of this file outside of the
# package archive.  This is because files in the '/kernels' directory are generally for
# use with the Slackware installer image, and we normally don't update those once the
# Slackware version is released (as they'd be different versions to those in the main
# 'slackware/' tree).
if [ "$SLACKPATCHING" = "no" ]; then
   for imgtype in {,u}initrd ; do
      [ -f $TMPBUILD/${imgtype}-$SLKKERNELARCH.gz ] && \
      install -vpm644 $TMPBUILD/${imgtype}-$SLKKERNELARCH.gz \
                      $PKGSTORE/../kernels/$SLKKERNELARCH/${imgtype}-$SLKKERNELARCH
   done
fi

# 2. Within $PKG/boot
#
# This allows devices whose boot loader can read the partition where /boot resides
# (all Directly Integrated Hardware Model support):
[ -f $TMPBUILD/uinitrd-$SLKKERNELARCH ] && \
   install -vpm644 $TMPBUILD/uinitrd-$SLKKERNELARCH $PKG/boot/uinitrd-$SLKKERNELARCH-$VERSION
# The gzipped compressed cpio version:
install -vpm644 $TMPBUILD/initrd-$SLKKERNELARCH.gz $PKG/boot/initrd-$SLKKERNELARCH-$VERSION

# Create symlinks to enable static boot loader configuration:
# (having version numbers would necessitate a boot loader change with every
# Kernel package release):
( cd $PKG/boot
 for imgtype in {,u}initrd ; do
     [ -f $imgtype-$SLKKERNELARCH-$VERSION ] && \
     ln -vfs $imgtype-$SLKKERNELARCH-$VERSION $imgtype-$SLKKERNELARCH
  done )

# It's nice to have this final touch (pun intended):
#if [ "$SLACKPATCHING" = "no" ]; then
#   ( cd $PKGSTORE/../kernels/$SLKKERNELARCH/
#     for imgtype in {,z,u}Image ; do
#        [ -f $imgtype-$SLKKERNELARCH ] && \
#          touch -r $imgtype-$SLKKERNELARCH * $PKG/boot/*
#     done )
#fi

# Compile the Device Tree Source (DTS) files into Device Tree Blobs (DTB):
# This file is for the 'Flattened Device Tree' technology.
# For the generic 'armv7' kernels, we have no way of knowing which DTB file
# the user will require, so we have to ship them all for each architecture.
#
mkdir -vpm755 $PKG/{install,boot/dtb-$VERSION}
ln -rvfs $PKG/boot/dtb-$VERSION $PKG/boot/dtb

# Ensure that we're in the correct directory to build the DTB files.
cd $TMPBUILD/linux-$VERSION && make ARCH=$LINUXKERNELARCH dtbs || failmake

# Install them to a temporary directory.  The make install
# creates a 'dtbs' directory within the specified path.
make INSTALL_PATH=$TMPBUILD dtbs_install || failmake

# Copy the extra ones that are not yet in the mainline kernel.  These are only for
# armv7:
# This was for an experiment where I was using a forked Kernel tree.
#if [ "$SLKKERNELARCH" = "armv7" ]; then
#  echo "Adding extra DTBs from $CWD/sources/extra-dtb/ (if any exist)"
#  cp -fav $CWD/sources/extra-dtb/*.dtb $TMPBUILD/linux-$VERSION/arch/$LINUXKERNELARCH/boot/dts/
#fi

# Install DTB's into the package:
#install -vpm644 $TMPBUILD/linux-$VERSION/arch/$LINUXKERNELARCH/boot/dts/*.dtb $PKG/boot/dtb-$VERSION/
# AArch64 groups the DTBs by platform type, unlike ARM where they're in a
# flat level directory structure.
# The directory structure is: $TMPBUILD/dtbs/5.10.21-armv8
cp -fa $TMPBUILD/dtbs/*/* $PKG/boot/dtb-$VERSION/ || failinstall

# Install copies into the 'kernels' directory so that they can be easily
# available for tftp booting:
# We don't version the DTB files inside the '/kernels' directory because
# the kernel + initrd files are not versioned here since this dir is not
# packaged/version managed.
if [ "$SLACKPATCHING" = "no" ]; then
   rm -rf $PKGSTORE/../kernels/$SLKKERNELARCH/dtb
   mkdir -vpm755 $PKGSTORE/../kernels/$SLKKERNELARCH/dtb
   cp -fa $TMPBUILD/dtbs/*/* $PKGSTORE/../kernels/$SLKKERNELARCH/dtb/ || failinstall
   #install -vpm644 -oroot -groot $PKG/boot/dtb-$VERSION/* $PKGSTORE/../kernels/$SLKKERNELARCH/dtb/
fi

# Move the Kernel modules into their own package:
cd $PKG
mkdir -vpm755 $TMPBUILD/package-kernel-modules/install
mv -fv lib $TMPBUILD/package-kernel-modules/

###############################################################################
# Build the base 'a/kernel' package:
###############################################################################
echo "*****************************************************************"
echo "Building base package slackware/a/$SLACKPACKAGE"
echo "*****************************************************************"

# Replace version number with a _ so it doesn't get confused with
# the package name.
# This is incase we're using any '-rc' releases.
export VERSION="$( echo $VERSION | sed 's?-??g' )"

cd $PKG

# Apply some of the generic Slackware packaging policies:
slackslack  # chown -R root:root, chmod -R og-w, slackchown, slack644docs

# We need to pre-pend the symlink code to the main 'doinst.sh' since it requires the
# versionless symlinks for /usr/sbin/os-initrd-mgr
#makepkg -p -l y -c n $PKGSTORE/$PKGSERIES/$PKGNAM-$VERSION-$SLKPORTARCH-$BUILD.txz
slackmp -p # run makepkg --prepend -l y -c n

###############################################################################
# Build the 'a/kernel-modules' package:
###############################################################################
# Set the package name to the particular architecture we're currently processing:
# I don't know why I had this - it makes no sense to have a package named
# "kernel-modules-kirkwood-2.6.38.2_kirkwood-arm-2.t?z"
# export SLACKPACKAGE=$PKGNAM-$ARCHTYPE-${VERSION}-$PKGARCH-$BUILD.t?z
# I do now, this matches the naming scheme for Slackware x86's "smp" kernel package.
# Even though the package name is different thus indeed creates a separate package,
# it breaks the installer build script and since the x86 package will remain with the
# same naming convention, it makes no sense to break it all here!
export PKGNAM=kernel-modules
[ $SLACKPATCHING = "no" ] && export PKGSERIES=a
export SLACKPACKAGE=$PKGNAM-$SLKKERNELARCH-${VERSION}_${SLKKERNELARCH}-$PKGARCH-$BUILD.txz

echo "*****************************************************************"
echo "Building package: $SLACKPACKAGE"
echo "*****************************************************************"

cd $TMPBUILD/package-kernel-modules

# Install package description:
install -vpm644 $CWD/slack-descs/$SLKKERNELARCH-kernel-modules install/slack-desc

# Install the post install script.
# This is taken from Slackware's kernel-modules.SlackBuild script:
cat << EOF > install/doinst.sh
# A good idea whenever kernel modules are added or changed:
if [ -x sbin/depmod ]; then
  chroot . /sbin/depmod -a $VERSION-$SLKKERNELARCH 1> /dev/null 2> /dev/null
fi

EOF

# This is a symlink to where the kernel was compiled
# We wipe these and create new ones pointing to /usr/src
# (our kernels were compiled in a temporary location, so the symlink would be broken)
# The symlinks looked like this:
# /lib/modules/<ver>/build -> /root/tmp/build-kernel_armv7/linux-5.15.19
# Why don't we just make the symlink using the existing variables?
# That's because at the time of writing I'm taking this from the old kernel-modules.SlackBuild
# and my guess is that at some points, the dir name might not be what we expected.
pushd lib/modules/*
LINKLOC=$( find . -name source -printf "%l\n" | rev | cut -d/ -f1 | rev )
rm -rf source
ln -vfs ../../../usr/src/$LINKLOC source
LINKLOC=$( find . -name build -printf "%l\n" | rev | cut -d/ -f1 | rev )
rm -rf build
ln -vfs ../../../usr/src/$LINKLOC build
popd

# Update the dependencies list:
# depmod -b $PKG $VERSION
# Generate modules.dep files for each ARM architecture we have inside lib/modules.
# This is legacy from when we had the all-in-one script, but I like it so it stays :-)
find lib/modules -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b.

# Handle building within /patches:
# This shouldn't be needed and I want all patches to be placed into
# /tmp/patches for future automation.
#if [ $SLACKPATCHING = "no" ]; then
#   export PKGSERIES=k
# else
#   export PKGSERIES=patches
#   export PKGSTORE=/tmp/
#   mkdir -vpm755 $PKGSTORE/$PKGSERIES
#fi

# Apply some of the generic Slackware packaging policies:
slackslack  # chown -R root:root, chmod -R og-w, slackchown, slack644docs

# run makepkg -l y -c n
slackmp

###############################################################################
# Build the 'd/kernel-headers' package:
###############################################################################

# The headers are installed into the root of this package earlier
# in the Kernel build process, so all we need here is to install the
# slack-desc and set permissions.

# Package information:
export PKGNAM=kernel-headers
export SLACKPACKAGE=$PKGNAM-$VERSION-$PKGARCH-$BUILD.txz

echo "*****************************************************************"
echo "Building package: $SLACKPACKAGE"
echo "*****************************************************************"

# Handle building within /patches:
[ $SLACKPATCHING = "no" ] && export PKGSERIES=d

# Enter package root:
cd $TMPBUILD/package-kernel-headers || exit 1

# Install package description:
install -vpm644 $CWD/slack-descs/kernel-headers install/slack-desc

# Apply some of the generic Slackware packaging policies:
slackslack  # chown -R root:root, chmod -R og-w, slackchown, slack644docs

echo " + Running makepkg for 'kernel-headers'"
slackmp # run makepkg

###############################################################################
# Build the 'k/kernel-source' package:
###############################################################################

# Package information:
export PKGNAM=kernel-source
export SLACKPACKAGE=$PKGNAM-$VERSION-$PKGARCH-$BUILD.txz

echo "*****************************************************************"
echo "Building package: $SLACKPACKAGE"
echo "*****************************************************************"

# Handle building within /patches:
[ $SLACKPATCHING = "no" ] && export PKGSERIES=k

# Move the Kernel source into a directory into which we can package it:
cd $TMPBUILD

# Prepare the package framework:
mkdir -vpm755 package-kernel-source/{install,usr/src}

# Move the Linux source into our packaging directory:
# echo "Copying Linux source for packaging..."
# We won't do this since it takes longer and during development
# I never need any of the assets that are removed by the packaging process.
# cp -fa linux-$VERSION package-kernel-source/usr/src/
mv -fv linux-$VERSION package-kernel-source/usr/src/ || exit 1
cd package-kernel-source/usr/src || exit 1

# Ensure that the linux dir name matches the $VERSION of the package so that
# in the a/kernel-modules package, the /lib/modules/*/{build,source}
# symlinks are correct.
ln -vfs linux-$VERSION linux
cd linux || exit 1

# Prepare for packaging:
echo " + Cleaning up the source tree"
make ARCH=$LINUXKERNELARCH clean
# Make sure header files aren't missing:
make ARCH=$LINUXKERNELARCH prepare
# Don't package the kernel in the sources:
find . -name "*Image" -exec rm "{}" \;
# No need for these:
rm -fv .config.old .version
find . -name "*.cmd" -exec rm -f "{}" \;
rm -v .*.d
find . -name '.gitignore' -print0 | xargs -0 rm -rf
find . -name '.tmp*' -print0 | xargs -0 rm -rf

# Install package description:
cd $TMPBUILD/package-kernel-source
install -vpm644 $CWD/slack-descs/kernel-source install/slack-desc

# Apply some of the generic Slackware packaging policies:
slackslack  # chown -R root:root, chmod -R og-w, slackchown, slack644docs

echo " + Running makepkg for 'kernel-source'"
slackmp # run makepkg

#EOF
