#!/bin/bash
#================
# FILE          : linuxrc
#----------------
# PROJECT       : openSUSE KIWI Image System
# COPYRIGHT     : (c) 2006 SUSE LINUX Products GmbH. All rights reserved
#               :
# AUTHOR        : Marcus Schaefer <ms@suse.de>
#               :
# BELONGS TO    : Operating System images
#               :
# DESCRIPTION   : This file is changed to become the real
#               : linuxrc script which is used to prepare the
#               : operating system for the main image
#               :
#               :
# STATUS        : BETA
#----------------
#======================================
# Exports (General)
#--------------------------------------
export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export IFS_ORIG=$IFS
export input=/part.input
export ARCH=`arch`
export DEBUG=0

#======================================
# Exports (Booting)
#--------------------------------------
export INITRD_MODULES=""
export LOCAL_BOOT="no"
export KERNEL_LIST

#======================================
# Exports (Alias)
#--------------------------------------
export SYSALIAS="undefined"
export NAME=0

#======================================
# Exports (Status)
#--------------------------------------
export SYSTEM_INTEGRITY
export SYSTEM_MD5STATUS
export systemIntegrity="unknown"
export haveDisk=0
export partOK=0
export haveRamDisk=0

#======================================
# Exports (clicfs usage)
#--------------------------------------
export kiwi_hybrid=true
export kiwi_hybridpersistent=true

#======================================
# Exports kernel options
#--------------------------------------
export kernel_cmdline=($@)

#======================================
# Functions
#--------------------------------------
. /include
initialize

#======================================
# Start logging
#--------------------------------------
errorLogStart

#======================================
# recreateVTOCTable
#--------------------------------------
function recreateVTOCTable {
    # /.../
    # re-create VTOC and delete all partitions
    # ----
    Echo "Recreate VTOC table [ $imageDiskDevice ]"
    createPartitionerInput r y w
    callPartitioner $input
    rm -f $input
}

#======================================
# Update library path
#--------------------------------------
ldconfig

#======================================
# 1) Mounting local file systems
#--------------------------------------
mountSystemFilesystems &>/dev/null

#======================================
# 2) Prepare module load support 
#--------------------------------------
touch /etc/modules.conf
touch /lib/modules/*/modules.dep
runHook init

#======================================
# 3) run udevd
#--------------------------------------
udevStart

#======================================
# 4) Include proc/cmdline information
#--------------------------------------
includeKernelParametersLowerCase
if [ ! -z "$IMAGE" ];then
    # /.../
    # if the image information is already in place at this stage
    # it comes from the cmdline data which means we are not booting
    # from the network but want to boot the local system
    # ----
    LOCAL_BOOT="yes"
fi

#======================================
# 5) start boot shell
#--------------------------------------
startShell

#======================================
# 6) probe/load network module
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
    loadNetworkCard
    setupNetworkInterfaceS390
fi

#======================================
# 7) Setup network interface and DNS
#--------------------------------------
runHook prenetwork
if [ $LOCAL_BOOT = "no" ];then
    setupNetworkStatic 1
fi
runHook postnetwork

#======================================
# 8) get TFTP Server IP/name
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
    pxeSetupDownloadServer
    startDropBear
fi

#======================================
# 9) Load configuration
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
    CONFIG=/etc/config.netclient
    #======================================
    # Store possible values set by cmdline
    #--------------------------------------
    unset ALLOW_CMDLINE_OVERWRITE
    if [ ! -z "$NBDROOT" ];then
        KLIST[0]="NBDROOT=$NBDROOT"
    fi
    if [ ! -z "$NFSROOT" ];then
        KLIST[1]="NFSROOT=$NFSROOT"
    fi
    if [ ! -z "$AOEROOT" ];then
        KLIST[2]="AOEROOT=$AOEROOT"
    fi
    Echo "Checking for config file..."
    #======================================
    # hook: preLoadConfiguration
    #--------------------------------------
    runHook preLoadConfiguration
    #======================================
    # Load config.<MAC>
    #--------------------------------------
    if [ ! -s $CONFIG ] ; then
        fetchFile KIWI/config.$DHCPCHADDR $CONFIG
    fi
    #======================================
    # Check alternative config names
    #--------------------------------------
    if [ ! -s $CONFIG ] ; then
        searchGroupConfig
    fi
    #======================================
    # Check alternative config names
    #--------------------------------------
    if [ ! -s $CONFIG ];then
        searchAlternativeConfig
    fi
    #======================================
    # try to import configuration
    #--------------------------------------
    IMPORTED=0
    if [ -s $CONFIG ] ;then
        importFile < $CONFIG
        #======================================
        # Check and import Hardware Maps if set
        #--------------------------------------
        searchHardwareMapConfig
        IMPORTED=1
    fi
    #======================================
    # No config found register new client
    #--------------------------------------
    if [ ! -s $CONFIG ];then
        #======================================
        # Register new network client
        #--------------------------------------
        Echo "Registering new network client..."
        pxeSetupSystemAliasName
        pxeSetupSystemHWInfoFile
        pxeSetupSystemHWTypeFile
        #======================================
        # Put files on the boot server
        #--------------------------------------
        putFile hwtype.$DHCPCHADDR upload/client.$DHCPCHADDR
        echo
        Echo "Registered as: $DHCPCHADDR"
        Echo "Waiting for configuration..."
        sleep 60
        #======================================
        # Wait for configuration (reload)
        #--------------------------------------
        while test ! -s $CONFIG;do
            Echo "Lookup network client config file again..."
            Echo "Checking for config file: config.$DHCPCHADDR"
            dhcpcd -n $PXE_IFACE
            fetchFile KIWI/config.$DHCPCHADDR $CONFIG
            if [ ! -s $CONFIG ] ; then
                searchGroupConfig
            fi
            if test ! -s $CONFIG;then
                searchAlternativeConfig
            fi
            test -s $CONFIG || {
                Echo "Couldn't get image configuration"
                Echo "sleeping [60 sec]..."
                sleep 60
            }
        done
    fi
    #======================================
    # import latest configuration
    #--------------------------------------
    if [ $IMPORTED -eq 0 ];then
        importFile < $CONFIG
        #======================================
        # Check and import Hardware Maps if set
        #--------------------------------------
        searchHardwareMapConfig
        IMPORTED=1
    fi
    #======================================
    # restore values from cmdline
    #--------------------------------------
    if [ ! -z "$ALLOW_CMDLINE_OVERWRITE" ];then
        # if cmdline had *ROOT entries cleanup *ROOT entries from config.mac
        if echo " ${KLIST[@]} " | grep -qE "[ \t](NFS|NBD|AOE)ROOT=" ;then
            unset NBDROOT
            unset NFSROOT
            unset AOEROOT
        fi
        for i in ${KLIST[@]};do
            eval export \"$i\"
        done
    fi
    #======================================
    # hook: postLoadConfiguration
    #--------------------------------------
    runHook postLoadConfiguration
fi

#======================================
# 10) Load Device modules
#--------------------------------------
runHook preprobe
probeDevices "skipUSB"
runHook postprobe

#======================================
# 11) Select language if not in cmdline
#--------------------------------------
selectLanguage

#======================================
# 12) Check for diskful station
#--------------------------------------
searchBusIDBootDevice
if [ $LOCAL_BOOT = "no" ];then
    biosBootDevice=$DISK
    if [ -z "$biosBootDevice" ];then
        biosBootDevice=$(echo $IMAGE | cut -f1 -d\;)
    fi
    setupBootDeviceIfMultipath
    if [ ! -z "$biosBootDevice" ];then
        if ! waitForStorageDevice $biosBootDevice;then
            systemException \
                "Block device $biosBootDevice doesn't appear... fatal !" \
            "reboot"
        fi
        if echo $biosBootDevice | grep -q dev\/ram;then
            export haveRamDisk=1
            systemIntegrity="clean"
        else
            export haveDisk=1
            export imageDiskDevice=$biosBootDevice
        fi
    fi
fi

#======================================
# 13) Check for installed system
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $haveDisk = "1" ];then
    if [ ! -z "$RAID" ];then
        if pxeRaidPartCheck ; then
            pxeRaidAssemble
            partOK=1
        fi
    else
        if pxePartCheck ; then
            partOK=1
        fi
    fi
    IMAGE_FIRST=$(echo $IMAGE | cut -f1 -d,)
    for i in $IMAGE_FIRST;do
        field=0
        for n in $(echo $i | tr ';' ' ');do
            case $field in
                0) imageDevice=$n ; field=1 ;;
                1) imageName=$n   ; field=2 ;;
                2) imageVersion=$n; field=3
            esac
        done
        export kiwi_RootPart=$(nd $imageDevice)
        updateNeeded initialize
        if [ "$partOK" = "1" ] ;then
            fstype=$(probeFileSystem $imageDevice)
            if [ "$fstype" = "luks" ];then
                luks_open_can_fail=yes
                if luksOpen $imageDevice ; then
                    imageDevice=$luksDeviceOpened
                    imageRODevice=$imageDevice
                    export haveLuks=yes
                fi
                unset luks_open_can_fail
            fi
            if mountSystem $imageDevice;then
                updateNeeded
                umountSystem
                systemIntegrity=`getSystemIntegrity 1`
                if [ $systemIntegrity = "fine" ];then
                    Echo "Base system is up to date, activating disk system..."
                fi
            else
                Echo -b "On-disk Image mount attempt failed,"
                Echo -b "Image Update for image [ $imageName ] needed"
                umountSystem
                RELOAD_IMAGE="yes"
                systemIntegrity="clean"
            fi
            if [ -n "$haveLuks" ]; then
                luksClose $imageDevice
            fi
        else
            systemIntegrity="clean"
        fi
    done
fi

#======================================
# 14) Create ptable on diskful system
#--------------------------------------
if \
    [ $LOCAL_BOOT = "no" ]         && \
    [ $systemIntegrity = "clean" ] && \
    [ "$haveRamDisk" = "0" ]       && \
    [ "$partOK" = "0" ]
then
    runHook prepartition
    #======================================
    # Validate partition table
    #--------------------------------------
    Echo "Validating partition setup"
    pxePartitionSetupCheck
    #======================================
    # Create partition table
    #--------------------------------------
    Echo "Creating partition table..."
    if [ -z "$RAID" ];then
        #======================================
        # Standard table
        #--------------------------------------
        cleanPartitionTable
        recreateVTOCTable
        createPartitionerInput $(pxePartitionInput)
        callPartitioner $input
        pxeRaidZeroSuperBlock
    else
        #======================================
        # Raid1 table
        #--------------------------------------
        field=0
        for n in $(echo $RAID | tr ';' ' ');do
            case $field in
                0) raidLevel=$n     ; field=1 ;;
                1) raidDiskFirst=$n ; field=2 ;;
                2) raidDiskSecond=$n; field=3
            esac
        done
        #======================================
        # wait for raid disks to appear
        #--------------------------------------
        if ! waitForStorageDevice $raidDiskFirst;then
            systemException \
                "Disk $raidDiskFirst does not appear... fatal !" \
            "reboot"
        fi
        if ! waitForStorageDevice $raidDiskSecond;then
            systemException \
                "Disk $raidDiskSecond does not appear... fatal !" \
            "reboot"
        fi
        #======================================
        # stop eventually assembled raid
        #--------------------------------------
        pxeRaidStop
        #======================================
        # call partitioner on each raid disk
        #--------------------------------------
        for raid_dev in $raidDiskFirst $raidDiskSecond;do
            imageDiskDevice=$raid_dev
            rm -f $input
            cleanPartitionTable
            recreateVTOCTable
            createPartitionerInput $(pxeRaidPartitionInput)
            callPartitioner $input
        done
        imageDiskDevice=$DISK
        #======================================
        # Create raid array
        #--------------------------------------
        pxeRaidCreate
    fi
    #======================================
    # Setup swap space if requested
    #--------------------------------------
    if [ -z "$RAID" ];then
        export imageSwapDevice=$(pxeSwapDevice)
    else
        export imageSwapDevice=$(pxeRaidSwapDevice)
    fi
    runHook preswap
    if [ ! -z "$imageSwapDevice" ];then
        if ! createSwap $imageSwapDevice 1>&2;then
            systemException "Failed to create swap signature" "reboot"
        fi
    fi
    runHook postswap
    #======================================
    # Setup boot space if requested
    #--------------------------------------
    if [ -z "$RAID" ];then
        export imageBootDevice=$(pxeBootDevice)
        if [ ! -z "$imageBootDevice" ];then
            fstype_boot=$(probeFileSystem $imageBootDevice)
            createFilesystem $imageBootDevice $fstype_boot
        fi
    fi
    runHook postpartition
else
    #======================================
    # Identify swap partition
    #--------------------------------------
    if [ -z "$RAID" ];then
        export imageSwapDevice=$(pxeSwapDevice)
    else
        export imageSwapDevice=$(pxeRaidSwapDevice)
    fi
fi

#======================================
# 15) Setup root device environment
#--------------------------------------
runHook predownload
if \
    [ $LOCAL_BOOT = "no" ] && \
    ([ $haveDisk = "1" ] || [ $haveRamDisk = "1" ])
then
    #======================================
    # 15.1) Download network client image
    #--------------------------------------
    count=0
    for i in $(echo $IMAGE | tr , ' ');do
        imageZipped="uncompressed"
        count=$(($count + 1))
        field=0
        for n in $(echo $i | tr ';' ' ');do
        case $field in
            0) imageDevice=$n ; field=1 ;;
            1) imageName=$n   ; field=2 ;;
            2) imageVersion=$n; field=3 ;;
            3) imageServer=$n ; field=4 ;;
            4) imageBlkSize=$n; field=5 ;;
            5) imageZipped=$n ;
        esac
        done
        if [ $count = 1 ];then
            imageRootDevice=$imageDevice
            imageRootName=$imageName
        fi
        # /.../
        # start download only if installed system is different
        # from the image on the pxe boot server
        # ---
        if test `getSystemIntegrity $count` = "fine";then
            continue
        fi
        imagePath="image/$imageName-$imageVersion"
        while true;do
            # /.../
            # get image md5sum to be able to check for the size
            # requirements if we are loading into RAM
            # ---
            fetchImageMD5 \
                "$imageName" "$imageVersion" \
                "$imageServer" "$imageBlkSize"
            if ! validateSize;then
                systemException \
                    "Not enough space available for this image" \
                "reboot"
            fi
            # /.../
            # now load the image into the imageDevice
            # ---
            imageInfo="$imagePath [$imageDevice BS:$imageBlkSize Byte]"
            if [ "$sum1" = "$sum_local" ] && [ -z "$sum2" ]; then
                Echo "Using cached $imageInfo..."
                fetchFileLocal $imagePath $imageDevice $imageZipped
            else
                Echo "Loading $imageInfo..."
                fetchFile $imagePath $imageDevice $imageZipped $imageServer
                if test $loadCode != 0 || ! loadOK "$loadStatus";then
                    if [ "$imageZipped" = "compressed" ]; then
                        Echo "Download of compressed $imageName.gz failed:"
                    else
                        Echo "Download of $imageName failed:"
                    fi
                    systemException "$loadStatus" "reboot"
                fi
            fi
            # /.../
            # check the md5sum of the downloaded data records
            # ----
            Echo "Download complete, checking data..."
            verifyBytes=$((blocks * blocksize))
            verifyMByte=$((verifyBytes / 1048576))
            if [ -x /usr/bin/dcounter ];then
                test -e /progress || mkfifo /progress
                TEXT_VERIFY=$(getText "Verifying %1" $imageDevice)
                echo "$TEXT_VERIFY ( 0% )" > /progress &
                dump="cat $imageDevice"
                dump="$dump | dcounter -s $verifyMByte -l \"$TEXT_VERIFY \""
                errorLogStop
                (
                    eval $dump 2>/progress |\
                        head --bytes=$verifyBytes | md5sum - > /etc/ireal.md5
                )&
                dump_pid=$!
                echo "cat /progress | dialog \
                    --backtitle \"$TEXT_INSTALLTITLE\" \
                    --progressbox 3 65
                " > /tmp/progress.sh
                if FBOK;then
                    fbiterm -m $UFONT -- bash -e /tmp/progress.sh || \
                    bash -e /tmp/progress.sh
                else
                    bash -e /tmp/progress.sh
                fi
                wait $dump_pid
                clear
                errorLogContinue
            else
                dd if=$imageDevice bs=1024 |\
                    head --bytes=$verifyBytes |\
                    md5sum - > /etc/ireal.md5
            fi
            read sum2 dumy < /etc/ireal.md5
            if test $sum1 = $sum2;then
                Echo "Image checksum test: fine :-)"
                break
            fi
            Echo "Image checksum test failed:"
            Echo "Possible reasons:"
            echo 
            Echo -b "1) Physical ethernet connection lost:"
            Echo -b "   please check cable"
            echo
            Echo -b "2) Data corruption while loading the image:"
            Echo -b "   will give it a new try..."
            echo
            Echo -b "3) wrong checksum file created for the image:"
            Echo -b "   check with the md5sum command if the image on the"
            Echo -b "   TFTP server provides the same md5 sum as included"
            Echo -b "   within the appropriate .md5 file for this image"
            echo
            if [ -z "$DISK" ];then
                Echo -b "4) ramdisk size is too small for the image:"
                Echo -b "   check the ramdisk_size parameter of the PXE"
                Echo -b "   configuration file on the TFTP server"
            else
                Echo -b "4) partition size is too small for the image:"
                Echo -b "   check the PART line in the image config file on the"
                Echo -b "   TFTP server"
            fi
            echo
            Echo "Retry to load image..."
            sleep 15
        done
        imageRootDevice=$imageDevice
        if [ ! -z "$UNIONFS_CONFIG" ];then
            imageRWDevice=$(echo $UNIONFS_CONFIG | cut -d , -f 1)
            imageRODevice=$(echo $UNIONFS_CONFIG | cut -d , -f 2)
            unionFST=$(echo $UNIONFS_CONFIG | cut -d , -f 3)
        fi
        rm -f /etc/ireal.md5
        rm -f /etc/image.md5
    done
else
    #======================================
    # 15.2) Check for local boot
    #--------------------------------------
    if [ $LOCAL_BOOT = "yes" ];then
        imageRootDevice=$root
        imageRootName="Local-System"
        if [ ! -z "$UNIONFS_CONFIG" ];then
            unionFST=$UNIONFS_CONFIG
            imageRWDevice=$(ddn $imageDisk 3)
            imageRODevice=$(ddn $imageDisk 2)
        fi
    fi
    #======================================
    # 15.3) Check for NFS root
    #--------------------------------------
    if [ ! -z "$NFSROOT" ];then
        for i in $(echo $NFSROOT | tr , ' ');do
            field=0
            for n in $(echo $i | tr ';' ' ');do
            case $field in
                0) nfsRootServer=$n ; field=1 ;;
                1) nfsRootDevice=$n ; field=2
            esac
            done
        done
        for m in nfs lockd sunrpc;do
            modprobe -i $m
        done
        if [ -z "$nfsRootServer" ];then
            nfsRootServer=$SERVER
        fi
        setupNFSServices
        Echo "Mounting NFS root system: $nfsRootServer:$nfsRootDevice..."
        imageRootDevice="-o vers=3,rw,nolock $nfsRootServer:$nfsRootDevice"
        if [ ! -z "$UNIONFS_CONFIG" ];then
            imageRootDevice="-o vers=3,ro,nolock $nfsRootServer:$nfsRootDevice"
        fi
        imageRootName="NFSRoot-System"
        systemIntegrity="clean"
        if [ ! -z "$UNIONFS_CONFIG" ];then
            imageRWDevice=$(echo $UNIONFS_CONFIG | cut -d , -f 1)
            imageRODevice=$(echo $UNIONFS_CONFIG | cut -d , -f 2)
            unionFST=$(echo $UNIONFS_CONFIG | cut -d , -f 3)
            if [ "$unionFST" = "clicfs" ];then
                systemException "clicfs over NFSROOT is not supported" "reboot"
            fi
        fi
    fi
    #======================================
    # 15.4) Check for NBD root
    #--------------------------------------
    if [ ! -z "$NBDROOT" ];then
        unionFST=$(echo $UNIONFS_CONFIG | cut -d , -f 3)
        if ! modprobe nbd;then
            systemException "Failed to load network blk device module" "reboot"
        fi
        for i in $(echo $NBDROOT | tr , ' ');do
            field=0
            for n in $(echo $i | tr ';' ' ');do
            case $field in
                0) nbdServer=$n     ; field=1 ;;
                1) nbdName=$n       ; field=2 ;;
                2) nbdDevice=$n     ; field=3 ;;
                3) nbdswapName=$n   ; field=4 ;;
                4) nbdswapDevice=$n ; field=5 ;;
                5) nbdwriteName=$n  ; field=6 ;;
                6) nbdwriteDevice=$n; field=7
            esac
            done
        done
        if [ -z "$nbdServer" ];then
            nbdServer=$SERVER
        fi
        if [ -z "$nbdDevice" ];then
            nbdDevice="/dev/nbd0"
        fi
        if [ -z "$nbdswapDevice" ];then
            nbdswapDevice="/dev/nbd1"
        fi
        if [ -z "$nbdName" ];then
            systemException "No NBD export name specified" "reboot"
        fi
        if [ -z "$nbdwriteDevice" ];then
            nbdwriteDevice="tmpfs"
        fi
        waitForBlockDevice $nbdDevice
        if [ ! -b $nbdDevice ];then
            systemException "Device $nbdDevice does not appear" "reboot"
        fi
        if [ ! -z "$nbdwriteName" ];then
            waitForBlockDevice $nbdwriteDevice
            if [ ! -b $nbdwriteDevice ];then
                systemException "Device $nbdwriteDevice does not appear" "reboot"
            fi
        fi
        if [ ! -z "$nbdswapName" ];then
            waitForBlockDevice $nbdswapDevice
            if [ ! -b $nbdswapDevice ];then
                systemException "Device $nbdswapDevice does not appear" "reboot"
            fi
        fi
        # /.../
        # try to get swap from the server if we dont have
        # enough ram (less than 62MB)
        # ----
        if [ ! -z "$nbdswapName" ];then
            min_ram=63488
            swap_wait_seconds=3
            real_ram=$(cat /proc/meminfo |grep MemTotal|tr -d " [a-z][A-Z]:")
            if [ ${real_ram} -lt ${min_ram} ];then
                Echo "NBD: memory is below required 62M"
                Echo "NBD: swap: $nbdServer [$nbdswapName] [$nbdswapDevice]"
                if ! nbd-client -N $nbdswapName \
                    $nbdServer $nbdswapDevice -persist
                then
                    systemException \
                        "Failed to setup $nbdswapDevice device" \
                    "reboot"
                fi
                Echo "NBD: Waiting for server to create swap space..."
                sleep $swap_wait_seconds
                swapon $nbdswapDevice || true
            fi
        fi
        # /.../
        # try to mount a remote read/write location based on NBD
        # this is then overlayed via $unionFST
        # ----
        if [ ! -z "$nbdwriteName" ];then
            Echo "NBD: R/W $nbdServer [$nbdwriteName] [$nbdwriteDevice]..."
            if ! nbd-client -N $nbdwriteName \
                $nbdServer $nbdwriteDevice -persist
            then
                systemException \
                    "Failed to setup $nbdwriteDevice device" \
                "reboot"
            fi
        fi
        # /.../
        # mount basic root filesystem exported via NBD
        # ----
        Echo "Mounting NBD root system: $nbdServer [$nbdName] [$nbdDevice]..."
        if ! nbd-client -N $nbdName $nbdServer $nbdDevice -persist;then
            systemException \
                "Failed to setup $nbdDevice device" \
            "reboot"
        fi
        # /.../
        # setup union if basic root filesystem is read-only
        # ----
        imageRootDevice=$nbdDevice
        imageRootName="NBDRoot-System"
        systemIntegrity="clean"
        imageRWDevice=$nbdwriteDevice
        imageRODevice=$imageRootDevice
    fi
    #======================================
    # 15.5) Check for AOE root
    #--------------------------------------
    if [ ! -z "$AOEROOT" ];then
        aoeRODevice=$(echo $AOEROOT | cut -d , -f 1)
        aoeRWDevice=$(echo $AOEROOT | cut -d , -f 2)
        unionFST=$(echo $UNIONFS_CONFIG | cut -d , -f 3)
        if [ -z "$aoeRWDevice" ] || [ "$aoeRODevice" = "$aoeRWDevice" ];then
            aoeRWDevice=tmpfs
        fi
        if ! modprobe aoe;then
            systemException "Failed to load AoE module" "reboot"
        fi
        waitForBlockDevice $aoeRODevice
        if [ ! -b $aoeRODevice ];then
            systemException "Device $aoeRODevice does not appear" "reboot"
        fi
        # /.../
        # check ram space, if we don't have more than 62MB
        # we can't use Ata over Ethernet and reboot
        # ----
        min_ram=63488
        real_ram=$(cat /proc/meminfo |grep MemTotal|tr -d " [a-z][A-Z]:")
        if [ ${real_ram} -lt ${min_ram} ];then
            Echo "AoE: memory is below required 62M"
            systemException "Not enough ram" "reboot"
        fi
        Echo "Mounting AoE root system: $aoeRODevice..."
        imageRootDevice=$aoeRODevice
        imageRootName="AOERoot-System"
        systemIntegrity="clean"
        imageRWDevice=$aoeRWDevice
        imageRODevice=$imageRootDevice
    fi
fi
runHook postdownload

#======================================
# 16) Get filesystem type
#--------------------------------------
if [ -b $imageRootDevice ];then
    fstype=$(probeFileSystem $imageRootDevice)
    if [ "$fstype" = "luks" ];then
        luksOpen $imageRootDevice
        imageRootDevice=$luksDeviceOpened
        imageRODevice=$imageRootDevice
        fstype=$(probeFileSystem $imageRootDevice)
        export haveLuks=yes
    fi
    if [ "$fstype" = "unknown" ];then
        systemException \
            "Couldn't determine filesystem type... abort" \
        "reboot"
    fi
fi

#======================================
# 17) resize fs on diskful client
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
    if [ $haveDisk = "1" ] || [ $haveRamDisk = "1" ];then
        resizeFilesystem $imageRootDevice
    fi
fi

#======================================
# 18) Check filesystem
#--------------------------------------
Echo "Filesystem of PXE system is: $fstype -> $imageRootDevice"
if [ ! -z "$kiwi_ROPart" ] || [ ! -z "$UNIONFS_CONFIG" ]; then
    if [ ! -z "$imageRWDevice" ] && [ ! -z "$imageRODevice" ];then
        setupUnionFS $imageRWDevice $imageRODevice $unionFST
    fi
fi

#======================================
# 19) Mount OS image to /mnt
#--------------------------------------
runHook premount
if ! mountSystem;then
    systemException "Failed to mount root filesystem" "reboot"
fi
validateRootTree
runHook postmount

#======================================
# 20) Import fixed configuration files
#--------------------------------------
runHook preconfig
if [ $LOCAL_BOOT = "no" ] || [ ! -z "$RELOAD_CONFIG" ];then
    if [ ! -z "$RELOAD_CONFIG" ];then
        Echo "Configuration files reload forced via RELOAD_CONFIG..."
    fi
    #=======================================
    # 20.0) Import NFS root files
    #---------------------------------------
    if [ ! -z "$NFSROOT" ];then
        test -f /etc/resolv.conf && cp /etc/resolv.conf /mnt/etc
    fi
    #=======================================
    # 20.1) Import RAID config file
    #---------------------------------------
    if [ ! -z "$RAID" ];then
        cp /mdadm.conf /mnt/etc
    fi
    #=======================================
    # 20.2) Import files from backup
    #---------------------------------------
    BCFG_BASE='etc/KIWI'
    BCFG_NAME='InstalledConfigFiles'
    if [ -s "/mnt/$BCFG_BASE/$BCFG_NAME" ] ;then
        importFile 'BK_' </mnt/$BCFG_BASE/$BCFG_NAME
    fi
    ALL_CCONF=`condenseConfigData "$CONF,$VENDOR_CONF"`
    ALL_CBK_CONF=`condenseConfigData "$BK_CONF,$BK_VENDOR_CONF"`
    #=======================================
    # 20.3) Store new configuration
    #---------------------------------------
    mkdir  /config
    mkdir -p  /config/$BCFG_BASE
    cp "$CONFIG" "/config/$BCFG_BASE/config.$DHCPCHADDR"
    echo "CONF=$CONF"               >  "/config/$BCFG_BASE/$BCFG_NAME"
    echo "VENDOR_CONF=$VENDOR_CONF" >> "/config/$BCFG_BASE/$BCFG_NAME"
    #=======================================
    # 20.4) Get files from CONF, VENDOR_CONF
    #---------------------------------------
    for i in $(echo $ALL_CCONF | tr , ' ');do
        unset configHash
        field=0
        for n in $(echo $i | tr ';' ' ');do
        case $field in
            0) configSource=$n ; field=1 ;;
            1) configDest=$n   ; field=2 ;;
            2) configServer=$n ; field=3 ;;
            3) configBlkSize=$n; field=4 ;;
            4) configHash=$n   ; field=5
        esac
        done
        # /.../
        # compare new config data to backup config data
        # ----
        cfg_copy=1
        cfgmsg_why='(forced)'
        if [ -z "$RELOAD_CONFIG" ];then
            cfgmsg_why='(missing)'
            for j in $(echo $ALL_CBK_CONF | tr , ' ');do
                BKconfigDest=`echo "$j" | cut -d ';' -f 2`
                BKconfigHash=`echo "$j" | cut -d ';' -f 5`
                if [ "$BKconfigDest" = "$configDest" ];then
                    cfgmsg_why='(changed)'
                    if [ "$configHash" = "$BKconfigHash" ];then
                        cfg_copy=0
                    fi
                    break
                fi
            done
        fi
        if [ $cfg_copy -eq 1 ];then
            Echo "Importing $cfgmsg_why configuration file: $configDest"
            dirs=`dirname  $configDest`
            mkdir -p /config/$dirs
            cacheConfig="$KIWI_LOCAL_CACHE_DIR/$configSource"
            if [ -f $cacheConfig ];then
                cacheHash=$(md5sum "$cacheConfig" | cut -f1 -d ' ')
            fi
            if [ -f $cacheConfig ] && [ "$cacheHash" = "$configHash" ];then
                cp -f $cacheConfig /config/$configDest
            else
                fetchFile \
                    $configSource /config/$configDest \
                    uncompressed $configServer
            fi
        fi
    done
    #=======================================
    # 20.5) check config files to be deleted
    #---------------------------------------
    for i in $(echo $ALL_CBK_CONF | tr , ' ');do
        BKconfigDest=`echo "$i" | cut -d ';' -f 2`
        deletethis=1
        for j in $(echo $ALL_CCONF | tr , ' ');do
            configDest=`echo "$j" | cut -d ';' -f 2`
            if [ "$BKconfigDest" = "$configDest" ];then
                deletethis=0
                break
            fi
        done
        if [ "$deletethis" -eq '1' ];then
            Echo "Deleting obsolete configuration file: $BKconfigDest"
            rm /mnt/$BKconfigDest
        fi
    done
    #=======================================
    # 20.6) Check for KIWI_INITRD
    #---------------------------------------
    if [ $haveDisk = "1" ] && [ $systemIntegrity = "clean" ];then
        if [ ! -z "$KIWI_INITRD" ] && [ ! -z "$KIWI_KERNEL" ];then
            Echo "Import KIWI initrd/kernel file: $KIWI_INITRD/$KIWI_KERNEL"
            rm -f /mnt/boot/initrd* && mkdir -p /mnt/boot >/dev/null 2>&1
            fetchFile $KIWI_INITRD /mnt/boot/initrd.kiwi
            Echo "Import KIWI kernel file: $KIWI_KERNEL"
            rm -f /mnt/boot/linux*
            fetchFile $KIWI_KERNEL /mnt/boot/linux.kiwi
            KIWI_INITRD_PARAMS="IMAGE=local"
            export PXE_KIWI_INITRD=yes
        fi
        if [ ! -z "$UNIONFS_CONFIG" ]; then
            unionFST=`echo $UNIONFS_CONFIG | cut -d , -f 3`
            UNIONED="UNIONFS_CONFIG=$unionFST"
            KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS $UNIONED"
        fi
    fi
fi
runHook postconfig

#======================================
# 21) check kernels
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
    kernelList /mnt
fi

#======================================
# 22) setup ird/kernel links for union
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ] && [ $systemIntegrity = "clean" ];then
    setupKernelLinks
fi

#======================================
# 23) Create system dependant files
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
    mkdir -p /config
    setupDefaultPXENetwork /config
    setupDefaultFstab /config
    updateRootDeviceFstab /config "$imageRootDevice"
    if [ ! -z "$DISK" ];then
        updateSwapDeviceFstab /config $imageSwapDevice
        updateOtherDeviceFstab /config
        setupBootLoader /mnt /config $(($bootid - 1)) \
            $imageRootDevice NET $imageSwapDevice
        setupKernelModules /config
    fi
fi

#======================================
# 24) copy system dependant files
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
    setupConfigFiles
fi

#======================================
# 25) update system dependant files
#--------------------------------------
setupInittab /mnt

echo 256 > /proc/sys/kernel/real-root-dev
#======================================
# 26) umount system filesystems
#--------------------------------------
umountSystemFilesystems

#======================================
# 27) copy initrd files to image
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
    if canWrite /mnt;then
        cp /preinit /mnt
        cp /include /mnt
    fi
fi

#======================================
# 28) kill boot shell
#--------------------------------------
killShell

#======================================
# 29) Activate new root
#--------------------------------------
runHook preactivate
activateImage

#======================================
# 30) Unmount initrd / system init
#--------------------------------------
bootImage
