#!/bin/bash

##########################################################################
# Script : kernel-2.6.SlackBuild
# Purpose: Natively build and package a Linux 2.6 Kernel for ARMedslack
# Author : Stuart Winter <mozes@armedslack.org>
# Date...: 20-Sep-2005
##########################################################################
# Changelog
############
# 20-Sep-2005 
#       * First version for Linux 2.6.13.1 on the StrongARM RiscPC
# 31-Dec-2005 
#       * Linux 2.6.14.5
##########################################################################

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

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

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

# Extract the kernel source:
echo -n "Extracting Kernel source... "
tar xf $CWD/sources/linux-2.6/linux-$VERSION.tar.*
echo "done"
cd linux-*
slackhousekeeping

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

# Bring the config file uptodate:
# When updating between major releases, it's easier and faster
# to run this on an x86:-
#   make ARCH=arm oldconfig
#make oldconfig
#read -p "You can run 'make menuconfig' in another session now, then press ENTER" 
# but don't run it here because it doesn't go well with logging :)
# make menuconfig
#read -p "Now run make menuconfig in another shell & fix up the config"

# Remove any hyphen from the EXTRAVERSION name.
# Having a dash in there breaks the package file naming convention,
# and even if we rename the package, the /lib/modules/2.x* directory
# still has the hyphen in it, which confuses the hell out of the installer
# build script.
sed -i '/EXTRAVERSION *=/s/-//g' Makefile
#sed -i 's/\(EXTRAVERSION *= *\)-/\1/' Makefile
#sed -i 's/^EXTRAVERSION.*=\(.*\)$/EXTRAVERSION = '"$VERSION"'/' Makefile

# Apply patches for the Kirkwood series.  These are taken from 
# the Marvell 'git' tree and eventually will be merged upstream.
#echo "Applying patches..."
#for i in $CWD/sources/linux-2.6/patches/*.patch ; do 
#   patch --verbose -p1 --dry-run < $i || exit 1
#done

# Apply build fixes.
# Temporary:
patch --verbose -p1 < $CWD/sources/linux-2.6/patches/dcache-libsas-2.6.30.1.diff || exit 1

# Build Kernel
make clean
make $NUMJOBS CONFIG_DEBUG_SECTION_MISMATCH=y zImage  || failmake
# Build the U-Boot image for 'Das U-Boot' - required for ARM devices
# that use the U-Boot Linux Loader:
make uImage || failmake

# Build modules:
make $NUMJOBS CONFIG_DEBUG_SECTION_MISMATCH=y modules || failmake

# Archive the compiled kernel source for future reference:
# This is handy for when we need the kernel source in /usr/src -- some packages
# look for it.  So on a new build box, I just extract it into /usr/src and 
# build the package.
# It takes a while to compress this on an ARM machine, and I never really 
# used these in the end, so I'll just rebuild the Kernel if necessary.
echo "Archiving compiled source for future reference..."
( cd .. && tar jcf $CWD/compiled-sources/$SLKARCH-kernel-$VERSION-compiled.tar.bz2 linux-$VERSION )

# Archive the Kernel headers in order to build the d/kernel-headers package.
echo "Archiving the Kernel includes for d/kernel-headers..."
mkdir -vpm755 $TMPBUILD/kernel-headers
# This installs 'sanitised' headers.  Previously I'd copied these manually but
# since ARM moved the headers to a new location in the kernel source, the headers
# became broken -- using this method results in stuff compiling, so I'll use it :-)
make INSTALL_HDR_PATH=$TMPBUILD/kernel-headers headers_install
( cd $TMPBUILD/kernel-headers
  # Wipe these '.install' and '..install.cmd' files
  find . -iname '.*' -type f -print0 | xargs -0 rm -f
  tar jcf $CWD/../d/kernel-headers/sources/kernel-headers-$VERSION.tar.bz2 . )

# Install modules into the package:
make modules_install INSTALL_MOD_PATH=$PKG
# And now spam the filesystem.  I don't like this, but unless I patch mkinitrd 
# to find modules in a location other than /, I need to do it:
# For all other work with modules, we should use the versions just compiled and
# packaged - the /lib/modules/xx may contain additional modules from previous builds,
# but it'll be good for mkinitrd since we know in advance which modules we'll
# include in the initrd, so these will always exist and be the latest builds.
# Eek!  -- this allows us to easily ensure that we don't specify any
# older now-compiled-in-kernel drivers as modules, which may have been
# left from an older build - makes testing easier without having to
# modify the mkinitrd line below.
# I need to patch mkinitrd ;-)
rm -rf /lib/modules/$VERSION-$SLKARCH 
make modules_install

# Install the modules into the a/kernel-modules source directory for use afterwards.
echo "Archiving Kernel modules for the a/kernel-modules package..."
( cd $PKG && tar jcvvf $CWD/../a/kernel-modules/sources/$SLKARCH-kernel-modules-$VERSION.tar.bz2 lib/ )

# When building in /patches/source:
#( cd $PKG && tar jcvvf $CWD/../kernel-modules/sources/$SLKARCH-kernel-modules-$VERSION.tar.bz2 lib/ )

# Install the kernel image and system map:
mkdir -vpm755 $PKG/{install,boot}
#gzip -f9cv System.map > $PKG/boot/System.map-$SLKARCH-$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-kirkwood", 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-$SLKARCH-$VERSION
install -vpm644 arch/arm/boot/zImage $PKG/boot/zImage-$SLKARCH-$VERSION
install -vpm644 arch/arm/boot/uImage $PKG/boot/uImage-$SLKARCH-$VERSION
# Make symlinks:
( cd $PKG/boot
  ln -vfs System.map-$SLKARCH-$VERSION System.map-$SLKARCH
  ln -vfs zImage-$SLKARCH-$VERSION zImage-$SLKARCH
  ln -vfs uImage-$SLKARCH-$VERSION uImage-$SLKARCH )

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

# The package description:
install -pvm644 $CWD/slack-descs/$SLKARCH-slack-desc $PKG/install/slack-desc

# Copy the Kernel into ARMedslack's 'kernels' directory:
# If you want to keep these, move the old one out of the way first
# otherwise it gets clobbered.
mkdir -vpm755 $PKGSTORE/../kernels/$SLKARCH
install -vm644 arch/arm/boot/zImage $PKGSTORE/../kernels/$SLKARCH/zImage-$SLKARCH
# Some Archs (eg ARM Versatile emulated by QEMU) won't need a U-Boot image,
# but if somebody *does* have a real ARM Versatile board (I don't know if it 
# uses U-Boot), then we ought to supply a U-Boot image anyway:
install -vm644 arch/arm/boot/uImage $PKGSTORE/../kernels/$SLKARCH/uImage-$SLKARCH
# This is really for the installer build script:
gzip -f9cv System.map  > $PKGSTORE/../kernels/$SLKARCH/System.map.gz
# And because Slackware includes the kernel config, let's do it too!
install -vpm644 .config $PKGSTORE/../kernels/$SLKARCH/config

# Make an initrd for the architecture - using a clean
# extraction (otherwise mkinitrd uses /boot/initrd-tree which on 
# the ARMedslack dev boxes, could contain anything! ;-)
#
# Note: Using mkinitrd will create the '/rootfs' file inside the initrd
#       filesystem in line with what the devbox running this script has
#       as its root filesystem.  However, you can (and probably should!)
#       (I tend to use ext3 though, so you'll be ok if you use that too! ;-) )
#       specify the root filesystem type at boot time by appending
#      
#       rootfs=ext4  or which ever filesystem you're using.
#
#       For QEMU, this is explained in the 'disk_launch' helper script
#       provided.  This 'rootfs=' is just a Kernel command line value
#       which is parsed by the initrd's '/init' script.
#
# This is work in progress and will probably need to be expanded for
# other architectures - as each arch will need a separate initrd anyway,
# otherwise they'll contain modules for all supported architectures
# as the installer does.
# Tip: when looking for what depends on what in the Kernel:
#      find /usr/src/linux-$VERSION/ -name Kconfig -exec grep -l ZLIB_ {} \;
rm -rf $TMPBUILD/initrd-tree
mkdir -vpm755 $TMPBUILD/initrd-tree
# Unpack the generic Slackware initial ram disk tree:
tar xf /usr/share/mkinitrd/initrd-tree.tar.gz -C $TMPBUILD/initrd-tree

#
#
# Filesystems & supporting libraries to include - these are the standard
# offered by the Slackware Installer:
# If we wanted ocfs2 (I originally thought Slackware supported it!)
# then we also need:
# ocfs2:configfs
#
# Note: If you were referred to this build script by some of the supporting
#       Slackware ARM documentation, please note that this list of filesystem
#       modules most likely far exceeds what is suggested by the
#       /usr/share/mkinitrd/mkinitrd_command_generator.sh script.
#       This is because the Slackware ARM initrd must be able to boot a newly
#       installed OS which could have been configured in a number of ways
#       (basically this means "what filesystems you used" ;-) ).
#       Also, I try to keep this list in sync with the modules required by the
#       Slackware installer.  All that is needed by your own initrd will be
#       enough to access the installes OS, and then load the rest of the Kernel
#       modules from there.
#       So, "DON'T PANIC!!"  
#       'mkinitrd' figures out the module dependencies and includes those too, so
#       we don't need to specify all associated modules (although I do try to keep a
#       running list where possible).
#

   # Generic requirements:
   # Filesystems:
   INITRDFS="vfat:jbd:jbd2:nls:exportfs:binfmt_misc:md:dm-mod:mbcache:ext2:ext3:ext4:reiserfs:xfs"
   # Generic SCSI drivers & low-level drivers for discs/media:
   INITRDSCSI="sg:scsi_mod:sd_mod:cdrom:sr_mod:scsi_tgt:mmc_block"
   # Network filesystems:
   INITRDNETFS="nfs:lockd:nfs_common"
   # USB hubs & support mods, followed by some specific device drivers.
   INITRDUSB="usbcore:usb-storage:ehci-hcd:ums-cypress:ums-usbat:ums-freecom:ums-isd200:ums-sddr09:ums-sddr55:ums-alauda:ums-jumpshot:ums-onetouch"

case "$SLKARCH" in

  # ARM Ltd. Versatile platform:
  versatile)

   # Network interface cards:
   INITRDNETDEV="smc91x"
   # SCSI cards:
   INITRDSCSI="$INITRDSCSI:sym53c8xx"
   mkinitrd \
      -w 3 \
      -k $VERSION-$SLKARCH \
      -s $TMPBUILD/initrd-tree \
      -m $INITRDSCSI:$INITRDUSB:$INITRDFS:$INITRDNETDEV:$INITRDNETFS \
      -o $PKGSTORE/../kernels/$SLKARCH/initrd-$SLKARCH.gz

   # Put a copy of the initial RAM disk into the $PKG's /boot
   # This allows devices whose boot loader can read the partition where /boot resides
   # can have a generic initrd to boot into after installation.
   install -vpm644 $PKGSTORE/../kernels/$SLKARCH/initrd-$SLKARCH.gz $PKG/boot/initrd-$SLKARCH-$VERSION.gz
   ( cd $PKG/boot
     ln -vfs initrd-$SLKARCH-$VERSION.gz initrd-$SLKARCH.gz )
 
   # Let's wipe the uInitrd and uimage files from this architecture.
   # We only support installing the Versatile from within QEMU.
   # Comment these lines if we want to keep the uImage, but I think it'll only
   # cause confusion to keep both copies.
   ( cd $PKG/boot
     rm -fv uImage* uinitrd* )
   rm -fv $PKGSTORE/../kernels/$SLKARCH/uImage*

  ;;

  # Marvell Kirkwood series (Including the 'SheevaPlug'):
  kirkwood) 

   # Network interface cards:
   INITRDNETDEV="mv643xx_eth"

   # Wait 10 seconds for the USB discs to spin up.  The SheevaPlug's
   # USB recognition can be a bit hit and miss, so it's best to
   # wait for longer than usual.
   mkinitrd \
      -w 10 \
      -k $VERSION-$SLKARCH \
      -s $TMPBUILD/initrd-tree \
      -m $INITRDSCSI:$INITRDUSB:$INITRDFS:$INITRDNETDEV:$INITRDNETFS \
      -o $TMPBUILD/uinitrd-kirkwood.gz

   # Create a uInitrd for U-boot:
   cd $TMPBUILD
   mkimage \
     -A arm \
     -O linux \
     -T ramdisk \
     -C gzip \
     -n "Slackware ARM Initial RAM disk for the $SLKARCH platform" \
     -d $TMPBUILD/uinitrd-kirkwood.gz \
     $PKGSTORE/../kernels/$SLKARCH/uinitrd-$SLKARCH
 
   # Put a copy of the initial RAM disk into the $PKG's /boot
   # This allows devices whose boot loader can read the partition where /boot resides
   # can have a generic initrd to boot into after installation.
   # This 'uinitrd' is for devices using the 'Das U-Boot' Linux loader.
   install -vpm644 $PKGSTORE/../kernels/$SLKARCH/uinitrd-$SLKARCH $PKG/boot/uinitrd-$SLKARCH-$VERSION
   ( cd $PKG/boot
     ln -vfs uinitrd-$SLKARCH-$VERSION uinitrd-$SLKARCH )

   # Wipe what we don't need for this architecture.
   # In this case we only retain the 'uImage' and 'uInitrd'
   ( cd $PKG/boot
     rm -fv zImage* initrd* )
   rm -fv $PKGSTORE/../kernels/$SLKARCH/zImage*

  ;;

esac

#   -o $TMPBUILD/initrd-dummy.gz
#	
#
# Compress the Kernel modules.
# The 'initrd-dummy.gz' above is a dummy - we use the newly updated
# 'initrd-tree' directory directly.
#
# I can't get the initrd to work with compressed Kernel modules.
# I'm not entirely sure why - it works for the installer.
# The /load-kernel-modules script would need updating to load the
# compressed file names - I tried that, but then it can't recognise
# the compressed kernel modules.
#
#( cd $TMPBUILD
#  cd initrd-tree
#  echo "Compressing Kernel modules for $SLKARCH initrd..."
#  find ./lib/modules -type f -name "*.ko" -exec gzip -9f {} \;
#  for i in $(find ./lib/modules -type l -name "*.ko") ; do ln -vfs $( readlink $i ).gz $i.gz ; rm -fv $i ; done
#  find ./lib/modules -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b.
#  find . | cpio -o -H newc | gzip -9fv > $PKGSTORE/../kernels/$SLKARCH/initrd-$SLKARCH.gz )

# It's nice to have this final touch (pun intended):
( cd $PKGSTORE/../kernels/$SLKARCH/
  touch -r ?Image-$SLKARCH * $PKG/boot/* )

# Build the base Kernel package (without libraries):
cd $PKG
chown -R root:root .
chmod -R og-w .
# Move the libs out of the way -- they go in a/kernel-modules package
# mv lib /tmp/$$lib
rm -rf lib # don't need these anymore since they are archived in the a/kernel-modules source directory

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

makepkg -l y -c n $PKGSTORE/$PKGSERIES/$PKGNAM-$VERSION-$ARCH-$BUILD.tgz
# Now put the libs back (we need them for the a/kernel-modules package):
# mv /tmp/$$lib lib

cat << EOF
Next steps:
-----------

 [1] If we're upgrading the Kernel headers, run the 
     build script in d/kernel-headers
     and modify l/glibc's build script to use the newer
     headers package and rebuild glibc.
     ** Normally I will not do this step **

 [2] # cd ~/tmp/build-kernel_xxx
     # cd linux*/arch/arm/boot
     # cp -fv zImage /mnt/somepath
     boot the OS with the new zImage
      
 [4] Kernel source package:
        - Rebuild the k/ kernel-source package.
        ./kernel-2.6-sourcepackage.SlackBuild     

 [5] Update Kernel modules:
cd ../../a/kernel-modules
Update Kernel version in 'arm/build'
./arm/build

EOF
