#!/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 ARCH=`arch`
export DEBUG=0

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

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

#======================================
# Exports (Partitioning)
#--------------------------------------
export PART_FILE="/etc/partition.table"
export PART_MOUNT
export PART_DEV
export PART_COUNT=0
export PART_NUMBER=0
export PART_NEED_EXTENDED=0
export PART_NEED_FILL=0
export NO_FILE_SYSTEM=0

#======================================
# Exports (Configuration)
#--------------------------------------
export LIVECD_CONFIG="/cdrom/config.isoclient"

#======================================
# Exports (Status)
#--------------------------------------
export SYSTEM_INTEGRITY
export SYSTEM_MD5STATUS

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

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

#======================================
# 1) Mounting local file systems
#--------------------------------------
mount -t proc  proc    /proc
mount -t sysfs sysfs   /sys
mount -t devpts devpts /dev/pts
closeKernelConsole

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

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

#======================================
# 3) Mount the CD device
#--------------------------------------
CDMount

#======================================
# 4) Load configuration
#--------------------------------------
importFile < $LIVECD_CONFIG

export systemIntegrity="clean"
#======================================
# 5) Check for installed system
#--------------------------------------
count=0
IFS="," ; for i in $IMAGE;do
case $count in
	0) {
	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
	count=1
	updateNeeded initialize
	if linuxPartition $DISK;then
		#e2fsck -y -C 0 $imageDevice
		mkdir -p /mnt
		mount $imageDevice /mnt >/dev/null 2>&1
		mountstatus=$?
		updateNeeded
		if test $mountstatus = 0;then
			umount /mnt
		fi
		systemIntegrity=`getSystemIntegrity 1`
		if [ $systemIntegrity = "fine" ];then
			Echo "Base system is up to date..."
		fi
	fi
    }
	;;
	*)
	# handle other images here...
	;;
esac
done

#======================================
# 6) Create partition table if needed
#--------------------------------------
if test $systemIntegrity = "clean";then
	Echo "Creating partition table..."
	partitionCount
	createSwap
	createPartition
	writePartitionTable $DISK
	IFS=":" ; for i in $PART_DEV;do
	if test ! -z "$i";then
		createFileSystem $i
	fi
	done
	mkswap ${DISK}1 >/dev/null 2>&1
fi

#======================================
# 7) Install disk 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) imageBlkSize=$n; field=4 ;;
		4) imageZipped=$n ;
	esac
	done
	if [ $count = 1 ];then
		imageRootDevice=$imageDevice
		imageRootName=$imageName
	fi
	if [ $count = 2 ];then
		imageNextRootDevice=$imageDevice
	fi
	if test `getSystemIntegrity $count` = "fine";then
		continue
	fi
	imageName="/cdrom/$imageName-$imageVersion"
	imageMD5s="$imageName.md5"
	while true;do
		IFS=" "
		read sum1 blocks blocksize < $imageMD5s
		if ! validateSize;then
			systemException \
				"Not enough space available for this image" \
				"reboot"
		fi
		# /.../
		# now load the image into the imageDevice
		# ---
		if test "$imageZipped" = "compressed"; then
			Echo "Compressed image found"
			test ! -p /dev/compressed_image && mkfifo /dev/compressed_image
			cat /dev/compressed_image | gzip -d > $imageDevice 2>/dev/null &
			imageDevice_orig=$imageDevice
			imageName_orig=$imageName
			imageDevice="/dev/compressed_image"
			imageName="$imageName.gz"
		fi
		Echo "Loading $imageName [$imageDevice BS:$imageBlkSize Byte]..."
		if ! dd if=$imageName of=$imageDevice bs=$blocksize count=$blocks >/dev/null 2>&1; then
			systemException \
				"Failed to load image: $imageName -> no such image" \
				"reboot"
		fi
		if test "$imageZipped" = "compressed"; then
			imageDevice=$imageDevice_orig
			imageName=$imageName_orig
			rm -f /dev/compressed_image
		fi
		# /.../
		# check the md5sum of the downloaded data records
		# ----
		dd if=$imageDevice count=$blocks bs=$blocksize 2>/dev/null |\
			md5sum - > /etc/ireal.md5
		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 "   disk provides the same md5 sum as included"
		Echo -b "   within the appropriate .md5 file for this image"
		echo
		if test -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"
		fi
		echo
		Echo "Retrying image load in 15 seconds..."
		sleep 15
	done

	mkdir -p /mnt
	probeFileSystem $imageRootDevice
	Echo "Resize filesystem to full partition space..."
	if test "$FSTYPE" = "reiserfs";then
		resize_reiserfs $imageDevice
		INITRD_MODULES="$INITRD_MODULES reiserfs"
	fi
	if test "$FSTYPE" = "ext2";then
		e2fsck -y -f $imageDevice
		resize2fs -F -p $imageDevice
		INITRD_MODULES="$INITRD_MODULES ext2"
	fi
	if test "$FSTYPE" = "ext3";then
		e2fsck -y -f $imageDevice
		resize2fs -F -p $imageDevice
		tune2fs -j $imageDevice
		INITRD_MODULES="$INITRD_MODULES ext3"
	fi
	if test "$FSTYPE" = "squashfs";then
		INITRD_MODULRES="$INITRD_MODULES squashfs"
	fi

	rm -f /etc/ireal.md5
	rm -f /etc/image.md5
done

#======================================
# 8) Check for RELOAD_CONFIG
#--------------------------------------
if test ! -z $RELOAD_CONFIG;then
	systemIntegrity_save=$systemIntegrity
	systemIntegrity="clean"
fi

#======================================
# 9) Mount OS image to /mnt
#--------------------------------------
mkdir -p /mnt
mount $imageRootDevice /mnt

#======================================
# 10) check filesystem and kernels
#--------------------------------------
if test $systemIntegrity = "clean";then
	probeFileSystem $imageRootDevice
	kernelList /mnt
fi

#======================================
# 11) Create system dependant files
#--------------------------------------
if test $systemIntegrity = "clean";then
	mkdir -p /config/etc
	echo "$imageRootDevice / $FSTYPE defaults 0 0"        > /config/etc/fstab
	echo "devpts  /dev/pts   devpts mode=0620,gid=5 0 0" >> /config/etc/fstab
	echo "proc    /proc   proc    defaults 0 0"          >> /config/etc/fstab
	echo "sysfs   /sys    sysfs   noauto 0 0"            >> /config/etc/fstab
	echo "tmpfs   /dev/shm tmpfs  defaults 0 0"          >> /config/etc/fstab
	if test ! -z $DISK;then
		# a) /etc/fstab...
		# ----------------
		echo "${DISK}1 swap swap pri=42 0 0" >> /config/etc/fstab
		index=0
		IFS=":" ; for i in $PART_MOUNT;do
		if test ! -z "$i";then
			count=0
			IFS=":" ; for n in $PART_DEV;do
				device=$n
				if test $count -eq $index;then
					break
				fi
				count=`expr $count + 1`
			done
			index=`expr $index + 1`
			if test ! $i = "/";then
				probeFileSystem $device
				echo "$device $i $FSTYPE defaults 1 1" >> /config/etc/fstab
			fi
		fi
		done
		# b) /boot/grub/menu.lst...
		# -------------------------
		console=""
		mkdir -p /config/boot/grub
		echo "timeout 10" > /config/boot/grub/menu.lst
		IFS="," ; for i in $KERNEL_LIST;do
		if test ! -z "$i";then
			kernel=`echo $i | cut -f1 -d:`
			initrd=`echo $i | cut -f2 -d:`
			menu=/config/boot/grub/menu.lst
			echo "title $kernel" >> $menu
			if [ $kernel = "vmlinuz-xen" ];then
				echo " root (hd0,1)"                   >> $menu
				echo " kernel /boot/xen.gz"            >> $menu
				echo -n " module /boot/$kernel"        >> $menu
				echo " root=${DISK}2 $console"         >> $menu
				echo " module /boot/$initrd"           >> $menu
			else
				echo -n " kernel (hd0,1)/boot/$kernel" >> $menu
				echo " root=${DISK}2 $console"         >> $menu
				echo " initrd (hd0,1)/boot/$initrd"    >> $menu
			fi
		fi
		done
		# c) /etc/grub.conf...
		# -------------------------
		mkdir -p /config/etc
		gconf=/config/etc/grub.conf
		echo -en "root (hd0,1)\ninstall"         > $gconf
		echo -n " --stage2=/boot/grub/stage2"   >> $gconf
		echo -n " /boot/grub/stage1 d (hd0)"    >> $gconf
		echo -n " /boot/grub/stage2 0x8000"     >> $gconf
		echo " (hd0,1)/boot/grub/menu.lst"      >> $gconf
		echo "quit"                             >> $gconf
		# d) /etc/sysconfig/kernel...
		# ---------------------------
		mkdir -p /config/etc/sysconfig
		syskernel=/config/etc/sysconfig/kernel
		echo "INITRD_MODULES=\"$INITRD_MODULES\""       > $syskernel
		echo "DOMU_INITRD_MODULES=\"$DOMURD_MODULES\"" >> $syskernel
	fi
fi

#======================================
# 12) copy system dependant files
#--------------------------------------
if test $systemIntegrity = "clean";then
	cd /config
	find . -type d | while read d ; do  mkdir -p /mnt/$d ; done
	find . -type f | while read f ; do  cp $f /mnt/$f ; done
	cd /
	rm -rf /config
fi

#======================================
# 13) copy initrd files to image
#--------------------------------------
cp /preinit /mnt
cp /include /mnt

#======================================
# 14) unmount the CD
#--------------------------------------
CDUmount

#======================================
# 15) Intall grub and initrd (preinit)
#--------------------------------------
Echo "Activating Image: [$imageRootDevice]"
cd /mnt && exec < dev/console >dev/console 2>&1
Echo "Calling preinit phase..."
reopenKernelConsole
/mnt/sbin/pivot_root . mnt >/dev/null 2>&1
if test $? != 0;then
	PIVOT=false
	cleanInitrd && mount --move . / && chroot . ./preinit
	chroot . rm ./preinit
	chroot . rm ./include
else
	PIVOT=true
	./preinit
	rm ./preinit
	rm ./include
fi

Echo "Rebooting System..."
sleep 5
/sbin/restart >/dev/null 2>&1
