#!/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 DOMURD_MODULES="xennet xenblk"
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=yes
export kiwi_hybridpersistent=yes

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

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

#======================================
# 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
#--------------------------------------
includeKernelParameters
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
fi

#======================================
# 7) Setup network interface and DNS
#--------------------------------------
runHook prenetwork
if [ $LOCAL_BOOT = "no" ];then
	setupNetwork
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
#--------------------------------------
if [ $LOCAL_BOOT = "no" ];then
	checkDevice=$DISK
	if [ -z "$checkDevice" ];then
		checkDevice=$(echo $IMAGE | cut -f1 -d\;)
	fi
	if [ ! -z "$checkDevice" ];then
		if ! waitForStorageDevice $checkDevice;then
			systemException \
				"Block device $checkDevice doesn't appear... fatal !" \
			"reboot"
		fi
		if echo $checkDevice | grep -q dev\/ram;then
			export haveRamDisk=1
		else
			export haveDisk=1
			export imageDiskDevice=$checkDevice
		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
		IFS=";" ; for n in $i;do
			case $field in
				0) imageDevice=$n ; field=1 ;;
				1) imageName=$n   ; field=2 ;;
				2) imageVersion=$n; field=3
			esac
		done
		updateNeeded initialize
		if [ "$partOK" = "1" ] ;then
			probeFileSystem $imageDevice
			if [ "$FSTYPE" = "luks" ];then
				luks_open_can_fail=yes
				if luksOpen $imageDevice ; then
					imageDevice=$luksDeviceOpened
					imageRODevice=$imageDevice
					probeFileSystem $imageRootDevice
					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" ] && \
	[ "$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
		createPartitionerInput $(pxePartitionInput)
		callPartitioner $input
		pxeRaidZeroSuperBlock
	else
		#======================================
		# Raid1 table
		#--------------------------------------
		field=0
		IFS=";" ; for n in $RAID;do
			case $field in
				0) raidLevel=$n     ; field=1 ;;
				1) raidDiskFirst=$n ; field=2 ;;
				2) raidDiskSecond=$n; field=3
			esac
		done
		IFS=$IFS_ORIG
		#======================================
		# wait for raid disks to appear
		#--------------------------------------
		if ! waitForStorageDevice $raidDiskFirst;then
			systemException \
				"Disk $raidDiskFirst doesn't appear... fatal !" \
			"reboot"
		fi
		if ! waitForStorageDevice $raidDiskSecond;then
			systemException \
				"Disk $raidDiskSecond doesn't 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
			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 ! mkswap $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
			createFilesystem $imageBootDevice
		fi
	fi
	runHook postpartition
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
	IFS="," ; for i in $IMAGE;do
		imageZipped="uncompressed"
		count=$(($count + 1))
		field=0
		IFS=";" ; for n in $i;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
		imageName="image/$imageName-$imageVersion"
		imageMD5s="$imageName.md5"
		[ -z "$imageServer" ]  && imageServer=$SERVER
		[ -z "$imageBlkSize" ] && imageBlkSize=8192
		while true;do
			# /.../
			# get image md5sum to be able to check for the size
			# requirements if we are loading into RAM
			# ---
			IFS=$IFS_ORIG
			fetchFile $imageMD5s /etc/image.md5 uncomp $imageServer
			if test $loadCode != 0 || ! loadOK "$loadStatus"; then
				systemException \
					"Download of $imageMD5s failed: $loadStatus" \
				"reboot"
			fi
			read sum1 blocks blocksize zblocks zblocksize < /etc/image.md5
			if ! validateSize;then
				systemException \
					"Not enough space available for this image" \
				"reboot"
			fi
			# /.../
			# now load the image into the imageDevice
			# ---
			Echo "Loading $imageName [$imageDevice BS:$imageBlkSize Byte]..."
			fetchFile $imageName $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
			# /.../
			# 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 [ -e /dev/fb0 ];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`
		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
		IFS="," ; for i in $NFSROOT;do
			field=0
			IFS=";" ; for n in $i;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 $nfsRootServer:$nfsRootDevice"
		if [ ! -z "$COMBINED_IMAGE" ] || [ ! -z "$UNIONFS_CONFIG" ];then
			imageRootDevice="-o vers=3,ro $nfsRootServer:$nfsRootDevice"
		fi
		imageRootName="NFSRoot-System"
		systemIntegrity="clean"
		export FSTYPE=nfs
		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
		if ! modprobe nbd;then
			systemException "Failed to load network blk device module" "reboot"
		fi
		IFS="," ; for i in $NBDROOT;do
			field=0
			IFS=";" ; for n in $i;do
			case $field in
				0) nbdServer=$n     ; field=1 ;;
				1) nbdPort=$n       ; field=2 ;;
				2) nbdDevice=$n     ; field=3 ;;
				3) nbdswapPort=$n   ; field=4 ;;
				4) nbdswapDevice=$n ; field=5 ;;
				5) nbdwritePort=$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 "$nbdPort" ];then
			nbdPort="2000"
		fi
		if [ -z "$nbdwriteDevice" ];then
			nbdwriteDevice="/dev/ram1"
		fi
		waitForBlockDevice $nbdDevice
		if [ ! -b $nbdDevice ];then
			systemException "Device $nbdDevice doesn't appear" "reboot"
		fi
		if [ ! -z "$nbdwritePort" ];then
			waitForBlockDevice $nbdwriteDevice
			if [ ! -b $nbdwriteDevice ];then
				systemException "Device $nbdwriteDevice doesn't appear" "reboot"
			fi
		fi
		if [ ! -z "$nbdswapPort" ];then
			waitForBlockDevice $nbdswapPort
			if [ ! -b $nbdswapDevice ];then
				systemException "Device $nbdswapDevice doesn't appear" "reboot"
			fi
		fi
		# /.../
		# try to get swap from the server if we dont have
		# enough ram (less than 62MB)
		# ----
		if [ ! -z "$nbdswapPort" ];then
			min_ram=63488
			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 $nbdswapPort [$nbdswapDevice]"
				if ! nbd-client $nbdServer $nbdswapPort $nbdswapDevice -persist
				then
					systemException \
						"Failed to setup $nbdswapDevice device" \
					"reboot"
				fi
				Echo "NBD: Waiting for server to create swap space..."; sleep 3
				swapon $nbdswapDevice || true
			fi
		fi
		# /.../
		# try to mount a remote read/write location based on NBD
		# this is then overlayed via $unionFST
		# ----
		if [ ! -z "$nbdwritePort" ];then
			Echo "NBD: read/write $nbdServer $nbdwritePort [$nbdwriteDevice]..."
			if ! nbd-client $nbdServer $nbdwritePort $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 $nbdPort [$nbdDevice]..."
		if ! nbd-client $nbdServer $nbdPort $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"
		if [ -z "$COMBINED_IMAGE" ];then
			imageRWDevice=$nbdwriteDevice
			imageRODevice=$imageRootDevice
		fi
	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`
		if [ -z "$aoeRWDevice" ] || [ "$aoeRODevice" = "$aoeRWDevice" ];then
			aoeRWDevice=/dev/ram1
		fi
		if ! modprobe aoe;then
			systemException "Failed to load AoE module" "reboot"
		fi
		waitForBlockDevice $aoeRODevice
		if [ ! -b $aoeRODevice ];then
			systemException "Device $aoeRODevice doesn't 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"
		if [ -z "$COMBINED_IMAGE" ];then
			imageRWDevice=$aoeRWDevice
			imageRODevice=$imageRootDevice
		fi
	fi
fi
runHook postdownload

#======================================
# 16) Get filesystem type
#--------------------------------------
if [ -b $imageRootDevice ];then
	probeFileSystem $imageRootDevice
	if [ "$FSTYPE" = "luks" ];then
		luksOpen $imageRootDevice
		imageRootDevice=$luksDeviceOpened
		imageRODevice=$imageRootDevice
		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 isFSTypeReadOnly;then
	if [ ! -z "$imageRWDevice" ] && [ ! -z "$imageRODevice" ];then
		setupUnionFS $imageRWDevice $imageRODevice $unionFST
	fi
fi

#======================================
# 19) Setup bootid for this table
#--------------------------------------
if [ ! -z "$imageBootDevice" ];then
	# bootid is boot partition
	export bootid=$(nd $imageBootDevice)
else
	if [ -z "$haveLuks" ]; then
		# bootid is root partition for non LUKS devices
		export bootid=$(nd $imageRootDevice)
	else
		# bootid can be a boot partition or undefined in
		# e.g pxe netboot only environments. let setupBootPartition
		# find out if we have one
		unset bootid
	fi
fi
if [ ! -z "$RAID" ] && [ ! -z "$bootid" ];then
	# raid md devices start with 0 but partition id's start with 1
	bootid=$((bootid + 1))
fi

#======================================
# 20) Mount OS image to /mnt
#--------------------------------------
runHook premount
if ! mountSystem;then
	systemException "Failed to mount root filesystem" "reboot"
fi
if [ ! -z "$imageBootDevice" ];then
	mkdir /boot_tmp && mount $imageBootDevice /boot_tmp
	cp -a /mnt/boot/* /boot_tmp
	umount /boot_tmp && rmdir /boot_tmp
	rm -rf /mnt/boot/*
	if ! mount $imageBootDevice /mnt/boot;then
		systemException "Failed to mount boot filesystem" "reboot"
	fi
fi
validateRootTree
runHook postmount

#======================================
# 21) 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
	#=======================================
	# 21.0) Import NFS root files
	#---------------------------------------
	if [ ! -z "$NFSROOT" ];then
		test -f /etc/resolv.conf && cp /etc/resolv.conf /mnt/etc
	fi
	#=======================================
	# 21.1) Import RAID config file
	#---------------------------------------
	if [ ! -z "$RAID" ];then
		cp /mdadm.conf /mnt/etc
	fi
	#=======================================
	# 21.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"`
	#=======================================
	# 21.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"
	#=======================================
	# 21.4) Get files from CONF, VENDOR_CONF
	#---------------------------------------
	IFS="," ; for i in $ALL_CCONF;do
		unset configHash
		field=0
		IFS=";"; for n in $i;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)'
			IFS=","; for j in $ALL_CBK_CONF;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
			fetchFile $configSource /config/$configDest uncomp $configServer
		fi
	done
	#=======================================
	# 21.5) check config files to be deleted
	#---------------------------------------
	IFS="," ; for i in $ALL_CBK_CONF;do
		BKconfigDest=`echo "$i" | cut -d ';' -f 2`
		deletethis=1
		IFS=","; for j in $ALL_CCONF;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
	IFS=$IFS_ORIG
	#=======================================
	# 21.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"
			if [ ! -z "$COMBINED_IMAGE" ]; then
				SPLIT="COMBINED_IMAGE=$COMBINED_IMAGE"
				KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS $SPLIT"
			fi
			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

#======================================
# 22) check filesystem and kernels
#--------------------------------------
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
	if [ "$FSTYPE" != "nfs" ];then
		probeFileSystem $imageRootDevice
	fi
	kernelList /mnt
fi

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

#======================================
# 24) 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

#======================================
# 25) send DHCP_RELEASE, reset cache
#--------------------------------------
runHook preNetworkRelease
if [ $LOCAL_BOOT = "no" ];then
	releaseNetwork
fi

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

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

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

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

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

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

#======================================
# 32) Unmount initrd / system init
#--------------------------------------
bootImage $@
