#!/bin/bash

# Build a kernel & initrd for the OpenRD client
# This is a test script for getting a shared working kernel for both
# the sheevaPlug & OpenRD.

# 01-Feb-2010
# Stuart Winter <mozes@slackware.com>
#
# Not to be used by the public!
# This is a messy amalgamation of Slackware ARM's 
#  kernel.SlackBuild;
#  kernel-modules.SlackBuild &
#  the installer repacker.
#

# Unpack your OpenRD client kernel source into /tmp or some place
# on the SheevaPlug's local storage.
# Use the Git tree as source.

#  cd /tmp
#  mkdir build-kernel-ord
#  cd build-kernel-ord
#  git clone git://repo.or.cz/linux-2.6/linux-2.6-openrd.git
#
# Then apply the patches:
#  xz -dc ../patches/*.xz | git am -3
# actually just  do this since I can't get the git am thing working atm.
#  for i in ../patches/*.xz ; do
#   xz -dc $i | patch --verbose -p1
#  done
  
source /usr/share/slackdev/buildkit.sh

CWD=$PWD
SLKARCH=openrd

# If it's an -rc release, remove the hyphen and rename
# the source archive.  It makes packaging and scripting all play happily.
export VERSION=${VERSION:-2.6.33rc8}
export BUILD=1

# Temporary build locations:
PKG=/tmp/package-openrdclient-kernel
TMPBUILD=/tmp/build-kernel-ord
rm -rf $PKG
mkdir -vpm755 $PKG

# For the installer:
rm -rf /tmp/ord-installer
mkdir -p /tmp/ord-installer/modules

# Setup distcc:
export DISTCC_HOSTS="turrican/2 prisere/4 kitt/2 goose/1 trance/1 kato/1"
export NUMJOBS=-j$[$(sed 's?[^0-9]*/?+?g' <<<$DISTCC_HOSTS)]
PATH=/tmp/DISTCC:$PATH
export CC=distcc

# Enter the kernel source:
cd $TMPBUILD/linux*

pwd
sleep 10

# Copy the OpenRD kernel config:
# This is basically the kirkwood config for the SheevaPlug
# in the main armedslack tree, but including the OpenRD client
# support, and the Framebuffer driver.
install -vpm644 $CWD/config-openrd .config
make oldconfig

# 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

# Build Kernel
make $NUMJOBS CONFIG_DEBUG_SECTION_MISMATCH=y zImage  || exit 1
make uImage || exit 1

# Build modules:
make $NUMJOBS CONFIG_DEBUG_SECTION_MISMATCH=y modules || exit 1

# Install modules into the package:
make modules_install INSTALL_MOD_PATH=$PKG
# Install them into the installer's temporary directory:
make modules_install INSTALL_MOD_PATH=/tmp/ord-installer/modules
# And into the filesystem so that mkinitrd will work:
rm -rf /lib/modules/$VERSION-$SLKARCH 
make modules_install

# Compress kernel modules to reduce the size of the initrd.
# Busybox >=1.14 supports compressed kernel modules.
echo "Compressing Kernel modules for $SLKARCH ..."
find /lib/modules/$VERSION-$SLKARCH -type f -name "*.ko" -exec gzip -9f {} \;
for i in $(find /lib/modules/$VERSION-$SLKARCH -type l -name "*.ko") ; do ln -vfs $( readlink $i ).gz $i.gz ; rm -fv $i ; done
# 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 module dependencies for $VERSION-$SLKARCH"
  find lib/modules -name $VERSION-$SLKARCH -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b. )

# 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 -Ixz -pcf $CWD/../a/kernel-modules/sources/$SLKARCH-kernel-modules-$VERSION.tar.xz lib/ )

# Add the new kernel to the tftpboot directory on the server:
rm -rf /mnt/prisroot/tftpboot/openrd
mkdir -vpm755 /mnt/prisroot/tftpboot/openrd
install -vm644 arch/arm/boot/uImage /mnt/prisroot/tftpboot/openrd/uImage-$SLKARCH

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

# The package description:
install -pvm644 $CWD/openrd-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
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

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

   # Generic requirements:
   # Filesystems:
   INITRDFS="vfat:jbd:jbd2:nls:exportfs:binfmt_misc:md:dm-mod:mbcache:ext2:ext3:ext4:reiserfs:jfs: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, including interface devices (USB keyboards etc)
   # followed by some specific device drivers.
   INITRDUSB="ehci-hcd:uhci_hcd:usbhid:ohci_hcd:hid:usbcore:usb-storage:ums-cypress:ums-usbat:ums-freecom:ums-isd200:ums-sddr09:ums-sddr55:ums-alauda:ums-jumpshot:ums-onetouch"

   # Network interface cards:
   INITRDNETDEV="mv643xx_eth"

   # eSATA support for the OpenRD:
   # Generic libata & Marvell's SATA driver.
   INITRDSATA="libata:sata_mv"

   # For SDHC cards:
   INITRDCARDS="mvsdio"

   # 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 \
      -R \
      -L \
      -u \
      -w 10 \
      -k $VERSION-$SLKARCH \
      -s $TMPBUILD/initrd-tree \
      -m $INITRDSCSI:$INITRDSATA:$INITRDUSB:$INITRDFS:$INITRDNETDEV:$INITRDNETFS:$INITRDCARDS \
      -o $TMPBUILD/uinitrd-$SLKARCH.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-$SLKARCH.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*

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


  ( mkdir -vpm755 etc/rc.d
    cd etc/rc.d

    # Install the Slackware Kernel module loading script, 'rc.modules':
    install -vpm755 $CWD/rc.modules.new rc.modules-${VERSION}.new
    # This broken symlink will be fixed by the install/doinst.sh script
    # after package installation.  However, if you install all the modules packages
    # of all supported archs then you will see dangling symlinks on your
    # filesystem.
    ln -vfs rc.modules-${VERSION} rc.modules-${VERSION}-${SLKARCH} )

    # Update /etc/rc.d/rc/rc.modules to contain additional loading for
    # some h/w specific stuff:
    # This means that each architecture's modules package will have the same
    # additional code, and that's intended since I don't know which package
    # you'll install!
    #
#cat << EOF >> etc/rc.d/rc.modules-${VERSION}.new
##
## RiscPC specific Kernel modules.
##
#if grep -q RiscPC /proc/cpuinfo ; then
#   # Regular RiscPC mouse support:
#   /sbin/modprobe rpcmouse
#   # Onboard sound:
#   /sbin/modprobe vidc_mod
#fi
cat << EOF >> etc/rc.d/rc.modules-${VERSION}.new
#
# ARM Versatile specific Kernel modules.
#
if grep -q ARM-Versatile /proc/cpuinfo ; then
   # ps/2 Mouse support:
   /sbin/modprobe psmouse
fi
EOF

   chmod 755 etc/rc.d/rc.modules-${VERSION}.new

# Compress Kernel modules.  Helps conserve disk space on the
# embedded devices with small on-board storage:
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

   # Install the post install script.
   # This is taken from Slackware's kernel-modules.SlackBuild script:
cat << EOF > install/doinst.sh
config() {
  NEW="\$1"
  OLD="\$(dirname \$NEW)/\$(basename \$NEW .new)"
  # If there's no config file by that name, mv it over:
  if [ ! -r \$OLD ]; then
    mv \$NEW \$OLD
  elif [ "\$(cat \$OLD | md5sum)" = "\$(cat \$NEW | md5sum)" ]; then # toss the redundant copy
    rm \$NEW
  fi
  # Otherwise, we leave the .new copy for the admin to consider...
}

config etc/rc.d/rc.modules-${VERSION}.new

# If rc.modules is a real file, back it up:
if [ -r etc/rc.d/rc.modules -a ! -L etc/rc.d/rc.modules ]; then
   cp -favv etc/rc.d/rc.modules etc/rc.d/rc.modules.bak
fi

# A good idea whenever kernel modules are added or changed:
if [ -x sbin/depmod ]; then
  chroot . /sbin/depmod -a ${VERSION} 1> /dev/null 2> /dev/null
fi

EOF

   # This is usually a symlink to where the kernel was compiled
   # (/usr/src) but Slackware does not have this:
   ( cd $PKG
     find . -type l -name source -print0 | xargs -0 rm -f
     find . -type l -name build  -print0 | xargs -0 rm -f )

   ( cd $PKG
     find lib/modules -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b. )

# 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/a/kernel_$SLKARCH-$VERSION-$ARCH-$BUILD.tgz

##### Repack the installer:

# Compress Kernel modules.  Helps conserve disk space on the
# embedded devices with small on-board storage:
( cd /tmp/ord-installer/modules 
  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 )

cd /tmp/ord-installer
zcat ~/ac/isolinux/initrd-versatile.img | cpio -di
LIST=/tmp/ord-installer/module-list

pushd lib/modules/
  ( cd *versatile*
   # Generate the list of Kernel modules which are included in the installer:
    find . -type f > $LIST )
   # Delete the ARM Versatile kernel modules; we'll be replacing these
   # with the Kirkwood's.
  rm -rf *versatile*
  EXTPOS=$PWD
popd

# Add a few additional modules required for the Kirkwood series.
# These can include specific hardware drivers, or additional
# USB/SCSI drivers which aren't needed by the ARM Versatile
# board.
#
#
cat << EOF >> $LIST
./kernel/drivers/mmc/
./kernel/drivers/net/mv643xx_eth.ko.gz
./kernel/drivers/usb/storage/usb-libusual.ko.gz
./kernel/drivers/scsi/scsi_tgt.ko.gz
./kernel/drivers/scsi/scsi_mod.ko.gz
./kernel/drivers/scsi/sg.ko.gz
./kernel/lib/crc-t10dif.ko.gz
./kernel/drivers/usb/core/usbcore.ko.gz
./kernel/drivers/usb/storage/usb-storage.ko.gz
./kernel/drivers/usb/storage/ums-cypress.ko.gz
./kernel/drivers/usb/host/ehci-hcd.ko.gz
./kernel/drivers/ata/sata_mv.ko.gz
./kernel/drivers/ata/libata.ko.gz
EOF

pushd /tmp/ord-installer/modules/lib/modules/
  # Work out what the name of the Kernel is (this may not match the
  # Kernel version number in this script, although it should!)
  KERNELNAME="$( ls -1d * )"
  cd $KERNELNAME
  # Create the /lib/modules/2.6.x-kirkwood directory:
  mkdir -vpm755 $EXTPOS/$KERNELNAME
  # Copy the same Kernel modules as the Versatile does -- including those
  # additional ones in the list above -- into the Kirkwood installer:
  tar pvvcf - -T $LIST | tar -C $EXTPOS/$KERNELNAME/ -pxf -
popd

cd /tmp/ord-installer
# Re-generate module dependencies list:
find ./lib/modules -type d -mindepth 1 -maxdepth 1 -printf "%f\n" | xargs -i depmod {} -b.

# Create U-Boot image & put it into the
# Slackware ARM tree ready for distribution:
find . | cpio -o -H newc | gzip -9fv > ../Slackware_Installer_$SLKARCH.gz
mkimage \
  -A arm \
  -O linux \
  -T ramdisk \
  -C gzip \
  -n 'Slackware ARM Installer' \
  -d ../Slackware_Installer_$SLKARCH.gz \
  $PKGSTORE/../isolinux/uinitrd-$SLKARCH.img

# Update the tftp boot version:
cp -fav $PKGSTORE/../isolinux/uinitrd-$SLKARCH.img /mnt/prisroot/tftpboot/openrd/

