#!/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 DEBUG=0
export bootid=1

#======================================
# Exports (Booting)
#--------------------------------------
export DOMURD_MODULES="xennet xenblk"
export INITRD_MODULES="reiserfs"
export LOCAL_BOOT=no
export systemIntegrity="clean"

#======================================
# Exports (Configuration)
#--------------------------------------
export VMX_SYSTEM="/config.vmxsystem"
export LIVECD_CONFIG="/cdrom/config.isoclient"
export OEM_PARTITION_CONFIG="/config.oempartition"

#======================================
# Functions...
#--------------------------------------
. /include
. /repart
. /dump

#======================================
# Functions...
#--------------------------------------
function setupInitialDeviceNames {
	#======================================
	# Check for DONT_PARTITION variable
	#--------------------------------------
	if [ ! -z "$DONT_PARTITION" ];then
		return
	fi
	#======================================
	# Check boot device
	#--------------------------------------
	if [ -z "$imageDiskDevice" ];then
		systemException \
			"Couldn't find any boot device... abort" \
		"reboot"
	fi
	#======================================
	# Set default filesystem device names
	#--------------------------------------
	export imageRWDevice=$(ddn $imageDiskDevice 2)
	export imageRODevice=$(ddn $imageDiskDevice 1)
	export imageIOWRDevice=$imageRWDevice
	#======================================
	# Check for LVM or standard boot
	#--------------------------------------
	if searchVolumeGroup; then
		#======================================
		# LVM setup...
		#--------------------------------------
		export haveLVM=yes
		if [ -e /dev/kiwiVG/LVComp ];then
			export imageRootDevice=/dev/kiwiVG/LVComp
		else
			export imageRootDevice=/dev/kiwiVG/LVRoot
		fi
		export imageRWDevice=/dev/kiwiVG/LVRoot
		export imageRODevice=/dev/kiwiVG/LVComp
		export imageIOWRDevice=$imageRWDevice
		export imageBootDevice=$(ddn $imageDiskDevice 2)
		if [ ! -z "$KIWI_RECOVERY" ];then
			export imageRecoveryDevice=/dev/kiwiVG/LVRecovery
		fi
		probeFileSystem $imageRootDevice
	else
		#======================================
		# Standard setup
		#--------------------------------------
		if [ ! -z "$KIWI_RECOVERY" ];then
			export imageRecoveryDevice=$(ddn $imageDiskDevice $KIWI_RECOVERY)
			export imageRootDevice=$(ddn $imageDiskDevice 1)
		else
			for i in 1 2;do
				export imageRootDevice=$imageDiskDevice$i
				probeFileSystem $imageRootDevice
				if [ ! "$FSTYPE" = "unknown" ];then
					break
				fi
			done
		fi
	fi
	#======================================
	# Check for LUKS extension on root fs
	#--------------------------------------
	if [ "$FSTYPE" = "luks" ];then
		imageRootDevice=$(luksOpen $imageRootDevice)
		probeFileSystem $imageRootDevice
		export haveLuks=yes
	fi
	#======================================
	# Check root filesystem type
	#--------------------------------------
	if [ "$FSTYPE" = "unknown" ];then
		systemException \
			"Couldn't determine filesystem type... abort" \
		"reboot"
	fi
	#======================================
	# Check for LUKS extension on rw fs
	#--------------------------------------
	if isFSTypeReadOnly;then
		FSTYPE_OLD=$FSTYPE
		probeFileSystem $imageRWDevice
		if [ "$FSTYPE" = "luks" ];then
			export haveLuks=yes
		fi
		FSTYPE=$FSTYPE_OLD
	fi
}

#======================================
# Beautify Startup
#--------------------------------------
echo "Loading KIWI OEM Boot-System..."
echo "-------------------------------"

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

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

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

#======================================
# 4) Include proc/cmdline information
#--------------------------------------
includeKernelParameters
if \
	[ ! -z "$UNIONFS_CONFIG" ] || [ "$COMBINED_IMAGE" = "local" ] ||\
	[ ! -z "$KIWI_RECOVERY" ]
then
	# /.../
	# if the unionfs/combined information is already in place at this
	# stage it comes from the cmdline data which means we are not
	# booting from CD/DVD USB stick but want to boot the local system
	# This also applies if we use an oem system with the recovery
	# feature enabled
	# ----
	export LOCAL_BOOT="yes"
fi
if [ "$loader" = "syslinux" ];then
	systemException \
		"syslinux boot not supported for OEM systems... abort" \
	"reboot"
fi
#======================================
# 5) start boot shell
#--------------------------------------
startBlogD
startShell
errorLogStart
openKernelConsole

#======================================
# 6) Including required kernel modules
#--------------------------------------
probeDevices

#======================================
# 7) Import OEM partition config
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ] && [ -f $OEM_PARTITION_CONFIG ];then
	Echo "Including oem partition info file"
	importFile < $OEM_PARTITION_CONFIG
fi

#======================================
# 8) Search boot device...
#--------------------------------------
Echo "Searching for boot device..."
if [ "$LOCAL_BOOT" = "no" ];then
	if ! searchBIOSBootDevice;then
		systemException "$biosBootDevice" "reboot"
	fi
	export imageDiskDevice=$biosBootDevice
else
	export imageDiskDevice=$(dn $root)
fi
Echo "Found boot device: $imageDiskDevice"

#======================================
# 9) Check for installation mode...
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
	OEMInstall
fi

#======================================
# 10) Run SAP checks if activated
#--------------------------------------
if [ ! -z "$OEM_SAP_INSTALL" ];then
	IFS=$IFS_ORIG
	SAPMemCheck
	SAPCPUCheck
	SAPStorageCheck $imageDiskDevice $imageDiskExclude
	SAPDataStorageSetup $imageDiskDevice $imageDiskExclude
fi

#======================================
# 11) Setup device names...
#--------------------------------------
setupInitialDeviceNames

#======================================
# 12) repartition the disk device
#--------------------------------------
Echo "Filesystem of OEM system is: $FSTYPE -> $imageRootDevice"
if [ "$LOCAL_BOOT" = "no" ];then
	OEMRepart
fi

#======================================
# 13) Check for read-only filesystem
#--------------------------------------
if isFSTypeReadOnly;then
	setupUnionFS $imageRWDevice $imageRODevice $unionFST
	bootid=2
fi

#======================================
# 14) Resize filesystem to full space
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
	deviceResize=$imageRootDevice
	fstypeRootFS=$FSTYPE
	if [ ! -z $COMBINED_IMAGE ];then
		deviceResize=$imageIOWRDevice
		KIWI_INITRD_PARAMS="COMBINED_IMAGE=local"
		probeFileSystem $deviceResize
		export KIWI_INITRD_PARAMS
	fi
	if isFSTypeReadOnly && [ -z "$COMBINED_IMAGE" ];then
		deviceResize=$imageIOWRDevice
		KIWI_INITRD_PARAMS="UNIONFS_CONFIG=yes"
		probeFileSystem $deviceResize
		export KIWI_INITRD_PARAMS
	fi
	if [ ! -z "$deviceResize" ] && partitionSize $deviceResize &>/dev/null;then
		if [ ! -z "$OEM_RECOVERY" ];then
			KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS LOCAL_BOOT=yes"
			export KIWI_INITRD_PARAMS
		fi
		if [ -z "$DONT_PARTITION" ];then
			if [ "$FSTYPE" = "reiserfs" ];then
				Echo "Resize Reiser filesystem to full partition space..."
				luksResize $deviceResize
				resize_reiserfs -q $deviceResize
				INITRD_MODULES="$INITRD_MODULES reiserfs"
			fi
			if [ "$FSTYPE" = "ext2" ];then
				Echo "Resize EXT2 filesystem to full partition space..."
				luksResize $deviceResize
				resize2fs -f -F -p $deviceResize
				Echo "Checking EXT2 filesystem..."
				e2fsck -p $deviceResize
				INITRD_MODULES="$INITRD_MODULES ext2"
			fi
			if [ "$FSTYPE" = "ext3" ];then
				Echo "Resize EXT3 filesystem to full partition space..."
				luksResize $deviceResize
				resize2fs -f -F -p $deviceResize
				Echo "Checking EXT3 filesystem..."
				e2fsck -p $deviceResize
				INITRD_MODULES="$INITRD_MODULES ext3"
			fi
			if [ "$FSTYPE" = "ext4" ];then
				Echo "Resize EXT4 filesystem to full partition space..."
				luksResize $deviceResize
				resize2fs -f -F -p $deviceResize
				Echo "Checking EXT4 filesystem..."
				e2fsck -p $deviceResize
				INITRD_MODULES="$INITRD_MODULES ext4"
			fi
		fi
	fi
	if [ "$OEM_KIWI_INITRD" = "yes" ];then
		if ! echo $KIWI_INITRD_PARAMS | grep -qi LOCAL_BOOT;then
			KIWI_INITRD_PARAMS="$KIWI_INITRD_PARAMS LOCAL_BOOT=yes"
		fi
	fi
	FSTYPE=$fstypeRootFS
fi

#======================================
# 15) Mount system
#--------------------------------------
if ! mountSystem $imageRootDevice;then
	systemException "Failed to mount root filesystem" "reboot"
fi
validateRootTree

#======================================
# 16) Recover system if requested
#--------------------------------------
if [ ! -z "$KIWI_RECOVERY" ];then
	dialog --defaultno --yesno "Do you want to start the System-Recovery ?" 5 50
	if [ ! $? = 0 ];then
		systemException "System-Recovery not started" "reboot"
	fi
	clear
	Echo "Starting System-Recovery..."
	#======================================
	# 16.1) mount recovery partition
	#--------------------------------------
	mkdir -p /reco-save
	if ! mount $imageRecoveryDevice /reco-save >/dev/null;then
		systemException "Failed to mount recovery device" "reboot"
	fi
	#======================================
	# 16.2) restore root archive
	#--------------------------------------
	mkfifo /progress && cd /mnt && cp /usr/bin/tail /usr/bin/mst
	(
		rFiles=$(cat /reco-save/recovery.tar.files)
		tar --numeric-owner -xvpf /reco-save/recovery.tar.gz >/tmp/rFiles &
		rPID=$!
		while kill -0 $rPID &>/dev/null;do
			rReady=$(cat /tmp/rFiles | wc -l)
			#Echo -e -n "$rReady files from $rFiles restored...\r"
			echo "$rReady files from $rFiles restored..." > /progress
			sleep 1
		done
		dPID=$(pidof mst)
		kill $dPID
	)&
	mst -f /progress | dialog \
		--backtitle "Restoring base operating system..." \
		--progressbox 3 50
	clear
	#======================================
	# 16.3) restore boot files
	#--------------------------------------
	Echo "Restoring boot files..."
	for i in etc/fstab etc/sysconfig/kernel etc/sysconfig/bootloader;do
		if ! cp /reco-save/$i /mnt/$i;then
			systemException "Failed to restore $i" "reboot"
		fi
	done
	for i in `setupBootLoaderFiles`;do
		if ! cp /reco-save/$i /mnt/$i;then
			systemException "Failed to restore $i" "reboot"
		fi
	done
	for i in /reco-save/boot/grub/*;do
		if echo $i | grep -q .system;then
			sysbase=`echo ${i%%.system}`
			sysbase=`echo $sysbase | cut -f3- -d/`
			cp $i /mnt/$sysbase
		fi
	done
	#======================================
	# 16.4) umount recovery and boot
	#--------------------------------------
	umount $imageRecoveryDevice
	#======================================
	# 16.5) import oem config file
	#--------------------------------------
	importFile < $OEM_PARTITION_CONFIG
	IFS=$IFS_ORIG
fi

#======================================
# 17) get installed kernels
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
	kernelList /mnt
fi

#======================================
# 18) setup boot partition
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ]; then
	if [ "$haveLVM" = "yes" ];then
		#======================================
		# LVM use second partition as boot
		#--------------------------------------
		mkdir /mnt/lvmboot
		mount $imageBootDevice /mnt/lvmboot
		if [ -z $UNIONFS_CONFIG ];then
			cp -a /mnt/boot/* /mnt/lvmboot/boot
		fi
		rm -rf /mnt/boot
		( cd /mnt && ln -s lvmboot/boot boot )
	elif [ "$haveDMSquash" = "yes" ];then
		#======================================
		# DM use third partition as boot
		#--------------------------------------
		mkdir /mnt/dmboot
		bootid=3
		export imageBootDevice=$(ddn $imageDiskDevice 3)
		mount $imageBootDevice /mnt/dmboot
		cp -a  /mnt/boot /mnt/dmboot
		test -f /tmp/linux.vmx  && mv /tmp/linux.vmx  /mnt/dmboot/boot
		test -f /tmp/initrd.vmx && mv /tmp/initrd.vmx /mnt/dmboot/boot
		test -f /tmp/mbrid && mv /tmp/mbrid /mnt/dmboot/boot/grub
		rm -rf /mnt/boot
		( cd /mnt && ln -s dmboot/boot boot )
	elif [ "$haveLuks" = "yes" ];then
		#======================================
		# LUKS use second or third part as boot
		#--------------------------------------
		mkdir -p /mnt/luksboot
		imageBootDevice=$(ddn $imageDiskDevice 2)
		bootid=2
		if isFSTypeReadOnly;then
			export imageBootDevice=$(ddn $imageDiskDevice 3)
			bootid=3
		fi
		mount $imageBootDevice /mnt/luksboot
		cp -a /mnt/boot /mnt/luksboot
		test -f /tmp/linux.vmx  && mv /tmp/linux.vmx  /mnt/luksboot/boot
		test -f /tmp/initrd.vmx && mv /tmp/initrd.vmx /mnt/luksboot/boot
		test -f /tmp/mbrid && mv /tmp/mbrid /mnt/luksboot/boot/grub
		rm -rf /mnt/boot
		( cd /mnt && ln -s luksboot/boot boot )
	fi
fi

#======================================
# 19) setup ird/kernel links for union
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then 
	if [ "$OEM_KIWI_INITRD" = "yes" ] || isFSTypeReadOnly;then
		# /.../
		# we are using a special root setup with aufs. In this case
		# we can't use the SuSE Linux initrd but must stick to the
		# kiwi boot system.
		# ----
		mountCalled=no
		if [ "$haveLVM" = "yes" ];then
			pushd /mnt/lvmboot/boot >/dev/null
		elif [ "$haveDMSquash" = "yes" ];then
			pushd /mnt/dmboot/boot >/dev/null
		elif [ "$haveLuks" = "yes" ];then
			pushd /mnt/luksboot/boot >/dev/null
		elif [ "$OEM_KIWI_INITRD" = "yes" ];then
			pushd /mnt/boot >/dev/null
		else
			kiwiMount $imageRWDevice "/mnt"
			pushd /mnt/boot >/dev/null
			mountCalled=yes
		fi
		IFS="," ; for i in $KERNEL_LIST;do
			if test -z "$i";then
				continue
			fi
			kernel=`echo $i | cut -f1 -d:`
			initrd=`echo $i | cut -f2 -d:`
			rm -f $initrd && ln -s initrd.vmx $initrd
			rm -f $kernel && ln -s linux.vmx  $kernel
			break
		done
		IFS=$IFS_ORIG
		popd >/dev/null
		if [ "$mountCalled" = "yes" ];then
			umount /mnt
		fi
	fi
fi

#======================================
# 20) Create system dependant files
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
	#======================================
	# setup: /etc/fstab
	#--------------------------------------
	setupDefaultFstab /config
	updateRootDeviceFstab /config $imageRootDevice
	if [ "$haveLVM" = "yes" ];then
		updateLVMBootDeviceFstab /config $imageBootDevice
	elif [ "$haveDMSquash" = "yes" ];then
		updateDMBootDeviceFstab /config $imageBootDevice
	elif [ "$haveLuks" = "yes" ];then
		updateLuksBootDeviceFstab /config $imageBootDevice
	fi
	if partitionSize $imageSwapDevice &>/dev/null;then
		updateSwapDeviceFstab /config $imageSwapDevice
	else
		unset $imageSwapDevice
	fi
	if [ -z "$OEM_WITHOUTHOME" ] && [ -z "$DONT_PARTITION" ];then
		if [ `ls /mnt/home/ | wc -l` != 0 ]; then
			Echo "Found non empty home/ directory !"
			Echo "Moving home/ data to home partition $imageHomeDevice"
			mount $imageHomeDevice /mnt/mnt
			mv /mnt/home/*  /mnt/mnt
			mv /mnt/home/.* /mnt/mnt
			umount /mnt/mnt
		fi
		Echo "Activate home partition $imageHomeDevice in fstab"
		echo "$imageHomeDevice /home ext3 defaults 0 0" >> /config/etc/fstab
	fi
	if [ ! -z "$OEM_SAP_INSTALL" ];then
		SAP_DATA=/dev/data_vg/sapdata
		vgchange -a y data_vg
		if partitionSize $SAP_DATA &>/dev/null;then
			mkdir -p /mnt/sapdata
			echo "$SAP_DATA /sapdata ext3 defaults 0 0" >> /config/etc/fstab
		fi
	fi
	#======================================
	# setup: bootloader files
	#--------------------------------------
	Echo "Creating boot loader configuration"
	if [ -z "$OEM_BOOT_TITLE" ];then
		export OEM_BOOT_TITLE="OEM"
	fi
	if [ ! -z $OEM_RECOVERY ];then
		OEM_RECOVERY=$imageRootDevice
	fi
	setupBootLoader \
		/mnt /config $(($bootid - 1)) $imageRootDevice \
		"$OEM_BOOT_TITLE" $imageSwapDevice
	setupKernelModules /config
fi

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

#======================================
# 22) copy recovery related files
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ] && [ ! -z "$OEM_RECOVERY" ];then
	IFS=$IFS_ORIG
	Echo "Setting up recovery configuration files..."
	mkdir -p /reco-save
	if ! mount $imageRecoveryDevice /reco-save >/dev/null;then
		systemException "Failed to mount recovery device" "reboot"
	fi
	mkdir -p /reco-save/etc/sysconfig
	if ! cp /mnt/etc/fstab /reco-save/etc;then
		systemException "Failed to copy recovery fstab" "reboot"
	fi
	if ! cp /mnt/etc/sysconfig/kernel /reco-save/etc/sysconfig;then
		systemException "Failed to copy recovery sysconfig/kernel" "reboot"
	fi
	if ! cp /mnt/etc/sysconfig/bootloader /reco-save/etc/sysconfig;then
		systemException "Failed to copy recovery sysconfig/bootloader" "reboot"
	fi
	for i in `setupBootLoaderFiles`;do
		bootdir=`dirname $i` && mkdir -p /reco-save/$bootdir
		if ! cp /mnt/$i /reco-save/$i;then
			systemException "Failed to copy recovery $i" "reboot"
		fi
	done
	Echo "Installing boot loader into recovery partition"
	setupBootLoaderRecovery /mnt /reco-save OEM
	umount /reco-save && rmdir /reco-save
	installBootLoaderRecovery
fi

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

#======================================
# 24) setup real root device
#--------------------------------------
echo 256 > /proc/sys/kernel/real-root-dev

#======================================
# 25) umount system filesystems
#--------------------------------------
umountSystemFilesystems

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

#======================================
# 27) kill boot shell
#--------------------------------------
killShell
killBlogD

#======================================
# 28) Activate new root
#--------------------------------------
activateImage

#======================================
# 29 Unmount initrd / system init
#--------------------------------------
bootImage $@
