You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
genkernel_fork/defaults/initrd.scripts

2121 lines
52 KiB

#!/bin/sh
. /etc/initrd.defaults
splash() {
return 0
}
[ -e "${INITRD_SPLASH}" ] && . "${INITRD_SPLASH}"
is_fbsplash() {
if [ -e "${INITRD_SPLASH}" ] && [ "${FBSPLASH}" = '1' ]
then
return 0
fi
return 1
}
is_plymouth() {
if [ "${PLYMOUTH}" = '1' ] && [ "${QUIET}" = '1' ] \
&& [ -e "${PLYMOUTHD_BIN}" ]
then
return 0
fi
return 1
}
is_plymouth_started() {
[ -n "${PLYMOUTH_FAILURE}" ] && return 1
is_plymouth && "${PLYMOUTH_BIN}" --ping 2>/dev/null && return 0
return 1
}
splashcmd() {
# plymouth support
local cmd="${1}"
shift
case "${cmd}" in
init)
is_fbsplash && splash init
is_plymouth && plymouth_init
;;
verbose)
is_fbsplash && splash verbose
plymouth_hide
;;
quiet)
# no fbsplash support
plymouth_show
;;
set_msg)
is_fbsplash && splash set_msg "${1}"
plymouth_message "${1}"
;;
hasroot)
# no fbsplash support
plymouth_newroot "${1}"
;;
esac
}
plymouth_init() {
good_msg "Enabling Plymouth"
mkdir -p /run/plymouth || return 1
# Make sure that udev is done loading tty and drm
if is_udev
then
udevadm trigger --action=add --attr-match=class=0x030000 \
>/dev/null 2>&1
udevadm trigger --action=add --subsystem-match=graphics \
--subsystem-match=drm --subsystem-match=tty \
>/dev/null 2>&1
udevadm settle
fi
local consoledev=
local other=
read consoledev other < /sys/class/tty/console/active
consoledev=${consoledev:-tty0}
"${PLYMOUTHD_BIN}" --attach-to-session --pid-file /run/plymouth/pid \
|| {
bad_msg "Plymouth load error";
PLYMOUTH_FAILURE=1
return 1;
}
plymouth_show
good_msg "Plymouth enabled"
}
plymouth_hide() {
is_plymouth_started && "${PLYMOUTH_BIN}" --hide-splash
}
plymouth_show() {
is_plymouth_started && "${PLYMOUTH_BIN}" --show-splash
}
plymouth_message() {
is_plymouth_started && "${PLYMOUTH_BIN}" --update="${1}"
}
plymouth_newroot() {
is_plymouth_started && "${PLYMOUTH_BIN}" --newroot="${1}"
}
splash_init() {
if is_udev; then
# if udev, we can load the splash earlier
# In the plymouth case, udev will load KMS automatically
splashcmd init
fi
}
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 1
fi
return 0
}
modules_load() {
for module in $*
do
echo ${module} >> /etc/modules/extra_load
done
modules_scan extra_load
}
modules_scan() {
local MODS
local loaded
MODS=$(cat /etc/modules/${1} 2>/dev/null)
[ -n "${MODS}" ] && [ -z "${QUIET}" ] && \
echo -ne "${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}" ] && \
echo -e "${BOLD} ::${NORMAL} Skipping ${x}..."
elif [ "${MLOAD}" = "${MLIST}" ]
then
if [ -n "${DEBUG}" ]; then
echo -ne "${BOLD} ::${NORMAL} "
echo -ne "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}" ] && \
echo -en "${x} "
else
[ -z "${QUIET}" ] && \
echo -e "${BOLD} ::${NORMAL} Skipping ${x}..."
fi
done
[ -n "${MODS}" ] && [ -z "${QUIET}" ] && echo
}
modules_init() {
if [ -z "${DO_modules}" ]; then
good_msg 'Skipping module load; disabled via commandline'
elif [ -d "/lib/modules/${KV}" ]; then
good_msg 'Loading modules'
# Load appropriate kernel modules
if [ "${NODETECT}" != '1' ]; then
for modules in ${MY_HWOPTS}
do
modules_scan ${modules}
done
fi
# Always eval doload=...
modules_load ${MDOLIST}
else
good_msg 'Skipping module load; no modules in the ramdisk!'
fi
# Give udev time to execute all the rules. This may be beneficial
# for usb-storage devices.
is_udev && udevadm settle
}
uppercase() {
# needs tr on busybox
echo $1 | tr 'a-z' 'A-Z'
}
is_livecd() {
[ "${CDROOT}" = "1" ] && return 0
return 1
}
is_nfs() {
[ "${REAL_ROOT}" = "/dev/nfs" ] && return 0
return 1
}
is_aufs() {
[ "${USE_AUFS}" = "1" ] && return 0
return 1
}
setup_real_root() {
if [ -z "${REAL_ROOT}" -a "${FAKE_ROOT}" != "/dev/ram0" ]; then
REAL_ROOT="${FAKE_ROOT}"
fi
if [ -z "${REAL_INIT}" -a "${FAKE_INIT}" != "/linuxrc" ]; then
REAL_INIT="${FAKE_INIT}"
fi
if [ -z "${REAL_ROOTFLAGS}" ]; then
REAL_ROOTFLAGS="${FAKE_ROOTFLAGS}"
fi
}
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
13 years ago
good_msg "Attempting to mount media: ${x}" ${CRYPT_SILENT}
mount -r -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}
}
bootstrap_cd() {
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}
}
bootstrap_key() {
# $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!"
}
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."
fi
fi
if [ "${NFSROOT}" != '' ]
then
NFSOPTIONS=${NFSROOT#*,}
NFSROOT=${NFSROOT%%,*}
if [ "${NFSOPTIONS}" = "${NFSROOT}" ]
then
NFSOPTIONS=$DEFAULT_NFSOPTIONS
else
NFSOPTIONS="${DEFAULT_NFSOPTIONS},${NFSOPTIONS}"
fi
if is_livecd
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 ?"
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 ?"
fi
# FIXME: Need to start portmap and the other rpc daemons in
# order to remount rw.
fi
fi
fi
}
find_real_device() {
local device="${1}"
local out=
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
out="${REAL_DEVICE}"
fi
;;
*)
out="${device}"
;;
esac
echo -n "${out}"
}
get_device_fstype() {
local device=$(find_real_device "${1}")
if [ -n "${device}" ]; then
blkid -o value -s TYPE "${device}"
return ${?} # readability
else
echo "Cannot resolve device: ${1}" >&2
return 1
fi
}
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}"
}
is_udev() {
[ -x "${UDEVD}" ] && [ -z "${USE_MDEV}" ] && return 0
return 1
}
is_mdev() {
if [ ! -x "${UDEVD}" ] || [ -n "${USE_MDEV}" ]
then
return 0
fi
return 1
}
devmgr_init() {
if is_udev; then
good_msg 'Activating udev'
echo "${UDEVD}" > /proc/sys/kernel/hotplug
echo "" > /sys/kernel/uevent_helper
"${UDEVD}" --daemon --resolve-names=never && \
udevadm trigger --action=add && \
udevadm settle || bad_msg "udevd failed to run"
elif is_mdev; then
good_msg 'Activating mdev'
# Serialize hotplug events
touch /dev/mdev.seq
echo "${MDEVD}" > /proc/sys/kernel/hotplug
# Ensure that device nodes are properly configured
"${MDEVD}" -s || bad_msg "mdev -s failed"
else
bad_msg "Cannot find either udev or mdev"
fi
}
# Terminate the device manager, this happens right before pivot_root
devmgr_terminate() {
if is_udev; then
udevadm settle
udevadm control --exit || bad_msg "Unable to terminate udevd"
fi
# mdev doesn't require anything, it seems
}
mount_devfs () {
# Use devtmpfs if enabled in kernel,
# else tmpfs. Always run mdev just in case
devfs=tmpfs
if grep -qs devtmpfs /proc/filesystems ; 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 ] && echo -e "${GOOD}>>${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}
bad_msg() {
msg_string=$1
msg_string="${msg_string:-...}"
if [ "$2" != 1 ]
then
splashcmd verbose
echo -e "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
fi
}
warn_msg() {
msg_string=$1
msg_string="${msg_string:-...}"
[ "$2" != 1 ] && echo -e "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}
# Courtesy of dracut. Licensed under GPL-2.
# Taken from: dracut/modules.d/90crypt/crypt-lib.sh
# ask_for_password
#
# Wraps around plymouth ask-for-password and adds fallback to tty password ask
# if plymouth is not present.
#
# --cmd command
# Command to execute. Required.
# --prompt prompt
# Password prompt. Note that function already adds ':' at the end.
# Recommended.
# --tries n
# How many times repeat command on its failure. Default is 3.
# --ply-[cmd|prompt|tries]
# Command/prompt/tries specific for plymouth password ask only.
# --tty-[cmd|prompt|tries]
# Command/prompt/tries specific for tty password ask only.
# --tty-echo-off
# Turn off input echo before tty command is executed and turn on after.
# It's useful when password is read from stdin.
ask_for_password() {
local cmd; local prompt; local tries=3
local ply_cmd; local ply_prompt; local ply_tries=3
local tty_cmd; local tty_prompt; local tty_tries=3
local ret
while [ $# -gt 0 ]; do
case "$1" in
--cmd) ply_cmd="$2"; tty_cmd="$2" shift;;
--ply-cmd) ply_cmd="$2"; shift;;
--tty-cmd) tty_cmd="$2"; shift;;
--prompt) ply_prompt="$2"; tty_prompt="$2" shift;;
--ply-prompt) ply_prompt="$2"; shift;;
--tty-prompt) tty_prompt="$2"; shift;;
--tries) ply_tries="$2"; tty_tries="$2"; shift;;
--ply-tries) ply_tries="$2"; shift;;
--tty-tries) tty_tries="$2"; shift;;
--tty-echo-off) tty_echo_off=yes;;
esac
shift
done
{ flock -s 9;
# Prompt for password with plymouth, if installed and running.
if is_plymouth_started
then
"${PLYMOUTH_BIN}" ask-for-password \
--prompt="$ply_prompt" \
--number-of-tries=$ply_tries \
--command="$ply_cmd"
ret=$?
else
splashcmd verbose
if [ "$tty_echo_off" = yes ]; then
stty_orig="$(stty -g)"
stty -echo
fi
local i=1
while [ $i -le $tty_tries ]; do
[ -n "$tty_prompt" ] && \
printf "$tty_prompt [$i/$tty_tries]:" >&2
eval "$tty_cmd" && ret=0 && break
ret=$?
i=$(($i+1))
[ -n "$tty_prompt" ] && printf '\n' >&2
done
[ "$tty_echo_off" = yes ] && stty $stty_orig
# no need for: splashcmd quiet
# since fbsplash does not support it
if [ $ret -ne 0 ] && is_fbsplash
then
splashcmd set_msg 'Disk unlocked.'
fi
fi
} 9>/.console_lock
[ $ret -ne 0 ] && bad_msg "Wrong password"
return $ret
}
crypt_exec() {
if [ "${CRYPT_SILENT}" = '1' ]
then
eval ${1} >/dev/null 2>/dev/null
else
ask_for_password --ply-tries 5 \
--ply-cmd "${1}" \
--ply-prompt "Encryption password (${LUKS_DEVICE}): " \
--tty-tries 5 \
--tty-cmd "${1}" || return 1
return 0
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}
[ $# != 2 -a $# != 3 ] && \
bad_msg "Bad invocation of function prompt_user."
bad_msg "Please file a bug report with this message" && exit 1
[ -n "${3}" ] && local explnt=" or : ${3}" || local explnt="."
splashcmd verbose
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...'
echo -n "${2}(${oldvalue}) :: "
read ${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 <Ctrl>+D"
run_shell
;;
'')
eval ${1}'='${oldvalue}
;;
esac
splashcmd quiet
}
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 ] && choose_keymap
[ "${DEVBIND}" = '1' ] && umount /dev
if [ -e /etc/sysconfig/keyboard ] && is_livecd
then
mkdir -p ${NEW_ROOT}/etc/sysconfig/
cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard
fi
fi
}
choose_keymap() {
good_msg "Loading keymaps"
if [ -z "${keymap}" ]
then
splashcmd verbose
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
mkdir -p /etc/sysconfig
echo "XKEYBOARD=${keymap}" > /etc/sysconfig/keyboard
splashcmd set_msg "Set keymap to ${keymap}"
elif [ -z "${keymap}" ]
then
good_msg
good_msg "Keeping default keymap"
splashcmd set_msg "Keeping default keymap"
else
bad_msg "Sorry, but keymap ''${keymap}'' is invalid!"
unset keymap
choose_keymap
fi
}
# This helper function is to be called using call_func_timeout.
# This works around the inability of busybox modprobe to handle complex module
# dependencies. This also enables us to wait a reasonable amount of time until
# /dev/zfs appears.
wait_for_zfs() {
Workaround busybox modprobe's inability to load ZFS modules Commit 3a054014e880e5b1ff28e3d87767c45a073da6b5 replaced our modprobe with busybox's modprobe. Unfortunately, busybox's modprobe appears to be unable to properly load modules with more than 1 level of dependencies. The zfs and zpool commands will invoke modprobe if /dev/zvol is missing, which concealed this problem. However, this caused problems because some invocations would fail and under certain circumstances, init would be killed, causing a kernel panic. This issue was made clear by commit c812c35100771bb527f6b03853fa6d8ef66a48fe, which ensured that the zpool and zfs commands were not run until the ZFS module was loaded. busybox modprobe's failure to load module dependencies correctly appears to occur because busybox modprobe does not wait until until a module is loaded before loading a module that depends on it, which is a race. It would be best to correct this race by waiting until the module has properly loaded, but it is not clear that the race is the only thing going wrong and developer time is a premium. We implement a workaround by modifying the busy loop added in the previous commit to explicit call `modprobe zfs` on each iteration. While the first few calls fail due to bugs in busybox modprobe, it will eventually work, after which each call is a noop. This lets us keep looping until either the loop exit condition that /dev/zvol exist is reached or the 5 second timeout is reached. Once the busybox modprobe issue is fixed, this workaround should be safe to revert. Signed-off-by: Richard Yao <ryao@gentoo.org>
12 years ago
while [ ! -c /dev/zfs ]; do modprobe zfs 2> /dev/null; done;
}
zfs_init() {
# Set variables based on the value of REAL_ROOT
case "${REAL_ROOT}" in
ZFS=*)
ZFS_POOL=${REAL_ROOT#*=}
ZFS_POOL=${ZFS_POOL%%/*}
USE_ZFS=1
;;
ZFS)
USE_ZFS=1
;;
esac
# Verify that it is safe to use ZFS
if [ "USE_ZFS" = "1" ]
then
for i in /sbin/zfs /sbin/zpool
do
if [ ! -x ${i} ]
then
USE_ZFS=0
bad_msg 'Aborting use of zfs because ${i} not found!'
break
fi
done
fi
}
start_volumes() {
#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 [ -e '/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
good_msg "Scanning for multipath devices"
/sbin/multipath -v 0
sleep 2
good_msg "Activating multipath devices"
/sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -a -v"
#for MULTIPATH_VOLUMES in /dev/mapper/*; do kpartx -a $MULTIPATH_VOLUMES; done
fi
if [ "${USE_DMRAID_NORMAL}" = '1' ]
then
if [ -e '/sbin/dmraid' ]
then
good_msg "Activating Device-Mapper RAID(s)"
if [ '${DMRAID_OPTS}' = '' ]
then
/sbin/dmraid -ay
else
/sbin/dmraid -ay ${DMRAID_OPTS}
fi
fi
fi
if [ "${USE_LVM_NORMAL}" = '1' ]
then
if [ -e '/sbin/lvm' ]
then
if is_mdev
then
for dev in ${RAID_DEVICES}
do
setup_md_device "${dev}"
done
fi
# This is needed for /sbin/lvm to accept the following logic
lvm_commands="#! /sbin/lvm"
# If there is a cahe, 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"
if is_mdev
then
# 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"
fi
# 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}" | /sbin/lvm /proc/self/fd/0
else
bad_msg "vgscan or vgchange not found: skipping LVM volume group activation!"
fi
fi
if [ "${USE_ZFS}" = '1' ]
then
# Avoid race involving asynchronous module loading
if call_func_timeout wait_for_zfs 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_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_FORCE} "${ZFS_POOL}"
fi
else
good_msg "Importing ZFS pool ${ZFS_POOL}"
/sbin/zpool import -N ${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
is_udev && udevadm settle
}
start_iscsi() {
if [ ! -e /usr/sbin/iscsistart ]; then
return 0 # disabled
fi
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}
# let iscsid settle - otherwise mounting the iSCSI-disk
# will fail (very rarely, though)
sleep 1
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-luks
# $1 - root/swap
open_luks() {
# 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=''
[ ! -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
else
local luks_dev=$(find_real_device "${LUKS_DEVICE}")
[ -n "${luks_dev}" ] && LUKS_DEVICE="${luks_dev}" # otherwise hope...
setup_md_device "${LUKS_DEVICE}"
/sbin/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}" ] && [ -n "${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}" ] && [ -n "${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}
bootstrap_key ${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" ] && [ -e /usr/bin/gpg ] ; then
[ -e /dev/tty ] && mv /dev/tty /dev/tty.org
mknod /dev/tty c 5 1
cryptsetup_options="${cryptsetup_options} -d -"
gpg_cmd="/usr/bin/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_exec "${gpg_cmd}/sbin/cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
crypt_exec_ret=$?
[ -e /dev/tty.org ] \
&& rm -f /dev/tty \
&& mv /dev/tty.org /dev/tty
if [ ${crypt_exec_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
}
start_luks() {
# if key is set but key device isn't, find it
[ -n "${CRYPT_ROOT_KEY}" ] && [ -z "${CRYPT_ROOT_KEYDEV}" ] \
&& sleep 6 && bootstrap_key "ROOT"
if [ -n "${CRYPT_ROOT}" ]; then
open_luks "root"
if [ -n "${REAL_ROOT}" ]
then
# Rescan volumes
start_volumes
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; bootstrap_key "SWAP"; }
if [ -n "${CRYPT_SWAP}" ]; then
open_luks "swap"
if [ -z "${REAL_RESUME}" ]
then
# Resume from swap as default
REAL_RESUME="/dev/mapper/swap"
fi
fi
}
sdelay() {
# Sleep a specific number of seconds if SDELAY is set
if [ -n "${SDELAY}" ]
then
good_msg "Waiting ${SDELAY} seconds..."
sleep ${SDELAY}
elif is_livecd
then
good_msg 'Hint: Use scandelay[=seconds] if your live medium is slowand 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 is_livecd
then
if [ -x /${CDROOT_PATH}/cdupdate.sh ]
then
good_msg "Running cdupdate.sh"
${CDROOT_PATH}/cdupdate.sh
if [ "$?" != '0' ]
then
bad_msg "Executing cdupdate.sh failed!"
run_shell
fi
else
good_msg 'No cdupdate.sh script found, skipping...'
fi
fi
}
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() {
splashcmd verbose
good_msg 'Type "exit" to continue with normal bootup.'
[ -x /bin/sh ] && /bin/sh || /bin/ash
splashcmd quiet
}
rundebugshell() {
if [ -n "$DEBUG" ]
then
good_msg 'Starting debug shell as requested by "debug" option.'
good_msg "Stopping by: ${1}"
do_rundebugshell
fi
}
resume_init() {
if [ -z "${REAL_RESUME}" ]; then
return 0
fi
if [ "${NORESUME}" = "1" ]; then
return 0
fi
local resume_dev=$(find_real_device "${REAL_RESUME}")
if [ -n "${resume_dev}" ]; then
REAL_RESUME="${resume_dev}"
good_msg "Detected real_resume=${resume_dev}"
else
bad_msg "Cannot resolve real_resume=${REAL_RESUME}"
bad_msg "Something bad may happen, crossing fingers"
fi
do_resume
}
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 -a -n "${device}" ] && \
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
local overlay=/mnt/overlay
local static=/mnt/livecd
for i in "${overlay}" "${static}"; do
[ ! -d "${i}" ] && mkdir -p "${i}"
done
good_msg "Loading aufs"
modprobe aufs > /dev/null 2>&1
mount -t squashfs -o loop,ro "${CDROOT_PATH}/${LOOPEXT}${LOOP}" "${static}"
mount -t tmpfs none "${overlay}"
mount -t aufs -o br:${overlay}:${static} aufs "${NEW_ROOT}"
[ ! -d "${NEW_ROOT}${overlay}" ] && mkdir -p "${NEW_ROOT}${overlay}"
[ ! -d "${NEW_ROOT}${static}" ] && mkdir -p "${NEW_ROOT}${static}"
echo "aufs / aufs defaults 0 0" > "${NEW_ROOT}"/etc/fstab
for i in "${overlay}" "${static}"; do mount --move "${i}" "${NEW_ROOT}${i}"; done
# have handy /mnt/cdrom (CDROOT_PATH) as well
local new_cdroot="${NEW_ROOT}${CDROOT_PATH}"
[ ! -d "${new_cdroot}" ] && mkdir -p "${new_cdroot}"
mount --bind "${CDROOT_PATH}" "${new_cdroot}"
}
livecd_init() {
good_msg "Making tmpfs for ${NEW_ROOT}"
mount -n -t tmpfs -o mode=0755 tmpfs "${NEW_ROOT}"
local dirs=
dirs="dev mnt proc run sys tmp mnt/livecd"
dirs="${dirs} mnt/key tmp/.initrd mnt/gentoo"
for i in ${dirs}; 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 "${NEW_ROOT}"/dev/null c 1 3
[ ! -e "${NEW_ROOT}/dev/console" ] && \
mknod "${NEW_ROOT}"/dev/console c 5 1
# 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.
if [ -e /dev/tty1 ]; then
[ ! -e "${NEW_ROOT}/dev/tty1" ] && \
mknod "${NEW_ROOT}/dev/tty1" c 4 1
fi
if ! is_nfs && [ "${LOOPTYPE}" != "sgimips" ]; then
bootstrap_cd
fi
if [ "${REAL_ROOT}" = '' ]
then
warn_msg "No bootable medium found. Waiting for new devices..."
COUNTER=0
while [ ${COUNTER} -lt 3 ]; do
sleep 3
let COUNTER=${COUNTER}+1
done
sleep 1
bootstrap_cd
fi
if [ "${REAL_ROOT}" = '' ]
then
# leave stale mounts around, make possible to debug
bad_msg 'Could not find CD to boot, something else needed!'
CDROOT=0
fi
}
livecd_mount() {
# Let Init scripts know that we booted from CD
export CDBOOT
CDBOOT=1
good_msg 'Determining looptype ...'
cd "${NEW_ROOT}"
# Find loop and looptype
[ -z "${LOOP}" ] && find_loop
[ -z "${LOOPTYPE}" ] && find_looptype
cache_cd_contents
# If encrypted, find key and mount, otherwise mount as usual
if [ -n "${CRYPT_ROOT}" ]
then
CRYPT_ROOT_KEY="$(head -n 1 "${CDROOT_PATH}"/${CDROOT_MARKER})"
CRYPT_ROOT='/dev/loop0'
good_msg 'You booted an encrypted livecd' "${CRYPT_SILENT}"
losetup /dev/loop0 "${CDROOT_PATH}/${LOOPEXT}${LOOP}"
test_success 'Preparing loop filesystem'
start_luks
case ${LOOPTYPE} in
normal)
MOUNTTYPE="ext2"
;;
*)
MOUNTTYPE="${LOOPTYPE}"
;;
esac
mount -t "${MOUNTTYPE}" -o ro /dev/mapper/root \
"${NEW_ROOT}/mnt/livecd"
test_success 'Mount filesystem'
FS_LOCATION='mnt/livecd'
else
# Setup the loopback mounts, if unencrypted
if [ "${LOOPTYPE}" = 'normal' ]; then
_livecd_mount_normal
FS_LOCATION='mnt/livecd'
elif [ "${LOOPTYPE}" = 'squashfs' ]; then
_livecd_mount_squashfs
FS_LOCATION='mnt/livecd'
elif [ "${LOOPTYPE}" = 'gcloop' ]; then
_livecd_mount_gcloop
FS_LOCATION='mnt/livecd'
elif [ "${LOOPTYPE}" = 'zisofs' ]; then
FS_LOCATION="${CDROOT_PATH/\/}/${LOOPEXT}${LOOP}"
elif [ "${LOOPTYPE}" = 'noloop' ]; then
FS_LOCATION="${CDROOT_PATH/\/}"
elif [ "${LOOPTYPE}" = 'sgimips' ]; then
_livecd_mount_sgimips
FS_LOCATION='mnt/livecd'
fi
fi
is_nfs && _livecd_mount_unpack_nfs
# Manually copy livecd content to tmpfs if aufs is disabled
is_aufs || _livecd_mount_copy_content
}
# Unpack additional packages from NFS mount
# This is useful for adding kernel modules to /lib
# We do this now, so that additional packages can add whereever
# they want.
_livecd_mount_unpack_nfs() {
if [ -e "${CDROOT_PATH}/add" ]; then
for targz in $(ls ${CDROOT_PATH}/add/*.tar.gz); do
tarname=$(basename ${targz})
good_msg "Adding additional package ${tarname}"
(cd ${NEW_ROOT} ; /bin/tar -xzf ${targz})
done
fi
}
_livecd_mount_sgimips() {
# getdvhoff finds the starting offset (in bytes) of the squashfs
# partition on the cdrom and returns this offset for losetup
#
# All currently supported SGI Systems use SCSI CD-ROMs, so
# so we know that the CD-ROM is usually going to be /dev/sr0.
#
# We use the value given to losetup to set /dev/loop0 to point
# to the liveCD root partition, and then mount /dev/loop0 as
# the LiveCD rootfs
good_msg 'Locating the SGI LiveCD Root Partition'
echo ' ' | \
losetup -o $(getdvhoff "${NEW_ROOT}${REAL_ROOT}" 0) \
"${NEW_ROOT}${CDROOT_DEV}" \
"${NEW_ROOT}${REAL_ROOT}"
test_success 'losetup /dev/sr0 /dev/loop0'
good_msg 'Mounting the Root Partition'
mount -t squashfs -o ro "${NEW_ROOT}${CDROOT_DEV}" \
"${NEW_ROOT}/mnt/livecd"
test_success 'mount /dev/loop0 /'
}
_livecd_mount_gcloop() {
good_msg 'Mounting gcloop filesystem'
echo ' ' | losetup -E 19 -e ucl-0 -p0 \
"${NEW_ROOT}/dev/loop0" \
"${CDROOT_PATH}/${LOOPEXT}${LOOP}"
test_success 'losetup the loop device'
mount -t ext2 -o ro "${NEW_ROOT}/dev/loop0" "${NEW_ROOT}/mnt/livecd"
test_success 'Mount the losetup loop device'
}
_livecd_mount_normal() {
good_msg 'Mounting loop filesystem'
mount -t ext2 -o loop,ro \
"${CDROOT_PATH}/${LOOPEXT}${LOOP}" \
"${NEW_ROOT}/mnt/livecd"
test_success 'Mount filesystem'
}
_livecd_mount_squashfs() {
# if AUFS, redirect to the squashfs+aufs setup function
if is_aufs; then
good_msg 'Mounting squashfs & aufs filesystems'
setup_squashfs_aufs
test_success 'Mount filesystem'
return # preserve old behaviour
fi
good_msg 'Mounting squashfs filesystem'
local cached_squashfs_path="${NEW_ROOT}/mnt/${LOOP}"
local squashfs_path="${CDROOT_PATH}/${LOOPEXT}${LOOP}"
# Upgrade to cached version if possible
if [ -n "${DO_cache}" ] && [ -f "${cached_squashfs_path}" ]; then
squashfs_path="${cached_squashfs_path}"
fi
mount -t squashfs -o loop,ro "${squashfs_path}" \
"${NEW_ROOT}/mnt/livecd" || {
bad_msg "squashfs filesystem could not be mounted."
do_rundebugshell
}
}
# Manually copy livecd read-only content into the final livecd root
# filesystem directory, which has been mounted as tmpfs.
_livecd_mount_copy_content() {
local fs_loc="${NEW_ROOT}/${FS_LOCATION}"
good_msg "Copying read-write image contents to tmpfs"
# Copy over stuff that should be writable
(
cd "${fs_loc}" && cp -a ${ROOT_TREES} "${NEW_ROOT}"
) || {
bad_msg "Copy failed, dropping into a shell."
do_rundebugshell
}
# Now we do the links.
for x in ${ROOT_LINKS}; do
if [ -L "${fs_loc}/${x}" ]; then
ln -s "$(readlink ${fs_loc}/${x})" "${x}" 2>/dev/null
continue
fi
# List all subdirectories of x
find "${fs_loc}/${x}" -type d 2>/dev/null | \
while read directory; do
# Strip the prefix of the FS_LOCATION
directory="${directory#${fs_loc}/}"
# Skip this directory if we already linked a parent
# directory
if [ "${current_parent}" != "" ]; then
var=$(echo "${directory}" | \
grep "^${current_parent}")
if [ "${var}" != "" ]; then
continue
fi
fi
local root_d="${NEW_ROOT}/${directory}"
local fsloc_d="${FS_LOCATION}/${directory}"
# Test if the directory exists already
if [ ! -e "/${root_d}" ]; then
# It does not exist, make a link to the livecd
ln -s "/${FS_LOCATION}/${directory}" \
"${directory}" 2>/dev/null
current_parent="${directory}"
continue
fi
# It does exist, link all the individual files
local fs_d="/${fs_loc}/${directory}"
for file in $(ls "${fs_d}"); do
[ -d "${fs_d}/${file}" ] && continue
[ -e "${root_d}/${file}" ] && continue
ln -s "/${fsloc_d}/${file}" \
"${directory}/${file}" 2> /dev/null
done
done
done
mkdir initramfs proc tmp sys run 2>/dev/null
chmod 1777 tmp
# have handy /mnt/cdrom (CDROOT_PATH) as well
_new_cdroot="${NEW_ROOT}${CDROOT_PATH}"
[ ! -d "${_new_cdroot}" ] && mkdir -p "${_new_cdroot}"
mount --bind "${CDROOT_PATH}" "${_new_cdroot}"
}
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 's/(,|^)(no)?auto(,|$)/,/g'
}
# Read /etc/initramfs.mounts from ${NEW_ROOT} and mount the
# listed filesystem mountpoints. For instance, /usr, which is
# required by udev & systemd.
ensure_initramfs_mounts() {
local fslist=
if [ -f "${NEW_ROOT}/etc/initramfs.mounts" ]; then
fslist="$(get_mounts_list)"
else
fslist="/usr"
fi
local dev= fstype= opts= mnt= cmd=
for fs in ${fslist}; do
mnt="${NEW_ROOT}${fs}"
if mountpoint -q "${mnt}"; then
good_msg "${fs} already mounted, skipping..."
continue
fi
dev=$(get_mount_device "${fs}")
[ -z "${dev}" ] && continue
# Resolve it like util-linux mount does
[ -L "${dev}" ] && dev=$(readlink "${dev}")
# In this case, it's probably part of the filesystem
# and not a mountpoint
[ -z "${dev}" ] && continue
fstype=$(get_mount_fstype "${fs}")
if get_mount_options "${fs}" | fgrep -q bind; then
opts="bind"
dev="${NEW_ROOT}${dev}"
else
# ro must be trailing, and the options will always
# contain at least 'defaults'
opts="$(get_mount_options ${fs} | strip_mount_options)"
opts="${opts},ro"
fi
cmd="mount -t ${fstype} -o ${opts} ${dev} ${mnt}"
good_msg "Mounting ${dev} as ${fs}: ${cmd}"
if ! ${cmd}; then
bad_msg "Unable to mount ${dev} for ${fs}"
fi
done
}
fstype_init() {
local fstype="${1}"
if [ "${fstype}" = "btrfs" ]; then
# start BTRFS volume detection, if available
[ -x /sbin/btrfs ] && /sbin/btrfs device scan
elif [ -z "${fstype}" ]; then
warn_msg "Unable to detect the filesystem type (empty variable)"
fi
}
rootdev_init() {
good_msg "Initializing root device..."
while true
do
local got_good_root=
while [ "${got_good_root}" != '1' ]
do
case "${REAL_ROOT}" in
LABEL=*|UUID=*)
local root_dev=$(find_real_device "${REAL_ROOT}")
if [ -n "${root_dev}" ]; then
REAL_ROOT="${root_dev}"
good_msg "Detected root: ${REAL_ROOT}"
else
bad_msg "Unable to resolve root: ${REAL_ROOT}"
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
continue
fi
;;
ZFS*)
if [ "${USE_ZFS}" = '0' ]; then
prompt_user "REAL_ROOT" "root block device"
continue
fi
ROOT_DEV="${REAL_ROOT#*=}"
if [ "${ROOT_DEV}" != 'ZFS' ]
then
if [ "$(zfs get type -o value -H ${ROOT_DEV})" = 'filesystem' ]
then
got_good_root=1;
REAL_ROOT=${ROOT_DEV}
ROOTFSTYPE=zfs
else
bad_msg "${ROOT_DEV} is not a filesystem"
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
continue
fi
else
BOOTFS=$(/sbin/zpool list -H -o bootfs)
if [ "${BOOTFS}" != '-' ]
then
for i in ${BOOTFS}
do
zfs get type ${i} > /dev/null
retval=$?
if [ ${retval} -eq 0 ]; then
got_good_root=1
REAL_ROOT=${i}
ROOTFSTYPE=zfs
break
fi
done
else
got_good_root=0
fi
fi
if [ ${got_good_root} -ne 1 ]; then
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
fi
continue
;;
esac
if [ "${REAL_ROOT}" = '' ]
then
# No REAL_ROOT determined/specified. Prompt user for root block device.
prompt_user "REAL_ROOT" "root block device"
got_good_root=0
# Check for a block device or NFS
elif [ -b "${REAL_ROOT}" ] || is_nfs
then
got_good_root=1
else
bad_msg "Block device ${REAL_ROOT} is not a valid root device..."
REAL_ROOT=""
got_good_root=0
fi
done
if [ "${got_good_root}" = "1" ] && is_livecd && ! is_nfs; then
# CD already mounted; no further checks necessary
break
fi
if [ "${LOOPTYPE}" = "sgimips" ]; then
# sgimips mounts the livecd root partition directly
# there is no isofs filesystem to worry about
break
fi
local fstype=$(get_device_fstype "${REAL_ROOT}")
good_msg "Initializing ${REAL_ROOT} if needed, detected fstype: ${fstype}"
fstype_init "${fstype}"
good_msg "Mounting ${REAL_ROOT} as root..."
if [ "${ROOTFSTYPE}" = 'zfs' ]
then
if [ "$(zfs get -H -o value mountpoint ${REAL_ROOT})" = 'legacy' ]
then
MOUNT_STATE=rw
else
MOUNT_STATE=rw,zfsutil
fi
else
MOUNT_STATE=ro
fi
# Try to mount the device as ${NEW_ROOT}
if is_nfs; then
findnfsmount
else
# mount ro so fsck doesn't barf later
if [ "${REAL_ROOTFLAGS}" = '' ]; then
good_msg "Using mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE}"
mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE} ${REAL_ROOT} ${NEW_ROOT}
else
good_msg "Using mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE},${REAL_ROOTFLAGS}"
mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE},${REAL_ROOTFLAGS} ${REAL_ROOT} ${NEW_ROOT}
fi
fi
# If mount is successful break out of the loop
# else not a good root and start over.
if [ "$?" = '0' ]
then
# now that the root filesystem is mounted, before
# checking the validity of ${NEW_ROOT} and ${REAL_INIT},
# ensure that ${NEW_ROOT}/etc/initramfs.mounts entries
# are mounted.
ensure_initramfs_mounts
# NFS does not need further checks here.
if is_nfs; then
break
fi
if [ ! -d "${NEW_ROOT}/dev" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain /dev"
_msg="${_msg}, init will likely fail..."
bad_msg "${_msg}"
fi
if [ ! -x "${NEW_ROOT}${REAL_INIT}" ]; then
_msg="The filesystem ${REAL_ROOT},"
_msg="${_msg} mounted at ${NEW_ROOT}"
_msg="${_msg} does not contain a valid"
_msg="${_msg} init=${REAL_INIT}"
bad_msg "${_msg}"
fi
break
else
bad_msg "Could not mount specified ROOT, try again"
got_good_root=0
REAL_ROOT=''
fi
done
}
# If devtmpfs is mounted, try move it to the new root
# If that fails, try to unmount all possible mounts of devtmpfs as
# stuff breaks otherwise
move_mounts_to_chroot() {
for fs in /run /dev /sys /proc; do
if grep -qs "$fs" /proc/mounts; then
local chroot_dir="${CHROOT}${fs}"
mkdir -p "${chroot_dir}"
if ! mount --move $fs "${chroot_dir}"
then
umount $fs || \
bad_msg "Failed to move and umount $fs!"
fi
fi
done
}