#! /bin/sh
#
# main script running inside initial ramdisk
#
# part of the LiveBackup project:  
#
#                     http://livebackup.sourceforge.net/
#
# Copyright 2007 by Wolfgang Rohrmoser <info@rohrmoser-engineering.de>
#
#    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 St, Fifth Floor, Boston, MA  02110-1301  USA
#



if [ -f /etc/version ]; then
    VERSION=$(cat /etc/version)
fi

BOOT_MSG="\nLiveBackup $VERSION \nhttp://livebackup.sourceforge.net\n(c) W.Rohrmoser 2006-2008\n\n"


#
# initialize 
#
. /lib/LiveBackup/rc.LiveBackup

# set mount point to MEDIA_MNT, this will change if copy2ram gets used
MASTER_MNT="$MEDIA_MNT"     

#
# show progress if splash screen is used
#
inc_progress_bar

#
# mount kernel fs /proc 
#
mount -n -t proc /proc /proc
CMDLINE="$(cat /proc/cmdline)"


# default values
SYSTEM="not_set"
SYSTEM_MOUNT_OPTS=""
LB_CONFIG="_default_"
ROOTPATH=/rootfs
LB_DEBUG=0
HWDETECT="not_set"
LB_SWAP="no"
COPY2RAM="50%"
MEM_ALLOCATED=0
MEDIAEJECT="yes"
CONSOLE="default"
COLOR="yes"
VERBOSITY=10
MEDIADEV="not_set"
INITRAMFS="yes"
MD5VERIFY="no"
ISOFILE="not_set"
XCMD=""
ADDRESS="not_set"
NFSMOUNT="not_set"
NETMASK="255.255.255.0"
GATEWAY="0.0.0.0"
INTERFACE="eth0"
WGETARGS="not_set"
MASTERSIZE="10M"
DISCOVER="not_set"
MAJOR=1
MINOR=0


export SYSTEM
export SYSTEM_MOUNT_OPTS
export LB_CONFIG
export ROOTPATH
export LB_DEBUG
export HWDETECT
export LB_SWAP
export COPY2RAM
export MEM_ALLOCATED
export MEDIAEJECT
export CONSOLE
export COLOR
export VERBOSITY
export MEDIADEV
export INITRAMFS
export MD5VERIFY
export ISOFILE
export XCMD
export ADDRESS
export NFSMOUNT
export NETMASK
export GATEWAY
export INTERFACE
export WGETARGS
export MASTERSIZE
export DISCOVER
export MAJOR
export MINOR




#
# select default technology
#

#
# unionfs settings:  LB_METHOD=unionfs; LB_METHOD_OPT=<size root fs>
#
LB_METHOD="unionfs"
LB_METHOD_OPT="64M"

#
# aufs settings:  LB_METHOD=aufs; LB_METHOD_OPT=<size root fs>
#
# LB_METHOD="aufs"
# LB_METHOD_OPT="64M"

#
# use symlinks to ramdisk settings: LB_METHOD=symlinks; LB_METHOD_OPT=<size ramfs>
#
# LB_METHOD="symlinks"
# LB_METHOD_OPT="32M"


# LB_METHOD="dmsnapshot"
# LB_METHOD_OPT=""

export LB_METHOD
export LB_METHOD_OPT


#
# parse options:
#
for token in $CMDLINE; do 

    key=$(echo $token | cut -f1 -d "=")
    value=$(echo $token | cut -s -f2-10 -d "=")

    if [ "$key" = "?" ]; then 
        # ToDo! more does not work yet!
	cat usage.txt
        sleep 120 
    fi

    if [ "$key" = "lb_system" ]; then 
	SYSTEM=$(echo $value | cut -f 1 -d ':') 
	SYSTEM_MOUNT_OPTS=$(echo $value | cut -s -f 2 -d ':') 
    fi
    
    if [ "$key" = "lb_config" ];         then LB_CONFIG=$value; fi

    if [ "$key" = "lb_hwdetect" ]; then
	if [ "$value" ]; then 
            HWDETECT="$value";
        else 
            HWDETECT="$MEDIA_MNT/hwdetect";
        fi
    fi

    if [ "$key" = "lb_swap" ];           then LB_SWAP="yes"; fi

    if [ "$key" = "lb_verify" ];         then MD5VERIFY="yes"; fi

    if [ "$key" = "lb_toram" ]; then 
	if [ "$value" ]; then
	    COPY2RAM=$value
	else
	    COPY2RAM="50%"
	fi
    fi

    if [ "$key" = "lb_rootdev" ]; then
        MAJOR=$(echo $value | cut -f 1 -d ':')
        MINOR=$(echo $value | cut -s -f 2 -d ':')
    fi

    if [ "$key" = "lb_skip" ];            then SKIP="yes"; fi


    if [ "$key" = "lb_noeject" ];         then MEDIAEJECT="no"; fi

    if [ "$key" = "lb_debug" ]; then 
	if [ "$value" ]; then 
	    LB_DEBUG=$value 
	else 
	    LB_DEBUG=100
	fi
    fi

    if [ "$key" = "lb_unionfs" ]; then 
	LB_METHOD="unionfs"
	if [ "$value" ]; then
	    LB_METHOD_OPT=$value 
	else
	    LB_METHOD_OPT="64M"
	fi
    fi

    if [ "$key" = "lb_aufs" ]; then 
	LB_METHOD="aufs"
	if [ "$value" ]; then
	    LB_METHOD_OPT=$value
	else
	    LB_METHOD_OPT="64M"
	fi
    fi

    if [ "$key" = "lb_symlinks" ]; then 
	LB_METHOD="symlinks"
	if [ "$value" ]; then
	    LB_METHOD_OPT=$value; 
	else
	    LB_METHOD_OPT="64M"
	fi
    fi

    if [ "$key" = "lb_dm" ]; then 
	LB_METHOD="dmsnapshot"
	if [ "$value" ]; then
	    LB_METHOD_OPT=$value; 
	else
	    LB_METHOD_OPT="64M"
	fi
    fi

    if [ "$key" = "lb_device" ];         then MEDIADEV=$value; fi
    if [ "$key" = "lb_isofile" ];        then ISOFILE=$value; fi

    if [ "$key" = "lb_console" ];        then CONSOLE=$value; fi
    if [ "$key" = "lb_NOcolor" ];        then COLOR="no"; fi
    if [ "$key" = "lb_verbosity" ];      then VERBOSITY=$value; fi

    if [ "$key" = "lb_xcmd" ]; then 
        XCMD="$(echo $value | sed s/%/\ /g)"
    fi

    if [ "$key" = "lb_address" ];         then ADDRESS=$value; fi
    if [ "$key" = "lb_netmask" ];         then NETMASK=$value; fi
    if [ "$key" = "lb_gateway" ];         then GATEWAY=$value; fi
    if [ "$key" = "lb_interface" ];       then INTERFACE=$value; fi

    if [ "$key" = "lb_wget" ]; then 
        WGETARGS="$(echo $value | sed s/%/\ /g)"
    fi

    if [ "$key" = "lb_nfsmount" ];        then NFSMOUNT=$value; fi

    if [ "$key" = "lb_mastersize" ];      then MASTERSIZE=$value; fi

done

#
# check if we use initramfs
#
grep -q "root.old" /proc/mounts
if [ $? -eq 0 ]; then 
  INITRAMFS="no"
fi

#
# copy2ram is sensless for network boot
#
if [ "$WGETARGS" != "not_set" ]; then
    COPY2RAM="no"
fi

#
# get kernel version
#
kversion=`uname -r`
export kversion

#
# user message
#
msg -e -i "$BOOT_MSG"
msg -e -i "linux kernel: $kversion"
msg -e -i "boot options: $CMDLINE"
msg -e -i "start system: $SYSTEM"

inc_progress_bar

#
echo "/sbin/modprobe" > /proc/sys/kernel/modprobe

#
# insert all modules (necessary to access boot media)
#
msg -i -n "loading essential kernel modules "

if [ -f /etc/modules ]; then
    modules=$(cat /etc/modules | grep -v ^#)
else
    modules=""
    for name in $(ls -1 /lib/modules/$kversion/*.ko); do
        modules="$modules $(basename $name .ko)"
    done
fi

for module in $modules; do
    inc_progress_bar

    if [ $LB_DEBUG -gt 50 ]; then
        msg -i -e -n "\n$module : "
        modprobe -v $module 
    else
        modprobe $module > /dev/null 2>&1
        if [ $? -eq 0 ]; then 
            msg -i -n "."
        else	
            msg -i -n "-"
        fi
    fi
done

msg -i " done"


#
# execute command from boot option first 
#
if [ "$XCMD" ]; then
    msg -i "executing extra command: $XCMD"
    $XCMD
    if [ $? -ne 0 ]; then
        msg -c "\n\nERROR: $XCMD failed!"
        rescue_shell "please check, system will continue boot procedure after exit"
    fi
fi

#
# Discover hardware detection can be build into initrd by option.
# If it is available store its result in environment.
#
if [ "$(which discover-show)" ]; then
    DISCOVER=\"$(discover-show | tr -d '\n')\"
fi


#
#  just start after modules are loaded
#
if [ "$SKIP" == "yes" ]; then
    execute runinit
fi


#
# Run stage1 according to selected technologie.
#  
#  - mount a writable rootfilesystem at $ROOTPATH
#  - provide basic devices in /dev 
#

case $LB_METHOD in

    unionfs)
    . /lib/LiveBackup/unionfs
    ;;

    aufs)
    . /lib/LiveBackup/aufs
    ;;

    symlinks)
    . /lib/LiveBackup/symlinks
    ;;

    dmsnapshot)
    . /lib/LiveBackup/dmsetup
    ;;

    *)
    msc -c "CRITICAL: do not know how to continue"
    exit 0
    ;;
    
esac

# provide kernel modules in $ROOTPATH 
execute kmodules 

# prepare $ROOTPATH to enter _stage2
execute prepare_stage2

#
# some debug messages
#
if [ $LB_DEBUG -gt 10 ]; then 
    msg -c "entering stage2:"  
    msg -n -i "<ret> (continue) | v <ret> (verbose) | d <ret> (debug shell): "
    read ans
    if [ "$ans" = "d" ]; then
	rescue_shell
	msg -c "continue with stage2:"  
	msg -n -i "<ret> (continue) | v <ret> (verbose): "
	read ans
    fi
    if [ "$ans" = "v" ]; then
	set -x
    fi
fi


#
# execute stage2 in a new root environment
#
if [ $INITRAMFS = "yes" ]; then
    exec switch_root $ROOTPATH /lib/LiveBackup/_stage2
    rescue_shell "FATAL: you should never be here, try to find out why..."
else
    # change to new root directory, old root is still mounted under initrd/ 
    mkdir -p $ROOTPATH/initrd
    cd $ROOTPATH
    pivot_root . initrd
    /bin/sh /initrd/lib/LiveBackup/_stage2 < /dev/console > /dev/console 2>&1
fi





