#! /bin/sh
#
# main script running inside initial ramdisk
#
# part of the LiveBackup project:  
#
#                     http://livebackup.sourceforge.net/
#
# Copyright 2006-2010 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-2010\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
POLICYFILE="Readme.LiveBackup"
HWDETECT="not_set"
LB_SWAP="no"
DEVLOCK="no"
COPY2RAM="no"
MEM_ALLOCATED=0
MEDIAEJECT="yes"
CONSOLE="default"
COLOR="yes"
VERBOSITY=10
MEDIADEV="not_set"
INITRAMFS="yes"
MD5VERIFY="no"
XCMD=""
AUTOUPDATE=""
ADDRESS="not_set"
NFSMOUNT="not_set"
NETMASK="255.255.255.0"
GATEWAY="0.0.0.0"
INTERFACE="eth0"
WGETARGS="not_set"
MASTERSIZE="10M"
HARDWARE="not_set"
DISCOVER=""
MAJOR=1
MINOR=0
MOUNTED_MEDIA_DEVICE=""
WIPEOUTMODULES="no"

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


#
# 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="128M"

#
# 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_discover" ];       then DISCOVER="yes"; fi

    if [ "$key" = "lb_lock" ];           then DEVLOCK="yes"; fi

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

    if [ "$key" = "lb_update" ];         then AUTOUPDATE="yes"; fi

    if [ "$key" = "lb_modclean" ];       then WIPEOUTMODULES="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_policyfile" ]; then 
	POLICYFILE=$value
    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_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)
#
execute essential



#
# 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
    HARDWARE=\"$(discover-show | tr -d '\n')\"
fi


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

#
# detect media and mount master directory
#
execute netconf
execute mount_nfs
execute netload
execute mount_media
execute drive_settings
execute search_image
execute verify_image
execute copy2ram
execute mount_image
execute mount_nested_image

#
# 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





