kiwi-el8/boot/functions.sh
Marcus Schäfer 09daca60c0
KIWI - appliance builder next generation
a rewrite of the current kiwi from https://github.com/openSUSE/kiwi
2015-12-05 16:17:10 +01:00

11330 lines
372 KiB
Bash

#================
# FILE : functions.sh
#----------------
# PROJECT : openSUSE Build-Service
# COPYRIGHT : (c) 2006 SUSE LINUX Products GmbH, Germany
# :
# AUTHOR : Marcus Schaefer <ms@suse.de>
# :
# BELONGS TO : Operating System images
# :
# DESCRIPTION : This module contains common used functions
# : for the suse linuxrc and preinit boot image
# : files
# :
# :
# STATUS : Development
#----------------
#======================================
# Exports (General)
#--------------------------------------
export BOOTABLE_FLAG="$(echo -ne '\x80')"
export ELOG_FILE=/var/log/boot.kiwi
export TRANSFER_ERRORS_FILE=/tmp/transfer.errors
export UFONT=/usr/share/fbiterm/fonts/b16.pcf.gz
export CONSOLE_FONT=/usr/share/kbd/consolefonts/default8x16.gz
export HYBRID_PERSISTENT_FS=btrfs
export HYBRID_PERSISTENT_ID=83
export HYBRID_PERSISTENT_DIR=/read-write
export UTIMER_INFO=/dev/utimer
export bootLoaderOK=0
export enablePlymouth=1
export IFS_ORIG=$IFS
export MEDIACHECK_OK_TIMER=5
export partitionerWriteStatus=0
#======================================
# lookup
#--------------------------------------
function lookup {
bash -c "PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin type -p $1"
}
#======================================
# Exports (console)
#--------------------------------------
test -z "$ELOG_BOOTSHELL" && export ELOG_BOOTSHELL=/dev/tty2
test -z "$ELOG_EXCEPTION" && export ELOG_EXCEPTION=/dev/console
#======================================
# Exports (General)
#--------------------------------------
test -z "$RECOVERY_THEME" && export RECOVERY_THEME=openSUSE
test -z "$splitroot_size" && export splitroot_size=512
test -z "$arch" && export arch=$(uname -m)
test -z "$haveDASD" && export haveDASD=0
test -z "$haveZFCP" && export haveZFCP=0
test -z "$ELOG_STOPPED" && export ELOG_STOPPED=0
test -z "$PARTITIONER" && export PARTITIONER=parted
test -z "$DEFAULT_VGA" && export DEFAULT_VGA=0x314
test -z "$HAVE_MODULES_ORDER" && export HAVE_MODULES_ORDER=1
test -z "$DIALOG_LANG" && export DIALOG_LANG=ask
test -z "$TERM" && export TERM=linux
test -z "$LANG" && export LANG=en_US.utf8
test -z "$UTIMER" && export UTIMER=0
test -z "$PARTED_HAVE_ALIGN" && export PARTED_HAVE_ALIGN=0
test -z "$PARTED_HAVE_MACHINE"&& export PARTED_HAVE_MACHINE=0
test -z "$DHCPCD_HAVE_PERSIST"&& export DHCPCD_HAVE_PERSIST=1
if lookup parted &>/dev/null;then
if parted -h | grep -q '\-\-align';then
export PARTED_HAVE_ALIGN=1
fi
if parted -h | grep -q '\-\-machine';then
export PARTED_HAVE_MACHINE=1
fi
if [ $PARTED_HAVE_MACHINE -eq 0 ];then
export PARTITIONER=unsupported
fi
fi
if lookup dhcpcd &>/dev/null;then
if dhcpcd -p 2>&1 | grep -q 'Usage';then
export DHCPCD_HAVE_PERSIST=0
fi
fi
#======================================
# Exports (arch specific)
#--------------------------------------
if [[ $arch =~ ppc64 ]];then
test -z "$loader" && export loader=yaboot
elif [[ $arch =~ arm ]];then
test -z "$loader" && export loader=uboot
elif [[ $arch =~ s390 ]];then
test -z "$loader" && export loader=zipl
else
test -z "$loader" && export loader=grub
fi
#======================================
# Exports boot options
#--------------------------------------
failsafe="ide=nodma apm=off noresume edd=off"
failsafe="$failsafe powersaved=off nohz=off"
failsafe="$failsafe highres=off processsor.max+cstate=1"
failsafe="$failsafe nomodeset x11failsafe"
#======================================
# hideSplash
#--------------------------------------
function hideSplash {
# /.../
# Only in case of one active console kiwi hides
# the splash screen for it to allow interactive dialog
# sessions on this console. In any other case the user
# can control a custom behavior using the handleSplash
# hook called at the end of this function
# ----
local IFS=$IFS_ORIG
local console_count=$(activeConsoles)
if [ $console_count -eq 1 ];then
test -e /proc/splash && echo verbose > /proc/splash
if lookup plymouthd &>/dev/null;then
plymouth hide-splash
# reset tty after plymouth messed with it
consoleInit
fi
fi
runHook handleSplash "$@"
}
#======================================
# Dialog
#--------------------------------------
function Dialog {
local IFS=$IFS_ORIG
local code=1
export DIALOG_CANCEL=1
hideSplash
cat > /tmp/fbcode << EOF
dialog \
--ok-label "$TEXT_OK" \
--cancel-label "$TEXT_CANCEL" \
--yes-label "$TEXT_YES" \
--no-label "$TEXT_NO" \
--exit-label "$TEXT_EXIT" \
$@
echo \$? > /tmp/fbcode
EOF
if FBOK;then
fbiterm -m $UFONT -- bash -e /tmp/fbcode
else
bash -e /tmp/fbcode
fi
code=$(cat /tmp/fbcode)
return $code
}
#======================================
# Debug
#--------------------------------------
function Debug {
# /.../
# print message if variable DEBUG is set to 1
# -----
local IFS=$IFS_ORIG
if test "$DEBUG" = 1;then
echo "+++++> $1"
fi
}
#======================================
# Echo
#--------------------------------------
function Echo {
# /.../
# print a message to the controling terminal
# ----
local IFS=$IFS_ORIG
if [ $ELOG_STOPPED = 0 ];then
set +x
fi
if [ ! $UTIMER = 0 ] && kill -0 $UTIMER &>/dev/null;then
kill -HUP $UTIMER
local prefix=$(cat $UTIMER_INFO)
else
local prefix="===>"
fi
local option=""
local optn=""
local opte=""
while getopts "bne" option;do
case $option in
b) prefix=" " ;;
n) optn="-n" ;;
e) opte="-e" ;;
*) echo "Invalid argument: $option" ;;
esac
done
shift $(($OPTIND - 1))
if [ $ELOG_STOPPED = 0 ];then
set -x
fi
echo $optn $opte "$prefix $1"
if [ $ELOG_STOPPED = 0 ];then
set +x
fi
OPTIND=1
if [ $ELOG_STOPPED = 0 ];then
set -x
fi
}
#======================================
# WaitKey
#--------------------------------------
function WaitKey {
# /.../
# if DEBUG is set wait for ENTER to continue
# ----
local IFS=$IFS_ORIG
if test "$DEBUG" = 1;then
Echo -n "Press ENTER to continue..."
read
fi
}
#======================================
# importFile
#--------------------------------------
function importFile {
# /.../
# import the config.<MAC> style format. the function
# will export each entry of the file as variable into
# the current shell environment
# ----
local IFS=$IFS_ORIG
local prefix=$1
# create clean input, no empty lines and comments
cat - | grep -v '^$' | grep -v '^[ \t]*#' > /tmp/srcme
# remove start/stop quoting from values
sed -i -e s"#\(^[a-zA-Z0-9_]\+\)=[\"']\(.*\)[\"']#\1=\2#" /tmp/srcme
# remove backslash quotes if any
sed -i -e s"#\\\\\(.\)#\1#g" /tmp/srcme
# quote simple quotation marks
sed -i -e s"#'\+#'\\\\''#g" /tmp/srcme
# add '...' quoting to values
sed -i -e s"#\(^[a-zA-Z0-9_]\+\)=\(.*\)#$prefix\1='\2'#" /tmp/srcme
source /tmp/srcme &>/dev/null
while read line;do
key=$(echo "$line" | cut -d '=' -f1)
eval "export $key" &>/dev/null
done < /tmp/srcme
if [ ! -z "$ERROR_INTERRUPT" ];then
Echo -e "$ERROR_INTERRUPT"
systemException "*** interrupted ****" "shell"
fi
}
#======================================
# unsetFile
#--------------------------------------
function unsetFile {
# /.../
# unset variables specified within the given file.
# the file must be in the config.<MAC> style format
# ----
local IFS="
"
local prefix=$1 #change name of key with a prefix
while read line;do
echo $line | grep -qi "^#" && continue
key=`echo "$line" | cut -d '=' -f1`
if [ -z "$key" ];then
continue
fi
Debug "unset $prefix$key"
eval unset "$prefix$key"
done
}
#======================================
# condenseConfigData
#--------------------------------------
function condenseConfigData {
# /.../
# if multiple same config files (config files with same deployment path)
# are present on the CONF line,
# only last one will be kept (this preserves compatibility)
# ----
local IFS=","
local conf=( $1 )
local cconf
local sep=''
for (( i=0; i<${#conf[@]}; i++ ));do
local configDest=`echo "${conf[$i]}" | cut -d ';' -f 2`
if test ! -z $configDest;then
local copythis=1
for (( j=i+1; j<${#conf[@]}; j++ ));do
local cmpconfigDest=`echo "${conf[$j]}" | cut -d ';' -f 2`
if [ "$cmpconfigDest" = "$configDest" ];then
copythis=0
break
fi
done
[ $copythis -eq '1' ] && cconf="${cconf}${sep}${conf[$i]}"
sep=$IFS
fi
done
echo "$cconf"
}
#======================================
# systemException
#--------------------------------------
function systemException {
# /.../
# print a message to the controling terminal followed
# by an action. Possible actions are reboot, wait, shutdown,
# and opening a shell
# ----
local IFS=$IFS_ORIG
set +x
local what=$2
local nuldev=/dev/null
local ttydev=$ELOG_EXCEPTION
local prefix=/mnt
for dev in $nuldev $prefix/$nuldev; do
if [ -e $dev ];then
nuldev=$dev; break
fi
done
for dev in $ttydev $prefix/$ttydev; do
if [ -e $dev ];then
ttydev=$dev; break
fi
done
hideSplash
if [ $enablePlymouth -eq 1 ]; then
plymouth quit
fi
if [ $what = "reboot" ];then
if cat /proc/cmdline 2>/dev/null | grep -qi "kiwidebug=1";then
what="shell"
fi
fi
runHook preException "$@"
Echo -e "$1"
case "$what" in
"reboot")
# in order to see all log information in case of a reboot exception
# we print the current log contents to the console. On systems like
# public clouds the console information is stored and provided to
# the user. Thus it makes sense to be verbose here
cat $ELOG_FILE
Echo "rebootException: reboot in 120 sec..."; sleep 120
/sbin/reboot -f -i >$nuldev
;;
"wait")
Echo "waitException: waiting for ever..."
while true;do sleep 100;done
;;
"waitkey")
Echo "waitException: Press any key to continue: "
read
;;
"shell")
if [ ! -z "$DROPBEAR_PID" ] && [ ! -z "$IPADDR" ];then
Echo "You can connect via ssh to this system"
Echo "ssh root@${IPADDR}"
fi
echo reset > /root/.bashrc
setctsid $ttydev sulogin -e $ttydev
;;
"user_reboot")
Echo "reboot triggered by user"
Echo "reboot in 30 sec..."; sleep 30
/sbin/reboot -f -i >$nuldev
;;
*)
Echo "unknownException..."
;;
esac
}
#======================================
# copyDevices
#--------------------------------------
function copyDeviceNodes {
local IFS=$IFS_ORIG
local search=$1
local prefix=$2
local dtype
local major
local minor
local perms
if [ -z "$search" ];then
search=/dev
fi
pushd $search >/dev/null
for i in *;do
if [ -e $prefix/$i ];then
continue
fi
if [ -b $i ];then
dtype=b
elif [ -c $i ];then
dtype=c
elif [ -p $i ];then
dtype=p
else
continue
fi
info=`stat $i -c "0%a:0x%t:0x%T"`
major=`echo $info | cut -f2 -d:`
minor=`echo $info | cut -f3 -d:`
perms=`echo $info | cut -f1 -d:`
if [ $dtype = "p" ];then
mknod -m $perms $prefix/$i $dtype
else
mknod -m $perms $prefix/$i $dtype $major $minor
fi
done
popd >/dev/null
}
#======================================
# createInitialDevices
#--------------------------------------
function createInitialDevices {
local IFS=$IFS_ORIG
local prefix=$1
#======================================
# create master dev dir
#--------------------------------------
mkdir -p $prefix
if [ ! -d $prefix ];then
return
fi
#======================================
# mount devtmpfs or tmpfs
#--------------------------------------
if mount -t devtmpfs -o mode=0755,nr_inodes=0 devtmpfs $prefix; then
export have_devtmpfs=true
else
export have_devtmpfs=false
mount -t tmpfs -o mode=0755,nr_inodes=0 udev $prefix
mknod -m 0666 $prefix/tty c 5 0
mknod -m 0600 $prefix/console c 5 1
mknod -m 0666 $prefix/ptmx c 5 2
mknod -m 0666 $prefix/null c 1 3
mknod -m 0600 $prefix/kmsg c 1 11
mknod -m 0660 $prefix/snapshot c 10 231
mknod -m 0666 $prefix/random c 1 8
mknod -m 0644 $prefix/urandom c 1 9
fi
#======================================
# mount shared mem tmpfs
#--------------------------------------
mkdir -m 1777 $prefix/shm
mount -t tmpfs -o mode=1777 tmpfs $prefix/shm
#======================================
# mount udev db tmpfs
#--------------------------------------
mkdir -p -m 0755 /run
mkdir -p -m 0755 /var/run
if [[ ! $kiwi_iname =~ SLE.11 ]];then
mount -t tmpfs -o mode=0755,nodev,nosuid tmpfs /run
mount --bind /run /var/run
fi
#======================================
# mount devpts tmpfs
#--------------------------------------
mkdir -m 0755 $prefix/pts
mount -t devpts -o mode=0620,gid=5 devpts $prefix/pts
#======================================
# link default descriptors
#--------------------------------------
ln -s /proc/self/fd $prefix/fd
ln -s fd/0 $prefix/stdin
ln -s fd/1 $prefix/stdout
ln -s fd/2 $prefix/stderr
#======================================
# create directories in /run
#--------------------------------------
mkdir -p -m 0755 /run/lock
mkdir -p -m 0755 /run/log
}
#======================================
# mount_rpc_pipefs
#--------------------------------------
function mount_rpc_pipefs {
local IFS=$IFS_ORIG
# See if the file system is there yet
if [ ! -e /var/lib/nfs/rpc_pipefs ];then
return 0
fi
case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs 2>/dev/null` in
*67596969*)
return 0;;
esac
mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
}
#======================================
# umount_rpc_pipefs
#--------------------------------------
function umount_rpc_pipefs {
local IFS=$IFS_ORIG
# See if the file system is there
case `stat -c "%t" -f /var/lib/nfs/rpc_pipefs 2>/dev/null` in
*67596969*)
umount /var/lib/nfs/rpc_pipefs
esac
}
#======================================
# setupNFSServices
#--------------------------------------
function setupNFSServices {
local IFS=$IFS_ORIG
mount_rpc_pipefs
if [ -x /sbin/rpcbind ];then
startproc /sbin/rpcbind
fi
if [ -x /usr/sbin/rpc.statd ];then
startproc /usr/sbin/rpc.statd --no-notify
fi
if [ -x /usr/sbin/rpc.idmapd ];then
startproc /usr/sbin/rpc.idmapd
fi
}
#======================================
# mountSystemFilesystems
#--------------------------------------
function mountSystemFilesystems {
local IFS=$IFS_ORIG
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
fi
if [ ! -e /sys/kernel ];then
mount -t sysfs sysfs /sys
fi
if [ -e /run/initramfs/shutdown ];then
chmod u+x /run/initramfs/shutdown
fi
}
#======================================
# umountSystemFilesystems
#--------------------------------------
function umountSystemFilesystems {
local IFS=$IFS_ORIG
umount_rpc_pipefs
umount /dev/pts &>/dev/null
umount /sys &>/dev/null
umount /proc &>/dev/null
}
#======================================
# createFramebufferDevices
#--------------------------------------
function createFramebufferDevices {
local IFS=$IFS_ORIG
if [ -f /proc/fb ]; then
while read fbnum fbtype; do
if [ $(($fbnum < 32)) ] ; then
if [ ! -c /dev/fb$fbnum ];then
Echo "Creating framebuffer device: /dev/fb$fbnum"
mknod -m 0660 /dev/fb$fbnum c 29 $fbnum
fi
fi
done < /proc/fb
fi
}
#======================================
# errorLogStop
#--------------------------------------
function errorLogStop {
local IFS=$IFS_ORIG
set +x
export ELOG_STOPPED=1
exec < $ELOG_EXCEPTION &> $ELOG_EXCEPTION
}
#======================================
# errorLogContinue
#--------------------------------------
function errorLogContinue {
local IFS=$IFS_ORIG
exec 2>>$ELOG_FILE
exec < $ELOG_EXCEPTION > $ELOG_EXCEPTION
export ELOG_STOPPED=0
set -x
}
#======================================
# errorLogStart
#--------------------------------------
function errorLogStart {
# /.../
# Log all errors and the debug information to the
# file set in ELOG_FILE.
# ----
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -f $ELOG_FILE ];then
#======================================
# Header for main stage log
#--------------------------------------
echo "KIWI Log:" >> $ELOG_FILE
else
#======================================
# Header for pre-init stage log
#--------------------------------------
startUtimer
echo "KIWI PreInit Log" >> $ELOG_FILE
fi
#======================================
# Contents of .profile environment
#--------------------------------------
if [ -f .profile ];then
echo "KIWI .profile contents:" >> $ELOG_FILE
cat .profile >> $ELOG_FILE
fi
#======================================
# Redirect stderr to ELOG_FILE
#--------------------------------------
exec 2>>$ELOG_FILE
#======================================
# Mount proc for cmdline quiet check
#--------------------------------------
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
umountProc=1
fi
if cat /proc/cmdline | grep -qi "quiet";then
#======================================
# Redirect/Clean stdout if quiet is set
#--------------------------------------
exec >/dev/null
if [ -x /usr/bin/setterm ];then
setterm -clear all
setterm -background black
fi
else
#======================================
# Redirect stdout to console
#--------------------------------------
exec < $ELOG_EXCEPTION > $ELOG_EXCEPTION
fi
#======================================
# Clean proc
#--------------------------------------
if [ $umountProc -eq 1 ];then
umount /proc
fi
#======================================
# Enable shell debugging
#--------------------------------------
set -x
}
#======================================
# udevPending
#--------------------------------------
function udevPending {
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -e /proc/cmdline ];then
mount -t proc proc /proc
umountProc=1
fi
local timeout=30
local udevadmExec=$(lookup udevadm 2>/dev/null)
if [ -x $udevadmExec ];then
$udevadmExec settle --timeout=$timeout
else
# udevsettle exists on old distros and is not
# affected by the move from sbin to usr
/sbin/udevsettle --timeout=$timeout
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# udevTrigger
#--------------------------------------
function udevTrigger {
local IFS=$IFS_ORIG
local udevadmExec=$(lookup udevadm 2>/dev/null)
if [ -x $udevadmExec ];then
$udevadmExec trigger
else
/sbin/udevtrigger
fi
}
#======================================
# udevSystemStart
#--------------------------------------
function udevSystemStart {
# /.../
# start udev daemon
# ----
local IFS=$IFS_ORIG
local udev_bin=/usr/lib/systemd/systemd-udevd
if [ ! -x $udev_bin ];then
udev_bin=/sbin/udevd
fi
if [ ! -x $udev_bin ];then
udev_bin=/lib/udev/udevd
fi
if [ ! -x $udev_bin ];then
systemException \
"Can't find udev daemon" \
"reboot"
fi
$udev_bin --daemon
export UDEVD_PID=$(pidof $udev_bin | tr ' ' ,)
}
#======================================
# udevSystemStop
#--------------------------------------
function udevSystemStop {
# /.../
# stop udev while in pre-init phase.
# ----
local IFS=$IFS_ORIG
local udevadmExec=$(lookup udevadm 2>/dev/null)
local umountProc=0
if [ ! -e "/proc/mounts" ];then
mount -t proc proc /proc
umountProc=1
fi
if [ -x $udevadmExec ];then
# ignore error messages here, because if the process is not
# stopped properly here, it will be killed the hard way a few
# lines down
$udevadmExec control --exit &>/dev/null
fi
if [ -z "$UDEVD_PID" ];then
. /iprocs
fi
local IFS=,
for p in $UDEVD_PID; do
if kill -0 $p &>/dev/null;then
udevPending
kill $p
fi
done
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# udevStart
#--------------------------------------
function udevStart {
# /.../
# start the udev daemon.
# ----
local IFS=$IFS_ORIG
#======================================
# Check time according to build day
#--------------------------------------
if [ -f /build_day ];then
importFile < /build_day
current_day="$(LC_ALL=C date -u '+%Y%m%d')"
if [ "$current_day" -lt "$build_day" ] ; then
LC_ALL=C date -us "$build_day"
sleep 3
export SYSTEM_TIME_INCORRECT=$current_day
fi
fi
#======================================
# Check for modules.order
#--------------------------------------
if ! ls /lib/modules/*/modules.order &>/dev/null;then
# /.../
# without modules.order in place we prevent udev from loading
# the storage modules because it does not make a propper
# choice if there are multiple possible modules available.
# Example:
# udev prefers ata_generic over ata_piix but the hwinfo
# order is ata_piix first which also seems to make more
# sense.
# -----
rm -f /etc/udev/rules.d/*-drivers.rules
rm -f /lib/udev/rules.d/*-drivers.rules
HAVE_MODULES_ORDER=0
fi
#======================================
# Start the daemon
#--------------------------------------
# static nodes
createInitialDevices /dev
# load modules required before udev
moduleLoadBeforeUdev
# start the udev daemon
udevSystemStart
echo UDEVD_PID=$UDEVD_PID >> /iprocs
# trigger events for all devices
udevTrigger
# wait for events to finish
udevPending
# init console
consoleInit
# start plymouth if it exists and enabled
for o in $(cat /proc/cmdline) ; do
case "$o" in
plymouth.enable=0*|rd.plymouth=0*)
enablePlymouth=0
break
;;
esac
done
if [ $enablePlymouth -eq 1 ]; then
startPlymouth
fi
}
#======================================
# moduleLoadBeforeUdev
#--------------------------------------
function moduleLoadBeforeUdev {
# /.../
# load modules which have to be loaded before the
# udev daemon is started in this function
# ----
loadAGPModules
}
#======================================
# loadAGPModules
#--------------------------------------
function loadAGPModules {
local IFS=$IFS_ORIG
local krunning=$(uname -r)
for i in /lib/modules/$krunning/kernel/drivers/char/agp/*; do
test -e $i || continue
modprobe $(echo $i | sed "s#.*\\/\\([^\\/]\\+\\).ko#\\1#")
done
}
#======================================
# udevKill
#--------------------------------------
function udevKill {
local IFS=$IFS_ORIG
udevSystemStop
}
#======================================
# activeConsoles
#--------------------------------------
function activeConsoles {
local IFS=$IFS_ORIG
for i in $(cat /sys/class/tty/console/active 2>/dev/null);do
echo $i
done | wc -l
}
#======================================
# consoleInit
#--------------------------------------
function consoleInit {
local IFS=$IFS_ORIG
local udev_console=/lib/udev/console_init
local systemd_console=/usr/lib/systemd/systemd-vconsole-setup
if [ -x $udev_console ];then
$udev_console /dev/console
elif [ -x $systemd_console ];then
$systemd_console
fi
}
#======================================
# startPlymouth
#--------------------------------------
function startPlymouth {
local IFS=$IFS_ORIG
local consoledev
if lookup plymouthd &>/dev/null;then
# first trigger graphics subsystem
udevadm trigger --action=add --attr-match=class=0x030000 &>/dev/null
# next trigger graphics and tty subsystem
udevadm trigger --action=add --subsystem-match=graphics \
--subsystem-match=drm --subsystem-match=tty &>/dev/null
udevadm settle --timeout=30
mkdir --mode 755 /run/plymouth
consoleInit
plymouth-set-default-theme $kiwi_splash_theme &>/dev/null
plymouthd --attach-to-session --pid-file /run/plymouth/pid &>/dev/null
plymouth show-splash &>/dev/null
# reset tty after plymouth messed with it
consoleInit
fi
}
#======================================
# startDropBear
#--------------------------------------
function startDropBear {
# /.../
# start dropbear ssh server if installed
# ---
local IFS=$IFS_ORIG
local auth_keys="/root/.ssh/authorized_keys"
if [ -z "$kiwidebug" ];then
return
fi
if lookup dropbear &>/dev/null;then
mkdir -p /root/.ssh
fetchFile KIWI/debug_ssh.pub $auth_keys
if [ ! -e $auth_keys ]; then
return
fi
mkdir -p /etc/dropbear
if [ ! -f /etc/dropbear/dropbear_dss_host_key ];then
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
fi
if [ ! -f /etc/dropbear/dropbear_rsa_host_key ];then
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
fi
Echo "Starting dropbear ssh server"
dropbear
export DROPBEAR_PID=$(pidof /usr/sbin/dropbear)
echo DROPBEAR_PID=$DROPBEAR_PID >> /iprocs
fi
}
#======================================
# installBootLoader
#--------------------------------------
function installBootLoader {
# /.../
# generic function to install the boot loader.
# The selection of the bootloader happens according to
# the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
case $arch-$loader in
i*86-grub) installBootLoaderGrub ;;
x86_64-grub) installBootLoaderGrub ;;
i*86-grub2) installBootLoaderGrub2 ;;
s390*-grub2) installBootLoaderGrub2 ;;
x86_64-grub2) installBootLoaderGrub2 ;;
ppc64*-grub2) installBootLoaderGrub2 ;;
ppc*) installBootLoaderYaboot ;;
arm*) installBootLoaderUBoot ;;
i*86-syslinux) installBootLoaderSyslinux ;;
x86_64-syslinux) installBootLoaderSyslinux ;;
i*86-extlinux) installBootLoaderSyslinux ;;
x86_64-extlinux) installBootLoaderSyslinux ;;
s390-zipl) installBootLoaderS390 ;;
s390x-zipl) installBootLoaderS390 ;;
s390x-grub2_s390x_emu) installBootLoaderS390Grub ;;
aarch64-uboot) installBootLoaderUBoot ;;
aarch64-grub2) installBootLoaderGrub2 ;;
*)
systemException \
"*** boot loader install for $arch-$loader not implemented ***" \
"reboot"
esac
#
# Warning message is disabled because sometimes the message
# can't be displayed on the console which leads to a stopped
# system but the user has no clue why
#
#if [ ! $? = 0 ];then
# if lookup dialog &>/dev/null;then
# Dialog \
# --backtitle \"$TEXT_BOOT_SETUP_FAILED\" \
# --msgbox "\"$TEXT_BOOT_SETUP_FAILED_INFO\"" 10 70
# else
# systemException \
# "$TEXT_BOOT_SETUP_FAILED\n\n$TEXT_BOOT_SETUP_FAILED_INFO" \
# "waitkey"
# fi
#fi
case $arch in
i*386|x86_64)
masterBootID=$(printf 0x%04x%04x $RANDOM $RANDOM)
Echo "writing new MBR ID to master boot record: $masterBootID"
echo $masterBootID > /boot/mbrid
masterBootIDHex=$(echo $masterBootID |\
sed 's/^0x\(..\)\(..\)\(..\)\(..\)$/\\x\4\\x\3\\x\2\\x\1/')
echo -e -n $masterBootIDHex | dd of=$imageDiskDevice \
bs=1 count=4 seek=$((0x1b8))
;;
*)
echo "skiped writing MBR ID for $arch"
;;
esac
}
#======================================
# installBootLoaderRecovery
#--------------------------------------
function installBootLoaderRecovery {
# /.../
# generic function to install the boot loader into
# the recovery partition. The selection of the bootloader
# happens according to the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
case $arch-$loader in
i*86-grub) installBootLoaderGrubRecovery ;;
x86_64-grub) installBootLoaderGrubRecovery ;;
i*86-grub2) installBootLoaderGrub2Recovery ;;
x86_64-grub2) installBootLoaderGrub2Recovery ;;
s390*-grub2) installBootLoaderGrub2Recovery ;;
i*86-syslinux) installBootLoaderSyslinuxRecovery ;;
x86_64-syslinux) installBootLoaderSyslinuxRecovery ;;
i*86-extlinux) installBootLoaderSyslinuxRecovery ;;
x86_64-extlinux) installBootLoaderSyslinuxRecovery ;;
s390-zipl) installBootLoaderS390Recovery ;;
s390x-zipl) installBootLoaderS390Recovery ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
}
#======================================
# installBootLoaderUBoot
#--------------------------------------
function installBootLoaderUBoot {
# /.../
# installation of uboot can't be done in a generic
# way because each arm board behaves differently.
# Thus we are only calling a hook script here
# ----
local IFS=$IFS_ORIG
if [ "$kiwi_bootloader" = "berryboot" ];then
runHook installBerryBoot "$@"
else
runHook installUBoot "$@"
fi
}
#======================================
# installBootLoaderS390Grub
#--------------------------------------
function installBootLoaderS390Grub {
# /.../
# Create/Delete
# - create active_devices.txt
# - delete kiwi initrd/kernel .vmx files
# Run grub2-mkconfig
# - create new boot/grub2/grub.cfg
# Run grub2-install
# - creates a new boot/zipl/config
# - creates zipl initrd which loads grub2/kexec
# - install zipl
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local instTool=grub2-install
local confFile_grub=/boot/grub2/grub.cfg
local active_devs=/boot/zipl/active_devices.txt
local deviceID=$(cat /sys/firmware/ipl/device)
#======================================
# mount zipl jump partition
#--------------------------------------
if [ ! -z "$kiwi_JumpPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_JumpPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "ZIPL" ];then
mkdir -p /boot/zipl
if ! mount $jdev /boot/zipl;then
Echo "Failed to mount zipl boot partition"
return 1
fi
fi
fi
#======================================
# Create active devices information
#--------------------------------------
echo $deviceID > $active_devs
#======================================
# create grub2 configuration
#--------------------------------------
if ! lookup $confTool &>/dev/null;then
Echo "System image doesn't provide $confTool"
Echo "Can't create bootloader configuration"
return 1
fi
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create grub2 boot configuration"
return 1
fi
#======================================
# Run grub2-install
#--------------------------------------
if ! lookup $instTool &>/dev/null;then
Echo "System image doesn't provide $instTool"
Echo "Can't install bootloader"
return 1
fi
if ! $instTool;then
Echo "Failed to install bootloader"
return 1
fi
#======================================
# Delete kiwi initrd files
#--------------------------------------
rm -f /boot/zipl/*.vmx
#======================================
# umount zipl boot partition
#--------------------------------------
mountpoint -q /boot/zipl && umount /boot/zipl
return 0
}
#======================================
# installBootLoaderS390
#--------------------------------------
function installBootLoaderS390 {
local IFS=$IFS_ORIG
if [ -x /sbin/zipl ];then
Echo "Installing boot loader..."
zipl -c /etc/zipl.conf 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
else
Echo "Image doesn't have zipl installed"
Echo "Can't install boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderSyslinux
#--------------------------------------
function installBootLoaderSyslinux {
local IFS=$IFS_ORIG
local syslmbr=/usr/share/syslinux/mbr.bin
if [ -e $syslmbr ];then
Echo "Installing boot loader..."
if [ $loader = "syslinux" ];then
if ! syslinux $imageBootDevice;then
Echo "Failed to install boot loader"
return 1
fi
else
if ! extlinux --install /boot/syslinux;then
Echo "Failed to install boot loader"
return 1
fi
fi
dd if=$syslmbr of=$imageDiskDevice bs=512 count=1 conv=notrunc
else
Echo "Image doesn't have syslinux (mbr.bin) installed"
Echo "Can't install boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderGrub
#--------------------------------------
function installBootLoaderGrub {
# /.../
# install the grub according to the contents of
# /etc/grub.conf and /boot/grub/menu.lst
# ----
local IFS=$IFS_ORIG
if lookup grub &>/dev/null;then
Echo "Installing boot loader..."
grub --batch --no-floppy < /etc/grub.conf 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
if [[ $kiwi_iname =~ boot-rhel ]];then
# on rhel systems grub.conf is a link to menu.lst.
rm -f /etc/grub.conf
ln -s /boot/grub/menu.lst /etc/grub.conf
fi
else
Echo "Image doesn't have grub installed"
Echo "Can't install boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderGrub2
#--------------------------------------
function installBootLoaderGrub2 {
# /.../
# configure and install grub2 according to the
# contents of /boot/grub2/grub.cfg
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local instTool=grub2-install
local confFile_grub_bios=/boot/grub2/grub.cfg
local confFile_uefi=/boot/efi/EFI/BOOT/grub.cfg
local confFile_grub=$confFile_grub_bios
local bios_grub=/boot/grub2/i386-pc
local product=/etc/products.d/baseproduct
local elilo_efi=/usr/lib64/efi/elilo.efi
local grub_efi=/boot/efi/EFI/BOOT/grub.efi
local isEFI=0
#======================================
# check for EFI and mount EFI partition
#--------------------------------------
if [ ! -z "$kiwi_JumpPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_JumpPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "EFI" ];then
mkdir -p /boot/efi
if ! mount $jdev /boot/efi;then
Echo "Failed to mount EFI boot partition"
return 1
fi
isEFI=1
fi
fi
#======================================
# check for elilo compat mode
#--------------------------------------
export elilo_compat=0
if [ $isEFI -eq 1 ] && [ -e $product ] && [ -e $elilo_efi ];then
local product=$(readlink $product)
local vendor=SuSE
local efipath=/boot/efi/EFI
if [[ "$product" =~ "SUSE_SLE" ]];then
#======================================
# check for recovery uuid
#--------------------------------------
if [ -z "$reco_uuid" ]; then
reco_uuid=$(blkid -o value -s UUID -t LABEL=recovery)
fi
#======================================
# check for bootloader displayname
#--------------------------------------
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
#======================================
# write elilo.conf
#--------------------------------------
. /etc/default/grub
local timeout=10
if [ ! -z "$kiwi_boot_timeout" ];then
timeout=$kiwi_boot_timeout
fi
cat > /etc/elilo.conf << EOF
# Modified by YaST2.
timeout = $timeout
##YaST - boot_efilabel = "$kiwi_oemtitle"
vendor-directory = $vendor
secure-boot = on
prompt
image = /boot/vmlinuz
###Don't change this comment - YaST2 identifier: Original name: linux###
initrd = /boot/initrd
label = linux
append = "$GRUB_CMDLINE_LINUX_DEFAULT"
description = "$kiwi_oemtitle"
root = $(getDiskID $imageRootDevice)
EOF
#====================================================
# setup kernel symlinks
#----------------------------------------------------
local kversion=$(uname -r)
ln -sf /boot/vmlinuz-$kversion /boot/vmlinuz
ln -sf /boot/initrd-$kversion /boot/initrd
#====================================================
# create vendor directory
#----------------------------------------------------
mkdir -p $efipath/$vendor
#======================================
# update sysconfig/bootloader
#--------------------------------------
sed -i -e s'@LOADER_TYPE.*@LOADER_TYPE="elilo"@' \
/etc/sysconfig/bootloader
#======================================
# set up boot files and configurations
#--------------------------------------
# create elilo.conf and grub.cfg and
# copy boot files to /boot/efi
# ----
elilo -vv
#====================================================
# Append recovery entry to elilo written grub.cfg
#----------------------------------------------------
if [ "$kiwi_oemrecovery" = "true" ];then
cat >> $efipath/$vendor/grub.cfg << EOF
menuentry 'Recovery' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
configfile /boot/grub2/grub.cfg
}
EOF
fi
#======================================
# write efi variable to NvRam
#--------------------------------------
# this is for the efi boot manager to show a better
# title for this system
# ----
elilo --refresh-EBM -vv
#====================================================
# create versionized kernel/initrd
#----------------------------------------------------
cp -a $efipath/$vendor/vmlinuz $efipath/$vendor/vmlinuz-$kversion
cp -a $efipath/$vendor/initrd $efipath/$vendor/initrd-$kversion
#====================================================
# sync vendor directory with standard boot path
#----------------------------------------------------
cp -a $efipath/$vendor/* $efipath/BOOT
#======================================
# set flag to indicate elilo is used
#--------------------------------------
elilo_compat=1
#======================================
# return early for elilo case
#--------------------------------------
mountpoint -q /boot/efi && umount /boot/efi
return 0
fi
fi
if ! lookup $confTool &>/dev/null;then
Echo "Image doesn't have grub2 installed"
Echo "Can't install boot loader"
return 1
fi
#======================================
# create grub2 configuration
#--------------------------------------
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create grub2 boot configuration"
return 1
fi
if [ -e $confFile_grub_bios ];then
cp $confFile_grub $confFile_grub_bios
fi
if [ $isEFI -eq 1 ] && [ -e $confFile_uefi ];then
cp $confFile_grub $confFile_uefi
umount /boot/efi
fi
#======================================
# install grub2 in BIOS mode
#--------------------------------------
if [ ! -z "$kiwi_OfwGrub" ];then
# install powerpc grub2
$instTool $imagePrepDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
elif [ $isEFI -eq 0 ];then
# use plain grub2-install in standard bios mode
$instTool $imageDiskDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
elif [ ! -z "$kiwi_BiosGrub" ] && [ -d $bios_grub ];then
# force install of bios grub2 in efi legacy mode
$instTool --force --target i386-pc $imageDiskDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install legacy boot loader"
return 1
fi
else
Echo "No bootloader installaton required"
fi
return 0
}
#======================================
# installBootLoaderYaboot
#--------------------------------------
function installBootLoaderYaboot {
# /.../
# install the lilo/yaboot bootloader
# ----
local IFS=$IFS_ORIG
if [ -x /sbin/lilo ];then
Echo "Installing boot loader..."
/sbin/lilo 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install boot loader"
return 1
fi
else
Echo "Image doesn't have lilo installed"
Echo "Can't install boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderS390Recovery
#--------------------------------------
function installBootLoaderS390Recovery {
local IFS=$IFS_ORIG
Echo "*** zipl: recovery boot not implemented ***"
return 1
}
#======================================
# installBootLoaderSyslinuxRecovery
#--------------------------------------
function installBootLoaderSyslinuxRecovery {
local IFS=$IFS_ORIG
local syslmbr=/usr/share/syslinux/mbr.bin
if [ -e $syslmbr ];then
if [ $loader = "syslinux" ];then
if ! syslinux $imageRecoveryDevice;then
Echo "Failed to install recovery boot loader"
return 1
fi
else
if ! extlinux --install /reco-save/boot/syslinux;then
Echo "Failed to install recovery boot loader"
return 1
fi
fi
else
Echo "Image doesn't have syslinux (mbr.bin) installed"
Echo "Can't install recovery boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderGrubRecovery
#--------------------------------------
function installBootLoaderGrubRecovery {
# /.../
# install the grub into the recovery partition.
# By design the recovery partition is always the
# last primary partition of the disk
# ----
local IFS=$IFS_ORIG
local input=/grub.input
local gdevreco=$((recoid - 1))
if [ ! -e /etc/redhat-release ];then
echo "device (hd0) $imageDiskDevice" > $input
fi
echo "root (hd0,$gdevreco)" >> $input
echo "setup (hd0,$gdevreco)" >> $input
echo "quit" >> $input
if lookup grub &>/dev/null;then
if [ -e /etc/redhat-release ];then
mount -L recovery /mnt
(cd /mnt/boot/grub && ln -s menu.lst grub.conf)
umount /mnt
fi
if ! grub --batch < $input 1>&2;then
Echo "Failed to install recovery boot loader"
return 1
fi
rm -f $input
else
Echo "Image doesn't have grub installed"
Echo "Can't install recovery boot loader"
return 1
fi
return 0
}
#======================================
# installBootLoaderGrub2Recovery
#--------------------------------------
function installBootLoaderGrub2Recovery {
# /.../
# install grub2 into the recovery partition
# By design the recovery partition is always the
# last primary partition of the disk
# ----
local IFS=$IFS_ORIG
local confTool=grub2-mkconfig
local confFile_grub_bios=/boot/grub2/grub.cfg
local confFile_uefi=/boot/efi/EFI/BOOT/grub.cfg
local confFile_grub=$confFile_grub_bios
local bios_grub=/reco-save/boot/grub2/i386-pc
local isEFI=0
#======================================
# check for EFI and mount EFI partition
#--------------------------------------
if [ ! -z "$kiwi_JumpPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_JumpPart)
local label=$(blkid $jdev -s LABEL -o value)
if [ "$label" = "EFI" ];then
mkdir -p /boot/efi
if ! mount $jdev /boot/efi;then
Echo "Failed to mount EFI boot partition"
return 1
fi
isEFI=1
fi
fi
#======================================
# check for elilo compat mode
#--------------------------------------
if [ "$elilo_compat" -eq 1 ];then
# the recovery menu entry has been appended already
# as part of the regular installBootLoaderGrub2. This is
# done to ensure the entry is recreated after a recovery
# run because elilo doesn't support that
return 0
fi
#======================================
# check tool status
#--------------------------------------
if ! lookup $confTool &>/dev/null;then
Echo "Image doesn't have grub2 installed"
Echo "Can't install recovery boot loader"
mountpoint -q /boot/efi && umount /boot/efi
return 1
fi
#======================================
# install grub2 into partition
#--------------------------------------
# this allows a bios to directly jump there, e.g with a function key
grub2-bios-setup -f -d $bios_grub $imageRecoveryDevice 1>&2
if [ ! $? = 0 ];then
Echo "Failed to install recovery boot loader"
fi
#======================================
# create custom recovery entry
#--------------------------------------
cat > /etc/grub.d/40_custom << DONE
#!/bin/bash
cat << EOF
menuentry 'Recovery' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
configfile /boot/grub2/grub.cfg
}
EOF
DONE
#======================================
# create grub2 config file
#--------------------------------------
$confTool > $confFile_grub
if [ ! $? = 0 ];then
Echo "Failed to create recovery grub2 boot configuration"
mountpoint -q /boot/efi && umount /boot/efi
return 1
fi
if [ $isEFI -eq 1 ] && [ -e $confFile_uefi ];then
cp $confFile_grub $confFile_uefi
fi
mountpoint -q /boot/efi && umount /boot/efi
return 0
}
#======================================
# updateModuleDependencies
#--------------------------------------
function updateModuleDependencies {
# /.../
# update the kernel module dependencies list
# ---
local IFS=$IFS_ORIG
local depmodExec=$(lookup depmod 2>/dev/null)
if [ ! -x "$depmodExec" ];then
Echo "Could not find depmod executable"
Echo "Skipping module dependency update"
systemIntegrity=unknown
return
fi
if ! $depmodExec -a;then
Echo "Module dependency update failed."
systemIntegrity=unknown
fi
}
#======================================
# setupInitrd
#--------------------------------------
function setupInitrd {
# /.../
# call mkinitrd to create the distro initrd
# ----
local IFS=$IFS_ORIG
bootLoaderOK=1
local umountProc=0
local umountSys=0
local systemMap=0
local dracutExec=$(lookup dracut 2>/dev/null)
local mkinitrdExec=$(lookup mkinitrd 2>/dev/null)
local params
local running
local rlinux
local rinitrd
local kernel_version=$(uname -r)
for i in $(find /boot/ -name "System.map*");do
systemMap=1
done
setupDefaultTheme
if [ $systemMap -eq 1 ];then
#======================================
# Cleanup
#--------------------------------------
rm -f /boot/initrd-*.img
#======================================
# Prepare for tool call
#--------------------------------------
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umountProc=1
fi
if [ ! -e /sys/block ];then
mount -t sysfs sysfs /sys
umountSys=1
fi
modprobe dm-mod &>/dev/null
updateModuleDependencies
#======================================
# Call initrd creation tool
#--------------------------------------
if [ -x "$dracutExec" ]; then
# 1. dracut
Echo "Creating dracut based initrd"
params=" -f /boot/initrd-$kernel_version $kernel_version"
if ! $dracutExec -H $params;then
Echo "Can't create initrd with dracut"
systemIntegrity=unknown
bootLoaderOK=0
fi
elif [ -x "$mkinitrdExec" ]; then
# 2. mkinitrd
Echo "Creating mkinitrd based initrd"
if grep -qi param_B $mkinitrdExec;then
params="-B"
fi
if ! $mkinitrdExec $params;then
Echo "Can't create initrd with mkinitrd"
systemIntegrity=unknown
bootLoaderOK=0
fi
else
# no tool found
Echo "Coudn't find a tool to create initrd image"
systemIntegrity=unknown
bootLoaderOK=0
fi
#======================================
# Cleanup kiwi firstboot initrd
#--------------------------------------
if [ $bootLoaderOK = "1" ];then
if [ -f /boot/initrd.vmx ];then
rm -f /boot/initrd.vmx
fi
if [ -f /boot/linux.vmx ];then
rm -f /boot/linux.vmx
fi
if [ -f /boot/initrd.uboot ];then
rm -f /boot/initrd.uboot
fi
fi
#======================================
# Loader exceptions
#--------------------------------------
if [ "$loader" = "syslinux" ];then
# /.../
# if syslinux is used we need to make sure to copy
# the kernel and initrd to /boot on the boot partition.
# This is normally done by the boot -> . link but we
# can't create links on fat
# ----
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:`
break
done
IFS=$IFS_ORIG
mkdir -p /boot/boot
cp /boot/$kernel /boot/boot/
cp /boot/$initrd /boot/boot/
fi
#======================================
# Cleanup mounts
#--------------------------------------
rmmod dm-mod &>/dev/null
if [ $umountSys -eq 1 ];then
umount /sys
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
else
Echo "Image doesn't include kernel system map"
Echo "Can't create initrd"
systemIntegrity=unknown
bootLoaderOK=0
fi
#======================================
# Display a warning on failure
#--------------------------------------
# Warning message is disabled because sometimes the message
# can't be displayed on the console which leads to a stopped
# system but the user has no clue why
#
#if [ $bootLoaderOK = 0 ];then
# if lookup dialog &>/dev/null;then
# Dialog \
# --backtitle \"$TEXT_BOOT_SETUP_FAILED\" \
# --msgbox "\"$TEXT_BOOT_SETUP_FAILED_INFO\"" 10 70
# else
# systemException \
# "$TEXT_BOOT_SETUP_FAILED\n\n$TEXT_BOOT_SETUP_FAILED_INFO" \
# "waitkey"
# fi
#fi
}
#======================================
# setupDefaultTheme
#--------------------------------------
function setupDefaultTheme {
local IFS=$IFS_ORIG
if lookup plymouthd &>/dev/null;then
plymouth-set-default-theme $kiwi_splash_theme &>/dev/null
fi
}
#======================================
# setupBootLoader
#--------------------------------------
function setupBootLoader {
# /.../
# generic function to setup the boot loader configuration.
# The selection of the bootloader happens according to
# the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=`uname -m`
local para=""
while [ $# -gt 0 ];do
# quote simple quotation marks
arg=$(echo $1 | sed -e s"#'#'\\\\''#g")
para="$para '$arg'"
shift
done
case $arch-$loader in
i*86-grub) eval setupBootLoaderGrub $para ;;
x86_64-grub) eval setupBootLoaderGrub $para ;;
i*86-grub2) eval setupBootLoaderGrub2 $para ;;
x86_64-grub2) eval setupBootLoaderGrub2 $para ;;
ppc64*-grub2) eval setupBootLoaderGrub2 $para ;;
s390*-grub2) eval setupBootLoaderGrub2 $para ;;
i*86-syslinux) eval setupBootLoaderSyslinux $para ;;
x86_64-syslinux) eval setupBootLoaderSyslinux $para ;;
i*86-extlinux) eval setupBootLoaderSyslinux $para ;;
x86_64-extlinux) eval setupBootLoaderSyslinux $para ;;
s390-zipl) eval setupBootLoaderS390 $para ;;
s390x-zipl) eval setupBootLoaderS390 $para ;;
s390x-grub2_s390x_emu) eval setupBootLoaderS390Grub $para ;;
ppc*) eval setupBootLoaderYaboot $para ;;
aarch64-uboot) eval setupBootLoaderUBoot $para ;;
aarch64-grub2) eval setupBootLoaderGrub2 $para ;;
arm*-grub2) eval setupBootLoaderGrub2 $para ;;
arm*) eval setupBootLoaderUBoot $para ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
setupBootThemes "/config"
}
#======================================
# setupBootThemes
#--------------------------------------
function setupBootThemes {
local IFS=$IFS_ORIG
local destprefix=$1
local prefix=$2
if [ -z "$prefix" ];then
prefix=/mnt
fi
#======================================
# Splash theme setup
#--------------------------------------
if [ ! -z "$kiwi_splash_theme" ];then
local theme=$kiwi_splash_theme
#======================================
# gfxboot default setup
#--------------------------------------
local orig_bootsplash=$prefix/etc/sysconfig/bootsplash
local inst_bootsplash=$destprefix/etc/sysconfig/bootsplash
mkdir -p $destprefix/etc/sysconfig
touch $inst_bootsplash
#======================================
# check for bootsplash config in sysimg
#--------------------------------------
if [ -f $orig_bootsplash ];then
cp $orig_bootsplash $inst_bootsplash
fi
#======================================
# change/create bootsplash config
#--------------------------------------
if cat $inst_bootsplash | grep -q -E "^THEME"; then
sed -i "s/^THEME=.*/THEME=\"$theme\"/" $inst_bootsplash
else
echo "THEME=\"$theme\"" >> $inst_bootsplash
fi
#======================================
# plymouth splash
#--------------------------------------
if lookup plymouthd &>/dev/null;then
local orig_plymouthconf=$prefix/etc/plymouth/plymouth.conf
local inst_plymouthconf=$destprefix/etc/plymouth/plymouth.conf
mkdir -p $destprefix/etc/plymouth
touch $inst_plymouthconf
#======================================
# check for plymouth config in sysimg
#--------------------------------------
if [ -f $orig_plymouthconf ];then
cp $orig_plymouthconf $inst_plymouthconf
fi
#======================================
# change/create plymouth config
#--------------------------------------
if cat $inst_plymouthconf | grep -q -E "^Theme"; then
sed -i "s/^Theme=.*/Theme=\"$theme\"/" $inst_plymouthconf
else
echo "[Daemon]" > $inst_plymouthconf
echo "Theme=\"$theme\"" >> $inst_plymouthconf
fi
fi
fi
}
#======================================
# setupBootLoaderRecovery
#--------------------------------------
function setupBootLoaderRecovery {
# /.../
# generic function to setup the boot loader configuration
# for the recovery partition. The selection of the bootloader
# happens according to the architecture of the system
# ----
local IFS=$IFS_ORIG
local arch=$(uname -m)
local para=""
while [ $# -gt 0 ];do
# quote simple quotation marks
arg=$(echo $1 | sed -e s"#'#'\\\\''#g")
para="$para '$arg'"
shift
done
case $arch-$loader in
i*86-grub) eval setupBootLoaderGrubRecovery $para ;;
x86_64-grub) eval setupBootLoaderGrubRecovery $para ;;
i*86-grub2) eval setupBootLoaderGrub2Recovery $para ;;
x86_64-grub2) eval setupBootLoaderGrub2Recovery $para ;;
s390*-grub2) eval setupBootLoaderGrub2Recovery $para ;;
i*86-syslinux) eval setupBootLoaderSyslinuxRecovery $para ;;
x86_64-syslinux) eval setupBootLoaderSyslinuxRecovery $para ;;
i*86-extlinux) eval setupBootLoaderSyslinuxRecovery $para ;;
x86_64-extlinux) eval setupBootLoaderSyslinuxRecovery $para ;;
s390-zipl) eval setupBootLoaderS390Recovery $para ;;
s390x-zipl) eval setupBootLoaderS390Recovery $para ;;
s390x-grub2_s390x_emu) eval setupBootLoaderS390Recovery $para ;;
*)
systemException \
"*** boot loader setup for $arch-$loader not implemented ***" \
"reboot"
esac
}
#======================================
# setupBootLoaderS390Recovery
#--------------------------------------
function setupBootLoaderS390Recovery {
local IFS=$IFS_ORIG
systemException \
"*** zipl: recovery boot not implemented ***" \
"reboot"
}
#======================================
# setupBootLoaderSyslinuxRecovery
#--------------------------------------
function setupBootLoaderSyslinuxRecovery {
# /.../
# create syslinux configuration for the recovery boot system
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # boot partition ID
local rdev=$4 # root partition
local gfix=$5 # syslinux title postfix
local swap=$6 # optional swap partition
local conf=$destsPrefix/boot/syslinux/syslinux.cfg
local kernel=""
local initrd=""
local fbmode=$vga
if [ -z "$fbmode" ];then
fbmode=$DEFAULT_VGA
fi
rdev_recovery=$imageRootDevice
diskByID=$(getDiskID $rdev_recovery)
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# import syslinux into recovery
#--------------------------------------
cp -a $mountPrefix/boot/syslinux $destsPrefix/boot
#======================================
# setup config file name
#--------------------------------------
if [ $loader = "extlinux" ];then
conf=$destsPrefix/boot/syslinux/extlinux.conf
fi
#======================================
# create syslinux.cfg file
#--------------------------------------
echo "implicit 1" > $conf
echo "prompt 1" >> $conf
echo "TIMEOUT $kiwi_boot_timeout" >> $conf
echo "display isolinux.msg" >> $conf
if [ -f "$mountPrefix/boot/syslinux/bootlogo" ];then
if \
[ -f "$mountPrefix/boot/syslinux/gfxboot.com" ] || \
[ -f "$mountPrefix/boot/syslinux/gfxboot.c32" ]
then
echo "ui gfxboot bootlogo isolinux.msg" >> $conf
else
echo "gfxboot bootlogo" >> $conf
fi
fi
kernel=linux.vmx # this is a copy of the kiwi linux.vmx file
initrd=initrd.vmx # this is a copy of the kiwi initrd.vmx file
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
#======================================
# Reboot
#--------------------------------------
title=$(makeLabel "Cancel/Reboot")
echo "DEFAULT $title" >> $conf
echo "label $title" >> $conf
echo " localboot 0x80" >> $conf
#======================================
# Recovery
#--------------------------------------
title=$(makeLabel "Recover/Repair System")
echo "label $title" >> $conf
if xenServer $kernel $mountPrefix;then
systemException \
"*** $loader: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "kernel /boot/$kernel" >> $conf
echo -n "append initrd=/boot/$initrd" >> $conf
echo -n " root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " vga=$fbmode" >> $conf
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo " KIWI_RECOVERY=$recoid" >> $conf
echo " showopts" >> $conf
fi
#======================================
# Restore
#--------------------------------------
title=$(makeLabel "Restore Factory System")
echo "label $title" >> $conf
if xenServer $kernel $mountPrefix;then
systemException \
"*** $loader: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "kernel /boot/$kernel" >> $conf
echo -n "append initrd=/boot/$initrd" >> $conf
echo -n " root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " vga=$fbmode" >> $conf
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo " KIWI_RECOVERY=$recoid RESTORE=1" >> $conf
echo " showopts" >> $conf
fi
fi
}
#======================================
# setupBootLoaderGrubRecovery
#--------------------------------------
function setupBootLoaderGrubRecovery {
# /.../
# create menu.lst file for the recovery boot system
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gfix=$3 # grub title
local menu=$destsPrefix/boot/grub/menu.lst
local kernel=""
local initrd=""
local fbmode=$vga
local gdevreco=$((recoid - 1))
if [ -z "$fbmode" ];then
fbmode=$DEFAULT_VGA
fi
gdev_recovery="(hd0,$gdevreco)"
rdev_recovery=$imageRootDevice
diskByID=$(getDiskID $rdev_recovery)
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# import grub stages into recovery
#--------------------------------------
mkdir -p $destsPrefix/boot/grub
cp $mountPrefix/boot/grub/stage1 $destsPrefix/boot/grub
cp $mountPrefix/boot/grub/stage2 $destsPrefix/boot/grub
#======================================
# create recovery menu.lst
#--------------------------------------
echo "timeout 30" > $menu
echo "gfxmenu $gdev_recovery/boot/message" >> $menu
kernel=vmlinuz # this is a copy of the kiwi linux.vmx file
initrd=initrd # this is a copy of the kiwi initrd.vmx file
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
#======================================
# Make the cancel option default
#--------------------------------------
echo "default 0" >> $menu
#======================================
# Reboot
#--------------------------------------
title=$(makeLabel "Cancel/Reboot")
echo "title $title" >> $menu
echo " reboot" >> $menu
#======================================
# Recovery
#--------------------------------------
title=$(makeLabel "Recover/Repair System")
echo "title $title" >> $menu
if xenServer $kernel $mountPrefix;then
echo " root $gdev_recovery" >> $menu
echo " kernel /boot/xen.gz" >> $menu
echo -n " module /boot/$kernel" >> $menu
echo -n " root=$diskByID $console" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " KIWI_RECOVERY=$recoid" >> $menu
echo " showopts" >> $menu
echo " module /boot/$initrd" >> $menu
else
echo -n " kernel $gdev_recovery/boot/$kernel" >> $menu
echo -n " root=$diskByID $console" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " KIWI_RECOVERY=$recoid" >> $menu
echo " showopts" >> $menu
echo " initrd $gdev_recovery/boot/$initrd" >> $menu
fi
#======================================
# Restore
#--------------------------------------
title=$(makeLabel "Restore Factory System")
echo "title $title" >> $menu
if xenServer $kernel $mountPrefix;then
echo " root $gdev_recovery" >> $menu
echo " kernel /boot/xen.gz" >> $menu
echo -n " module /boot/$kernel" >> $menu
echo -n " root=$diskByID $console" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " KIWI_RECOVERY=$recoid" >> $menu
echo " showopts" >> $menu
echo " module /boot/$initrd" >> $menu
else
echo -n " kernel $gdev_recovery/boot/$kernel" >> $menu
echo -n " root=$diskByID $console" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " KIWI_RECOVERY=$recoid RESTORE=1" >> $menu
echo " showopts" >> $menu
echo " initrd $gdev_recovery/boot/$initrd" >> $menu
fi
fi
}
#======================================
# setupBootLoaderGrub2Recovery
#--------------------------------------
function setupBootLoaderGrub2Recovery {
# /.../
# create grub.cfg file for the recovery boot system
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gfix=$3 # grub title
local kernel=vmlinuz # this is a copy of the kiwi linux.vmx file
local initrd=initrd # this is a copy of the kiwi initrd.vmx file
local conf=$destsPrefix/boot/grub2/grub.cfg
local theme=$RECOVERY_THEME
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $imageRootDevice)
local diskByID=$(getDiskID $imageDiskDevice)
if [ "$FSTYPE" = "zfs" ];then
rootByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# operate only in recovery mode
#--------------------------------------
if [ -z "$kiwi_oemrecovery" ];then
return
fi
#======================================
# import grub2 modules into recovery
#--------------------------------------
mkdir -p $destsPrefix/boot
cp -a $mountPrefix/boot/grub2 $destsPrefix/boot/
rm -f $destsPrefix/boot/grub2/grub.cfg
rm -f $destsPrefix/boot/grub2/bootpart.cfg
#======================================
# check for kernel options
#--------------------------------------
local cmdline="KIWI_RECOVERY=$recoid"
if [ ! -z "$KIWI_KERNEL_OPTIONS" ];then
cmdline="$cmdline $KIWI_KERNEL_OPTIONS"
fi
if [ ! -z "$KIWI_INITRD_PARAMS" ];then
cmdline="$cmdline $KIWI_INITRD_PARAMS";
fi
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ -e /dev/xvc0 ];then
cmdline="$cmdline console=xvc console=tty"
elif [ -e /dev/hvc0 ];then
cmdline="$cmdline console=hvc console=tty"
fi
#======================================
# create recovery grub.cfg
#--------------------------------------
cat > $conf << EOF
insmod ext2
insmod gettext
insmod part_msdos
insmod chain
insmod png
insmod vbe
insmod vga
insmod gzio
set default=0
search --no-floppy --fs-uuid --set=root $reco_uuid
set font=/boot/unicode.pf2
if loadfont \$font ;then
set gfxmode=auto
insmod gfxterm
insmod gfxmenu
terminal_input gfxterm
if terminal_output gfxterm; then true; else
terminal gfxterm
fi
fi
if loadfont /boot/grub2/themes/$theme/ascii.pf2;then
loadfont /boot/grub2/themes/$theme/DejaVuSans-Bold14.pf2
loadfont /boot/grub2/themes/$theme/DejaVuSans10.pf2
loadfont /boot/grub2/themes/$theme/DejaVuSans12.pf2
loadfont /boot/grub2/themes/$theme/ascii.pf2
set theme=/boot/grub2/themes/$theme/theme.txt
set bgimg=/boot/grub2/themes/$theme/background.png
background_image -m stretch \$bgimg
fi
if [ \$grub_platform = "efi" ]; then
set linux=linuxefi
set initrd=initrdefi
else
set linux=linux
set initrd=initrd
fi
set timeout=30
EOF
if xenServer $kernel $mountPrefix;then
cat >> $conf << EOF
menuentry 'Recover/Repair System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading Xen...
multiboot /boot/xen.gz dummy
echo Loading $kernel...
set gfxpayload=keep
module /boot/$kernel dummy $cmdline $kiwi_cmdline showopts
echo Loading $initrd...
module /boot/$initrd dummy
}
menuentry 'Restore Factory System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading Xen...
multiboot /boot/xen.gz dummy
echo Loading $kernel...
set gfxpayload=keep
module /boot/$kernel dummy $cmdline $kiwi_cmdline RESTORE=1 showopts
echo Loading $initrd...
module /boot/$initrd dummy
}
EOF
else
cat >> $conf << EOF
menuentry 'Recover/Repair System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading $kernel...
set gfxpayload=keep
\$linux /boot/$kernel $cmdline $kiwi_cmdline showopts
echo Loading $initrd...
\$initrd /boot/$initrd
}
menuentry 'Restore Factory System' --class os {
search --no-floppy --fs-uuid --set=root $reco_uuid
echo Loading $kernel...
set gfxpayload=keep
\$linux /boot/$kernel $cmdline $kiwi_cmdline RESTORE=1 showopts
echo Loading $initrd...
\$initrd /boot/$initrd
}
EOF
fi
}
#======================================
# setupBootLoaderUBoot
#--------------------------------------
function setupBootLoaderUBoot {
# /.../
# The setup of the uboot boot.script can't be done
# in a generic way because each arm board behaves
# differently. Thus we are only calling a hook
# script here
# ----
local IFS=$IFS_ORIG
if [ "$kiwi_bootloader" = "berryboot" ];then
runHook setupBerryBoot "$@"
else
runHook setupUBoot "$@"
fi
}
#======================================
# setupBootLoaderS390Grub
#--------------------------------------
function setupBootLoaderS390Grub {
# /.../
# create grub2 configuration for s390
# ----
local IFS=$IFS_ORIG
#======================================
# function paramters
#--------------------------------------
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # grub boot partition ID
local rdev=$4 # grub root partition
local gfix=$5 # grub title postfix
local swap=$6 # optional swap partition
#======================================
# local variables
#--------------------------------------
local kname=$(uname -r)
local loader_type=grub2
local timeout=10
local title
local cmdline
local vesa
#======================================
# setup path names
#--------------------------------------
local orig_sysimg_profile=$mountPrefix/image/.profile
local inst_default_grub=$destsPrefix/etc/default/grub
local inst_default_grubdev=$destsPrefix/etc/default/grub_installdevice
local inst_default_grubmap=$destsPrefix/boot/grub2/device.map
local inst_sysb=$destsPrefix/etc/sysconfig/bootloader
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
local diskByID=$(getDiskID $imageDiskDevice)
if [ "$FSTYPE" = "zfs" ];then
rootByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $orig_sysimg_profile ];then
importFile < $orig_sysimg_profile
fi
#======================================
# setup title name
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
title=$(makeLabel "$gfix")
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ ! -z "$swapByID" ];then
cmdline="$cmdline resume=$swapByID"
fi
if [ ! -z "$kiwi_cmdline" ];then
cmdline="$cmdline $kiwi_cmdline"
fi
if [[ ! $cmdline =~ quiet ]];then
cmdline="$cmdline quiet"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ ! -z "$kiwi_boot_timeout" ];then
timeout=$kiwi_boot_timeout
fi
#======================================
# write etc/default/grub
#--------------------------------------
mkdir -p $destsPrefix/etc/default
cat > $inst_default_grub << EOF
GRUB_DISTRIBUTOR=$(printf %q "$title")
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=$timeout
GRUB_CMDLINE_LINUX_DEFAULT="$cmdline"
GRUB_TERMINAL=console
EOF
#======================================
# enable rollback capability
#--------------------------------------
if [ "$FSTYPE" = "btrfs" ];then
echo "SUSE_BTRFS_SNAPSHOT_BOOTING=true" >> $inst_default_grub
fi
#======================================
# write etc/default/grub_installdevice
#--------------------------------------
cat > $inst_default_grubdev << EOF
$diskByID
EOF
#======================================
# write boot/grub2/device.map
#--------------------------------------
mkdir -p $destsPrefix/boot/grub2
cat > $inst_default_grubmap << EOF
(hd0) $diskByID
EOF
#======================================
# write sysconfig/bootloader
#--------------------------------------
mkdir -p $destsPrefix/etc/sysconfig
cat > $inst_sysb << EOF
LOADER_TYPE=$loader_type
DEFAULT_APPEND="$cmdline"
FAILSAFE_APPEND="$failsafe $cmdline"
EOF
}
#======================================
# setupBootLoaderS390
#--------------------------------------
function setupBootLoaderS390 {
# /.../
# create /etc/zipl.conf used for the
# zipl bootloader
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local znum=$3 # boot partition ID
local rdev=$4 # root partition
local zfix=$5 # zipl title postfix
local swap=$6 # optional swap partition
local conf=$destsPrefix/etc/zipl.conf
local sysb=$destsPrefix/etc/sysconfig/bootloader
local kname=""
local kernel=""
local initrd=""
local title=""
#======================================
# check for device by ID
#--------------------------------------
local diskByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# check for bootloader displayname
#--------------------------------------
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $mountPrefix/image/.profile ];then
importFile < $mountPrefix/image/.profile
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$kiwi_cmdline" ];then
KIWI_KERNEL_OPTIONS="$KIWI_KERNEL_OPTIONS $kiwi_cmdline"
fi
#======================================
# check for syslinux title postfix
#--------------------------------------
if [ -z "$zfix" ];then
zfix="unknown"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
kiwi_boot_timeout=100;
fi
#======================================
# create directory structure
#--------------------------------------
for dir in $conf $sysb;do
dir=`dirname $dir`; mkdir -p $dir
done
#======================================
# create zipl.conf file
#--------------------------------------
local count
local title_default
local title_failsafe
echo "[defaultboot]" > $conf
echo "defaultmenu = menu" >> $conf
echo ":menu" >> $conf
echo " default = 1" >> $conf
echo " prompt = 1" >> $conf
echo " target = /boot/zipl" >> $conf
echo " timeout = $kiwi_boot_timeout" >> $conf
count=1
IFS="," ; for i in $KERNEL_LIST;do
if test -z "$i";then
continue
fi
kname=${KERNEL_NAME[$count]}
if ! echo $zfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
if [ "$count" = "1" ];then
title_default=$(makeLabel "$zfix")
else
title_default=$(makeLabel "$kname ( $zfix )")
fi
elif [ -z "$kiwi_oemtitle" ];then
title_default=$(makeLabel "$kname ( $zfix )")
else
if [ "$count" = "1" ];then
title_default=$(makeLabel "$kiwi_oemtitle ( $zfix )")
else
title_default=$(makeLabel "$kiwi_oemtitle-$kname ( $zfix )")
fi
fi
title_failsafe=$(makeLabel "Failsafe -- $title_default")
echo " $count = $title_default" >> $conf
count=$((count + 1))
echo " $count = $title_failsafe" >> $conf
count=$((count + 1))
done
count=1
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:`
kname=${KERNEL_NAME[$count]}
if ! echo $zfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
if [ "$count" = "1" ];then
title_default=$(makeLabel "$zfix")
else
title_default=$(makeLabel "$kname ( $zfix )")
fi
elif [ -z "$kiwi_oemtitle" ];then
title_default=$(makeLabel "$kname ( $zfix )")
else
if [ "$count" = "1" ];then
title_default=$(makeLabel "$kiwi_oemtitle ( $zfix )")
else
title_default=$(makeLabel "$kiwi_oemtitle-$kname ( $zfix )")
fi
fi
title_failsafe=$(makeLabel "Failsafe -- $title_default")
#======================================
# create standard entry
#--------------------------------------
echo "[$title_default]" >> $conf
echo "target = /boot/zipl" >> $conf
echo "image = /boot/$kernel" >> $conf
echo "ramdisk = /boot/$initrd,0x2000000" >> $conf
echo -n "parameters = \"root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo " showopts\"" >> $conf
#======================================
# create failsafe entry
#--------------------------------------
echo "[$title_failsafe]" >> $conf
echo "target = /boot/zipl" >> $conf
echo "image = /boot/$kernel" >> $conf
echo "ramdisk = /boot/$initrd,0x2000000" >> $conf
echo -n "parameters = \"root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo -n " x11failsafe" >> $conf
echo " showopts\"" >> $conf
count=$((count + 1))
done
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
systemException \
"*** zipl: recovery chain loading not implemented ***" \
"reboot"
fi
#======================================
# create sysconfig/bootloader
#--------------------------------------
echo "LOADER_TYPE=\"$loader\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo -n "DEFAULT_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo " showopts\"" >> $sysb
echo -n "FAILSAFE_APPEND=\"root=$diskByID" >> $sysb
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo -n " x11failsafe noresume\"" >> $sysb
}
#======================================
# setupBootLoaderSyslinux
#--------------------------------------
function setupBootLoaderSyslinux {
# /.../
# create syslinux.cfg used for the
# syslinux bootloader
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # boot partition ID
local rdev=$4 # root partition
local gfix=$5 # syslinux title postfix
local swap=$6 # optional swap partition
local conf=$destsPrefix/boot/syslinux/syslinux.cfg
local sysb=$destsPrefix/etc/sysconfig/bootloader
local console=""
local kname=""
local kernel=""
local initrd=""
local title=""
local fbmode=$vga
if [ ! -z "$kiwi_oemrecovery" ];then
local gdevreco=$recoid
fi
if [ -z "$fbmode" ];then
fbmode=$DEFAULT_VGA
fi
#======================================
# check for device by ID
#--------------------------------------
local diskByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# check for bootloader displayname
#--------------------------------------
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $mountPrefix/image/.profile ];then
importFile < $mountPrefix/image/.profile
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$kiwi_cmdline" ];then
KIWI_KERNEL_OPTIONS="$KIWI_KERNEL_OPTIONS $kiwi_cmdline"
fi
#======================================
# setup config file name
#--------------------------------------
if [ $loader = "extlinux" ];then
conf=$destsPrefix/boot/syslinux/extlinux.conf
fi
#======================================
# check for syslinux title postfix
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
kiwi_boot_timeout=100;
fi
#======================================
# create directory structure
#--------------------------------------
for dir in $conf $sysb;do
dir=`dirname $dir`; mkdir -p $dir
done
#======================================
# create syslinux.cfg file
#--------------------------------------
echo "implicit 1" > $conf
echo "prompt 1" >> $conf
echo "TIMEOUT $kiwi_boot_timeout" >> $conf
echo "display isolinux.msg" >> $conf
if [ -f "$mountPrefix/boot/syslinux/bootlogo" ];then
if \
[ -f "$mountPrefix/boot/syslinux/gfxboot.com" ] || \
[ -f "$mountPrefix/boot/syslinux/gfxboot.c32" ]
then
echo "ui gfxboot bootlogo isolinux.msg" >> $conf
else
echo "gfxboot bootlogo" >> $conf
fi
fi
local count=1
IFS="," ; for i in $KERNEL_LIST;do
if test ! -z "$i";then
#======================================
# setup syslinux requirements
#--------------------------------------
kernel=`echo $i | cut -f1 -d:`
initrd=`echo $i | cut -f2 -d:`
kname=${KERNEL_NAME[$count]}
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
if [ "$count" = "1" ];then
title=$(makeLabel "$gfix")
else
title=$(makeLabel "$kname [ $gfix ]")
fi
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
if [ "$count" = "1" ];then
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle-$kname [ $gfix ]")
fi
fi
#======================================
# create standard entry
#--------------------------------------
echo "DEFAULT $title" >> $conf
echo "label $title" >> $conf
if xenServer $kname $mountPrefix;then
systemException \
"*** $loader: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "kernel /boot/$kernel" >> $conf
echo -n "append initrd=/boot/$initrd" >> $conf
echo -n " root=$diskByID $console" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " vga=$fbmode" >> $conf
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $conf
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $conf
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo " showopts" >> $conf
fi
#======================================
# create Failsafe entry
#--------------------------------------
title=$(makeLabel "Failsafe -- $title")
echo "label $title" >> $conf
if xenServer $kname $mountPrefix;then
systemException \
"*** $loader: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "kernel /boot/$kernel" >> $conf
echo -n "append initrd=/boot/$initrd" >> $conf
echo -n " root=$diskByID $console" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " vga=$fbmode" >> $conf
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $conf
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $conf
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo -n " $failsafe" >> $conf
echo " showopts" >> $conf
fi
count=$((count + 1))
fi
done
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
echo "label Recovery" >> $conf
echo "kernel chain" >> $conf
echo "append hd0 $gdevreco" >> $conf
fi
#======================================
# create sysconfig/bootloader
#--------------------------------------
echo "LOADER_TYPE=\"$loader\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo "DEFAULT_VGA=\"$fbmode\"" >> $sysb
echo -n "DEFAULT_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo " showopts\"" >> $sysb
echo "FAILSAFE_VGA=\"$fbmode\"" >> $sysb
echo -n "FAILSAFE_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo -n " $failsafe" >> $sysb
echo "\"" >> $sysb
}
#======================================
# setupBootLoaderGrub
#--------------------------------------
function setupBootLoaderGrub {
# /.../
# create grub.conf and menu.lst file used for
# installing the bootloader
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # grub boot partition ID
local rdev=$4 # grub root partition
local gfix=$5 # grub title postfix
local swap=$6 # optional swap partition
local menu=$destsPrefix/boot/grub/menu.lst
local conf=$destsPrefix/etc/grub.conf
local dmap=$destsPrefix/boot/grub/device.map
local sysb=$destsPrefix/etc/sysconfig/bootloader
local stage=/boot/grub/stage2
local console=""
local kname=""
local kernel=""
local initrd=""
local title=""
local rdisk=""
local fbmode=$vga
if [ ! -z "$kiwi_oemrecovery" ];then
local gdevreco=$((recoid - 1))
fi
if [ -z "$fbmode" ];then
fbmode=$DEFAULT_VGA
fi
#======================================
# check for device by ID
#--------------------------------------
local diskByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $mountPrefix/image/.profile ];then
importFile < $mountPrefix/image/.profile
fi
#======================================
# check for bootloader displayname
#--------------------------------------
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$kiwi_cmdline" ];then
KIWI_KERNEL_OPTIONS="$KIWI_KERNEL_OPTIONS $kiwi_cmdline"
fi
#======================================
# check for grub device
#--------------------------------------
if [ -z "$gnum" ];then
gnum=1
fi
#======================================
# check for grub title postfix
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
kiwi_boot_timeout=10;
fi
#======================================
# create directory structure
#--------------------------------------
for dir in $menu $conf $dmap $sysb;do
dir=`dirname $dir`; mkdir -p $dir
done
#======================================
# setup grub device node
#--------------------------------------
gdev="(hd0,$gnum)"
#======================================
# create menu.lst file
#--------------------------------------
echo "timeout $kiwi_boot_timeout" > $menu
if [ -f $mountPrefix/boot/grub/splash.xpm.gz ];then
echo "splashimage=$gdev/boot/grub/splash.xpm.gz" >> $menu
elif [ -f /image/loader/message ] || [ -f /boot/message ];then
echo "gfxmenu $gdev/boot/message" >> $menu
fi
local count=1
IFS="," ; for i in $KERNEL_LIST;do
if test ! -z "$i";then
#======================================
# create grub requirements
#--------------------------------------
kernel=`echo $i | cut -f1 -d:`
initrd=`echo $i | cut -f2 -d:`
kname=${KERNEL_NAME[$count]}
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
if [ "$count" = "1" ];then
title=$(makeLabel "$gfix")
else
title=$(makeLabel "$kname [ $gfix ]")
fi
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
if [ "$count" = "1" ];then
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle-$kname [ $gfix ]")
fi
fi
#======================================
# create standard entry
#--------------------------------------
echo "title $title" >> $menu
if xenServer $kname $mountPrefix;then
echo " root $gdev" >> $menu
echo " kernel /boot/xen.gz" >> $menu
echo -n " module /boot/$kernel" >> $menu
echo -n " root=$diskByID" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " $console vga=$fbmode" >> $menu
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $menu
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $menu
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $menu
fi
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo " showopts" >> $menu
echo " module /boot/$initrd" >> $menu
else
echo -n " kernel $gdev/boot/$kernel" >> $menu
echo -n " root=$diskByID" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " $console vga=$fbmode" >> $menu
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $menu
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $menu
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $menu
fi
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo " showopts" >> $menu
echo " initrd $gdev/boot/$initrd" >> $menu
fi
#======================================
# create failsafe entry
#--------------------------------------
title=$(makeLabel "Failsafe -- $title")
echo "title $title" >> $menu
if xenServer $kname $mountPrefix;then
echo " root $gdev" >> $menu
echo " kernel /boot/xen.gz" >> $menu
echo -n " module /boot/$kernel" >> $menu
echo -n " root=$diskByID" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " $console vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " $failsafe" >> $menu
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $menu
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $menu
fi
echo " showopts" >> $menu
echo " module /boot/$initrd" >> $menu
else
echo -n " kernel $gdev/boot/$kernel" >> $menu
echo -n " root=$diskByID" >> $menu
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $menu
fi
echo -n " $console vga=$fbmode" >> $menu
echo -n " $KIWI_INITRD_PARAMS" >> $menu
echo -n " $KIWI_KERNEL_OPTIONS" >> $menu
echo -n " $failsafe" >> $menu
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $menu
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc console=tty" >> $menu
fi
echo " showopts" >> $menu
echo " initrd $gdev/boot/$initrd" >> $menu
fi
count=$((count + 1))
fi
done
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
echo "title Recovery" >> $menu
echo " rootnoverify (hd0,$gdevreco)" >> $menu
echo " chainloader +1" >> $menu
fi
#======================================
# create grub.conf file
#--------------------------------------
echo "root $gdev" > $conf
if dd if=$rdev bs=1 count=512 | file - | grep -q Bootloader;then
echo "setup --stage2=$stage $gdev" >> $conf
else
echo "setup --stage2=$stage (hd0)" >> $conf
fi
echo "quit" >> $conf
#======================================
# create grub device map
#--------------------------------------
rdisk=`echo $rdev | sed -e s"@[0-9]@@g"`
if [ ! -z "$imageDiskDevice" ];then
rdisk=$imageDiskDevice
fi
rdisk=$(getDiskID $rdisk)
echo "(hd0) $rdisk" > $dmap
#======================================
# create sysconfig/bootloader
#--------------------------------------
echo "LOADER_TYPE=\"grub\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo "DEFAULT_VGA=\"$fbmode\"" >> $sysb
echo -n "DEFAULT_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo " showopts\"" >> $sysb
echo "FAILSAFE_VGA=\"$fbmode\"" >> $sysb
echo -n "FAILSAFE_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo -n " $failsafe" >> $sysb
echo "\"" >> $sysb
}
#======================================
# setupBootLoaderGrub2
#--------------------------------------
function setupBootLoaderGrub2 {
# /.../
# create/update default grub2 configuration
# ----
local IFS=$IFS_ORIG
#======================================
# function paramters
#--------------------------------------
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local gnum=$3 # grub boot partition ID
local rdev=$4 # grub root partition
local gfix=$5 # grub title postfix
local swap=$6 # optional swap partition
#======================================
# local variables
#--------------------------------------
local kname=$(uname -r)
local title
local cmdline
local timeout
local vesa
local loader_type="grub2"
#======================================
# vesa hex => resolution table
#--------------------------------------
vesa[0x301]="640x480"
vesa[0x310]="640x480"
vesa[0x311]="640x480"
vesa[0x312]="640x480"
vesa[0x303]="800x600"
vesa[0x313]="800x600"
vesa[0x314]="800x600"
vesa[0x315]="800x600"
vesa[0x305]="1024x768"
vesa[0x316]="1024x768"
vesa[0x317]="1024x768"
vesa[0x318]="1024x768"
vesa[0x307]="1280x1024"
vesa[0x319]="1280x1024"
vesa[0x31a]="1280x1024"
vesa[0x31b]="1280x1024"
#======================================
# setup ID device names
#--------------------------------------
local rootByID=$(getDiskID $rdev)
local swapByID=$(getDiskID $swap swap)
local diskByID=$(getDiskID $imageDiskDevice)
if [ "$FSTYPE" = "zfs" ];then
rootByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# setup path names
#--------------------------------------
local orig_sysimg_profile=$mountPrefix/image/.profile
local inst_default_grub=$destsPrefix/etc/default/grub
local inst_default_grubdev=$destsPrefix/etc/default/grub_installdevice
local inst_default_grubmap=$destsPrefix/boot/grub2/device.map
local unifont=$mountPrefix/usr/share/grub2/unicode.pf2
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $orig_sysimg_profile ];then
importFile < $orig_sysimg_profile
fi
#======================================
# setup title name
#--------------------------------------
if [ -z "$gfix" ];then
gfix="unknown"
fi
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
if ! echo $gfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
title=$(makeLabel "$gfix")
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $gfix ]")
else
title=$(makeLabel "$kiwi_oemtitle [ $gfix ]")
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$KIWI_KERNEL_OPTIONS" ];then
cmdline="$cmdline $KIWI_KERNEL_OPTIONS"
fi
if [ ! -z "$KIWI_INITRD_PARAMS" ];then
cmdline="$cmdline $KIWI_INITRD_PARAMS";
fi
if [ ! -z "$rootByID" ];then
cmdline="$cmdline root=$rootByID"
fi
if [ ! -z "$diskByID" ];then
cmdline="$cmdline disk=$diskByID"
fi
if [ ! -z "$swapByID" ];then
cmdline="$cmdline resume=$swapByID"
fi
if [ ! -z "$kiwi_cmdline" ];then
cmdline="$cmdline $kiwi_cmdline"
fi
if [ -e /dev/xvc0 ];then
cmdline="$cmdline console=xvc console=tty"
elif [ -e /dev/hvc0 ];then
cmdline="$cmdline console=hvc console=tty"
fi
if [[ ! $cmdline =~ quiet ]];then
cmdline="$cmdline quiet"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
timeout=10;
fi
#======================================
# write etc/default/grub
#--------------------------------------
mkdir -p $destsPrefix/etc/default
cat > $inst_default_grub << EOF
GRUB_DISTRIBUTOR=$(printf %q "$title")
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=$timeout
GRUB_CMDLINE_LINUX_DEFAULT="$cmdline"
GRUB_CMDLINE_LINUX=""
EOF
#======================================
# set terminal mode
#--------------------------------------
if [ -e $unifont ];then
echo "GRUB_TERMINAL=gfxterm" >> $inst_default_grub
else
echo "GRUB_TERMINAL=console" >> $inst_default_grub
fi
#======================================
# write etc/default/grub_installdevice
#--------------------------------------
cat > $inst_default_grubdev << EOF
$diskByID
EOF
#======================================
# write boot/grub2/device.map
#--------------------------------------
mkdir -p $destsPrefix/boot/grub2
cat > $inst_default_grubmap << EOF
(hd0) $diskByID
EOF
#======================================
# Use linuxefi/initrdefi if needed
#--------------------------------------
if [ "$kiwi_firmware" = "uefi" ] || [ "$kiwi_firmware" = "efi" ];then
case $arch in
i?86|x86_64)
echo "GRUB_USE_LINUXEFI=true" >> $inst_default_grub
echo "GRUB_USE_INITRDEFI=true" >> $inst_default_grub
;;
esac
loader_type="grub2-efi"
fi
#======================================
# write vesa vga setup
#--------------------------------------
if [ ! -z "$kiwi_vga" ] && [ ! -z "${vesa[$kiwi_vga]}" ];then
echo "GRUB_GFXMODE=${vesa[$kiwi_vga]}" >> $inst_default_grub
echo "GRUB_GFXPAYLOAD_LINUX=${vesa[$kiwi_vga]}" >> $inst_default_grub
else
echo "GRUB_GFXMODE=${vesa[$DEFAULT_VGA]}" >> $inst_default_grub
echo "GRUB_GFXPAYLOAD_LINUX=keep" >> $inst_default_grub
fi
#======================================
# write bootloader theme setup
#--------------------------------------
if [ ! -z "$kiwi_loader_theme" ];then
local theme=/boot/grub2/themes/$kiwi_loader_theme/theme.txt
local bgpng=/boot/grub2/themes/$kiwi_loader_theme/background.png
echo "GRUB_THEME=\"$theme\"" >> $inst_default_grub
echo "GRUB_BACKGROUND=\"$bgpng\"" >> $inst_default_grub
fi
#======================================
# write bootloader timeout setup
#--------------------------------------
if [ ! -z "$kiwi_boot_timeout" ];then
echo "GRUB_TIMEOUT=\"$kiwi_boot_timeout\"" >> $inst_default_grub
fi
#======================================
# enable rollback capability
#--------------------------------------
if [ "$FSTYPE" = "btrfs" ];then
echo "SUSE_BTRFS_SNAPSHOT_BOOTING=true" >> $inst_default_grub
fi
#======================================
# create sysconfig/bootloader
#--------------------------------------
mkdir -p $destsPrefix/etc/sysconfig
local sysb=$destsPrefix/etc/sysconfig/bootloader
echo "LOADER_TYPE=\"$loader_type\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo "DEFAULT_APPEND=\"$cmdline\"" >> $sysb
echo "FAILSAFE_APPEND=\"$failsafe $cmdline\"" >> $sysb
#======================================
# Cleanup protective MBR
#--------------------------------------
if [ ! -z "$needProtectiveMBR" ];then
updateProtectiveMBR
fi
}
#======================================
# setupBootLoaderYaboot
#--------------------------------------
function setupBootLoaderYaboot {
# /.../
# create lilo.conf file used for installing the bootloader
# this file is converted to yaboot.conf therefore lilo.conf
# has some restrictions
# ----
local IFS=$IFS_ORIG
local mountPrefix=$1 # mount path of the image
local destsPrefix=$2 # base dir for the config files
local lnum=$3 # lilo boot partition ID
local rdev=$4 # lilo root partition
local lfix=$5 # lilo title postfix
local swap=$6 # optional swap partition
local conf=$destsPrefix/etc/lilo.conf
local sysb=$destsPrefix/etc/sysconfig/bootloader
local console=""
local kname=""
local kernel=""
local initrd=""
local title=""
local rdisk=""
local fbmode=$vga
local loader_type=lilo
if [[ $arch =~ ppc64 ]];then
loader_type=ppc
fi
if [ -z "$fbmode" ];then
fbmode=$DEFAULT_VGA
fi
#======================================
# check for device by ID
#--------------------------------------
local diskByID=`getDiskID $rdev`
local swapByID=`getDiskID $swap swap`
if [ "$FSTYPE" = "zfs" ];then
diskByID="ZFS=kiwipool/ROOT/system-1"
fi
#======================================
# check for bootloader displayname
#--------------------------------------
if [ -z "$kiwi_oemtitle" ] && [ ! -z "$kiwi_displayname" ];then
kiwi_oemtitle=$kiwi_displayname
fi
#======================================
# check for system image .profile
#--------------------------------------
if [ -f $mountPrefix/image/.profile ];then
importFile < $mountPrefix/image/.profile
fi
#======================================
# check for kernel options
#--------------------------------------
if [ ! -z "$kiwi_cmdline" ];then
KIWI_KERNEL_OPTIONS="$KIWI_KERNEL_OPTIONS $kiwi_cmdline"
fi
#======================================
# check for lilo title postfix
#--------------------------------------
if [ -z "$lfix" ];then
lfix="unknown"
fi
#======================================
# check for boot TIMEOUT
#--------------------------------------
if [ -z "$kiwi_boot_timeout" ];then
kiwi_boot_timeout=10;
fi
#======================================
# setup lilo boot device
#--------------------------------------
rdisk=`echo $rdev | sed -e s"@[0-9]@@g"`
if [ ! -z "$imageDiskDevice" ];then
rdisk=$imageDiskDevice
fi
rdev=$(ddn $(dn $rdisk) $lnum)
#======================================
# create directory structure
#--------------------------------------
for dir in $conf $sysb;do
dir=`dirname $dir`; mkdir -p $dir
done
#======================================
# create lilo.conf file
#--------------------------------------
local timeout=$((kiwi_boot_timeout * 10))
echo "boot=$rdev" > $conf
echo "activate" >> $conf
echo "timeout=$timeout" >> $conf
local count=1
IFS="," ; for i in $KERNEL_LIST;do
if test ! -z "$i";then
#======================================
# create lilo requirements
#--------------------------------------
kernel=`echo $i | cut -f1 -d:`
initrd=`echo $i | cut -f2 -d:`
kname=${KERNEL_NAME[$count]}
if ! echo $lfix | grep -E -q "OEM|USB|VMX|NET|unknown";then
if [ "$count" = "1" ];then
title=$(makeLabel "$lfix")
else
title=$(makeLabel "$kname [ $lfix ]")
fi
elif [ -z "$kiwi_oemtitle" ];then
title=$(makeLabel "$kname [ $lfix ]")
else
if [ "$count" = "1" ];then
title=$(makeLabel "$kiwi_oemtitle [ $lfix ]")
else
title=$(makeLabel "$kiwi_oemtitle-$kname [ $lfix ]")
fi
fi
#======================================
# create standard entry
#--------------------------------------
if xenServer $kname $mountPrefix;then
systemException \
"*** lilo: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "default=\"$title\"" >> $conf
echo "image=/boot/$kernel" >> $conf
echo "label=\"$title\"" >> $conf
echo "initrd=/boot/$initrd" >> $conf
echo -n "append=\"sysrq=1 panic=9" >> $conf
echo -n " root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " $console vga=$fbmode" >> $conf
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $conf
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $conf
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc0 console=tty" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo " showopts\"" >> $conf
fi
#======================================
# create failsafe entry
#--------------------------------------
title=$(makeLabel "Failsafe -- $title")
if xenServer $kname $mountPrefix;then
systemException \
"*** lilo: Xen dom0 boot not implemented ***" \
"reboot"
else
echo "image=/boot/$kernel" >> $conf
echo "label=\"$title\"" >> $conf
echo "initrd=/boot/$initrd" >> $conf
echo -n "append=\"sysrq=1 panic=9" >> $conf
echo -n " root=$diskByID" >> $conf
if [ ! -z "$imageDiskDevice" ];then
echo -n " disk=$(getDiskID $imageDiskDevice)" >> $conf
fi
echo -n " $console vga=$fbmode" >> $conf
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $conf
fi
if [ -e /dev/xvc0 ];then
echo -n " console=xvc console=tty" >> $conf
elif [ -e /dev/hvc0 ];then
echo -n " console=hvc0 console=tty" >> $conf
fi
echo -n " $KIWI_INITRD_PARAMS" >> $conf
echo -n " $KIWI_KERNEL_OPTIONS" >> $conf
echo -n " $failsafe" >> $conf
echo " showopts\"" >> $conf
fi
count=$((count + 1))
fi
done
#======================================
# create recovery entry
#--------------------------------------
if [ ! -z "$kiwi_oemrecovery" ];then
systemException \
"*** lilo: recovery chain loading not implemented ***" \
"reboot"
fi
#======================================
# create sysconfig/bootloader
#--------------------------------------
echo "LOADER_TYPE=\"$loader_type\"" > $sysb
echo "LOADER_LOCATION=\"mbr\"" >> $sysb
echo "DEFAULT_VGA=\"$fbmode\"" >> $sysb
echo -n "DEFAULT_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo " showopts\"" >> $sysb
echo "FAILSAFE_VGA=\"$fbmode\"" >> $sysb
echo -n "FAILSAFE_APPEND=\"root=$diskByID" >> $sysb
if [ ! -z "$swap" ];then
echo -n " resume=$swapByID" >> $sysb
fi
echo -n " $KIWI_INITRD_PARAMS $KIWI_KERNEL_OPTIONS" >> $sysb
echo -n " $failsafe" >> $sysb
echo "\"" >> $sysb
}
#======================================
# setupDefaultPXENetwork
#--------------------------------------
function setupDefaultPXENetwork {
# /.../
# create the /sysconfig/network file according to the PXE
# boot interface.
# ----
local IFS=$IFS_ORIG
if [ -z "$PXE_IFACE" ];then
return
fi
local prefix=$1
local niface=$prefix/etc/sysconfig/network/ifcfg-$PXE_IFACE
mkdir -p $prefix/etc/sysconfig/network
cat > $niface < /dev/null
echo "BOOTPROTO='dhcp'" >> $niface
echo "STARTMODE='ifplugd'" >> $niface
echo "USERCONTROL='no'" >> $niface
}
#======================================
# setupDefaultFstab
#--------------------------------------
function setupDefaultFstab {
# /.../
# Update or create new /etc/fstab file with the default entries
# ----
local IFS=$IFS_ORIG
local prefix=$1
local nfstab=$prefix/etc/fstab
mkdir -p $prefix/etc
grep -q devpts $nfstab || \
echo "devpts /dev/pts devpts mode=0620,gid=5 0 0" >> $nfstab
grep -q proc $nfstab || \
echo "proc /proc proc defaults 0 0" >> $nfstab
grep -q sysfs $nfstab || \
echo "sysfs /sys sysfs noauto 0 0" >> $nfstab
grep -q debugfs $nfstab || test -e /sys/kernel/debug && \
echo "debugfs /sys/kernel/debug debugfs noauto 0 0" >> $nfstab
grep -q usbfs $nfstab || test -e /proc/bus/usb && \
echo "usbfs /proc/bus/usb usbfs noauto 0 0" >> $nfstab
grep -q /run $nfstab || test -e /run && \
echo "tmpfs /run tmpfs noauto 0 0" >> $nfstab
}
#======================================
# updateRootDeviceFstab
#--------------------------------------
function updateRootDeviceFstab {
# /.../
# add one line to the fstab file for the root device
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
local config_tmp=$1
local rdev=$2
local nfstab=$config_tmp/etc/fstab
local diskByID=$(getDiskID $rdev)
local opts=defaults
#======================================
# check for custom options
#--------------------------------------
if [ ! -z "$kiwi_fsmountoptions" ] && [ ! $FSTYPE = "zfs" ];then
opts=$kiwi_fsmountoptions
fi
#======================================
# check for NFSROOT
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
local server=$(echo $rdev | cut -f3 -d" ")
local option=$(echo $rdev | cut -f2 -d" ")
echo "$server / nfs $option 0 0" >> $nfstab
return
fi
#======================================
# check for device by ID
#--------------------------------------
if [ -z "$UNIONFS_CONFIG" ]; then
echo "$diskByID / $FSTYPE $opts 1 1" >> $nfstab
else
echo "/dev/root / auto defaults 1 1" >> $nfstab
fi
#======================================
# check for LVM volume setup
#--------------------------------------
if [ "$haveLVM" = "yes" ];then
local variable
local volume
local content
local volpath
local mpoint
local mppath
for i in $(cat /.profile | grep -E 'kiwi_LVM_|kiwi_allFreeVolume');do
variable=$(echo $i|cut -f1 -d=)
volume=$(echo $i| cut -f3- -d_ | cut -f1 -d=)
content=$(echo $i|cut -f2 -d= | tr -d \' | tr -d \")
volpath=$(echo $content | cut -f3 -d:)
if [ -z "$volpath" ];then
volpath=$(echo $volume | tr _ /)
fi
mpoint=$(echo $volpath | sed -e s@^LV@@)
mppath="/dev/$kiwi_lvmgroup/$volume"
if \
[ ! $volume = "LVRoot" ] && \
[ ! $volume = "LVComp" ] && \
[ ! $volume = "LVSwap" ]
then
echo "$mppath /$mpoint $FSTYPE $opts 1 2" >> $nfstab
fi
done
elif [ "$FSTYPE" = "btrfs" ];then
local fsuuid=$(blkid $rdev -s UUID -o value)
for subvol in $(btrfs subvol list $prefix |grep -v @ |cut -f9 -d' ');do
echo "UUID=$fsuuid /$subvol btrfs subvol=@/$subvol 0 0" >> $nfstab
done
fi
}
#======================================
# updateSwapDeviceFstab
#--------------------------------------
function updateSwapDeviceFstab {
# /.../
# add one line to the fstab file for the swap device
# ----
local IFS=$IFS_ORIG
local prefix=$1
local sdev=$2
local diskByID=`getDiskID $sdev`
local nfstab=$prefix/etc/fstab
echo "$diskByID swap swap defaults 0 0" >> $nfstab
}
#======================================
# updateBootDeviceFstab
#--------------------------------------
function updateBootDeviceFstab {
# /.../
# add temporary bind mounted boot entry to fstab
# ----
local IFS=$IFS_ORIG
local config_tmp=$1
local sdev=$2
local nfstab=$config_tmp/etc/fstab
local mount=boot_bind
local prefix=/mnt
#======================================
# Store boot entry
#--------------------------------------
if [ -e $prefix/$mount ];then
local diskByID=$(getDiskID $sdev)
if [ ! -z "$FSTYPE" ];then
FSTYPE_SAVE=$FSTYPE
fi
probeFileSystem $sdev
if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ];then
FSTYPE="auto"
fi
echo "$diskByID /$mount $FSTYPE defaults 1 2" >> $nfstab
echo "/$mount/boot /boot none bind 0 0" >> $nfstab
if [ ! -z "$FSTYPE_SAVE" ];then
FSTYPE=$FSTYPE_SAVE
fi
fi
#======================================
# Store boot/efi entry
#--------------------------------------
if [ ! -z "$kiwi_JumpPart" ];then
local jdev=$(ddn $imageDiskDevice $kiwi_JumpPart)
local fstype=$(blkid $jdev -s TYPE -o value)
local label=$(blkid $jdev -s LABEL -o value)
if [ ! -z "$fstype" ] && [ "$label" = "EFI" ];then
jdev=$(getDiskID $jdev)
echo "$jdev /boot/efi $fstype defaults 0 0" >> $nfstab
fi
if [ ! -z "$fstype" ] && [ "$label" = "ZIPL" ];then
jdev=$(getDiskID $jdev)
echo "$jdev /boot/zipl $fstype defaults 0 0" >> $nfstab
fi
fi
}
#======================================
# updateOtherDeviceFstab
#--------------------------------------
function updateOtherDeviceFstab {
# /.../
# check the contents of the $PART variable and
# add one line to the fstab file for each partition
# which has a mount point defined.
# ----
local IFS=$IFS_ORIG
local prefix=$1
local prefix=$2
local nfstab=$prefix/etc/fstab
local index=0
local field=0
local count=0
local device
local diskByID
local IFS=","
if [ -z "$prefix" ];then
prefix=/mnt
fi
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if \
[ ! -z "$partMount" ] && \
[ ! "$partMount" = "x" ] && \
[ ! "$partMount" = "swap" ] && \
[ ! "$partMount" = "/" ]
then
if [ ! -z "$RAID" ];then
device=/dev/md$((count - 1))
else
device=$(ddn $DISK $count)
fi
probeFileSystem $device
if [ ! "$FSTYPE" = "luks" ] && [ ! "$FSTYPE" = "unknown" ];then
if [ ! -d $prefix/$partMount ];then
mkdir -p $prefix/$partMount
fi
diskByID=$(getDiskID $device)
echo "$diskByID $partMount $FSTYPE defaults 0 0" >> $nfstab
fi
fi
done
}
#======================================
# setupKernelModules
#--------------------------------------
function setupKernelModules {
# /.../
# create sysconfig/kernel file which includes the
# kernel modules to become integrated into the initrd
# if created by the distro mkinitrd tool
# ----
local IFS=$IFS_ORIG
local destprefix=$1
local prefix=$2
if [ -z "$prefix" ];then
prefix=/mnt
fi
local sysimg_ktempl=$prefix/var/adm/fillup-templates/sysconfig.kernel
local sysimg_syskernel=$prefix/etc/sysconfig/kernel
local syskernel=$destprefix/etc/sysconfig/kernel
local newstyle_mkinitrd=$prefix/lib/mkinitrd/scripts/boot-usb.sh
local key
local val
mkdir -p $destprefix/etc/sysconfig
#======================================
# include USB host controllers
#--------------------------------------
local USB_MODULES="ehci-hcd ohci-hcd uhci-hcd xhci-hcd"
INITRD_MODULES="$INITRD_MODULES $USB_MODULES"
#======================================
# check for mkinitrd capabilities
#--------------------------------------
if [ ! -e $newstyle_mkinitrd ];then
# /.../
# if boot-usb.sh does not exist we are based on an old
# mkinitrd version which requires all modules as part of
# sysconfig/kernel. Therefore we include USB core modules
# required to support USB storage like USB sticks
# ----
USB_MODULES="usbcore usb-storage sd"
INITRD_MODULES="$INITRD_MODULES $USB_MODULES"
# /.../
# old mkinitrd cannot figure this out on its own
# ---
if [ -e /sys/devices/virtio-pci ];then
Echo 'Adding virtio kernel modules to initrd.'
INITRD_MODULES="$INITRD_MODULES virtio-blk virtio-pci"
fi
fi
#======================================
# use system image config or template
#--------------------------------------
if [ -f $sysimg_syskernel ];then
cp $sysimg_syskernel $syskernel
elif [ -f $sysimg_ktempl ];then
cp $sysimg_ktempl $syskernel
fi
#======================================
# update config file
#--------------------------------------
for key in INITRD_MODULES DOMU_INITRD_MODULES;do
if [ $key = "INITRD_MODULES" ];then
val=$INITRD_MODULES
fi
if [ $key = "DOMU_INITRD_MODULES" ];then
val=$DOMURD_MODULES
fi
if [ -z "$val" ];then
continue
fi
sed -i -e \
s"@^$key=\"\(.*\)\"@$key=\"\1 $val\"@" \
$syskernel
done
}
#======================================
# getKernelBootParameters
#--------------------------------------
function getKernelBootParameters {
# /.../
# check contents of bootloader configuration
# and extract cmdline parameters
# ----
local IFS=$IFS_ORIG
local prefix=$1
local params
local files="
$prefix/boot/syslinux/syslinux.cfg
$prefix/boot/syslinux/extlinux.conf
$prefix/boot/grub/menu.lst
$prefix/etc/lilo.conf
$prefix/etc/zipl.conf
"
for c in $files;do
if [ -f $c ];then
params=$(cat $c | grep 'root=' | head -n1)
break
fi
done
params=$(echo $params | sed -e 's@^append=@@')
params=$(echo $params | sed -e 's@^append@@')
params=$(echo $params | sed -e 's@^module@@')
params=$(echo $params | sed -e 's@^kernel@@')
params=$(echo $params | sed -e 's@^parameters=@@')
params=$(echo $params | sed -e 's@"@@g')
params=$(echo $params)
echo $params
}
#======================================
# kernelCheck
#--------------------------------------
function kernelCheck {
# /.../
# Check the running kernel against the kernel
# installed in the image. If the version does not
# match we need to reboot to activate the system
# image kernel. This is done by either using kexec
# or a real reboot is triggered
# ----
local IFS=$IFS_ORIG
local kactive=`uname -r`
local kreboot=1
local prefix=$1
local kernel
local initrd
local params
#======================================
# check installed and running kernel
#--------------------------------------
for i in $prefix/lib/modules/*;do
if [ ! -d $i ];then
continue
fi
kinstname=${i##*/}
if [ $kinstname = $kactive ];then
kreboot=0
break
fi
done
#======================================
# check for forced reboot
#--------------------------------------
if [ ! -z "$FORCE_KEXEC" ];then
kreboot=2
fi
#======================================
# evaluate kreboot condition
#--------------------------------------
case $kreboot in
1) Echo "Kernel versions do not match..." ;;
2) Echo "kexec based reboot forced..." ;;
0) return ;;
esac
#======================================
# trigger reboot if kexec doesn't exist
#--------------------------------------
if [ ! -f /sbin/kexec ];then
Echo "Reboot triggered in 5 sec..."
sleep 5 ; /sbin/reboot -f -i
fi
#======================================
# trigger reboot using kexec
#--------------------------------------
if [ -f /sbin/kexec ];then
#======================================
# find installed kernel / initrd
#--------------------------------------
if [ -z "$KERNEL_LIST" ] ; then
kernelList $prefix
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:`
break
done
IFS=$IFS_ORIG
if [ ! -f $prefix/boot/$kernel ] || [ ! -f $prefix/boot/$initrd ];then
Echo "Can't find $kernel / $initrd in system image"
Echo "Reboot triggered in 5 sec..."
sleep 5 ; /sbin/reboot -f -i
fi
#======================================
# extract bootloader cmdline params
#--------------------------------------
params=$(getKernelBootParameters $prefix)
#======================================
# load and run kernel...
#--------------------------------------
kexec -l $prefix/boot/$kernel \
--append="$params" --initrd=$prefix/boot/$initrd
if [ ! $? = 0 ];then
Echo "Failed to load kernel"
Echo "Reboot triggered in 5 sec..."
sleep 5 ; /sbin/reboot -f -i
fi
#======================================
# go for gold
#--------------------------------------
exec kexec -e
fi
}
#======================================
# probeFileSystem
#--------------------------------------
function probeFileSystem {
# /.../
# probe for the filesystem type. The function will
# read 128 kB of the given device and check the
# filesystem header data to detect the type of the
# filesystem
# ----
local IFS=$IFS_ORIG
FSTYPE=unknown
FSTYPE=$(blkid $1 -s TYPE -o value)
case $FSTYPE in
btrfs) FSTYPE=btrfs ;;
ext4) FSTYPE=ext4 ;;
ext3) FSTYPE=ext3 ;;
ext2) FSTYPE=ext2 ;;
reiserfs) FSTYPE=reiserfs ;;
squashfs) FSTYPE=squashfs ;;
luks) FSTYPE=luks ;;
crypto_LUKS) FSTYPE=luks ;;
vfat) FSTYPE=vfat ;;
clicfs) FSTYPE=clicfs ;;
xfs) FSTYPE=xfs ;;
udf) FSTYPE=udf ;;
zfs_member) FSTYPE=zfs ;;
*)
FSTYPE=unknown
;;
esac
if [ $FSTYPE = "unknown" ];then
dd if=$1 of=/tmp/filesystem-$$ bs=128k count=1 >/dev/null
fi
if [ $FSTYPE = "unknown" ];then
if grep -q ^CLIC /tmp/filesystem-$$;then
FSTYPE=clicfs
fi
if grep -q ^hsqs /tmp/filesystem-$$;then
FSTYPE=squashfs
fi
fi
export FSTYPE
}
#======================================
# getSystemIntegrity
#--------------------------------------
function getSystemIntegrity {
# /.../
# check the variable SYSTEM_INTEGRITY which contains
# information about the status of all image portions
# per partition. If a number is given as parameter only
# the information from the image assigned to this partition
# is returned
# ----
local IFS=$IFS_ORIG
if [ -z "$SYSTEM_INTEGRITY" ];then
echo "clean"
else
echo $SYSTEM_INTEGRITY | cut -f$1 -d:
fi
}
#======================================
# getSystemMD5Status
#--------------------------------------
function getSystemMD5Status {
# /.../
# return the md5 status of the given image number.
# the function works similar to getSystemIntegrity
# ----
local IFS=$IFS_ORIG
echo $SYSTEM_MD5STATUS | cut -f$1 -d:
}
#======================================
# waitForIdleEventQueue
#--------------------------------------
function waitForIdleEventQueue {
local IFS=$IFS_ORIG
local devs=0
local p_devs=1
local timeout=5
Echo -n "Waiting for devices to settle..."
while true;do
udevPending
devs=$(ls -1 /dev | wc -l)
if [ $devs -eq $p_devs ];then
break
fi
p_devs=$devs
sleep $timeout
echo -n .
done
echo
}
#======================================
# probeUSB
#--------------------------------------
function probeUSB {
local IFS=$IFS_ORIG
local module=""
local stdevs=""
local hwicmd="/usr/sbin/hwinfo"
if [ $HAVE_MODULES_ORDER = 0 ];then
#======================================
# load host controller modules
#--------------------------------------
IFS="%"
for i in \
`$hwicmd --usb | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
for i in \
`$hwicmd --usb-ctrl | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
IFS=$IFS_ORIG
stdevs=`echo $stdevs`
for module in $stdevs;do
Echo "Probing module: $module"
modprobe $module >/dev/null
done
#======================================
# check load status for host controller
#--------------------------------------
if [ -z "$stdevs" ];then
return
fi
#======================================
# manually load storage/input drivers
#--------------------------------------
for i in usbhid usb-storage;do
modprobe $i &>/dev/null
done
fi
}
#======================================
# probeDevices
#--------------------------------------
function probeDevices {
local IFS=$IFS_ORIG
local skipUSB=$1
udevPending
if [ $HAVE_MODULES_ORDER = 0 ];then
waitForIdleEventQueue
fi
#======================================
# probe USB devices and load modules
#--------------------------------------
if [ -z "$skipUSB" ];then
probeUSB
fi
#======================================
# probe Disk devices and load modules
#--------------------------------------
if [ $HAVE_MODULES_ORDER = 0 ];then
Echo "Including required kernel modules..."
IFS="%"
local module=""
local stdevs=""
local hwicmd="/usr/sbin/hwinfo"
for i in \
`$hwicmd --storage | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $stdevs | grep -q $m;then
stdevs="$stdevs $m"
fi
done
fi
done
IFS=$IFS_ORIG
stdevs=`echo $stdevs`
if [ ! -z "$kiwikernelmodule" ];then
for module in $kiwikernelmodule;do
Echo "Probing module (cmdline): $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
done
fi
for module in $stdevs;do
loadok=1
for broken in $kiwibrokenmodule;do
if [ $broken = $module ];then
Echo "Prevent loading module: $module"
loadok=0; break
fi
done
if [ $loadok = 1 ];then
Echo "Probing module: $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
fi
done
hwinfo --block &>/dev/null
# /.../
# older systems require ide-disk to be present at any time
# for details on this crappy call see bug: #250241
# ----
modprobe ide-disk &>/dev/null
else
if [ ! -z "$kiwikernelmodule" ];then
for module in $kiwikernelmodule;do
Echo "Probing module (cmdline): $module"
INITRD_MODULES="$INITRD_MODULES $module"
modprobe $module >/dev/null
done
fi
fi
#======================================
# Manual loading of modules
#--------------------------------------
for i in rd brd edd dm-mod xennet xenblk virtio_blk loop squashfs;do
modprobe $i &>/dev/null
done
udevPending
if [ $HAVE_MODULES_ORDER = 0 ];then
waitForIdleEventQueue
fi
}
#======================================
# USBStickDevice
#--------------------------------------
function USBStickDevice {
local IFS=$IFS_ORIG
stickFound=0
local mode=$1
local prefix=/mnt
#======================================
# search for USB removable devices
#--------------------------------------
for device in /sys/bus/usb/drivers/usb-storage/*;do
if [ ! -L $device ];then
continue
fi
descriptions=$device/host*/target*/*/block*
for description in $descriptions;do
if [ ! -d $description ];then
continue
fi
isremovable=$description/removable
storageID=$(echo $description | cut -f1 -d: | xargs basename)
devicebID=$(basename $description | cut -f2 -d:)
if [ $devicebID = "block" ];then
devicebID=`ls -1 $description`
isremovable=$description/$devicebID/removable
fi
serial="/sys/bus/usb/devices/$storageID/serial"
device="/dev/$devicebID"
if [ ! -b $device ];then
continue;
fi
if [ ! -f $isremovable ];then
continue;
fi
if ! partitionSize $device >/dev/null;then
continue;
fi
if [ ! -f $serial ];then
serial="USB Stick (unknown type)"
else
serial=`cat $serial`
fi
removable=`cat $isremovable`
# /.../
# don't check the removable flag, it could be wrong
# especially for USB hard disks connected via a
# USB caddy, details in bug: 535113
# ----
removable=1
if [ $removable -eq 1 ];then
stickRoot=$device
stickDevice=$(ddn $device 1)
for devnr in 1 2;do
dev=$(ddn $stickRoot $devnr)
if ! kiwiMount "$dev" "$prefix" "-o ro";then
continue
fi
if [ "$mode" = "install" ];then
# /.../
# USB stick search for install media
# created with kiwi
# ----
if \
[ ! -e $prefix/config.isoclient ] && \
[ ! -e $prefix/config.usbclient ]
then
umountSystem
continue
fi
elif [ "$mode" = "kexec" ];then
# /.../
# USB stick search for hotfix media
# with kernel/initrd for later kexec
# ----
if \
[ ! -e $prefix/linux.kexec ] && \
[ ! -e $prefix/initrd.kexec ]
then
umountSystem
continue
fi
else
# /.../
# USB stick search for Linux system tree
# created with kiwi
# ----
if [ ! -e $prefix/etc/ImageVersion ]; then
umountSystem
continue
fi
fi
stickFound=1
umountSystem
break
done
if [ "$stickFound" = 0 ];then
continue
fi
stickSerial=$serial
return
fi
done
done
}
#======================================
# CDMountOption
#--------------------------------------
function CDMountOption {
# /.../
# checks for the ISO 9660 extension and prints the
# mount option required to mount the device in full
# speed mode
# ----
local IFS=$IFS_ORIG
local id=$(blkid -o value -s TYPE $1)
if [ "$id" = "iso9660" ];then
echo "-t iso9660"
fi
if [ "$id" = "udf" ]; then
echo "-t udf"
fi
}
#======================================
# searchImageISODevice
#--------------------------------------
function searchImageISODevice {
# /.../
# search all devices for the MBR ID stored in the
# iso header. This function is called to identify the
# live media and/or install media
# ----
local IFS=$IFS_ORIG
local mbrVID
local mbrIID
local count=0
local isoinfo=/usr/bin/isoinfo
mkdir -p /cdrom
if [ ! -x $isoinfo ]; then
isoinfo=/usr/lib/genisoimage/isoinfo
fi
if [ ! -x $isoinfo ];then
systemException \
"Can't find isoinfo tool in initrd" \
"reboot"
fi
if [ ! -f /boot/mbrid ];then
systemException \
"Can't find MBR id file in initrd" \
"reboot"
fi
mbrIID=$(cat /boot/mbrid)
udevPending
#======================================
# Check for ISO file on storage media
#--------------------------------------
if [ ! -z "$isofrom_device" ] && [ ! -z "$isofrom_system" ];then
Echo "Looking up ISO on $isofrom_device..."
mkdir /isofrom
if [[ $isofrom_device =~ nfs: ]];then
setupNetwork
isofrom_device=$(echo $isofrom_device | cut -c 5-)
mount -t nfs -o nolock $isofrom_device /isofrom
else
waitForStorageDevice $isofrom_device
mount $isofrom_device /isofrom
fi
if [ ! $? = 0 ];then
systemException \
"Failed to mount ISO storage device !" \
"reboot"
fi
biosBootDevice=$(loop_setup /isofrom/$isofrom_system)
if [ ! $? = 0 ];then
systemException \
"Failed to loop setup ISO system !" \
"reboot"
fi
return 0
fi
#======================================
# Search ISO header in device list
#--------------------------------------
Echo -n "Searching for boot device in Application ID..."
while true;do
for i in /dev/*;do
if [ ! -b $i ];then
continue
fi
mbrVID=$(
$isoinfo -d -i $i 2>/dev/null|grep "Application id:"|cut -f2 -d:
)
mbrVID=$(echo $mbrVID)
if [ "$mbrVID" = "$mbrIID" ];then
# /.../
# found ISO header on a device, now check if there is
# also a partition for this device with the same
# information and prefer that device if it exists
# ----
biosBootDevice=$i
for n in 1 2;do
local pdev=$(ddn $i $n)
if [ -e $pdev ];then
mbrVID=$(
$isoinfo -d -i $pdev 2>/dev/null |\
grep "Application id:"|cut -f2 -d:
)
mbrVID=$(echo $mbrVID)
if [ "$mbrVID" = "$mbrIID" ];then
biosBootDevice=$pdev
echo; return 0
fi
fi
done
echo; return 0
fi
done
if [ $count -eq 30 ];then
systemException \
"Failed to find MBR identifier !" \
"reboot"
fi
count=$(($count + 1))
echo -n .
sleep 1
done
}
#======================================
# runMediaCheck
#--------------------------------------
function runMediaCheck {
# /.../
# run checkmedia program on the specified device
# ----
local IFS=$IFS_ORIG
local device_iso=$biosBootDevice
local device_sdx=$(dn $biosBootDevice)
if [ -e "$device_sdx" ];then
device_iso=$device_sdx
fi
if ! checkmedia $device_iso;then
systemException \
"ISO check failed, you have been warned" \
"waitkey"
else
Echo "ISO check passed"
Echo "Press any key to continue (waiting $MEDIACHECK_OK_TIMER sec...)"
read -s -n 1 -t $MEDIACHECK_OK_TIMER
fi
}
#======================================
# setupHybridFeatures
#--------------------------------------
function setupHybridPersistent {
# /.../
# create a write partition for hybrid images if requested
# and store the device name in HYBRID_RW
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_hybridpersistent" = "true" ];then
return
fi
local diskDevice=$(dn $biosBootDevice)
#======================================
# create write partition for hybrid
#--------------------------------------
if [ -z "$kiwi_cowdevice" ] && [ -z "$kiwi_cowsystem" ];then
#======================================
# try to create a write partition
#--------------------------------------
createHybridPersistent $diskDevice
else
#======================================
# use given cow device
#--------------------------------------
createCustomHybridPersistent
fi
#======================================
# check hybrid write partition device
#--------------------------------------
if [ ! -e "$HYBRID_RW" ]; then
# /.../
# failed to create read-write partition
# disable persistent writing
# ----
unset HYBRID_RW
unset kiwi_hybridpersistent
export skipSetupBootPartition=1
fi
}
#======================================
# CDUmount
#--------------------------------------
function CDUmount {
# /.../
# umount the CD device
# ----
local IFS=$IFS_ORIG
umount $biosBootDevice
}
#======================================
# CDEject
#--------------------------------------
function CDEject {
local IFS=$IFS_ORIG
eject $biosBootDevice
}
#======================================
# searchOFBootDevice
#--------------------------------------
function searchOFBootDevice {
# /.../
# search for the device with the OF PROM id
# this is required for the ppc boot architecture
# as we don't have a BIOS and a MBR here
# ----
local IFS=$IFS_ORIG
local ofdev=`cat /proc/device-tree/chosen/bootpath|cut -f1 -d:`
local h=/usr/sbin/ofpathname
local ddevs=`$h -l $ofdev`
#======================================
# Store device with PROM id
#--------------------------------------
for curd in $ddevs;do
if [ $curd = "sda" -o $curd = "vda" ];then
export biosBootDevice="/dev/$curd"
return 0
fi
done
export biosBootDevice="Can't find OF boot device"
return 1
}
#======================================
# searchBusIDBootDevice
#--------------------------------------
function searchBusIDBootDevice {
# /.../
# check for a DASD or ZFCP devices
# like they exist on the s390 architecture. If found the
# device is set online and the biosBootDevice variable
# is set to this device for further processing
# ----
local IFS=$IFS_ORIG
local dpath=/dev/disk/by-path
local ipl_type=$(cat /sys/firmware/ipl/ipl_type)
local deviceID=$(cat /sys/firmware/ipl/device)
local dev_type=$(cat /sys/bus/ccw/devices/$deviceID/devtype)
local wwpn
local slun
#======================================
# check for custom device init command
#--------------------------------------
if [ ! -z "$DEVICE_INIT" ];then
if ! eval $DEVICE_INIT;then
export biosBootDevice="Failed to call: $DEVICE_INIT"
return 1
fi
export biosBootDevice=$DISK
return 0
fi
#======================================
# determine device type: dasd or zfcp
#--------------------------------------
if [ -z "$deviceID" ];then
systemException \
"Can't find IPL device" \
"reboot"
fi
if [ "$ipl_type" = "fcp" ];then
# plain FCP device 512b blocksize
haveZFCP=1
elif [ "$ipl_type" = "ccw" ];then
if [[ "$dev_type" =~ "3390" ]];then
# plain DASD device 4k blocksize
haveDASD=1
elif [[ "$dev_type" =~ "9336" ]];then
# emulated DASD device 512b blocksize, handled as FCP device
# but don't configure host and disk as required for plain
# FCP devices
haveZFCP=1
else
systemException \
"Unknown Device type: $dev_type" \
"reboot"
fi
else
systemException \
"Unknown IPL type: $ipl_type" \
"reboot"
fi
#======================================
# check if we can find the device
#--------------------------------------
if [ ! -e /sys/bus/ccw/devices/$deviceID ];then
systemException \
"Can't find disk with ID: $deviceID" \
"reboot"
fi
#======================================
# DASD real in CDL / LDL mode
#--------------------------------------
if [ $haveDASD -eq 1 ];then
dasd_configure $deviceID 1 0
biosBootDevice="$dpath/ccw-$deviceID"
fi
#======================================
# DASD emulated in FBA mode
#--------------------------------------
if [ $haveZFCP -eq 1 ] && [ "$ipl_type" = "ccw" ];then
dasd_configure $deviceID 1 0
biosBootDevice="$dpath/ccw-$deviceID"
fi
#======================================
# ZFCP real in SCSI mode
#--------------------------------------
if [ $haveZFCP -eq 1 ] && [ "$ipl_type" = "fcp" ];then
wwpn=$(cat /sys/firmware/ipl/wwpn)
slun=$(cat /sys/firmware/ipl/lun)
zfcp_host_configure $deviceID 1
zfcp_disk_configure $deviceID $wwpn $slun 1
biosBootDevice="$dpath/ccw-$deviceID-zfcp-$wwpn:$slun"
fi
#======================================
# setup boot device variable
#--------------------------------------
waitForStorageDevice $biosBootDevice
if [ ! -e $biosBootDevice ];then
export biosBootDevice="Failed to set disk $deviceID online"
return 1
fi
export biosBootDevice=$(getDiskDevice $biosBootDevice)
return 0
}
#======================================
# lookupDiskDevices
#--------------------------------------
function lookupDiskDevices {
# /.../
# use hwinfo to search for disk device nodes
# ----
local IFS=$IFS_ORIG
local h=/usr/sbin/hwinfo
local c="Device File:|BIOS id"
udevPending
diskDevices=$($h --disk | \
grep -E "$c" | sed -e"s@(.*)@@" | cut -f2 -d: | tr -d " ")
}
#======================================
# lookupBiosBootDevice
#--------------------------------------
function lookupBiosBootDevice {
# /.../
# check for devices which have 0x80 bios flag assigned
# ----
local IFS=$IFS_ORIG
local curd
local pred
for curd in $diskDevices;do
if [ $curd = "0x80" ];then
bios=$pred
return
fi
pred=$curd
done
}
#======================================
# searchBIOSBootDevice
#--------------------------------------
function searchBIOSBootDevice {
# /.../
# search for the boot device. The edd 0x80 information
# is used here but not trusted. Trusted is the MBR disk
# disk label which is compared with the kiwi written
# mbrid file in /boot/grub/ of the system image
# If we got a root device set via cmdline this value
# takes precedence over everything else though
# ----
local IFS=$IFS_ORIG
local file=/boot/mbrid
local ifix
local match_count
local matched
local curd
local mbrML
local mbrMB
local mbrI
local try_count=0
#======================================
# Check root variable
#--------------------------------------
if [ ! -z "$root" ];then
if ! waitForStorageDevice $root;then
Echo "Specified root device $root not found. Found devices:"
hwinfo --disk
systemException \
"root device not found... fatal !" \
"reboot"
fi
export biosBootDevice=$(dn $root)
if [ ! -e /config.partids ];then
echo "kiwi_RootPart=1" > /config.partids
fi
return 0
fi
#======================================
# Read mbrid from initrd
#--------------------------------------
if [ ! -e $file ];then
export biosBootDevice="Failed to find MBR identifier !"
return 1
fi
read mbrI < $file
#======================================
# Lookup until found
#--------------------------------------
while true;do
#======================================
# initialize variables
#--------------------------------------
ifix=0
match_count=0
try_count=$((try_count + 1))
#======================================
# stop after a long time of retry
#--------------------------------------
if [ $try_count -eq 15 ];then
export biosBootDevice="Failed to find boot device !"
return 1
fi
#======================================
# create device list
#--------------------------------------
lookupDiskDevices
lookupBiosBootDevice
#======================================
# Compare ID with MBR entry
#--------------------------------------
for curd in $diskDevices;do
if [ ! -b $curd ];then
continue
fi
mbrML=$(dd if=$curd bs=1 count=4 skip=$((0x1b8)) | \
hexdump -n4 -e '"0x%08x"')
mbrMB=$(echo $mbrML | \
sed 's/^0x\(..\)\(..\)\(..\)\(..\)$/0x\4\3\2\1/')
if [ "$mbrML" = "$mbrI" ] || [ "$mbrMB" = "$mbrI" ];then
ifix=1
matched=$curd
match_count=$(($match_count + 1))
if [ "$mbrML" = "$mbrI" ];then
export masterBootID=$mbrML
fi
if [ "$mbrMB" = "$mbrI" ];then
export masterBootID=$mbrMB
fi
if [ "$curd" = "$bios" ];then
export biosBootDevice=$curd
return 0
fi
fi
done
#======================================
# Multiple matches are bad
#--------------------------------------
if [ $match_count -gt 1 ];then
export biosBootDevice="multiple devices matches same MBR ID: $mbrI"
return 2
fi
#======================================
# Found it...
#--------------------------------------
if [ $ifix -eq 1 ];then
export biosBootDevice=$matched
return 0
fi
export biosBootDevice="No devices matches MBR ID: $mbrI !"
sleep 1
done
}
#======================================
# searchVolumeGroup
#--------------------------------------
function searchVolumeGroup {
# /.../
# search for a volume group named $kiwi_lvmgroup and if it can be
# found activate it while creating appropriate device nodes:
# /dev/$kiwi_lvmgroup/LVRoot and/or /dev/$kiwi_lvmgroup/LVComp
# return zero on success
# ----
local IFS=$IFS_ORIG
local vg_count=0
local vg_found
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
local rootdevice=$(ddn $imageDiskDevice $kiwi_RootPart)
probeFileSystem $rootdevice
if [ "$FSTYPE" = "luks" ];then
luksOpen $rootdevice
export haveLuks=yes
fi
for i in $(vgs --noheadings -o vg_name 2>/dev/null);do
vg_found=$(echo $i)
if [ "$vg_found" = "$kiwi_lvmgroup" ];then
vg_count=$((vg_count + 1))
fi
done
if [ $vg_count -gt 1 ];then
Echo "Duplicate VolumeGroup name $kiwi_lvmgroup found !"
Echo "$vg_count versions of this volume group exists"
Echo "The volume group name must be unique"
Echo "Please check your disks and rename/remove the duplicates"
systemException \
"VolumeGroup $kiwi_lvmgroup not unique !" \
"reboot"
fi
Echo "Activating $kiwi_lvmgroup volume group..."
vgchange -a y $kiwi_lvmgroup
}
#======================================
# deactivateVolumeGroup
#--------------------------------------
function deactivateVolumeGroup {
# /.../
# as signals/ioctls from earlier operations may
# not have been processed by the kernel or udev
# we may require a moment before 'vgchange -a n'
# return zero on success
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
udevPending
Echo "Deactivating $kiwi_lvmgroup volume group..."
vgchange -a n $kiwi_lvmgroup
udevPending
}
#======================================
# activateVolumeGroup
#--------------------------------------
function activateVolumeGroup {
# /.../
# activate volume group if LVM is present
# ----
local IFS=$IFS_ORIG
if [ ! "$kiwi_lvm" = "true" ];then
return 1
fi
udevPending
Echo "Activating $kiwi_lvmgroup volume group..."
vgchange -a y $kiwi_lvmgroup
udevPending
}
#======================================
# activateMDRaid
#--------------------------------------
function activateMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ];then
udevPending
Echo "Activating $kiwi_RaidDev mdraid array..."
mdadm --assemble --scan
waitForStorageDevice $kiwi_RaidDev
fi
}
#======================================
# resizeMDRaid
#--------------------------------------
function resizeMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ];then
udevPending
Echo "Resizing $kiwi_RaidDev mdraid array..."
mdadm --grow --size=max $kiwi_RaidDev
fi
}
#======================================
# resizeLVMPVs
#--------------------------------------
function resizeLVMPVs {
local IFS=$IFS_ORIG
local extendID=$1
local device=$(ddn $imageDiskDevice $extendID)
if [ ! -z "$kiwi_RaidDev" ];then
device=$kiwi_RaidDev
fi
if [ ! -z "$luksDeviceOpened" ];then
device=$luksDeviceOpened
fi
local unixDevice=$(getDiskDevice $device)
pvresize $unixDevice
}
#======================================
# deactivateMDRaid
#--------------------------------------
function deactivateMDRaid {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ] && [ -e $kiwi_RaidDev ];then
udevPending
Echo "Deactivating $kiwi_RaidDev mdraid array..."
mdadm --stop $kiwi_RaidDev
fi
}
#======================================
# zeroMDRaidSuperBlock
#--------------------------------------
function zeroMDRaidSuperBlock {
local IFS=$IFS_ORIG
if [ ! -z "$kiwi_RaidDev" ] && [ -e $kiwi_RaidDev ];then
local diskDevice=$1
for i in /dev/md*;do
test -b $i && mdadm --stop $i &>/dev/null
done
mdadm --zero-superblock $diskDevice &>/dev/null
fi
}
#======================================
# searchSwapSpace
#--------------------------------------
function searchSwapSpace {
# /.../
# search for a type=82 swap partition
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwinoswapsearch ];then
return
fi
local hwapp=/usr/sbin/hwinfo
local diskdevs=`$hwapp --disk | grep "Device File:" | cut -f2 -d:`
diskdevs=`echo $diskdevs | sed -e "s@(.*)@@"`
for diskdev in $diskdevs;do
for disknr in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15;do
id=$(partitionID $diskdev $disknr)
if [ "$id" = "82" ];then
echo $diskdev$disknr
return
fi
done
done
}
#======================================
# updateMTAB
#--------------------------------------
function updateMTAB {
local IFS=$IFS_ORIG
local prefix=$1
local umount=0
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umount=1
fi
if [ -e /proc/self/mounts ];then
pushd $prefix/etc >/dev/null
rm -f mtab && ln -s /proc/self/mounts mtab
popd >/dev/null
fi
if [ $umount -eq 1 ];then
umount /proc
fi
}
#======================================
# getNicNames
#--------------------------------------
function getNicNames {
local IFS=$IFS_ORIG
for nic in $(ip -4 -o link | cut -f2 -d:);do
if [ ! $nic = 'lo' ];then
echo $nic
fi
done
}
#======================================
# getHWAddress
#--------------------------------------
function getHWAddress {
local IFS=$IFS_ORIG
local iface=$1
ip addr show dev $iface |\
grep 'link\/ether ' | cut -f6 -d ' '
}
#======================================
# setupNic
#--------------------------------------
function setupNic {
local IFS=$IFS_ORIG
local iface=$1
local address=$2
local netmask=$3
ip addr flush dev $iface
ip addr add $address broadcast $netmask dev $iface
ip link set dev $iface up
}
#======================================
# probeNetworkCard
#--------------------------------------
function probeNetworkCard {
# /.../
# use hwinfo to probe for all network devices. The
# function will check for the driver which is needed
# to support the card and returns the information in
# the networkModule variable
# ----
local IFS="%"
local module=""
local hwicmd="/usr/sbin/hwinfo"
for i in \
`$hwicmd --netcard | grep "Driver [IA]" |
sed -es"@modprobe\(.*\)\"@\1%@" | tr -d "\n"`
do
if echo $i | grep -q "#0";then
module=`echo $i | cut -f2 -d"\"" | tr -d " "`
module=`echo $module | sed -es"@modprobe@@g"`
IFS=";"
for m in $module;do
if ! echo $networkModule | grep -q $m;then
if [ ! -z "$networkModule" ];then
networkModule="$networkModule:$m"
else
networkModule=$m
fi
fi
done
fi
done
networkModule=`echo $networkModule`
}
#======================================
# loadNetworkCard
#--------------------------------------
function loadNetworkCard {
# /.../
# load network module found by probeNetworkCard()
# ----
local IFS=$IFS_ORIG
local loaded=0
probeNetworkCard
IFS=":" ; for i in $networkModule;do
if [ ! -z "$i" ];then
modprobe $i 2>/dev/null
if [ $? = 0 ];then
loaded=1
fi
fi
done
}
#======================================
# loadNetworkCardS390
#--------------------------------------
function loadNetworkCardS390 {
# /.../
# search and include parameters from a parm file
# provided on the specified dasd id
# ----
local IFS=$IFS_ORIG
local host=$1
local skip="/etc/deactivate_s390_network_config_from_dasd"
local hostdev=/dev/disk/by-path/ccw-${host}
local parmfile_name=PARM-S11
if [ ! -z "$kiwi_oemvmcp_parmfile" ];then
parmfile_name=$kiwi_oemvmcp_parmfile
fi
Echo "Trying parm file lookup on DASD id: ${host}"
#======================================
# check if we got stopped
#--------------------------------------
if [ -e $skip ];then
Echo "Processing skipped by $skip"
rm -f $skip
return 1
fi
#======================================
# check for required tools
#--------------------------------------
if [ ! lookup cmsfscat &>/dev/null ];then
Echo "Can't find cmsfscat program required for loading"
return 1
fi
#======================================
# check for required kernel support
#--------------------------------------
# If loading vmcp fails we assume the support for it has been
# compiled into the kernel. If this is not the case we will run
# into an exception on 'vmcp query' which is the intended way
# to handle the error condition
modprobe vmcp &>/dev/null
#======================================
# bring host online
#--------------------------------------
if [ ! -b $hostdev ];then
dasd_configure ${host} 1 0
udevPending
if [ ! -b $hostdev ];then
Echo "Failed to activate DASD id: ${host}"
return 1
fi
fi
#======================================
# load parm file using cmsfscat
#--------------------------------------
Echo "Loading configuration file <UID>.${parmfile_name} from ${host}..."
local parmfile="$(vmcp query userid | cut -d ' ' -f 1).$parmfile_name"
if ! cmsfscat -d $hostdev -a "$parmfile" > /tmp/"$parmfile";then
Echo "Can't create /tmp/${parmfile} on DASD id: ${host}"
return 1
fi
#======================================
# import data into environment
#--------------------------------------
includeKernelParametersLowerCase "/tmp/$parmfile"
#======================================
# unbind host and cleanup
#--------------------------------------
rm -f "/tmp/$parmfile"
dasd_configure ${host} 0 0
return 0
}
#======================================
# dhclientImportInfo
#-------------------------------------
function dhclientImportInfo {
# /.../
# Import and export the information form the
# dhclient.lease file into the enviroment.
# ----
local IFS=$IFS_ORIG
if [ ! -n $1 ]; then
Echo "NULL argument passed to dhclientImportInfo"
return
fi
local lease=/var/lib/dhclient/$1.lease
export IPADDR=$(
cat $lease | grep 'fixed-address'|\
awk '{print $2}' | tr -d ';'
)
export NETMASK=$(
cat $lease | grep 'subnet-mask'|\
awk '{print $3}' | tr -d ';'
)
export GATEWAYS=$(
cat $lease | grep 'routers ' |\
awk '{print $3}' |tr -d ';'
)
export DOMAIN=$(
cat $lease | grep 'domain-name' | grep -v 'domain-name-server' |\
awk '{print $3}'| tr -d ';'
)
export DNSSERVERS=$(
cat $lease | grep 'domain-name-servers'|\
awk '{print $3}'| tr -d ';' | tr ',' ' '
)
export DHCPSIADDR=$(
cat $lease | grep 'dhcp-server-identifier'|\
awk '{print $3}'| tr -d ';' | tr ',' ' '
)
export DNS=$DNSSERVERS
export DHCPCHADDR=$(
ip link show $1| grep link | awk '{print $2}'
)
}
#======================================
# setupNetworkWicked
#--------------------------------------
function setupNetworkWicked {
# /.../
# assign DHCP IP address by using the wicked tool
# ----
local IFS=$IFS_ORIG
local nic_config
local dhcp_info
local wicked_dhcp4=/usr/lib/wicked/bin/wickedd-dhcp4
for try_iface in ${prefer_iface[*]}; do
# try DHCP_DISCOVER on all prefered interfaces
if ip link set dev $try_iface up;then
if [ $try_iface = "lo" ];then
continue
fi
waitForLinkUp $try_iface
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
$wicked_dhcp4 --debug all \
--test --test-output $dhcp_info $try_iface
if [ $? == 0 ] && [ -s $dhcp_info ];then
importFile < $dhcp_info
if setupNic $try_iface $IPADDR $NETMASK;then
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
fi
fi
fi
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# setup routing for first discovered
#--------------------------------------
for try_iface in $DHCPCD_STARTED; do
dhcp_info=/var/run/wicked/wicked-${try_iface}.info
if [ -s $dhcp_info ]; then
export PXE_IFACE=$try_iface
ip route add default dev $PXE_IFACE
if [ ! -z "$GATEWAYS" ];then
# Use first entry as primary gateway
local gw=$(echo $GATEWAYS | cut -f1 -d " ")
ip route change default via $gw dev $PXE_IFACE
fi
break
fi
done
#======================================
# fallback to local boot if possible
#--------------------------------------
if [ -z "$PXE_IFACE" ];then
if [ -e "$root" ];then
Echo "Can't get DHCP reply on any interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't get DHCP reply on any interface !" \
"reboot"
fi
fi
#======================================
# setup selected interface
#--------------------------------------
dhcp_info=/var/run/wicked/wicked-${PXE_IFACE}.info
if [ -s $dhcp_info ]; then
importFile < /var/run/wicked/wicked-${PXE_IFACE}.info
fi
}
#======================================
# setupNetworkDHCPCD
#--------------------------------------
function setupNetworkDHCPCD {
# /.../
# assign DHCP IP address by using the dhcpcd tool
# ----
local IFS=$IFS_ORIG
if [ $DHCPCD_HAVE_PERSIST -eq 0 ];then
# /.../
# older version of dhcpd which doesn't have the
# options we want to pass
# ----
unset opts
fi
mkdir -p /var/lib/dhcpcd
for try_iface in ${dev_list[*]}; do
# try DHCP_DISCOVER on all interfaces
dhcpcd $opts -T $try_iface > /var/lib/dhcpcd/dhcpcd-$try_iface.info &
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# wait for any preferred interface(s)
#--------------------------------------
for j in 1 2 ;do
for i in 1 2 3 4 5 6 7 8 9 10 11;do
for try_iface in ${prefer_iface[*]} ; do
if [ -s /var/lib/dhcpcd/dhcpcd-$try_iface.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info
then
break 3
fi
done
sleep 2
done
# /.../
# we are behind the dhcpcd timeout 20s so the only thing
# we can do now is to try again
# ----
for try_iface in $DHCPCD_STARTED; do
dhcpcd $opts -T $try_iface \
> /var/lib/dhcpcd/dhcpcd-$try_iface.info &
done
sleep 2
done
#======================================
# select interface from preferred list
#--------------------------------------
for try_iface in ${prefer_iface[*]} $DHCPCD_STARTED; do
if [ -s /var/lib/dhcpcd/dhcpcd-$try_iface.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info
then
export PXE_IFACE=$try_iface
eval `grep "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$try_iface.info`
rm /var/lib/dhcpcd/dhcpcd-$try_iface.info
# continue with the DHCP protocol on the selected interface
if [ -e /var/run/dhcpcd-$PXE_IFACE.pid ];then
rm -f /var/run/dhcpcd-$PXE_IFACE.pid
fi
if [ $DHCPCD_HAVE_PERSIST -eq 0 ];then
# /.../
# older version of dhcpd which doesn't provide
# an option to request a specific IP address
# ----
dhcpcd $opts $PXE_IFACE 2>&1
else
dhcpcd $opts -r $IPADDR $PXE_IFACE 2>&1
fi
break
fi
done
#======================================
# fallback to local boot if possible
#--------------------------------------
if [ -z "$PXE_IFACE" ];then
if [ -e "$root" ];then
Echo "Can't get DHCP reply on any interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't get DHCP reply on any interface !" \
"reboot"
fi
fi
#======================================
# wait for iface to finish negotiation
#--------------------------------------
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20;do
if [ -s /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
then
break
fi
sleep 2
done
#======================================
# setup selected interface
#--------------------------------------
setupNic lo 127.0.0.1/8 255.0.0.0
if [ -s /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info ] &&
grep -q "^IPADDR=" /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info; then
importFile < /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
fi
}
#======================================
# setupNetworkDHCLIENT
#--------------------------------------
function setupNetworkDHCLIENT {
# /.../
# assign DHCP IP address by using the dhclient tool
# ----
local IFS=$IFS_ORIG
local dhclient_opts=" -4 -1 -q"
mkdir -p /var/lib/dhclient
mkdir -p /var/run
for try_iface in ${dev_list[*]}; do
# try DHCP_DISCOVER on all interfaces
dhclient $dhclient_opts \
-lf /var/lib/dhclient/${try_iface}.lease \
-pf /var/run/dhclient-${try_iface}.pid ${try_iface}
DHCPCD_STARTED="$DHCPCD_STARTED $try_iface"
done
if [ -z "$DHCPCD_STARTED" ];then
if [ -e "$root" ];then
Echo "Failed to setup DHCP network interface !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to setup DHCP network interface !" \
"reboot"
fi
fi
#======================================
# wait for any preferred interface(s)
#--------------------------------------
for j in 1 2 ;do
for i in 1 2 3 4 5 6 7 8 9 10 11;do
for try_iface in ${prefer_iface[*]} ; do
if [ -f /var/lib/dhclient/${try_iface}.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/${try_iface}.lease
then
break 3
fi
done
sleep 2
done
# /.../
# we are behind the dhclient timeout 20s so the only thing
# we can do now is to try again
# ----
for try_iface in $DHCPCD_STARTED; do
dhclient $dhclient_opts \
-lf /var/lib/dhclient/${try_iface}.lease \
-pf /var/run/dhclient-${try_iface}.pid ${try_iface}
done
sleep 2
done
#======================================
# select interface from preferred list
#--------------------------------------
for try_iface in ${prefer_iface[*]} $DHCPCD_STARTED; do
if [ -f /var/lib/dhclient/${try_iface}.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/${try_iface}.lease
then
export PXE_IFACE=$try_iface
export IPADDR=$(
cat /var/lib/dhclient/${try_iface}.lease |\
grep 'fixed-address'| awk '{print $2}' | tr -d ';'
)
break
fi
done
#======================================
# setup selected interface
#--------------------------------------
setupNic lo 127.0.0.1/8 255.0.0.0
if [ -f /var/lib/dhclient/$PXE_IFACE.lease ] &&
grep -q "fixed-address" /var/lib/dhclient/$PXE_IFACE.lease; then
dhclientImportInfo "$PXE_IFACE"
fi
}
#======================================
# setupNetwork
#--------------------------------------
function setupNetwork {
# /.../
# probe for the existing network interface names and
# hardware addresses. Match the BOOTIF address from PXE
# to the correct linux interface name. Setup the network
# interface using a dhcp request. On success the dhcp
# info file is imported into the current shell environment
# and the nameserver information is written to
# /etc/resolv.conf
# ----
local IFS=$IFS_ORIG
#======================================
# local variable setup
#--------------------------------------
local MAC=0
local DEV=0
local mac_list=0
local dev_list=0
local index=0
local hwicmd=/usr/sbin/hwinfo
local opts="--noipv4ll -p"
local try_iface
export DHCPCD_STARTED=""
#======================================
# detect iface and HWaddr
#--------------------------------------
for DEV in $(getNicNames);do
MAC=$(getHWAddress $DEV)
mac_list[$index]=$MAC
dev_list[$index]=$DEV
index=$((index + 1))
done
if [ $index = 0 ];then
systemException \
"No network interfaces found" \
"reboot"
fi
#======================================
# preselect first nic as a start
#--------------------------------------
export prefer_iface=${dev_list[0]}
#======================================
# continue to be smarter in nic check
#--------------------------------------
if [ -z "$BOOTIF" ];then
# /.../
# there is no PXE boot interface information. We will use
# the first interface that responds to dhcp
# ----
prefer_iface=${dev_list[*]}
else
# /.../
# evaluate the information from the PXE boot interface
# if we found the MAC in the list the appropriate interface
# name is assigned.
# ----
index=0
BOOTIF=$(echo $BOOTIF | cut -f2- -d - | tr "-" ":")
for i in ${mac_list[*]};do
list_iface=$(echo $i | tr [:upper:] [:lower:])
if [ $list_iface = $BOOTIF ];then
prefer_iface=${dev_list[$index]}
fi
index=$((index + 1))
done
fi
#======================================
# ask for an address
#--------------------------------------
if lookup wicked &>/dev/null; then
setupNetworkWicked
elif lookup dhcpcd &>/dev/null; then
setupNetworkDHCPCD
elif lookup dhclient &>/dev/null; then
setupNetworkDHCLIENT
else
Echo "No supported DHCP client tool found (dhcpcd/dhclient)"
return 1
fi
#======================================
# check if we got an address
#--------------------------------------
if [ -z "$IPADDR" ];then
if [ -e "$root" ];then
Echo "Can't assign IP addr via dhcp info: dhcpcd-$PXE_IFACE.info !"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Can't assign IP addr via dhcp info: dhcpcd-$PXE_IFACE.info !" \
"reboot"
fi
fi
if [ -z "$DOMAIN" ] && [ -n "$DNSDOMAIN" ];then
export DOMAIN=$DNSDOMAIN
fi
echo "search $DOMAIN" > /etc/resolv.conf
if [ -z "$DNS" ] && [ -n "$DNSSERVERS" ];then
export DNS=$DNSSERVERS
fi
IFS="," ; for i in $DNS;do
echo "nameserver $i" >> /etc/resolv.conf
done
export DHCPCHADDR=$(
ip link show dev $PXE_IFACE | grep link | awk '{print $2}'
)
}
#======================================
# releaseNetwork
#--------------------------------------
function releaseNetwork {
# /.../
# release network setup by dhcpcd and free the lease
# Do that only for _non_ network root devices
# ----
local IFS=$IFS_ORIG
if [ -z "$NFSROOT" ] && [ -z "$NBDROOT" ] && [ -z "$AOEROOT" ];then
if lookup dhcpcd &>/dev/null; then
#======================================
# unset dhcp info variables
#--------------------------------------
unsetFile < /var/lib/dhcpcd/dhcpcd-$PXE_IFACE.info
#======================================
# free the lease and the cache
#--------------------------------------
dhcpcd -k $PXE_IFACE
elif lookup dhclient &>/dev/null; then
#======================================
# unset dhclient info variables
#--------------------------------------
unset IPADDR
unset GATEWAYS
unset DNSSERVERS
unset NETMASK
unset DOMAIN
unset DNSSERVERS
unset DNS
unset DHCPCHADDR
#======================================
# free the lease and the cache
#--------------------------------------
kill -9 $(cat /var/run/dhclient-$PXE_IFACE.pid )
dhclient -r \
-lf /var/lib/dhclient/$PXE_IFACE.lease $PXE_IFACE
fi
#======================================
# remove sysconfig state information
#--------------------------------------
rm -rf /dev/.sysconfig/network
#======================================
# unset host information
#--------------------------------------
unset HOSTNAME
fi
}
#======================================
# setupNetworkInterfaceS390
#--------------------------------------
function setupNetworkInterfaceS390 {
# /.../
# bring up the network card according to the parm file
# parameters and create the correspondent udev rules
# needs includeKernelParametersLowerCase to be run
# because parm file parameters are case insensitive
# ----
local IFS=$IFS_ORIG
case "$instnetdev" in
"osa"|"hsi")
local qeth_cmd="/sbin/qeth_configure"
if [ "$layer2" = "1" ];then
qeth_cmd="$qeth_cmd -l"
fi
if [ -n "$portname" ];then
qeth_cmd="$qeth_cmd -p $portname"
fi
if [ -n "$portno" ];then
qeth_cmd="$qeth_cmd -n $portno"
fi
qeth_cmd="$qeth_cmd $readchannel $writechannel"
if [ -n "$datachannel" ];then
qeth_cmd="$qeth_cmd $datachannel"
fi
eval $qeth_cmd 1
;;
"ctc")
/sbin/ctc_configure $readchannel $writechannel 1 $ctcprotocol
;;
"iucv")
/sbin/iucv_configure $iucvpeer 1
;;
*)
if [ -e "$root" ];then
Echo "Unknown s390 network type: $instnetdev"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Unknown s390 network type: $instnetdev" \
"reboot"
fi
;;
esac
if [ ! $? = 0 ];then
if [ -e "$root" ];then
Echo "Failed to bring up the network: $instnetdev"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to bring up the network: $instnetdev" \
"reboot"
fi
fi
udevPending
}
#======================================
# convertCIDRToNetmask
#--------------------------------------
function convertCIDRToNetmask {
# /.../
# convert the CIDR part to a useable netmask
# ----
local IFS=$IFS_ORIG
local cidr=$1
local count=0
for count in `seq 1 4`;do
if [ $((cidr / 8)) -gt 0 ];then
echo -n 255
else
local remainder=$((cidr % 8))
if [ $remainder -gt 0 ];then
echo -n $(( value = 256 - (256 >> remainder)))
else
echo -n 0
fi
fi
cidr=$((cidr - 8))
if [ $count -lt 4 ];then
echo -n .
fi
done
echo
}
#======================================
# setupNetworkStatic
#--------------------------------------
function setupNetworkStatic {
# /.../
# configure static network either bring it up manually
# or save the configuration depending on 'up' parameter
# ----
local IFS=$IFS_ORIG
local up=$1
if [[ $hostip =~ / ]];then
#======================================
# convert CIDR to netmask
#--------------------------------------
netmask=$(convertCIDRToNetmask $(echo $hostip | cut -f2 -d/))
fi
if [ "$up" = "1" ];then
#======================================
# activate network
#--------------------------------------
# Please note: It is assumed the last interface in the list is the
# one which should receive the interface config. While the loopback
# interface is skipped this could still result in an unexpected
# behavior.
local iface=$(
cat /proc/net/dev|grep -v lo:|tail -n1|cut -d':' -f1|sed 's/ //g'
)
if ! setupNic $iface $hostip $netmask;then
if [ -e "$root" ];then
Echo "Failed to set up the network: $iface"
Echo "Try fallback to local boot on: $root"
LOCAL_BOOT=yes
return
else
systemException \
"Failed to set up the network: $iface" \
"reboot"
fi
fi
export iface_static=$iface
elif [ ! -z $iface_static ];then
#======================================
# write network setup
#--------------------------------------
local netFile="/etc/sysconfig/network/ifcfg-$iface_static"
echo "BOOTPROTO='static'" > $netFile
echo "STARTMODE='auto'" >> $netFile
echo "IPADDR='$hostip'" >> $netFile
echo "NETMASK='$netmask'" >> $netFile
if [ -n "$broadcast" ];then
echo "BROADCAST='$broadcast'" >> $netFile
fi
if [ -n "$pointopoint" ];then
echo "REMOTE_IPADDR='$pointopoint'" >> $netFile
fi
fi
setupDefaultGateway $up
setupDNS
}
#======================================
# setupDefaultGateway
#--------------------------------------
function setupDefaultGateway {
# /.../
# setup default gateway. either set the route or save
# the configuration depending on 'up' parameter
# ----
local IFS=$IFS_ORIG
local up=$1
if [ "$up" == "1" ];then
#======================================
# activate GW route
#--------------------------------------
ip route add default via $gateway
else
#======================================
# write GW configuration
#--------------------------------------
echo "default $gateway - -" > "/etc/sysconfig/network/routes"
fi
}
#======================================
# setupDNS
#--------------------------------------
function setupDNS {
# /.../
# setup DNS. write data to resolv.conf
# ----
local IFS=$IFS_ORIG
local file="/etc/resolv.conf"
if [ -n "$domain" ];then
export DOMAIN=$domain
local line="search $domain"
if ! grep -q $line $file;then
echo "$line" >> "$file"
fi
fi
if [ -n "$nameserver" ];then
export DNS=$nameserver
IFS="," ; for i in $nameserver;do
local line="nameserver $i"
if ! grep -q $line $file;then
echo "$line" >> "$file"
fi
done
fi
}
#======================================
# fetchImageMD5
#--------------------------------------
function fetchImageMD5 {
# /.../
# download image.md5 file either from the network
# or from a local cache directory if specified by
# KIWI_LOCAL_CACHE_DIR.
# ----
local IFS=$IFS_ORIG
local imageMD5s="image/$1-$2.md5"
local imageServer=$3
local imageBlkSize=$4
local error=0
[ -z "$imageServer" ] && imageServer=$SERVER
[ -z "$imageBlkSize" ] && imageBlkSize=8192
#======================================
# Check for MD5 in the local cache
#--------------------------------------
if [ -n "$KIWI_LOCAL_CACHE_DIR" ];then
local cached_md5="$KIWI_LOCAL_CACHE_DIR/$imageMD5s"
if [ -f "$cached_md5" ];then
read sum_local blocks blocksize zblocks zblocksize < "$cached_md5"
fi
fi
#======================================
# Download latest MD5 from the network
#--------------------------------------
fetchFile $imageMD5s /etc/image.md5 uncompressed $imageServer
#======================================
# Check results if download failed
#--------------------------------------
if test $loadCode != 0 || ! loadOK "$loadStatus"; then
Echo "Download of $imageMD5s failed: $loadStatus"
if [ -z "$sum_local" ]; then
Echo "Fatal: No cache copy available"
error=1
else
Echo "Using cache copy: $KIWI_LOCAL_CACHE_DIR/$imageMD5s"
cp "$KIWI_LOCAL_CACHE_DIR/$imageMD5s" /etc/image.md5
error=0
fi
fi
#======================================
# Check error state
#--------------------------------------
# failed MD5 download and no cache copy is fatal
if [ $error -eq 1 ];then
systemException \
"Failed to provide image MD5 data" \
"reboot"
fi
#======================================
# Read in provided MD5 data
#--------------------------------------
read sum1 blocks blocksize zblocks zblocksize < /etc/image.md5
}
#======================================
# updateNeeded
#--------------------------------------
function updateNeeded {
# /.../
# check the contents of the IMAGE key and compare the
# image version file as well as the md5 sum of the installed
# and the available image on the tftp server
# ----
#======================================
# Local variables
#--------------------------------------
local IFS=$IFS_ORIG
local count=0
local sum2
local installed
local field
local atversion
local versionFile
local imageName
local imageVersion
local imageServer
local imageBlkSize
local imageZipped
local prefix=/mnt
#======================================
# Global variables
#--------------------------------------
SYSTEM_INTEGRITY=""
SYSTEM_MD5STATUS=""
#======================================
# Check system update status via md5
#--------------------------------------
IFS="," ; for i in $IMAGE;do
field=0
IFS=";" ; for n in $i;do
case $field in
0) 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
atversion="$imageName-$imageVersion"
versionFile="$prefix/etc/ImageVersion-$atversion"
IFS=" "
if [ -f "$versionFile" ];then
read installed sum2 < $versionFile
fi
fetchImageMD5 \
"$imageName" "$imageVersion" \
"$imageServer" "$imageBlkSize"
if [ ! -z "$sum1" ];then
SYSTEM_MD5STATUS="$SYSTEM_MD5STATUS:$sum1"
else
SYSTEM_MD5STATUS="$SYSTEM_MD5STATUS:none"
fi
if [ ! -z "$1" ];then
continue
fi
if test "$count" = 1;then
if test "$SYSTEM_INTEGRITY" = ":clean";then
Echo "Main OS image update needed"
Echo -b "Forcing download for multi image session"
RELOAD_IMAGE="yes"
fi
fi
count=$(($count + 1))
Echo "Checking update status for image: $imageName"
if test ! -z $RELOAD_IMAGE;then
Echo -b "Update forced via RELOAD_IMAGE..."
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
continue
fi
if test ! -f $versionFile;then
Echo -b "Update forced: /etc/ImageVersion-$atversion not found"
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
RELOAD_IMAGE="yes"
continue
fi
Echo -b "Current: $atversion Installed: $installed"
if test "$atversion" = "$installed";then
if test "$sum1" = "$sum2";then
Echo -b "Update status: Fine"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:fine"
continue
fi
Echo -b "Image Update for image [ $imageName ] needed"
Echo -b "Image version equals but md5 checksum failed"
Echo -b "This means the contents of the new image differ"
RELOAD_IMAGE="yes"
else
Echo -b "Image Update for image [ $imageName ] needed"
Echo -b "Name and/or image version differ"
RELOAD_IMAGE="yes"
fi
Echo -b "Update status: Clean"
SYSTEM_INTEGRITY="$SYSTEM_INTEGRITY:clean"
done
SYSTEM_INTEGRITY=`echo $SYSTEM_INTEGRITY | cut -f2- -d:`
SYSTEM_MD5STATUS=`echo $SYSTEM_MD5STATUS | cut -f2- -d:`
}
#======================================
# cleanSweep
#--------------------------------------
function cleanSweep {
# /.../
# zero out a the given disk device
# ----
local IFS=$IFS_ORIG
local diskDevice=$1
dd if=/dev/zero of=$diskDevice bs=32M >/dev/null
}
#======================================
# fdasdGetPartitionID
#--------------------------------------
function fdasdGetPartitionID {
local IFS=$IFS_ORIG
local device=$1
local partid=$2
local count=1
for i in $(fdasd -s -p $device | grep -E '^[ ]+\/' |\
awk -v OFS=":" '$1=$1' | cut -f7 -d:)
do
if [ $count -eq $partid ];then
if [ $i = "native" ];then
echo 83
elif [ $i = "swap" ];then
echo 82
else
# /.../
# don't know this partition information
# assume it's a linux partition
# ----
echo 83
fi
return
fi
count=$((count + 1))
done
}
#======================================
# partedGetPartitionID
#--------------------------------------
function partedGetPartitionID {
# /.../
# prints the partition ID for the given device and number
# In case of a GPT map to the GUID code from the sgdisk
# utility. If sgdisk is not available map to the kiwi
# fdisk compatible hex id's which uses ee for any kind
# of unknown GPT partition entry
# ----
local IFS=$IFS_ORIG
local parted=$(parted -m -s $1 print | grep -v Warning:)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
if [ -z "$plabel" ];then
# can't find a partition label for this disk
echo xx
return
fi
if [[ $plabel =~ gpt ]];then
plabel=gpt
fi
if [ ! $plabel = "gpt" ];then
parted -m -s $1 print | grep ^$2: | cut -f2 -d= |\
sed -e 's@[,; ]@@g' | tr -d 0
else
local name=$(parted -m -s $1 print | grep ^$2: | cut -f6 -d:)
if lookup sgdisk &>/dev/null;then
# map to short gdisk code
echo $(sgdisk -p $1 | grep -E "^ $2") | cut -f6 -d ' '
elif [ "$name" = "lxroot" ];then
# map lxroot to MBR type 83 (linux)
echo 83
elif [ "$name" = "lxswap" ];then
# map lxswap to MBR type 82 (linux swap)
echo 82
elif [ "$name" = "lxlvm" ];then
# map lxlvm to MBR type 8e (linux LVM)
echo 8e
elif [ "$name" = "UEFI" ];then
# map UEFI to MBR type 6 (fat 16)
echo 6
elif [ "$name" = "legacy" ];then
# map bios grub legacy partition to MBR type ef (EFI)
echo ef
else
# map anything else to ee (GPT)
echo ee
fi
fi
}
#======================================
# partitionID
#--------------------------------------
function partitionID {
local IFS=$IFS_ORIG
local diskDevice=$1
local diskNumber=$2
if [ $PARTITIONER = "fdasd" ];then
fdasdGetPartitionID $diskDevice $diskNumber
else
partedGetPartitionID $diskDevice $diskNumber
fi
}
#======================================
# partitionSize
#--------------------------------------
function partitionSize {
local IFS=$IFS_ORIG
local diskDevice=$1
local psizeBytes
local psizeKBytes
if [ -z "$diskDevice" ] || [ ! -e "$diskDevice" ];then
echo 1 ; return 1
fi
psizeBytes=$(blockdev --getsize64 $diskDevice)
psizeKBytes=$((psizeBytes / 1024))
echo $psizeKBytes
}
#======================================
# kernelList
#--------------------------------------
function kernelList {
# /.../
# check for all installed kernels whether there are valid
# links to the initrd and kernel files. The function will
# save the valid linknames in the variable KERNEL_LIST
# ----
local IFS=$IFS_ORIG
local prefix=$1
local kcount=1
local kname=""
local kernel=""
local initrd=""
local kpair=""
local krunning=`uname -r`
KERNEL_LIST=""
KERNEL_NAME=""
KERNEL_PAIR=""
#======================================
# search running kernel first
#--------------------------------------
if [ -d $prefix/lib/modules/$krunning ];then
for name in vmlinux vmlinuz image uImage;do
if [ -f $prefix/boot/$name-$krunning ];then
kernel=$name-$krunning
initrd=initrd-$krunning
break
fi
done
if [ ! -z "$kernel" ];then
KERNEL_PAIR=$kernel:$initrd
KERNEL_NAME[$kcount]=$krunning
KERNEL_LIST=$KERNEL_PAIR
kcount=$((kcount+1))
fi
fi
#======================================
# search for other kernels
#--------------------------------------
for i in $prefix/lib/modules/*;do
if [ ! -d $i ];then
continue
fi
unset kernel
unset initrd
kname=$(basename "$i")
if [ "$kname" = $krunning ];then
continue
fi
for name in vmlinux vmlinuz image uImage;do
for k in $prefix/boot/$name-${i##*/}; do
if [ -f $k ];then
kernel=${k##*/}
initrd=initrd-${i##*/}
break 2
fi
done
done
if [ ! -z "$kernel" ];then
kpair=$kernel:$initrd
KERNEL_NAME[$kcount]=$kname
KERNEL_LIST=$KERNEL_LIST,$kpair
kcount=$((kcount+1))
fi
done
#======================================
# what if no kernel was found...
#--------------------------------------
if [ -z "$KERNEL_LIST" ];then
# /.../
# the system image doesn't provide the kernel and initrd but
# if there is a downloaded kernel and initrd from the KIWI_INITRD
# setup. the kernelList function won't find initrds that gets
# downloaded over tftp so make sure the vmlinu[zx]/initrd combo
# gets added as well as the linux.vmx/initrd.vmx combo
# ----
if [ -e $prefix/boot/vmlinuz ];then
KERNEL_LIST="vmlinuz:initrd"
KERNEL_NAME[1]=vmlinuz
fi
if [ -e $prefix/boot/vmlinux ];then
KERNEL_LIST="vmlinux:initrd"
KERNEL_NAME[1]=vmlinux
fi
if [ -e $prefix/boot/linux.vmx ];then
KERNEL_LIST="vmlinux:initrd"
KERNEL_NAME[1]="vmlinux"
fi
fi
KERNEL_LIST=$(echo $KERNEL_LIST | sed -e s@^,@@)
export KERNEL_LIST
export KERNEL_NAME
export KERNEL_PAIR
}
#======================================
# validateSize
#--------------------------------------
function validateSize {
# /.../
# check if the image fits into the requested partition.
# An information about the sizes is printed out
# ----
local IFS=$IFS_ORIG
haveBytes=$(partitionSize $imageDevice)
haveBytes=$((haveBytes * 1024))
haveMByte=$((haveBytes / 1048576))
needBytes=$((blocks * blocksize))
needMByte=$((needBytes / 1048576))
Echo "Have size: $imageDevice -> $haveBytes Bytes [ $haveMByte MB ]"
Echo "Need size: $needBytes Bytes [ $needMByte MB ]"
if test $haveBytes -gt $needBytes;then
return 0
fi
return 1
}
#======================================
# validateBlockSize
#--------------------------------------
function validateBlockSize {
# /.../
# check the block size value. atftp limits to a maximum of
# 65535 blocks, so the block size must be checked according
# to the size of the image. The block size itself is also
# limited to 65464 bytes
# ----
local IFS=$IFS_ORIG
local blkTest
local nBlk
if [ -z "$zblocks" ] && [ -z "$blocks" ];then
# md5 file not yet read in... skip
return
fi
if [ ! -z "$zblocks" ];then
isize=$((zblocks * zblocksize))
else
isize=$((blocks * blocksize))
fi
local IFS=' '
testBlkSizes="32768 61440 65464"
if [ "$imageBlkSize" -gt 0 ]; then
testBlkSizes="$imageBlkSize $testBlkSizes"
fi
for blkTest in $testBlkSizes ; do
nBlk=$((isize / blkTest))
if [ $nBlk -lt 65535 ] ; then
imageBlkSize=$blkTest
return
fi
done
systemException \
"Maximum blocksize for atftp protocol exceeded" \
"reboot"
}
#======================================
# loadOK
#--------------------------------------
function loadOK {
# /.../
# check the output of the atftp command, unfortunately
# there is no useful return code to check so we have to
# check the output of the command
# ----
local IFS=$IFS_ORIG
for i in "File not found" "aborting" "no option named" "unknown host" ; do
if echo "$1" | grep -q "$i" ; then
return 1
fi
done
return 0
}
#======================================
# includeKernelParameters
#--------------------------------------
function includeKernelParameters {
# /.../
# include the parameters from /proc/cmdline into
# the current shell environment
# ----
local IFS=$IFS_ORIG
local file=$1
local translate=$2
if [ -z "$file" ];then
file=/proc/cmdline
fi
for i in $(cat $file);do
if ! echo $i | grep -q "=";then
continue
fi
kernelKey=`echo $i | cut -f1 -d=`
#======================================
# convert parameters to lowercase if required
#--------------------------------------
if [ "$translate" = "lowercase" ];then
kernelKey=`echo $kernelKey | tr [:upper:] [:lower:]`
fi
kernelVal=`echo $i | cut -f2 -d=`
eval export $kernelKey=$kernelVal
done
if [ ! -z "$kiwikernelmodule" ];then
kiwikernelmodule=`echo $kiwikernelmodule | tr , " "`
fi
if [ ! -z "$kiwibrokenmodule" ];then
kiwibrokenmodule=`echo $kiwibrokenmodule | tr , " "`
fi
if \
[ ! -z "$kiwisplitroot_size" ] && \
[[ $kiwisplitroot_size = *[[:digit:]]* ]] && \
[ $kiwisplitroot_size -gt $splitroot_size ]
then
splitroot_size=$kiwisplitroot_size
fi
if [ ! -z "$ramdisk_size" ];then
local modfile=/etc/modprobe.d/99-local.conf
if [ ! -f $modfile ];then
modfile=/etc/modprobe.conf.local
fi
if [ -f $modfile ];then
if grep -q rd_size $modfile;then
sed -i -e s"@rd_size=.*@rd_size=$ramdisk_size@" $modfile
else
echo "options brd rd_size=$ramdisk_size" >> $modfile
fi
fi
fi
if [ ! -z "$lang" ];then
# lang set on the commandline, e.g by the boot theme
export DIALOG_LANG=$lang
elif [ ! -z "$kiwi_language" ];then
# lang set from the XML data, first item is the primary language
export DIALOG_LANG=$(echo $kiwi_language | cut -f1 -d,)
fi
}
#======================================
# includeKernelParametersLowerCase
#--------------------------------------
function includeKernelParametersLowerCase {
includeKernelParameters "$1" "lowercase"
}
#======================================
# umountSystem
#--------------------------------------
function umountSystem {
local IFS=$IFS_ORIG
local retval=0
local mountList="/mnt /read-only /read-write"
#======================================
# umount boot device
#--------------------------------------
if [ ! -z "$imageBootDevice" ];then
umount $imageBootDevice 1>&2
fi
#======================================
# umount mounted mountList paths
#--------------------------------------
for mpath in $(cat /proc/mounts | cut -f2 -d " ");do
for umount in $mountList;do
if [ "$mpath" = "$umount" ];then
if ! umount $mpath >/dev/null;then
if ! umount -l $mpath >/dev/null;then
retval=1
fi
fi
fi
done
done
#======================================
# remove mount points
#--------------------------------------
for dir in "/read-only" "/read-write" "/xino";do
test -d $dir && rmdir $dir 1>&2
done
return $retval
}
#======================================
# isFSTypeReadOnly
#--------------------------------------
function isFSTypeReadOnly {
local IFS=$IFS_ORIG
if [ "$FSTYPE" = "squashfs" ];then
export unionFST=overlay
return 0
fi
if [ "$FSTYPE" = "clicfs" ];then
export unionFST=clicfs
return 0
fi
return 1
}
#======================================
# kiwiMount
#--------------------------------------
function kiwiMount {
local IFS=$IFS_ORIG
local src=$1
local dst=$2
local opt=$3
local lop=$4
#======================================
# load not autoloadable fs modules
#--------------------------------------
modprobe squashfs &>/dev/null
#======================================
# store old FSTYPE value
#--------------------------------------
if [ ! -z "$FSTYPE" ];then
FSTYPE_SAVE=$FSTYPE
fi
#======================================
# decide for a mount method
#--------------------------------------
if [ ! -z "$lop" ];then
src=$(loop_setup $lop)
if [ ! -e $src ]; then
return 1
fi
# /.../
# for iso images the root device name is set via
# config.isoclient. But in case of a filename the
# root device must be loop mounted and the loop
# setup creates the root device which is stored
# in imageDevice for the isoboot code
# ----
imageDevice=$src
fi
#======================================
# probe filesystem
#--------------------------------------
if [ ! "$FSTYPE" = "nfs" ];then
probeFileSystem $src
fi
if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ];then
FSTYPE="auto"
fi
if [ "$FSTYPE" = "zfs" ];then
if [ -b $src ];then
if ! zpool import -N kiwipool >/dev/null;then
return 1
fi
else
local basedir=$(dirname $src)
if ! zpool import -N -d $basedir kiwipool;then
return 1
fi
fi
zfs set mountpoint=$dst kiwipool/ROOT/system-1 && zfs mount -a
if [ ! $? = 0 ];then
return 1
fi
else
if ! mount -t $FSTYPE $opt $src $dst >/dev/null;then
return 1
fi
fi
if [ ! -z "$FSTYPE_SAVE" ];then
FSTYPE=$FSTYPE_SAVE
fi
return 0
}
#======================================
# setupReadWrite
#--------------------------------------
function setupReadWrite {
# /.../
# check/create read-write filesystem used for
# overlay data
# ----
local IFS=$IFS_ORIG
local rwDir=/read-write
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
mkdir -p $rwDir
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
if [ "$RELOAD_IMAGE" = "yes" ] || \
! mount -o ro $rwDevice $rwDir &>/dev/null
then
#======================================
# store old FSTYPE value
#--------------------------------------
if [ ! -z "$FSTYPE" ];then
FSTYPE_SAVE=$FSTYPE
fi
#======================================
# probe filesystem
#--------------------------------------
probeFileSystem $rwDevice
if [ ! "$FSTYPE" = "unknown" ];then
Echo "Checking filesystem for RW data on $rwDevice..."
e2fsck -p $rwDevice
fi
#======================================
# restore FSTYPE
#--------------------------------------
if [ ! -z "$FSTYPE_SAVE" ];then
FSTYPE=$FSTYPE_SAVE
fi
if [ "$RELOAD_IMAGE" = "yes" ] || \
! mount -o ro $rwDevice $rwDir &>/dev/null
then
Echo "Creating filesystem for RW data on $rwDevice..."
if ! mkfs.ext3 -F $rwDevice >/dev/null;then
Echo "Failed to create ext3 filesystem"
return 1
fi
e2fsck -p $rwDevice >/dev/null
fi
else
umount $rwDevice
fi
fi
return 0
}
#======================================
# mountSystemSeedBtrFS
#--------------------------------------
function mountSystemSeedBtrFS {
local IFS=$IFS_ORIG
local loopf=$1
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local prefix=/mnt
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -e $rwDevice ];then
rwDevice=/dev/ram1
fi
#======================================
# mount/check btrfs file
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
#======================================
# btrfs exported via NFS
#--------------------------------------
if ! kiwiMount "$roDevice" "$prefix" "" $loopf;then
Echo "Failed to mount NFS filesystem"
return 1
fi
else
#======================================
# mount btrfs container
#--------------------------------------
if [ -z "$loopf" ];then
loopf=$roDevice
fi
if ! mount -o loop,$kiwi_fsmountoptions $loopf $prefix; then
Echo "Failed to mount btrfs filesystem"
return 1
fi
fi
#======================================
# add seed device
#--------------------------------------
if ! btrfs device add $rwDevice $prefix; then
Echo "Failed to attach btrfs seed device"
return 1
fi
if ! mount -o remount,rw $prefix; then
Echo "Failed to remount read-write"
return 1
fi
return 0
}
#======================================
# mountSystemUnionFS
#--------------------------------------
function mountSystemUnionFS {
local IFS=$IFS_ORIG
local loopf=$1
local roDir=/read-only
local rwDir=/read-write
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local unionFST=`echo $UNIONFS_CONFIG | cut -d , -f 3`
local prefix=/mnt
#======================================
# load fuse module
#--------------------------------------
modprobe fuse &>/dev/null
#======================================
# create overlay mount points
#--------------------------------------
mkdir -p $roDir
mkdir -p $rwDir
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# mount read only device
#--------------------------------------
if ! kiwiMount "$roDevice" "$roDir" "" $loopf;then
Echo "Failed to mount read only filesystem"
return 1
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -z "$kiwi_ramonly" ];then
rwDevice=tmpfs
fi
if [ "$rwDevice" = "tmpfs" ];then
#======================================
# write into tmpfs
#--------------------------------------
if ! mount -t tmpfs tmpfs $rwDir >/dev/null;then
Echo "Failed to mount tmpfs read/write filesystem"
return 1
fi
else
#======================================
# write to another device
#--------------------------------------
if [ "$roDevice" = "nfs" ];then
rwDevice="-o nolock,rw $nfsRootServer:$rwDevice"
fi
if [ ! "$roDevice" = "nfs" ] && ! setupReadWrite; then
return 1
fi
if ! kiwiMount "$rwDevice" "$rwDir";then
Echo "Failed to mount read/write filesystem"
return 1
fi
fi
#======================================
# overlay mount the locations
#--------------------------------------
if [ "$unionFST" = "overlay" ];then
#======================================
# setup overlayfs mount
#--------------------------------------
local opts="rw,lowerdir=$roDir,upperdir=$rwDir"
if ! mount -t overlayfs -o $opts overlayfs $prefix;then
# overlayfs in version >= v22 behaves differently
# + renamed from overlayfs to overlay
# + requires a workdir to become mounted
# + requires workdir and upperdir to reside under the same mount
# + requires workdir and upperdir to be in separate subdirs
mkdir -p $rwDir/work
mkdir -p $rwDir/rw
opts="rw,lowerdir=$roDir,upperdir=$rwDir/rw,workdir=$rwDir/work"
if ! mount -t overlay -o $opts overlay $prefix;then
Echo "Failed to mount root via overlayfs"
return 1
fi
fi
elif [ "$unionFST" = "unionfs" ];then
#======================================
# setup fuse union mount
#--------------------------------------
local opts="cow,max_files=65000,allow_other,use_ino,suid,dev,nonempty"
if ! unionfs -o $opts $rwDir=RW:$roDir=RO $prefix;then
Echo "Failed to mount root via unionfs"
return 1
fi
fi
export haveUnionFS=yes
return 0
}
#======================================
# mountSystemClicFS
#--------------------------------------
function mountSystemClicFS {
local IFS=$IFS_ORIG
local loopf=$1
local roDir=/read-only
local rwDevice=`echo $UNIONFS_CONFIG | cut -d , -f 1`
local roDevice=`echo $UNIONFS_CONFIG | cut -d , -f 2`
local clic_cmd=clicfs
local resetReadWrite=0
local ramOnly=0
local haveBytes
local haveKByte
local haveMByte
local wantCowFS
local size
local prefix=/mnt
#======================================
# load fuse module
#--------------------------------------
modprobe fuse &>/dev/null
#======================================
# create read only mount point
#--------------------------------------
mkdir -p $roDir
#======================================
# check read/only device location
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
roDevice="$imageRootDevice"
fi
#======================================
# check kernel command line for log file
#--------------------------------------
if [ -n "$cliclog" ]; then
clic_cmd="$clic_cmd -l $cliclog"
fi
#======================================
# check read/write device location
#--------------------------------------
if [ ! -z "$kiwi_ramonly" ];then
ramOnly=1
elif [ ! -e $rwDevice ];then
ramOnly=1
elif getDiskDevice $rwDevice | grep -q ram;then
ramOnly=1
fi
if [ $ramOnly = 1 ];then
haveKByte=`cat /proc/meminfo | grep MemFree | cut -f2 -d:| cut -f1 -dk`
haveMByte=$((haveKByte / 1024))
haveMByte=$((haveMByte * 7 / 10))
clic_cmd="$clic_cmd -m $haveMByte"
else
haveBytes=$(blockdev --getsize64 $rwDevice)
haveMByte=$((haveBytes / 1024 / 1024))
wantCowFS=0
if \
[ "$kiwi_hybrid" = "true" ] && \
[ "$kiwi_hybridpersistent" = "true" ]
then
# write into a cow file on a filesystem, for hybrid iso's
wantCowFS=1
fi
if [ $wantCowFS = 1 ];then
# write into a cow file on a filesystem
mkdir -p $HYBRID_PERSISTENT_DIR
if [ $LOCAL_BOOT = "no" ] && [ $systemIntegrity = "clean" ];then
resetReadWrite=1
elif ! mount $rwDevice $HYBRID_PERSISTENT_DIR;then
resetReadWrite=1
elif [ ! -z "$wipecow" ];then
resetReadWrite=1
fi
if [ $resetReadWrite = 1 ];then
if ! setupReadWrite; then
Echo "Failed to setup read-write filesystem"
return 1
fi
if ! mount $rwDevice $HYBRID_PERSISTENT_DIR;then
Echo "Failed to mount read/write filesystem"
return 1
fi
fi
clic_cmd="$clic_cmd -m $haveMByte"
clic_cmd="$clic_cmd -c $HYBRID_PERSISTENT_DIR/.clicfs_COW"
else
# write into a device directly
clic_cmd="$clic_cmd -m $haveMByte -c $rwDevice --ignore-cow-errors"
fi
fi
#======================================
# mount/check clic file
#--------------------------------------
if [ ! -z "$NFSROOT" ];then
#======================================
# clic exported via NFS
#--------------------------------------
if ! kiwiMount "$roDevice" "$roDir" "" $loopf;then
Echo "Failed to mount NFS filesystem"
return 1
fi
if [ ! -e "$roDir/fsdata.ext4" ];then
Echo "Can't find clic fsdata.ext4 in NFS export"
return 1
fi
else
#======================================
# mount clic container
#--------------------------------------
if [ -z "$loopf" ];then
loopf=$roDevice
fi
if ! $clic_cmd $loopf $roDir; then
Echo "Failed to mount clic filesystem"
return 1
fi
fi
#======================================
# mount root over clic
#--------------------------------------
size=$(stat -c %s $roDir/fsdata.ext4)
size=$((size/512))
# we don't want reserved blocks...
tune2fs -m 0 $roDir/fsdata.ext4 >/dev/null
# we don't want automatic filesystem check...
tune2fs -i 0 $roDir/fsdata.ext4 >/dev/null
if [ ! $LOCAL_BOOT = "no" ];then
e2fsck -p $roDir/fsdata.ext4
fi
if [ $LOCAL_BOOT = "no" ] || [ $ramOnly = 1 ];then
resize2fs $roDir/fsdata.ext4 $size"s"
fi
mount -o loop,noatime,nodiratime,errors=remount-ro,barrier=0 \
$roDir/fsdata.ext4 $prefix
if [ ! $? = 0 ];then
Echo "Failed to mount ext4 clic container"
return 1
fi
# Give fuse enough time to settle for I/O in the ext4 container
# Unconditional waiting is never a good idea however I couldn't
# find a good solution to this problem because a lookup on read
# or write could cause an ro remount of the ext4 container
# Thus we just sleep a while before proceeding
sleep 5
export haveClicFS=yes
return 0
}
#======================================
# mountSystemCombined
#--------------------------------------
function mountSystemCombined {
local IFS=$IFS_ORIG
local mountDevice=$1
local loopf=$2
local roDevice=$mountDevice
local rwDevice
local options
local rootfs
local meta
local inode_nr
local min_size
local haveKByte
local haveMByte
local needMByte
local prefix=/mnt
if [ -e "$HYBRID_RW" ];then
rwDevice=$HYBRID_RW
elif [ "$haveLuks" = "yes" ]; then
rwDevice="/dev/mapper/luksReadWrite"
elif [ "$haveLVM" = "yes" ]; then
rwDevice="/dev/$kiwi_lvmgroup/LVRoot"
else
rwDevice=$(getNextPartition $mountDevice)
fi
mkdir /read-only >/dev/null
# /.../
# mount the read-only partition to /read-only and use
# mount option -o ro for this filesystem
# ----
if ! kiwiMount "$roDevice" "/read-only" "" $loopf;then
Echo "Failed to mount read only filesystem"
return 1
fi
# /.../
# mount a tmpfs which will become the root fs (/) later on
# and extract the rootfs tarball with the RAM data and the read-only
# and read-write links into the tmpfs.
# ----
rootfs=/read-only/rootfs.tar
if [ ! -f $rootfs ];then
Echo "Can't find rootfs tarball"
umount "$roDevice" &>/dev/null
return 1
fi
meta=/read-only/rootfs.meta
if [ ! -f $inodes ];then
Echo "Can't find rootfs meta data"
umount "$roDevice" &>/dev/null
return 1
fi
# /.../
# source rootfs meta data variables:
# => min_size # minimum required tmpfs size in bytes
# => inode_nr # number of inodes
# ----
source $meta
# /.../
# check if rootfs tarball fits into memory
# ----
haveKByte=$(cat /proc/meminfo | grep MemFree | cut -f2 -d: | cut -f1 -dk)
haveMByte=$((haveKByte / 1024))
needMByte=$((min_size / 1048576))
Echo "Have size: proc/meminfo -> $haveMByte MB"
Echo "Need size: $rootfs -> $needMByte MB"
if [ "$haveMByte" -lt "$needMByte" ];then
systemException \
"Not enough RAM space available for temporary data" \
"reboot"
fi
# /.../
# mount tmpfs, reserve max $splitroot_size for the rootfs data
# ----
options="size=${splitroot_size}M,nr_inodes=$inode_nr"
if ! mount -t tmpfs tmpfs -o $options $prefix;then
systemException \
"Failed to mount root tmpfs" \
"reboot"
fi
cd $prefix && tar xf $rootfs >/dev/null && cd /
# /.../
# check for a read-write data file and put it on the read-write
# device or to the root tmpfs
# ---
if [ -e ${loopf}-read-write ];then
local target=$prefix
if [ -e "$HYBRID_RW" ];then
mkdir -p $prefix/read-write
kiwiMount "$rwDevice" "$prefix/read-write"
target=$prefix/read-write
fi
mkdir -p $prefix-tmp
if ! mount -o loop ${loopf}-read-write $prefix-tmp;then
systemException \
"Failed to mount read-write data file" \
"reboot"
fi
pushd $prefix-tmp &>/dev/null
for item in *;do
if [ -L /$target/$item ];then
rm -f /$target/$item
fi
if [ ! -e /$target/$item ];then
if ! cp -a $prefix-tmp/$item $target;then
systemException \
"Failed to copy $item to $target" \
"reboot"
fi
fi
done
popd &>/dev/null
if [ -e "$HYBRID_RW" ];then
umount $prefix/read-write
fi
umount $prefix-tmp
rmdir $prefix-tmp
fi
# /.../
# create a read-only mount point and move the /read-only
# mount into the root tree. After that remove the read-only
# directory and create a link to read-only instead
# ----
mkdir $prefix/read-only >/dev/null
mount --move /read-only $prefix/read-only >/dev/null
rm -rf /read-only >/dev/null
ln -s $prefix/read-only /read-only >/dev/null || return 1
if ! echo $rwDevice | grep -q loop;then
if partitionSize $rwDevice &>/dev/null;then
# /.../
# mount the read-write partition to read-write and create a link
# ----
mkdir -p $prefix/read-write >/dev/null
kiwiMount "$rwDevice" "$prefix/read-write"
rm -rf /read-write >/dev/null
ln -s $prefix/read-write /read-write >/dev/null
fi
fi
}
#======================================
# mountSystemStandard
#--------------------------------------
function mountSystemStandard {
local IFS=$IFS_ORIG
local mountDevice=$1
local variable
local volume
local content
local volpath
local mpoint
local mppath
local prefix=/mnt
if [ ! -z $FSTYPE ] &&
[ ! $FSTYPE = "unknown" ] &&
[ ! $FSTYPE = "auto" ]
then
kiwiMount "$mountDevice" "$prefix"
else
mount $mountDevice $prefix >/dev/null
fi
if [ "$haveLVM" = "yes" ];then
for i in $(cat /.profile | grep -E 'kiwi_LVM_|kiwi_allFreeVolume');do
variable=$(echo $i|cut -f1 -d=)
volume=$(echo $i| cut -f3- -d_ | cut -f1 -d=)
content=$(echo $i|cut -f2 -d= | tr -d \' | tr -d \")
volpath=$(echo $content | cut -f3 -d:)
if [ -z "$volpath" ];then
volpath=$(echo $volume | tr _ /)
fi
mpoint=$(echo $volpath | sed -e s@^LV@@)
if \
[ ! $volume = "LVRoot" ] && \
[ ! $volume = "LVComp" ] && \
[ ! $volume = "LVSwap" ]
then
mkdir -p $prefix/$mpoint
kiwiMount "/dev/$kiwi_lvmgroup/$volume" "$prefix/$mpoint"
fi
done
fi
return $?
}
#======================================
# mountSystem
#--------------------------------------
function mountSystem {
local IFS=$IFS_ORIG
local retval=0
#======================================
# set primary mount device
#--------------------------------------
local mountDevice="$imageRootDevice"
if [ ! -z "$1" ];then
mountDevice="$1"
fi
#======================================
# wait for storage device to appear
#--------------------------------------
if ! echo $mountDevice | grep -qE "loop|vers=";then
waitForStorageDevice $mountDevice
fi
#======================================
# check root tree type
#--------------------------------------
if [ ! -z "$COMBINED_IMAGE" ];then
mountSystemCombined "$mountDevice" $2
retval=$?
elif [ ! -z "$UNIONFS_CONFIG" ];then
local unionFST=`echo $UNIONFS_CONFIG | cut -d , -f 3`
if [ "$unionFST" = "clicfs" ];then
mountSystemClicFS $2
elif [ "$unionFST" = "seed" ];then
mountSystemSeedBtrFS $2
elif [ "$unionFST" = "overlay" ];then
mountSystemUnionFS $2
elif [ "$unionFST" = "unionfs" ];then
mountSystemUnionFS $2
else
systemException \
"Unknown overlay mount method: $unionFST" \
"reboot"
fi
retval=$?
else
mountSystemStandard "$mountDevice"
retval=$?
fi
#======================================
# setup boot partition
#--------------------------------------
if \
[ -z "$skipSetupBootPartition" ] && \
[ "$LOCAL_BOOT" = "no" ] && \
[ ! "$systemIntegrity" = "fine" ] && \
[ $retval = 0 ] && \
[ -z "$RESTORE" ]
then
if [[ $kiwi_iname =~ netboot ]];then
setupBootPartitionPXE
else
setupBootPartition
fi
fi
#======================================
# reset mount counter
#--------------------------------------
resetMountCounter
return $retval
}
#======================================
# cleanDirectory
#--------------------------------------
function cleanDirectory {
local IFS=$IFS_ORIG
local directory=$1
shift 1
local save=$@
local tmpdir=`mktemp -d`
for saveItem in $save;do
mv $directory/$saveItem $tmpdir >/dev/null
done
rm -rf $directory/*
mv $tmpdir/* $directory
rm -rf $tmpdir
}
#======================================
# searchGroupConfig
#--------------------------------------
function searchGroupConfig {
local IFS=$IFS_ORIG
local localhwaddr=$DHCPCHADDR
local GROUPCONFIG=/etc/config.group
local list_var
local mac_list
#======================================
# Load group file if it exists
#--------------------------------------
Echo "Checking for config file: config.group";
fetchFile KIWI/config.group $GROUPCONFIG
if [ ! -s $GROUPCONFIG ]; then
return
fi
Echo "Found config.group, determining available groups";
importFile < $GROUPCONFIG
Debug "KIWI_GROUP = '$KIWI_GROUP'"
#======================================
# Parse group file
#--------------------------------------
if [ -z "$KIWI_GROUP" ] ; then
systemException \
"No groups defined in $GROUPCONFIG" \
"reboot"
fi
for i in `echo "$KIWI_GROUP" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
Echo "Lookup MAC address: $localhwaddr in ${i}_KIWI_MAC_LIST"
eval list_var="${i}_KIWI_MAC_LIST"
eval mac_list=\$$list_var
searchGroupHardwareAddress $i "$mac_list"
if [ -s $CONFIG ]; then
break
fi
unset list_var
unset mac_list
done
}
#======================================
# searchGroupHardwareAddress
#--------------------------------------
function searchGroupHardwareAddress {
# /.../
# function to check the existance of the hosts
# hardware address within the defined "mac_list".
# If the hardware address is found, load the config file.
# ----
local IFS=$IFS_ORIG
local localhwaddr=$DHCPCHADDR
local local_group=$1
local mac_list=$2
for j in `echo "$mac_list" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
if [ "$localhwaddr" = "$j" ] ; then
Echo "MAC address $localhwaddr found in group $local_group"
Echo "Checking for config file: config.$local_group"
fetchFile KIWI/config.$local_group $CONFIG
if [ ! -s $CONFIG ]; then
systemException \
"No configuration found for $j" \
"reboot"
fi
break
fi
done
}
#======================================
# searchAlternativeConfig
#--------------------------------------
function searchAlternativeConfig {
local IFS=$IFS_ORIG
# Check config.IP in Hex (pxelinux style)
localip=$IPADDR
hexip1=`echo $localip | cut -f1 -d'.'`
hexip2=`echo $localip | cut -f2 -d'.'`
hexip3=`echo $localip | cut -f3 -d'.'`
hexip4=`echo $localip | cut -f4 -d'.'`
hexip=`printf "%02X" $hexip1 $hexip2 $hexip3 $hexip4`
STEP=8
while [ $STEP -gt 0 ]; do
hexippart=`echo $hexip | cut -b -$STEP`
Echo "Checking for config file: config.$hexippart"
fetchFile KIWI/config.$hexippart $CONFIG
if test -s $CONFIG;then
break
fi
let STEP=STEP-1
done
# Check config.default if no hex config was found
if test ! -s $CONFIG;then
Echo "Checking for config file: config.default"
fetchFile KIWI/config.default $CONFIG
fi
}
#======================================
# searchHardwareMapConfig
#--------------------------------------
function searchHardwareMapConfig {
local IFS=$IFS_ORIG
local list_var
local mac_list
#======================================
# return if no map was specified
#--------------------------------------
if [ -z "$HARDWARE_MAP" ];then
return
fi
Echo "Found hardware/vendor map configuration variable"
#===========================================
# Evaluate the MAP list, and test for hwaddr
#-------------------------------------------
for i in `echo "$HARDWARE_MAP" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
Echo "Lookup MAC address: $localhwaddr in ${i}_HARDWARE_MAP"
eval list_var="${i}_HARDWARE_MAP"
eval mac_list=\$$list_var
Debug "${i}_HARDWARE_MAP = '$mac_list'"
searchHardwareMapHardwareAddress $i "$mac_list"
if [ -s $CONFIG ]; then
break
fi
unset list_var
unset mac_list
done
}
#======================================
# searchHardwareMapHardwareAddress
#--------------------------------------
function searchHardwareMapHardwareAddress {
local IFS=$IFS_ORIG
local HARDWARE_CONFIG=/etc/config.hardware
local localhwaddr=$DHCPCHADDR
local hardware_group=$1
local mac_list=$2
Debug "hardware_group = '$hardware_group'"
Debug "mac_list = '$mac_list'"
for j in `echo "$mac_list" | sed 's/,/ /g' | sed 's/[ \t]+/ /g'`; do
if [ "$localhwaddr" = "$j" ] ; then
Echo "MAC address $localhwaddr found in group $hardware_group"
Echo "Checking for config file: hardware_config.$hardware_group"
fetchFile KIWI/hardware_config.$hardware_group $HARDWARE_CONFIG
if [ ! -s $HARDWARE_CONFIG ]; then
systemException \
"No configuration found for $j" \
"reboot"
fi
importFile < $HARDWARE_CONFIG
break
fi
done
}
#======================================
# runHook
#--------------------------------------
function runHook {
local IFS=$IFS_ORIG
#======================================
# Check for execution permission
#--------------------------------------
if [ ! -z "$KIWI_FORBID_HOOKS" ];then
Echo "Hook script execution is forbidden by KIWI_FORBID_HOOKS"
return
fi
#======================================
# Init custom post hook commands
#--------------------------------------
# a) switch post command execution off, can be activated by hook script
export eval KIWI_ALLOW_HOOK_CMD_$1=0
#======================================
# Search and execute hook script
#--------------------------------------
HOOK="/kiwi-hooks/$1.sh"
if [ ! -e $HOOK ];then
HOOK="/lib/kiwi/hooks/$1.sh"
fi
if [ -e $HOOK ]; then
. $HOOK "$@"
fi
#======================================
# Run custom post hook commands
#--------------------------------------
# b) check permisson and state of command list
if [ ! -z "$KIWI_FORBID_HOOK_CMDS" ];then
Echo "Post-Hook command execution is forbidden by KIWI_FORBID_HOOK_CMDS"
return
fi
eval local call_cmd=\$KIWI_ALLOW_HOOK_CMD_$1
if [ "$call_cmd" -eq 1 ]; then
eval local call=\$KIWI_HOOK_CMD_$1
eval $call
fi
}
#======================================
# getNextPartition
#--------------------------------------
function getNextPartition {
local IFS=$IFS_ORIG
part=$1
nextPart=`echo $part | sed -e "s/\(.*\)[0-9]/\1/"`
nextPartNum=`echo $part | sed -e "s/.*\([0-9]\)/\1/"`
nextPartNum=$((nextPartNum + 1))
nextPart="${nextPart}${nextPartNum}"
echo $nextPart
}
#======================================
# startShell
#--------------------------------------
function startShell {
# /.../
# start a debugging shell on ELOG_BOOTSHELL
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwidebug ];then
if [ ! -e $ELOG_BOOTSHELL ];then
Echo "No terminal $ELOG_BOOTSHELL available for debug shell"
return
fi
Echo "Starting boot shell on $ELOG_BOOTSHELL"
setctsid -f $ELOG_BOOTSHELL /bin/bash -i
ELOGSHELL_PID=$(fuser $ELOG_BOOTSHELL | tr -d " ")
echo ELOGSHELL_PID=$ELOGSHELL_PID >> /iprocs
fi
}
#======================================
# killShell
#--------------------------------------
function killShell {
# /.../
# kill debugging shell on ELOG_BOOTSHELL
# ----
local IFS=$IFS_ORIG
local umountProc=0
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
umountProc=1
fi
if [ ! -z "$ELOGSHELL_PID" ];then
Echo "Stopping boot shell"
kill $ELOGSHELL_PID &>/dev/null
fi
if [ $umountProc -eq 1 ];then
umount /proc
fi
}
#======================================
# waitForStorageDevice
#--------------------------------------
function waitForStorageDevice {
# /.../
# function to check access on a storage device
# which could be a whole disk or a partition.
# the function will wait until the size of the
# storage device could be obtained or the check
# counter equals 4
# ----
local IFS=$IFS_ORIG
local device=$1
local check=0
udevPending
while true;do
partitionSize $device &>/dev/null
if [ $? = 0 ];then
sleep 1; return 0
fi
if [ $check -eq 30 ];then
return 1
fi
Echo "Waiting for device $device to settle..."
check=$((check + 1))
sleep 2
done
}
#======================================
# waitForLinkUp
#--------------------------------------
function waitForLinkUp {
# /.../
# wait for the network link to enter UP state
# ----
local IFS=$IFS_ORIG
local dev=$1
local check=0
while true;do
ip link ls $dev | grep -qi "state UP"
if [ $? = 0 ];then
sleep 1; return 0
fi
if [ $check -eq 30 ];then
return 1
fi
Echo "Waiting for link up on ${dev}..."
check=$((check + 1))
sleep 2
done
}
#======================================
# waitForBlockDevice
#--------------------------------------
function waitForBlockDevice {
# /.../
# function to check if the given block device
# exists. If not the function will wait until the
# device appears or the check counter equals 4
# ----
local IFS=$IFS_ORIG
local device=$1
local check=0
udevPending
while true;do
if [ -b $device ] || [ $check -eq 4 ];then
break
fi
Echo "Waiting for device $device to settle..."
check=$((check + 1))
sleep 2
done
}
#======================================
# atftpProgress
#--------------------------------------
function atftpProgress {
# /.../
# atftp doesn't use a stream based download and sometimes
# seek back and forth which makes it hard to use pipes for
# progress indication. Therefore we watch the trace output
# ----
local IFS=$IFS_ORIG
local imgsize=$1 # image size in MB
local prefix=$2 # line prefix text
local file=$3 # file with progress data
local blocksize=$4 # blocksize use for download
local bytes=0 # log lines multiplied by blocksize
local lines=0 # log lines
local percent=0 # in percent of all
local all=$((imgsize * 1024 * 1024))
local line
local step=0
# number of cycles for approx. 2% steps
local max_step=$(($all / $blocksize / 25))
cat < dev/null > $file.tmp
#======================================
# print progress information
#--------------------------------------
while read line ;do
echo "$line" >> $file.tmp
let step=step+1
if [ $step -lt $max_step ]; then
continue
fi
step=0
# /.../
# the trace logs two lines indicating one download block of
# blocksize bytes. We assume only full blocks. At the end
# it might happen that only a part of blocksize bytes is
# required. The function does not precisely calculate them
# and assumes blocksize bytes. imho that's ok for the progress
# bar. In order to be exact the function would have to sum
# up all bytes from the trace log for each iteration which
# would cause the download to pause because it has to wait
# for the progress bar to get ready
# ----
# the same block can be transferred multiple times
lines=$(grep "^sent ACK" $file.tmp | sort -u | wc -l)
bytes=$((lines * $blocksize))
percent=$(echo "scale=2; $bytes * 100" | bc)
percent=$(echo "scale=0; $percent / $all" | bc)
echo -en "$prefix ( $percent%)\r"
done
grep -v "^\(received \)\|\(sent \)" $file.tmp > $file
rm $file.tmp
echo
}
#======================================
# encodeURL
#--------------------------------------
function encodeURL {
# /.../
# encode special characters in URL's to correctly
# serve as input for fetchFile and putFile
# ----
local IFS=$IFS_ORIG
local STR
local CH
STR="$@"
echo -n "$STR" | while read -n1 CH; do
[[ $CH =~ [-_A-Za-z0-9./] ]] && printf "$CH" || printf "%%%x" \'"$CH"
done
}
#======================================
# fetchFile
#--------------------------------------
function fetchFile {
# /.../
# the generic fetcher which is able to use different protocols
# tftp,ftp, http, https. fetchFile is used in the netboot linuxrc
# and uses curl and atftp to download files from the network
# ----
local IFS=$IFS_ORIG
local path=$1
local dest=$2
local izip=$3
local host=$4
local type=$5
local chunk=$6
local encoded_path
local dump
local call
local call_pid
local unzip
#======================================
# source path is required
#--------------------------------------
if [ -z "$path" ]; then
systemException "No source path specified" "reboot"
fi
#======================================
# destination path is required
#--------------------------------------
if [ -z "$dest" ];then
systemException "No destination path specified" "reboot"
fi
#======================================
# source host is required
#--------------------------------------
if [ -z "$host" ]; then
if test -z "$SERVER"; then
systemException "No source server specified" "reboot"
fi
host=$SERVER
fi
#======================================
# set default chunk size
#--------------------------------------
if [ -z "$chunk" ];then
chunk=4k
fi
#======================================
# set default service type
#--------------------------------------
if [ -z "$type" ]; then
if [ -z "$SERVERTYPE" ]; then
type="tftp"
else
type="$SERVERTYPE"
fi
fi
#======================================
# set source path + tool if compressed
#--------------------------------------
if [ ! -z "$izip" ] && [[ ! "$izip" =~ ^uncomp ]];then
if [ $izip = "compressed" ] || [ "$izip" = "compressed-gzip" ]; then
unzip="gzip -d"
path=$(echo "$path" | sed -e s@\\.gz@@)
path="$path.gz"
elif [ $izip = "compressed-xz" ];then
unzip="xz -d"
path=$(echo "$path" | sed -e s@\\.xz@@)
path="$path.xz"
else
systemException "Unknown compression mode: $izip" "reboot"
fi
else
unset izip
fi
#======================================
# encode special URL characters
#--------------------------------------
encoded_path=$(encodeURL "$path")
#======================================
# setup progress meta information
#--------------------------------------
dump="dd bs=$chunk of=\"$dest\""
showProgress=0
if \
[ -x /usr/bin/dcounter ] && \
[ -f /etc/image.md5 ] && \
[ -b "$dest" ] && \
[ -z "$disableProgressInfo" ]
then
showProgress=1
read sum1 blocks blocksize zblocks zblocksize < /etc/image.md5
needBytes=$((blocks * blocksize))
needMByte=$((needBytes / 1048576))
if [ ! -z "$zblocks" ];then
needZBytes=$((zblocks * zblocksize))
needZMByte=$((needZBytes / 1048576))
fi
progressBaseName=$(basename "$path")
TEXT_LOAD=$(getText "Loading %1" "$progressBaseName")
TEXT_COMP=$(getText "Uncompressing %1" "$progressBaseName")
dump="dcounter -s $needMByte -l \"$TEXT_LOAD \" 2>/progress | $dump"
fi
#======================================
# build download command
#--------------------------------------
case "$type" in
"local")
if [ ! -z "$izip" ];then
call="$unzip < $host/$path \
2>$TRANSFER_ERRORS_FILE | $dump"
else
call="dd if=$host/$path bs=$chunk |\
$dump"
fi
;;
"http")
if [ ! -z "$izip" ];then
call="curl -f http://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl -f http://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"https")
if [ ! -z "$izip" ];then
call="curl -f -k https://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl -f -k https://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"ftp")
if [ ! -z "$izip" ];then
call="curl ftp://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$unzip 2>>$TRANSFER_ERRORS_FILE | $dump"
else
call="curl ftp://$host/$encoded_path \
2>$TRANSFER_ERRORS_FILE |\
$dump"
fi
;;
"tftp")
validateBlockSize
# /.../
# atftp activates multicast by '--option "multicast"'
# and deactivates it again by '--option "disable multicast"'
# ----
if [ -f /etc/image.md5 ] && [ -b "$dest" ];then
# enable multicast for system image and transfer to block device
multicast_atftp="multicast"
else
# disable multicast for any other transfer
multicast_atftp="disable multicast"
fi
havetemp_dir=1
if [ -z "$FETCH_FILE_TEMP_DIR" ];then
# we don't have a tmp dir available for downloading
havetemp_dir=0
elif [ -e "$FETCH_FILE_TEMP_DIR/${path##*/}" ];then
# temporary download data already exists
havetemp_dir=0
else
# prepare use of temp files for compressed download
FETCH_FILE_TEMP_FILE="$FETCH_FILE_TEMP_DIR/${path##*/}"
export FETCH_FILE_TEMP_FILE
fi
if [ ! -z "$izip" ];then
if [ $havetemp_dir -eq 0 ];then
# /.../
# operate without temp files, standard case
# ----
call="busybox tftp \
-b $imageBlkSize -g -r \"$path\" \
-l >($unzip 2>>$TRANSFER_ERRORS_FILE | $dump) \
$host 2>>$TRANSFER_ERRORS_FILE"
else
# /.../
# operate using temp files
# export the path to allow temp file management in a hook
# ----
if [ $showProgress -eq 1 ];then
call="(atftp \
--trace \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$FETCH_FILE_TEMP_FILE\" \
$host 2>&1 | \
atftpProgress \
$needZMByte \"$TEXT_LOAD\" \
$TRANSFER_ERRORS_FILE $imageBlkSize \
>&2 ; \
$unzip < \"$FETCH_FILE_TEMP_FILE\" | \
dcounter -s $needMByte -l \"$TEXT_COMP \" | \
dd bs=$chunk of=\"$dest\" ) 2>/progress "
else
call="atftp \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$FETCH_FILE_TEMP_FILE\" $host \
&> $TRANSFER_ERRORS_FILE ; \
$unzip < \"$FETCH_FILE_TEMP_FILE\" | \
dd bs=$chunk of=\"$dest\" "
fi
fi
else
if [ $showProgress -eq 1 ];then
call="atftp \
--trace \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$dest\" $host 2>&1 | \
atftpProgress \
$needMByte \"$TEXT_LOAD\" \
$TRANSFER_ERRORS_FILE $imageBlkSize \
> /progress"
else
call="atftp \
--option \"$multicast_atftp\" \
--option \"blksize $imageBlkSize\" \
-g -r \"$path\" -l \"$dest\" $host \
&> $TRANSFER_ERRORS_FILE"
fi
fi
;;
*)
systemException "Unknown download type: $type" "reboot"
;;
esac
#======================================
# run the download
#--------------------------------------
if [ $showProgress -eq 1 ];then
test -e /progress || mkfifo /progress
test -e /tmp/load_code && rm -f /tmp/load_code
errorLogStop
(
eval $call \; 'echo ${PIPESTATUS[0]} > /tmp/load_code' &>/dev/null
)&
call_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
else
bash -e /tmp/progress.sh
fi
clear
wait $call_pid
loadCode=`cat /tmp/load_code`
if [ -z "$loadCode" ]; then
systemException \
"Failed to get the download process return value" \
"reboot"
fi
else
eval $call \; 'loadCode=${PIPESTATUS[0]}'
fi
if [ $showProgress -eq 1 ];then
errorLogContinue
fi
loadStatus=`cat $TRANSFER_ERRORS_FILE`
return $loadCode
}
#======================================
# fetchFileLocal
#--------------------------------------
function fetchFileLocal {
# /.../
# ----
fetchFile "$1" "$2" "$3" "$KIWI_LOCAL_CACHE_DIR" "local"
}
#======================================
# putFile
#--------------------------------------
function putFile {
# /.../
# the generic putFile function is used to upload boot data on
# a server. Supported protocols are tftp, ftp, http, https
# ----
local IFS=$IFS_ORIG
local path=$1
local dest=$2
local host=$3
local type=$4
local encoded_dest
if test -z "$path"; then
systemException "No path specified" "reboot"
fi
if test -z "$host"; then
if test -z "$SERVER"; then
systemException "No server specified" "reboot"
fi
host=$SERVER
fi
if test -z "$type"; then
if test -z "$SERVERTYPE"; then
type="tftp"
else
type="$SERVERTYPE"
fi
fi
encoded_dest=$(encodeURL "$dest")
case "$type" in
"local")
cp -f "$path" "$host/$dest" > $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"http")
curl -f -T "$path" http://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"https")
curl -f -T "$path" https://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"ftp")
curl -T "$path" ftp://$host/$encoded_dest \
> $TRANSFER_ERRORS_FILE 2>&1
return $?
;;
"tftp")
atftp -p -l "$path" -r "$dest" $host >/dev/null 2>&1
return $?
;;
*)
systemException "Unknown download type: $type" "reboot"
;;
esac
}
#======================================
# importBranding
#--------------------------------------
function importBranding {
# /.../
# include possible custom boot loader and bootsplash files
# to the system to allow to use them persistently
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
if [ -f /image/loader/message ];then
if ! canWrite $prefix/boot;then
Echo "Can't write to boot, import of boot message skipped"
else
mv /image/loader/message $prefix/boot
fi
fi
if [ -f /image/loader/branding/logo.mng ];then
if [ -d $prefix/etc/bootsplash/themes ];then
for theme in $prefix/etc/bootsplash/themes/*;do
if [ -d $theme/images ];then
if ! canWrite $theme;then
Echo "Can't write to $theme, import of boot theme skipped"
continue
fi
cp /image/loader/branding/logo.mng $theme/images
cp /image/loader/branding/logov.mng $theme/images
cp /image/loader/branding/*.jpg $theme/images
cp /image/loader/branding/*.cfg $theme/config
fi
done
fi
fi
}
#======================================
# validateRootTree
#--------------------------------------
function validateRootTree {
# /.../
# after the root of the system image has been mounted we should
# check whether that mount is a valid system tree or not. Therefore
# some sanity checks are made here
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
if [ ! -x $prefix/sbin/init -a ! -L $prefix/sbin/init ];then
systemException "/sbin/init no such file or not executable" "reboot"
fi
}
#======================================
# getDiskID
#--------------------------------------
function getDiskID {
# /.../
# this function is able to turn a given standard device
# name into the udev ID based representation
# ----
local IFS=$IFS_ORIG
local device=$1
local swap=$2
local prefix=by-id
if [ -z "$device" ];then
return
fi
if [ ! -z "$kiwi_lvmgroup" ] && echo $device | grep -q "$kiwi_lvmgroup";then
echo $device
return
fi
if [ -z "$swap" ] && [[ $device =~ ^/dev/md ]];then
echo $device
return
fi
if [ ! -z "$NON_PERSISTENT_DEVICE_NAMES" ]; then
echo $device
return
fi
if [[ $device =~ ^/dev/dm- ]];then
for i in /dev/mapper/*;do
if [ ! -L $i ];then
continue
fi
local dev=$(readlink $i)
dev=/dev/$(basename "$dev")
if [ $dev = $device ];then
echo $i
return
fi
done
fi
if [ ! -z "$kiwi_devicepersistency" ];then
prefix=$kiwi_devicepersistency
fi
for i in /dev/disk/$prefix/*;do
if [ -z "$i" ];then
continue
fi
if echo $i | grep -q edd-;then
continue
fi
local dev=$(readlink $i)
dev=/dev/$(basename "$dev")
if [ $dev = $device ];then
echo $i
return
fi
done
echo $device
}
#======================================
# getDiskDevice
#--------------------------------------
function getDiskDevice {
# /.../
# this function is able to turn the given udev disk
# ID label into the /dev/ device name
# ----
local IFS=$IFS_ORIG
local device=$(readlink $1)
if [ -z "$device" ];then
echo $1
return
fi
device=$(basename $device)
device=/dev/$device
echo $device
}
#======================================
# getDiskModel
#--------------------------------------
function getDiskModels {
# /.../
# this function returns the disk identifier as
# registered in the sysfs layer
# ----
local IFS=$IFS_ORIG
local models=`cat /sys/block/*/device/model 2>/dev/null`
if [ ! -z "$models" ];then
echo $models; return
fi
echo "unknown"
}
#======================================
# setupInittab
#--------------------------------------
function setupInittab {
# /.../
# setup default runlevel according to /proc/cmdline
# information. If textmode is set to 1 we will boot into
# runlevel 3
# ----
local IFS=$IFS_ORIG
local prefix=$1
if cat /proc/cmdline | grep -qi "textmode=1";then
sed -i -e s"@id:.*:initdefault:@id:3:initdefault:@" $prefix/etc/inittab
fi
}
#======================================
# setupConfigFiles
#--------------------------------------
function setupConfigFiles {
# /.../
# all files created below /config inside the initrd are
# now copied into the system image
# ----
local IFS=$IFS_ORIG
local file
local dir
local prefix=/mnt
cd /config
find . -type f | while read file;do
dir=$(dirname $file)
if [ ! -d $prefix/$dir ];then
mkdir -p $prefix/$dir
fi
if ! canWrite $prefix/$dir;then
Echo "Can't write to $dir, read-only filesystem... skipped"
continue
fi
cp $file $prefix/$file
done
cd /
rm -rf /config
}
#======================================
# activateImage
#--------------------------------------
function activateImage {
# /.../
# move the udev created nodes from the initrd into
# the system root tree call the pre-init phase which
# already runs in the new tree and finaly switch the
# new tree to be the new root (/)
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# setup image name
#--------------------------------------
local name
if [ ! -z "$stickSerial" ];then
name="$stickSerial on -> $stickDevice"
elif [ ! -z "$imageName" ];then
name=$imageName
elif [ ! -z "$imageRootName" ];then
name=$imageRootName
elif [ ! -z "$imageRootDevice" ];then
name=$imageRootDevice
elif [ ! -z "$imageDiskDevice" ];then
name=$imageDiskDevice
else
name="unknown"
fi
#======================================
# move union mount points to system
#--------------------------------------
local roDir=read-only
local rwDir=read-write
local xiDir=xino
if [ -z "$NFSROOT" ];then
if [ -d $roDir ];then
mkdir -p $prefix/$roDir && mount --move /$roDir $prefix/$roDir
fi
if [ -d $rwDir ];then
mkdir -p $prefix/$rwDir && mount --move /$rwDir $prefix/$rwDir
fi
if [ -d $xiDir ];then
mkdir -p $prefix/$xiDir && mount --move /$xiDir $prefix/$xiDir
fi
fi
#======================================
# move live CD mount points to system
#--------------------------------------
local cdDir=/livecd
if [ -d $cdDir ];then
mkdir -p $prefix/$cdDir && mount --move /$cdDir $prefix/$cdDir
if [ -d /cow ];then
mkdir -p $prefix/cow && mount --move /cow $prefix/cow
fi
if [ -d /isofrom ];then
mkdir -p $prefix/isofrom && mount --move /isofrom $prefix/isofrom
fi
fi
#======================================
# create dbus machine id
#--------------------------------------
if lookup dbus-uuidgen &>/dev/null;then
dbus-uuidgen > $prefix/var/lib/dbus/machine-id
fi
#======================================
# move device nodes
#--------------------------------------
Echo "Activating Image: [$name]"
udevPending
mkdir -p $prefix/run
mkdir -p $prefix/dev
mkdir -p $prefix/var/run
mount --move /dev $prefix/dev
if [[ ! $kiwi_iname =~ SLE.11 ]];then
mount --move /run $prefix/run
if [ ! -L $prefix/var/run ];then
mount --move /var/run $prefix/var/run
fi
fi
udevKill
#======================================
# run preinit stage
#--------------------------------------
Echo "Preparing preinit phase..."
if ! cp /usr/bin/utimer $prefix;then
systemException "Failed to copy: utimer" "reboot"
fi
if ! cp /iprocs $prefix;then
systemException "Failed to copy: iprocs" "reboot"
fi
if ! cp /preinit $prefix;then
systemException "Failed to copy: preinit" "reboot"
fi
if ! cp /include $prefix;then
systemException "Failed to copy: include" "reboot"
fi
local killall5=$(lookup killall5)
if [ ! -e $prefix/$killall5 ]; then
touch $prefix/killall5.from-initrd
fi
if ! cp -f -a $killall5 $prefix/$killall5;then
systemException "Failed to copy: killall5" "reboot"
fi
local pidof=$(lookup pidof)
if [ ! -e $prefix/$pidof ];then
touch $prefix/pidof.from-initrd
fi
if ! cp -f -a $pidof $prefix/$pidof;then
systemException "Failed to copy: pidof" "reboot"
fi
}
#======================================
# cleanImage
#--------------------------------------
function cleanImage {
# /.../
# remove preinit code from system image before
# real init is called. this function runs already
# inside the system root directory via chroot
# ----
local IFS=$IFS_ORIG
local bootdir=boot_bind
#======================================
# setup logging in this mode
#--------------------------------------
exec 2>>$ELOG_FILE
set -x
#======================================
# kill second utimer and tail
#--------------------------------------
. /iprocs
kill $UTIMER_PID &>/dev/null
#======================================
# remove preinit code from system image
#--------------------------------------
rm -f /tmp/utimer
rm -f /dev/utimer
rm -f /utimer
rm -f /iprocs
rm -f /preinit
rm -f /include
rm -f /.kconfig
rm -f /.profile
rm -rf /image
if [ -e /pidof.from-initrd ];then
rm -f /pidof.from-initrd
rm -f $(lookup pidof)
fi
if [ -e /killall5.from-initrd ];then
rm -f /killall5.from-initrd
rm -f $(lookup killall5)
fi
#======================================
# return early for special types
#--------------------------------------
if \
[ "$haveClicFS" = "yes" ] || \
[ ! -z "$NFSROOT" ] || \
[ ! -z "$NBDROOT" ] || \
[ ! -z "$AOEROOT" ] || \
[ ! -z "$COMBINED_IMAGE" ]
then
return
fi
#======================================
# return early for systemd
#--------------------------------------
if [ $init = "/bin/systemd" ];then
return
fi
#======================================
# umount LVM root parts
#--------------------------------------
local variable
local volume
local content
local volpath
local mpoint
for i in $(cat /.profile | grep -E 'kiwi_LVM_|kiwi_allFreeVolume');do
variable=$(echo $i|cut -f1 -d=)
volume=$(echo $i| cut -f3- -d_ | cut -f1 -d=)
content=$(echo $i|cut -f2 -d= | tr -d \' | tr -d \")
volpath=$(echo $content | cut -f3 -d:)
if [ -z "$volpath" ];then
volpath=$(echo $volume | tr _ /)
fi
mpoint=$(echo $volpath | sed -e s@^LV@@)
if \
[ ! $volume = "LVRoot" ] && \
[ ! $volume = "LVComp" ] && \
[ ! $volume = "LVSwap" ]
then
umount /$mpoint 1>&2
fi
done
#======================================
# umount image boot partition if any
#--------------------------------------
if [ -e /$bootdir ];then
umount /$bootdir 1>&2
fi
umount /boot 1>&2
#======================================
# turn off swap
#--------------------------------------
mount -t proc proc /proc
swapoff -a 1>&2
umount /proc 1>&2
}
#======================================
# bootImage
#--------------------------------------
function bootImage {
# /.../
# call the system image init process and therefore
# boot into the operating system
# ----
local IFS=$IFS_ORIG
local reboot=no
local option=${kernel_cmdline[@]}
local prefix=/mnt
#======================================
# Set active console to default font
#--------------------------------------
setupConsoleFont
#======================================
# check for init kernel option
#--------------------------------------
if [ -z "$init" ];then
if [ -e $prefix/bin/systemd ];then
export init=/bin/systemd
else
export init=/sbin/init
fi
fi
#======================================
# turn runlevel 4 to 5 if found
#--------------------------------------
option=$(echo $@ | sed -e s@4@5@)
echo && Echo "Booting System: $option"
#======================================
# check for reboot request
#--------------------------------------
if [ "$LOCAL_BOOT" = "no" ];then
if [ -z "$KIWI_RECOVERY" ];then
if [ ! -z "$kiwi_oemreboot" ] || [ ! -z "$REBOOT_IMAGE" ];then
reboot=yes
fi
if [ ! -z "$kiwi_oemrebootinteractive" ];then
rebootinter=yes
fi
if [ ! -z "$kiwi_oemshutdown" ];then
shutdown=yes
fi
if [ ! -z "$kiwi_oemshutdowninteractive" ];then
shutdowninter=yes
fi
fi
fi
#======================================
# run resetBootBind
#--------------------------------------
if [ -z "$NETBOOT_ONLY" ];then
resetBootBind $prefix
fi
#======================================
# setup warpclock for local time setup
#--------------------------------------
local warpclock=/lib/mkinitrd/bin/warpclock
if [ -e $prefix/etc/localtime ] && [ -x $warpclock ];then
cp $prefix/etc/localtime /etc
if [ -e $prefix/etc/adjtime ];then
cp $prefix/etc/adjtime /etc
while read line;do
if test "$line" = LOCAL
then
$warpclock > $prefix/dev/shm/warpclock
fi
done < /etc/adjtime
elif [ -e $prefix/etc/sysconfig/clock ];then
cp $prefix/etc/sysconfig/clock /etc
. /etc/clock
case "$HWCLOCK" in
*-l*) $warpclock > $prefix/dev/shm/warpclock
esac
fi
fi
#======================================
# kill initial tail and utimer
#--------------------------------------
. /iprocs
kill $UTIMER_PID &>/dev/null
#======================================
# copy boot log file into system image
#--------------------------------------
mkdir -p $prefix/var/log
rm -f $prefix/boot/mbrid
if [ -e $prefix/dev/shm/initrd.msg ];then
cp -f $prefix/dev/shm/initrd.msg $prefix/var/log/boot.msg
fi
if [ -e $ELOG_FILE ];then
cp -f $ELOG_FILE $prefix/$ELOG_FILE
fi
if [ ! -d $prefix/var/log/ConsoleKit ];then
mkdir -p $prefix/var/log/ConsoleKit
fi
#======================================
# umount proc
#--------------------------------------
umount proc &>/dev/null && \
umount proc &>/dev/null
#======================================
# copy initrd to /run/initramfs
#--------------------------------------
mkdir -p $prefix/run/initramfs
match='mnt|lost\+found|dev|boot|tmp|run|proc|sys|read-only|read-write'
for dir in /*;do
if [[ $dir =~ $match ]]; then
mkdir -p $prefix/run/initramfs/$dir
continue
fi
cp -a $dir $prefix/run/initramfs
done
if [ "$FSTYPE" = "zfs" ];then
#======================================
# setup shutdown script
#--------------------------------------
local halt=$prefix/run/initramfs/shutdown
cat > $halt << EOF
#!/bin/sh
# if systemd is used this script is called after all
# services are terminated and mount points unmounted
# ---
ACTION="\$1"
EOF
#======================================
# shutdown: zfs -> export pool
#--------------------------------------
echo "zpool export kiwipool" >> $halt
#======================================
# shutdown: handle requested action
#--------------------------------------
cat >> $halt << EOF
case "\$ACTION" in
reboot)
reboot -f -d
;;
poweroff)
reboot -f -d -p
;;
halt)
halt
;;
kexec)
kexec -e
;;
*)
reboot -f -d
;;
esac
EOF
fi
#======================================
# run preinit and cleanImage
#--------------------------------------
chroot $prefix /bin/bash -c \
"/preinit"
chroot $prefix /bin/bash -c \
". /include ; exec 2>>$ELOG_FILE ; set -x ; cleanImage"
cd $prefix
#======================================
# tell logging the new root fs
#--------------------------------------
exec 2>>$prefix/$ELOG_FILE
set -x
#======================================
# tell plymouth the new root fs
#--------------------------------------
if lookup plymouthd &>/dev/null;then
plymouth update-root-fs --new-root-dir=$prefix
#======================================
# stop if not installed in system image
#--------------------------------------
if [ ! -e $prefix/usr/bin/plymouth ];then
plymouth quit
fi
fi
#======================================
# export root block device
#--------------------------------------
if [ -b "$imageRootDevice" ];then
export ROOTFS_BLKDEV=$imageRootDevice
fi
#======================================
# rootfs is clean, skip check
#--------------------------------------
export ROOTFS_FSCK="0"
#======================================
# stop dropbear ssh server
#--------------------------------------
if [ ! -z "$DROPBEAR_PID" ];then
kill $DROPBEAR_PID
fi
#======================================
# hand over control to init
#--------------------------------------
if [ $reboot = "yes" ];then
Echo "Reboot requested... rebooting after preinit"
exec chroot . /sbin/reboot -f -i
fi
if [ "$rebootinter" = "yes" ];then
Echo "Reboot requested... rebooting after preinit"
if [ "$OEMInstallType" = "CD" ];then
TEXT_DUMP=$TEXT_CDPULL
else
TEXT_DUMP=$TEXT_USBPULL
fi
Dialog \
--backtitle \"$TEXT_INSTALLTITLE\" \
--msgbox "\"$TEXT_DUMP\"" 5 70
clear
Echo "Prepare for reboot"
exec chroot . /sbin/reboot -f -i
fi
if [ "$shutdown" = "yes" ];then
Echo "Shutdown requested... system shutdown after preinit"
exec chroot . /sbin/halt -fihp
fi
if [ "$shutdowninter" = "yes" ];then
Echo "Shutdown requested... system shutdown after preinit"
if [ "$OEMInstallType" = "CD" ];then
TEXT_DUMP=$TEXT_CDPULL_SDOWN
else
TEXT_DUMP=$TEXT_USBPULL_SDOWN
fi
Dialog \
--backtitle \"$TEXT_INSTALLTITLE\" \
--msgbox "\"$TEXT_DUMP\"" 5 70
clear
Echo "Prepare for shutdown"
exec chroot . /sbin/halt -fihp
fi
if lookup switch_root &>/dev/null;then
exec switch_root . $init $option
else
if lookup pivot_root &>/dev/null;then
pivot_root . run/initramfs
fi
exec chroot . $init $option
fi
}
#======================================
# setupUnionFS
#--------------------------------------
function setupUnionFS {
# /.../
# export the UNIONFS_CONFIG environment variable
# which contains a three part coma separated list of the
# following style: rwDevice,roDevice,unionType. The
# devices are stores by disk ID if possible
# ----
local IFS=$IFS_ORIG
local rwDevice=`getDiskID $1`
local roDevice=`getDiskID $2`
local unionFST=$3
if [[ "$roDevice" =~ aoe|nbd ]]; then
roDevice=$imageRootDevice
fi
if [ -e "$rwDevice" ]; then
luksOpen $rwDevice luksReadWrite
rwDeviceLuks=$luksDeviceOpened
fi
if [ -e "$roDevice" ]; then
luksOpen $roDevice luksReadOnly
roDeviceLuks=$luksDeviceOpened
fi
if [ ! -z "$rwDeviceLuks" ] && [ ! "$rwDeviceLuks" = "$rwDevice" ];then
rwDevice=$rwDeviceLuks
export haveLuks="yes"
fi
if [ ! -z "$roDeviceLuks" ] && [ ! "$roDeviceLuks" = "$roDevice" ];then
roDevice=$roDeviceLuks
export haveLuks="yes"
fi
if [ ! -z "$rwDevice" ] && [ ! -z "$roDevice" ];then
export UNIONFS_CONFIG="$rwDevice,$roDevice,$unionFST"
fi
}
#======================================
# canWrite
#--------------------------------------
function canWrite {
# /.../
# check if we can write to the given location
# returns zero on success.
# ---
local IFS=$IFS_ORIG
local prefix=$1
if [ -z "$prefix" ];then
prefix=/mnt
fi
if [ ! -d $prefix ];then
return 1
fi
if touch $prefix/can-write &>/dev/null;then
rm $prefix/can-write
return 0
fi
return 1
}
#======================================
# xenServer
#--------------------------------------
function xenServer {
# /.../
# check if the given kernel is a xen kernel and if so
# check if a dom0 or a domU setup was requested
# ----
local IFS=$IFS_ORIG
local kname=$1
local mountPrefix=$2
local sysmap="$mountPrefix/boot/System.map-$kname"
local isxen
if [ ! -e $sysmap ]; then
sysmap="$mountPrefix/boot/System.map"
fi
if [ ! -e $sysmap ]; then
Echo "No system map for kernel $kname found"
return 1
fi
isxen=$(grep -c "xen_base" $sysmap)
if [ $isxen -eq 0 ]; then
# not a xen kernel
return 1
fi
if [ -z "$kiwi_xendomain" ];then
# no xen domain set, assume domU
return 1
fi
if [ $kiwi_xendomain = "dom0" ];then
# xen dom0 requested
return 0
fi
return 1
}
#======================================
# makeLabel
#--------------------------------------
function makeLabel {
# /.../
# create boot label and replace all spaces with
# underscores. current bootloaders show the
# underscore sign as as space in the boot menu
# ---
local IFS=$IFS_ORIG
if \
[ ! $loader = "syslinux" ] && \
[ ! $loader = "extlinux" ] && \
[ ! $loader = "grub2" ]
then
echo $1 | tr " " "_"
else
echo $1
fi
}
#======================================
# waitForX
#--------------------------------------
function waitForX {
# /.../
# wait for the X-Server with PID $xserver_pid to
# become read for client calls
# ----
local IFS=$IFS_ORIG
local xserver_pid=$1
local testx=/usr/sbin/testX
local err=1
while kill -0 $xserver_pid 2>/dev/null ; do
sleep 1
if test -e /tmp/.X11-unix/X0 && test -x $testx ; then
$testx 16 2>/dev/null
err=$?
# exit code 1 -> XOpenDisplay failed...
if test $err = 1;then
Echo "TestX: XOpenDisplay failed"
return 1
fi
# exit code 2 -> color or dimensions doesn't fit...
if test $err = 2;then
Echo "TestX: color or dimensions doesn't fit"
kill $xserver_pid
return 1
fi
# server is running, detach oom-killer from it
echo -n '-17' > /proc/$xserver_pid/oom_adj
return 0
fi
done
return 1
}
#======================================
# startX
#--------------------------------------
function startX {
# /.../
# start X-Server and wait for it to become ready
# ----
local IFS=$IFS_ORIG
export DISPLAY=:0
local XServer=/usr/bin/Xorg
if [ -x /usr/X11R6/bin/Xorg ];then
XServer=/usr/X11R6/bin/Xorg
fi
$XServer -deferglyphs 16 vt07 &
export XServerPID=$!
if ! waitForX $XServerPID;then
Echo "Failed to start X-Server"
return 1
fi
return 0
}
#======================================
# stoppX
#--------------------------------------
function stoppX {
local IFS=$IFS_ORIG
if [ -z "$XServerPID" ];then
return
fi
if kill -0 $XServerPID 2>/dev/null; then
sleep 1 && kill $XServerPID
while kill -0 $XServerPID 2>/dev/null; do
sleep 1
done
fi
}
#======================================
# luksOpen
#--------------------------------------
function luksOpen {
# /.../
# check given device if it uses the LUKS extension
# if yes open the device and return the new
# /dev/mapper/ device name
# ----
local IFS=$IFS_ORIG
local ldev=$1
local name=$2
local retry=1
local info
if [ -z "$ldev" ];then
ldev=$(ddn $imageDiskDevice $kiwi_RootPart)
fi
#======================================
# check device for luks extension
#--------------------------------------
if ! cryptsetup isLuks $ldev &>/dev/null;then
return
fi
#======================================
# no map name set, build it from device
#--------------------------------------
if [ -z "$name" ];then
name=luks_$(basename "$ldev")
fi
#======================================
# luks map already exists, return
#--------------------------------------
if [ -e /dev/mapper/$name ];then
export luksDeviceOpened=/dev/mapper/$name
return
fi
#======================================
# ask for passphrase if not cached
#--------------------------------------
while true;do
if [ -z "$luks_pass" ];then
Echo "Try: $retry"
errorLogStop
luks_pass=$(runInteractive \
"--insecure --passwordbox "\"$TEXT_LUKS\"" 10 60"
)
errorLogContinue
fi
if echo "$luks_pass" | cryptsetup luksOpen $ldev $name;then
break
fi
unset luks_pass
if [ -n "$luks_open_can_fail" ]; then
unset luksDeviceOpened
return 1
fi
if [ $retry -eq 3 ];then
systemException \
"Max retries reached... reboot" \
"reboot"
fi
retry=$(($retry + 1))
done
#======================================
# wait for the luks map to appear
#--------------------------------------
if ! waitForStorageDevice /dev/mapper/$name &>/dev/null;then
systemException \
"LUKS map /dev/mapper/$name doesn't appear... fatal !" \
"reboot"
fi
#======================================
# store luks device and return
#--------------------------------------
export luksDeviceOpened=/dev/mapper/$name
return 0
}
#======================================
# luksResize
#--------------------------------------
function luksResize {
# /.../
# check if luksDeviceOpened is defined and
# run cryptsetup resize on the mapper name
# ----
local IFS=$IFS_ORIG
if [ ! -z "$luksDeviceOpened" ] && [ -e $luksDeviceOpened ];then
cryptsetup resize $luksDeviceOpened
udevPending
fi
}
#======================================
# luksClose
#--------------------------------------
function luksClose {
# /.../
# close all open LUKS mappings
# ----
local IFS=$IFS_ORIG
local name=$1
#======================================
# close specified name if set
#--------------------------------------
if [ -n "$1" ]; then
name=$(basename $1)
cryptsetup luksClose $name
return
fi
#======================================
# close all luks* map names
#--------------------------------------
for i in /dev/mapper/luks*;do
name=$(basename "$i")
cryptsetup luksClose $name
done
}
#======================================
# importText
#--------------------------------------
function importText {
# /.../
# read in all texts from the catalog
# ----
local IFS=$IFS_ORIG
export TEXT_TIMEOUT=$(
getText "Boot continues in 10 sec...")
export TEXT_OK=$(
getText "OK")
export TEXT_CANCEL=$(
getText "Cancel")
export TEXT_YES=$(
getText "Yes")
export TEXT_NO=$(
getText "No")
export TEXT_EXIT=$(
getText "Exit")
export TEXT_LUKS=$(
getText "Enter LUKS passphrase")
export TEXT_LICENSE=$(
getText "Do you accept the license agreement ?")
export TEXT_RESTORE=$(
getText "Do you want to start the System-Restore ?")
export TEXT_REPAIR=$(
getText "Do you want to start the System-Recovery ?")
export TEXT_RECOVERYTITLE=$(
getText "Restoring base operating system...")
export TEXT_INSTALLTITLE=$(
getText "Installation...")
export TEXT_CDPULL=$(
getText "Please remove the CD/DVD before reboot")
export TEXT_USBPULL=$(
getText "Please unplug the USB stick before reboot")
export TEXT_CDPULL_SDOWN=$(
getText "Please remove the CD/DVD before shutdown")
export TEXT_USBPULL_SDOWN=$(
getText "System will be shutdown. Remove USB stick before power on")
export TEXT_SELECT=$(
getText "Select disk for installation:")
export TEXT_BOOT_SETUP_FAILED=$(
getText "Bootloader installation has failed")
export TEXT_BOOT_SETUP_FAILED_INFO=$(
getText "The system will not be able to reboot. Please make sure to fixup and install the bootloader before next reboot. Check $ELOG_FILE for details")
}
#======================================
# selectLanguage
#--------------------------------------
function selectLanguage {
# /.../
# select language if not yet done. The value is
# used for all dialog windows with i18n support
# ----
local IFS=$IFS_ORIG
local title="\"Select Language\""
local list="en_US \"[ English ]\" on"
local list_orig=$list
local zh_CN=Chinese
local zh_TW=Taiwanese
local ru_RU=Russian
local de_DE=German
local ar_AR=Arabic
local cs_CZ=Czech
local el_GR=Greek
local es_ES=Spanish
local fi_FI=Finnish
local fr_FR=French
local hu_HU=Hungarian
local it_IT=Italian
local ja_JP=Japanese
local ko_KR=Korean
local nl_NL=Dutch
local pl_PL=Polish
local pt_BR=Portuguese
local sv_SE=Swedish
local tr_TR=Turkish
local nb_NO=Norwegian
local da_DK=Danish
local pt_PT=Portuguese
local en_GB=English
local code
local lang
#======================================
# Exports (Texts), default language
#--------------------------------------
importText
#======================================
# Check language environment
#--------------------------------------
if [ ! -z "$kiwi_oemunattended" ] && [ "$DIALOG_LANG" = "ask" ];then
# answer the language question in unatteneded mode
DIALOG_LANG=en_US
fi
if [ "$DIALOG_LANG" = "ask" ];then
for code in $(echo $kiwi_language | tr "," " ");do
if [ $code = "en_US" ];then
continue
fi
eval lang=\$$code
list="$list $code \"[ $lang ]\" off"
done
if [ "$list" = "$list_orig" ];then
DIALOG_LANG=en_US
else
DIALOG_LANG=$(runInteractive \
"--timeout 10 --no-cancel \
--backtitle \"$TEXT_TIMEOUT\" \
--radiolist $title 20 40 10 $list"
)
fi
fi
export LANG=$DIALOG_LANG.utf8
#======================================
# Exports (Texts), selected language
#--------------------------------------
importText
}
#======================================
# getText
#--------------------------------------
function getText {
# /.../
# return translated text
# ----
local IFS=$IFS_ORIG
local text=$(gettext kiwi "$1")
if [ ! -z "$2" ];then
text=$(echo $text | sed -e s"@%1@$2@")
fi
if [ ! -z "$3" ];then
text=$(echo $text | sed -e s"@%2@$3@")
fi
echo "$text"
}
#======================================
# displayEULA
#--------------------------------------
function displayEULA {
# /.../
# display in a dialog window the text part of the
# selected language file(s). The files are searched
# by the names in kiwi_showlicense
# ----
local IFS=$IFS_ORIG
local code=$(echo $DIALOG_LANG | cut -f1 -d_)
if [ -z "$kiwi_showlicense" ];then
Echo "No license name(s) configured"
return
fi
for name in $kiwi_showlicense;do
#======================================
# select license file by name
#--------------------------------------
code=/$name.$code.txt
if [ ! -f $code ];then
code=/$name.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name.$code.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name.txt
fi
if [ ! -f $code ];then
code=/etc/YaST2/licenses/base/$name
fi
if [ ! -f $code ];then
Echo "License with basename $name not found... skipped"
continue
fi
#======================================
# show license until accepted
#--------------------------------------
while true;do
Dialog --textbox $code 20 70 \
--and-widget --extra-button \
--extra-label "$TEXT_NO" \
--ok-label "$TEXT_YES" \
--cancel-label "$TEXT_CANCEL" \
--yesno "\"$TEXT_LICENSE\"" \
5 45
case $? in
0 ) break
;;
1 ) continue
;;
* ) systemException \
"License not accepted... reboot" \
"reboot"
;;
esac
done
done
}
#======================================
# ddn
#--------------------------------------
function ddn {
# /.../
# print disk device name (node name) according to the
# linux device node specs: If the last character of the
# device is a letter, attach the partition number. If the
# last character is a number, attach a 'p' and then the
# partition number. Exceptions:
# a) If the device name starts with /dev/disk
# the /dev/disk/<name>[-_]partN schema is used exclusively
# b) If the device name starts with /dev/ram
# the /dev/mapper/<name>pN schema is used exclusively
# c) If the device name starts with /dev/mapper
# the /dev/mapper/<name>_partN schema is checked optionally
# if it does not exist the default device node specs applies
# ----
local IFS=$IFS_ORIG
if echo $1 | grep -q "^\/dev\/disk\/" ; then
if [ -e $1"_part"$2 ]; then
echo $1"_part"$2
return
fi
echo $1"-part"$2
return
elif echo $1 | grep -q "^\/dev\/mapper\/" ; then
if [ -e $1"_part"$2 ]; then
echo $1"_part"$2
return
fi
elif echo $1 | grep -q "^\/dev\/ram";then
name=$(echo $1 | tr -d /dev)
echo /dev/mapper/${name}p$2
return
fi
local lastc=$(echo $1 | sed -e 's@\(^.*\)\(.$\)@\2@')
if echo $lastc | grep -qP "^\d+$";then
echo $1"p"$2
return
fi
echo $1$2
}
#======================================
# dn
#--------------------------------------
function dn {
# /.../
# print disk name (device name) according to the
# linux device node specs: If the device matches "p"
# followed by a number remove pX else remove
# the last number. Exceptions:
# loop devices
# ----
local IFS=$IFS_ORIG
local part=$(getDiskDevice $1)
if [[ $part =~ dev/loop[0-9] ]];then
echo $part
return
fi
if [[ $part =~ mapper/loop ]];then
part=$(echo $part | sed -e s@/mapper@@)
fi
local part_new=$(echo $part | sed -e 's@\(^.*\)\(p[0-9].*$\)@\1@')
if [ $part = $part_new ];then
part_new=$(echo $part | sed -e 's@\(^.*\)\([0-9].*$\)@\1@')
fi
echo $part_new
}
#======================================
# nd
#--------------------------------------
function nd {
# /.../
# print the number of the disk device according to the
# device node name.
# ----
local IFS=$IFS_ORIG
local part=$(getDiskDevice $1)
local part_new=$(echo $part | sed -e 's@\(^.*\)p\([0-9].*$\)@\2@')
if [ $part = $part_new ];then
part_new=$(echo $part | sed -e 's@\(^.*\)\([0-9].*$\)@\2@')
fi
echo $part_new
}
#======================================
# runInteractive
#--------------------------------------
function runInteractive {
# /.../
# run dialog in a bash inside an fbiterm or directly
# on the running terminal. Make the terminal the controlling
# tty first. The output of the dialog call is stored in
# a file and printed as result to this function
# ----
local IFS=$IFS_ORIG
hideSplash
local r=/tmp/rid
local code
echo "dialog $@ 2> /tmp/out" > $r
echo "echo -n \$? > /tmp/out.exit" >> $r
if FBOK;then
setctsid $ELOG_EXCEPTION fbiterm -m $UFONT -- bash -i $r
else
setctsid $ELOG_EXCEPTION bash -i $r
fi
code=$(cat /tmp/out.exit)
if [ ! $code = 0 ];then
return $code
fi
cat /tmp/out && rm -f /tmp/out* $r
return 0
}
#======================================
# createCustomHybridPersistent
#--------------------------------------
function createCustomHybridPersistent {
# /.../
# import the write space for the hybrid according to
# the information given by kiwi_cowdevice and kiwi_cowsystem
# ----
local IFS=$IFS_ORIG
#======================================
# check for custom cow location
#--------------------------------------
if [ -z "$kiwi_cowdevice" ];then
return
fi
if [ -z "$kiwi_cowsystem" ];then
return
fi
Echo "Using custom cow file: $kiwi_cowdevice:$kiwi_cowsystem"
#======================================
# got custom cow location
#--------------------------------------
waitForStorageDevice $kiwi_cowdevice
#======================================
# mount cow device
#--------------------------------------
mkdir /cow
if ! mount $kiwi_cowdevice /cow;then
systemException \
"Failed to mount cow device !" \
"reboot"
fi
#======================================
# does the cow file exist
#--------------------------------------
if [ ! -f /cow/$kiwi_cowsystem ];then
Echo "Can't find cow file on write partition... deactivated"
unset kiwi_hybridpersistent
umount /cow
rmdir /cow
return
fi
#======================================
# loop setup cow space
#--------------------------------------
kiwi_cowdevice=$(loop_setup /cow/$kiwi_cowsystem)
if [ ! -e $kiwi_cowdevice ];then
systemException \
"Failed to loop setup cow file !" \
"reboot"
fi
#======================================
# export read-write device name
#--------------------------------------
export skipSetupBootPartition=1
export HYBRID_RW=$kiwi_cowdevice
}
#======================================
# createHybridPersistent
#--------------------------------------
function createHybridPersistent {
# /.../
# create a new partition to handle the copy-on-write actions
# by the clicfs live mount. A new partition with a filesystem
# inside labeled as 'hybrid' is created for this purpose
# ----
local IFS=$IFS_ORIG
local device=$1
local input=/part.input
local pID
rm -f $input
#======================================
# check for custom cow location
#--------------------------------------
if [ ! -z "$kiwi_cowdevice" ] || [ ! -z "$kiwi_cowsystem" ];then
return
fi
#======================================
# check persistent write partition
#--------------------------------------
local hybrid_fs=$HYBRID_PERSISTENT_FS
if [ ! -z "$kiwi_hybridpersistent_filesystem" ];then
hybrid_fs=$kiwi_hybridpersistent_filesystem
fi
for pID in 4 3 2 1;do
local partd=$(ddn $device $pID)
local label=$(blkid $partd -s LABEL -o value)
if [ "$label" = "hybrid" ];then
Echo "Existing persistent hybrid partition found"
if [ $hybrid_fs = "fat" ];then
if ! setupHybridCowDevice;then
Echo "Failed to setup hybrid cow device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
else
export HYBRID_RW=$partd
fi
export skipSetupBootPartition=1
return
fi
done
#======================================
# create persistent write partition
#--------------------------------------
Echo "Creating hybrid persistent partition for COW data"
export imageDiskDevice=$device
if [ ! -e "$imageDiskDevice" ];then
Echo "Disk device $device does not exist, most likely not a disk"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
# Find partition ID we could use to create a new write partition
for pID in 1 2 3 4;do
local partd=$(ddn $device $pID)
if [ ! -e "$partd" ];then
Echo "Creating write partition at ID: $pID"
break
fi
done
if [ "$kiwi_firmware" = "bios" ];then
# we support creation of partitions which are not in ascending order
# in bios mode. The partition table created via isohybrid starts at
# the second partition to allow the creation of the write partition
# as first partition. Reason for this is to support Windows systems
# with a fat partition as write space which has to be the first
# partition otherwise Windows can't cope with it.
#
# Such a write partition can be created using fdisk, however for
# EFI capable hybrid ISO images the GPT table is used which fdisk
# can't handle.
#
# Therefore we use fdisk for bios firmware images and parted for
# efi|uefi firmware images.
#
# This also means we don't support fat
# based persistent write partitions to be created as first partition
# on efi|uefi ISO hybrid images
echo -e "n\np\n$pID\n\n\nw\nq" | fdisk $imageDiskDevice
else
createPartitionerInput \
n p:lxrw $pID . . t $pID $HYBRID_PERSISTENT_ID
callPartitioner $input
fi
#======================================
# check partition device node
#--------------------------------------
if [ $partitionerWriteStatus != 0 ];then
Echo "Partition creation failed for device $device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
if ! waitForStorageDevice $(ddn $device $pID);then
Echo "Partition $pID on $device doesn't appear... fatal !"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
#======================================
# create filesystem on write partition
#--------------------------------------
local hybrid_device=$(ddn $device $pID)
local exception_handling="false"
if ! createFilesystem \
$hybrid_device "" "" "hybrid" $exception_handling $hybrid_fs
then
Echo "Failed to create hybrid persistent filesystem"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
#======================================
# export read-write device name
#--------------------------------------
if [ $hybrid_fs = "fat" ];then
# The fat filesystem is not really suitable to be used as rootfs
# for linux. Therefore we create a btrfs based file which we store
# on the fat filesystem and loop setup it. The size of the file
# is set to half the size of the fat device
if ! setupHybridCowDevice $hybrid_device;then
Echo "Failed to setup hybrid cow device"
Echo "Persistent writing deactivated"
unset kiwi_hybridpersistent
return
fi
else
export HYBRID_RW=$(ddn $device $pID)
fi
#======================================
# skip boot partition setup on overlay
#--------------------------------------
export skipSetupBootPartition=1
}
#======================================
# setupHybridCowDevice
#--------------------------------------
function setupHybridCowDevice {
local IFS=$IFS_ORIG
local hybrid_device=$1
mkdir -p /cow
for i in 1 2 3;do
mount -L hybrid /cow && break || sleep 2
done
if [ ! $? = 0 ];then
Echo "Failed to mount hybrid persistent filesystem !"
return 1
fi
if [ ! -e "/cow/cowfile" ];then
local cowsize=$(($(blockdev --getsize64 $hybrid_device) / 2))
local exception_handling="false"
qemu-img create /cow/cowfile $cowsize
if ! createFilesystem \
"/cow/cowfile" "" "" "" $exception_handling "btrfs"
then
Echo "Failed to create hybrid persistent cow filesystem"
return 1
fi
fi
export HYBRID_RW=$(loop_setup /cow/cowfile)
if [ ! -e "$cowdevice" ];then
Echo "Failed to loop setup hybrid cow file !"
return 1
fi
return 0
}
#======================================
# callPartitioner
#--------------------------------------
function callPartitioner {
local IFS=$IFS_ORIG
local input=$1
if [ $PARTITIONER = "fdasd" ];then
Echo "Partition the disk according to real geometry [ fdasd ]"
echo "w" >> $input
echo "q" >> $input
fdasd $imageDiskDevice < $input 1>&2
export partitionerWriteStatus=$?
if test $partitionerWriteStatus != 0; then
systemException "Failed to create partition table" "reboot"
fi
udevPending
blockdev --rereadpt $imageDiskDevice
else
# /.../
# nothing to do for parted here as we write
# imediately with parted and don't create a
# command input file as for fdasd but we re-read
# the disk so that the new table will be used
# ----
udevPending
blockdev --rereadpt $imageDiskDevice
fi
}
#======================================
# createPartitionerInput
#--------------------------------------
function createPartitionerInput {
local IFS=$IFS_ORIG
if isDASDDevice; then
PARTITIONER=fdasd
fi
if [ $PARTITIONER = "fdasd" ];then
createFDasdInput $@
else
updatePartitionTable $imageDiskDevice
Echo "Partition the disk according to real geometry [ parted ]"
partedInit $imageDiskDevice
partedSectorInit $imageDiskDevice
createPartedInput $imageDiskDevice $@
fi
}
#======================================
# createFDasdInput
#--------------------------------------
function createFDasdInput {
local IFS=$IFS_ORIG
local input=/part.input
local ignore_once=0
local ignore=0
normalizeRepartInput $*
for cmd in ${pcmds[*]};do
if [ $ignore = 1 ] && echo $cmd | grep -qE '[dntwq]';then
ignore=0
elif [ $ignore = 1 ];then
continue
fi
if [ $ignore_once = "1" ];then
ignore_once=0
continue
fi
if [ $cmd = "a" ];then
ignore=1
continue
fi
if [[ $cmd =~ ^p: ]];then
ignore_once=1
continue
fi
if [ $cmd = "83" ] || [ $cmd = "8e" ];then
cmd=1
fi
if [ $cmd = "82" ];then
cmd=2
fi
if [ $cmd = "." ];then
echo >> $input
continue
fi
echo $cmd >> $input
done
}
#======================================
# partedInit
#--------------------------------------
function partedInit {
# /.../
# initialize current partition table output
# as well as the number of cylinders and the
# cyliner size in kB for this disk
# ----
local IFS=$IFS_ORIG
local devname=$1
local device=$(getDiskDevice $devname)
IFS=""
local parted=$(parted -m -s $device unit cyl print | grep -v Warning:)
local header=$(echo $parted | head -n 3 | tail -n 1)
local ccount=$(echo $parted | grep ^$device | cut -f 2 -d: | tr -d cyl)
local cksize=$(echo $header | cut -f4 -d: | cut -f1 -dk)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
if [[ $plabel =~ gpt ]];then
plabel=gpt
fi
export partedTableType=$plabel
export partedOutput=$parted
export partedCylCount=$ccount
export partedCylKSize=$cksize
}
#======================================
# partedWrite
#--------------------------------------
function partedWrite {
# /.../
# call parted with current command queue.
# This will immediately change the partition table
# ----
local IFS=$IFS_ORIG
local device=$1
local cmds=$2
local opts
if [ $PARTED_HAVE_ALIGN -eq 1 ];then
opts="-a cyl"
fi
parted $opts -m -s $device unit cyl $cmds
export partitionerWriteStatus=$?
if [ $partitionerWriteStatus != 0 ];then
if [ ! -z "$kiwi_hybridpersistent" ];then
# /.../
# in case of a iso hybrid table don't stop with a fatal reboot
# exception on error. In this case we want to proceed with the
# boot process but deactivate the persistent write feature
# ----
return 1
fi
systemException "Failed to create partition table" "reboot"
fi
partedInit $device
}
#======================================
# partedSectorInit
#--------------------------------------
function partedSectorInit {
# /.../
# return aligned start/end sectors of current table.
# ----
local IFS=$IFS_ORIG
local disk=$1
local s_start
local s_stopp
unset startSectors
unset endSectors
local align=$((kiwi_align / kiwi_sectorsize))
for i in $(
parted -m -s $disk unit s print |\
grep -E ^[1-9]+:| cut -f2-3 -d: | tr -d s
);do
s_start=$(echo $i | cut -f1 -d:)
s_stopp=$(echo $i | cut -f2 -d:)
if [ -z "$startSectors" ];then
startSectors=${s_start}s
else
startSectors=${startSectors}:${s_start}s
fi
if [ -z "$endSectors" ];then
endSectors=$((s_stopp/align*align+align))s
else
endSectors=$endSectors:$((s_stopp/align*align+align))s
fi
done
# /.../
# in case of an empty disk we use the default start sector
# ----
if [ -z "$startSectors" ];then
startSectors=${kiwi_startsector}s
fi
}
#======================================
# partedEndCylinder
#--------------------------------------
function partedEndCylinder {
# /.../
# return end cylinder of given partition, next
# partition must start at return value plus 1
# ----
local IFS=$IFS_ORIG
local part=$(($1 + 3))
IFS=""
local header=$(echo $partedOutput | head -n $part | tail -n 1)
local ccount=$(echo $header | cut -f3 -d: | tr -d cyl)
echo $ccount
}
#======================================
# partedMBToCylinder
#--------------------------------------
function partedMBToCylinder {
# /.../
# convert size given in MB to cylinder count
# ----
local IFS=$IFS_ORIG
local sizeBytes=$(($1 * 1048576))
local cylreq=$(echo "scale=0; $sizeBytes / ($partedCylKSize * 1000)" | bc)
echo $cylreq
}
#======================================
# createPartedInput
#--------------------------------------
function createPartedInput {
# /.../
# evaluate partition instructions and turn them
# into a parted command line queue. As soon as the
# geometry data would be changed according to the
# last partedInit() call the command queue is processed
# and the partedInit() will be called afterwards
# ----
local IFS=$IFS_ORIG
local disk=$1
shift
local index=0
local partid
local partnm
local pstart
local pstopp
local value
local cmdq
#======================================
# normalize commands
#--------------------------------------
normalizeRepartInput $*
for cmd in ${pcmds[*]};do
case $cmd in
#======================================
# delete partition
#--------------------------------------
"d")
partid=${pcmds[$index + 1]}
partid=$(($partid / 1))
cmdq="$cmdq rm $partid"
partedWrite "$disk" "$cmdq"
cmdq=""
;;
#======================================
# create new partition
#--------------------------------------
"n")
partnm=${pcmds[$index + 1]}
partid=${pcmds[$index + 2]}
partid=$(($partid / 1))
pstart=${pcmds[$index + 3]}
if [ ! "$partedTableType" = "gpt" ];then
partnm=primary
else
partnm=$(echo $partnm | cut -f2 -d:)
fi
if [ "$pstart" = "1" ];then
pstart=$(echo $startSectors | cut -f $partid -d:)
fi
if [ $pstart = "." ];then
# start is next sector according to previous partition
pstart=$(($partid - 1))
if [ $pstart -gt 0 ];then
pstart=$(echo $endSectors | cut -f $pstart -d:)
else
pstart=$(echo $startSectors | cut -f $partid -d:)
fi
fi
pstopp=${pcmds[$index + 4]}
if [ $pstopp = "." ];then
# use rest of the disk for partition end
pstopp=$partedCylCount
elif echo $pstopp | grep -qi M;then
# calculate stopp cylinder from size
pstopp=$(($partid - 1))
if [ $pstopp -gt 0 ];then
pstopp=$(partedEndCylinder $pstopp)
fi
value=$(echo ${pcmds[$index + 4]} | cut -f1 -dM | tr -d +)
value=$(partedMBToCylinder $value)
pstopp=$((1 + $pstopp + $value))
if [ $pstopp -gt $partedCylCount ];then
# given size is out of bounds, reduce to end of disk
pstopp=$partedCylCount
fi
fi
cmdq="$cmdq mkpart $partnm $pstart $pstopp"
partedWrite "$disk" "$cmdq"
partedSectorInit $imageDiskDevice
cmdq=""
;;
#======================================
# change partition ID
#--------------------------------------
"t")
ptypex=${pcmds[$index + 2]}
partid=${pcmds[$index + 1]}
flagok=1
if [ "$ptypex" = "82" ];then
if [[ $kiwi_iname =~ boot-suse ]];then
# /.../
# suse parted is not able to set swap flag. I consider
# this as a bug in the suse parted tool. In order to
# proceed here kiwi uses suse parted 'type' command
# extension.
#
cmdq="$cmdq set $partid type 0x$ptypex"
elif [[ $kiwi_iname =~ boot-rhel ]];then
# /.../
# parted on RHEL is not able to set swap flag. I don't
# have a good solution for this thus we skip the flag
# setup in this case
#
flagok=0
else
cmdq="$cmdq set $partid swap on"
fi
elif [ "$ptypex" = "fd" ];then
cmdq="$cmdq set $partid raid on"
elif [ "$ptypex" = "8e" ];then
cmdq="$cmdq set $partid lvm on"
elif [ "$ptypex" = "83" ];then
# default partition type set by parted is linux(83)
flagok=0
else
# be careful, this is a suse parted extension
cmdq="$cmdq set $partid type 0x$ptypex"
fi
if [ ! "$partedTableType" = "gpt" ] && [ $flagok = 1 ];then
partedWrite "$disk" "$cmdq"
fi
cmdq=""
;;
esac
index=$(($index + 1))
done
}
#======================================
# normalizeRepartInput
#--------------------------------------
function normalizeRepartInput {
local IFS=$IFS_ORIG
local pcmds_fix
local index=0
local index_fix=0
local partid
local cmd
#======================================
# create list of commands
#--------------------------------------
unset pcmds
for cmd in $*;do
pcmds[$index]=$cmd
index=$(($index + 1))
done
index=0
#======================================
# fix list of commands
#--------------------------------------
while [ ! -z "${pcmds[$index]}" ];do
cmd=${pcmds[$index]}
pcmds_fix[$index_fix]=$cmd
case $cmd in
"d")
partid=${pcmds[$index + 1]}
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the deletion
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=1
fi
;;
"n")
partid=${pcmds[$index + 2]}
if [ ! "$PARTITIONER" = "fdasd" ];then
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the creation
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=${pcmds[$index + 1]}
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=4
index=$(($index + 1))
fi
fi
;;
"t")
partid=${pcmds[$index + 1]}
if ! echo $partid | grep -q -E "^[0-9]+$";then
# make sure there is a ID set for the type
index_fix=$(($index_fix + 1))
pcmds_fix[$index_fix]=1
fi
;;
esac
index=$(($index + 1))
index_fix=$(($index_fix + 1))
done
#======================================
# use fixed list and print log info
#--------------------------------------
unset pcmds
pcmds=(${pcmds_fix[*]})
unset pcmds_fix
echo "Normalized Repartition input: ${pcmds[*]}" 1>&2
}
#======================================
# reloadKernel
#--------------------------------------
function reloadKernel {
# /.../
# reload the given kernel and initrd. This function
# checks USB stick devices for a kernel and initrd
# and shows them in a dialog window. The selected kernel
# and initrd is loaded via kexec.
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# check proc/cmdline
#--------------------------------------
ldconfig
mountSystemFilesystems &>/dev/null
if ! cat /proc/cmdline | grep -qi "hotfix=1";then
umountSystemFilesystems
return
fi
#======================================
# check for kexec
#--------------------------------------
if [ ! -x /sbin/kexec ];then
systemException "Can't find kexec" "reboot"
fi
#======================================
# start udev
#--------------------------------------
touch /etc/modules.conf
touch /lib/modules/*/modules.dep
udevStart
errorLogStart
probeDevices
#======================================
# search hotfix stick
#--------------------------------------
USBStickDevice kexec
if [ $stickFound = 0 ];then
systemException "No hotfix USB stick found" "reboot"
fi
#======================================
# mount stick
#--------------------------------------
if ! mount -o ro $stickDevice $prefix;then
systemException "Failed to mount hotfix stick" "reboot"
fi
#======================================
# load kernel
#--------------------------------------
kexec -l $prefix/linux.kexec --initrd=$prefix/initrd.kexec \
--append="$(cat /proc/cmdline | sed -e s"@hotfix=1@@")"
if [ ! $? = 0 ];then
systemException "Failed to load hotfix kernel" "reboot"
fi
#======================================
# go for gold
#--------------------------------------
exec kexec -e
}
#======================================
# resizeFilesystem
#--------------------------------------
function resizeFilesystem {
local IFS=$IFS_ORIG
local deviceResize=$1
local callme=$2
local ramdisk=0
local resize_fs
local check
local mpoint=/fs-resize
udevPending
mkdir -p $mpoint
if echo $deviceResize | grep -qi "/dev/ram";then
ramdisk=1
fi
if [ -z "$FSTYPE" ];then
probeFileSystem $deviceResize
fi
if [ "$FSTYPE" = "reiserfs" ];then
resize_fs="resize_reiserfs -q $deviceResize"
check="reiserfsck -y $deviceResize"
elif [ "$FSTYPE" = "ext2" ];then
resize_fs="resize2fs -f -F -p $deviceResize"
check="e2fsck -p $deviceResize"
if [ $ramdisk -eq 1 ];then
resize_fs="resize2fs -f $deviceResize"
fi
elif [ "$FSTYPE" = "ext3" ];then
resize_fs="resize2fs -f -F -p $deviceResize"
check="e2fsck -p $deviceResize"
if [ $ramdisk -eq 1 ];then
resize_fs="resize2fs -f $deviceResize"
fi
elif [ "$FSTYPE" = "ext4" ];then
resize_fs="resize2fs -f -F -p $deviceResize"
check="e2fsck -p $deviceResize"
if [ $ramdisk -eq 1 ];then
resize_fs="resize2fs -f $deviceResize"
fi
elif [ "$FSTYPE" = "btrfs" ];then
resize_fs="mount $deviceResize $mpoint &&"
if lookup btrfs &>/dev/null;then
resize_fs="$resize_fs btrfs filesystem resize max $mpoint"
resize_fs="$resize_fs;umount $mpoint"
else
resize_fs="$resize_fs btrfsctl -r max $mpoint;umount $mpoint"
fi
check="btrfsck $deviceResize"
elif [ "$FSTYPE" = "xfs" ];then
resize_fs="mount $deviceResize $mpoint &&"
resize_fs="$resize_fs xfs_growfs $mpoint;umount $mpoint"
check="xfs_repair -n $deviceResize"
elif [ "$FSTYPE" = "zfs" ];then
local device=$(getDiskID $deviceResize)
resize_fs="zpool import kiwipool && udevPending &&"
resize_fs="$resize_fs zpool online -e kiwipool $device;"
resize_fs="$resize_fs zpool export kiwipool"
else
# don't know how to resize this filesystem
Echo "Don't know how to resize ${FSTYPE}... skip it"
return
fi
if [ -z "$callme" ];then
if [ $ramdisk -eq 0 ] && [ ! -z "$check" ];then
Echo "Checking $FSTYPE filesystem on ${deviceResize}..."
eval $check
fi
Echo "Resizing $FSTYPE filesystem on ${deviceResize}..."
eval $resize_fs
if [ ! $? = 0 ];then
systemException \
"Failed to resize/check filesystem" \
"reboot"
fi
else
echo $resize_fs
fi
}
#======================================
# resetMountCounter
#--------------------------------------
function resetMountCounter {
local IFS=$IFS_ORIG
local curtype=$FSTYPE
local command
for device in \
$imageRootDevice $imageBootDevice \
$imageRecoveryDevice
do
if [ ! -e $device ];then
continue
fi
probeFileSystem $device
if [ "$FSTYPE" = "ext2" ];then
command="tune2fs -c -1 -i 0"
elif [ "$FSTYPE" = "ext3" ];then
command="tune2fs -c -1 -i 0"
elif [ "$FSTYPE" = "ext4" ];then
command="tune2fs -c -1 -i 0"
else
# nothing to do here...
continue
fi
eval $command $device 1>&2
done
FSTYPE=$curtype
}
#======================================
# createFilesystem
#--------------------------------------
function createFilesystem {
local IFS=$IFS_ORIG
local deviceCreate=$1
local blocks=$2
local uuid=$3
local label=$4
local exception_handling=$5
local filesystem=$6
local opts=$7
if [ -z "$filesystem" ];then
filesystem=$FSTYPE
fi
if [ -z "$exception_handling" ];then
exception_handling="true"
else
exception_handling="false"
fi
if [[ "$filesystem" =~ ext ]];then
opts="$opts -F"
if [ ! -z "$uuid" ];then
opts="$opts -U $uuid"
fi
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
elif [ "$filesystem" = "reiserfs" ];then
opts="$opts -f"
if [ ! -z "$uuid" ];then
opts="$opts -d $uuid"
fi
if [ ! -z "$label" ];then
opts="$opts -l $label"
fi
elif [ "$filesystem" = "btrfs" ];then
opts="$opts -f"
if [ ! -z "$uuid" ];then
opts="$opts -U $uuid"
fi
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
if [ ! -z "$blocks" ];then
local bytes=$((blocks * 4096))
opts="$opts -b $bytes"
fi
elif [ "$filesystem" = "fat" ];then
if [ ! -z "$label" ];then
opts="$opts -n $label"
fi
elif [ "$filesystem" = "ntfs" ];then
if [ ! -z "$label" ];then
opts="$opts -L $label"
fi
fi
if [ "$filesystem" = "reiserfs" ];then
mkreiserfs $opts $deviceCreate $blocks 1>&2
elif [ "$filesystem" = "ext2" ];then
mkfs.ext2 $opts $deviceCreate $blocks 1>&2
elif [ "$filesystem" = "ext3" ];then
mkfs.ext3 $opts $deviceCreate $blocks 1>&2
elif [ "$filesystem" = "ext4" ];then
mkfs.ext4 $opts $deviceCreate $blocks 1>&2
elif [ "$filesystem" = "btrfs" ];then
# delete potentially existing btrfs on the device because even
# with the force option enabled mkfs.btrfs refuses to create a
# filesystem if the existing metadata contains the same UUID
dd if=/dev/zero of=$deviceCreate bs=1M count=1 conv=notrunc
mkfs.btrfs $opts $deviceCreate
elif [ "$filesystem" = "xfs" ];then
mkfs.xfs -f $deviceCreate
xfs_admin -U $uuid $deviceCreate
elif [ "$filesystem" = "fat" ];then
mkfs.fat $opts $deviceCreate $blocks 1>&2
elif [ "$filesystem" = "ntfs" ];then
mkfs.ntfs $opts $deviceCreate $blocks 1>&2
else
# use ext3 by default
mkfs.ext3 $opts $deviceCreate $blocks 1>&2
fi
if [ $exception_handling = "false" ];then
return $?
fi
if [ ! $? = 0 ];then
systemException \
"Failed to create filesystem" \
"reboot"
fi
}
#======================================
# restoreBtrfsSubVolumes
#--------------------------------------
function restoreBtrfsSubVolumes {
local IFS=$IFS_ORIG
local root=$1
local variable
local volume
local content
local volpath
local mpoint
local mppath
local volbase
btrfs subvolume create $root/@ || return
local rootid=$(btrfs subvolume list $root | cut -f2 -d ' ')
btrfs subvolume set-default $rootid $root || return
for i in $(cat /.profile | grep -E 'kiwi_LVM_|kiwi_allFreeVolume');do
variable=$(echo $i|cut -f1 -d=)
volume=$(echo $i| cut -f3- -d_ | cut -f1 -d=)
content=$(echo $i|cut -f2 -d= | tr -d \' | tr -d \")
volpath=$(echo $content | cut -f3 -d:)
if [ -z "$volpath" ];then
volpath=$(echo $volume | tr _ /)
fi
mpoint=$(echo $volpath | sed -e s@^LV@@)
volbase="$root/@/$(dirname $mpoint)"
if [ ! -d $volbase ];then
mkdir -p $volbase
fi
btrfs subvolume create $root/@/$mpoint || return
done
umount $root && mount $imageRootDevice $root
}
#======================================
# restoreLVMMetadata
#--------------------------------------
function restoreLVMPhysicalVolumes {
# /.../
# restore the pysical volumes by the given restore file
# created from vgcfgbackup. It's important to create them
# with the same uuid's compared to the restore file
# ----
local IFS=$IFS_ORIG
local restorefile=$1
cat $restorefile | grep -A2 -E 'pv[0-9] {' | while read line;do
if [ -z "$uuid" ];then
uuid=$(echo $line | grep 'id =' |\
cut -f2 -d= | tr -d \")
fi
if [ -z "$pdev" ];then
pdev=$(echo $line|grep 'device =' |\
cut -f2 -d\" | cut -f1 -d\")
fi
if [ ! -z "$pdev" ];then
pvcreate -u $uuid $pdev
unset uuid
unset pdev
fi
done
}
#======================================
# pxeCheckServer
#--------------------------------------
function pxeCheckServer {
# /.../
# check the kernel commandline parameter kiwiserver.
# If it exists its contents will be used as
# server address stored in the SERVER variabe
# ----
local IFS=$IFS_ORIG
if [ ! -z $kiwiserver ];then
Echo "Found server in kernel cmdline"
SERVER=$kiwiserver
fi
if [ ! -z $kiwiservertype ]; then
Echo "Found server type in kernel cmdline"
SERVERTYPE=$kiwiservertype
else
SERVERTYPE=tftp
fi
}
#======================================
# pxeSetupDownloadServer
#--------------------------------------
function pxeSetupDownloadServer {
# /.../
# the pxe image system requires a server which stores
# the image files. This function setup the SERVER variable
# pointing to that server using the following heuristic:
# ----
# 1) check for $kiwiserver from cmdline
# 2) try tftp.$DOMAIN whereas $DOMAIN is from dhcpcd-info
# 3) try address of DHCP server if no servertype or tftp is used
# 4) fail if no location was found
# ----
local IFS=$IFS_ORIG
pxeCheckServer
if [ -z "$SERVER" ];then
if [ ! -z "$ip" ];then
Echo "Found PXE download server IP in kernel cmdline"
SERVER=$(echo $ip | awk -F ':' '{ print $2 }')
else
Echo "No PXE download server configured, trying: tftp.$DOMAIN"
SERVER=tftp.$DOMAIN
fi
fi
Echo "Checking connectivity of PXE download server: $SERVER"
if ! ping -c 1 -w 30 $SERVER >/dev/null 2>&1;then
Echo "PXE download server: $SERVER not found"
if [ -z "$SERVERTYPE" ] || [ "$SERVERTYPE" = "tftp" ]; then
if [ ! -z "$DHCPSIADDR" ];then
Echo "Using: $DHCPSIADDR from DHCP info"
SERVER=$DHCPSIADDR
elif [ ! -z "$DHCPSID" ];then
Echo "Using: $DHCPSID from DHCP info"
SERVER=$DHCPSID
elif [ ! -z "$SERVERID" ];then
Echo "Using: $SERVERID from DHCP info"
SERVER=$SERVERID
else
systemException \
"Can't find responding PXE download server... fatal !" \
"reboot"
fi
fi
fi
}
#======================================
# pxeSetupSystemAliasName
#--------------------------------------
function pxeSetupSystemAliasName {
# /.../
# Ask for an alias name if NAME from config.<MAC>
# contains a number. If the number is -1 the system will
# ask for ever for this name otherwhise the number sets
# a timeout how long to wait for input of this data
# ----
local IFS=$IFS_ORIG
if test $NAME -ne 0;then
if test $NAME -eq -1;then
Echo -n "Enter Alias Name for this system: " && \
read SYSALIAS
else
Echo -n "Enter Alias Name [timeout in $NAME sec]: " && \
read -t $NAME SYSALIAS
fi
fi
}
#======================================
# pxeSetupSystemHWInfoFile
#--------------------------------------
function pxeSetupSystemHWInfoFile {
# /.../
# calls hwinfo and stores the information into a file
# suffixed by the hardware address of the network card
# NOTE: it's required to have the dhcp info file sourced
# before this function is called
# ----
local IFS=$IFS_ORIG
hwinfo --all --log=hwinfo.$DHCPCHADDR >/dev/null
}
#======================================
# pxeSetupSystemHWTypeFile
#--------------------------------------
function pxeSetupSystemHWTypeFile {
# /.../
# collects information about the alias name the
# architecture and more and stores that into a
# file suffixed by the hardware address of the
# network card.
# ----
local IFS=$IFS_ORIG
echo "NCNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR
echo "CRNAME=$SYSALIAS" >> hwtype.$DHCPCHADDR
echo "IPADDR=$IPADDR" >> hwtype.$DHCPCHADDR
echo "ARCHITECTURE=$ARCH" >> hwtype.$DHCPCHADDR
}
#======================================
# pxeSizeToMB
#--------------------------------------
function pxeSizeToMB {
local IFS=$IFS_ORIG
local size=$1
if [ "$size" = "x" ];then
echo . ; return
fi
local lastc=$(echo $size | sed -e 's@\(^.*\)\(.$\)@\2@')
local value=$(echo $size | sed -e 's@\(^.*\)\(.$\)@\1@')
if [ "$lastc" = "m" ] || [ "$lastc" = "M" ];then
size=$value
elif [ "$lastc" = "g" ] || [ "$lastc" = "G" ];then
size=$(($value * 1024))
fi
echo +"$size"M
}
#======================================
# pxePartitionInput
#--------------------------------------
function pxePartitionInput {
local IFS=$IFS_ORIG
if [ $PARTITIONER = "fdasd" ];then
pxePartitionInputFDASD
else
pxePartitionInputGeneric
fi
}
#======================================
# pxeRaidPartitionInput
#--------------------------------------
function pxeRaidPartitionInput {
local IFS=$IFS_ORIG
if [ $PARTITIONER = "fdasd" ];then
pxeRaidPartitionInputFDASD
else
pxeRaidPartitionInputGeneric
fi
}
#======================================
# pxePartitionInputFDASD
#--------------------------------------
function pxePartitionInputFDASD {
local IFS=$IFS_ORIG
local field=0
local count=0
local IFS=","
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
partSize=$(pxeSizeToMB $partSize)
if [ "$partID" = '82' ] || [ "$partID" = 'S' ];then
partID=2
elif [ "$partID" = '83' ] || [ "$partID" = 'L' ];then
partID=1
elif [ "$partID" = '8e' ] || [ "$partID" = 'V' ];then
partID=4
else
partID=1
fi
echo -n "n . $partSize "
if [ $partID = "2" ] || [ $partID = "4" ];then
echo -n "t $count $partID "
fi
done
echo "w"
}
#======================================
# pxeRaidPartitionInputFDASD
#--------------------------------------
function pxeRaidPartitionInputFDASD {
pxePartitionInputFDASD
}
#======================================
# pxePartitionInputGeneric
#--------------------------------------
function pxePartitionInputGeneric {
local IFS=","
local field=0
local count=0
local pname
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
partSize=$(pxeSizeToMB $partSize)
pname=lxrw
if [ $partID = "S" ] || [ $partID = "82" ];then
partID=82
pname=lxswap
fi
if [ $partID = "L" ] || [ $partID = "83" ];then
partID=83
if [ "$partMount" = "/boot" ];then
pname=lxboot
else
pname=lxroot
fi
fi
if [ $partID = "V" ] || [ $partID = "8e" ];then
partID=8e
pname=lxlvm
fi
if [ $partID = "fd" ] || [ ! -z "$RAID" ];then
partID=fd
pname=lxroot
fi
if [ $count -eq 1 ];then
echo -n "n p:$pname $count 1 $partSize "
if [ $partID = "82" ] || \
[ $partID = "8e" ] || \
[ $partID = "41" ] || \
[ $partID = "fd" ]
then
echo -n "t $count $partID "
fi
else
echo -n "n p:$pname $count . $partSize "
if [ $partID = "82" ] || \
[ $partID = "8e" ] || \
[ $partID = "41" ] || \
[ $partID = "fd" ]
then
echo -n "t $count $partID "
fi
fi
done
echo "w q"
}
#======================================
# pxeRaidPartitionInputGeneric
#--------------------------------------
function pxeRaidPartitionInputGeneric {
pxePartitionInputGeneric
}
#======================================
# pxeRaidCreate
#--------------------------------------
function pxeRaidCreate {
local IFS=","
local count=0
local mdcount=0
local raidFirst
local raidSecond
local conf=/mdadm.conf
echo -n > $conf
for i in $PART;do
count=$((count + 1))
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if ! waitForStorageDevice $raidFirst;then
return
fi
if ! waitForStorageDevice $raidSecond;then
return
fi
mdadm --zero-superblock $raidFirst
mdadm --zero-superblock $raidSecond
mdadm --create --metadata=0.9 --run /dev/md$mdcount \
--level=$raidLevel --raid-disks=2 $raidFirst $raidSecond
if [ ! $? = 0 ];then
systemException \
"Failed to create raid array... fatal !" \
"reboot"
fi
mdadm -Db /dev/md$mdcount >> $conf
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidAssemble
#--------------------------------------
function pxeRaidAssemble {
local IFS=";"
local count=0
local mdcount=0
local field=0
local devices
local raidFirst
local raidSecond
local conf=/mdadm.conf
echo -n > $conf
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=","
for i in $PART;do
count=$((count + 1))
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if ! waitForStorageDevice $raidFirst;then
echo "Warning: device $raidFirst did not appear"
else
devices=$raidFirst
fi
if ! waitForStorageDevice $raidSecond;then
echo "Warning: device $raidSecond did not appear"
else
devices="$devices $raidSecond"
fi
IFS=$IFS_ORIG
mdadm --assemble --run /dev/md$mdcount $devices
mdadm -Db /dev/md$mdcount >> $conf
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidZeroSuperBlock
#--------------------------------------
function pxeRaidZeroSuperBlock {
# /.../
# if we switch from a raid setup back to a non-raid
# setup and use the same partition table setup as before
# it might happen that the raid superblock survives.
# This function removes all raid super blocks from
# all partitions in the PART setup. If the partition
# layout is different compared to the former raid layout
# the superblock is not valid anymore
# ----
local IFS=","
local count=1
local device
for i in $PART;do
device=$(ddn $imageDiskDevice $count)
if ! waitForStorageDevice $device;then
continue
fi
mdadm --zero-superblock $device
count=$((count + 1))
done
}
#======================================
# pxeRaidStop
#--------------------------------------
function pxeRaidStop {
local IFS=","
local count=0
for i in $PART;do
mdadm --stop /dev/md$count
count=$((count + 1))
done
}
#======================================
# pxeSwapDevice
#--------------------------------------
function pxeSwapDevice {
local IFS=","
local field=0
local count=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if test $partID = "82" -o $partID = "S";then
device=$(ddn $DISK $count)
waitForStorageDevice $device
echo $device
return
fi
done
}
#======================================
# pxeRaidSwapDevice
#--------------------------------------
function pxeRaidSwapDevice {
local IFS=","
local field=0
local count=0
local mdcount=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if test $partID = "82" -o $partID = "S";then
device=/dev/md$mdcount
waitForStorageDevice $device
echo $device
return
fi
mdcount=$((mdcount + 1))
done
}
#======================================
# pxeRaidPartCheck
#--------------------------------------
function pxeRaidPartCheck {
local IFS=";"
local count=0
local field=0
local n
local raidLevel
local raidDiskFirst
local raidDiskSecond
local device
local partSize
local partID
local partMount
local IdFirst
local IdSecond
local raidFirst
local raidSecond
local size
local maxDiffPlus=10240 # max 10MB bigger
local maxDiffMinus=10240 # max 10MB smaller
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=","
for i in $PART;do
count=$((count + 1))
field=0
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
IdFirst="$(partitionID $raidDiskFirst $count)"
IdSecond="$(partitionID $raidDiskSecond $count)"
raidFirst=$(ddn $raidDiskFirst $count)
raidSecond=$(ddn $raidDiskSecond $count)
if [ "$IdFirst" != "fd" ] || ! waitForStorageDevice $raidFirst;then
raidFirst=
fi
if [ "$IdSecond" != "fd" ] || ! waitForStorageDevice $raidSecond;then
raidSecond=
fi
# /.../
# RAID should be able to work in degraded mode when
# one of the disks is missing
# ----
if [ -z "$raidFirst" -a -z "$raidSecond" ]; then
return 1
fi
if [ "$partSize" == "x" ] ; then
# partition use all available space
continue
fi
for device in $raidFirst $raidSecond ; do
size=$(partitionSize $device)
if [ "$(( partSize * 1024 - size ))" -gt "$maxDiffMinus" -o \
"$(( size - partSize * 1024 ))" -gt "$maxDiffPlus" ]
then
return 1
fi
done
done
return 0
}
#======================================
# pxePartitionSetupCheck
#--------------------------------------
function pxePartitionSetupCheck {
# /.../
# validation check for the PART line. So far this
# function counts the given partition sizes and
# checks if it's possible to setup those partitions
# with respect to the available disk size
# ----
local IFS=","
local field=0
local count=0
local reqsizeMB=0
if [ -z "$DISK" ];then
# no disk device available, might be a ram only
# or diskless client
return
fi
local haveKBytes=$(partitionSize $DISK)
local haveMBytes=$((haveKBytes / 1024))
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n; field=1 ;;
esac
done
if [ "$partSize" == "x" ] ; then
# partition requests all available space
# use a fake value of 10 MB as minimum
reqsizeMB=$((reqsizeMB + 10))
else
# some size was requested, use value as MB size
reqsizeMB=$((reqsizeMB + partSize))
fi
done
if [ $reqsizeMB -gt $haveMBytes ];then
systemException \
"Requested partition sizes exceeds disk size" \
"reboot"
fi
}
#======================================
# pxePartCheck
#--------------------------------------
function pxePartCheck {
# /.../
# check the current partition table according to the
# current setup of the PART line. Thus this function
# checks if a new partition table setup compared to
# the existing one was requested. Additionally the check
# is clever enough to find out if the new partition
# table setup would destroy data on the existing one
# or if it only increases the partitions so that no
# data loss is expected.
# ----
local IFS=$IFS_ORIG
local count=0
local field=0
local n
local partSize
local partID
local partMount
local device
local size
local maxDiffPlus=10240 # max 10MB bigger
local maxDiffMinus=10240 # max 10MB smaller
IFS=","
for i in $PART;do
count=$((count + 1))
field=0
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
device=$(ddn $DISK $count)
if [ "$(partitionID $DISK $count)" != "$partID" ]; then
return 1
fi
if ! waitForStorageDevice $device;then
return 1
fi
if [ "$partSize" == "x" ] ; then
# partition use all available space
continue
fi
size=$(partitionSize $device)
if [ "$(( partSize * 1024 - size ))" -gt "$maxDiffMinus" -o \
"$(( size - partSize * 1024 ))" -gt "$maxDiffPlus" ]
then
return 1
fi
done
return 0
}
#======================================
# pxeBootDevice
#--------------------------------------
function pxeBootDevice {
local IFS=","
local field=0
local count=0
local device
for i in $PART;do
field=0
count=$((count + 1))
IFS=";" ; for n in $i;do
case $field in
0) partSize=$n ; field=1 ;;
1) partID=$n ; field=2 ;;
2) partMount=$n;
esac
done
if [ $partMount = "/boot" ];then
device=$(ddn $DISK $count)
waitForStorageDevice $device
echo $device
return
fi
done
}
#======================================
# startUtimer
#--------------------------------------
function startUtimer {
local IFS=$IFS_ORIG
local utimer=/usr/bin/utimer
if [ ! -x $utimer ];then
utimer=/utimer
fi
if [ -x $utimer ];then
if [ ! -e /tmp/utimer ];then
ln -s $UTIMER_INFO /tmp/utimer
fi
$utimer
export UTIMER=$(cat /var/run/utimer.pid)
if [ -f /iprocs ];then
cat /iprocs | grep -v UTIMER_PID > /iprocs
fi
echo UTIMER_PID=$UTIMER >> /iprocs
fi
}
#======================================
# setupBootPartitionPXE
#--------------------------------------
function setupBootPartitionPXE {
#======================================
# Variable setup
#--------------------------------------
local IFS=$IFS_ORIG
local fs_type
local FSTYPE_SAVE=$FSTYPE
local mpoint=boot_bind
unset NETBOOT_ONLY
local prefix=/mnt
#======================================
# Don't operate with unknown root part
#--------------------------------------
if [ -z "$imageRootDevice" ];then
# /.../
# this case should only be reached when the netboot
# code checks if the image needs an update. The update
# check happens as early as possible and at that time
# the root device variable is not set, so we use this
# as the trigger to return
#
return
fi
if [ ! -e "$imageRootDevice" ];then
# /.../
# the device does not exist case happens if NFSROOT is used.
# In this situation the variable holds the nfs root path
# and options and not a local device. For this setup we
# also don't need a boot partition because the client will
# always boot from the network, so we use this as return
# trigger too
# ----
export NETBOOT_ONLY=yes
return
fi
#======================================
# Check for boot partition in PART
#--------------------------------------
local bootdev=$(pxeBootDevice)
if [ -e "$bootdev" ];then
export imageBootDevice=$bootdev
fi
#======================================
# Initial bootid setup
#--------------------------------------
if [ ! -z "$imageBootDevice" ];then
# bootid is boot partition
export bootid=$(nd $imageBootDevice)
else
# bootid is root partition
export bootid=$(nd $imageRootDevice)
export imageBootDevice=$imageRootDevice
fi
if [ ! -z "$RAID" ] && [ ! -z "$bootid" ];then
# raid md devices start with 0 but partition id's start with 1
export bootid=$((bootid + 1))
fi
#======================================
# Probe boot/root filesystem
#--------------------------------------
probeFileSystem $imageRootDevice
fs_type=$FSTYPE ; FSTYPE=$FSTYPE_SAVE
#======================================
# return if no extra boot partition
#--------------------------------------
if [ $imageBootDevice = $imageRootDevice ];then
if [ $fs_type = "unknown" ] || [ "$haveLuks" = "yes" ];then
# /.../
# there is no extra boot device and the root device has an
# unsupported boot filesystem or layer, mark as netboot only
# ----
export NETBOOT_ONLY=yes
fi
# no boot partition setup required
return
fi
#======================================
# Check boot partition filesystem
#--------------------------------------
if [ $fs_type = "unknown" ];then
# /.../
# there is a boot device with an unknown filesystem
# create boot filesystem
# ----
createFilesystem $imageBootDevice
fi
#======================================
# export bootpart relevant variables
#--------------------------------------
export bootPartitionFSType=$fs_type
export kiwi_BootPart=$bootid
#======================================
# copy boot data from image to bootpart
#--------------------------------------
mkdir -p /$mpoint
mount $imageBootDevice /$mpoint
cp -a $prefix/boot /$mpoint
if [ -e /boot.tgz ];then
tar -xf /boot.tgz -C /$mpoint
fi
umount /$mpoint
rmdir /$mpoint
#======================================
# bind mount boot partition
#--------------------------------------
# the resetBootBind() function will resolve this to a
# standard /boot mount when the bootloader will be
# installed in preinit.
# ---
if ! isFSTypeReadOnly;then
rm -rf $prefix/boot
mkdir $prefix/boot
fi
mkdir $prefix/$mpoint
mount $imageBootDevice $prefix/$mpoint
mount --bind \
$prefix/$mpoint/boot $prefix/boot
}
#======================================
# setupBootPartition
#--------------------------------------
function setupBootPartition {
#======================================
# Variable setup
#--------------------------------------
local IFS=$IFS_ORIG
local label=undef
local mpoint=boot_bind
local FSTYPE_SAVE=$FSTYPE
local fs_type=undef
local BID=1
local prefix=/mnt
#======================================
# Check for partition IDs meta data
#--------------------------------------
if [ ! -z "$kiwi_BootPart" ];then
BID=$kiwi_BootPart
fi
#======================================
# Check for boot partition
#--------------------------------------
if [ -z "$imageDiskDevice" ];then
# no disk device like for live ISO based on clicfs
return
fi
label=$(blkid $(ddn $imageDiskDevice $BID) -s LABEL -o value)
if [ "$label" = "BOOT" ];then
export imageBootDevice=$(ddn $imageDiskDevice $BID)
fi
#======================================
# Probe boot partition filesystem
#--------------------------------------
probeFileSystem $(ddn $imageDiskDevice $BID)
fs_type=$FSTYPE ; FSTYPE=$FSTYPE_SAVE
export bootPartitionFSType=$fs_type
#======================================
# Export bootid if not yet done
#--------------------------------------
if [ -z "$bootid" ];then
export bootid=$BID
fi
#======================================
# Return if no boot setup required
#--------------------------------------
if [ ! "$label" = "BOOT" ] || [ ! -e "$imageBootDevice" ];then
return
fi
#======================================
# copy boot data from image to bootpart
#--------------------------------------
mkdir -p /$mpoint
mount $imageBootDevice /$mpoint
cp -a $prefix/boot /$mpoint
if [ -e /boot.tgz ];then
tar -xf /boot.tgz -C /$mpoint
fi
umount /$mpoint
rmdir /$mpoint
#======================================
# bind mount boot partition
#--------------------------------------
# the resetBootBind() function will resolve this to a
# standard /boot mount when the bootloader will be
# installed in preinit.
# ---
if ! isFSTypeReadOnly;then
rm -rf $prefix/boot
mkdir $prefix/boot
fi
mkdir $prefix/$mpoint
mount $imageBootDevice $prefix/$mpoint
mount --bind \
$prefix/$mpoint/boot $prefix/boot
}
#======================================
# isVirtioDevice
#--------------------------------------
function isVirtioDevice {
local IFS=$IFS_ORIG
if [ $haveDASD -eq 0 ] && [ $haveZFCP -eq 0 ];then
return 0
fi
return 1
}
#======================================
# isDASDDevice
#--------------------------------------
function isDASDDevice {
local IFS=$IFS_ORIG
if [ $haveDASD -eq 1 ];then
return 0
fi
return 1
}
#======================================
# isZFCPDevice
#--------------------------------------
function isZFCPDevice {
local IFS=$IFS_ORIG
if [ $haveZFCP -eq 1 ];then
return 0
fi
return 1
}
#======================================
# runPreinitServices
#--------------------------------------
function runPreinitServices {
# /.../
# run the .sh scripts in /etc/init.d/kiwi while
# inside the preinit stage of the kiwi boot process
# ----
local IFS=$IFS_ORIG
local service=/etc/init.d/kiwi/$1
if [ ! -d $service ];then
Echo "kiwi service $service not found... skipped"
return
fi
for script in $service/*.sh;do
test -e $script && bash -x $script
done
}
#======================================
# setupTTY
#--------------------------------------
function setupTTY {
# /.../
# create tty device nodes in case we don't have devtmpfs
# ----
local IFS=$IFS_ORIG
local tty_driver
local major
local minor
local tty
if $have_devtmpfs;then
return
fi
if [ "$console" ]; then
tty_driver="${tty_driver:+$tty_driver }${console%%,*}"
fi
for o in $tty_driver; do
case "$o" in
ttyS*) test -e /dev/$o || mknod -m 0660 /dev/$o c 4 64 ;;
tty*) test -e /dev/$o || mknod -m 0660 /dev/$o c 4 1 ;;
esac
done
tty_driver=$(showconsole -n 2>/dev/null)
if test -n "$tty_driver" ; then
major=${tty_driver%% *}
minor=${tty_driver##* }
if test $major -eq 4 -a $minor -lt 64 ; then
tty=/dev/tty$minor
test -e $tty || mknod -m 0660 $tty c 4 $minor
fi
if test $major -eq 4 -a $minor -ge 64 ; then
tty=/dev/ttyS$((64-$minor))
test -e $tty || mknod -m 0660 $tty c 4 $minor
fi
fi
}
#======================================
# setupConsoleFont
#--------------------------------------
function setupConsoleFont {
setfont $CONSOLE_FONT
}
#======================================
# setupConsole
#--------------------------------------
function setupConsole {
# /.../
# setup the xvc and/or hvc console if the device is present
# also remove the ttyS0 console if no ttyS0 device exists
# ----
local IFS=$IFS_ORIG
local itab=/etc/inittab
local stty=/etc/securetty
local init=/bin/systemd
local xvc="X0:12345:respawn:/sbin/mingetty --noclear xvc0 linux"
local hvc="H0:12345:respawn:/sbin/mingetty --noclear hvc0 linux"
#======================================
# return early in case of systemd
#--------------------------------------
if [ -e $init ];then
return
fi
#======================================
# create tty nodes if not done
#--------------------------------------
setupTTY
#======================================
# setup xvc console (xen)
#--------------------------------------
if [ -e /sys/class/tty/xvc0 ];then
if ! cat $itab | grep -v '^#' | grep -q xvc0;then
echo "$xvc" >> $itab
echo "xvc0" >> $stty
fi
fi
#======================================
# setup hvc console (kvm)
#--------------------------------------
if [ -e /sys/class/tty/hvc0 ];then
if ! cat $itab | grep -v '^#' | grep -q hvc0;then
echo "$hvc" >> $itab
echo "hvc0" >> $stty
fi
fi
#======================================
# remove ttyS0 if not present
#--------------------------------------
if [ ! -e /sys/class/tty/ttyS0 ];then
cat $itab | grep -vi 'ttyS0' > $itab.new && mv $itab.new $itab
fi
}
#======================================
# cleanPartitionTable
#--------------------------------------
function cleanPartitionTable {
# /.../
# remove partition table and create a new msdos
# table label if parted is in use
# ----
local IFS=$IFS_ORIG
dd if=/dev/zero of=$imageDiskDevice bs=512 count=1 >/dev/null
if [ $PARTITIONER = "parted" ];then
parted -s $imageDiskDevice mklabel msdos
fi
}
#======================================
# updatePartitionTable
#--------------------------------------
function updatePartitionTable {
# /.../
# fix gpt geometry and backup gpt by using parted. parted asks
# for fixing the table when e.g the print command is called.
# We tell parted to fix the table
# ----
local IFS=$IFS_ORIG
local device=$(getDiskDevice $1)
local diskhd
local plabel
local line
local partn
local begin
local stopp
local label
local pflag
#======================================
# check for hybrid iso
#--------------------------------------
if [ "$kiwi_hybridpersistent" = "true" ];then
# /.../
# The partition table written into an iso doesn't
# like the resync, so we return early here
# ----
return
fi
#======================================
# fix and store current table
#--------------------------------------
# the strange parted creates a gpt_sync_mbr if the disk
# geometry has changed. If this happened we have to rewrite
# the entire table with a new GPT label, thanks parted :(
# ----
if ! parted -m -s $device unit s print > /tmp/table;then
systemException \
"Failed to store current partition table" \
"reboot"
fi
#======================================
# check table type
#--------------------------------------
plabel=$(cat /tmp/table | grep ^$device: | cut -f6 -d:)
if [ ! "$plabel" = "gpt_sync_mbr" ];then
return 0
fi
#======================================
# clone GPT table
#--------------------------------------
Echo "Updating GPT metadata..."
if ! parted -s $device mklabel gpt;then
systemException \
"Failed to create GPT label" \
"reboot"
fi
while read line;do
if [[ ! $line =~ ^[0-9]+: ]];then
continue
fi
line=$(echo "${line%?}")
partn=$(echo $line | cut -f1 -d:)
begin=$(echo $line | cut -f2 -d:)
stopp=$(echo $line | cut -f3 -d:)
label=$(echo $line | cut -f6 -d:)
pflag=$(echo $line | cut -f7 -d:)
if [ -z "$label" ];then
label=primary
fi
if ! parted -s $device mkpart $label $begin $stopp 1>&2;then
systemException \
"Failed to clone GPT table" \
"reboot"
fi
if [ ! -z "$pflag" ];then
# set flag, but ignore errors here
parted -s $device set $partn $pflag on &>/dev/null
if [ $pflag = "bios_grub" ];then
export needProtectiveMBR=1
fi
fi
done < /tmp/table
return 0
}
#======================================
# resetBootBind
#--------------------------------------
function resetBootBind {
# /.../
# remove the bind mount boot setup and replace with a
# symbolic link to make the suse kernel update process
# to work correctly
# ----
local IFS=$IFS_ORIG
local bprefix=$1
local bootdir=$bprefix/boot_bind
if [ ! -e /proc/mounts ];then
mount -t proc proc /proc
fi
#======================================
# find bind boot dir
#--------------------------------------
if [ ! -e "/$bootdir" ];then
return
fi
#======================================
# reset bind mount to standard boot dir
#--------------------------------------
umount $bprefix/boot
mv /$bootdir/boot /$bootdir/tmp
mv /$bootdir/tmp/* /$bootdir
rm -rf /$bootdir/tmp
umount /$bootdir
rmdir /$bootdir
#======================================
# update fstab entry
#--------------------------------------
grep -v ^/boot_bind $bprefix/etc/fstab > $bprefix/etc/fstab.new
mv $bprefix/etc/fstab.new $bprefix/etc/fstab
sed -i -e s@/boot_bind@/boot@ $bprefix/etc/fstab
#======================================
# mount boot again
#--------------------------------------
chroot $bprefix mount $imageBootDevice /boot
#======================================
# check for syslinux requirements
#--------------------------------------
if [ "$loader" = "syslinux" ];then
# /.../
# if syslinux is used we need to make sure to copy
# the kernel and initrd to /boot on the boot partition.
# This is normally done by the boot -> . link but we
# can't create links on fat
# ----
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:`
break
done
IFS=$IFS_ORIG
mkdir -p $bprefix/boot/boot
cp $bprefix/boot/$kernel $bprefix/boot/boot/
cp $bprefix/boot/$initrd $bprefix/boot/boot/
fi
}
#======================================
# setupKernelLinks
#--------------------------------------
function setupKernelLinks {
# /.../
# check kernel names and links to kernel and initrd
# according to the different boot-up situations
# ----
local IFS=$IFS_ORIG
local prefix=/mnt
#======================================
# mount boot partition if required
#--------------------------------------
local mountCalled=no
if [ -e "$imageBootDevice" ] && blkid $imageBootDevice;then
if kiwiMount $imageBootDevice "$prefix";then
mountCalled=yes
fi
fi
#======================================
# Change to boot directory
#--------------------------------------
pushd $prefix/boot >/dev/null
#======================================
# remove garbage if possible
#--------------------------------------
if [ "$loader" = "syslinux" ] || [ "$loader" = "extlinux" ];then
rm -rf grub
fi
#======================================
# setup if overlay filesystem is used
#--------------------------------------
if [ "$kiwi_oemkboot" = "true" ] || \
[ "$PXE_KIWI_INITRD" = "yes" ] || \
isFSTypeReadOnly
then
# /.../
# we are using a special root setup based on an overlay
# filesystem. In this case we can't use the SuSE Linux
# initrd but must stick to the kiwi boot system.
# ----
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:`
break
done
IFS=$IFS_ORIG
if [ "$loader" = "syslinux" ];then
rm -f $initrd && mv initrd.vmx $initrd
rm -f $kernel && mv linux.vmx $kernel
elif [ "$PXE_KIWI_INITRD" = "yes" ];then
if [ ! -f initrd.kiwi ] && [ ! -f linux.kiwi ];then
Echo "WARNING: can't find kiwi initrd/linux !"
Echo -b "local boot will not work, maybe you forgot"
Echo -b "to add KIWI_INITRD and KIWI_KERNEL in config.<MAC> ?"
else
if [ "$loader" = "syslinux" ];then
rm -f $initrd && mv initrd.kiwi $initrd
rm -f $kernel && mv linux.kiwi $kernel
else
rm -f $initrd && ln -s initrd.kiwi $initrd
rm -f $kernel && ln -s linux.kiwi $kernel
fi
fi
else
rm -f $initrd && ln -s initrd.vmx $initrd
rm -f $kernel && ln -s linux.vmx $kernel
fi
fi
#======================================
# make sure boot => . link exists
#--------------------------------------
if [ ! "$bootPartitionFSType" = "vfat" ] && [ ! -e boot ];then
ln -s . boot
fi
#======================================
# umount boot partition if required
#--------------------------------------
popd >/dev/null
if [ "$mountCalled" = "yes" ];then
umount $prefix
fi
}
#======================================
# activateBootPartition
#--------------------------------------
function activateBootPartition {
if [[ ! $arch =~ i.86|x86_64 ]];then
# activation of a partition is only needed on
# x86 legacy BIOS implementations
return
fi
local IFS=$IFS_ORIG
local device=$imageBootDevice
if [ ! -e $device ];then
device=$imageRootDevice
fi
if [ ! -e $device ];then
echo "Can't find boot partition, activation skipped"
return
fi
local bootID=$(nd $device)
local diskID=$(dn $device)
sfdisk $diskID --force -A $bootID
}
#======================================
# refreshProtectiveMBR
#--------------------------------------
function updateProtectiveMBR {
local IFS=$IFS_ORIG
local device=$1
local input=/part.input
if ! lookup gdisk &>/dev/null;then
Echo "Warning, gdisk tool not found"
Echo "This could prevent the system to boot via EFI"
fi
rm -f $input
if [ ! -e "$device" ];then
device=$imageDiskDevice
fi
for cmd in x n w y; do
echo $cmd >> $input
done
gdisk $device < $input 1>&2
if [ ! $? = 0 ]; then
Echo "Failed to create protective MBR !"
Echo "This could prevent the system to boot via EFI"
fi
}
#======================================
# FBOK
#--------------------------------------
function FBOK {
local IFS=$IFS_ORIG
if [ ! -e /dev/fb0 ];then
# no framebuffer device found
return 1
fi
if ! lookup fbiterm &>/dev/null;then
# no framebuffer terminal program found
return 1
fi
if lookup isconsole &>/dev/null;then
if ! isconsole;then
# inappropriate ioctl (not a linux console)
return 1
fi
elif ! fbiterm echo &>/dev/null;then
# fbiterm can't be called with echo test cmd
return 1
fi
return 0
}
#======================================
# backupDiskLayout
#--------------------------------------
function backupDiskLayout {
local IFS=$IFS_ORIG
local devname=$1
local device=$(getDiskDevice $devname)
IFS=""
local parted=$(parted -m -s $device unit cyl print | grep -v Warning:)
local pcount=$(echo $parted | tail -n 1 | cut -f1 -d:)
local diskhd=$(echo $parted | head -n 3 | tail -n 2 | head -n 1)
local plabel=$(echo $diskhd | cut -f6 -d:)
IFS=$IFS_ORIG
if [[ $plabel =~ gpt ]];then
backupGPT $device $pcount
else
backupMBR $device
fi
}
#======================================
# backupMBR
#--------------------------------------
function backupMBR {
local IFS=$IFS_ORIG
local device=$1
dd if=$device bs=1 count=512
}
#======================================
# backupGPT
#--------------------------------------
function backupGPT {
local IFS=$IFS_ORIG
local device=$1
local pcount=$2
dd if=$device bs=1 count=$(((128 * pcount) + 1024))
}
#======================================
# loop_setup
#--------------------------------------
function loop_setup {
local IFS=$IFS_ORIG
local target=$1
local logical_sector_size
if [ ! -z "$kiwi_target_blocksize" ];then
logical_sector_size="-L $kiwi_target_blocksize"
fi
local loop=$(losetup $logical_sector_size -f --show $target)
if [ ! -e "$loop" ];then
return 1
fi
echo $loop
}
#======================================
# loop_delete
#--------------------------------------
function loop_delete {
local IFS=$IFS_ORIG
local target=$1
losetup -d $target
}
#======================================
# initialize
#--------------------------------------
function initialize {
local IFS=$IFS_ORIG
#======================================
# Exports boot image .profile
#--------------------------------------
if [ -f /.profile ];then
importFile < /.profile
if [ ! -z "$kiwi_bootloader" ];then
export loader=$kiwi_bootloader
fi
fi
#======================================
# Check partitioner capabilities
#--------------------------------------
if echo $kiwi_iname | grep -qE '(oem|net)boot';then
if [ $PARTITIONER = "unsupported" ];then
systemException \
"Installed parted version is too old" \
"reboot"
fi
fi
#======================================
# Check for hotfix kernel
#--------------------------------------
reloadKernel
#======================================
# Prevent blank screen
#--------------------------------------
if [ -x /usr/bin/setterm ];then
setterm -powersave off -blank 0
fi
#======================================
# Start boot timer (first stage)
#--------------------------------------
startUtimer
}
# vim: set noexpandtab: