#!/bin/bash
#================
# FILE          : livestick
#----------------
# PROJECT       : openSUSE Build-Service
# COPYRIGHT     : (c) 2013 SUSE LINUX Products GmbH, Germany
#               :
# AUTHOR        : Marcus Schaefer <ms@suse.de>
#               :
# BELONGS TO    : Operating System images
#               :
# DESCRIPTION   : helper tool to deploy kiwi live iso image on a
#               : USB stick without removing data from the stick
#               :
# STATUS        : Work-In-Progress
#----------------
#==========================================
# pre-checks
#------------------------------------------
if [ -z "$1" ] || [ -z "$2" ];then
	echo "Usage: livestick kiwi-live.iso /dev/stick"
	exit 1
fi

#==========================================
# Functions
#------------------------------------------
. /usr/share/kiwi/modules/KIWILinuxRC.sh

#==========================================
# Functions
#------------------------------------------
function clean {
	if [ -d "$tmpdir" ];then
		rm -rf $tmpdir
	fi
	exit 1
}

#==========================================
# Signal handling
#------------------------------------------
trap clean INT TERM

#==========================================
# get disk-by-id device name first
#------------------------------------------
disk=$2
device_disk=$(getDiskID $disk)
device_part=$(getDiskID $(ddn $(dn $device_disk) 1))
if [ ! -e "$device_disk" ];then
	echo "Can't find disk for $disk"
	clean
fi
if [ ! -e "$device_part" ];then
	echo "Can't find partition table for $disk"
	clean
fi

#==========================================
# check if iso file exists
#------------------------------------------
image=$1
image_base=$(basename $image)
if [ ! -e $image ];then
	echo "Can't find OS image"
	clean
fi

#==========================================
# create tmp directory
#------------------------------------------
tmpdir=$(mktemp -q -d /tmp/kiwi-livestick.XXXXXX)
if [ ! -d $tmpdir ];then
	echo "Can't create tmpdir"
	clean
fi
mkdir -p $tmpdir/boot/grub2

#==========================================
# unpack grub2 theme tarball into a tmpdir
#------------------------------------------
echo "==> Preparation in progress..."
theme=/usr/share/kiwi/livestick/theme/suse-12.3/booting.tgz
if ! tar -C $tmpdir/boot/grub2 -xf $theme;then
	echo "Can't extract grub2 theme files"
	clean
fi

#==========================================
# unpack boot helpers, bootnext, memcheck
#------------------------------------------
tools=/usr/share/kiwi/livestick/theme/suse-12.3/tooling.tgz
if ! tar -C $tmpdir/boot -xf $tools; then
	echo "Can't extract boot helper files"
	clean
fi

#==========================================
# hard link grub2 stages
#------------------------------------------
if [ ! -d /boot/grub2/i386-pc ];then
	echo "Can't find grub2(i386-pc) on this system"
	clean
fi
cp -al /boot/grub2/i386-pc $tmpdir/boot/grub2

#==========================================
# create device.map file
#------------------------------------------
echo "(hd0) $device_disk" > $tmpdir/boot/grub2/device.map

#==========================================
# create grub2 prefix boot file
#------------------------------------------
uuid=$(blkid -o value -s UUID $device_part)
conf=$tmpdir/boot/grub2/bootpart.cfg
echo "search --no-floppy --fs-uuid --set=root $uuid" > $conf
echo 'set prefix=($root)/boot/grub2'   >> $conf

#==========================================
# create grub configuration
#------------------------------------------
conf=$tmpdir/boot/grub2/grub.cfg
arch=x86_64
if ! isoinfo -p -i $image | grep -q X86_64;then
	arch=i386
	title=$(echo $image_base | sed -e s@\.i.86.*@@)
else
	title=$(echo $image_base | sed -e s@\.x86_64.*@@)
fi
cmdline_std="isofrom_device=$device_part"
cmdline_std="$cmdline_std isofrom_system=/boot/$image_base"
cmdline_std="$cmdline_std kiwi_cowdevice=$device_part"
cmdline_std="$cmdline_std kiwi_cowsystem=/boot/cowfile"
cmdline_std="$cmdline_std kiwi_hybridpersistent=yes splash=silent"
cmdline_std="$cmdline_std ramdisk_size=512000 ramdisk_blocksize=4096"

cmdline_fsf="$cmdline_std ide=nodma apm=off noresume edd=off powersaved=off"
cmdline_fsf="$cmdline_fsf nohz=off highres=off processsor.max+cstate=1"
cmdline_fsf="$cmdline_fsf nomodeseet x11failsafe"

cat > $conf <<- EOF
	insmod fat
	insmod ntfs
	insmod ext2
	insmod gettext
	insmod part_msdos
	insmod chain
	insmod vbe
	insmod vga
	insmod video_bochs
	insmod video_cirrus
	insmod gzio
	insmod search
	insmod configfile
	insmod png
	search --no-floppy --fs-uuid --set=root $uuid
	set default=0
	set font=/boot/grub2/fonts/unicode.pf2
	if loadfont \$font ;then
	    set gfxmode=auto
	    insmod gfxterm
	    insmod gfxmenu
	    if terminal_output gfxterm; then true; else
	        terminal gfxterm
	    fi
	fi
	if loadfont /boot/grub2/themes/openSUSE/ascii.pf2;then
	    loadfont /boot/grub2/themes/openSUSE/DejaVuSans-Bold14.pf2
	    loadfont /boot/grub2/themes/openSUSE/DejaVuSans10.pf2
	    loadfont /boot/grub2/themes/openSUSE/DejaVuSans12.pf2
	    loadfont /boot/grub2/themes/openSUSE/ascii.pf2
	    set theme=/boot/grub2/themes/openSUSE/theme.txt
	    background_image -m stretch /boot/grub2/themes/openSUSE/background.png
	fi
	set timeout=10
	menuentry "$title" --class opensuse --class os {
	    echo Loading live system...
	    loopback loop /boot/$image_base
		echo Loading linux...
	    linux (loop)/boot/$arch/loader/linux $cmdline_std quiet
		echo Loading initrd...
	    initrd (loop)/boot/$arch/loader/initrd
	}
	menuentry "Failsafe -- $title" --class opensuse --class os {
	    echo Loading live system...
	    loopback loop /boot/$image_base
	    echo Loading linux...
	    linux (loop)/boot/$arch/loader/linux $cmdline_fsf quiet
	    echo Loading initrd...
	    initrd (loop)/boot/$arch/loader/initrd
	}
	menuentry "Boot from Hard Disk" --class opensuse --class os {
	    set root=(hd1)
	    chainloader +1
	}
	menuentry "Memory Test" --class opensuse --class os {
	    linux16 /boot/memtest
	}
EOF

#==========================================
# hard link image
#------------------------------------------
if ! cp -l $image $tmpdir/boot;then
	echo "Can't copy image"
	clean
fi

#==========================================
# create grub2 core image
#------------------------------------------
format=i386-pc
biosmod="biosdisk part_msdos ext2 iso9660 chain"
biosmod="$biosmod normal linux echo vga vbe png"
biosmod="$biosmod video_bochs video_cirrus gzio"
biosmod="$biosmod multiboot search configfile fat ntfs"
core=$tmpdir/boot/grub2/$format/core.img
bootconf=$tmpdir/boot/grub2/bootpart.cfg
if ! grub2-mkimage -O $format -o $core -c $bootconf $biosmod &>/dev/null;then
	echo "Can't create core boot image"
	clean
fi

#==========================================
# create cow file space
#------------------------------------------
if ! qemu-img create $tmpdir/boot/cowfile 500M &>/dev/null;then
	echo "Can't create cow file"
	clean
fi

#==========================================
# mount stick partition nr 1
#------------------------------------------
echo "==> Mounting stick..."
if ! mount $device_part /mnt;then
	echo "Can't mount target device"
	clean
fi

#==========================================
# sync tmpdir to / on the stick
#------------------------------------------
if ! rsync -rltvh --progress --modify-window=1 --delete $tmpdir/* /mnt;then
	echo "Can't rsync data to target"
	umount /mnt
	clean
fi

#==========================================
# install grub2 on stick
#------------------------------------------
stages=/mnt/boot/grub2/$format
devmap=/mnt/boot/grub2/device.map
if ! sfdisk $device_disk --force -A 1;then
	echo "Can't set first partition active"
	umount /mnt
	clean
fi
if ! grub2-bios-setup -f -d $stages -m $devmap $device_disk &>/dev/null;then
	echo "Can't install grub2 into MBR"
	umount /mnt
	clean
fi

echo "==> Umount..."
umount /mnt
clean
