#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Description: output the pxelinux default

# Load DRBL setting and functions
if [ ! -f "/opt/drbl/sbin/drbl-conf-functions" ]; then
  echo "Unable to find /opt/drbl/sbin/drbl-conf-functions! Program terminated!" 
  exit 1
fi
. /opt/drbl/sbin/drbl-conf-functions

export LC_ALL=C
#
USAGE() {
  echo "Generate the PXELINUX menu for DRBL clients."
  echo "Usage: $(basename $0) [OPTION]"
  echo "Options:"
  echo "-c, --console OPT: set the console output parameters."
  echo "-s, --serial OPT:  set the PXE menu to work with serial console output."
  echo "-g, --graphic [y|n]:  Option to set client to use graphical mode or not when booting GNU/Linux (now only for Fedora Core)"
  echo "-m, --pxe-mode [text|graphic]:  Set the default PXE linux menu mode to text or graphic"
  echo "-v, --verbose:  verbose mode."
  echo "Ex:"
  echo "To create the console output in DRBL client:"
  echo "$(basename $0) -v -s \"serial 0 38400\" -c \"console=ttyS0,38400n81 console=tty0\" "
  echo "Note! You must put the \" before and after your serial OPT and console OPT."
}

# default settings
pxe_mode="graphic"

#
check_if_root

# Parse command-line options
while [ $# -gt 0 ]; do
  case "$1" in
    -s|--serial)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              PXE_SERIAL_OUTPUT="$1"
              shift
            fi
	    [ -z "$PXE_SERIAL_OUTPUT" ] && USAGE && exit 1
	    ;;
    -c|--console)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              CONSOLE_OUTPUT="$1"
              shift
            fi
	    [ -z "$CONSOLE_OUTPUT" ] && USAGE && exit 1
	    ;;
    -f|--fdos)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              fdos_img_output="$1"
              shift
            fi
	    [ -z "$fdos_img_output" ] && USAGE && exit 1
	    ;;
    -g|--graphic)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              graphical_boot="$1"
              shift
            fi
	    [ -z "$graphical_boot" ] && USAGE && exit 1
	    ;;
    -m|--pxe-mode)  
            shift;
            # skip the -xx option, in case 
	    if [ -z "$(echo $1 |grep ^-.)" ]; then
	      pxe_mode="$1"
	      shift
            fi
            ;;
    -v|--verbose)
            shift; verbose="on"
            ;;
    -*)     echo "${0}: ${1}: invalid option" >&2
            USAGE >& 2
            exit 2 ;;
    *)      break ;;
  esac
done

# fdos_img_output should be in /opt/drbl/conf/drbl.conf
[ -z "$fdos_img_output" ] && echo "You must provide the FreeDOS image filename! Program terminated!!!" && exit 1

# if console output is assign, default to use menu.c32 instead of vesamenu.c32
if [ -n "$CONSOLE_OUTPUT" ]; then
  pxe_mode="text"
fi

echo "Generating default pxelinux config ($PXELINUX_DIR/default)..."
# clean the old one
[ -f "$PXELINUX_DIR/default" ] && rm -f $PXELINUX_DIR/default

# get the OS_Version and OS_type
check_distribution_name

# $graphical_boot is in drbl.conf or from command parameter.
case "$graphical_boot" in
  y|Y|[yY][eE][sS])
    case "$OS_Version" in
      FC*)
        echo "Use graphical boot for DRBL Fedora Core client..."
        # We'd better use "rhgb" instead of "quiet rhgb" since if something goes wrong in net initrd, it's not easy to debug.
        drbl_dist_append="rhgb"
        ;;
    esac
    ;;
  n|N|[nN][oO])
    drbl_dist_append=""
    ;;
esac
#
# PXE Linux menu mode
case "$pxe_mode" in
  text*|TEXT*) MENUC32="menu.c32" ;;
  graphic*|GRAPHIC*) MENUC32="vesamenu.c32" ;;
esac
# find the drbl background logo and memtest
drbl_logo="$(basename $pxelinux_bg_img)"
# get memtest filename
memtest_filename="$(basename $memtest86_file)"
# show some prompts
echo "Use com32 module: $MENUC32"
[ -n "$PXE_SERIAL_OUTPUT" ] && echo "PXE serial output param: $PXE_SERIAL_OUTPUT"
[ -n "$CONSOLE_OUTPUT" ] && echo "Linux console output param: $CONSOLE_OUTPUT"
[ -n "$drbl_dist_append" ] && echo "Extra param: $drbl_dist_append"

# read drbl_deploy.conf if this program is run again after drblpush is done.
[ -f /etc/drbl/drbl_deploy.conf ] && . /etc/drbl/drbl_deploy.conf
[ "$drbl_mode" = "drbl_ssi_mode" ] && drbl_mode_opt="clientdir=node_root"
[ "$clonezilla_mode" = "clonezilla_box_mode" ] && clonezilla_mode_opt="clientdir=node_root"

# Get version number. 
case "$OS_Version" in
   RH*|FC*|CO*|MDK*|MDV*|SUSE*)
      drbl_ver="$(rpm -q drbl | sed -e "s/^drbl-//g")"
      ocs_ver="$(rpm -q clonezilla | sed -e "s/^clonezilla-//g")"
      memtest_ver="$(cat $pxecfg_pd/MEMTEST86+_VERSION)"
      ;;
   DBN*)
      drbl_ver="$(dpkg -l drbl | tail -n 1 | awk -F" " '{print $3}')"
      ocs_ver="$(dpkg -l clonezilla | tail -n 1 | awk -F" " '{print $3}')"
      memtest_ver="$(cat $pxecfg_pd/MEMTEST86+_VERSION)"
      ;;
esac
[ -z "$drbl_ver" ] && drbl_ver="Unknown"
[ -z "$ocs_ver" ] && ocs_ver="Unknown"

#
[ -f "$PXELINUX_DIR/default" ] && mv -f $PXELINUX_DIR/default $PXELINUX_DIR/default.drblsaved
echo "Adding menus for DRBL, local boot, memtest86+, FreeDOS..."
cat <<-PXE_END > $PXELINUX_DIR/default
# Created by generate-pxe-menu! Do NOT edit unless you know what you are doing! 
# Keep those comment "MENU DEFAULT" and "MENU HIDE"! Do NOT remove them.
# Note!!! If "serial" directive exists, it must be the first directive
$PXE_SERIAL_OUTPUT
default $MENUC32
timeout 70
prompt 0
noescape 1
MENU MARGIN 5
MENU BACKGROUND ${drbl_logo}
# Set the color for unselected menu item and timout message
MENU COLOR UNSEL 7;32;41 #c0000090 #00000000
MENU COLOR TIMEOUT_MSG 7;32;41 #c0000090 #00000000
MENU COLOR TIMEOUT 7;32;41 #c0000090 #00000000
MENU COLOR HELP 7;32;41 #c0000090 #00000000

# MENU MASTER PASSWD

say **********************************************
say Welcome to DRBL.
say NCHC Free Software Labs, Taiwan.
say http://drbl.nchc.org.tw; http://drbl.sf.net
say **********************************************

# Do NOT allow client to edit the parameters
ALLOWOPTIONS 0

# simple menu title
MENU TITLE DRBL (http://drbl.nchc.org.tw, http://drbl.sf.net)

label drbl
  MENU DEFAULT
  # MENU HIDE
  MENU LABEL $FULL_OS_Version $powerful_client_menu_label
  # MENU PASSWD
  kernel vmlinuz-pxe
  append initrd=initrd-pxe.img devfs=nomount drblthincli=off selinux=0 $CONSOLE_OUTPUT $drbl_mode_opt $drbl_dist_append
  TEXT HELP
  * DRBL version: $drbl_ver. (C) 2003-2008, NCHC, Taiwan
  * Disclaimer: DRBL comes with ABSOLUTE NO WARRANTY
  ENDTEXT

label clonezilla
  # MENU DEFAULT
  MENU HIDE
  MENU LABEL Clonezilla
  # MENU PASSWD
  kernel vmlinuz-pxe
  append initrd=initrd-pxe.img devfs=nomount drblthincli=off selinux=0 1 $CONSOLE_OUTPUT $clonezilla_mode_opt $drbl_dist_append
  TEXT HELP
  * Clonezilla version: $ocs_ver. (C) 2003-2008, NCHC, Taiwan
  * Disclaimer: Clonezilla comes with ABSOLUTE NO WARRANTY
  ENDTEXT

label local
  # MENU DEFAULT
  # MENU HIDE
  MENU LABEL $local_os_menu_label
  # MENU PASSWD
  # 2 method to boot local device:
  # (1) For localboot 0, it is decided by boot order in BIOS, so uncomment the follow 1 line if you want this method:
  # localboot 0

  # (2) For chain.c32, you can assign the boot device.
  # Ref: extlinux.doc from syslinux
  # Syntax: APPEND [hd|fd]<number> [<partition>]
  # [<partition>] is optional.
  # Ex:
  # Second partition (2) on the first hard disk (hd0);
  # Linux would *typically* call this /dev/hda2 or /dev/sda2, then it's "APPEND hd0 2"
  #
  kernel chain.c32
  append hd0
  TEXT HELP
  Boot local OS from first hard disk if it's available
  ENDTEXT

# Note! *.bin is specially purpose for syslinux, 
# Do NOT use memtest86.bin, use memtest86 instead of memtest86.bin
label memtest
  # MENU DEFAULT
  # MENU HIDE
  MENU LABEL Memory test using Memtest86+
  # MENU PASSWD
  kernel $memtest_filename
  TEXT HELP
  Run memory test using Memtest86+ $memtest_ver
  ENDTEXT

# ref: http://syslinux.zytor.com/memdisk.php
label fdos
  # MENU DEFAULT
  MENU HIDE
  MENU LABEL FreeDOS
  # MENU PASSWD
  kernel memdisk
  append initrd=$fdos_img_output
  TEXT HELP
  Run FreeDOS
  ENDTEXT

label drbl-terminal
  # MENU DEFAULT
  MENU HIDE
  MENU LABEL $FULL_OS_Version $thin_client_menu_label
  # MENU PASSWD
  kernel vmlinuz-pxe
  append initrd=initrd-pxe.img devfs=nomount drblthincli=on
  TEXT HELP
  Run DRBL in terminal mode.
  ENDTEXT

PXE_END

# output the netinstall menu
# Here 2 types: Linux and BSD
# The netinstall kernel files (linux) or pxeboot file (bsd) in /tftpboot/nbi_img are, e.g.:
# Type 1: for Linux, the file names are like:
# vmlinuz-netinstall-CentOS-4.6-i386
# vmlinuz-netinstall-CentOS-4.6-x86_64
# vmlinuz-netinstall-CentOS-5.1-i386
# vmlinuz-netinstall-CentOS-5.1-x86_64
# vmlinuz-netinstall-Debian-etch-amd64
# vmlinuz-netinstall-Debian-etch-i386
# vmlinuz-netinstall-Debian-sarge-i386
# vmlinuz-netinstall-Fedora-7-i386
# vmlinuz-netinstall-Fedora-7-x86_64

# Type 2: for BSD, the file names are like:
# OpenBSD-4.2-i386-pxeboot.0
# FreeBSD-7.0-i386-pxeboot.0

# Type 1: Linux
for inet in $pxecfg_pd/vmlinuz-netinstall-*; do
   # /tftpboot/nbi_img/vmlinuz-netinstall-CentOS-4-i386
   # /tftpboot/nbi_img/initrd-netinstall-CentOS-4-i386.img

   [ ! -e "$inet" ] && continue
   # Truncate "vmlinuz-"
   # For debina based, back convert x86-64 to x86_64, since alien convert x86_64 to x86-64.
   kernel="$(basename $inet)"
   inet_="$(basename $inet | sed -e "s/^vmlinuz-//g" -e "s/x86-64/x86_64/g")"
   img_menu="$(echo "$inet_" | awk -F"-" '{print $1"-"$2"-"$3"-"$4}')"
   img="$(unalias ls 2>/dev/null; ls $pxecfg_pd/*${inet_}* 2>/dev/null)"
   img="$(basename $img)"

   extra_append=""
   if [ -n "$(echo $inet | grep -i "\-debian-sarge" 2>/dev/null)" ]; then
      # For Debian Sarge, we need extra options in append
      # refer to http://opensource.nchc.org.tw/debian/dists/sarge/main/installer-i386/current/images/netboot/pxelinux.cfg/default
      NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      extra_append="root=/dev/rd/0 devfs=mount,dall rw  --"
   elif [ -n "$(echo $inet | grep -i "\-debian-woody" 2>/dev/null)" ]; then
      # For Debian Woody, we use extra options bf24
      # refer to http://www.debianplanet.com/node.php?id=818&cid=13384
      NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      extra_append="flavor=bf2.4"
   elif [ -n "$(echo $inet | grep -iE "\-redhat-" 2>/dev/null)" ]; then
      # For RedHat, enable reiserfs when installing
      NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      extra_append="reiserfs"
   elif [ -n "$(echo $inet | grep -iE "\-fedora-" 2>/dev/null)" ]; then
      # ramdisk_size only necessary for fedora 1-4, from fc5, it's initramfs, ramdisk_size is not used anymore 
      if [ -n "$(echo $inet | grep -iE "\-fedora-[1-4]-" 2>/dev/null)" ]; then
        NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      else
        NETINSTALL_RAMDISK_SIZE=""
      fi
      # For Fedora, enable reiserfs when installing
      extra_append="reiserfs"
   elif [ -n "$(echo $inet | grep -iE "(\-mandrake-|\-mandriva-)" 2>/dev/null)" ]; then
      # For Mandrake/Mandriva
      # use larger ramdisk size for Mandrake, overwrite the default one.
      NETINSTALL_RAMDISK_SIZE=128000
      extra_append="acpi=ht vga=788 splash=silent label vgalo"
   elif [ -n "$(echo $inet | grep -i "\-ubuntu-feisty" 2>/dev/null)" ]; then
      # For Ubuntu Feisty (7.04)
      # ref to http://opensource.nchc.org.tw/ubuntu/dists/feisty/main/installer-i386/current/images/netboot/ubuntu-installer/i386/pxelinux.cfg/default
      # It's initramfs, so ramdisk_size is no more.
      NETINSTALL_RAMDISK_SIZE=""
      extra_append="vga=normal --"
   elif [ -n "$(echo $inet | grep -i "\-ubuntu-" 2>/dev/null)" ]; then
      # For other Ubuntu: 5.10, 6.06, 6.10
      # ref to ftp://linux.nchc.org.tw/distributions/ubuntu/dists/hoary/main/installer-i386/current/images/netboot/ubuntu-installer/i386/pxelinux.cfg/default
      NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      extra_append="root=/dev/rd/0 rw  --"
   elif [ -n "$(echo $inet | grep -i "\-suse-" 2>/dev/null)" ]; then
      # For SuSE
      # For extra_append, refer to something like 
      # http://free.nchc.org.tw/SuSE/SuSE/i386/9.3/boot/loader/isolinux.cfg
      # use larger ramdisk size, overwrite the default one.
      NETINSTALL_RAMDISK_SIZE=128000
      extra_append="splash=silent showopts"
   elif [ -n "$(echo $inet | grep -i "\-opensuse-" 2>/dev/null)" ]; then
      # For OpenSuSE
      # For extra_append, refer to something like 
      # http://ftp.cs.pu.edu.tw/Linux/OpenSuse/distribution/SL-10.0-OSS/inst-source/boot/loader/isolinux.cfg
      # use larger ramdisk size, overwrite the default one.
      NETINSTALL_RAMDISK_SIZE=128000
      extra_append="splash=silent showopts"
   else
      NETINSTALL_RAMDISK_SIZE="$NETINSTALL_RAMDISK_SIZE_DEF"
      extra_append=""
   fi

   # skip if we can not find the menu, img or kernel.
   [ -z "$img_menu" ] && continue
   [ -z "$img" -o -z "$kernel" ] && continue

   echo "Adding $img_menu menu..."
   [ -n "$verbose" ] && echo "extra option in append: $extra_append"    
   # Generate the description:
   # EX for i: rh-8.0-netinstall
   # create the description for the netinstall image
   des="$(echo $img_menu | sed -e "s/^netinstall-//g" | sed -e "s/-/ /g")"
   des="${des} installation via network"
   # For initramfs, ramdisk_size is no more.
   if [ -n "$NETINSTALL_RAMDISK_SIZE" ]; then
     ramdisk_size_opt="ramdisk_size=$NETINSTALL_RAMDISK_SIZE"
   else
     ramdisk_size_opt=""
   fi
   cat <<-PXE_END >> $PXELINUX_DIR/default
label $img_menu
  # MENU DEFAULT
  MENU HIDE
  MENU LABEL $des
  # MENU PASSWD
  kernel $kernel
  append initrd=$img $ramdisk_size_opt $extra_append
  TEXT HELP
  $des
  ENDTEXT

PXE_END
done

# Type 2: BSD
for inet in $pxecfg_pd/*-pxeboot.0; do
   # Ex: /tftpboot/nbi_img/FreeBSD-7.0-i386-pxeboot.0
   [ ! -e "$inet" ] && continue
   # Truncate "-pxeboot.0"
   inet_="$(basename $inet | sed -e "s/-pxeboot.0//g")"
   img_menu="$(echo "$inet_" | awk -F"-" '{print $1"-"$2"-"$3}')-netinstall"
   img="$(unalias ls 2>/dev/null; ls $pxecfg_pd/*${inet_}* 2>/dev/null)"
   img="$(basename $img)"
   # create the description for the netinstall image
   des="$(echo $img_menu | sed -e "s/-netinstall$//g" | sed -e "s/-/ /g")"
   des="${des} installation via network"
   [ -z "$img_menu" ] && continue
   echo "Adding $img_menu menu..."
   cat <<-PXE_END >> $PXELINUX_DIR/default
label $img_menu
  # MENU DEFAULT
  MENU HIDE
  MENU LABEL $des
  # MENU PASSWD
  kernel $img
  TEXT HELP
  $des
  ENDTEXT

PXE_END
done

echo "done!"
