#!/bin/bash
#
# gentcos    generate network bootable initramfs images
# Creation Date: 2 Feb 2006
#
# Copyright (C) 2006-2011  mariodebian at gmail
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#

ID=$(id -u)

if [ $ID -ne 0 ]; then
 echo "You must run this script as root"
 exit 1
fi

. /etc/tcos/tcos.conf
[ -e /var/lib/tcos/version.conf ] && . /var/lib/tcos/version.conf
. ${TCOS_DIR}/tcos-generation-functions.sh
. /usr/share/initramfs-tools/hook-functions


# Multiarch DIR
LIB_MULTIARCH=/lib/
USRLIB_MULTIARCH=/usr/lib/
if [ -n "$TCOS_MULTIARCH" ] && [ -e "/usr/lib/$TCOS_MULTIARCH" ]; then
  LIB_MULTIARCH="/lib/$TCOS_MULTIARCH"
  USRLIB_MULTIARCH="/usr/lib/$TCOS_MULTIARCH"
fi
export LIB_MULTIARCH
export USRLIB_MULTIARCH

for tpl in $(tcos_get_templates); do
  . $tpl
done

# load forced settings for derivatives
if [ -d /etc/tcos/conf.d/ ]; then
  for file in /etc/tcos/conf.d/tcos*conf; do
    [ -e $file ] && . $file
  done
fi

if [ -z $TCOS_KERNEL ]; then
  NEWEST_VMLINUZ=$(basename $(ls /boot/vmlinuz-*| head -1))
  TCOS_KERNEL=${NEWEST_VMLINUZ#vmlinuz-}
fi

# default output files
OUTPUTIMAGE=${ISOS}/tcos-boot-usb.iso

if [ -e /usr/bin/mkisofs ];then
  GENISO="/usr/bin/mkisofs"
else
  GENISO="/usr/bin/genisoimage"
fi

OUTINITRAMFS=initramfs
OUTNBI=linux.nbi

OUTROOTFS_TMP=/tmp/rootfs-${TCOS_KERNEL}-$$
OUTROOTFS_END=${TFTP_DIR}/rootfs-${TCOS_KERNEL}.squashfs

# temp vars
INITRAMFS=/tmp/initramfs-$$
TMPNBI=/tmp/nbi-$$

EXTRA_APPEND=""
TCOS_SUFFIX=
MKVERBOSE=""


# BASH COLORS
NORMAL="\033[0;39m"
GRAY="\033[1;30m"
LIGHT_GRAY="\033[0;37m"
CYAN="\033[0;36m"
LIGHT_CYAN="\033[1;36m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
MAGENTA="\033[1;35m"
WHITE="\033[1;37m"



_exit () {
 if [ "$1" = "1" ];then
   rm -f ${TFTP_DIR}/usr${TCOS_SUFFIX}-${TCOS_KERNEL}.squashfs 2>/dev/null
   rm -f ${TFTP_DIR}/${OUTINITRAMFS}${TCOS_SUFFIX} 2>/dev/null
   rm -f ${TFTP_DIR}/${OUTNBI}${TCOS_SUFFIX} 2>/dev/null
   rm -f ${TFTP_DIR}/root-${TCOS_KERNEL}.squashfs 2>/dev/null
   rm -f ${TFTP_DIR}/${OUTINITRAMFS}-nfs 2>/dev/null
 fi
 unset TCOS_SQUASHFS
 unset TCOS_ALL_MODULES
 unset TCOS_SUFFIX
 rm -f ${TMPNBI}
 rm -f ${INITRAMFS}
 rm -f ${INITRAMFS}-nfs
 rm -rf ${OUTROOTFS_TMP}
 # exit wrapper
 #echo "DONE"
 exit $1
}

call_mkinitramfs() {
 rm -rf /tmp/mkinitramfs* /tmp/gentcos* /var/tmp/mkinitramfs*
 NEWINITRAMFS=$1
 #echo "mkinitramfs $MKVERBOSE -d ${TCOS_CONF} -o ${NEWINITRAMFS} ${TCOS_KERNEL}"
 mkinitramfs -k $MKVERBOSE -d ${TCOS_CONF} -o ${NEWINITRAMFS} ${TCOS_KERNEL}

 DESTDIR2="$(find /var/tmp/ /tmp/ -maxdepth 1 -type d -name "mkinitramfs*")"
 #(cd "${MKDIR}" && find . | cpio --quiet --dereference -o -H newc | gzip > "${NEWINITRAMFS}" )

 if [ ! -d "$DESTDIR2/scripts" ]; then
   _echo " **ERROR** mkinitramfs temp dir not found"
   return
 fi
 
 export DESTDIR="${DESTDIR2}"
 # clean dir
 bash ${TCOS_DIR}/hooks-addons/clean_initramfs

 echo -n "   * Updating module dependencies..."
 DEPMOD_ARGS="-a -F /boot/System.map-${TCOS_KERNEL}"
 if depmod -h 2>&1|grep -q map; then
   DEPMOD_ARGS="-am -F /boot/System.map-${TCOS_KERNEL}"
 fi

 # convert module kernel links in files
 LINKS=$(find ${DESTDIR}/lib/modules/${TCOS_KERNEL}/ -type l)
 for link in $LINKS; do
   fname=$(echo $link| sed -e s@"$DESTDIR"@""@g)
   #echo "  fname=$fname link=$link"
   rm -f "$link"
   cp "$fname" "$link"
 done

 mkdir -p ${DESTDIR}/boot/
 cp /boot/System.map-${TCOS_KERNEL} ${DESTDIR}/boot/
 chroot ${DESTDIR}/ /sbin/depmod $DEPMOD_ARGS ${TCOS_KERNEL}
 rm -rf ${DESTDIR}/boot/
 echo " done."

 # compress again
 rm -f ${NEWINITRAMFS}

 # LZMA gets 11 MB and GZIP 9,9, disable LZMA for now
 #if grep -q -i ^config_rd_lzma /boot/config-${TCOS_KERNEL}; then
 #  echo -n "   * Using LZMA (experimental) to compress image..."
 #  (cd "${DESTDIR2}" && find . | cpio --quiet -o -H newc | lzop -9 > "${NEWINITRAMFS}" )
 #  echo " done."
 #else
   (cd "${DESTDIR2}" && find . | cpio --quiet -o -H newc | gzip > "${NEWINITRAMFS}" )
 #fi

 rm -rf "${DESTDIR2}"
 rm -rf /tmp/mkinitramfs_* /tmp/gentcos_* /var/tmp/mkinitramfs*
}


# some functions 
create_initramfs() {
 # call mkinitramfs
 _echo "TCOS $DISTRIBUTION/$TCOS_DISTRO/$TCOS_ARCH  $TCOS_VERSION"
 _echo "Creating initramfs with ${TCOS_KERNEL} kernel..."
 call_mkinitramfs ${INITRAMFS}

 if [ ! -f ${TFTP_DIR}/vmlinuz-${TCOS_KERNEL} ]; then
   _echo "  Linking vmlinuz-${TCOS_KERNEL} in ${TFTP_DIR}"
   ln -s /boot/vmlinuz-${TCOS_KERNEL} ${TFTP_DIR}
 fi
}

# some functions 
create_initramfs_nfs() {
 # call mkinitramfs
 _echo "Creating NFS initramfs with ${TCOS_KERNEL} kernel..."

 export TCOS_BOOT=tcos-nfs
 call_mkinitramfs "${INITRAMFS}-nfs"
 unset TCOS_BOOT
 

 if [ ! -f ${TFTP_DIR}/vmlinuz-${TCOS_KERNEL} ]; then
   _echo "  Linking vmlinuz-${TCOS_KERNEL} in ${TFTP_DIR}"
   ln -s /boot/vmlinuz-${TCOS_KERNEL} ${TFTP_DIR}
 fi


}


create_rootfs() {
 if [ ! -e /etc/tcos/chroot ] && [ ! -f /etc/exports ]; then
    echo "  Warning:"
    echo "          No NFS server detected and /etc/exports file."
    echo "          Install nfs-kernel-server and put this line into /etc/exports"
    echo ""
    echo "          /var/lib/tcos  192.168.0.0/255.255.255.0(ro,no_root_squash,sync,no_subtree_check)"
    echo ""
    echo "          (change 192.168.0.0 with your network addresses)"
    echo ""
    echo "          Ignore this if you are running with a 32bit chroot."
 fi

 _echo "Creating NFS rootfs in ${TCOS_VAR}/fs-${TCOS_KERNEL}/"
 rm -rf ${OUTROOTFS_TMP} && mkdir -p ${OUTROOTFS_TMP}

 export TCOS_ENV_DISABLE_SQUASHFS=1
 create_initramfs
 unset TCOS_ENV_DISABLE_SQUASHFS
 
 _echo "  Uncompressing initramfs..."
 # uncompress initramfs
 cp ${INITRAMFS} ${OUTROOTFS_TMP}/initramfs.gz
 gunzip ${OUTROOTFS_TMP}/initramfs.gz
 
 old_dir=$(pwd)
 cd ${OUTROOTFS_TMP}
 cpio -i < initramfs 2> /dev/null
 rm -f initramfs

 rm -rf ${TCOS_VAR}/fs-${TCOS_KERNEL}
 mkdir ${TCOS_VAR}/fs-${TCOS_KERNEL}
 mv ${OUTROOTFS_TMP}/* ${TCOS_VAR}/fs-${TCOS_KERNEL}/

 echo -n "   * Updating modules dependencies..."
 DEPMOD_ARGS="-a -F -F /boot/System.map-${TCOS_KERNEL}"
 if depmod -h 2>&1|grep -q map; then
   DEPMOD_ARGS="-am -F /boot/System.map-${TCOS_KERNEL}"
 fi
 mkdir -p ${TCOS_VAR}/fs-${TCOS_KERNEL}/boot/
 cp /boot/System.map-${TCOS_KERNEL} ${TCOS_VAR}/fs-${TCOS_KERNEL}/boot/
 chroot ${TCOS_VAR}/fs-${TCOS_KERNEL}/ /sbin/depmod $DEPMOD_ARGS ${TCOS_KERNEL}
 rm -rf ${TCOS_VAR}/fs-${TCOS_KERNEL}/boot/
 echo " done."
 
 if [ -e /sbin/nbd-client ]; then
   echo -n "   * Creating root-${TCOS_KERNEL}.squashfs to use with NBD..."
   MKSQUASHFS=mksquashfs
   [ -x /usr/bin/mksquashfs ]  && MKSQUASHFS=/usr/bin/mksquashfs
   [ -x /usr/sbin/mksquashfs ] && MKSQUASHFS=/usr/sbin/mksquashfs
   $MKSQUASHFS ${TCOS_VAR}/fs-${TCOS_KERNEL}/ ${TFTP_DIR}/root-${TCOS_KERNEL}.squashfs > /dev/null 2>&1
   chmod 644 ${TFTP_DIR}/root-${TCOS_KERNEL}.squashfs
   echo " done."
 fi

 cd ${old_dir}
 rmdir ${OUTROOTFS_TMP}
}


ramdisk_size () {
  # uncompress initramfs and exec du
  _echo "Uncompressing ramdisk to get sizes..."
  tmpdir="$(mktemp -t -d gentcos_XXXXXX)"
  cp ${INITRAMFS} ${tmpdir}/initrd.gz
  gunzip ${tmpdir}/initrd.gz || return
  oldpwd=$(pwd)
  cd ${tmpdir}/
  cpio -i < initrd >/dev/null 2>&1
  rm initrd
  squashfs_size=0
  ramdisk_size=$(du -s . | awk '{print $1}')
  if [ -e ${TFTP_DIR}/usr${TCOS_SUFFIX}-${TCOS_KERNEL}.squashfs ]; then
    squashfs_size=$(du -s ${TFTP_DIR}/usr${TCOS_SUFFIX}-${TCOS_KERNEL}.squashfs 2> /dev/null | awk '{print $1}')
  fi
  echo "RAMDISK=${ramdisk_size}"
  echo "EXTERNAL_SQUASHFS=${squashfs_size}"
  if [ $TCOS_NBI ]; then
    nbi_size=$(du -s ${TMPNBI} | awk '{print $1}')
    echo "NBI_IMAGE=${nbi_size}"
    echo "TOTAL_RAM=$((${nbi_size}+${squashfs_size}))"
  else
    echo "TOTAL_RAM=$((${ramdisk_size}+${squashfs_size}))"
  fi
  rm -rf ${tmpdir}
  cd ${oldpwd}
}

create_nbi() {
 # call mknbi
 _echo "Creating nbi image with ${TCOS_KERNEL} kernel"
 # TCOS_APPEND add more append with -extra-append
 echo "Building NBI image with this append: ${TCOS_APPEND} ${EXTRA_APPEND}"
 if [ "${EXTRA_APPEND}" = "" ]; then
   echo " Please add option -extra-append=\"your_modifiers\" "
 fi
 /usr/bin/mkelf-linux /boot/vmlinuz-${TCOS_KERNEL} /tmp/initramfs-${TCOS_KERNEL} \
   --output=${TMPNBI} --append="${TCOS_APPEND} ${EXTRA_APPEND}"
 rm /tmp/initramfs-${TCOS_KERNEL}
}

create_isolinux_iso() {
 # ISOLINUX
 dir=/tmp/isolinux-iso$$
 mkdir -p ${dir}/isolinux
 [ ! -d ${ISOS} ] && mkdir -p ${ISOS}
 create_initramfs
 cp ${INITRAMFS} ${dir}/isolinux/initrd.cdrom

 parse_pxelinuxcfg ${dir}/isolinux/isolinux.cfg isolinux
 sed -i s/"vmlinuz-${TCOS_KERNEL}"/"vmlinuz"/g ${dir}/isolinux/isolinux.cfg
 sed -i s/"initramfs-${TCOS_KERNEL}"/"initrd.cdrom"/g ${dir}/isolinux/isolinux.cfg

 cp ${TFTP_DIR}/${TFTP_LOGO_LSS} ${dir}/isolinux/
 cp ${TFTP_DIR}/${TFTP_MSG} ${dir}/isolinux/
 cp ${TFTP_DIR}/${TFTP_MSG_HELP1} ${dir}/isolinux/
 cp ${TFTP_DIR}/${TFTP_MSG_HELP2} ${dir}/isolinux/

 cp /usr/lib/syslinux/isolinux.bin ${dir}/isolinux/
 cp /boot/vmlinuz-${TCOS_KERNEL} ${dir}/isolinux/vmlinuz

${GENISO} -l -r -J -V "${VOLUMENAME}" -hide-rr-moved -v -b isolinux/isolinux.bin -c boot.cat \
 -no-emul-boot -boot-load-size 4 -boot-info-table -o  ${OUTPUTIMAGE} ${dir}/ > /dev/null 2>&1

  if [ $? = 0 ]; then
    echo "Iso image done succesfully: ${OUTPUTIMAGE}"
   else
    echo "Error running mkisofs."
  fi
  rm -rf ${dir} > /dev/null 2>&1
}


usage() {
/bin/echo -e "Usage:
  $WHITE$(basename $0)$NORMAL $RED-tftp$NORMAL  [-o=initrd-pc1]           PXE (>= 64 Mb)
          $RED-nfs$NORMAL   [$GREEN-rootfs$NORMAL]                 LTSP like (28 - 64 Mb)
          $RED-nbi$NORMAL   [-nbi-output=linux.nbi]   Floppy
          $RED-cdrom$NORMAL [-force]     CDROM
          $RED-instpkg$NORMAL pkgname
          $RED-rmpkg$NORMAL pkgname
          $RED-listpkg$NORMAL
          $RED-fix-nvidia-ati$NORMAL

      [-h] or [-help] $(basename $0) extended help
      [${RED}-vmlinux=${WHITE}vmlinuz-x.x.x${RED}|${WHITE}/boot/vmlinuz-x.x.x${NORMAL}] kernel version
      [${RED}-suffix=${WHITE}foo${NORMAL}] ( suffix for filenames )
      [${RED}-size${NORMAL}]       ( print ramdisk size )
      [${RED}-v${NORMAL}]          ( show verbose output of mkinitramfs )
      [${RED}-allmodules${NORMAL}] ( generate allmodules-${TCOS_KERNEL}.squashfs to
                              know what kernel modules need )
      [${RED}-extramodules=${WHITE}"foo,bar"${NORMAL}] ( add coma separated list of modules )

"
_exit 0
}

_help() {
/bin/echo -e "
This is gentcos help info about generating net init images.

  ${BLUE}TFTP PXE images:${NORMAL}
     ${GREEN}-tftp${NORMAL}  or [-t] make initramfs-${TCOS_KERNEL} and copy to ${TFTP_DIR}
    [${GREEN}-o=initramfs-tcos1${NORMAL}] output file
             ( default ${TFTP_DIR}/${OUTINITRAMFS} )

  ${BLUE}NFS (like LTSP) images:${NORMAL}
     ${GREEN}-nfs${NORMAL}  or [-n] make initramfs-${TCOS_KERNEL}-nfs and copy to ${TFTP_DIR}
    [${GREEN}-rootfs${NORMAL}] Make a complete initramfs and uncompress in ${TCOS_VAR}/fs-${TCOS_KERNEL}
             ( default ${TFTP_DIR}/${OUTINITRAMFS}-nfs )

  ${BLUE}NBI IMAGES:${NORMAL} ( Etherboot floppy )
     ${GREEN}-nbi${NORMAL}  or [-b] create NBI (network bootable images) in ${TFTP_DIR}
    [${GREEN}-nbi-output=linux-tcos1.nbi${NORMAL}] output nbi file 
              ( default ${OUTNBI}-${TCOS_KERNEL} )
    [${GREEN}-extra-append${NORMAL}] append more options to cmline of NBI image
      ( Example: -extra-append=\"startx=N volume=80%\"

  ${BLUE}ISO IMAGES:${NORMAL}
     ${GREEN}-cdrom${NORMAL}  or [-c] create cdrom iso file in $ISOS
    [${GREEN}-force${NORMAL}] force cdrom build if external SQUASH is enabled
            ( this will put squashfs into initramfs )

  ${BLUE}Install package in cache:${NORMAL}
     ${GREEN}-instpkg${NORMAL}
        This option download with apt-get install -d -y (not install)
        and extract package in ${TCOS_PKG_CACHE}
        This is used for use some tool (example esound) without instllin it.

  ${BLUE}Remove package from cache:${NORMAL}
     ${GREEN}-rmpkg${NORMAL}
        This option remove cached package from ${TCOS_PKG_CACHE}

  ${BLUE}List cached packages:${NORMAL}
     ${GREEN}-listpkg${NORMAL}
        This option list all cached packages with -instpkg option

  ${BLUE}Fix NVIDIA/ATI driver problem:${NORMAL}
     ${GREEN}-fix-nvidia-ati${NORMAL}
        This option cache xserver-xorg-core and libgl1-mesa-glx 
        packages to avoid using nvidia/ati libs.


   In all build you can add this params:

    ${BLUE}-vmlinuz${NORMAL}=[ vmlinuz.x.x.x | /boot/vmlinuz.x.x.x ]
        this will build all images with the kernel version of this file

  Examples of use:
${WHITE}
     gentcos -tftp -suffix=-pc1
     gentcos -nfs -rootfs
     gentcos -cdrom
     gentcos -nbi -extra-append=\"vga=791 uselocal\"
     gentcos -instpkg esound
     gentcos -rmpkg esound
     gentcos -listpkg
     gentcos -fix-nvidia-ati
${NORMAL}
"
}

if [ $# = 0 ]; then
 usage
 _exit 0
fi



alert_need_module() {
       _mod=$1
      echo "ERROR:"
      echo "    to build usable TCOS initramfs images need this kernel module: \"${_mod}\""
      echo ""
      echo "    Perhaps we have compiled for you, try installing tcos-extra-modules-${TCOS_KERNEL}"
      echo "    if package don't exist you can try to build it"
      echo ""
      echo "   # apt-get install module-assistant linux-headers-${TCOS_KERNEL} ${_mod}-source"
      echo "   # m-a -t -k /usr/src/linux-headers-${TCOS_KERNEL} build,install ${_mod}"
      echo ""

      echo ""
      echo "NOTE: You can change kernel version in ${TCOS_CONF}/tcos.conf file"
}



check_modules() {
    NEED_MODULES="aufs|overlayfs|unionfs squashfs"

    for _module in ${NEED_MODULES}; do
       have_module=0
       if [ "$(echo $_module | awk -F "|" '{print $2}')" != "" ]; then
         for _mod in $(echo $_module | sed 's/|/ /g'); do
           #_echo "searching for module $_mod"
           tcos_find_module "${_mod}" && have_module=1
         done
       else
         tcos_find_module "${_module}" && have_module=1
       fi

       if [ ${have_module} = 0 ] ; then
          alert_need_module $_module
          _exit 1
       fi
    done
}


check_xfs() {
    # since 0.89.13 TCOS not need XFS server
    return
    if [ ! -e /etc/tcos/chroot ] && [ ! -f /etc/X11/fs/config ]; then
        echo ""
        echo "WARNING:"
        echo "        TCOS needs a font server, please install xfs package"
        echo "        and configure to allow remote connections. See README."
        echo ""
    else
      if [ ! -e /etc/tcos/chroot ] && grep -q "^no-listen" /etc/X11/fs/config ; then
        echo "WARNING:"
        echo "        TCOS need a network font server. Please edit /etc/X11/fs/config"
        echo "        search for no-listen = tcp line and put like this:"
        echo "                 #no-listen = tcp   "
        echo "        Then restart service:   /etc/init.d/xfs restart"
      fi

    fi
}

link_vmlinuz() {
    if [ $TCOS_VMLINUZ ]; then
       if [ -f $TCOS_VMLINUZ ] ; then
          vmlinuz=$(basename ${TCOS_VMLINUZ} )
          TCOS_KERNEL=${vmlinuz#vmlinuz-}
           if ! find  ${TFTP_DIR}/*${vmlinuz}* 2> /dev/null | grep -q vmlinuz ; then
              # no link, create
              echo "Linking ${TCOS_VMLINUZ} in ${TFTP_DIR}/"
              ln -s $TCOS_VMLINUZ ${TFTP_DIR}/
           fi
       elif [ -f /boot/${TCOS_VMLINUZ} ]; then
          vmlinuz=${TCOS_VMLINUZ}
          TCOS_KERNEL=${vmlinuz#vmlinuz-}
           if ! find  ${TFTP_DIR}/*${vmlinuz}* 2> /dev/null | grep -q vmlinuz ; then
              # no link, create
              echo "Linking ${TCOS_VMLINUZ} in ${TFTP_DIR}/"
              ln -s /boot/$TCOS_VMLINUZ ${TFTP_DIR}/
           fi      
       else
          echo "ERROR: vmlinuz argument not found: ${TCOS_VMLINUZ}"
          echo "       You can use -vmlinuz=vmlinuz-x.x.x or"
          echo "                   -vmlinuz=/boot/vmlinuz-x.x.x"
          echo ""
          echo "       Using default kernel ${TCOS_KERNEL}"
       fi
    fi
}



list_pkg() {
      echo "  Installed cached packages are:"
      ls -1 ${TCOS_PKG_CACHE} 2>/dev/null
     _exit 0
}

check_cached_packages(){
for PKG in $(echo ${TCOS_PKG_CACHE_LIST} | sed 's/,/ /g'); do
    if [ ${PKG} = "fix-nvidia-ati" ];then
         CANDIDATE1=$(LC_ALL=C apt-cache policy xserver-xorg-core | awk -F"Candidate: " '/Candidate/ {print $2}' | sed 's/[[:blank:]]*//g')
         CANDIDATE2=$(LC_ALL=C apt-cache policy libgl1-mesa-glx | awk -F"Candidate: " '/Candidate/ {print $2}' | sed 's/[[:blank:]]*//g')
         VER1=""
         VER2=""
         [ -e ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.xserver ] && VER1=$(cat ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.xserver)
         [ -e ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.glx ] && VER2=$(cat ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.glx)
         if [ "${CANDIDATE1}" != "${VER1}" -o "${CANDIDATE2}" != "${VER2}" ];then
             echo "Updating package cache fix-nvidia-ati..."
             fix_nvidia_ati "1"
         fi
    else
         CANDIDATE=$(LC_ALL=C apt-cache policy ${PKG} | awk -F"Candidate: " '/Candidate/ {print $2}' | sed 's/[[:blank:]]*//g')
         VER=""
         [ -e ${TCOS_PKG_CACHE}/${PKG}/VERSION ] && VER=$(cat ${TCOS_PKG_CACHE}/${PKG}/VERSION)
         if [ "${CANDIDATE}" != "${VER}" ];then
             echo "Updating package cache ${PKG} to version ${CANDIDATE}..."
             tcos_inst_pkg ${PKG}
         fi
    fi
done
}

get_pkg_uri() {
  PKG_MIRROR=$(basename $(rgrep "/$1_" /var/lib/apt/ 2>/dev/null| awk -F":" '{print $1}'| head -1) 2>/dev/null)
  if [ $? != 0 ]; then
    return 1
  fi
  MIRROR=$(echo $PKG_MIRROR | sed 's|_|/|g' | awk -F"/dists" '{print $1}')
  COMPLETE_MIRROR=$(grep "$MIRROR " /etc/apt/sources.list | grep -v "^#" |awk '{print $2}')
  PKG_FILE=$(rgrep "/$1_" /var/lib/apt/ 2>/dev/null| awk '{print $2}'| head -1)

  echo ${COMPLETE_MIRROR}/${PKG_FILE}
}

tcos_inst_pkg() {
  error=0
  echo "Install PKG \"$@\""
  for PKG in ${@}; do
    rm -f /var/cache/apt/archives/${PKG}_* 2>/dev/null
    PKG_URI=$(apt-get install -qq --print-uris --reinstall ${PKG}| egrep 'file|http|ftp' \
	 | grep "/${PKG}_" | awk '{print $1}'| tr -d "'")

    if [ "${PKG_URI}" = "" ]; then
      PKG_URI=$(get_pkg_uri ${PKG})
    fi

    PKG_PROTOCOL=$(echo ${PKG_URI} | awk -F ":" '{print $1}')
    if [ "${PKG_PROTOCOL}" = "http" ] || [ "${PKG_PROTOCOL}" = "ftp" ]; then
      PKG_FILE=/tmp/$(basename $PKG_URI)
      _echo "  * Downloading ${PKG_URI}"
      wget -q "${PKG_URI}" -O ${PKG_FILE}
    elif [ "${PKG_PROTOCOL}" = "file" ]; then
      PKG_FILE=$(echo ${PKG_URI} | sed s/"file:"//g )
      echo "Using file:// protocol, package is in ${PKG_FILE} "
    else
      echo "Unknow PKG_URI=${PKG_URI} protocol: ${PKG_PROTOCOL} "
      error=1
      PKG_FILE=""
      echo "There are some errors during caching \"${PKG}\". PLEASE CHECK REPOSITORIES!!"
    fi
    dpkg -I ${PKG_FILE} >/dev/null 2>&1
    if [ $? -ne 0 ] || [ "${PKG_FILE}" = "" ] ; then
      echo "Error: Unknow package: ${PKG}"
      error=1
      echo "There are some errors during caching \"${PKG}\". PLEASE CHECK REPOSITORIES!!"
    else
      echo "Extracting $(basename ${PKG_FILE})..."
      VER=$(LC_ALL=C apt-cache policy ${PKG} | awk -F"Candidate: " '/Candidate/ {print $2}' | sed 's/[[:blank:]]*//g')
      rm -rf ${TCOS_PKG_CACHE}/${PKG}
      mkdir -p ${TCOS_PKG_CACHE}/${PKG}
      dpkg --extract "${PKG_FILE}" ${TCOS_PKG_CACHE}/${PKG}
      if [ "${PKG}" = "xserver-xorg-core" ];then
           echo ${VER} > ${TCOS_PKG_CACHE}/${PKG}/VERSION.xserver
      elif [ "${PKG}" = "libgl1-mesa-glx" ];then
           echo ${VER} > ${TCOS_PKG_CACHE}/${PKG}/VERSION.glx
      else
           echo ${VER} > ${TCOS_PKG_CACHE}/${PKG}/VERSION
      fi
      [ -e /tmp/$(basename $PKG_URI) ] && rm -f /tmp/$(basename $PKG_URI)
    fi
  done
  [ $error = 0 ] && echo "All package installed."
  [ $error != 0 ] && _exit 1
}

tcos_rm_pkg() {
  echo "Remove PKG \"$@\""
  for PKG in ${@}; do

    if [ -d "${TCOS_PKG_CACHE}/${PKG}" ]; then
      echo -n "Removing package ${PKG}..."
      rm -rf "${TCOS_PKG_CACHE}/${PKG}"
      echo " done."
    fi
  done
  _exit 0
}


fix_nvidia_ati() {
    tcos_inst_pkg "xserver-xorg-core libgl1-mesa-glx"
    rm -rf   ${TCOS_PKG_CACHE}/fix-nvidia-ati
    mkdir -p ${TCOS_PKG_CACHE}/fix-nvidia-ati

    [ -e ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/extensions/libglx.so ] && \
    mv ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/extensions/libglx.so \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libglx.so
       
    # libGLcore.so is not provided by xserver-xorg-core in >= 1.6
    [ -e ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/extensions/libGLcore.so ] && \
       mv ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/extensions/libGLcore.so \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libGLcore.so

    [ -e ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/libwfb.so ] && \
       mv ${TCOS_PKG_CACHE}/xserver-xorg-core/usr/lib/xorg/modules/libwfb.so \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libwfb.so
    
    [ -e ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/libGL.so.1.2 ] && \
    mv ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/libGL.so.1.2 \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libGL.so.1.2

    # multiarch support i386
    [ -e ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/i386-linux-gnu/libGL.so.1.2 ] && \
    mv ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/i386-linux-gnu/libGL.so.1.2 \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libGL.so.1.2

    # multiarch support amd64
    [ -e ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/x86_64-linux-gnu/libGL.so.1.2 ] && \
    mv ${TCOS_PKG_CACHE}/libgl1-mesa-glx/usr/lib/x86_64-linux-gnu/libGL.so.1.2 \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/libGL.so.1.2

    [ -e ${TCOS_PKG_CACHE}/xserver-xorg-core/VERSION.xserver ] && \
       mv ${TCOS_PKG_CACHE}/xserver-xorg-core/VERSION.xserver \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.xserver

    [ -e ${TCOS_PKG_CACHE}/libgl1-mesa-glx/VERSION.glx ] && \
       mv ${TCOS_PKG_CACHE}/libgl1-mesa-glx/VERSION.glx \
       ${TCOS_PKG_CACHE}/fix-nvidia-ati/VERSION.glx
       
    rm -rf ${TCOS_PKG_CACHE}/xserver-xorg-core
    rm -rf ${TCOS_PKG_CACHE}/libgl1-mesa-glx
    echo "NVIDIA/ATI cache done"
    [ ! -z $1 ] || _exit 0
}

for opt in $@ ; do
   case ${opt} in
        -h) _help
            _exit 0
            ;;
        -help) _help
            _exit 0
            ;;
        -c) TCOS_CDROM=1
            ;;
        -cdrom) TCOS_CDROM=1
            ;;
        -t) TCOS_TFTP=1
            ;;
        -tftp) TCOS_TFTP=1
            ;;
        -nfs) TCOS_NFS=1
            ;;
        -n) TCOS_NFS=1
            ;;
        -o=*) OUTINITRAMFS=${opt#-o=}
            ;;
        -b) TCOS_NBI=1 ;
		    TCOS_TFTP=1 
            ;;
        -nbi) TCOS_NBI=1 ;
		      TCOS_TFTP=1
            ;;
        -nbi-output=*) OUTNBI=${opt#-nbi-output=}
            ;;
        -extra-append=*) EXTRA_APPEND=${opt#-extra-append=}
            ;;
        -suffix=*) TCOS_SUFFIX=${opt#-suffix=}
            ;;
        -f) TCOS_FORCE=1
            ;;
        -v) MKVERBOSE="-v"
            ;;
        -force) TCOS_FORCE=1
            ;;
        -type=*) 
          	TYPE=${opt#-type=} ;
			TCOS_CDROM=1
            ;;
        -vmlinuz=*) 
          	TCOS_VMLINUZ=${opt#-vmlinuz=} ;
            ;;
        -size)
            TCOS_SIZE=1
            ;;
        -allmodules) TCOS_ALL_MODULES=1
            ;;
        -extramodules=*) TCOS_EXTRA_MODULES="${TCOS_EXTRA_MODULES},"${opt#-extramodules=}
            ;;
        -rootfs)
            TCOS_ROOTFS=1
            ;;
        -instpkg) tcos_inst_pkg "${@#-instpkg}"; _exit 0
            ;;
        -rmpkg) tcos_rm_pkg "${@#-rmpkg}"; _exit 0
            ;;
        -listpkg) list_pkg
            ;;
        -fix-nvidia-ati) fix_nvidia_ati
            ;;
        -parse-pxelinuxcfg)
            parse_pxelinuxcfg
            _exit 0
            ;;
        --*)
            echo "Double -- is not accepted as command line parameter."
            echo "See $0 -help to know about usage"
            _exit 1
            ;;
	esac
done






################# START APP here ############################

if [ ! -d /lib/modules/${TCOS_KERNEL} ]; then
   echo "Error: kernel ${TCOS_KERNEL} not found."
   _exit 1
fi

# link vmlinuz in TFTP_DIR
link_vmlinuz

# check for unionfs and squashfs
check_modules

# check for XFS setup
# check_xfs

# make a pxelinux.cfg/default with this kernel
#parse_pxelinuxcfg




OUTINITRAMFS=initramfs-${TCOS_KERNEL}
OUTNBI=linux-${TCOS_KERNEL}.nbi


# disable usr.squashfs external file (need into initramfs)
if [ $TCOS_CDROM ] ; then
  export TCOS_SQUASHFS=
fi

# add suffix to usr.squashfs into hooks/tcosbin
if [ $TCOS_SUFFIX ]; then
  export TCOS_SUFFIX
fi

# generate allmodules.squashfs to teast all hardware in terminal
if [ $TCOS_ALL_MODULES ]; then
  export TCOS_ALL_MODULES
fi

# Check if cached packages need update only if action is regenerate image
if [ $TCOS_PKG_CACHE_LIST ];then
  export TCOS_PKG_CACHE_LIST
  check_cached_packages
fi

if [ ! -z $TCOS_CDROM ]; then
 if [ ${TCOS_SQUASHFS} ]; then
   echo "Can build external usr.squashfs to use in cdrom iso."
   echo "Edit ${TCOS_CONF}/tcos.conf and set TCOS_DISABLE_SQUASHFS=1 or TCOS_SQUASHFS="
   if [ ! ${TCOS_FORCE} ]; then
     echo "  Use [-f | -force]  to continue."
     _exit 1
   fi
 fi
fi


# default isolinux
if [ ! -z $TCOS_CDROM ]; then
  create_isolinux_iso
fi



if [ ! -z $TCOS_TFTP ]; then
 if [ ! -f ${INITRAMFS} ]; then
   create_initramfs
 fi

 if [ $TCOS_NBI ]; then
   cp ${INITRAMFS} /tmp/initramfs-${TCOS_KERNEL}
   create_nbi
 fi

 # don't overwrite initramfs if we are generating NBI image
 if [ ! ${TCOS_NBI} ]; then
  _echo "Copying initramfs to ${TFTP_DIR}/${OUTINITRAMFS}${TCOS_SUFFIX}" 
  cp ${INITRAMFS} ${TFTP_DIR}/${OUTINITRAMFS}${TCOS_SUFFIX}
 fi

 if [ $TCOS_NBI ]; then
   _echo "Moving nbi image to ${TFTP_DIR}/${OUTNBI}${TCOS_SUFFIX}"
   cp ${TMPNBI} ${TFTP_DIR}/${OUTNBI}${TCOS_SUFFIX}
 fi

fi

if [ $TCOS_NFS ]; then
  create_initramfs_nfs
  _echo "Copying initramfs to ${TFTP_DIR}/${OUTINITRAMFS}-nfs" 
  cp ${INITRAMFS}-nfs ${TFTP_DIR}/${OUTINITRAMFS}-nfs
fi

if [ $TCOS_ROOTFS ]; then
  create_rootfs
fi

if [ $TCOS_SIZE ]; then
  ramdisk_size
fi

parse_pxelinuxcfg
_exit 0
