#!/bin/ash . /etc/initrd.defaults call_func_timeout() { local func=$1 timeout=$2 pid watcher [ $# -ne 2 ] && gen_die "call_func_timeout() called with $# arguments" ( ${func} ) & pid=$! ( sleep ${timeout} && kill -HUP ${pid} ) 2>/dev/null & watcher=$! if wait ${pid} 2>/dev/null; then kill -HUP $watcher 2> /dev/null wait $watcher 2>/dev/null return 0 fi return 1 } modules_load() { fn=$1 shift for module in $* do echo ${module} >> /etc/modules/$fn done modules_scan $fn } modules_scan() { local MODS local loaded MODS=$(cat /etc/modules/${1} 2>/dev/null) [ -n "${MODS}" ] && [ -z "${QUIET}" ] && \ printf "%b" "${BOLD} ::${NORMAL} Loading from ${1}: " for x in ${MODS} do MLOAD=$(echo ${MLIST} | sed -e "s/.*${x}.*/${x}/") if [ "${MLOAD}" = "${x}" ] # Only module to no-load then [ -z "${QUIET}" ] && \ printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x}..." elif [ "${MLOAD}" = "${MLIST}" ] then if [ "${ROOTFSTYPE}" != 'auto' ] && [ -b "${REAL_ROOT}" ]; then echo "Root block device found, continuing..." break fi if [ -n "${DEBUG}" ]; then printf "%b" "${BOLD} ::${NORMAL} " printf "%b" "Scanning for ${x}..." fi modprobe ${x} > /dev/null 2>&1 loaded=${?} [ -n "${DEBUG}" -a "${loaded}" = "0" ] && \ echo "loaded" [ -n "${DEBUG}" -a "${loaded}" != "0" ] && \ echo "not loaded" [ -z "${DEBUG}" -a "${loaded}" = "0" ] && \ [ -z "${QUIET}" ] && \ printf "%b" "${x} " else [ -z "${QUIET}" ] && \ printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x}..." fi done [ -n "${MODS}" ] && [ -z "${QUIET}" ] && echo } uppercase(){ # needs tr on busybox echo $1 | tr 'a-z' 'A-Z' } findmediamount() { # $1 = mount dir name / media name # $2 = recognition file # $3 = variable to have the device path # $4 = actual mount dir path (full path) # args remaining are possible devices local media=$1 recon=$2 vrbl=$3 mntdir=$4 shift 4 good_msg "Looking for the ${media}" ${CRYPT_SILENT} if [ "$#" -gt "0" ] then [ ! -d "${mntdir}" ] && mkdir -p ${mntdir} 2>/dev/null >/dev/null if [ -n "${ISOBOOT}" ] then mntcddir="${mntdir%${media}}iso" if [ ! -f ${mntcddir} ] then mkdir ${mntcddir} fi else mntcddir=${mntdir} fi for x in $* do # Check for a block device to mount if [ -b "${x}" ] then skip=0 bsn=`basename "${x}"` # # If disk and it has at least one partition, skip. # We use /sys/block/${bsn}/${bsn}[0-9]* to make sure that we # don't skip device mapper devices. Even the craziest scenario # deserves a fair chance. # for part in `ls /sys/block/${bsn}/${bsn}*[0-9]* 2>/dev/null` do skip=1 break; done if [ ${skip} -eq 1 ] then continue fi good_msg "Attempting to mount media: ${x}" ${CRYPT_SILENT} mount -t ${CDROOT_TYPE} ${x} ${mntcddir} >/dev/null 2>&1 if [ "$?" = '0' ] then if [ -n "${ISOBOOT}" ]; then if [ -f ${mntcddir}/${ISOBOOT} ]; then mount -o loop ${mntcddir}/${ISOBOOT} ${mntdir} if [ "$?" = "0" ]; then good_msg "iso mounted on ${mntdir}" fi fi fi # Check for the media if [ -f "${mntdir}/${recon}" ] then #set REAL_ROOT, CRYPT_ROOT_KEYDEV or whatever ${vrbl} is eval ${vrbl}'='"${x}" good_msg "Media found on ${x}" ${CRYPT_SILENT} break else umount ${mntcddir} fi fi fi done fi eval local result='$'${vrbl} [ -n "${result}" ] || bad_msg "Media not found" ${CRYPT_SILENT} } devicelist(){ # Locate the cdrom device with our media on it. # CDROM DEVICES local DEVICES="/dev/cdroms/* /dev/ide/cd/* /dev/sr*" # USB Keychain/Storage DEVICES="$DEVICES /dev/sd*" # IDE devices DEVICES="$DEVICES /dev/hd*" # virtio devices DEVICES="$DEVICES /dev/vd*" # USB using the USB Block Driver DEVICES="$DEVICES /dev/ubd* /dev/ubd/*" # iSeries devices DEVICES="$DEVICES /dev/iseries/vcd*" # builtin mmc/sd card reader devices DEVICES="$DEVICES /dev/mmcblk* /dev/mmcblk*/*" # fallback scanning, this might scan something twice, but it's better than # failing to boot. [ -e /proc/partitions ] && DEVICES="${DEVICES} $(awk '/([0-9]+[[:space:]]+)/{print "/dev/" $4}' /proc/partitions)" echo ${DEVICES} } bootstrapFS() { if [ 1 = "$aufs" ]; then # Directories used for rw aufs mount filesystem aufs_union=/union aufs_memory=/memory # Mountpoint for the aufs dev aufs_dev_mnt=/mnt/aufs-dev if [ -z "$aufs_dev_uid" ]; then aufs_branch=$aufs_memory/aufs-rw-branch/default else aufs_branch=$aufs_memory/aufs-rw-branch/$aufs_dev_uid fi mkdir -p $aufs_memory $aufs_union $aufs_dev_mnt else # Legacy SquashFS implementation good_msg "Making tmpfs for ${NEW_ROOT}" mount -n -t tmpfs tmpfs ${NEW_ROOT} fi # Setup the filesystem nodes and directories for i in ${CDROOT_PATH} /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do mkdir -p "${NEW_ROOT}${i}" chmod 755 "${NEW_ROOT}${i}" done [ ! -d "${CDROOT_PATH}" ] && mkdir -p "${CDROOT_PATH}" [ ! -e "${NEW_ROOT}/dev/null" ] && mknod -m 666 "${NEW_ROOT}"/dev/null c 1 3 [ ! -e "${NEW_ROOT}/dev/zero" ] && mknod -m 666 "${NEW_ROOT}"/dev/zero c 1 5 [ ! -e "${NEW_ROOT}/dev/console" ] && mknod -m 600 "${NEW_ROOT}"/dev/console c 5 1 [ ! -e "${NEW_ROOT}/dev/ttyS0" ] && mknod -m 660 "${NEW_ROOT}"/dev/ttyS0 c 4 64 # For SGI LiveCDs if [ "${LOOPTYPE}" = "sgimips" ]; then [ ! -e "${NEW_ROOT}/dev/sr0" ] && mknod "${NEW_ROOT}/dev/sr0" b 11 0 [ ! -e "${NEW_ROOT}/dev/loop0" ] && mknod "${NEW_ROOT}/dev/loop0" b 7 0 fi # Required for splash to work. Not an issue with the initrd as this # device isn't created there and is not needed. for minor in 0 1 ; do [ ! -e "${NEW_ROOT}/dev/$minor" ] && mknod -m 600 "${NEW_ROOT}/dev/tty$minor" c 4 $minor done } bootstrapCD() { local DEVICES= # The device was specified on the command line, so there's no need # to scan a bunch of extra devices [ -n "${CDROOT_DEV}" ] && DEVICES="${CDROOT_DEV}" [ -z "${CDROOT_DEV}" ] && DEVICES=$(devicelist) findmediamount "cdrom" "${SUBDIR}/${CDROOT_MARKER}" \ "REAL_ROOT" "${CDROOT_PATH}" ${DEVICES} if [ $VERIFY = 1 ]; then cd "${CDROOT_PATH}" if [ -f isoroot_checksums ]; then good_msg "Verifying checksums, this may take some time..." if ! busybox sha512sum -c isoroot_checksums; then bad_msg "Some checksums failed, press any key to poweroff..." read -n1 -s busybox poweroff -f else good_msg "Checksums all valid, continuing boot..." fi cd $OLDPWD else bad_msg "Verify enabled but no checksums file exists, skipping" fi fi } bootstrapKey() { # $1 = ROOT/SWAP local KEYDEVS=`devicelist` eval local keyloc='"${CRYPT_'${1}'_KEY}"' findmediamount "key" "${keyloc}" "CRYPT_${1}_KEYDEV" "/mnt/key" ${KEYDEVS} } cache_cd_contents() { # Check loop file exists and cache to ramdisk if DO_cache is enabled if [ "${LOOPTYPE}" != "noloop" ] && [ "${LOOPTYPE}" != "sgimips" ] then check_loop if [ "${DO_cache}" ] then # TODO: Check the size of the image versus the size of our tmpfs # along with the amount of available RAM and increase tmpfs size # if necessary. (Not having awk sucks...) # z=0 # for i in $(cat /proc/meminfo | grep -e ^MemFree -e ^Cached | \ # cut -d: -f2 | cut -dk -f1 | sed -e "s/^\s*//") ; do # z=$(($z + $i)) ; done # echo $z good_msg "Copying loop file for caching..." # Verify that the needed directory exists mkdir -p "$(dirname ${NEW_ROOT}/mnt/${LOOP})" cp -a ${CDROOT_PATH}/${LOOP} ${NEW_ROOT}/mnt/${LOOP} if [ $? -ne 0 ] then warn_msg "Failed to cache the loop file! Lack of RAM?" rm -rf ${NEW_ROOT}/mnt/${LOOP} 2>/dev/null rm -rf ${NEW_ROOT}/mnt/livecd.* 2>/dev/null rm -rf ${NEW_ROOT}/mnt/image.* 2>/dev/null rm -rf ${NEW_ROOT}/mnt/zisofs 2>/dev/null fi fi fi } mount_sysfs() { mount -t sysfs sysfs /sys -o noexec,nosuid,nodev >/dev/null 2>&1 ret=$? [ ${ret} -eq 0 ] || bad_msg "Failed to mount /sys!" } # Check support for both aufs and overlayfs # union file system style support # is_union_modules() { local mod mod_dir case $1 in aufs) mod=$aufs_modules mod_dir=$aufs_modules_dir ;; overlayfs) mod=$overlayfs_modules mod_dir=$overlayfs_modules_dir esac # When {aufs,overlayfs}.modules= is used or $CDROOT_PATH/modules # directory is available if [[ 1 = "$mod" || -d $CDROOT_PATH/modules ]]; then if [ -d $CDROOT_PATH/modules ]; then warn_msg "Adding all modules in $CDROOT_PATH/modules" union_insert_modules "$CDROOT_PATH"/modules # Is it a block device? elif [ ! -b "$mod_dir" ]; then bad_msg "$mod_dir is not a valid block device" bad_msg "aborting modules insert into $CHROOT" else warn_msg "Adding all modules in $mod_dir" mkdir /mnt/modules mount "$mod_dir" /mnt/modules union_insert_modules /mnt/modules fi fi return 0 } # Insert a directory tree $2 to a aufs union specified by $1 # Top-level read-write branch is specified by it's index 0 # $1 = union absolute path (starting with /) # $2 = path to data directory # aufs_insert_dir() { # Always mount it over the precedent (add:1:) if mount -n -o "remount,add:1:$2=rr" aufs "$1"; then good_msg "Addition of $2 to $1 successful" fi } # Insert all modules found in $1, usually $CDROOT_PATH # added to allow users to add their own apps. union_insert_modules() { local module for module in "$1/"*.lzm; do if [ 1 = "$overlayfs" ];then if union_mod overlayfs "$module";then good_msg "Addition of '$module' to overlay successful" else bad_msg "Unable to insert module: '$module'" fi # Used in setup_overlayfs() mod_path="$mod_path:$mod_dir/.$mod" # Assign variable with paths to modules mount point # TODO: Stop using eval eval $mod="$mod_dir/.$mod" mods="$mods $mod" else union_mod aufs "$module" || bad_msg "Unable to insert module: '$module'" fi done } # Helper function for union_insert_modules() union_mod() { [ -e "$2" ] || return 0 mod_dir=/mnt/overlay mod=${2##*/} mod=${mod//-/_} mod=${mod%.*} if [ 1 = "$aufs" ]; then if [ ! -d "$aufs_union"/mnt/"$mod" ]; then mkdir -p "$aufs_union"/mnt/modules/"$mod" || return fi mount -o loop,ro "$2" "$aufs_union"/mnt/modules/"$mod" aufs_insert_dir "$aufs_union" "$aufs_union"/mnt/modules/"$mod" else if [ ! -d "$mod_dir/.$mod" ]; then mkdir -p "$mod_dir/.$mod" || return fi mount -o loop,ro "$2" "$mod_dir/.$mod" fi } # Implements no_umounts variable into $CHROOT/etc/conf.d/localmount for a cleaner shutdown process conf_rc_no_umounts() { local conf nomount fnd conf=$CHROOT/etc/conf.d/localmount fnd=0 if nomount=$(grep -n '^[[:blank:]]*no_umounts=' $conf); then local i n data cmd IFS IFS=' ' set -- $nomount unset IFS for i; do n=${i%%:*}; i=${i#"$n"} data=${i#*=} case $data in "\"$no_umounts\""|"'$no_umounts'") fnd=1;; *) cmd="$cmd$n d;" esac done if [ -n "$cmd" ]; then sed -i "${cmd%;}" $conf test_success "Unable to edit /etc/conf.d/localmount" fi fi if [ 0 -eq "$fnd" ]; then printf 'no_umounts="%s"\n' "$no_umounts" >> $conf test_success "Unable to write to /etc/conf.d/localmount" fi } # is_int "$A" ["$B"..] # NOTE we consider a leading 0 false as it would be interpreted as octal is_int(){ local i for i; do case $i in ''|*[!0-9]*|0?*) return 1 ;; *) : esac done } # Function to create an ext2 fs on $aufs_dev, $aufs_dev_mnt mountpoint create_changefs() { local size while :; do read -p '<< Size of file (Press Enter for default 256 MB): ' size size=${size:-256} if ! is_int $size; then bad_msg "Non numeric value given for size, try again" continue elif [ 15 -ge "$size" ]; then bad_msg "Please give a size of at least 16 Megabytes" else if dd if=/dev/zero "of=$aufs_dev_mnt$aufs_union_file" bs=1 seek="$size"M count=0 &>/dev/null; then good_msg "Creation of $aufs_union_file, ${size}MB on $aufs_dev successful, formatting it ext2" mke2fs -F "$aufs_dev_mnt$aufs_union_file" &>/dev/null break else rm "$aufs_dev_mnt$aufs_union_file" bad_msg "Unable to create ${aufs_union_file#*/} on $aufs_dev of ${size}MB" bad_msg "Ensure your disk is not full or read-only" read -p '<< Type "a" to abort, anything else to continue : ' doabort if [ a = "$doabort" ]; then bad_msg "Aborting creation of $aufs_union_file!" umount "$aufs_dev" && rmdir "$aufs_dev_mnt" return 1 fi fi fi done return $? } setup_aufs() { bootstrapCD if [ "$aufs_dev" = "search" ]; then findmediamount "aufs-dev" "$aufs_union_file" \ "aufs_dev" "$aufs_dev_mnt" $(devicelist) aufs_mounted="1" elif [ -z $aufs_dev ] && [ -w "$CDROOT_PATH/$aufs_union_file" ]; then aufs_dev="$REAL_ROOT" aufs_dev_mnt="$CDROOT_PATH" aufs_mounted="1" fi if [ -z $aufs_dev ] && [ -w "$CDROOT_PATH/casper-rw" ]; then aufs_dev="$REAL_ROOT" aufs_dev_mnt="$CDROOT_PATH" aufs_union_file="/casper-rw" aufs_mounted="1" fi if [ -n "$aufs_dev" ]; then if [ ! -b $aufs_dev ]; then bad_msg "$aufs_dev is not a valid block device" local invalidblk=1 unset aufs_dev #skip this block when aufs_dev_mnt is already mounted elif [ "$aufs_mounted" != "1" ]; then good_msg "Mounting $aufs_dev to $aufs_memory for aufs support" if ! mount -t auto "$aufs_dev" "$aufs_dev_mnt" &>/dev/null; then bad_msg "Mount of $aufs_dev failed, falling back to ramdisk based aufs" unset aufs_dev fi fi # Check and attempt to create the AUFS union file if [ ! -e $aufs_dev_mnt$aufs_union_file ] && [ -n "$aufs_dev" ]; then create_changefs && mount -t auto "$aufs_dev_mnt$aufs_union_file" "$aufs_memory" elif [ -n "$aufs_dev" ]; then while :; do if mount -t auto "$aufs_dev_mnt$aufs_union_file" "$aufs_memory" &>/dev/null; then if [ "$aufs_union_file" = "/casper-rw" ];then bad_msg "Use of livecd.aufs preferred to casper-rw for changes saving, please rename the file." fi break else bad_msg "Mounting of changes file failed, Running e2fsck" if ! hash e2fsck &>/dev/null; then bad_msg "/sbin/e2fsck not found! aborting filesystem check" bad_msg "Moving ${aufs_union_file#*/} to ${aufs_union_file#*/}.bad" mv "$aufs_dev_mnt$aufs_union_file" "$aufs_dev_mnt$aufs_union_file.bad" break fi if e2fsck "$aufs_dev_mnt$aufs_union_file" &>/dev/null; then good_msg "e2fsck ran successfully. Please verify data after bootup" else bad_msg "Your ${aufs_union_file#*/} image might be corrupted" bad_msg "moving ${aufs_union_file#*/} to ${aufs_union_file#*/}.bad" mv "$aufs_dev_mnt$aufs_union_file" "$aufs_dev_mnt$aufs_union_file.bad" break fi fi done fi # Mount tmpfs only in the case when aufs= boot parameter was # empty or we were not able to mount the storage device if [ 1 = "$CDROOT" ] && [ ! -f "$aufs_dev_mnt$aufs_union_file" ]; then aufs_xino=$aufs_memory umount "$aufs_memory" &>/dev/null if [ 1 = "$invalidblk" ]; then bad_msg "Verify that you've entered a valid device path" else bad_msg "Create an extfs ${aufs_union_file#*/} file on this device" fi bad_msg "if you wish to have aufs data persistency on reboots" bad_msg "Falling back to ramdisk based aufs" good_msg "Mounting ramdisk to $aufs_memory for aufs support" mount -t tmpfs tmpfs "$aufs_memory" else aufs_xino=$aufs_memory/xino mkdir -p "$aufs_xino" mount -t tmpfs aufs-xino "$aufs_xino" fi else aufs_xino=$aufs_memory good_msg "Mounting ramdisk to $aufs_memory for aufs support" mount -t tmpfs tmpfs "$aufs_memory" fi mkdir -p "$aufs_branch" if ! mount -t aufs -n -o "nowarn_perm,udba=none,xino=$aufs_xino/.aufs.xino,br:$aufs_branch=rw" aufs "$aufs_union"; then bad_msg "Can't setup union $aufs_union in directory!" aufs=0 fi } setup_overlayfs() { # Setup directories and vars local overlay=/mnt/overlay local upperdir="${overlay}/.upper" local workdir="${overlay}/.work" local static=/mnt/livecd rundebugshell overlayfs for i in "${overlay}" "${static}"; do [ ! -d "${i}" ] && mkdir -p "${i}" done good_msg "Loading overlayfs" modprobe overlay > /dev/null 2>&1 checkfs overlay mount -t squashfs -o loop,ro "$CDROOT_PATH/$LOOPEXT$LOOP" "${static}" mount -t tmpfs none "${overlay}" mkdir "${upperdir}" "${workdir}" is_union_modules overlayfs mount -t overlay overlay -o lowerdir="${static}${mod_path}",upperdir="${upperdir}",workdir="${workdir}" "${NEW_ROOT}" [ ! -d "${NEW_ROOT}${overlay}" ] && mkdir -p "${NEW_ROOT}${overlay}" [ ! -d "${NEW_ROOT}${static}" ] && mkdir -p "${NEW_ROOT}${static}" echo "overlay / overlay defaults 0 0" > "${NEW_ROOT}"/etc/fstab for i in "${overlay}" "${static}"; do mount --bind "${i}" "${NEW_ROOT}${i}" done # Did we populate the overlayfs modules path locations variable? if [ -n "$mods" ]; then for i in $mods; do mount --bind "${overlay}/.${i}" "${NEW_ROOT}/${overlay}/.${i}" done fi } findnfsmount() { if [ "${IP}" != '' ] || busybox udhcpc -n -T 15 -q then [ -e /rootpath ] && NFSROOT=`cat /rootpath` if [ "${NFSROOT}" = '' ] then # Obtain NFSIP OPTIONS=`busybox dmesg | grep rootserver | sed -e "s/,/ /g"` for OPTION in $OPTIONS do if [ `echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 1` = 'rootserver' ] then NFSIP=`echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 2` fi done # Obtain NFSPATH OPTIONS=`busybox dmesg | grep rootpath | sed -e "s/,/ /g"` for OPTION in $OPTIONS do if [ `echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 1` = 'rootpath' ] then NFSPATH=`echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 2` fi done # Setup NFSROOT if [ "${NFSIP}" != '' ] && [ "$NFSPATH" != '' ] then NFSROOT="${NFSIP}:${NFSPATH}" else bad_msg "The DHCP Server did not send a valid root-path." bad_msg "Please check your DHCP setup, or provide a nfsroot=<...> parameter." return 1 fi fi if [ "${NFSROOT}" != '' ] then NFSOPTIONS=${NFSROOT#*,} NFSROOT=${NFSROOT%%,*} if [ "${NFSOPTIONS}" = "${NFSROOT}" ] then NFSOPTIONS=$DEFAULT_NFSOPTIONS else NFSOPTIONS="${DEFAULT_NFSOPTIONS},${NFSOPTIONS}" fi if [ "${CDROOT}" != '0' ] then good_msg "Attempting to mount NFS CD image on ${NFSROOT} with options ${NFSOPTIONS}" mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${CDROOT_PATH} if [ "$?" = '0' ] then REAL_ROOT="/dev/nfs" else bad_msg "NFS Mounting failed. Is the path corrent ?" return 1 fi else good_msg "Attempting to mount NFS root on ${NFSROOT} with options ${NFSOPTIONS}" mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${NEW_ROOT} if [ "$?" = '0' ] then REAL_ROOT="/dev/nfs" else bad_msg "NFS Mounting failed. Is the path correct ?" return 1 fi # FIXME: Need to start portmap and the other rpc daemons in # order to remount rw. fi fi else # IP / DHCP return 1 fi } find_real_device() { local DEVICE="${1}" case "${DEVICE}" in UUID\=*|LABEL\=*) local REAL_DEVICE="" local retval=1 if [ "${retval}" -ne 0 ]; then REAL_DEVICE=`findfs "${DEVICE}" 2>/dev/null` retval=$? fi if [ "$retval" -ne 0 ]; then REAL_DEVICE=`busybox findfs "${DEVICE}" 2>/dev/null` retval=$? fi if [ "${retval}" -ne 0 ]; then REAL_DEVICE=`blkid -o device -l -t "${DEVICE}"` retval=$? fi if [ "${retval}" -eq 0 ] && [ -n "${REAL_DEVICE}" ]; then DEVICE="${REAL_DEVICE}" fi ;; esac printf "%s" "${DEVICE}" } check_loop() { if [ "${LOOP}" = '' -o ! -e "${CDROOT_PATH}/${LOOP}" ] then bad_msg "Invalid loop location: ${LOOP}" bad_msg 'Please export LOOP with a valid location, or reboot and pass a proper loop=...' bad_msg 'kernel command line!' run_shell fi } run_shell() { /bin/ash } fs_type_in_use() { fs_type=$1 cut -d ' ' -f 3 < /proc/mounts | fgrep -q "${fs_type}" } mount_devfs() { # Use devtmpfs if enabled in kernel, # else tmpfs. Always run mdev just in case devfs=tmpfs if checkfs devtmpfs > /dev/null ; then devfs=devtmpfs fi # Options copied from /etc/init.d/udev-mount, should probably be kept in sync if ! fs_type_in_use devtmpfs; then mount -t $devfs -o "exec,nosuid,mode=0755,size=10M" udev /dev \ || bad_msg "Failed to mount /dev as ${devfs}" fi # http://git.busybox.net/busybox/plain/docs/mdev.txt if ! fs_type_in_use devpts; then mkdir -m 0755 /dev/pts mount -t devpts -o gid=5,mode=0620 devpts /dev/pts || bad_msg "Failed to mount /dev/pts" fi } test_success() { retcode=$? # If last command failed send error message and fall back to a shell if [ "$retcode" != '0' ] then error_string=$1 error_string="${error_string:-run command}" bad_msg 'Failed to $1; failing back to the shell...' run_shell fi } # msg functions arguments # $1 string # $2 hide flag good_msg() { [ -n "${QUIET}" ] && [ -z "${DEBUG}" ] && return 0 msg_string=$1 msg_string="${msg_string:-...}" [ "$2" != 1 ] && printf "%b\n" "${GOOD}>>${NORMAL}${BOLD} ${msg_string} ${NORMAL}" } bad_msg() { msg_string=$1 msg_string="${msg_string:-...}" if [ "$2" != 1 ] then splash 'verbose' > /dev/null & printf "%b\n" "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}" fi } warn_msg() { msg_string=$1 msg_string="${msg_string:-...}" [ "$2" != 1 ] && printf "%b\n" "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}" } crypt_filter() { if [ "${CRYPT_SILENT}" = '1' ] then eval $1 >/dev/null 2>/dev/null else splash 'verbose' > /dev/null & eval $1 res=$? if [ ${res} -eq 0 ] then splash set_msg 'Disk unlocked.' fi return ${res} fi } prompt_user(){ # $1 = variable whose value is the path (examples: "REAL_ROOT", # "LUKS_KEYDEV") # $2 = label # $3 = optional explanations for failure eval local oldvalue='$'${1} if [ $# != 2 -a $# != 3 ]; then bad_msg "Bad invocation of function prompt_user." bad_msg "Please file a bug report with this message" exit 1 fi [ -n "${3}" ] && local explnt=" or : ${3}" || local explnt="." bad_msg "Could not find the ${2} in ${oldvalue}${explnt}" bad_msg "Please specify another value or:" bad_msg "- press Enter for the same" bad_msg '- type "shell" for a shell' bad_msg '- type "q" to skip...' printf "%s" "${2}(${oldvalue}) :: " read -t 10 ${1} case `eval echo '$'${1}` in 'q') eval ${1}'='${oldvalue} warn_msg "Skipping step, this will likely cause a boot failure." break ;; 'shell') eval ${1}'='${oldvalue} warn_msg "To leave and try again just press +D" run_shell ;; '') eval ${1}'='${oldvalue} ;; esac } cmdline_hwopts() { # Scan CMDLINE for any "doscsi" or "noscsi"-type arguments local FOUND local TMP_HWOPTS for x in $HWOPTS do for y in $CMDLINE do if [ "${y}" = "do${x}" ] then MY_HWOPTS="${MY_HWOPTS} $x" elif [ "${y}" = "no${x}" ] then MY_HWOPTS="`echo ${MY_HWOPTS} | sed -e \"s/${x}//g\" -`" fi if [ "$(echo ${y} | cut -b -7)" = "keymap=" ] then MY_HWOPTS="${MY_HWOPTS} keymap" fi done done # Shouldnt need to sort this as the following loop should figure out the # duplicates and strip them out #MY_HWOPTS=`echo ${MY_HWOPTS}| sort` for x in ${MY_HWOPTS} do FOUND=0 for y in ${TMP_HWOPTS} do if [ "${y}" = "${x}" ] then continue 2 fi done TMP_HWOPTS="${TMP_HWOPTS} ${x}" eval DO_`echo ${x} | sed 's/-//'`=1 done MY_HWOPTS=${TMP_HWOPTS} } load_modules() { # Load modules listed in MY_HWOPTS if /lib/modules exists for the running # kernel version if [ -d "/lib/modules/${KV}" ] then good_msg 'Loading modules' # Load appropriate kernel modules for modules in $MY_HWOPTS do modules_scan $modules done else good_msg 'Skipping module load; no modules in the ramdisk!' fi } setup_keymap() { if [ "${DO_keymap}" ] then if [ ! -e /dev/vc/0 -a ! -e /dev/tty0 ] then DEVBIND=1 mount -o bind ${NEW_ROOT}/dev /dev fi [ ! -e /dev/tty0 ] && ln -s /dev/tty1 /dev/tty0 [ -f /lib/keymaps/keymapList ] && chooseKeymap [ "${DEVBIND}" = '1' ] && umount /dev fi } setup_locale() { if [ ! -z "${locale}" ]; then echo "LANG=${locale}" > ${NEW_ROOT}/etc/sysconfig/locale fi } chooseKeymap() { good_msg "Loading keymaps" if [ -z "${keymap}" ] then splash 'verbose' > /dev/null & cat /lib/keymaps/keymapList read -t 10 -p '<< Load keymap (Enter for default): ' keymap case ${keymap} in 1|azerty) keymap=azerty ;; 2|be) keymap=be ;; 3|bg) keymap=bg ;; 4|br-a) keymap=br-a ;; 5|br-l) keymap=br-l ;; 6|by) keymap=by ;; 7|cf) keymap=cf ;; 8|croat) keymap=croat ;; 9|cz) keymap=cz ;; 10|de) keymap=de ;; 11|dk) keymap=dk ;; 12|dvorak) keymap=dvorak ;; 13|es) keymap=es ;; 14|et) keymap=et ;; 15|fi) keymap=fi ;; 16|fr) keymap=fr ;; 17|gr) keymap=gr ;; 18|hu) keymap=hu ;; 19|il) keymap=il ;; 20|is) keymap=is ;; 21|it) keymap=it ;; 22|jp) keymap=jp ;; 23|la) keymap=la ;; 24|lt) keymap=lt ;; 25|mk) keymap=mk ;; 26|nl) keymap=nl ;; 27|no) keymap=no ;; 28|pl) keymap=pl ;; 29|pt) keymap=pt ;; 30|ro) keymap=ro ;; 31|ru) keymap=ru ;; 32|se) keymap=se ;; 33|sg) keymap=sg ;; 34|sk-y) keymap=sk-y ;; 35|sk-z) keymap=sk-z ;; 36|slovene) keymap=slovene ;; 37|trf) keymap=trf ;; 38|trq) keymap=trq ;; 39|ua) keymap=ua ;; 40|uk) keymap=uk ;; 41|us) keymap=us ;; 42|wangbe) keymap=wangbe ;; 43|sf|ch*) keymap=sf ;; esac fi if [ -e /lib/keymaps/${keymap}.map ] then good_msg "Loading the ''${keymap}'' keymap" loadkmap < /lib/keymaps/${keymap}.map # xkeymap=${keymap} # echo ${keymap} | egrep -e "[0-9]+" >/dev/null 2>&1 # if [ $? -eq 0 ] # then # xkeymap=`tail -n 8 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | egrep -v 1` # fi mkdir -p /etc/sysconfig # echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard echo "XKEYBOARD=${keymap}" > /etc/sysconfig/keyboard splash set_msg "Set keymap to ${keymap}" elif [ -z "${keymap}" ] then good_msg good_msg "Keeping default keymap" splash set_msg "Keeping default keymap" else bad_msg "Sorry, but keymap ''${keymap}'' is invalid!" unset keymap chooseKeymap fi } # # Copy over user selected keymap # copyKeymap() { if [ -e /etc/sysconfig/keyboard -a "${CDROOT}" = '1' ]; then [ ! -d ${NEW_ROOT}/etc/sysconfig ] && mkdir -p ${NEW_ROOT}/etc/sysconfig cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard fi } # This helper function is to be called using call_func_timeout. # It enables us to wait a reasonable amount of time until /dev/zfs appears. waitForZFS() { while [ ! -c /dev/zfs ]; do echo >/dev/null; done; exit 1 } startVolumes() { #good_msg 'Checking if volumes need to be started...' # Here, we check for /dev/device-mapper, and if it exists, we setup a # a symlink, which should hopefully fix bug #142775 and bug #147015 if [ -e /dev/device-mapper ] && [ ! -e /dev/mapper/control ] then mkdir -p /dev/mapper ln -sf /dev/device-mapper /dev/mapper/control fi if [ "${USE_MDADM}" = '1' ] then if [ -x '/sbin/mdadm' ] then /sbin/mdadm --assemble --scan else bad_msg "mdadm not found: skipping mdadm raid assembly!" fi fi if [ "${USE_MULTIPATH_NORMAL}" = '1' ] then for multipath_path in /sbin/multipath /bin/multipath MISSING ; do [ -x "$multipath_path " ] && break done for dmsetup_path in /sbin/dmsetup /bin/dmsetup MISSING ; do [ -x "$dmsetup_path " ] && break done for kpartx_path in /sbin/kpartx /bin/kpartx MISSING ; do [ -x "$kpartx_path " ] && break done fail=0 ["${multipath_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but multipath binary missing! Skipping multipath" ["${dmsetup_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but dmsetup binary missing! Skipping multipath" ["${kpartx_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but kpartx binary missing! Skipping multipath" if [ "$fail" = "0" ] then good_msg "Scanning for multipath devices" good_msg ":: Populating scsi_id info for libudev queries" mkdir -p /run/udev/data for ech in /sys/block/* ; do local tgtfile=b$(cat ${ech}/dev) /lib/udev/scsi_id -g -x /dev/${ech##*/} |sed -e 's/^/E:/' >/run/udev/data/${tgtfile} done $multipath_path -v 0 sleep 2 good_msg "Activating multipath devices" $dmsetup_path ls --target multipath --exec "$kpartx_path -a -v" #for MULTIPATH_VOLUMES in /dev/mapper/*; do $kpartx_path -a $MULTIPATH_VOLUMES; done fi fi if [ "${USE_DMRAID_NORMAL}" = '1' ] then if [ -x '/sbin/dmraid' ] then good_msg "Activating Device-Mapper RAID(s)" if [ '${DMRAID_OPTS}' = '' ] then /sbin/dmraid -ay else /sbin/dmraid -ay ${DMRAID_OPTS} fi [ -x '/sbin/kpartx' ] && /sbin/dmsetup ls --exec '/sbin/kpartx -a -s' fi fi if [ "${USE_LVM_NORMAL}" = '1' ] then for lvm_path in /sbin/lvm /bin/lvm MISSING ; do [ -x "$lvm_path" ] && break done if [ "${lvm_path}" = "MISSING" ] then bad_msg "dolvm invoked, but LVM binary not available! skipping LVM volume group activation!" else for dev in ${RAID_DEVICES} do setup_md_device "${dev}" done # This is needed for LVM to accept the following logic lvm_commands="#! ${lvm_path}" # If there is a cache, update it. Unbreak at least dmcrypt [ -d /etc/lvm/cache ] && lvm_commands="${lvm_commands} \nvgscan" # To activate volumegroups on all devices in the cache lvm_commands="${lvm_commands} \nvgchange -ay --sysinit" # To create symlinks so users can use real_root=/dev/vg/root # This needs to run after vgchange, using vgchange --mknodes is too # early. lvm_commands="${lvm_commands} \nvgmknodes --ignorelockingfailure" # And finally execute it all (/proc/... needed if lvm is compiled without readline) good_msg "Scanning for and activating Volume Groups" printf "%b\n" "${lvm_commands}" | $lvm_path /proc/self/fd/0 fi fi if [ "${USE_BTRFS}" = '1' ] then if [ -x '/sbin/btrfs' ] then /sbin/btrfs device scan else bad_msg "btrfs not found: skipping btrfs device scanning!" fi fi if [ "${USE_ZFS}" = '1' ] then # Avoid race involving asynchronous module loading if call_func_timeout waitForZFS 5 then bad_msg "Cannot import ZFS pool because /dev/zfs is missing" elif [ -z "${ZFS_POOL}" ] then good_msg "Importing ZFS pools" /sbin/zpool import -N -a ${ZPOOL_CACHE} ${ZPOOL_FORCE} if [ "$?" = '0' ] then good_msg "Importing ZFS pools succeeded" else bad_msg "Imported ZFS pools failed" fi else if [ "$(zpool list -H -o name ${ZFS_POOL} 2>&1)" = "$ZFS_POOL" ] then good_msg "ZFS pool ${ZFS_POOL} already imported." if [ -n "${CRYPT_ROOT}" -o -n "${CRYPT_SWAP}" ] then good_msg "LUKS detected. Reimporting ${ZFS_POOL}" /sbin/zpool export -f "${ZFS_POOL}" /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} "${ZFS_POOL}" fi else good_msg "Importing ZFS pool ${ZFS_POOL}" /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} "${ZFS_POOL}" if [ "$?" = '0' ] then good_msg "Import of ${ZFS_POOL} succeeded" else bad_msg "Import of ${ZFS_POOL} failed" fi fi fi fi } startiscsi() { if [ ! -n "${ISCSI_NOIBFT}" ] then good_msg "Activating iSCSI via iBFT" iscsistart -b fi if [ -n "${ISCSI_INITIATORNAME}" ] && [ -n "${ISCSI_TARGET}" ] && [ -n "${ISCSI_ADDRESS}" ] then good_msg "Activating iSCSI via cmdline" if [ "${ISCSI_TGPT}" ] then ADDITIONAL="${ADDITIONAL} -g ${ISCSI_TGPT}" else ADDITIONAL="${ADDITIONAL} -g 1" fi if [ "${ISCSI_PORT}" ] then ADDITIONAL="${ADDITIONAL} -p ${ISCSI_PORT}" fi if [ "${ISCSI_USERNAME}" ] then ADDITIONAL="${ADDITIONAL} -u ${ISCSI_USERNAME}" fi if [ "${ISCSI_PASSWORD}" ] then ADDITIONAL="${ADDITIONAL} -w ${ISCSI_PASSWORD}" fi if [ "${ISCSI_USERNAME_IN}" ] then ADDITIONAL="${ADDITIONAL} -U ${ISCSI_USERNAME_IN}" fi if [ "${ISCSI_PASSWORD_IN}" ] then ADDITIONAL="${ADDITIONAL} -W ${ISCSI_PASSWORD_IN}" fi if [ "${ISCSI_DEBUG}" ] then ADDITIONAL="${ADDITIONAL} -d ${ISCSI_DEBUG}" fi iscsistart -i "${ISCSI_INITIATORNAME}" -t "${ISCSI_TARGET}" -a "${ISCSI_ADDRESS}" ${ADDITIONAL} fi } # Open a LUKS device # It is either the root or a swap, other devices are supported in the scripts provided with sys-fs/cryptsetup # $1 - root/swap openLUKS() { # please use 'tr' and this line, or remove it # eval local TYPE=`uppercase $1` case $1 in root) local TYPE=ROOT ;; swap) local TYPE=SWAP ;; esac eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"' LUKS_NAME="$1" LUKS_KEY='"${CRYPT_'${TYPE}'_KEY}"' LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"' LUKS_TRIM='"${CRYPT_'${TYPE}'_TRIM}"' local DEV_ERROR=0 KEY_ERROR=0 KEYDEV_ERROR=0 local mntkey="/mnt/key/" cryptsetup_options='' flag_opened="/${TYPE}.decrypted" [ ! -e /sbin/cryptsetup ] && bad_msg "The ramdisk does not support LUKS" && exit 1 while [ 1 ] do local gpg_cmd="" # if crypt_silent=1 and some error occurs, enter shell quietly if [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${DEV_ERROR} -eq 1 \) -o \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ] then run_shell elif [ ${DEV_ERROR} -eq 1 ] then prompt_user "LUKS_DEVICE" "${LUKS_NAME}" DEV_ERROR=0 elif [ ${KEY_ERROR} -eq 1 ] then prompt_user "LUKS_KEY" "${LUKS_NAME} key" KEY_ERROR=0 elif [ ${KEYDEV_ERROR} -eq 1 ] then prompt_user "LUKS_KEYDEV" "${LUKS_NAME} key device" KEYDEV_ERROR=0 elif [ -e ${flag_opened} ] then good_msg "The LUKS device ${LUKS_DEVICE} meanwhile was opened by someone else." break else LUKS_DEVICE=$(find_real_device "${LUKS_DEVICE}") setup_md_device ${LUKS_DEVICE} cryptsetup isLuks ${LUKS_DEVICE} if [ $? -ne 0 ] then bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT} DEV_ERROR=1 continue else # Handle keys if [ "x${LUKS_TRIM}" = "xyes" ] then good_msg "Enabling TRIM support for ${LUKS_NAME}." ${CRYPT_SILENT} cryptsetup_options="${cryptsetup_options} --allow-discards" fi if [ -n "${LUKS_KEY}" ] then local REAL_LUKS_KEYDEV="${LUKS_KEYDEV}" if [ ! -e "${mntkey}${LUKS_KEY}" ] then REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}") if [ -b "${REAL_LUKS_KEYDEV}" ] then good_msg "Using key device ${REAL_LUKS_KEYDEV}." ${CRYPT_SILENT} else good_msg "Please insert removable device ${LUKS_KEYDEV} for ${LUKS_NAME}" ${CRYPT_SILENT} # abort after 10 secs local count=10 while [ ${count} -gt 0 ] do count=$((count-1)) sleep 1 REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}") if [ -b "${REAL_LUKS_KEYDEV}" ] then good_msg "Removable device ${REAL_LUKS_KEYDEV} detected." ${CRYPT_SILENT} break fi done if [ ! -b "${REAL_LUKS_KEYDEV}" ] then eval CRYPT_${TYPE}_KEY=${LUKS_KEY} bootstrapKey ${TYPE} eval LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"' REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}") if [ ! -b "${REAL_LUKS_KEYDEV}" ]; then KEYDEV_ERROR=1 bad_msg "Removable device ${LUKS_KEYDEV} not found." ${CRYPT_SILENT} continue fi # continue otherwise will mount keydev which is mounted by bootstrap continue fi fi # At this point a device was recognized, now let's see if the key is there [ ! -d "$mntkey" ] && mkdir -p ${mntkey} 2>/dev/null >/dev/null mount -n -o ro ${REAL_LUKS_KEYDEV} ${mntkey} >/dev/null 2>/dev/null if [ "$?" != '0' ] then KEYDEV_ERROR=1 bad_msg "Mounting of device ${REAL_LUKS_KEYDEV} failed." ${CRYPT_SILENT} continue else good_msg "Removable device ${REAL_LUKS_KEYDEV} mounted." ${CRYPT_SILENT} sleep 2 # keyfile exists? if [ ! -e "${mntkey}${LUKS_KEY}" ]; then umount -n ${mntkey} 2>/dev/null >/dev/null KEY_ERROR=1 KEYDEV_ERROR=1 bad_msg "Key {LUKS_KEY} on device ${REAL_LUKS_KEYDEV} not found." ${CRYPT_SILENT} continue fi fi fi # At this point a candidate key exists (either mounted before or not) good_msg "${LUKS_KEY} on device ${REAL_LUKS_KEYDEV} found" ${CRYPT_SILENT} if [ "$(echo ${LUKS_KEY} | grep -o '.gpg$')" = ".gpg" ] && [ -x /sbin/gpg ] ; then [ -e /dev/tty ] && mv /dev/tty /dev/tty.org mknod /dev/tty c 5 1 cryptsetup_options="${cryptsetup_options} -d -" gpg_cmd="/sbin/gpg --logger-file /dev/null --quiet --decrypt ${mntkey}${LUKS_KEY} |" else cryptsetup_options="${cryptsetup_options} -d ${mntkey}${LUKS_KEY}" fi fi # At this point, keyfile or not, we're ready! crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}" crypt_filter_ret=$? touch ${flag_opened} [ -e /dev/tty.org ] \ && rm -f /dev/tty \ && mv /dev/tty.org /dev/tty if [ ${crypt_filter_ret} -eq 0 ] then good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT} break else bad_msg "Failed to open LUKS device ${LUKS_DEVICE}" ${CRYPT_SILENT} DEV_ERROR=1 KEY_ERROR=1 KEYDEV_ERROR=1 fi fi fi done umount ${mntkey} 2>/dev/null >/dev/null rmdir -p ${mntkey} 2>/dev/null >/dev/null } startLUKS() { # if key is set but neither ssh enabled or key device is given, find # the key device if [ -e "/usr/sbin/dropbear" ]; then startdropbear fi [ -n "${CRYPT_ROOT_KEY}" ] && [ -z "${CRYPT_ROOT_KEYDEV}" ] \ && sleep 6 && bootstrapKey "ROOT" if [ -n "${CRYPT_ROOT}" ]; then openLUKS "root" if [ -n "${REAL_ROOT}" ] then # Rescan volumes startVolumes else REAL_ROOT="/dev/mapper/root" fi fi # same for swap, but no need to sleep if root was unencrypted [ -n "${CRYPT_SWAP_KEY}" ] && [ -z "${CRYPT_SWAP_KEYDEV}" ] \ && { [ -z "${CRYPT_ROOT}" ] && sleep 6; bootstrapKey "SWAP"; } if [ -n "${CRYPT_SWAP}" ]; then openLUKS "swap" if [ -z "${REAL_RESUME}" ] then # Resume from swap as default REAL_RESUME="/dev/mapper/swap" fi fi if [ -e "/usr/sbin/dropbear" ]; then /bin/kill $(cat /var/run/dropbear.pid) /sbin/ifconfig $(echo "${IP}" | awk -F":" '{print $6}' ) 0.0.0.0 fi if [ -e /root.decrypted ]; then rm /root.decrypted fi if [ -e /swap.decrypted ]; then rm /swap.decrypted fi } startdropbear() { if [ "${IP}" == '' ] ; then busybox udhcpc -n -T 15 -q fi # setup environment variables for the ssh login shell echo "CRYPT_ROOT=${CRYPT_ROOT}" > /etc/login-remote.conf echo "CRYPT_SWAP=${CRYPT_SWAP}" >> /etc/login-remote.conf touch /var/log/lastlog /usr/sbin/dropbear } sdelay() { # Sleep a specific number of seconds if SDELAY is set if [ -n "${SDELAY}" ] then good_msg "Waiting ${SDELAY} seconds..." sleep ${SDELAY} elif [ "${CDROOT}" = '1' ] then good_msg 'Hint: Use scandelay[=seconds] if your live medium is slow and boot fails' fi } quiet_kmsg() { # if QUIET is set make the kernel less chatty [ -n "$QUIET" ] && echo '0' > /proc/sys/kernel/printk } verbose_kmsg() { # if QUIET is set make the kernel less chatty [ -n "$QUIET" ] && echo '6' > /proc/sys/kernel/printk } cdupdate() { if [ "${CDROOT}" = '1' ] then cdupdate_path='' for p in /${NEW_ROOT}/${CDROOT_PATH}/ /${CDROOT_PATH}/ ; do [ -x "${p}/cdupdate.sh" ] && cdupdate_path="${p}/cdupdate.sh" && break done if [ -n "${cdupdate_path}" ] then good_msg "Running cdupdate.sh ($cdupdate_path)" ${cdupdate_path} if [ "$?" != '0' ] then bad_msg "Executing cdupdate.sh failed!" run_shell fi else good_msg 'No cdupdate.sh script found, skipping...' fi fi } setup_btrfsctl() { # start BTRFS volume detection, if available [ -x /sbin/btrfsctl ] && /sbin/btrfsctl -a } setup_md_device() { local device [ -z "$1" ] && device="${REAL_ROOT}" || device="$1" [ -z "${device}" ] && return # LiveCD if [ `echo ${device}|sed -e 's#\(luks:\)\?\(/dev/md\)[[:digit:]]\+#\2#'` = "/dev/md" ] then good_msg 'Detected real_root as a md device. Setting up the device node...' MD_NUMBER=`echo ${device}|sed -e 's#\(luks:\)\?/dev/md\([[:digit:]]\+\)#\2#'` if [ ! -e /dev/md${MD_NUMBER} ] then mknod /dev/md${MD_NUMBER} b 9 ${MD_NUMBER} >/dev/null 2>&1 [ $? -ne 0 ] && bad_msg "Creation of /dev/md${MD_NUMBER} failed..." fi mdstart ${MDPART} /dev/md${MD_NUMBER} fi } do_rundebugshell() { good_msg 'Type "exit" to continue with normal bootup.' [ -x /bin/sh ] && /bin/sh || /bin/ash } rundebugshell() { if [ -n "$DEBUG" ] then good_msg 'Starting debug shell as requested by "debug" option.' good_msg "Stopping by: ${1}" do_rundebugshell fi } do_resume() { if [ -d /proc/suspend2 -o -d /sys/power/suspend2 -o -d /sys/power/tuxonice ]; then tuxonice_resume else swsusp_resume fi } swsusp_resume() { # determine swap resume partition local device=$(ls -lL "${REAL_RESUME}" | sed 's/\ */ /g' | cut -d \ -f 5-6 | sed 's/,\ */:/') [ -f /sys/power/resume ] && echo "${device}" > /sys/power/resume } tuxonice_resume() { local splash_theme if grep "splash=" /proc/cmdline > /dev/null 2>&1; then splash_theme=$(cat /proc/cmdline | sed 's/.*splash=/splash=/' | sed 's/ .*//' | sed 's/.*theme://' | sed 's/,.*//') fi local tuxonice_userui_program="/sys/power/tuxonice/user_interface/program" local tuxonice_do_resume="/sys/power/tuxonice/do_resume" local tuxonice_resumedev="/sys/power/tuxonice/resume" local tuxonice_replace_swsusp="/sys/power/tuxonice/replace_swsusp" # # Backward compatibility # if [ -e /sys/power/suspend2 ]; then tuxonice_userui_program="/sys/power/suspend2/user_interface/program" tuxonice_do_resume="/sys/power/suspend2/do_resume" tuxonice_resumedev="/sys/power/suspend2/resume" tuxonice_replace_swsusp="/sys/power/suspend2/replace_swsusp" elif [ -e /proc/suspend2 ]; then tuxonice_userui_program="/proc/suspend2/userui_program" tuxonice_do_resume="/proc/suspend2/do_resume" tuxonice_resumedev="/proc/suspend2/resume" tuxonice_replace_swsusp="/proc/suspend2/replace_swsusp" fi # if 'use_swsusp' is given, use swsusp instead if grep "use_swsusp" /proc/cmdline > /dev/null 2>&1; then echo 0 > ${tuxonice_replace_swsusp} swsusp_resume return fi modules_scan tuxonice # we both configure tuxonice and activate resuming, # however the kernel will resume only if an image is found if ! grep suspend_noui /proc/cmdline > /dev/null 2>&1; then which suspend2ui_text > /dev/null 2>&1 && which suspend2ui_text > "${tuxonice_userui_program}" which tuxoniceui_text > /dev/null 2>&1 && which tuxoniceui_text > "${tuxonice_userui_program}" if [ -n "${splash_theme}" ]; then ln -s /etc/splash/${splash_theme} /etc/splash/suspend2 ln -s /etc/splash/${splash_theme} /etc/splash/tuxonice which suspend2ui_fbsplash > /dev/null 2>&1 && which suspend2ui_fbsplash > "${tuxonice_userui_program}" which tuxoniceui_fbsplash > /dev/null 2>&1 && which tuxoniceui_fbsplash > "${tuxonice_userui_program}" fi fi echo "${REAL_RESUME}" > "${tuxonice_resumedev}" echo > "${tuxonice_do_resume}" } find_loop() { for loop in ${LOOPS} do if [ -e "${CDROOT_PATH}""${loop}" ] then LOOP="${loop}" fi done } find_looptype() { LOOPTYPE="${LOOP##*.}" [ "${LOOPTYPE}" == "loop" ] && LOOPTYPE="normal" [ "${LOOP}" == "/zisofs" ] && LOOPTYPE="${LOOP#/}" [ -z "${LOOPTYPE}" ] && LOOPTYPE="noloop" } getdvhoff() { echo $(( $(hexdump -n 4 -s $((316 + 12 * $2)) -e '"%i"' $1) * 512)) } setup_squashfs_aufs() { # Setup aufs directories and vars aufs_rw_branch=/mnt/aufs-rw-branch aufs_ro_branch=/mnt/livecd for dir in $aufs_rw_branch $aufs_ro_branch; do [ ! -d $dir ] && mkdir -p "$dir" done good_msg "Loading aufs module ..." modprobe aufs &>/dev/null checkfs aufs mount -t squashfs -o loop,ro "$CDROOT_PATH/$LOOPEXT$LOOP" "$aufs_ro_branch" mount -t tmpfs none "$aufs_rw_branch" mount -t aufs -o "br:$aufs_rw_branch:$aufs_ro_branch" aufs "$NEW_ROOT" } setup_unionfs() { local rw_dir=$1 local ro_dir=$2 if [ "${USE_UNIONFS_NORMAL}" = '1' ] then # Directory used for rw changes in union mount filesystem UNION=/union # MEMORY=/memory # if [ -z "$UID" ] # then # CHANGES=$MEMORY/unionfs_changes/default # else # CHANGES=$MEMORY/unionfs_changes/$UID # fi # mkdir -p ${MEMORY} mkdir -p ${UNION} good_msg "Loading fuse module" modprobe fuse > /dev/null 2>&1 # if [ -n "${UNIONFS}" ] # then # CHANGESDEV=${UNIONFS} # good_msg "mounting $CHANGESDEV to $MEMORY for unionfs support" # mount -t auto $CHANGESDEV $MEMORY # # mount tmpfs only in the case when changes= boot parameter was # # empty or we were not able to mount the storage device # ret=$? # if [ ${ret} -ne 0 ] # then # bad_msg "mount of $CHANGESDEV failed falling back to ramdisk based unionfs" # mount -t tmpfs tmpfs $MEMORY # fi # if [ "${CDROOT}" -eq '1' -a ! -f ${MEMORY}/livecd.unionfs ] # then # umount $MEMORY # bad_msg "failed to find livecd.unionfs file on $CHANGESDEV" # bad_msg "create a livecd.unionfs file on this device if you wish to use it for unionfs" # bad_msg "falling back to ramdisk based unionfs for safety" # mount -t tmpfs tmpfs $MEMORY # fi # else # good_msg "Mounting ramdisk to $MEMORY for unionfs support..." # mount -t tmpfs tmpfs $MEMORY # fi mkdir /tmp mkdir -p ${UNION} # mkdir -p $CHANGES # mount -t unionfs -o dirs=$CHANGES=rw unionfs ${UNION} good_msg "Creating union mount" unionfs -o allow_other,cow,noinitgroups,suid,dev,default_permissions,use_ino ${rw_dir}=RW:${ro_dir}=RO ${UNION} 2>/dev/null ret=$? if [ ${ret} -ne 0 ] then bad_msg "Can't setup union mount!" USE_UNIONFS_NORMAL=0 fi [ ! -d "${NEW_ROOT}${CDROOT_PATH}" ] && mkdir -p "${NEW_ROOT}${CDROOT_PATH}" mount --bind "${CDROOT_PATH}" "${NEW_ROOT}${CDROOT_PATH}" else USE_UNIONFS_NORMAL=0 fi } get_mounts_list() { awk ' /^[[:blank:]]*#/ { next } { print $1 } ' ${NEW_ROOT}/etc/initramfs.mounts } get_mount_fstype() { [ -e "${NEW_ROOT}"/etc/fstab ] || return 1 awk -v fs="$1" ' /^[[:blank:]]*#/ { next } $2 == fs { print $3 } ' ${NEW_ROOT}/etc/fstab } get_mount_options() { [ -e "${NEW_ROOT}"/etc/fstab ] || return 1 awk -v fs="$1" ' /^[[:blank:]]*#/ { next } $2 == fs { print $4 } ' ${NEW_ROOT}/etc/fstab } get_mount_device() { [ -e "${NEW_ROOT}"/etc/fstab ] || return 1 awk -v fs="$1" ' /^[[:blank:]]*#/ { next } $2 == fs { print $1 } ' ${NEW_ROOT}/etc/fstab } # If the kernel is handed a mount option is does not recognize, it WILL fail to # mount. util-linux handles auto/noauto, but busybox passes it straight to the kernel # which then rejects the mount. # To make like a little easier, busybox mount does not care about leading, # trailing or duplicate commas. strip_mount_options() { sed -r \ -e 's/(,|^)(no)?auto(,|$)/,/g' \ -e 's/(,|^)iversion(,|$)/,/g' } checkfs() { if [ -r "/proc/filesystems" ]; then if grep -qs "$1" /proc/filesystems ; then return 0 fi fi warn_msg "No ${1} support listed in /proc/filesystems" warn_msg "${1} is not likely to work on this medium" return 1 }