aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'defaults/initrd.scripts')
-rw-r--r--defaults/initrd.scripts2027
1 files changed, 1441 insertions, 586 deletions
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index bc19fff3..506f8c6c 100644
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -29,49 +29,117 @@ modules_load() {
modules_scan() {
local MODS
local loaded
+ local x
+ local smart_loading=yes
+ local _root_dev
+ local root_dev_found="Root block device found, skipping loading of module group \"${1}\" ..."
MODS=$(cat /etc/modules/${1} 2>/dev/null)
- [ -n "${MODS}" ] && [ -z "${QUIET}" ] && \
- printf "%b" "${BOLD} ::${NORMAL} Loading from ${1}: "
+ if [ -z "${MODS}" ]
+ then
+ log_msg "/etc/modules/${1} is empty; Nothing to load for '${1}' ..."
+ return
+ fi
+
+ if [ -z "${MODULES_SCAN_WARNING_SHOWN}" ]
+ then
+ local note_msg="NOTE: Due to how genkernel auto-detects your"
+ note_msg="${note_msg} hardware you will now see a lot of failed modprobe" \
+ note_msg="${note_msg} attempts which you can ignore:"
+
+ log_msg "${note_msg}"
+
+ MODULES_SCAN_WARNING_SHOWN=yes
+ fi
+
+ if [ "${GK_HW_LOAD_ALL_MODULES}" = '1' ]
+ then
+ smart_loading=no
+ elif [ "${1}" = "virtio" ] || [ "${1}" = "hyperv" ]
+ then
+ # Virtio/HyperV modules group is special -- it's about
+ # hypervisor support in general, not root block device
+ smart_loading=no
+ elif [ "${1}" = "net" ]
+ then
+ # We already load network modules only when we need
+ # network so don't stop loading network modules when
+ # $REAL_ROOT is already present or we will probably
+ # end up without network we wanted ...
+ smart_loading=no
+ elif [ "${1}" = "fs" ]
+ then
+ # We don't know if kernel supports root filesystem so
+ # better load all filesystems ...
+ smart_loading=no
+ elif [ "${USE_MDADM}" = '1' ] \
+ || [ "${USE_LVM_NORMAL}" = '1' ] \
+ || [ "${USE_CRYPTSETUP}" = '1' ] \
+ || [ "${USE_ZFS}" = '1' ] \
+ || [ "${USE_DMRAID_NORMAL}" = '1' ]
+ then
+ # All of this will require the call of another program before
+ # root becomes available so checking for root after each module
+ # was loaded will only waste time.
+ smart_loading=no
+ fi
+
+ log_msg "Loading modules of module group '${1}' (smart loading: ${smart_loading}) ..."
+ is_quiet \
+ || printf "%b" "${BOLD} ::${NORMAL} Loading from ${1}: "
for x in ${MODS}
do
MLOAD=$(echo ${MLIST} | sed -e "s/.*${x}.*/${x}/")
if [ "${MLOAD}" = "${x}" ] # Only module to no-load
then
- [ -z "${QUIET}" ] && \
- printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x} ..."
+ is_quiet \
+ || printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x} ..."
elif [ "${MLOAD}" = "${MLIST}" ]
then
- if [ "${ROOTFSTYPE}" != 'auto' ] && [ -b "${REAL_ROOT}" ]
+ if [ "${smart_loading}" = "yes" ]
then
- echo "Root block device found, continuing ..."
- break
+ if [ ! -f "${GK_ROOT_DEV_DETECTED_STATEFILE}" ]
+ then
+ _root_dev=$(findfs "${REAL_ROOT}" 2>/dev/null)
+ if [ $? -eq 0 ] && [ -n "${_root_dev}" ] && [ -b "${_root_dev}" ]
+ then
+ echo "${_root_dev}" > "${GK_ROOT_DEV_DETECTED_STATEFILE}"
+ fi
+ fi
+
+ if [ -f "${GK_ROOT_DEV_DETECTED_STATEFILE}" ]
+ then
+ log_msg "${root_dev_found}"
+ printf "%b" "${root_dev_found}"
+ break
+ fi
fi
- if [ -n "${DEBUG}" ]
+ if is_debug
then
printf "%b" "${BOLD} ::${NORMAL} "
printf "%b" "Scanning for ${x} ..."
fi
- modprobe ${x} >/dev/null 2>&1
+ run modprobe ${x} >/dev/null 2>&1
loaded=${?}
- [ -n "${DEBUG}" -a "${loaded}" = "0" ] && \
+ is_debug && [ "${loaded}" = "0" ] && \
echo "loaded"
- [ -n "${DEBUG}" -a "${loaded}" != "0" ] && \
+ is_debug && [ "${loaded}" != "0" ] && \
echo "not loaded"
- [ -z "${DEBUG}" -a "${loaded}" = "0" ] && \
- [ -z "${QUIET}" ] && \
+ ! is_debug && [ "${loaded}" = "0" ] && \
+ ! is_quiet && \
printf "%b" "${x} "
else
- [ -z "${QUIET}" ] && \
- printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x} ..."
+ is_quiet \
+ || printf "%b\n" "${BOLD} ::${NORMAL} Skipping ${x} ..."
fi
done
- [ -n "${MODS}" ] && [ -z "${QUIET}" ] && echo
+
+ is_quiet || echo
}
uppercase() {
@@ -79,7 +147,6 @@ uppercase() {
echo $1 | tr 'a-z' 'A-Z'
}
-
findmediamount() {
# $1 = mount dir name / media name
# $2 = recognition file
@@ -111,33 +178,18 @@ findmediamount() {
# Check for a block device to mount
if [ -b "${x}" ]
then
- skip=0
- bsn=$(basename "${x}")
- #
- # If disk and it has at least one partition, skip.
- # We use /sys/block/${bsn}/${bsn}[0-9]* to make sure that we
- # don't skip device mapper devices. Even the craziest scenario
- # deserves a fair chance.
- #
- for part in $(ls /sys/block/${bsn}/${bsn}*[0-9]* 2>/dev/null)
- do
- skip=1
- break;
- done
- if [ ${skip} -eq 1 ]
- then
- continue
- fi
good_msg "Attempting to mount media: ${x}" ${CRYPT_SILENT}
- mount -t ${CDROOT_TYPE} ${x} ${mntcddir} >/dev/null 2>&1
+ CDROOT_TYPE=$(determine_fs "${x}" "${CDROOT_TYPE}")
+
+ run mount -t ${CDROOT_TYPE} ${x} ${mntcddir} >/dev/null 2>&1
if [ $? -eq 0 ]
then
if [ -n "${ISOBOOT}" ]
then
if [ -f "${mntcddir}/${ISOBOOT}" ]
then
- mount -o loop "${mntcddir}/${ISOBOOT}" "${mntdir}"
+ run mount -o loop "${mntcddir}/${ISOBOOT}" "${mntdir}"
if [ $? -eq 0 ]
then
good_msg "iso mounted on ${mntdir}"
@@ -153,7 +205,7 @@ findmediamount() {
good_msg "Media found on ${x}" ${CRYPT_SILENT}
break
else
- umount ${mntcddir}
+ run umount ${mntcddir}
fi
fi
fi
@@ -165,6 +217,31 @@ findmediamount() {
[ -n "${result}" ] || bad_msg "Media not found" ${CRYPT_SILENT}
}
+determine_fs() {
+ local _dev="${1}"
+ local _orig="${2:-auto}"
+ local _fs line
+
+ _fs=$(udevadm info --query=env --name="$_dev" 2>/dev/null | \
+ while read line || [ -n "${line}" ]
+ do
+ if str_starts ${line} "ID_FS_TYPE="
+ then
+ echo ${line#ID_FS_TYPE=}
+ break
+ fi
+ done
+ )
+ _fs=${_fs:-auto}
+
+ if [ "${_fs}" = "auto" ]
+ then
+ _fs="${_orig}"
+ fi
+
+ echo "${_fs}"
+}
+
devicelist() {
# Locate the cdrom device with our media on it.
# CDROM DEVICES
@@ -203,37 +280,38 @@ bootstrapFS() {
aufs_branch=${aufs_memory}/aufs-rw-branch/${aufs_dev_uid}
fi
- mkdir -p ${aufs_memory} ${aufs_union} ${aufs_dev_mnt}
+ run mkdir -p ${aufs_memory} ${aufs_union} ${aufs_dev_mnt}
else
# Legacy SquashFS implementation
good_msg "Making tmpfs for ${NEW_ROOT}"
- mount -n -t tmpfs tmpfs ${NEW_ROOT}
+ run mount -n -t tmpfs tmpfs ${NEW_ROOT}
fi
# Setup the filesystem nodes and directories
- for i in ${CDROOT_PATH} /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do
- mkdir -p "${NEW_ROOT}${i}"
- chmod 755 "${NEW_ROOT}${i}"
+ for i in ${CDROOT_PATH} /mnt/header /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do
+ run mkdir -p "${NEW_ROOT}${i}"
+ run chmod 755 "${NEW_ROOT}${i}"
done
- [ ! -d "${CDROOT_PATH}" ] && mkdir -p "${CDROOT_PATH}"
- [ ! -e "${NEW_ROOT}/dev/null" ] && mknod -m 666 "${NEW_ROOT}"/dev/null c 1 3
- [ ! -e "${NEW_ROOT}/dev/zero" ] && mknod -m 666 "${NEW_ROOT}"/dev/zero c 1 5
- [ ! -e "${NEW_ROOT}/dev/console" ] && mknod -m 600 "${NEW_ROOT}"/dev/console c 5 1
- [ ! -e "${NEW_ROOT}/dev/ttyS0" ] && mknod -m 660 "${NEW_ROOT}"/dev/ttyS0 c 4 64
+ [ ! -d "${CDROOT_PATH}" ] && run mkdir -p "${CDROOT_PATH}"
+ [ ! -e "${NEW_ROOT}/dev/null" ] && run mknod -m 666 "${NEW_ROOT}"/dev/null c 1 3
+ [ ! -e "${NEW_ROOT}/dev/zero" ] && run mknod -m 666 "${NEW_ROOT}"/dev/zero c 1 5
+ [ ! -e "${NEW_ROOT}/dev/console" ] && run mknod -m 600 "${NEW_ROOT}"/dev/console c 5 1
+ [ ! -e "${NEW_ROOT}/dev/tty0" ] && run mknod -m 620 "${NEW_ROOT}"/dev/tty0 c 4 0
+ [ ! -e "${NEW_ROOT}/dev/ttyS0" ] && run mknod -m 660 "${NEW_ROOT}"/dev/ttyS0 c 4 64
# For SGI LiveCDs
if [ "${LOOPTYPE}" = "sgimips" ]
then
- [ ! -e "${NEW_ROOT}/dev/sr0" ] && mknod "${NEW_ROOT}/dev/sr0" b 11 0
- [ ! -e "${NEW_ROOT}/dev/loop0" ] && mknod "${NEW_ROOT}/dev/loop0" b 7 0
+ [ ! -e "${NEW_ROOT}/dev/sr0" ] && run mknod "${NEW_ROOT}/dev/sr0" b 11 0
+ [ ! -e "${NEW_ROOT}/dev/loop0" ] && run mknod "${NEW_ROOT}/dev/loop0" b 7 0
fi
# Required for splash to work. Not an issue with the initrd as this
# device isn't created there and is not needed.
for minor in 0 1
do
- [ ! -e "${NEW_ROOT}/dev/${minor}" ] && mknod -m 600 "${NEW_ROOT}/dev/tty${minor}" c 4 ${minor}
+ [ ! -e "${NEW_ROOT}/dev/${minor}" ] && run mknod -m 600 "${NEW_ROOT}/dev/tty${minor}" c 4 ${minor}
done
}
@@ -251,24 +329,58 @@ bootstrapCD() {
if [ "${VERIFY}" = '1' ]
then
cd "${CDROOT_PATH}"
- if [ -f isoroot_checksums ]
+ checkfile=""
+ checker=""
+ if [ -r "isoroot_checksums" ] && [ -z "${checkfile}" ]
+ then
+ checkfile="isoroot_checksums"
+ checker="sha512sum"
+ fi
+ if [ -r "isoroot_b2sums" ]
then
- good_msg "Verifying checksums, this may take some time ..."
- if ! busybox sha512sum -c isoroot_checksums
+ if [ -x "$(command -v b2sum 2>&1)" ]
+ then
+ checkfile="isoroot_b2sums"
+ checker="b2sum"
+ else
+ bad_msg "Unable to verify isoroot_b2sums due to missing b2sums"
+ bad_msg "Please use 'genkernel --b2sums' to generate initramfs"
+ if [ -z "${checkfile}" ]
+ then
+ bad_msg "Press any key to skip ..."
+ read -n1 -s
+ return
+ fi
+ fi
+ fi
+
+ if [ -n "${checkfile}" ]
+ then
+ good_msg "Verifying ${checkfile}, this may take some time ..."
+ if ! run "${checker}" -c "${checkfile}"
then
bad_msg "Some checksums failed, press any key to poweroff ..."
read -n1 -s
- busybox poweroff -f
+ poweroff -f
else
- good_msg "Checksums all valid, continuing boot ..."
+ good_msg "${checkfile} all valid, continuing boot ..."
fi
cd "${OLDPWD}"
else
- bad_msg "Verify enabled but no checksums file exists, skipping"
+ bad_msg "Verify requested but no checksums file exists, press any key to skip ..."
+ read -n1 -s
fi
fi
}
+bootstrapHeader() {
+ # $1 = ROOT/SWAP
+ local HEADERDEVS=$(devicelist)
+ eval local headerloc='"${CRYPT_'${1}'_HEADER}"'
+
+ findmediamount "header" "${headerloc}" "CRYPT_${1}_HEADERDEV" "/mnt/header" ${HEADERDEVS}
+}
+
bootstrapKey() {
# $1 = ROOT/SWAP
local KEYDEVS=$(devicelist)
@@ -294,23 +406,25 @@ cache_cd_contents() {
# 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}
+ run mkdir -p "$(dirname ${NEW_ROOT}/mnt/${LOOP})"
+ run 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
+ warn_msg "Failed to cache the loop file! Lack of RAM?" 0
+ run rm -rf ${NEW_ROOT}/mnt/${LOOP} 2>/dev/null
+ run rm -rf ${NEW_ROOT}/mnt/livecd.* 2>/dev/null
+ run rm -rf ${NEW_ROOT}/mnt/image.* 2>/dev/null
+ run 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
- [ $? -eq 0 ] || bad_msg "Failed to mount /sys!"
+ if ! run mount -t sysfs sysfs /sys -o noexec,nosuid,nodev >/dev/null 2>&1
+ then
+ bad_msg "Failed to mount /sys!"
+ fi
}
# Check support for both aufs and overlayfs
@@ -345,8 +459,8 @@ is_union_modules() {
else
warn_msg "Adding all modules in ${mod_dir}"
- mkdir /mnt/modules
- mount "${mod_dir}" /mnt/modules
+ run mkdir /mnt/modules
+ run mount "${mod_dir}" /mnt/modules
union_insert_modules /mnt/modules
fi
fi
@@ -361,12 +475,18 @@ is_union_modules() {
#
aufs_insert_dir() {
# Always mount it over the precedent (add:1:)
- if mount -n -o "remount,add:1:$2=rr" aufs "$1"
+ if run mount -n -o "remount,add:1:$2=rr" aufs "$1"
then
good_msg "Addition of $2 to $1 successful"
fi
}
+udevsettle() {
+ local timeout=${1-${GK_UDEV_TIMEOUT}}
+
+ run udevadm settle --timeout=${timeout}
+}
+
# Insert all modules found in $1, usually $CDROOT_PATH
# added to allow users to add their own apps.
union_insert_modules() {
@@ -409,18 +529,18 @@ union_mod() {
then
if [ ! -d "${aufs_union}"/mnt/"${mod}" ]
then
- mkdir -p "${aufs_union}"/mnt/modules/"${mod}" || return
+ run mkdir -p "${aufs_union}"/mnt/modules/"${mod}" || return
fi
- mount -o loop,ro "$2" "${aufs_union}"/mnt/modules/"${mod}"
+ run mount -o loop,ro "$2" "${aufs_union}"/mnt/modules/"${mod}"
aufs_insert_dir "${aufs_union}" "${aufs_union}"/mnt/modules/"${mod}"
else
if [ ! -d "${mod_dir}/.${mod}" ]
then
- mkdir -p "${mod_dir}/.${mod}" || return
+ run mkdir -p "${mod_dir}/.${mod}" || return
fi
- mount -o loop,ro "$2" "${mod_dir}/.${mod}"
+ run mount -o loop,ro "$2" "${mod_dir}/.${mod}"
fi
}
@@ -450,7 +570,7 @@ conf_rc_no_umounts() {
if [ -n "${cmd}" ]
then
- sed -i "${cmd%;}" ${conf}
+ run sed -i "${cmd%;}" ${conf}
test_success "Unable to edit /etc/conf.d/localmount"
fi
fi
@@ -462,6 +582,17 @@ conf_rc_no_umounts() {
fi
}
+is_debug() {
+ local is_debug=1
+
+ if [ -f "${GK_DEBUGMODE_STATEFILE}" ]
+ then
+ is_debug=0
+ fi
+
+ return ${is_debug}
+}
+
# is_int "${A}" ["${B}"..]
# NOTE we consider a leading 0 false as it would be interpreted as octal
is_int() {
@@ -475,6 +606,55 @@ is_int() {
done
}
+is_log_enabled() {
+ if [ -z "${GK_INIT_LOG}" ]
+ then
+ return 1
+ elif [ -f "${GK_INIT_LOG_DISABLED}" ]
+ then
+ return 1
+ fi
+
+ return 0
+}
+
+is_quiet() {
+ is_true "${QUIET}" && return 0
+
+ return 1
+}
+
+is_true() {
+ case "${1}" in
+ 1)
+ return 0
+ ;;
+ [Tt][Rr][Uu][Ee])
+ return 0
+ ;;
+ [Tt])
+ return 0
+ ;;
+ [Yy][Ee][Ss])
+ return 0
+ ;;
+ [Yy])
+ return 0
+ ;;
+ esac
+
+ return 1
+}
+
+is_userinteraction_allowed() {
+ if [ -f "${GK_USERINTERACTION_DISABLED_STATEFILE}" ]
+ then
+ return 1
+ fi
+
+ return 0
+}
+
# Function to create an ext2 fs on $aufs_dev, $aufs_dev_mnt mountpoint
create_changefs() {
local size
@@ -493,13 +673,13 @@ create_changefs() {
then
bad_msg "Please give a size of at least 16 Megabytes"
else
- if dd if=/dev/zero "of=${aufs_dev_mnt}${aufs_union_file}" bs=1 seek="${size}"M count=0 >/dev/null 2>&1
+ if run dd if=/dev/zero "of=${aufs_dev_mnt}${aufs_union_file}" bs=1 seek="${size}"M count=0 >/dev/null 2>&1
then
good_msg "Creation of ${aufs_union_file}, ${size}MB on ${aufs_dev successful}, formatting it ext2"
- mke2fs -F "${aufs_dev_mnt}${aufs_union_file}" >/dev/null 2>&1
+ run mke2fs -F "${aufs_dev_mnt}${aufs_union_file}" >/dev/null 2>&1
break
else
- rm "${aufs_dev_mnt}${aufs_union_file}"
+ run rm "${aufs_dev_mnt}${aufs_union_file}"
bad_msg "Unable to create ${aufs_union_file#*/} on ${aufs_dev} of ${size}MB"
bad_msg "Ensure your disk is not full or read-only"
@@ -507,7 +687,7 @@ create_changefs() {
if [ "${doabort}" = 'a' ]
then
bad_msg "Aborting creation of ${aufs_union_file}!"
- umount "${aufs_dev}" && rmdir "${aufs_dev_mnt}"
+ run umount "${aufs_dev}" && rmdir "${aufs_dev_mnt}"
return 1
fi
fi
@@ -551,7 +731,9 @@ setup_aufs() {
then
good_msg "Mounting ${aufs_dev} to ${aufs_memory} for aufs support"
- if ! mount -t auto "${aufs_dev}" "${aufs_dev_mnt}" >/dev/null 2>&1
+ local mounttype=$(determine_fs "${aufs_dev}" "auto")
+
+ if ! run mount -t ${mounttype} "${aufs_dev}" "${aufs_dev_mnt}" >/dev/null 2>&1
then
bad_msg "Mount of ${aufs_dev} failed, falling back to ramdisk based aufs"
unset aufs_dev
@@ -561,12 +743,12 @@ setup_aufs() {
# Check and attempt to create the AUFS union file
if [ ! -e ${aufs_dev_mnt}${aufs_union_file} ] && [ -n "${aufs_dev}" ]
then
- create_changefs && mount -t auto "${aufs_dev_mnt}${aufs_union_file}" "${aufs_memory}"
+ create_changefs && run mount -t auto "${aufs_dev_mnt}${aufs_union_file}" "${aufs_memory}"
elif [ -n "${aufs_dev}" ]
then
while :;
do
- if mount -t auto "${aufs_dev_mnt}${aufs_union_file}" "${aufs_memory}" >/dev/null 2>&1
+ if run mount -t auto "${aufs_dev_mnt}${aufs_union_file}" "${aufs_memory}" >/dev/null 2>&1
then
if [ "${aufs_union_file}" = "/casper-rw" ]
then
@@ -578,21 +760,21 @@ setup_aufs() {
if ! hash e2fsck >/dev/null 2>&1
then
- bad_msg "/sbin/e2fsck not found! aborting filesystem check"
+ bad_msg "e2fsck not found! aborting filesystem check"
bad_msg "Moving ${aufs_union_file#*/} to ${aufs_union_file#*/}.bad"
- mv "${aufs_dev_mnt}${aufs_union_file}" "${aufs_dev_mnt}${aufs_union_file}.bad"
+ run mv "${aufs_dev_mnt}${aufs_union_file}" "${aufs_dev_mnt}${aufs_union_file}.bad"
break
fi
- if e2fsck "${aufs_dev_mnt}${aufs_union_file}" >/dev/null 2>&1
+ if run e2fsck "${aufs_dev_mnt}${aufs_union_file}" >/dev/null 2>&1
then
good_msg "e2fsck ran successfully. Please verify data after bootup"
else
bad_msg "Your ${aufs_union_file#*/} image might be corrupted"
bad_msg "moving ${aufs_union_file#*/} to ${aufs_union_file#*/}.bad"
- mv "${aufs_dev_mnt}${aufs_union_file}" "${aufs_dev_mnt}${aufs_union_file}.bad"
+ run mv "${aufs_dev_mnt}${aufs_union_file}" "${aufs_dev_mnt}${aufs_union_file}.bad"
break
fi
fi
@@ -617,22 +799,22 @@ setup_aufs() {
bad_msg "Falling back to ramdisk based aufs"
good_msg "Mounting ramdisk to ${aufs_memory} for aufs support"
- mount -t tmpfs tmpfs "${aufs_memory}"
+ run mount -t tmpfs tmpfs "${aufs_memory}"
else
aufs_xino=${aufs_memory}/xino
- mkdir -p "${aufs_xino}"
- mount -t tmpfs aufs-xino "${aufs_xino}"
+ run mkdir -p "${aufs_xino}"
+ run mount -t tmpfs aufs-xino "${aufs_xino}"
fi
else
aufs_xino=${aufs_memory}
good_msg "Mounting ramdisk to ${aufs_memory} for aufs support"
- mount -t tmpfs tmpfs "${aufs_memory}"
+ run mount -t tmpfs tmpfs "${aufs_memory}"
fi
- mkdir -p "${aufs_branch}"
- if ! mount -t aufs -n -o "nowarn_perm,udba=none,xino=${aufs_xino}/.aufs.xino,br:${aufs_branch}=rw" aufs "${aufs_union}"
+ run mkdir -p "${aufs_branch}"
+ if ! run mount -t aufs -n -o "nowarn_perm,udba=none,xino=${aufs_xino}/.aufs.xino,br:${aufs_branch}=rw" aufs "${aufs_union}"
then
bad_msg "Can't setup union ${aufs_union} in directory!"
aufs=0
@@ -646,14 +828,14 @@ setup_overlayfs() {
local workdir="${overlay}/.work"
local static=/mnt/livecd
- rundebugshell overlayfs
+ run_debug_shell overlayfs
for i in "${overlay}" "${static}"
do
- [ ! -d "${i}" ] && mkdir -p "${i}"
+ [ ! -d "${i}" ] && run mkdir -p "${i}"
done
good_msg "Loading overlayfs"
- modprobe overlay >/dev/null 2>&1
+ run modprobe overlay >/dev/null 2>&1
checkfs overlay
mount -t squashfs -o loop,ro "${CDROOT_PATH}/${LOOPEXT}${LOOP}" "${static}"
@@ -661,7 +843,7 @@ setup_overlayfs() {
mkdir "${upperdir}" "${workdir}"
is_union_modules overlayfs
- mount -t overlay overlay -o lowerdir="${static}${mod_path}",upperdir="${upperdir}",workdir="${workdir}" "${NEW_ROOT}"
+ run mount -t overlay overlay -o lowerdir="${static}${mod_path}",upperdir="${upperdir}",workdir="${workdir}" "${NEW_ROOT}"
[ ! -d "${NEW_ROOT}${overlay}" ] && mkdir -p "${NEW_ROOT}${overlay}"
[ ! -d "${NEW_ROOT}${static}" ] && mkdir -p "${NEW_ROOT}${static}"
@@ -670,7 +852,14 @@ setup_overlayfs() {
for i in "${overlay}" "${static}"
do
- mount --bind "${i}" "${NEW_ROOT}${i}"
+ run mount --bind "${i}" "${NEW_ROOT}${i}"
+ done
+
+ # Setup the filesystem nodes and directories
+ # Copied from non-overlayfs logic earlier in this script
+ for i in ${CDROOT_PATH} /mnt/header /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do
+ run mkdir -p "${NEW_ROOT}${i}"
+ run chmod 755 "${NEW_ROOT}${i}"
done
# Did we populate the overlayfs modules path locations variable?
@@ -678,7 +867,7 @@ setup_overlayfs() {
then
for i in ${mods}
do
- mount --bind "${overlay}/.${i}" "${NEW_ROOT}/${overlay}/.${i}"
+ run mount --bind "${overlay}/.${i}" "${NEW_ROOT}/${overlay}/.${i}"
done
fi
}
@@ -736,7 +925,7 @@ findnfsmount() {
if [ "${CDROOT}" != '0' ]
then
good_msg "Attempting to mount NFS CD image on ${NFSROOT} with options ${NFSOPTIONS}"
- mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${CDROOT_PATH}
+ run mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${CDROOT_PATH}
if [ $? -eq 0 ]
then
REAL_ROOT="/dev/nfs"
@@ -746,7 +935,7 @@ findnfsmount() {
fi
else
good_msg "Attempting to mount NFS root on ${NFSROOT} with options ${NFSOPTIONS}"
- mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${NEW_ROOT}
+ run mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${NEW_ROOT}
if [ $? -eq 0 ]
then
REAL_ROOT="/dev/nfs"
@@ -765,31 +954,39 @@ findnfsmount() {
}
find_real_device() {
- local DEVICE="${1}"
- case "${DEVICE}" in
- UUID\=*|LABEL\=*|PARTUUID\=*)
- local REAL_DEVICE=""
+ local device="${1}"
+ local real_device=
+ local candidate=
+ case "${device}" in
+ UUID\=*|LABEL\=*|PARTLABEL=*|PARTUUID\=*)
local retval=1
if [ ${retval} -ne 0 ]
then
- REAL_DEVICE=$(findfs "${DEVICE}" 2>/dev/null)
+ candidate=$(findfs "${device}" 2>/dev/null)
retval=$?
fi
if [ ${retval} -ne 0 ]
then
- REAL_DEVICE=$(blkid -o device -l -t "${DEVICE}" 2>/dev/null)
+ candidate=$(blkid -o device -l -t "${device}" 2>/dev/null)
retval=$?
fi
- if [ ${retval} -eq 0 ] && [ -n "${REAL_DEVICE}" ]
+ if [ ${retval} -eq 0 ] && [ -n "${candidate}" ]
then
- DEVICE="${REAL_DEVICE}"
+ real_device="${candidate}"
fi
;;
+ *)
+ candidate=$(readlink -f "${device}")
+ if [ -b "${candidate}" ]
+ then
+ real_device="${candidate}"
+ fi
esac
- printf "%s" "${DEVICE}"
+
+ printf "%s" "${real_device}"
}
check_loop() {
@@ -800,36 +997,104 @@ check_loop() {
bad_msg 'Please export LOOP with a valid location, or reboot and pass a proper loop=...'
bad_msg 'kernel command line!'
- run_shell
+ run_emergency_shell
fi
}
+run() {
+ local retval
+
+ if "$@"; then
+ retval=$?
+ log_msg "Executed: '$*'"
+ else
+ retval=$?
+ log_msg "Failed (${retval}): '$*'"
+ fi
+
+ return ${retval}
+}
+
+run_debug_shell() {
+ is_debug || return
+
+ good_msg 'Starting debug shell as requested by "debug" option.' 0
+ good_msg "Run '${BOLD}gksosreport${NORMAL}' to generate debug report" 0
+ good_msg "in case you want to file a bug report." 0
+ good_msg "Stopping by: ${1}" 0
+ run_shell
+}
+
+run_emergency_shell() {
+ if is_userinteraction_allowed
+ then
+ echo
+ gksosreport
+ good_msg 'You might want to save "/run/initramfs/gksosreport.txt" to a USB stick or /boot' 0
+ good_msg 'after mounting them and attach it to a bug report.' 0
+ fi
+
+ run_shell
+}
+
run_shell() {
+ splash 'verbose' >/dev/null &
+
+ if ! is_userinteraction_allowed
+ then
+ bad_msg "gk.userinteraction.disabled is set; Spawning a shell is disabled!"
+ return
+ fi
+
[ -x /bin/sh ] && SH=/bin/sh || SH=/bin/ash
+ run touch "${GK_SHELL_LOCKFILE}"
+
export PS1='rescueshell \w \# '
- if [ -n "${CONSOLE}" ] && [ -c "/dev/${CONSOLE}" ]
+ echo
+ GOOD=${BLUE} good_msg "${NORMAL}Welcome to ${BOLD}${GK_META_VERSION}${NORMAL} (${GK_META_BUILD_DATE}) ${BOLD}rescue shell${NORMAL}!" 0
+ GOOD=${BLUE} good_msg "${NORMAL}...running Linux kernel ${BOLD}${KV}${NORMAL}" 0
+ echo
+
+ # Avoid /dev/{console,tty0} due to "can't access tty; job control turned off" problem;
+ # cttyhack will handle this for us...
+ if [ -n "${CONSOLE}" ] \
+ && [ "${CONSOLE}" != "/dev/console" ] \
+ && [ "${CONSOLE}" != "/dev/tty0" ] \
+ && [ -c "${CONSOLE}" ]
then
- setsid ${SH} -c "exec sh --login </dev/${CONSOLE} >/dev/${CONSOLE} 2>&1"
+ log_msg "Opening rescue shell on ${CONSOLE} ..."
+ setsid ${SH} -c "exec sh --login 0<>${CONSOLE} 1<>${CONSOLE} 2<>${CONSOLE}"
elif command -v cttyhack 1>/dev/null 2>&1
then
+ log_msg "Opening rescue shell using cttyhack ..."
setsid cttyhack ${SH} --login
elif [ -c '/dev/tty1' ]
then
- setsid ${SH} -c 'exec sh --login </dev/tty1 >/dev/tty1 2>&1'
+ log_msg "Opening rescue shell on /dev/tty1 fallback ..."
+ setsid ${SH} -c "exec sh --login 0<>/dev/tty1 1<>/dev/tty1 2<>/dev/tty1"
else
+ log_msg "Opening rescue shell (last resort) ..."
${SH} --login
fi
+ # Leave function early when /dev/null does not exist anymore,
+ # i.e. after failed switch_root call
+ [ ! -e /dev/null ] && return
+
+ rm "${GK_SHELL_LOCKFILE}"
+
echo
- :> "${GK_SHELL_LOCKFILE}"
+ # We maybe have called exec and dettached from main script; We
+ # must restore control...
+ exec 0<>${CONSOLE} 1<>${CONSOLE} 2<>${CONSOLE}
}
fs_type_in_use() {
fs_type=$1
- cut -d ' ' -f 3 < /proc/mounts | fgrep -q "${fs_type}"
+ cut -d ' ' -f 3 < /proc/mounts | grep -Fq "${fs_type}"
}
mount_devfs() {
@@ -845,16 +1110,20 @@ mount_devfs() {
# 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 \
+ run 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"
+ run mkdir -m 0755 /dev/pts
+ run mount -t devpts -o gid=5,mode=0620 devpts /dev/pts || bad_msg "Failed to mount /dev/pts"
fi
+
+ run mkdir -m 1777 /dev/shm
+ run mount -t tmpfs -o mode=1777,nosuid,nodev,strictatime tmpfs /dev/shm \
+ || bad_msg "Failed to mount /dev/shm"
}
test_success() {
@@ -863,56 +1132,128 @@ test_success() {
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
+ error_string="${error_string:-Failed to run command}"
+ bad_msg "${error_string}; Failing back to the shell ..."
+ run_emergency_shell
fi
}
+trim() {
+ local var="$*"
+
+ var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
+ var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
+
+ printf "%s" "${var}"
+}
+
+log_msg() {
+ is_log_enabled || return
+
+ if [ ! -f "${GK_INIT_LOG}" ]
+ then
+ touch "${GK_INIT_LOG}" 2>/dev/null || return
+ fi
+
+ local log_prefix=
+ [ -n "${GK_INIT_LOG_PREFIX}" ] && log_prefix="${GK_INIT_LOG_PREFIX}: "
+
+ local msg=${1}
+
+ # Cannot use substitution because $msg could contain infinite color
+ # codes and substitution can't be greedy.
+ # Because Busybox's sed cannot deal with control characters, we
+ # have to get rid of all non-printable characters like "^[" first...
+ LANG=C echo "] ${log_prefix}${msg}" | sed \
+ -e "s,[^[:print:]],,g" \
+ -e 's,\(\\033\)\?\[[0-9;]\+m,,g' \
+ | ts '[ %Y-%m-%d %H:%M:%.S' >> "${GK_INIT_LOG}"
+}
# msg functions arguments
# $1 string
# $2 hide flag
good_msg() {
- [ -n "${QUIET}" ] && [ -z "${DEBUG}" ] && return 0
-
- msg_string=${1}
+ local msg_string=${1}
msg_string="${msg_string:-...}"
- [ "$2" != '1' ] && printf "%b\n" "${GOOD}>>${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
+
+ log_msg "[OK] ${msg_string}"
+
+ is_true "${2-${QUIET}}" || printf "%b\n" "${GOOD}>>${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}
good_msg_n() {
- [ -n "${QUIET}" ] && [ -z "${DEBUG}" ] && return 0
-
- msg_string=${1}
+ local msg_string=${1}
msg_string="${msg_string:-...}"
- [ "$2" != '1' ] && printf "%b" "${GOOD}>>${NORMAL}${BOLD} ${msg_string}"
+
+ log_msg "[OK] ${msg_string}"
+
+ is_true "${2-${QUIET}}" || printf "%b" "${GOOD}>>${NORMAL}${BOLD} ${msg_string}"
}
bad_msg() {
- msg_string=${1}
+ local msg_string=${1}
msg_string="${msg_string:-...}"
- if [ "$2" != '1' ]
- then
- splash 'verbose' >/dev/null &
- printf "%b\n" "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
- fi
+
+ log_msg "[!!] ${msg_string}"
+
+ splash 'verbose' >/dev/null &
+ printf "%b\n" "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}
warn_msg() {
- msg_string=${1}
+ local msg_string=${1}
+ msg_string="${msg_string:-...}"
+
+ log_msg "[**] ${msg_string}"
+
+ is_true "${2-${QUIET}}" || printf "%b\n" "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
+}
+
+warn_msg_n() {
+ local msg_string=${1}
msg_string="${msg_string:-...}"
- [ "$2" != '1' ] && printf "%b\n" "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
+
+ log_msg "[**] ${msg_string}"
+
+ is_true "${2-${QUIET}}" || printf "%b" "${WARN}**${NORMAL}${BOLD} ${msg_string}"
+}
+
+write_env_file() {
+ local env_file=${1}
+ shift
+
+ run touch "${env_file}"
+
+ local varname= varvalue=
+ for varname in $*
+ do
+ eval varvalue=\$${varname}
+ echo "${varname}='${varvalue}'" >> "${env_file}"
+ done
}
crypt_filter() {
+ local ask_pass=${2}
+ good_msg "Using the following decryption command: ${1}" ${CRYPT_SILENT}
+
if [ "${CRYPT_SILENT}" = '1' ]
then
- eval $1 >/dev/null 2>&1
+ eval run ${1}
+ elif [ "${PLYMOUTH}" = '1' ] && [ ${ask_pass} -eq 1 ]
+ then
+ local ply_cmd_file="$(mktemp -t 'ply_cmd.XXXXXX' 2>/dev/null)"
+ printf '#!/bin/sh\n%s\n' "${1}" > "${ply_cmd_file}"
+ run chmod 500 "${ply_cmd_file}"
+ plymouthRun ask-for-password --prompt "Enter LUKS passphrase" \
+ --number-of-tries=3 --command="${ply_cmd_file}"
+ res=$?
+ run rm "${ply_cmd_file}" >/dev/null 2>&1
+ return ${res}
else
splash 'verbose' >/dev/null &
- eval $1
+ eval run ${1}
res=$?
if [ ${res} -eq 0 ]
then
@@ -922,6 +1263,55 @@ crypt_filter() {
fi
}
+process_initramfs_mounts() {
+ local fslist=
+
+ if [ -f "${NEW_ROOT}/etc/initramfs.mounts" ]
+ then
+ fslist="$(get_mounts_list)"
+ else
+ fslist="/usr"
+ fi
+
+ local dev= fs= fstype= opts= mnt= cmd=
+ for fs in ${fslist}
+ do
+ mnt="${NEW_ROOT}${fs}"
+ if run 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=$(realpath "${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}" | grep -Fq 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 ! run ${cmd}
+ then
+ bad_msg "Unable to mount ${dev} for ${fs}"
+ fi
+ done
+}
+
prompt_user() {
# $1 = variable whose value is the path (examples: "REAL_ROOT",
# "LUKS_KEYDEV")
@@ -938,33 +1328,91 @@ prompt_user() {
fi
[ -n "${3}" ] && local explnt=" or : ${3}" || local explnt="."
+ splash 'verbose' >/dev/null &
bad_msg "Could not find the ${2} in ${oldvalue}${explnt}"
+
+ if [ -f "${GK_USERINTERACTION_DISABLED_STATEFILE}" ]
+ then
+ bad_msg "gk.userinteraction.disabled is set; No user interaction allowed!"
+
+ wait_sshd
+
+ if [ -f "${GK_SSHD_LOCKFILE}" ]
+ then
+ warn_msg "The lockfile at '${GK_SSHD_LOCKFILE}' exists." 0
+ warn_msg "The boot process will be paused until the lock is removed." 0
+ while true
+ do
+ if [ -f "${GK_SSHD_LOCKFILE}" ]
+ then
+ sleep 1
+ else
+ break
+ fi
+ done
+ fi
+
+ local timeout=${GK_PROMPT_TIMEOUT}
+ [ ${timeout} -eq 0 ] && timeout=10
+
+ warn_msg_n "System will automatically reboot in ${timeout} seconds ..." 0
+ while [ ${timeout} -gt 0 ]
+ do
+ let timeout=${timeout}-1
+ sleep 1
+ printf "."
+ done
+ echo
+
+ reboot -f
+ fi
+
bad_msg "Please specify another value or:"
bad_msg "- press Enter for the same"
bad_msg '- type "shell" for a shell'
bad_msg '- type "q" to skip ...'
printf "%s" "${2}(${oldvalue}) :: "
- read ${1}
- #if [ $? -gt 0 ]
- #then
- # # prompt timed out
- # printf "\n"
- #fi
+
+ if [ "${GK_PROMPT_TIMEOUT}" = '0' ]
+ then
+ read ${1}
+ else
+ local read_timeout_timestamp
+ let read_timeout_timestamp=$(date +%s)+${GK_PROMPT_TIMEOUT}
+
+ echo "# Could not find the ${2} in ${oldvalue}${explnt}" > "${GK_PROMPT_FILE}"
+ echo "# Please specify another value (file will be processed at $(date -d @${read_timeout_timestamp}):" >> "${GK_PROMPT_FILE}"
+ echo "${1}=${oldvalue}" >> "${GK_PROMPT_FILE}"
+ read -t ${GK_PROMPT_TIMEOUT} ${1}
+ if [ $? -gt 0 ]
+ then
+ # prompt timed out
+ printf "\n"
+
+ if [ -f "${GK_PROMPT_FILE}" ]
+ then
+ warn_msg "Timeout! Trying to read answer from '${GK_PROMPT_FILE}' ..." 0
+ . "${GK_PROMPT_FILE}" && run rm "${GK_PROMPT_FILE}"
+ fi
+ fi
+ fi
case $(eval echo '$'${1}) in
'q')
eval ${1}'='${oldvalue}
- warn_msg "Skipping step, this will likely cause a boot failure."
+ warn_msg "Skipping step, this will likely cause a boot failure." 0
;;
'shell')
eval ${1}'='${oldvalue}
- warn_msg "To leave and try again just press <Ctrl>+D"
- run_shell
+ warn_msg "To leave and try again just press <Ctrl>+D" 0
+ run_emergency_shell
;;
'')
eval ${1}'='${oldvalue}
;;
esac
+
+ splash 'quiet' >/dev/null &
}
cmdline_hwopts() {
@@ -1011,35 +1459,25 @@ cmdline_hwopts() {
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
+ local console=$(get_active_console)
+ if echo "${console}" | grep -qF 'ttyS'
+ then
+ warn_msg "Active console is ${console}; Skipping dokeymap ..."
+ return
+ fi
+
if [ ! -e /dev/vc/0 -a ! -e /dev/tty0 ]
then
DEVBIND=1
- mount -o bind ${NEW_ROOT}/dev /dev
+ run mount -o bind ${NEW_ROOT}/dev /dev
fi
- [ ! -e /dev/tty0 ] && ln -s /dev/tty1 /dev/tty0
[ -f /lib/keymaps/keymapList ] && chooseKeymap
- [ "${DEVBIND}" = '1' ] && umount /dev
+ [ "${DEVBIND}" = '1' ] && run umount /dev
fi
}
@@ -1055,66 +1493,62 @@ chooseKeymap() {
if [ -z "${keymap}" ]
then
splash 'verbose' >/dev/null &
- cat /lib/keymaps/keymapList
+ run 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 ;;
+ 3|bepo) keymap=bepo ;;
+ 4|bg) keymap=bg ;;
+ 5|br-a) keymap=br-a ;;
+ 6|br-l) keymap=br-l ;;
+ 7|by) keymap=by ;;
+ 8|cf) keymap=cf ;;
+ 9|colemak) keymap=colemak ;;
+ 10|croat) keymap=croat ;;
+ 11|cz) keymap=cz ;;
+ 12|de) keymap=de ;;
+ 13|dk) keymap=dk ;;
+ 14|dvorak) keymap=dvorak ;;
+ 15|es) keymap=es ;;
+ 16|et) keymap=et ;;
+ 17|fi) keymap=fi ;;
+ 18|fr) keymap=fr ;;
+ 19|gr) keymap=gr ;;
+ 20|hu) keymap=hu ;;
+ 21|il) keymap=il ;;
+ 22|is) keymap=is ;;
+ 23|it) keymap=it ;;
+ 24|jp) keymap=jp ;;
+ 25|la) keymap=la ;;
+ 26|lt) keymap=lt ;;
+ 27|mk) keymap=mk ;;
+ 28|nl) keymap=nl ;;
+ 29|no) keymap=no ;;
+ 30|pl) keymap=pl ;;
+ 31|pt) keymap=pt ;;
+ 32|ro) keymap=ro ;;
+ 33|ru) keymap=ru ;;
+ 34|se) keymap=se ;;
+ 35|sf|ch*) keymap=sf ;;
+ 36|sg) keymap=sg ;;
+ 37|sk-y) keymap=sk-y ;;
+ 38|sk-z) keymap=sk-z ;;
+ 39|slovene) keymap=slovene ;;
+ 40|trf) keymap=trf ;;
+ 41|ua) keymap=ua ;;
+ 42|uk) keymap=uk ;;
+ 43|us) keymap=us ;;
+ 44|wangbe) keymap=wangbe ;;
esac
fi
+
if [ -e /lib/keymaps/${keymap}.map ]
then
good_msg "Loading the '${keymap}' keymap ..."
- loadkmap < /lib/keymaps/${keymap}.map
-# xkeymap=${keymap}
-# echo ${keymap} | egrep -e "[0-9]+" >/dev/null 2>&1
-# if [ $? -eq 0 ]
-# then
-# xkeymap=$(tail -n 8 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | egrep -v 1)
-# fi
- mkdir -p /etc/sysconfig
-# echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard
+ run loadkmap < /lib/keymaps/${keymap}.map
+
+ run mkdir -p /etc/sysconfig
echo "XKEYBOARD=${keymap}" > /etc/sysconfig/keyboard
splash set_msg "Set keymap to '${keymap}'"
elif [ -z "${keymap}" ]
@@ -1135,20 +1569,70 @@ chooseKeymap() {
copyKeymap() {
if [ -e /etc/sysconfig/keyboard -a ${CDROOT} -eq 1 ]
then
- [ ! -d ${NEW_ROOT}/etc/sysconfig ] && mkdir -p ${NEW_ROOT}/etc/sysconfig
- cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard
+ [ ! -d ${NEW_ROOT}/etc/sysconfig ] && run mkdir -p ${NEW_ROOT}/etc/sysconfig
+ run cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard
fi
}
-# This helper function is to be called using call_func_timeout.
-# It enables us to wait a reasonable amount of time until /dev/zfs appears.
-waitForZFS() {
- while [ ! -c /dev/zfs ]
- do
- echo >/dev/null
- done
+splash() {
+ if [ "${FBSPLASH}" = '1' ]
+ then
+ return 0
+ elif [ "${PLYMOUTH}" = '1' ]
+ then
+ case "${1}" in
+ init)
+ plymouthInit
+ ;;
- exit 1
+ verbose)
+ plymouthRun --hide-splash
+ ;;
+
+ set_msg)
+ plymouthRun --update="${2}"
+ ;;
+
+ quiet)
+ plymouthRun --show-splash
+ ;;
+
+ hasroot)
+ plymouthRun --newroot="${2}"
+ ;;
+ esac
+ fi
+}
+
+plymouthRun() {
+ run plymouth --ping 2>/dev/null || return $?
+ run plymouth "${@}" 2>/dev/null
+}
+
+plymouthInit() {
+ good_msg "Starting Plymouth..."
+ run mkdir -p -m 0755 /run/plymouth || return 1
+
+ # Make sure that udev is done loading tty and drm
+ run udevadm trigger --action=add --attr-match=class=0x030000 >/dev/null 2>&1
+ run udevadm trigger --action=add --subsystem-match=graphics \
+ --subsystem-match=drm --subsystem-match=tty >/dev/null 2>&1
+ udevsettle
+
+ run plymouthd --mode=boot --attach-to-session \
+ --pid-file=/run/plymouth/pid
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Can't start plymouthd!"
+ PLYMOUTH=0
+ return 1
+ fi
+
+ plymouthRun --show-splash
+ if [ $? -eq 0 ]
+ then
+ good_msg "Plymouth initialized"
+ fi
}
start_volumes() {
@@ -1156,196 +1640,183 @@ start_volumes() {
# a symlink, which should hopefully fix bug #142775 and bug #147015
if [ -e /dev/device-mapper ] && [ ! -e /dev/mapper/control ]
then
- mkdir -p /dev/mapper
- ln -sf /dev/device-mapper /dev/mapper/control
- fi
-
- if [ "${USE_MDADM}" = '1' ]
- then
- if [ -x '/sbin/mdadm' ]
- then
- /sbin/mdadm --assemble --scan
- #Intel Matrix RAID (and possibly others) have a container layer above the actual volumes,
- #So we have to look for volumes that haven't been activated.
- mdadm -IRs
- else
- bad_msg "mdadm not found: skipping mdadm raid assembly!"
- fi
+ run mkdir -p /dev/mapper
+ run ln -sf /dev/device-mapper /dev/mapper/control
fi
if [ "${USE_MULTIPATH_NORMAL}" = '1' ]
then
- for multipath_path in /sbin/multipath /bin/multipath MISSING
- do
- [ -x "${multipath_path}" ] && break
- done
-
- for dmsetup_path in /sbin/dmsetup /bin/dmsetup MISSING
- do
- [ -x "${dmsetup_path}" ] && break
- done
-
- for kpartx_path in /sbin/kpartx /bin/kpartx MISSING
- do
- [ -x "${kpartx_path}" ] && break
- done
-
- fail=0
- [ "${multipath_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but multipath binary missing! Skipping multipath"
- [ "${dmsetup_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but dmsetup binary missing! Skipping multipath"
- [ "${kpartx_path}" = "MISSING" ] && fail=1 && bad_msg "domultipath called, but kpartx binary missing! Skipping multipath"
-
- if [ ${fail} -eq 0 ]
+ if ! hash multipath >/dev/null 2>&1
then
+ bad_msg "domultipath called, but multipath binary missing! Skipping multipath"
+ else
good_msg "Scanning for multipath devices"
- good_msg ":: Populating scsi_id info for libudev queries"
- mkdir -p /run/udev/data
- local ech
- for ech in /sys/block/*
- do
- local tgtfile=b$(cat ${ech}/dev)
- /lib/udev/scsi_id -g -x /dev/${ech##*/} |sed -e 's/^/E:/' >/run/udev/data/${tgtfile}
- done
+ local multipath_cmd="run multipath -v 0 2>&1"
+ is_log_enabled && multipath_cmd="${multipath_cmd} | tee -a '${GK_INIT_LOG}'"
- ${multipath_path} -v 0
- sleep 2
- good_msg "Activating multipath devices"
- ${dmsetup_path} ls --target multipath --exec "${kpartx_path} -a -v"
+ eval "${multipath_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Scanning for multipath devices failed!"
+ else
+ udevsettle
+ fi
fi
fi
if [ "${USE_DMRAID_NORMAL}" = '1' ]
then
- if [ -x '/sbin/dmraid' ]
+ if ! hash dmraid >/dev/null 2>&1
then
- good_msg "Activating Device-Mapper RAID(s)"
+ bad_msg "dodmraid invoked but 'dmraid' not found; Skipping dmraid activation ..."
+ else
+ good_msg "Activating Device-Mapper RAID(s) ..."
+ local dmraid_cmd="run dmraid -ay"
if [ -z "${DMRAID_OPTS}" ]
then
- /sbin/dmraid -ay
+ dmraid_cmd="${dmraid_cmd} 2>&1"
else
- /sbin/dmraid -ay ${DMRAID_OPTS}
+ dmraid_cmd="${dmraid_cmd} ${DMRAID_OPTS} 2>&1"
+ fi
+ is_log_enabled && dmraid_cmd="${dmraid_cmd} | tee -a '${GK_INIT_LOG}'"
+
+ eval "${dmraid_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Activation of Device-Mapper RAID(s) failed!"
+ else
+ udevsettle
fi
- [ -x '/sbin/kpartx' ] && /sbin/dmsetup ls --exec '/sbin/kpartx -a -s'
fi
fi
if [ "${USE_LVM_NORMAL}" = '1' ]
then
- for lvm_path in /sbin/lvm /bin/lvm MISSING
- do
- [ -x "${lvm_path}" ] && break
- done
-
- if [ "${lvm_path}" = "MISSING" ]
+ if ! hash lvm >/dev/null 2>&1
then
- bad_msg "dolvm invoked, but LVM binary not available! skipping LVM volume group activation!"
+ bad_msg "dolvm invoked but LVM binary not available; Skipping LVM volume group activation ..."
else
- for dev in ${RAID_DEVICES}
- do
- setup_md_device "${dev}"
- done
-
- # This is needed for LVM to accept the following logic
- lvm_commands="#! ${lvm_path}"
-
# If there is a cache, update it. Unbreak at least dmcrypt
- [ -d /etc/lvm/cache ] && lvm_commands="${lvm_commands} \nvgscan"
-
- # To activate volumegroups on all devices in the cache
- lvm_commands="${lvm_commands} \nvgchange -ay --sysinit"
-
- # To create symlinks so users can use real_root=/dev/vg/root
- # This needs to run after vgchange, using vgchange --mknodes is too
- # early.
- lvm_commands="${lvm_commands} \nvgmknodes --ignorelockingfailure"
+ if [ -d /etc/lvm/cache ]
+ then
+ good_msg "Scanning for volume groups ..."
- # And finally execute it all (/proc/... needed if lvm is compiled without readline)
- good_msg "Scanning for and activating Volume Groups"
- printf "%b\n" "${lvm_commands}" | ${lvm_path} /proc/self/fd/0
- fi
- fi
+ local lvm_cmd="run lvm vgscan 2>&1"
+ is_log_enabled && lvm_cmd="${lvm_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && lvm_cmd="${lvm_cmd} 1>/dev/null"
- if [ "${USE_BCACHE}" = '1' ]
- then
- if [ ! -e /sys/fs/bcache/register_quiet ]
- then
- warn_msg "'/sys/fs/bcache/register_quiet' does not exist. Missing kernel driver? Skipping dobcache ..."
- else
- local i=
- for i in $(awk '$4 !~ /^(name$|$)/ { print $4 }' /proc/partitions)
- do
- if [ -e "/dev/${i}" ]
+ eval "${lvm_cmd}"
+ if [ $? -ne 0 ]
then
- # Push all the block devices to register_quiet
- # If its bcache, it will bring it up, if not, it will simply ignore it.
- echo "/dev/${i}" >/sys/fs/bcache/register_quiet 2>/dev/null
+ bad_msg "Scanning for volume groups failed!"
else
- warn_msg "'/dev/${i}' should exist but is missing; Ignoring ..."
+ udevsettle
fi
- done
- fi
- fi
+ fi
- if [ "${USE_BTRFS}" = '1' ]
- then
- if [ -x '/sbin/btrfs' ]
- then
- /sbin/btrfs device scan
- else
- bad_msg "btrfs not found: skipping btrfs device scanning!"
+ good_msg "Activating volume groups ..."
+
+ # To activate volumegroups on all devices in the cache
+ local lvm_cmd="run lvm vgchange -ay --sysinit 2>&1"
+ is_log_enabled && lvm_cmd="${lvm_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && lvm_cmd="${lvm_cmd} 1>/dev/null"
+
+ eval "${lvm_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Activation of volume groups failed!"
+ fi
fi
fi
if [ "${USE_ZFS}" = '1' ]
then
# Avoid race involving asynchronous module loading
- if call_func_timeout waitForZFS 5
+ if [ ! -e /dev/zfs ]
then
bad_msg "Cannot import ZFS pool because /dev/zfs is missing"
elif [ -z "${ZFS_POOL}" ]
then
- good_msg "Importing ZFS pools"
+ good_msg "Importing ZFS pools ..."
- /sbin/zpool import -N -a ${ZPOOL_CACHE} ${ZPOOL_FORCE}
- if [ $? -eq 0 ]
+ local zfs_cmd="run /sbin/zpool import -N -a ${ZPOOL_CACHE} ${ZPOOL_FORCE} 2>&1"
+ is_log_enabled && zfs_cmd="${zfs_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && zfs_cmd="${zfs_cmd} 1>/dev/null"
+
+ eval "${zfs_cmd}"
+ if [ $? -ne 0 ]
then
- good_msg "Importing ZFS pools succeeded"
- else
- bad_msg "Imported ZFS pools failed"
+ bad_msg "Importing ZFS pools failed!"
fi
else
-
if [ "$(zpool list -H -o name ${ZFS_POOL} 2>&1)" = "${ZFS_POOL}" ]
then
good_msg "ZFS pool ${ZFS_POOL} already imported."
if [ -n "${CRYPT_ROOT}" -o -n "${CRYPT_SWAP}" ]
then
- good_msg "LUKS detected. Reimporting ${ZFS_POOL}"
- /sbin/zpool export -f "${ZFS_POOL}"
- /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} "${ZFS_POOL}"
+ good_msg "LUKS detected. Reimporting ${ZFS_POOL} ..."
+
+ local zfs_cmd="run /sbin/zpool export -f '${ZFS_POOL}' 2>&1"
+ is_log_enabled && zfs_cmd="${zfs_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && zfs_cmd="${zfs_cmd} 1>/dev/null"
+
+ eval "${zfs_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Exporting ZFS pools failed!"
+ else
+ udevsettle
+ fi
+
+ zfs_cmd="run /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} '${ZFS_POOL}' 2>&1"
+ is_log_enabled && zfs_cmd="${zfs_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && zfs_cmd="${zfs_cmd} 1>/dev/null"
+
+ eval "${zfs_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Re-importing ZFS pools failed!"
+ fi
fi
else
- good_msg "Importing ZFS pool ${ZFS_POOL}"
+ good_msg "Importing ZFS pool ${ZFS_POOL} ..."
- /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} "${ZFS_POOL}"
- if [ $? -eq 0 ]
+ local zfs_cmd="run /sbin/zpool import -N ${ZPOOL_CACHE} ${ZPOOL_FORCE} '${ZFS_POOL}' 2>&1"
+ is_log_enabled && zfs_cmd="${zfs_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && zfs_cmd="${zfs_cmd} 1>/dev/null"
+
+ eval "${zfs_cmd}"
+ if [ $? -ne 0 ]
then
- good_msg "Import of ${ZFS_POOL} succeeded"
- else
- bad_msg "Import of ${ZFS_POOL} failed"
+ bad_msg "Import of ${ZFS_POOL} failed!"
fi
fi
fi
fi
+
+ udevsettle
}
start_iscsi() {
+ local iscsi_cmd
+
if [ ! -n "${ISCSI_NOIBFT}" ]
then
- good_msg "Activating iSCSI via iBFT"
- iscsistart -b
+ good_msg "Activating iSCSI via iBFT ..."
+
+ iscsi_cmd="run iscsistart -b 2>&1"
+ is_log_enabled && iscsi_cmd="${iscsi_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && iscsi_cmd="${iscsi_cmd} 1>/dev/null"
+
+ eval "${iscsi_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Activation of iSCSI via iBFT failed!"
+ else
+ udevsettle
+ fi
fi
if [ -n "${ISCSI_INITIATORNAME}" ] && [ -n "${ISCSI_TARGET}" ] && [ -n "${ISCSI_ADDRESS}" ]
@@ -1389,7 +1860,17 @@ start_iscsi() {
ADDITIONAL="${ADDITIONAL} -d ${ISCSI_DEBUG}"
fi
- iscsistart -i "${ISCSI_INITIATORNAME}" -t "${ISCSI_TARGET}" -a "${ISCSI_ADDRESS}" ${ADDITIONAL}
+ iscsi_cmd="run iscsistart -i '${ISCSI_INITIATORNAME}' -t '${ISCSI_TARGET}' -a '${ISCSI_ADDRESS}' ${ADDITIONAL} 2>&1"
+ is_log_enabled && iscsi_cmd="${iscsi_cmd} | tee -a '${GK_INIT_LOG}'"
+ is_quiet && iscsi_cmd="${iscsi_cmd} 1>/dev/null"
+
+ eval "${iscsi_cmd}"
+ if [ $? -ne 0 ]
+ then
+ bad_msg "Activation of iSCSI via cmdline failed!"
+ else
+ udevsettle
+ fi
fi
}
@@ -1398,42 +1879,79 @@ start_iscsi() {
# It is either the root or a swap, other devices are supported in the scripts provided with sys-fs/cryptsetup
# $1 - root/swap
openLUKS() {
- if [ ! -x /sbin/cryptsetup ]
+ if ! hash cryptsetup >/dev/null 2>&1
then
bad_msg "cryptsetup program is missing. Was initramfs built without --luks parameter?"
exit 1
fi
- case $1 in
+ case ${1} in
root)
local TYPE=ROOT
;;
swap)
local TYPE=SWAP
;;
+ *)
+ bad_msg "OpenLUKS(): Unknown type '${1}' specified!"
+ exit 1
+ ;;
esac
- eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"' LUKS_NAME="$1" LUKS_KEY='"${CRYPT_'${TYPE}'_KEY}"'
- eval local LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"' LUKS_TRIM='"${CRYPT_'${TYPE}'_TRIM}"'
+ local LUKS_NAME="${1}"
+ eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"'
+ eval local LUKS_HEADER='"${CRYPT_'${TYPE}'_HEADER}"'
+ eval local LUKS_HEADERDEV='"${CRYPT_'${TYPE}'_HEADERDEV}"'
+ eval local LUKS_HEADERDEV_FSTYPE='"${CRYPT_'${TYPE}'_HEADERDEV_FSTYPE}"'
+ eval local LUKS_KEY='"${CRYPT_'${TYPE}'_KEY}"'
+ eval local LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"'
+ eval local LUKS_KEYDEV_FSTYPE='"${CRYPT_'${TYPE}'_KEYDEV_FSTYPE}"'
eval local OPENED_LOCKFILE='"${CRYPT_'${TYPE}'_OPENED_LOCKFILE}"'
- local DEV_ERROR=0 KEY_ERROR=0 KEYDEV_ERROR=0
- local mntkey="/mnt/key/" crypt_filter_ret= cryptsetup_options=''
+ local ASK_PASS=0
+ local DEV_ERROR=0
+ local HEADER_ERROR=0 HEADERDEV_ERROR=0
+ local KEY_ERROR=0 KEYDEV_ERROR=0
+ local mntheader="/mnt/header/" mntkey="/mnt/key/" crypt_filter_ret=
+
+ if [ -z "${LUKS_DEVICE}" ]
+ then
+ bad_msg "'crypt_${1}' kernel command-line argument is not set!"
+ exit 1
+ fi
while true
do
+ # Reset cryptsetup_options on each iteration
+ eval local cryptsetup_options='"${CRYPT_'${TYPE}'_OPTIONS}"'
+ cryptsetup_options="$(trim "${cryptsetup_options}")"
+
local gpg_cmd=""
if [ -e "${OPENED_LOCKFILE}" ]
then
good_msg "The LUKS device ${LUKS_DEVICE} meanwhile was opened by someone else."
break
# if crypt_silent=1 and some error occurs, enter shell quietly
- elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${DEV_ERROR} -eq 1 \) -o \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ]
+ elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( ${DEV_ERROR} -eq 1 \) \) ]
+ then
+ run_emergency_shell
+ elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${HEADER_ERROR} -eq 1 \) \) -o \( ${HEADERDEV_ERROR} -eq 1 \) \) ]
+ then
+ run_emergency_shell
+ elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ]
then
- run_shell
+ run_emergency_shell
elif [ ${DEV_ERROR} -eq 1 ]
then
prompt_user "LUKS_DEVICE" "${LUKS_NAME}"
DEV_ERROR=0
+ elif [ ${HEADER_ERROR} -eq 1 ]
+ then
+ prompt_user "LUKS_HEADER" "${LUKS_NAME} header"
+ HEADER_ERROR=0
+ elif [ ${HEADERDEV_ERROR} -eq 1 ]
+ then
+ prompt_user "LUKS_HEADERDEV" "${LUKS_NAME} header device"
+ HEADERDEV_ERROR=0
elif [ ${KEY_ERROR} -eq 1 ]
then
prompt_user "LUKS_KEY" "${LUKS_NAME} key"
@@ -1446,133 +1964,292 @@ openLUKS() {
LUKS_DEVICE=$(find_real_device "${LUKS_DEVICE}")
if [ -z "${LUKS_DEVICE}" ]
then
- bad_msg "Looks like CRYPT_${TYPE} kernel cmdline argument is not set." ${CRYPT_SILENT}
+ bad_msg "Failed to find LUKS device. If crypt_${1} kernel command-line argument is correct you are probably missing kernel support for your storage!" ${CRYPT_SILENT}
DEV_ERROR=1
continue
fi
- setup_md_device ${LUKS_DEVICE}
- cryptsetup isLuks ${LUKS_DEVICE}
- if [ $? -ne 0 ]
+ # Handle headers
+ if [ -n "${LUKS_HEADER}" ]
then
- bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT}
- DEV_ERROR=1
- continue
- else
- if [ "x${LUKS_TRIM}" = "xyes" ]
+ local REAL_LUKS_HEADERDEV="${LUKS_HEADERDEV}"
+ if [ ! -e "${mntheader}${LUKS_HEADER}" ]
then
- good_msg "Enabling TRIM support for ${LUKS_NAME} ..." ${CRYPT_SILENT}
- cryptsetup_options="${cryptsetup_options} --allow-discards"
- fi
-
- # Handle keys
- if [ -n "${LUKS_KEY}" ]
- then
- local REAL_LUKS_KEYDEV="${LUKS_KEYDEV}"
- if [ ! -e "${mntkey}${LUKS_KEY}" ]
+ REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}")
+ if [ -b "${REAL_LUKS_HEADERDEV}" ]
then
- REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
- if [ -b "${REAL_LUKS_KEYDEV}" ]
- then good_msg "Using key device ${REAL_LUKS_KEYDEV}." ${CRYPT_SILENT}
- else
- good_msg "Please insert removable device ${LUKS_KEYDEV} for ${LUKS_NAME}" ${CRYPT_SILENT}
- # abort after 10 secs
- local count=10
- while [ ${count} -gt 0 ]
- do
- count=$((count-1))
- sleep 1
- REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
- if [ -b "${REAL_LUKS_KEYDEV}" ]
- then
- good_msg "Removable device ${REAL_LUKS_KEYDEV} detected." ${CRYPT_SILENT}
- break
- fi
- done
- if [ ! -b "${REAL_LUKS_KEYDEV}" ]
+ good_msg "Using header device ${REAL_LUKS_HEADERDEV}." ${CRYPT_SILENT}
+ else
+ good_msg "Please insert removable device ${LUKS_HEADERDEV} for ${LUKS_NAME}" ${CRYPT_SILENT}
+ # abort after 10 secs
+ local count=10
+ while [ ${count} -gt 0 ]
+ do
+ count=$((count-1))
+ sleep 1
+ REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}")
+ if [ -b "${REAL_LUKS_HEADERDEV}" ]
+ then
+ good_msg "Removable device ${REAL_LUKS_HEADERDEV} detected." ${CRYPT_SILENT}
+ break
+ fi
+ done
+ if [ ! -b "${REAL_LUKS_HEADERDEV}" ]
+ then
+ eval CRYPT_${TYPE}_HEADER=${LUKS_HEADER}
+ bootstrapHeader ${TYPE}
+ eval LUKS_HEADERDEV='"${CRYPT_'${TYPE}'_HEADERDEV}"'
+ REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}")
+ if [ ! -b "${REAL_LUKS_HEADERDEV}" ]
then
- eval CRYPT_${TYPE}_KEY=${LUKS_KEY}
- bootstrapKey ${TYPE}
- eval LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"'
- REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
- if [ ! -b "${REAL_LUKS_KEYDEV}" ]
- then
- KEYDEV_ERROR=1
- bad_msg "Removable device ${LUKS_KEYDEV} not found." ${CRYPT_SILENT}
- continue
- fi
- # continue otherwise will mount keydev which is mounted by bootstrap
+ HEADERDEV_ERROR=1
+ bad_msg "Removable device ${LUKS_HEADERDEV} not found." ${CRYPT_SILENT}
continue
fi
+ # continue otherwise will mount headerdev which is mounted by bootstrap
+ continue
fi
+ fi
+
+ # At this point a device was recognized, now let's see if the header is there
+ [ ! -d "${mntheader}" ] && mkdir -p "${mntheader}" >/dev/null 2>&1
+
+ # determine fs -- 'auto' will not trigger module loading!
+ LUKS_HEADERDEV_FSTYPE=$(determine_fs "${REAL_LUKS_HEADERDEV}" "${LUKS_HEADERDEV_FSTYPE}")
- # At this point a device was recognized, now let's see if the key is there
- [ ! -d "${mntkey}" ] && mkdir -p "${mntkey}" >/dev/null 2>&1
+ if ! run mount -n -t ${LUKS_HEADERDEV_FSTYPE} -o ro ${REAL_LUKS_HEADERDEV} ${mntheader} >/dev/null 2>&1
+ then
+ HEADERDEV_ERROR=1
+ bad_msg "Mounting of device ${REAL_LUKS_HEADERDEV} failed." ${CRYPT_SILENT}
+ continue
+ fi
+
+ good_msg "Removable device ${REAL_LUKS_HEADERDEV} mounted." ${CRYPT_SILENT}
+ sleep 2
+
+ # headerfile exists?
+ if [ ! -e "${mntheader}${LUKS_HEADER}" ]
+ then
+ run umount -n "${mntheader}" >/dev/null 2>&1
+ HEADER_ERROR=1
+ HEADERDEV_ERROR=1
+ bad_msg "Header {LUKS_HEADER} on device ${REAL_LUKS_HEADERDEV} not found." ${CRYPT_SILENT}
+ continue
+ fi
+ fi
- mount -n -o ro ${REAL_LUKS_KEYDEV} ${mntkey} >/dev/null 2>&1
- if [ "$?" != '0' ]
+ if ! run cryptsetup isLuks ${LUKS_DEVICE} --header ${mntheader}${LUKS_HEADER}
+ then
+ bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT}
+ DEV_ERROR=1
+ continue
+ fi
+
+ # At this point a candidate header exists (either mounted before or not)
+ good_msg "${LUKS_HEADER} on device ${REAL_LUKS_HEADERDEV} found" ${CRYPT_SILENT}
+
+ cryptsetup_options="${cryptsetup_options} --header ${mntheader}${LUKS_HEADER}"
+ elif ! run cryptsetup isLuks ${LUKS_DEVICE}
+ then
+ bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT}
+ DEV_ERROR=1
+ continue
+ fi
+
+ # Handle keys
+ if [ -n "${LUKS_KEY}" ]
+ then
+ local REAL_LUKS_KEYDEV="${LUKS_KEYDEV}"
+ if [ ! -e "${mntkey}${LUKS_KEY}" ]
+ then
+ REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
+ if [ -b "${REAL_LUKS_KEYDEV}" ]
+ then
+ good_msg "Using key device ${REAL_LUKS_KEYDEV}." ${CRYPT_SILENT}
+ else
+ good_msg "Please insert removable device ${LUKS_KEYDEV} for ${LUKS_NAME}" ${CRYPT_SILENT}
+ # abort after 10 secs
+ local count=10
+ while [ ${count} -gt 0 ]
+ do
+ count=$((count-1))
+ sleep 1
+ REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
+ if [ -b "${REAL_LUKS_KEYDEV}" ]
+ then
+ good_msg "Removable device ${REAL_LUKS_KEYDEV} detected." ${CRYPT_SILENT}
+ break
+ fi
+ done
+ if [ ! -b "${REAL_LUKS_KEYDEV}" ]
then
- 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}" ]
+ eval CRYPT_${TYPE}_KEY=${LUKS_KEY}
+ bootstrapKey ${TYPE}
+ eval LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"'
+ REAL_LUKS_KEYDEV=$(find_real_device "${LUKS_KEYDEV}")
+ if [ ! -b "${REAL_LUKS_KEYDEV}" ]
then
- umount -n "${mntkey}" >/dev/null 2>&1
- KEY_ERROR=1
KEYDEV_ERROR=1
- bad_msg "Key {LUKS_KEY} on device ${REAL_LUKS_KEYDEV} not found." ${CRYPT_SILENT}
+ 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 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" ]
+ # At this point a device was recognized, now let's see if the key is there
+ [ ! -d "${mntkey}" ] && mkdir -p "${mntkey}" >/dev/null 2>&1
+
+ # determine fs -- 'auto' will not trigger module loading!
+ LUKS_KEYDEV_FSTYPE=$(determine_fs "${REAL_LUKS_KEYDEV}" "${LUKS_KEYDEV_FSTYPE}")
+
+ if ! run mount -n -t ${LUKS_KEYDEV_FSTYPE} -o ro ${REAL_LUKS_KEYDEV} ${mntkey} >/dev/null 2>&1
+ then
+ KEYDEV_ERROR=1
+ bad_msg "Mounting of device ${REAL_LUKS_KEYDEV} failed." ${CRYPT_SILENT}
+ continue
+ fi
+
+ good_msg "Removable device ${REAL_LUKS_KEYDEV} mounted." ${CRYPT_SILENT}
+ sleep 2
+
+ # keyfile exists?
+ if [ ! -e "${mntkey}${LUKS_KEY}" ]
then
- if [ ! -x '/sbin/gpg' ]
+ run umount -n "${mntkey}" >/dev/null 2>&1
+ KEY_ERROR=1
+ KEYDEV_ERROR=1
+ bad_msg "Key {LUKS_KEY} on device ${REAL_LUKS_KEYDEV} not found." ${CRYPT_SILENT}
+ continue
+ 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" ]
+ then
+ if ! hash gpg >/dev/null 2>&1
+ then
+ bad_msg "GPG-encrypted key file provided but gpg program is missing. Was initramfs built without --gpg parameter?"
+ bad_msg "Falling back to passphrase usage!"
+ else
+ [ -e /dev/tty ] && run mv /dev/tty /dev/tty.org
+ run mknod /dev/tty c 5 1
+ ASK_PASS=1
+ cryptsetup_options="${cryptsetup_options} -d -"
+ gpg_cmd="gpg --logger-file /dev/null --quiet"
+ # plymouth password entry is passed through STDIN, requiring '--passphrase-fd 0 --batch'
+ # for newer gpg versions (>=2.1) '--pinentry-mode loopback' may also be required for the above
+ # '--no-tty' is included to prevent interruption of plymouth by any gpg output
+ if [ "${PLYMOUTH}" = '1' -a "${CRYPT_SILENT}" != '1' ]
then
- bad_msg "GPG-encrypted key file provided but gpg program is missing. Was initramfs built without --gpg parameter?"
- bad_msg "Falling back to passphrase usage!"
+ gpg_cmd="${gpg_cmd} --passphrase-fd 0 --batch --no-tty --decrypt ${mntkey}${LUKS_KEY} | "
else
- [ -e /dev/tty ] && mv /dev/tty /dev/tty.org
- mknod /dev/tty c 5 1
- cryptsetup_options="${cryptsetup_options} -d -"
- gpg_cmd="/sbin/gpg --logger-file /dev/null --quiet --decrypt ${mntkey}${LUKS_KEY} |"
+ gpg_cmd="${gpg_cmd} --decrypt ${mntkey}${LUKS_KEY} | "
fi
- else
- cryptsetup_options="${cryptsetup_options} -d ${mntkey}${LUKS_KEY}"
fi
+ else
+ cryptsetup_options="${cryptsetup_options} -d ${mntkey}${LUKS_KEY}"
fi
- # At this point, keyfile or not, we're ready!
- crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
- crypt_filter_ret=$?
+ else
+ # no keyfile defined, password is required
+ ASK_PASS=1
+ fi
+
+ if [ -n "${cryptsetup_options}" ]
+ then
+ good_msg "Using the following cryptsetup options for ${LUKS_NAME}: ${cryptsetup_options}" ${CRYPT_SILENT}
+ fi
- [ -e /dev/tty.org ] \
- && rm -f /dev/tty \
- && mv /dev/tty.org /dev/tty
+ # At this point, {header,key}file or not, we're ready!
+ crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}" "${ASK_PASS}"
+ crypt_filter_ret=$?
- if [ ${crypt_filter_ret} -eq 0 ]
- then
- touch "${OPENED_LOCKFILE}"
- good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT}
- break
- elif [ ! -e "${OPENED_LOCKFILE}" ]
- then
- bad_msg "Failed to open LUKS device ${LUKS_DEVICE}" ${CRYPT_SILENT}
- DEV_ERROR=1
- KEY_ERROR=1
- KEYDEV_ERROR=1
- fi
+ [ -e /dev/tty.org ] \
+ && run rm -f /dev/tty \
+ && run mv /dev/tty.org /dev/tty
+
+ if [ ${crypt_filter_ret} -eq 0 ]
+ then
+ run touch "${OPENED_LOCKFILE}"
+ good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT}
+ break
+ elif [ ! -e "${OPENED_LOCKFILE}" ]
+ then
+ bad_msg "Failed to open LUKS device ${LUKS_DEVICE}" ${CRYPT_SILENT}
+ DEV_ERROR=1
+ HEADER_ERROR=1
+ HEADERDEV_ERROR=1
+ KEY_ERROR=1
+ KEYDEV_ERROR=1
fi
fi
done
- umount "${mntkey}" >/dev/null 2>&1
- rmdir -p "${mntkey}" >/dev/null 2>&1
+
+ udevsettle
+
+ if run mountpoint "${mntheader}" >/dev/null 2>&1
+ then
+ run umount "${mntheader}" >/dev/null 2>&1
+ fi
+
+ if run mountpoint "${mntkey}" >/dev/null 2>&1
+ then
+ run umount "${mntkey}" >/dev/null 2>&1
+ fi
+
+ [ -d "${mntheader}" ] && run rmdir -p "${mntheader}" >/dev/null 2>&1
+ [ -d "${mntkey}" ] && run rmdir -p "${mntkey}" >/dev/null 2>&1
+}
+
+keyctl_keyadd() {
+ if [ -n "${KEYCTL_KEYDESC}" ]
+ then
+ if [ ! -x /bin/keyctl ]
+ then
+ bad_msg "keyctl program is missing. Was initramfs built without --keyctl parameter?"
+ exit 1
+ fi
+
+ # not using read to avoid secrets being left in memory
+ stty -echo
+ echo -n "Please type the key '${KEYCTL_KEYDESC}' for the user keyring then press Ctrl-D twice: "
+ KEYCTL_KEYID=`keyctl padd user "${KEYCTL_KEYDESC}" @u`
+ echo
+ stty echo
+
+ if [ -n "${KEYCTL_KEYID}" -a -n "${KEYCTL_KEYTIMEOUT}" ]
+ then
+ keyctl timeout "${KEYCTL_KEYID}" "${KEYCTL_KEYTIMEOUT}"
+ fi
+ fi
+}
+
+keyctl_keyremove() {
+ if [ -n "${KEYCTL_KEYID}" -a -z "${KEYCTL_KEYKEEP}" ]
+ then
+ if [ ! -x /bin/keyctl ]
+ then
+ bad_msg "keyctl program is missing. Was initramfs built without --keyctl parameter?"
+ exit 1
+ fi
+
+ keyctl revoke "${KEYCTL_KEYID}"
+ keyctl unlink "${KEYCTL_KEYID}" >/dev/null
+
+ # trust but verify
+ if keyctl show "${KEYCTL_KEYID}" >/dev/null 2>&1
+ then
+ # better reboot than leave the user passphrase accidentally exposed
+ bad_msg "unable to remove the newly added key from keyring, rebooting in 5 seconds for security"
+ sleep 5
+ reboot -f
+ fi
+
+ KEYCTL_KEYID=
+ fi
}
iface_name() {
@@ -1585,7 +2262,9 @@ iface_name() {
for interface in /sys/class/net/*
do
- if [ $(cat ${interface}/address) = "${mac}" ]
+ [ -e ${interface}/address ] || continue
+
+ if [ "$(cat ${interface}/address 2>/dev/null)" = "${mac}" ]
then
echo ${interface##*/}
return
@@ -1597,6 +2276,16 @@ iface_name() {
}
start_network() {
+ good_msg "Starting network ..."
+
+ if [ "${GK_HW_USE_MODULES_LOAD}" = '1' ]
+ then
+ # Load network modules only when we need them to avoid possible
+ # firmware problems for people not using network that early
+ modules_scan net
+ udevsettle
+ fi
+
# At least gk.net.iface can only be processed after sysfs was
# mounted.
local x=
@@ -1620,17 +2309,21 @@ start_network() {
GK_NET_GW=${x#*=}
;;
gk.net.iface=*)
- local tmp_iface=$(iface_name "${x#*=}")
- if [ -z "${tmp_iface}" ]
- then
- warn_msg "Interface specified by '${x}' not found, falling back to genkernel defaults ..."
- else
- GK_NET_IFACE=${tmp_iface}
- fi
+ GK_NET_IFACE=${x#*=}
;;
gk.net.routes=*)
GK_NET_ROUTES=${x#*=}
;;
+ gk.net.timeout.interface=*)
+ local tmp_interface_timeout=${x#*=}
+ if is_int "${tmp_interface_timeout}"
+ then
+ GK_NET_TIMEOUT_INTERFACE=${tmp_interface_timeout}
+ else
+ warn_msg "'${x}' does not look like a valid number -- will keep using default value ${GK_NET_TIMEOUT_INTERFACE}!"
+ fi
+ unset tmp_interface_timeout
+ ;;
gk.net.timeout.dad=*)
local tmp_dad_timeout=${x#*=}
if is_int "${tmp_dad_timeout}"
@@ -1664,53 +2357,148 @@ start_network() {
esac
done
- if [ ! -d "/sys/class/net/${GK_NET_IFACE}" ]
+ local interface_identifier=device
+ if echo "${GK_NET_IFACE}" | grep -qE ':|-'
then
- warn_msg "Interface ${GK_NET_IFACE} not found; Will not try to start network ..."
- return
+ interface_identifier=mac
+ good_msg_n "Waiting for interface with MAC address ${GK_NET_IFACE} ..."
+ else
+ good_msg_n "Waiting for interface ${GK_NET_IFACE} ..."
+ fi
+
+ local tmp_interface=
+ local have_interface=0
+ local interface_time_waited=0
+ local interface_timeout_100msec_modulo=
+ local interface_timeout && let interface_timeout=$(date +%s)+1
+ [ -n "${GK_NET_TIMEOUT_INTERFACE}" -a "${GK_NET_TIMEOUT_INTERFACE}" -gt 0 ] && let interface_timeout=${interface_timeout}+${GK_NET_TIMEOUT_INTERFACE}-1
+
+ while [ "${have_interface}" != '1' -a $(date +%s) -le ${interface_timeout} ]
+ do
+ tmp_interface=$(iface_name "${GK_NET_IFACE}")
+ if [ -n "${tmp_interface}" ]
+ then
+ # We got at least something to probe
+ if [ -d "/sys/class/net/${tmp_interface}" ]
+ then
+ GK_NET_IFACE="${tmp_interface}"
+ have_interface=1
+ break
+ fi
+ fi
+
+ if [ "${have_interface}" != '1' ]
+ then
+ let interface_time_waited=${interface_time_waited}+1
+ sleep 0.1s
+
+ let interface_timeout_100msec_modulo=${interface_time_waited}%10
+ if [ ${interface_timeout_100msec_modulo} = 0 ]
+ then
+ is_quiet || printf "."
+ fi
+ fi
+ done
+
+ is_quiet || echo
+
+ if [ "${have_interface}" != '1' ]
+ then
+ # Timeout!
+ if [ "${interface_identifier}" = 'mac' ]
+ then
+ bad_msg "Interface with MAC address ${GK_NET_IFACE} not found!"
+ else
+ bad_msg "Interface ${GK_NET_IFACE} not found!"
+ fi
+
+ warn_msg "Will not try to start network ..."
+ return 1
+ elif [ "${interface_identifier}" = 'mac' ]
+ then
+ good_msg "Interface detected as ${GK_NET_IFACE}"
fi
if [ -z "${IP}" -o "${IP}" = 'dhcp' ]
then
- good_msg "Bringing up interface ${GK_NET_IFACE} using dhcp ..." ${QUIET}
- busybox udhcpc -i "${GK_NET_IFACE}" -n -t ${GK_NET_DHCP_RETRIES} -T ${GK_NET_TIMEOUT_DHCP} -R -p "${GK_NET_DHCP_PIDFILE}"
+ if is_interface_up
+ then
+ # CONFIG_IP_PNP_DHCP and ip=dhcp probably caused kernel to bring up
+ # network for us. Really no need re-run dhcp...
+ warn_msg "Interface ${GK_NET_IFACE} is already up."
+ warn_msg "Skipping network setup; Will use existing network configuration ..."
+ run touch "${GK_NET_LOCKFILE}"
+ return 0
+ fi
+
+ local udhcpc_cmd="run udhcpc -i '${GK_NET_IFACE}' -n -t ${GK_NET_DHCP_RETRIES} -T ${GK_NET_TIMEOUT_DHCP} -R -p '${GK_NET_DHCP_PIDFILE}' 2>&1"
+ is_log_enabled && udhcpc_cmd="${udhcpc_cmd} | tee -a '${GK_INIT_LOG}'"
+
+ good_msg "Bringing up interface ${GK_NET_IFACE} using dhcp ..."
+ eval "${udhcpc_cmd}"
if [ $? -ne 0 ]
then
bad_msg "Failed to start udhcpc for interface ${GK_NET_IFACE}!"
- return
+ return 1
+ fi
+ elif echo "${IP}" | grep -qE ':|,'
+ then
+ if is_interface_up
+ then
+ # CONFIG_IP_PNP probably caused kernel to bring up
+ # network for us. Due to presence of ":" or ","
+ # we can assume an advanced network configuration
+ # which we cannot reproduce...
+ warn_msg "Interface ${GK_NET_IFACE} is already up."
+ warn_msg "Skipping network setup; Will use existing network configuration ..."
+ run touch "${GK_NET_LOCKFILE}"
+ return 0
fi
+
+ warn_msg "Found advanced network configuration (check ip= kernel command-line argument)!"
+ warn_msg "Assuming user want to use kernel's IP PNP; Will not try to start network ..."
+ return 1
else
- good_msg "Bringing up interface ${GK_NET_IFACE} ..." ${QUIET}
- ip link set "${GK_NET_IFACE}" up
+ if is_interface_up
+ then
+ # At this point we don't know if kernel has brought up network the
+ # way we wanted. It's safer to restart interface and do it on our own...
+ warn_msg "Interface ${GK_NET_IFACE} is already up and therefore in an unknown state!"
+ warn_msg "Will now restart interface ${GK_NET_IFACE} to get into a known state ..."
+ kill_network
+ fi
- good_msg "Setting address '${IP}' on ${GK_NET_IFACE} ..." ${QUIET}
- ip addr add "${IP}" dev "${GK_NET_IFACE}"
+ good_msg "Bringing up interface ${GK_NET_IFACE} ..."
+ run ip link set "${GK_NET_IFACE}" up
+
+ good_msg "Setting address '${IP}' on ${GK_NET_IFACE} ..."
+ run ip addr add "${IP}" dev "${GK_NET_IFACE}"
if [ -n "${GK_NET_ROUTES}" ]
then
local route=
for route in ${GK_NET_ROUTES}
do
- good_msg "Adding additional route '${route}' on ${GK_NET_IFACE} ..." ${QUIET}
- ip route add "${route}" dev "${GK_NET_IFACE}"
+ good_msg "Adding additional route '${route}' on ${GK_NET_IFACE} ..."
+ run ip route add "${route}" dev "${GK_NET_IFACE}"
done
fi
if [ -n "${GK_NET_GW}" ]
then
- good_msg "Adding default route via '${GK_NET_GW}' on ${GK_NET_IFACE} ..." ${QUIET}
- ip route add default via "${GK_NET_GW}" dev "${GK_NET_IFACE}"
+ good_msg "Adding default route via '${GK_NET_GW}' on ${GK_NET_IFACE} ..."
+ run ip route add default via "${GK_NET_GW}" dev "${GK_NET_IFACE}"
fi
fi
- touch "${GK_NET_LOCKFILE}"
+ run touch "${GK_NET_LOCKFILE}"
}
kill_network() {
if [ -s "${GK_NET_DHCP_PIDFILE}" ]
then
good_msg "Stopping udhcpc ..."
- kill $(cat "${GK_NET_DHCP_PIDFILE}")
+ run kill $(cat "${GK_NET_DHCP_PIDFILE}")
fi
if [ ! -d "/sys/class/net/${GK_NET_IFACE}" ]
@@ -1728,8 +2516,7 @@ kill_network() {
# interface.
if ipv6_tentative
then
- [ -z "${QUIET}" ] && \
- printf "%b" "${WARN}**${NORMAL}${BOLD} Waiting for tentative IPv6 addresses to complete DAD ${NORMAL}..."
+ good_msg_n "Waiting for tentative IPv6 addresses to complete DAD ..."
local dad_timeout=10
while [ ${dad_timeout} -gt 0 ]
@@ -1737,11 +2524,10 @@ kill_network() {
ipv6_tentative || break
sleep 1
: $(( dad_timeout -= 1 ))
- [ -z "${QUIET}" ] && \
- printf "."
+ is_quiet || printf "."
done
- echo ""
+ is_quiet || echo
if [ ${dad_timeout} -le 0 ]
then
@@ -1749,26 +2535,24 @@ kill_network() {
fi
fi
- [ -z "${QUIET}" ] && \
- printf "%b" "${GOOD}>>${NORMAL}${BOLD} Bringing down interface ${GK_NET_IFACE} ${NORMAL}..."
+ good_msg_n "Bringing down interface ${GK_NET_IFACE} ..."
local deconfiguration_timeout=${GK_NET_TIMEOUT_DECONFIGURATION}
while [ ${deconfiguration_timeout} -gt 0 ]
do
- ip addr flush dev "${GK_NET_IFACE}"
- ip route flush dev "${GK_NET_IFACE}"
- ip link set "${GK_NET_IFACE}" down
+ run ip addr flush dev "${GK_NET_IFACE}"
+ run ip route flush dev "${GK_NET_IFACE}"
+ run ip link set "${GK_NET_IFACE}" down
if grep -q "down" "/sys/class/net/${GK_NET_IFACE}/operstate" 2>/dev/null
then
break
fi
sleep 1
: $(( deconfiguration_timeout -= 1 ))
- [ -z "${QUIET}" ] && \
- printf "."
+ is_quiet || printf "."
done
- echo ""
+ is_quiet || echo
if [ ${deconfiguration_timeout} -le 0 ]
then
@@ -1776,7 +2560,16 @@ kill_network() {
return
fi
- rm "${GK_NET_LOCKFILE}"
+ [ -f "${GK_NET_LOCKFILE}" ] && run rm "${GK_NET_LOCKFILE}"
+}
+
+is_interface_up() {
+ if ip link show dev "${GK_NET_IFACE}" 2>/dev/null | grep -q ',UP,'
+ then
+ return 0
+ else
+ return 1
+ fi
}
ipv6_tentative() {
@@ -1788,12 +2581,23 @@ ipv6_tentative() {
fi
}
-start_LUKS() {
- # if key is set but neither ssh enabled or key device is given, find
- # the key device
+start_LUKS_root() {
+ # if key/header is set but neither ssh enabled or key device is given, find
+ # the key/header device
- [ -n "${CRYPT_ROOT_KEY}" ] && [ -z "${CRYPT_ROOT_KEYDEV}" ] \
- && sleep 6 && bootstrapKey "ROOT"
+ if (
+ [ -n "${CRYPT_ROOT_KEY}" -a -z "${CRYPT_ROOT_KEYDEV}" ] ||
+ [ -n "${CRYPT_ROOT_HEADER}" -a -z "${CRYPT_ROOT_HEADERDEV}" ]
+ )
+ then
+ sleep 6
+ fi
+
+ [ -n "${CRYPT_ROOT_KEY}" -a -z "${CRYPT_ROOT_KEYDEV}" ] \
+ && bootstrapKey "ROOT"
+
+ [ -n "${CRYPT_ROOT_HEADER}" -a -z "${CRYPT_ROOT_HEADERDEV}" ] \
+ && bootstrapHeader "ROOT"
if [ -n "${CRYPT_ROOT}" ]
then
@@ -1806,10 +2610,24 @@ start_LUKS() {
REAL_ROOT="/dev/mapper/root"
fi
fi
+}
+start_LUKS_swap() {
# same for swap, but no need to sleep if root was unencrypted
- [ -n "${CRYPT_SWAP_KEY}" ] && [ -z "${CRYPT_SWAP_KEYDEV}" ] \
- && { [ -z "${CRYPT_ROOT}" ] && sleep 6; bootstrapKey "SWAP"; }
+
+ if (
+ [ -n "${CRYPT_SWAP_KEY}" -a -z "${CRYPT_SWAP_KEYDEV}" ] ||
+ [ -n "${CRYPT_SWAP_HEADER}" -a -z "${CRYPT_SWAP_HEADERDEV}" ]
+ )
+ then
+ [ -z "${CRYPT_ROOT}" ] && sleep 6
+ fi
+
+ [ -n "${CRYPT_SWAP_KEY}" -a -z "${CRYPT_SWAP_KEYDEV}" ] \
+ && bootstrapKey "SWAP"
+
+ [ -n "${CRYPT_SWAP_HEADER}" -a -z "${CRYPT_SWAP_HEADERDEV}" ] \
+ && bootstrapHeader "SWAP"
if [ -n "${CRYPT_SWAP}" ]
then
@@ -1831,30 +2649,39 @@ start_sshd() {
if [ ! -f "${GK_NET_LOCKFILE}" ]
then
- warn_msg "Network not started; Not starting sshd ..."
+ warn_msg "Network not started; Not starting sshd ..." 0
return
fi
- if [ ! -x "/usr/sbin/dropbear" ]
+ if ! hash dropbear >/dev/null 2>&1
then
- bad_msg "/usr/sbin/dropbear not found! Did you call genkernel with --ssh parameter?"
+ bad_msg "/usr/sbin/dropbear not found! Was initramfs built without --ssh parameter?"
return
fi
- # setup environment variables for the ssh login shell
- local varname= varvalue=
- touch "${CRYPT_ENV_FILE}"
- for varname in CRYPT_ROOT CRYPT_ROOT_TRIM CRYPT_SILENT CRYPT_SWAP DEBUG
- do
- eval varvalue=\$${varname}
- echo "${varname}=${varvalue}" >> "${CRYPT_ENV_FILE}"
- done
+ # setup environment variables for the remote rescue shell
+ # ZFS will use a different file because $REAL_ROOT for ZFS
+ # isn't known yet.
+ write_env_file \
+ "${CRYPT_ENV_FILE}" \
+ CRYPT_ROOT \
+ CRYPT_ROOT_OPTIONS \
+ CRYPT_SILENT \
+ CRYPT_SWAP \
+ CRYPT_SWAP_OPTIONS
- touch /var/log/lastlog
+ run touch /var/log/lastlog
- good_msg "Starting dropbear sshd ..." ${QUIET}
- /usr/sbin/dropbear -p ${GK_SSHD_PORT} -R -P "${GK_SSHD_PIDFILE}" 2>/var/log/dropbear.log
- test_success "Failed to start dropbear"
+ good_msg "Starting dropbear sshd ..."
+ run dropbear -p ${GK_SSHD_PORT} -R -P "${GK_SSHD_PIDFILE}" 2>/run/initramfs/dropbear.log
+ if [ $? -eq 0 ]
+ then
+ if [ "${GK_PROMPT_TIMEOUT}" = '0' ]
+ then
+ warn_msg "Changing gk.prompt.timeout=0 to 30 to allow remote user to answer prompts ..."
+ GK_PROMPT_TIMEOUT=30
+ fi
+ fi
}
wait_sshd() {
@@ -1868,7 +2695,10 @@ wait_sshd() {
return
fi
- printf "%b" "${GOOD}>>${NORMAL}${BOLD} gk.sshd.wait set; Waiting ${GK_SSHD_WAIT} seconds for SSH connection ${NORMAL}..."
+ good_msg_n "gk.sshd.wait set; Waiting ${GK_SSHD_WAIT} seconds for SSH connection ..."
+
+ local last_cmd="run last -W 2>/dev/null | head -n 3"
+ is_log_enabled && last_cmd="${last_cmd} | tee -a '${GK_INIT_LOG}'"
local ssh_timeout=${GK_SSHD_WAIT}
while [ ${ssh_timeout} -gt 0 ]
@@ -1876,22 +2706,22 @@ wait_sshd() {
if [ -f "${GK_SSHD_LOCKFILE}" ]
then
echo ""
- last -W | head -n 3 2>/dev/null
+ eval "${last_cmd}"
break
fi
sleep 1
: $(( ssh_timeout -= 1 ))
- printf "."
+ is_quiet || printf "."
done
- echo ""
+ is_quiet || echo
}
kill_sshd() {
if [ -s "${GK_SSHD_PIDFILE}" ]
then
- good_msg "Stopping dropbear sshd ..." ${QUIET}
- kill $(cat "${GK_SSHD_PIDFILE}")
+ good_msg "Stopping dropbear sshd ..."
+ run kill $(cat "${GK_SSHD_PIDFILE}")
fi
}
@@ -1900,8 +2730,8 @@ cleanup() {
then
if [ -f "${GK_SSHD_LOCKFILE}" ]
then
- warn_msg "The lockfile at '${GK_SSHD_LOCKFILE}' exists."
- warn_msg "The boot process will be paused until the lock is removed."
+ warn_msg "The lockfile at '${GK_SSHD_LOCKFILE}' exists." 0
+ warn_msg "The boot process will be paused until the lock is removed." 0
while true
do
if [ -f "${GK_SSHD_LOCKFILE}" ]
@@ -1917,11 +2747,19 @@ cleanup() {
kill_sshd
# Ensure that we terminated any existing connection
- pkill -9 dropbear >/dev/null 2>&1
+ if pgrep dropbear >/dev/null 2>&1
+ then
+ run pkill -9 dropbear >/dev/null 2>&1
+ fi
if [ -f "${GK_NET_LOCKFILE}" ]
then
- kill_network
+ if [ "${REAL_ROOT}" = "/dev/nfs" ]
+ then
+ warn_msg "real_root=/dev/nfs; Will not bring down interface ${GK_NET_IFACE} ..."
+ else
+ kill_network
+ fi
fi
}
@@ -1929,12 +2767,12 @@ sdelay() {
# Sleep a specific number of seconds if SDELAY is set
if [ -n "${SDELAY}" ]
then
- good_msg_n "Waiting ${SDELAY} seconds ..."
+ good_msg_n "scandelay set; Waiting ${SDELAY} seconds ..."
while [ ${SDELAY} -gt 0 ]
do
let SDELAY=${SDELAY}-1
sleep 1
- printf "."
+ is_quiet || printf "."
done
echo
elif [ "${CDROOT}" = '1' ]
@@ -1943,16 +2781,6 @@ sdelay() {
fi
}
-quiet_kmsg() {
- # if QUIET is set make the kernel less chatty
- [ -n "${QUIET}" ] && echo '0' > /proc/sys/kernel/printk
-}
-
-verbose_kmsg() {
- # if QUIET is set make the kernel less chatty
- [ -n "${QUIET}" ] && echo '6' > /proc/sys/kernel/printk
-}
-
cdupdate() {
if [ "${CDROOT}" = '1' ]
then
@@ -1965,11 +2793,11 @@ cdupdate() {
if [ -n "${cdupdate_path}" ]
then
good_msg "Running cdupdate.sh (${cdupdate_path})"
- ${cdupdate_path}
+ run ${cdupdate_path}
if [ "$?" != '0' ]
then
bad_msg "Executing cdupdate.sh failed!"
- run_shell
+ run_emergency_shell
fi
else
good_msg 'No cdupdate.sh script found, skipping ...'
@@ -1977,52 +2805,42 @@ cdupdate() {
fi
}
-setup_btrfsctl() {
- # start BTRFS volume detection, if available
- [ -x /sbin/btrfsctl ] && /sbin/btrfsctl -a
-}
-
-setup_md_device() {
- local device
-
- [ -z "$1" ] && device="${REAL_ROOT}" || device="$1"
- [ -z "${device}" ] && return # LiveCD
-
- if [ $(echo ${device}|sed -e 's#\(luks:\)\?\(/dev/md\)[[:digit:]]\+#\2#') = "/dev/md" ]
+do_resume() {
+ local device=$(find_real_device "${REAL_RESUME}")
+ if [ -z "${device}" ]
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}
+ warn_msg "resume device (${REAL_RESUME}) not found; Skipping resume ..." 0
+ return 0
+ else
+ REAL_RESUME="${device}"
fi
-}
-rundebugshell() {
- if [ -n "${DEBUG}" ]
+ local resume_tried=no
+ if [ -d /proc/suspend2 -o -d /sys/power/suspend2 -o -d /sys/power/tuxonice ]
+ then
+ tuxonice_resume
+ resume_tried=yes
+ elif [ -f /sys/power/resume ]
then
- good_msg 'Starting debug shell as requested by "debug" option.'
- good_msg "Stopping by: ${1}"
- run_shell
+ swsusp_resume
+ resume_tried=yes
fi
-}
-do_resume() {
- if [ -d /proc/suspend2 -o -d /sys/power/suspend2 -o -d /sys/power/tuxonice ]
+ if is_true "${resume_tried}"
then
- tuxonice_resume
+ warn_msg "System is not resuming from ${REAL_RESUME}, probably because it wasn't suspended; Continue normal booting ..."
else
- swsusp_resume
+ warn_msg "resume device (${REAL_RESUME}) specified but kernel is lacking proper hibernation support!"
fi
}
swsusp_resume() {
# determine swap resume partition
local device=$(ls -lL "${REAL_RESUME}" | sed 's/\ */ /g' | cut -d \ -f 5-6 | sed 's/,\ */:/')
- [ -f /sys/power/resume ] && echo "${device}" > /sys/power/resume
+
+ log_msg "Trying to resume using swsusp ..."
+ log_msg "COMMAND: 'echo \"${device}\" > /sys/power/resume'"
+ echo "${device}" > /sys/power/resume
}
tuxonice_resume() {
@@ -2069,20 +2887,24 @@ tuxonice_resume() {
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}"
+ command -v suspend2ui_text >/dev/null 2>&1 && command -v suspend2ui_text > "${tuxonice_userui_program}"
+ command -v tuxoniceui_text >/dev/null 2>&1 && command -v 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}"
+ command -v suspend2ui_fbsplash >/dev/null 2>&1 && command -v suspend2ui_fbsplash > "${tuxonice_userui_program}"
+ command -v tuxoniceui_fbsplash >/dev/null 2>&1 && command -v tuxoniceui_fbsplash > "${tuxonice_userui_program}"
fi
fi
+
+ log_msg "Trying to resume using TuxOnIce ..."
+ log_msg "COMMAND: 'echo \"${REAL_RESUME}\" > ${tuxonice_resumedev}'"
echo "${REAL_RESUME}" > "${tuxonice_resumedev}"
+ log_msg "COMMAND: 'echo > ${tuxonice_do_resume}'"
echo > "${tuxonice_do_resume}"
}
@@ -2113,16 +2935,16 @@ setup_squashfs_aufs() {
for dir in ${aufs_rw_branch} ${aufs_ro_branch}
do
- [ ! -d "${dir}" ] && mkdir -p "${dir}"
+ [ ! -d "${dir}" ] && run mkdir -p "${dir}"
done
good_msg "Loading aufs module ..."
- modprobe aufs >/dev/null 2>&1
+ run modprobe aufs >/dev/null 2>&1
checkfs aufs
- mount -t squashfs -o loop,ro "${CDROOT_PATH}/${LOOPEXT}${LOOP}" "${aufs_ro_branch}"
- mount -t tmpfs none "${aufs_rw_branch}"
- mount -t aufs -o "br:${aufs_rw_branch}:${aufs_ro_branch}" aufs "${NEW_ROOT}"
+ run mount -t squashfs -o loop,ro "${CDROOT_PATH}/${LOOPEXT}${LOOP}" "${aufs_ro_branch}"
+ run mount -t tmpfs none "${aufs_rw_branch}"
+ run mount -t aufs -o "br:${aufs_rw_branch}:${aufs_ro_branch}" aufs "${NEW_ROOT}"
}
setup_unionfs() {
@@ -2141,9 +2963,9 @@ setup_unionfs() {
# fi
# mkdir -p ${MEMORY}
- mkdir -p ${UNION}
+ run mkdir -p ${UNION}
good_msg "Loading fuse module"
- modprobe fuse >/dev/null 2>&1
+ run modprobe fuse >/dev/null 2>&1
# if [ -n "${UNIONFS}" ]
# then
# CHANGESDEV=${UNIONFS}
@@ -2170,12 +2992,12 @@ setup_unionfs() {
# mount -t tmpfs tmpfs ${MEMORY}
# fi
- mkdir /tmp
- mkdir -p ${UNION}
+ run mkdir /tmp
+ run mkdir -p ${UNION}
# mkdir -p ${CHANGES}
# mount -t unionfs -o dirs=${CHANGES}=rw unionfs ${UNION}
good_msg "Creating union mount"
- unionfs -o allow_other,cow,noinitgroups,suid,dev,default_permissions,use_ino ${rw_dir}=RW:${ro_dir}=RO ${UNION} 2>/dev/null
+ run unionfs -o allow_other,cow,noinitgroups,suid,dev,default_permissions,use_ino ${rw_dir}=RW:${ro_dir}=RO ${UNION} 2>/dev/null
ret=$?
if [ ${ret} -ne 0 ]
then
@@ -2183,12 +3005,27 @@ setup_unionfs() {
USE_UNIONFS_NORMAL=0
fi
[ ! -d "${NEW_ROOT}${CDROOT_PATH}" ] && mkdir -p "${NEW_ROOT}${CDROOT_PATH}"
- mount --bind "${CDROOT_PATH}" "${NEW_ROOT}${CDROOT_PATH}"
+ run mount --bind "${CDROOT_PATH}" "${NEW_ROOT}${CDROOT_PATH}"
else
USE_UNIONFS_NORMAL=0
fi
}
+get_active_console() {
+ local active_console=console
+
+ while [ -f /sys/class/tty/${active_console}/active ]
+ do
+ active_console=$(cat /sys/class/tty/${active_console}/active)
+
+ # last console will be the active one,
+ # see https://www.kernel.org/doc/html/latest/admin-guide/serial-console.html
+ active_console=${active_console##* }
+ done
+
+ echo ${active_console}
+}
+
get_mounts_list() {
awk '
/^[[:blank:]]*#/ { next }
@@ -2220,6 +3057,24 @@ get_mount_device() {
' ${NEW_ROOT}/etc/fstab
}
+get_zfs_property() {
+ local device=${1}
+ local propertyname=${2}
+
+ echo "$(zfs get -H -o value ${propertyname} "${device}" 2>/dev/null)"
+}
+
+# Returns TRUE if $1 contains literal string $2 at the
+# beginning and is not empty
+str_starts() {
+ if [ "${1#"${2}"*}" != "${1}" ]
+ then
+ return 0
+ fi
+
+ return 1
+}
+
# 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.