#!/bin/sh # shellcheck source=initrd.defaults . /etc/initrd.defaults # shellcheck source=initrd.scripts . /etc/initrd.scripts # shellcheck source=/dev/null [ -e /etc/initrd.splash ] && . /etc/initrd.splash # Basic /dev content, we need it as fast as possible. [ ! -e /dev/console ] && mknod /dev/console c 5 1 [ ! -e /dev/null ] && mknod /dev/null c 1 3 [ ! -e /dev/random ] && mknod /dev/random c 1 8 [ ! -e /dev/tty ] && mknod /dev/tty c 5 0 [ ! -e /dev/tty0 ] && mknod /dev/tty0 c 4 0 [ ! -e /dev/tty1 ] && mknod /dev/tty1 c 4 1 [ ! -e /dev/ttyS0 ] && mknod /dev/ttyS0 c 4 64 [ ! -e /dev/ttyS1 ] && mknod /dev/ttyS1 c 4 65 [ ! -e /dev/urandom ] && mknod /dev/urandom c 1 9 [ ! -e /dev/zero ] && mknod /dev/zero c 1 5 # Take control CONSOLE="/dev/$(get_active_console)" exec 0<>${CONSOLE} 1<>${CONSOLE} 2<>${CONSOLE} if [ "$$" != '1' ] then echo '/linuxrc has to be run as the init process as the one' echo 'with a PID of 1. Try adding init="/linuxrc" to the' echo 'kernel command line or running "exec /linuxrc".' exit 1 fi mount -t proc -o noexec,nosuid,nodev proc /proc >/dev/null 2>&1 mount -o remount,rw / >/dev/null 2>&1 mount -t tmpfs -o rw,nosuid,nodev,relatime,mode=755 none /run 2>&1 if [ ! -d /run/initramfs ] then mkdir -p /run/initramfs chmod 0750 /run/initramfs fi if [ ! -s /etc/ld.so.cache ] then # Looks like we were unable to run ldconfig during initramfs generation hash ldconfig >/dev/null 2>&1 && run ldconfig fi # Set up symlinks run busybox --install -s # Handle kernel command-line parameters CMDLINE=$(cat /proc/cmdline 2>/dev/null) for x in ${CMDLINE} do case "${x}" in real_root=*) REAL_ROOT=${x#*=} ;; root=*) FAKE_ROOT=${x#*=} ;; subdir=*) SUBDIR=${x#*=} ;; real_init=*) REAL_INIT=${x#*=} ;; init=*) FAKE_INIT=${x#*=} ;; # Livecd options cdroot) CDROOT=1 ;; cdroot=*) CDROOT=1 CDROOT_DEV=${x#*=} ;; cdroot_type=*) CDROOT_TYPE=${x#*=} ;; cdroot_marker=*) CDROOT_MARKER=${x#*=} ;; # Start livecd loop, looptype options loop=*) LOOP=${x#*=} ;; looptype=*) LOOPTYPE=${x#*=} ;; isoboot=*) ISOBOOT=${x#*=} ;; # Start Volume manager options dolvm) USE_LVM_NORMAL=1 ;; domdadm) USE_MDADM=1 ;; dodmraid) USE_DMRAID_NORMAL=1 ;; dodmraid=*) DMRAID_OPTS=${x#*=} USE_DMRAID_NORMAL=1 ;; domultipath) USE_MULTIPATH_NORMAL=1 ;; dozfs*) USE_ZFS=1 case "${x#*=}" in *force*) ZPOOL_FORCE=-f ;; esac case "${x#*=}" in *cache*) if [ -s "/etc/zfs/zpool.cache" ] then ZPOOL_CACHE="-c /etc/zfs/zpool.cache" else bad_msg "zpool.cache not found or empty, zpool import will be slow" fi ;; esac ;; quiet|quiet_genkernel) QUIET=1 ;; # Debug Options debug) run touch "${GK_DEBUGMODE_STATEFILE}" ;; # Scan delay options scandelay=*) SDELAY=${x#*=} ;; scandelay) SDELAY=3 ;; rootdelay=*|rootwait=*) ROOTDELAY=${x#*=} ;; rootdelay|rootwait) ROOTDELAY=5 ;; firstmods=*) FIRSTMODS=$(echo ${FIRSTMODS} ${x#*=} | sed -e 's/^\ *//;s/,/ /g') ;; # Module no-loads doload=*) MDOLIST=$(echo ${MDOLIST} ${x#*=} | sed -e 's/^\ *//;s/,/ /g') ;; noload=*) MLIST=$(echo ${MLIST} ${x#*=} | sed -e 's/^\ *//;s/,/ /g') export MLIST ;; # /dev/md lvmraid=*) warn_msg "'${x}' kernel command-line argument is deprecated; Use 'dolvm' instead!" USE_LVM_NORMAL=1 ;; part=*) MDPART=${x#*=} ;; part|partitionable) MDPART=1 ;; # For network options see start_network() in initrd.scripts # NFS nfsroot=*) NFSROOT=${x#*=} ;; # iSCSI iscsi_initiatorname=*) ISCSI_INITIATORNAME=${x#*=} ;; iscsi_target=*) ISCSI_TARGET=${x#*=} ;; iscsi_tgpt=*) ISCSI_TGPT=${x#*=} ;; iscsi_address=*) ISCSI_ADDRESS=${x#*=} ;; iscsi_port=*) ISCSI_PORT=${x#*=} ;; iscsi_username=*) ISCSI_USERNAME=${x#*=} ;; iscsi_password=*) ISCSI_PASSWORD=${x#*=} ;; iscsi_username_in=*) ISCSI_USERNAME_IN=${x#*=} ;; iscsi_password_in=*) ISCSI_PASSWORD_IN=${x#*=} ;; iscsi_debug=*) ISCSI_DEBUG=${x#*=} ;; iscsi_noibft) ISCSI_NOIBFT=1 ;; # Crypto crypt_root=*) CRYPT_ROOT=${x#*=} USE_CRYPTSETUP=1 ;; crypt_root_options=*) CRYPT_ROOT_OPTIONS=$(echo ${CRYPT_ROOT_OPTIONS} ${x#*=} | sed -e 's/,/ /g') ;; crypt_swap=*) CRYPT_SWAP=${x#*=} USE_CRYPTSETUP=1 ;; crypt_swap_options=*) CRYPT_SWAP_OPTIONS=$(echo ${CRYPT_SWAP_OPTIONS} ${x#*=} | sed -e 's/,/ /g') ;; root_key=*) CRYPT_ROOT_KEY=${x#*=} ;; root_keydev=*) CRYPT_ROOT_KEYDEV=${x#*=} ;; root_keydev_fstype=*) CRYPT_ROOT_KEYDEV_FSTYPE=${x#*=} ;; root_trim=*) tmp_enabled=${x#*=} if is_true "${tmp_enabled}" then CRYPT_ROOT_OPTIONS="${CRYPT_ROOT_OPTIONS} --allow-discards" fi unset tmp_enabled ;; swap_key=*) CRYPT_SWAP_KEY=${x#*=} ;; swap_keydev=*) CRYPT_SWAP_KEYDEV=${x#*=} ;; swap_keydev_fstype=*) CRYPT_SWAP_KEYDEV_FSTYPE=${x#*=} ;; real_resume=*|resume=*) REAL_RESUME=${x#*=} ;; noresume) NORESUME=1 ;; crypt_silent) CRYPT_SILENT=1 ;; dosshd) USE_SSH=1 ;; gk.bootfont.disabled=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then GK_BOOTFONT_DISABLED=1 fi unset tmp_disabled ;; gk.emergency=*) tmp_action=${x#*=} case "${tmp_action}" in reboot) GK_EMERGENCY_ACTION="reboot -f" ;; poweroff) GK_EMERGENCY_ACTION="poweroff -f" ;; halt) GK_EMERGENCY_ACTION="halt -f" ;; *) warn_msg "'${x}' is an unsupported emergency action -- ignored!" ;; esac unset tmp_action ;; gk.hw.load-all=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then GK_HW_LOAD_ALL_MODULES=1 fi unset tmp_disabled ;; gk.hw.use-modules_load=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then GK_HW_USE_MODULES_LOAD=1 fi unset tmp_disabled ;; gk.log.disabled=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then [ -f "${GK_INIT_LOG}" ] && rm "${GK_INIT_LOG}" GK_INIT_LOG= touch "${GK_INIT_LOG_DISABLED}" fi unset tmp_disabled ;; gk.sshd.port=*) tmp_port=${x#*=} if is_int "${tmp_port}" then GK_SSHD_PORT=${tmp_port} else warn_msg "'${x}' does not look like a valid port -- ignored!" fi unset tmp_port ;; gk.sshd.wait=*) tmp_wait=${x#*=} if is_int "${tmp_wait}" then GK_SSHD_WAIT=${tmp_wait} else warn_msg "'${x}' does not look like a valid time (second) value -- ignored!" fi unset tmp_wait ;; gk.udev.debug=*) tmp_enabled=${x#*=} if is_true "${tmp_enabled}" then GK_UDEV_DEBUG=1 fi unset tmp_enabled ;; gk.udev.timeout=*) tmp_timeout=${x#*=} if is_int "${tmp_timeout}" then GK_UDEV_TIMEOUT=${tmp_timeout} else warn_msg "'${x}' does not look like a valid time (second) value -- ignored!" fi unset tmp_timeout ;; gk.userinteraction.disabled=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then touch "${GK_USERINTERACTION_DISABLED_STATEFILE}" fi unset tmp_disabled ;; gk.preserverun.disabled=*) tmp_disabled=${x#*=} if is_true "${tmp_disabled}" then warn_msg "gk.preserverun.disabled is set; /run will not be moved to newroot!" GK_PRESERVE_RUN=0 fi unset tmp_disabled ;; gk.prompt.timeout=*) tmp_timeout=${x#*=} if is_int "${tmp_timeout}" then GK_PROMPT_TIMEOUT=${tmp_timeout} else warn_msg "'${x}' does not look like a valid time (second) value -- ignored!" fi unset tmp_timeout ;; real_rootflags=*) REAL_ROOTFLAGS=${x#*=} ;; rootflags=*) FAKE_ROOTFLAGS=${x#*=} ;; rootfstype=*) ROOTFSTYPE=${x#*=} ;; keymap=*) keymap=${x#*=} ;; locale=*) locale=${x#*=} ;; aufs) aufs=1 ;; aufs\=*) aufs=1 if echo "${x#*=}" | grep , &>/dev/null then aufs_dev_uid=${x#*,} aufs_dev=${x%,*} else aufs_dev=${x#*=} fi ;; # Allow user to specify the modules location aufs.modules\=*) aufs_modules_dir=${x#*=} aufs_modules=1 ;; overlayfs) overlayfs=1 ;; overlayfs\=*) overlayfs=1 if echo "${x#*=}" | grep , &>/dev/null then overlayfs_dev_uid=${x#*,} overlayfs_dev=${x%,*} else overlayfs_dev=${x#*=} fi ;; # Allow user to specify the modules location overlayfs.modules\=*) overlayfs_modules_dir=${x#*=} overlayfs_modules=1 ;; unionfs) if [ ! -x /sbin/unionfs ] then USE_UNIONFS_NORMAL=0 bad_msg 'unionfs binary not found: aborting use of unionfs!' else USE_UNIONFS_NORMAL=1 fi ;; nounionfs) USE_UNIONFS_NORMAL=0 ;; verify) VERIFY=1 ;; esac done # Prevent superfluous printks from being printed to the console echo ${GK_CONSOLE_LOGLEVEL} > /proc/sys/kernel/printk good_msg "${GK_META_VERSION} (${GK_META_BUILD_DATE}). Linux kernel ${KV}" if [ "${GK_BOOTFONT_DISABLED}" = '0' -a -e /lib/console/font ] then if echo "$(get_active_console)" | grep -qF ttyS then warn_msg "Active console is ${console}; Not loading embedded boot font ..." elif hash setfont >/dev/null 2>&1 then run setfont /lib/console/font -C ${CONSOLE} 2>&1 fi fi if [ "${CDROOT}" = '0' ] then if [ -z "${REAL_ROOT}" -a "${FAKE_ROOT}" != "/dev/ram0" ] then REAL_ROOT="${FAKE_ROOT}" fi if [ -z "${REAL_INIT}" -a "${FAKE_INIT}" != "/linuxrc" ] then REAL_INIT="${FAKE_INIT}" fi if [ -z "${REAL_ROOTFLAGS}" ] then REAL_ROOTFLAGS="${FAKE_ROOTFLAGS}" fi fi # Set variables based on the value of REAL_ROOT case "${REAL_ROOT}" in ZFS=*) ZFS_POOL=${REAL_ROOT#*=} ZFS_POOL=${ZFS_POOL%%/*} USE_ZFS=1 ;; ZFS) USE_ZFS=1 ;; esac # Verify that it is safe to use ZFS if [ "${USE_ZFS}" = '1' ] then for i in zfs zpool do if ! hash ${i} >/dev/null 2>&1 then USE_ZFS=0 bad_msg "Aborting use of ZFS because '${i}' not found!" break fi done unset i [ "${USE_ZFS}" = '1' ] && MY_HWOPTS="${MY_HWOPTS} zfs" fi if [ "${ROOTFSTYPE}" = "f2fs" ] then # Hack for f2fs, which uses crc32 but does not depend on it (in many kernels at least): FIRSTMODS="${FIRSTMODS} crc32_generic" fi if [ "${ROOTFSTYPE}" = "btrfs" -o -x /sbin/btrfs ] then # We have no mechanism to trigger btrfs module loading before UDEV's btrfs builtin # will run; In addition, loading btrfs via UDEV could cause problems for slow # machines, see https://github.com/dracutdevs/dracut/issues/658 FIRSTMODS="${FIRSTMODS} btrfs" fi splash 'init' cmdline_hwopts # Mount devfs mount_devfs # Mount sysfs mount_sysfs if [ -e /proc/sys/kernel/hotplug ] then log_msg "COMMAND: 'echo "" > /proc/sys/kernel/hotplug'" echo "" > /proc/sys/kernel/hotplug fi # Load modules listed in MY_HWOPTS if /lib/modules exists for the running kernel if [ -z "${DO_modules}" ] then good_msg 'Skipping module load; disabled via command-line' elif [ -d "/lib/modules/${KV}" ] then if [ -n "${FIRSTMODS}" ] then good_msg 'Loading first modules ...' # try these modules first -- detected modules for root device: modules_load firstmods ${FIRSTMODS} fi # Load appropriate kernel modules if [ "${GK_HW_USE_MODULES_LOAD}" = '1' ] then good_msg 'Loading modules ...' for modules in ${MY_HWOPTS} do modules_scan ${modules} done fi if [ -n "${MDOLIST}" ] then good_msg 'Loading modules from command-line ...' modules_load extra_load ${MDOLIST} fi else good_msg 'Skipping module load; no modules in the ramdisk!' fi # Run debug shell if requested run_debug_shell "before starting udevd" # Initialize udev if [ ! -f "/etc/udev/hwdb.bin" ] then good_msg 'Generating /etc/udev/hwdb.bin ...' run udevadm hwdb --update \ || bad_msg 'Failed to generate /etc/udev/hwdb.bin!' fi good_msg 'Activating udev ...' udevd_cmd="run udevd --resolve-names=never" if [ "${GK_UDEV_DEBUG}" = '1' ] then udevd_cmd="${udevd_cmd} --debug > ${GK_UDEV_LOG} 2>&1 &" else udevd_cmd="${udevd_cmd} --daemon" fi eval "${udevd_cmd}" if [ $? -eq 0 ] then run udevadm trigger --action=add udevsettle else bad_msg "udevd failed to run" fi cd / # Start iSCSI if hash iscsistart >/dev/null 2>&1 then start_iscsi fi # Loop file already exists on fs, assume no mount needed, # This allows for squashfs in initrd, which can be used for (i)PXE booting if [ -e "${LOOP}" ] then got_good_root=1 got_loop_wo_mount=1 CDROOT_PATH=$(dirname "${LOOP}") fi # Apply scan delay if specified sdelay # Scan volumes start_volumes setup_keymap if [ "${USE_SSH}" = '1' ] then start_network start_sshd fi # Initialize LUKS root device except for livecd's if [ "${CDROOT}" != '1' ] then start_LUKS if [ "${NORESUME}" != '1' ] && [ -n "${REAL_RESUME}" ] then case "${REAL_RESUME}" in LABEL=*|UUID=*|PARTLABEL=*|PARTUUID=*) RESUME_DEV="" retval=1 good_msg "Determining resume device (trying ${REAL_RESUME}) ..." if [ ${retval} -ne 0 ] then RESUME_DEV=$(findfs "${REAL_RESUME}" 2>/dev/null) retval=$? fi if [ ${retval} -ne 0 ] then RESUME_DEV=$(blkid -o device -l -t "${REAL_RESUME}" 2>/dev/null) retval=$? fi if [ ${retval} -eq 0 ] && [ -n "${RESUME_DEV}" ] then good_msg "Resume device detected as ${RESUME_DEV}!" REAL_RESUME="${RESUME_DEV}" fi ;; esac do_resume fi fi run mkdir -p "${NEW_ROOT}" CHROOT="${NEW_ROOT}" # Run debug shell if requested run_debug_shell "before setting up the root filesystem" if [ "${CDROOT}" = '1' ] then # Setup the root filesystem bootstrapFS if [ "${aufs}" = '1' ] then setup_aufs CHROOT=${aufs_union} elif [ "${overlayfs}" = '1' ] && [ "${got_good_root}" != '1' ] then bootstrapCD CHROOT=${NEW_ROOT} fi if [ "${got_good_root}" != '1' ] && [ /dev/nfs != "${REAL_ROOT}" ] && [ sgimips != "${LOOPTYPE}" ] && [ 1 != "${aufs}" ] && [ 1 != "${overlayfs}" ] then bootstrapCD fi if [ "${REAL_ROOT}" = '' ] && [ "${got_good_root}" != '1' ] then warn_msg "No bootable medium found. Waiting for new devices ..." COUNTER=0 while [ ${COUNTER} -lt 3 ] do sleep 3 let COUNTER=${COUNTER}+1 done sleep 1 bootstrapCD fi if [ "${REAL_ROOT}" = '' ] && [ "${got_good_root}" != '1' ] then # Undo stuff run umount "${NEW_ROOT}/dev" 2>/dev/null run umount "${NEW_ROOT}/sys" 2>/dev/null run umount /sys 2>/dev/null run umount "${NEW_ROOT}" run rm -rf "${NEW_ROOT}/*" bad_msg 'Could not find CD to boot, something else needed!' CDROOT=0 fi fi # Determine root device let ROOTDELAY_TIMEOUT=$(date +%s)+1 ROOTDELAY_TIME_WAITED=0 [ -n "${ROOTDELAY}" -a ${ROOTDELAY} -gt 0 ] && let ROOTDELAY_TIMEOUT=${ROOTDELAY_TIMEOUT}+${ROOTDELAY}-1 while true do good_msg_n "Determining root device (trying ${REAL_ROOT}) ..." while [ "${got_good_root}" != '1' ] do # Start of sleep loop waiting on root while [ "${got_good_root}" != '1' -a $(date +%s) -le ${ROOTDELAY_TIMEOUT} ] do case "${REAL_ROOT}" in LABEL=*|UUID=*|PARTLABEL=*|PARTUUID=*) ROOT_DEV="" retval=1 if [ ${retval} -ne 0 ] then ROOT_DEV=$(findfs "${REAL_ROOT}" 2>/dev/null) retval=$? fi if [ ${retval} -ne 0 ] then ROOT_DEV=$(blkid -o device -l -t "${REAL_ROOT}" 2>/dev/null) retval=$? fi if [ ${retval} -eq 0 ] && [ -n "${ROOT_DEV}" ] then got_good_root=1 REAL_ROOT="${ROOT_DEV}" echo good_msg "Root device detected as ${REAL_ROOT}!" break fi ;; ZFS*) if [ "${USE_ZFS}" = '0' ] then bad_msg "Cannot use ZFS when started without 'dozfs' kernel command-line parameter!" break fi ROOT_DEV="${REAL_ROOT#*=}" if [ "${ROOT_DEV}" != 'ZFS' ] then if [ "$(get_zfs_property "${ROOT_DEV}" type)" = 'filesystem' ] then got_good_root=1 REAL_ROOT=${ROOT_DEV} ROOTFSTYPE=zfs echo good_msg "Root device detected as ${REAL_ROOT}!" break else bad_msg "${ROOT_DEV} is not a filesystem" continue fi else BOOTFS=$(zpool list -H -o bootfs 2>/dev/null) if [ "${BOOTFS}" != '-' ] then for i in ${BOOTFS} do zfs get type ${i} > /dev/null 2>&1 if [ $? -eq 0 ] then got_good_root=1 REAL_ROOT=${i} ROOTFSTYPE=zfs echo good_msg "Root device detected as ${REAL_ROOT}!" break fi done fi fi ;; *) ROOT_DEV=$(readlink -f "${REAL_ROOT}") if [ -b "${ROOT_DEV}" ] then got_good_root=1 REAL_ROOT=${ROOT_DEV} echo good_msg "Root device detected as ${REAL_ROOT}!" break fi ;; esac unset ROOT_DEV if [ "${got_good_root}" != '1' ] then let ROOTDELAY_TIME_WAITED=${ROOTDELAY_TIME_WAITED}+1 sleep 0.1s let ROOTDELAY_100MSEC_MODULO=${ROOTDELAY_TIME_WAITED}%10 if [ ${ROOTDELAY_100MSEC_MODULO} = 0 ] then printf "." fi fi done # End of sleep loop waiting on root if [ $(date +%s) -gt ${ROOTDELAY_TIMEOUT} ] then echo fi if [ "${USE_ZFS}" = '1' ] then write_env_file \ "${ZFS_ENC_ENV_FILE}" \ REAL_ROOT \ ROOTFSTYPE fi # Check for a block device or /dev/nfs or zfs encryption if [ -n "${REAL_ROOT}" ] && [ "${REAL_ROOT}" = "/dev/nfs" ] || [ "${ROOTFSTYPE}" = "zfs" ] || [ -b "${REAL_ROOT}" ] then if [ "${ROOTFSTYPE}" = "zfs" ] then # at this point we determined dataset and are ready to mount # let's check if this dataset is encrypted and ask for passphrase if [ "$(zpool list -H -o feature@encryption "${REAL_ROOT%%/*}" 2>/dev/null)" = 'active' ] then ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)" ZFS_ENCRYPTIONROOT="$(get_zfs_property "${REAL_ROOT}" encryptionroot)" if [ "${ZFS_ENCRYPTIONROOT}" != '-' ] && [ "${ZFS_KEYSTATUS}" = 'unavailable' ] then good_msg "Detected ZFS encryption, asking for key" run zfs load-key "${ZFS_ENCRYPTIONROOT}" # Get new key status to check if load-key was successful # or dataset has been opened by someone else in the meantime (through SSH for instance) ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)" if [ "${ZFS_KEYSTATUS}" != 'available' ] then bad_msg "${REAL_ROOT} is encrypted and not mountable without key" got_good_root=0 break fi if [ -f "${ZFS_ENC_OPENED_LOCKFILE}" ] then good_msg "${REAL_ROOT} device meanwhile was opened by someone else." else run touch "${ZFS_ENC_OPENED_LOCKFILE}" fi fi fi else got_good_root=1 fi fi break done if [ "${got_good_root}" = '1' -a "${CDROOT}" = 1 -a "${REAL_ROOT}" != "/dev/nfs" ] then # CD already mounted; no further checks necessary break elif [ "${got_good_root}" = '1' -a "${LOOPTYPE}" = 'sgimips' ] then # sgimips mounts the livecd root partition directly # there is no isofs filesystem to worry about break elif [ "${got_good_root}" = '1' ] then good_msg "Mounting ${REAL_ROOT} as root ..." if [ "${ROOTFSTYPE}" = 'zfs' ] then if [ "$(get_zfs_property "${REAL_ROOT}" mountpoint)" = 'legacy' ] then MOUNT_STATE=rw else MOUNT_STATE=rw,zfsutil fi else MOUNT_STATE=ro fi # Try to mount the device as ${NEW_ROOT} if [ "${REAL_ROOT}" = '/dev/nfs' ] then findnfsmount mountret=$? else # If $REAL_ROOT is a symlink # Resolve it like util-linux mount does [ -L ${REAL_ROOT} ] && REAL_ROOT=$(readlink -f ${REAL_ROOT}) # determine fs -- 'auto' will not trigger module loading! ROOTFSTYPE=$(determine_fs "${REAL_ROOT}" "${ROOTFSTYPE}") # mount ro so fsck doesn't barf later if [ "${REAL_ROOTFLAGS}" = '' ] then good_msg "Using mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE} ${REAL_ROOT} ${NEW_ROOT}" run mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE} ${REAL_ROOT} ${NEW_ROOT} mountret=$? else good_msg "Using mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE},${REAL_ROOTFLAGS} ${REAL_ROOT} ${NEW_ROOT}" run mount -t ${ROOTFSTYPE} -o ${MOUNT_STATE},${REAL_ROOTFLAGS} ${REAL_ROOT} ${NEW_ROOT} mountret=$? fi fi # If mount is successful break out of the loop # else not a good root and start over. if [ "${mountret}" = '0' ] then # Make sure that entries from $NEWROOT/etc/initramfs.mounts # are mounted before validating $REAL_INIT in case init isn't # located on $REAL_ROOT. process_initramfs_mounts init_binary_file="${NEW_ROOT}${REAL_INIT:-/sbin/init}" init_binary_fallback_file="${NEW_ROOT}/bin/sh" if [ -f "${init_binary_file}" -a -x "${init_binary_file}" ] then break else warn_msg "'${init_binary_file}' was not found, is not a file or is not executable, maybe a symlink?" fi if [ -L "${init_binary_file}" ] then good_msg "Symlink detected! Assuming split /usr ..." break else warn_msg "'${init_binary_file}' is not a symlink, do we have at least /bin/sh?" fi if [ -f "${init_binary_fallback_file}" -a -x "${init_binary_fallback_file}" ] then REAL_INIT="${init_binary_fallback_file/${NEW_ROOT}}" good_msg "Executable fallback file '${init_binary_fallback_file}' detected!" break else warn_msg "'${init_binary_fallback_file}' was not found, is not a file or is not executable, maybe we are working with NFS?" fi if [ "${REAL_ROOT}" = "/dev/nfs" ] then good_msg "NFS detected!" break else warn_msg "No NFS detected!" fi bad_msg "The filesystem mounted at ${REAL_ROOT} does not appear to be a valid /:" bad_msg "Neither executable file '${init_binary_file}' nor '${init_binary_fallback_file}' was found." bad_msg "If correct root device was specified, check 'root' or 'init' kernel command-line parameter!" got_good_root=0 else bad_msg "Could not mount specified ROOT!" got_good_root=0 fi fi if [ "${got_good_root}" = '0' ] then if mountpoint "${NEW_ROOT}" 1>/dev/null 2>&1 then run umount "${NEW_ROOT}" 1>/dev/null 2>&1 if [ $? -ne 0 ] then echo bad_msg "Failed to umount ${REAL_ROOT} which was mounted as ${NEW_ROOT}!" warn_msg "You probably need to open a shell and restore mountpoint before you are able to mount another device as ${NEW_ROOT}." echo fi fi bad_msg "Block device ${REAL_ROOT} is not a valid root device ..." prompt_user "REAL_ROOT" "root block device" ROOTDELAY_TIME_WAITED=0 let ROOTDELAY_TIMEOUT=$(date +%s)+1 fi done # End determine root device # If CD root is set determine the looptype to boot if [ "${CDROOT}" = '1' ] then good_msg 'Determining looptype ...' cd "${NEW_ROOT}" # Find loop and looptype [ -z "${LOOP}" ] && find_loop [ -z "${LOOPTYPE}" ] && find_looptype cache_cd_contents # If encrypted, find key and mount, otherwise mount as usual if [ -n "${CRYPT_ROOT}" ] then CRYPT_ROOT_KEY="$(head -n 1 "${CDROOT_PATH}"/${CDROOT_MARKER})" CRYPT_ROOT='/dev/loop0' good_msg 'You booted an encrypted livecd' ${CRYPT_SILENT} losetup /dev/loop0 "${CDROOT_PATH}/${LOOPEXT}${LOOP}" test_success 'Preparing loop filesystem' start_LUKS case ${LOOPTYPE} in normal) MOUNTTYPE="ext2" ;; *) MOUNTTYPE=$(determine_fs "/dev/mapper/root" "${MOUNTTYPE}") ;; esac run mount -t "${MOUNTTYPE}" -o ro /dev/mapper/root "${NEW_ROOT}/mnt/livecd" test_success 'Mount filesystem' FS_LOCATION='mnt/livecd' # Setup the loopback mounts, if unencrypted else # if [ -n "${CRYPT_ROOT}" ] if [ "${LOOPTYPE}" = 'normal' ] then good_msg 'Mounting loop filesystem' run mount -t ext2 -o loop,ro "${CDROOT_PATH}/${LOOPEXT}${LOOP}" "${NEW_ROOT}/mnt/livecd" test_success 'Mount filesystem' FS_LOCATION='mnt/livecd' elif [ "${LOOPTYPE}" = 'squashfs' ] then good_msg 'Mounting squashfs filesystem' if [ "${aufs}" = '1' ] then setup_squashfs_aufs test_success 'Mount aufs filesystem' elif [ "${overlayfs}" = '1' ] then setup_overlayfs test_success 'Mount overlayfs filesystem' else _CACHED_SQUASHFS_PATH="${NEW_ROOT}/mnt/${LOOP}" _squashfs_path="${CDROOT_PATH}/${LOOPEXT}${LOOP}" # Default to uncached # Upgrade to cached version if possible [ "${DO_cache}" -a -f "${_CACHED_SQUASHFS_PATH}" ] \ && _squashfs_path=${_CACHED_SQUASHFS_PATH} mount -t squashfs -o loop,ro "${_squashfs_path}" "${NEW_ROOT}/mnt/livecd" || { bad_msg "Squashfs filesystem could not be mounted, dropping into shell." if [ -e /proc/filesystems ] then grep -Fq squashfs /proc/filesystems || \ bad_msg "HINT: Your kernel does not know filesystem \"squashfs\"." fi run_emergency_shell } fi FS_LOCATION='mnt/livecd' elif [ "${LOOPTYPE}" = 'gcloop' ] then good_msg 'Mounting gcloop filesystem' echo ' ' | losetup -E 19 -e ucl-0 -p0 "${NEW_ROOT}/dev/loop0" "${CDROOT_PATH}/${LOOPEXT}${LOOP}" test_success 'losetup the loop device' run mount -t ext2 -o ro "${NEW_ROOT}/dev/loop0" "${NEW_ROOT}/mnt/livecd" test_success 'Mount the losetup loop device' FS_LOCATION='mnt/livecd' elif [ "${LOOPTYPE}" = 'zisofs' ] then FS_LOCATION="${CDROOT_PATH/\/}/${LOOPEXT}${LOOP}" elif [ "${LOOPTYPE}" = 'noloop' ] then FS_LOCATION="${CDROOT_PATH/\/}" elif [ "${LOOPTYPE}" = 'sgimips' ] then # getdvhoff finds the starting offset (in bytes) of the squashfs # partition on the cdrom and returns this offset for losetup # # All currently supported SGI Systems use SCSI CD-ROMs, so # so we know that the CD-ROM is usually going to be /dev/sr0. # # We use the value given to losetup to set /dev/loop0 to point # to the liveCD root partition, and then mount /dev/loop0 as # the LiveCD rootfs good_msg 'Locating the SGI LiveCD Root Partition' echo ' ' | \ losetup -o $(getdvhoff "${NEW_ROOT}${REAL_ROOT}" 0) \ "${NEW_ROOT}${CDROOT_DEV}" \ "${NEW_ROOT}${REAL_ROOT}" test_success 'losetup /dev/sr0 /dev/loop0' good_msg 'Mounting the Root Partition' run mount -t squashfs -o ro "${NEW_ROOT}${CDROOT_DEV}" "${NEW_ROOT}/mnt/livecd" test_success 'mount /dev/loop0 /' FS_LOCATION='mnt/livecd' fi fi # if [ -n "${CRYPT_ROOT}" ] if [ "${aufs}" = '1' ] then aufs_insert_dir "${CHROOT}" "${aufs_ro_branch}" # Function to handle the RC_NO_UMOUNTS variable in $CHROOT/etc/rc.conf conf_rc_no_umounts # Fstab changes for aufs if ! grep -q '^aufs' "${CHROOT}/etc/fstab" 2>/dev/null then for dir in /var/tmp /tmp do [ ! -d ${CHROOT}${dir} ] && run mkdir -p "${CHROOT}${dir}" done cat > "${CHROOT}/etc/fstab" << FSTAB #################################################### ## ATTENTION: THIS IS THE FSTAB ON THE LIVECD ## ## PLEASE EDIT THE FSTAB at /mnt/gentoo/etc/fstab ## #################################################### aufs / aufs defaults 0 0 vartmp /var/tmp tmpfs defaults 0 0 tmp /tmp tmpfs defaults 0 0 FSTAB fi # Check modules support is_union_modules aufs # Create the directories for our new union mounts [ ! -d ${CHROOT}${NEW_ROOT} ] && mkdir -p "${CHROOT}${NEW_ROOT}" # Check to see if we successfully mounted $aufs_dev if [ -n "${aufs_dev}" ] && grep ${aufs_dev} /etc/mtab 1>/dev/null then [ ! -d ${CHROOT}${aufs_dev_mnt} ] && run mkdir -p "${CHROOT}${aufs_dev_mnt}" run mount --move "${aufs_dev_mnt}" "${CHROOT}${aufs_dev_mnt}" fi fi # Unpacking additional packages from NFS mount, or root (if squashfs was found there) # This is useful for adding kernel modules to /lib # We do this now, so that additional packages can add whereever they want. if [ "${REAL_ROOT}" = '/dev/nfs' ] || [ "${got_loop_wo_mount}" = '1' ] then if [ -e "${CDROOT_PATH}/add" ] then # shellcheck disable=SC2045 for targz in $(ls ${CDROOT_PATH}/add/*.tar.gz) do tarname=$(basename ${targz}) good_msg "Adding additional package ${tarname}" (cd ${NEW_ROOT} ; tar -xf ${targz}) done fi fi if [ "${USE_UNIONFS_NORMAL}" = '1' ] then setup_unionfs ${NEW_ROOT} /${FS_LOCATION} CHROOT=/union elif [ "${aufs}" != '1' ] && [ "${overlayfs}" != '1' ] then good_msg "Copying read-write image contents to tmpfs" # Copy over stuff that should be writable ( cd "${NEW_ROOT}/${FS_LOCATION}" cp -a ${ROOT_TREES} "${NEW_ROOT}" ) || { bad_msg "Copying failed, dropping into a shell." run_emergency_shell } # Now we do the links. for x in ${ROOT_LINKS} do if [ -L "${NEW_ROOT}/${FS_LOCATION}/${x}" ] then ln -s "$(readlink ${NEW_ROOT}/${FS_LOCATION}/${x})" "${x}" 2>/dev/null else # List all subdirectories of x find "${NEW_ROOT}/${FS_LOCATION}/${x}" -type d 2>/dev/null | while read directory do # Strip the prefix of the FS_LOCATION directory="${directory#${NEW_ROOT}/${FS_LOCATION}/}" # Skip this directory if we already linked a parent directory if [ "${current_parent}" != '' ] then var=$(echo "${directory}" | grep "^${current_parent}") if [ "${var}" != '' ] then continue fi fi # Test if the directory exists already if [ -e "/${NEW_ROOT}/${directory}" ] then # It does exist, link all the individual files # shellcheck disable=SC2045 for file in $(ls /${NEW_ROOT}/${FS_LOCATION}/${directory}) do if [ ! -d "/${NEW_ROOT}/${FS_LOCATION}/${directory}/${file}" ] && [ ! -e "${NEW_ROOT}/${directory}/${file}" ] then ln -s "/${FS_LOCATION}/${directory}/${file}" "${directory}/${file}" 2> /dev/null fi done else # It does not exist, make a link to the livecd ln -s "/${FS_LOCATION}/${directory}" "${directory}" 2>/dev/null current_parent="${directory}" fi done fi done mkdir -p initramfs proc tmp run sys 2>/dev/null chmod 1777 tmp fi # Have handy /mnt/cdrom (CDROOT_PATH) as well if [ "${aufs}" = '1' ] then [ ! -d "${CHROOT}${CDROOT_PATH}" ] && mkdir "${CHROOT}${CDROOT_PATH}" run mount --move "${CDROOT_PATH}" "${CHROOT}${CDROOT_PATH}" else [ ! -d "${NEW_ROOT}${CDROOT_PATH}" ] && mkdir -p "${NEW_ROOT}${CDROOT_PATH}" run mount --move "${CDROOT_PATH}" "${NEW_ROOT}${CDROOT_PATH}" fi # Let Init scripts know that we booted from CD export CDBOOT CDBOOT=1 else if [ "${USE_UNIONFS_NORMAL}" = '1' ] then run mkdir /union_changes run mount -t tmpfs tmpfs /union_changes setup_unionfs /union_changes ${NEW_ROOT} run mkdir -p ${UNION}/tmp/.initrd elif [ "${aufs}" = '1' ] then aufs_insert_dir "${aufs_union}" "${NEW_ROOT}" run mkdir -p "${aufs_union}/tmp/.initrd" fi fi # if [ "${CDROOT}" = '1' ] # Re-run to ensure $NEWROOT/etc/initramfs.mounts was processed at least once process_initramfs_mounts # Execute script on the cdrom just before boot to update things if necessary cdupdate if [ "${SUBDIR}" != '' -a -e "${CHROOT}/${SUBDIR}" ] then good_msg "Entering ${SUBDIR} to boot" CHROOT="${CHROOT}/${SUBDIR}" fi if [ "${aufs}" = '1' ] then aufs_union_memory=${CHROOT}/.unions/memory run mkdir -p "${aufs_union_memory}" run mount --move "${aufs_memory}" "${aufs_union_memory}" test_success "Failed to move aufs ${aufs_memory} into the system root" for dir in /mnt/gentoo ${aufs_rw_branch} ${aufs_ro_branch} do run mkdir -p "${CHROOT}${dir}" run chmod 755 "${CHROOT}${dir}" done for mount in ${aufs_rw_branch} ${aufs_ro_branch} do run mount --move "${mount}" "${CHROOT}${mount}" done fi # Copy user keymap generated file if available copyKeymap # Setup any user defined environment locales for desktop usage setup_locale if [ "${USE_SSH}" = '1' ] then wait_sshd fi cleanup udevsettle run udevadm control --exit if pgrep udevd >/dev/null 2>&1 then warn_msg "udevd is still running -- Trying to kill it ..." run pkill -9 udevd >/dev/null 2>&1 fi # Run debug shell if requested run_debug_shell "before switch_root" if [ "${GK_PRESERVE_RUN}" = '0' ] then GK_INIT_LOG= run umount /run fi # init_opts is set in the environment by the kernel when it parses the command line init=${REAL_INIT:-/sbin/init} while true do # switch_root can only be called from PID 1; # So stay in loop as long as user is able # to fix the problem. if ! mountpoint "${CHROOT}" 1>/dev/null 2>&1 then bad_msg "${CHROOT} is not a mountpoint; Was root device (${REAL_ROOT}) not mounted?" elif ! chroot "${CHROOT}" test -x /${init#/} 1>/dev/null 2>&1 then mounted_root_device=$(mountpoint -n /newroot 2>/dev/null | awk '{ print $1 }') bad_msg "init (${init}) not found in mounted root device (${mounted_root_device})!" else break fi run_emergency_shell if ! is_userinteraction_allowed then ${GK_EMERGENCY_ACTION} || exit 1 fi done if [[ "${CONSOLE_LOGLEVEL}" != "${GK_CONSOLE_LOGLEVEL}" ]] then good_msg "Restoring console log level (${CONSOLE_LOGLEVEL}) ..." echo ${CONSOLE_LOGLEVEL} > /proc/sys/kernel/printk \ && log_msg "COMMAND: 'echo \"${CONSOLE_LOGLEVEL}\" > /proc/sys/kernel/printk'" fi good_msg "Switching to real root: switch_root ${CHROOT} ${init} ${init_opts}" exec switch_root "${CHROOT}" "${init}" ${init_opts} # If we reached here, something went very badly wrong in the initramfs. # However, spawning a rescue shell at this point would not help anymore: # 1) We have to assume that switch_root has already messed with # initramfs (i.e. we probably have no /dev anymore). # 2) Any shell we would spawn would become child of PID 1 which would # prevent user from calling switch_root once the user believes the # problem was fixed. ${GK_EMERGENCY_ACTION} || exit 1