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

851 lines
27 KiB

#!/bin/sh
. /etc/initrd.defaults
. /etc/initrd.d/00-splash.sh
. /etc/initrd.d/00-common.sh
. /etc/initrd.d/00-fsdev.sh
. /etc/initrd.d/00-devmgr.sh
. /etc/initrd.d/00-zfs.sh
. /etc/initrd.d/00-modules.sh
. /etc/initrd.d/00-livecd.sh
real_root_init() {
if [ -z "${REAL_ROOT}" ] && [ "${FAKE_ROOT}" != "/dev/ram0" ]; then
REAL_ROOT="${FAKE_ROOT}"
fi
if [ -z "${REAL_INIT}" ] && [ "${FAKE_INIT}" != "/linuxrc" ]; then
REAL_INIT="${FAKE_INIT}"
fi
if [ -z "${REAL_ROOTFLAGS}" ]; then
REAL_ROOTFLAGS="${FAKE_ROOTFLAGS}"
fi
# let zfs code setup its parameters
zfs_real_root_init
}
bootstrap_key() {
# $1 = ROOT/SWAP
local KEYDEVS=$(device_list)
eval local keyloc='"${CRYPT_'${1}'_KEY}"'
media_find "key" "${keyloc}" "CRYPT_${1}_KEYDEV" "/mnt/key" ${KEYDEVS}
}
find_nfs() {
if [ -z "${IP}" ]; then
# IP is not set, return straight away
return 1
fi
if ! busybox udhcpc -n -T 15 -q; then
bad_msg "udhcpc returned error, skipping nfs setup..."
return 1
fi
local options=
[ -e /rootpath ] && NFSROOT=$(cat /rootpath)
if [ -z "${NFSROOT}" ]; then
# Obtain NFSIP
# TODO: this is bogus, because dmesg is a circular buffer...
# TODO: provide dmesg as symlink (see gen_initramfs.sh)
options=$(busybox dmesg | grep rootserver | sed -e "s/,/ /g")
local opt= optn=
for opt in ${options}; do
optn=$(echo $opt | sed -e "s/=/ /g" | cut -d " " -f 1)
if [ "${optn}" = "rootserver" ]; then
NFSIP=$(echo $opt | sed -e "s/=/ /g" | cut -d " " -f 2)
fi
done
# Obtain NFSPATH
# TODO: this is bogus, because dmesg is a circular buffer...
# TODO: provide dmesg as symlink (see gen_initramfs.sh)
options=$(busybox dmesg | grep rootpath | sed -e "s/,/ /g")
for opt in ${options}; do
optn=$(echo $opt | sed -e "s/=/ /g" | cut -d " " -f 1)
if [ "${optn}" = "rootpath" ]; then
NFSPATH=$(echo $opt | sed -e "s/=/ /g" | cut -d " " -f 2)
fi
done
# Setup NFSROOT
if [ -n "${NFSIP}" ] && [ -n "$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 set nfsroot=<...>"
return 1
fi
fi
# expecting a valid NFSROOT here, or the code should have returned
NFSOPTIONS=${NFSROOT#*,}
NFSROOT=${NFSROOT%%,*}
if [ "${NFSOPTIONS}" = "${NFSROOT}" ]; then
NFSOPTIONS="${DEFAULT_NFSOPTIONS}"
else
NFSOPTIONS="${DEFAULT_NFSOPTIONS},${NFSOPTIONS}"
fi
local path=
# override path if on livecd
if is_livecd; then
path="${CDROOT_PATH}"
good_msg "Attempting to mount NFS CD image on ${NFSROOT}."
else
path="${NEW_ROOT}"
good_msg "Attempting to mount NFS root on ${NFSROOT}."
fi
good_msg "NFS options: ${NFSOPTIONS}"
mount -t nfs -o ${NFSOPTIONS} "${NFSROOT}" "${path}"
if [ "${?}" = "0" ]; then
REAL_ROOT="/dev/nfs"
return 0
else
bad_msg "NFS Mounting failed. Is the path corrent ?"
return 1
fi
}
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
}
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
}
start_volumes() {
# 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
# TODO(lxnay): horrible sleep!
sleep 2
good_msg "Activating multipath devices"
/sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -a -v"
fi
if [ "${USE_DMRAID_NORMAL}" = "1" ]; then
if [ -e "/sbin/dmraid" ]; then
good_msg "Activating Device-Mapper RAID(s)"
/sbin/dmraid -ay ${DMRAID_OPTS}
else
bad_msg "/sbin/dmraid not found"
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
local cmds="#! /sbin/lvm"
# If there is a cahe, update it. Unbreak at least dmcrypt
[ -d /etc/lvm/cache ] && cmds="${cmds} \nvgscan"
# To activate volumegroups on all devices in the cache
cmds="${cmds} \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.
cmds+="${cmds} \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" "${cmds}" | /sbin/lvm /proc/self/fd/0
else
bad_msg "/sbin/lvm not found: skipping LVM activation"
fi
fi
# If zfs is enabled, this will initialize the volumes
zfs_start_volumes
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() {
# TODO(lxnay): what has been seen, cannot be unseen.
# TODO(lxnay): there is so much wrong in this function...
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
# TODO(lxnay): this sleep 6 thing is hurting my eyes sooooo much.
# 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
}
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
}
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
swsusp_resume
}
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
}
getdvhoff() {
echo $(( $(hexdump -n 4 -s $((316 + 12 * $2)) -e '"%i"' $1) * 512))
}
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_detect() {
local got_good_root=0
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}"
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
ZFS*)
# zfs_rootdev_init will tweak ${REAL_ROOT}
zfs_rootdev_init
if [ "${?}" = "0" ]; then
got_good_root=1
else
got_good_root=0
prompt_user "REAL_ROOT" "root block device"
continue
fi
;;
esac
if [ -z "${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 "${REAL_ROOT} is an invalid root device..."
REAL_ROOT=""
got_good_root=0
fi
done
return 0
}
_rootdev_mount() {
local mount_opts=ro
local mount_fstype="${ROOTFSTYPE}"
local fstype=$(get_device_fstype "${REAL_ROOT}")
if is_zfs_fstype "${fstype}"; then
mount_fstype=zfs
mount_opts=$(zfs_get_real_root_mount_flags)
fi
good_msg "Detected fstype: ${fstype}"
good_msg "Using mount fstype: ${mount_fstype}"
fstype_init "${fstype}"
local mopts="${mount_opts}"
[ -n "${REAL_ROOTFLAGS}" ] && \
mopts="${mopts},${REAL_ROOTFLAGS}"
good_msg "Using mount opts: -o ${mopts}"
mount -t "${mount_fstype}" -o "${mopts}" \
"${REAL_ROOT}" "${NEW_ROOT}" || return 1
return 0
}
rootdev_init() {
good_msg "Initializing root device..."
while true; do
if ! _rootdev_detect; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
if 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
good_msg "Mounting ${REAL_ROOT} as root..."
# Try to mount the device as ${NEW_ROOT}
local out=1
if is_nfs; then
find_nfs && out=0
else
_rootdev_mount && out=0
fi
if [ "${out}" != "0" ]; then
bad_msg "Could not mount specified ROOT, try again"
prompt_user "REAL_ROOT" "root block device"
continue
fi
# 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.
is_nfs && break
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}"
prompt_user "REAL_ROOT" "root block device"
continue
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}"
prompt_user "REAL_ROOT" "root block device"
continue
fi
break
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
}