|
|
|
#!/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
|
|
|
|
}
|