| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- # -*- shell-script -*-
- _log_msg()
- {
- if [ "$quiet" = "y" ]; then return; fi
- printf "$@"
- }
- log_success_msg()
- {
- _log_msg "Success: $@\n"
- }
- log_failure_msg()
- {
- _log_msg "Failure: $@\n"
- }
- log_warning_msg()
- {
- _log_msg "Warning: $@\n"
- }
- log_begin_msg()
- {
- _log_msg "Begin: $@ ... "
- }
- log_end_msg()
- {
- _log_msg "done.\n"
- }
- # Add failure hook
- add_mountroot_fail_hook()
- {
- mkdir -p /tmp/mountroot-fail-hooks.d
- ln -s "$0" /tmp/mountroot-fail-hooks.d/"$1"
- }
- # Run failure hooks.
- # When a failure hook exits "1", it has not done anything to correct the
- # system. Exiting "0" means that something has been attempted to resolve
- # the lack of a root filesystem.
- # Hooks are run in lexigraphical order, and are responsible for removing
- # themselves if they should not re-run in a later cycle. When one exits
- # "0", the stack is stopped, so the caller can return to the main rootfs
- # wait loop.
- try_failure_hooks()
- {
- local hook
- # Disable usplash so text from hooks can be seen
- if [ -x /sbin/usplash_write ]; then
- /sbin/usplash_write "QUIT"
- fi
- chvt 1
- if [ -x /bin/plymouth ] && plymouth --ping; then
- /bin/plymouth hide-splash > /dev/null 2>&1
- fi
- for hook in /tmp/mountroot-fail-hooks.d/*; do
- if [ -x ${hook} ] && ${hook} mountfail; then
- return 0
- fi
- done
- return 1
- }
- panic()
- {
- if command -v chvt >/dev/null 2>&1; then
- chvt 1
- fi
- echo "$@"
- # Disallow console access
- if [ -n "${panic}" ]; then
- echo "Rebooting automatically due to panic= boot argument"
- sleep ${panic}
- reboot
- exit # in case reboot fails, force kernel panic
- fi
- modprobe -v i8042 || true
- modprobe -v atkbd || true
- modprobe -v ehci-pci || true
- modprobe -v ehci-orion || true
- modprobe -v ehci-hcd || true
- modprobe -v uhci-hcd || true
- modprobe -v ohci-hcd || true
- modprobe -v usbhid || true
- run_scripts /scripts/panic
- REASON="$@" PS1='(initramfs) ' /bin/sh -i </dev/console >/dev/console 2>&1
- }
- maybe_break()
- {
- case ",$break," in
- *,$1,*)
- panic "Spawning shell within the initramfs"
- ;;
- esac
- }
- render()
- {
- eval "echo -n \${$@}"
- }
- # For boot time only; this is overridden at build time in hook-functions
- run_scripts()
- {
- initdir=${1}
- [ ! -d ${initdir} ] && return
- shift
- . ${initdir}/ORDER
- }
- # Load custom modules first
- load_modules()
- {
- if [ -e /conf/modules ]; then
- cat /conf/modules | while read m; do
- # Skip empty lines
- if [ -z "$m" ]; then
- continue
- fi
- # Skip comments - d?ash removes whitespace prefix
- com=$(printf "%.1s" "${m}")
- if [ "$com" = "#" ]; then
- continue
- fi
- modprobe $m
- done
- fi
- }
- # lilo compatibility
- parse_numeric() {
- case $1 in
- *:*)
- # Does it match /[0-9]*:[0-9]*/?
- minor=${1#*:}
- major=${1%:*}
- case $major$minor in
- *[!0-9]*)
- # No.
- return
- ;;
- esac
- ;;
- "" | *[!A-Fa-f0-9]*)
- # "", "/*", etc.
- return
- ;;
- *)
- # [A-Fa-f0-9]*
- value=$(( 0x${1} ))
- minor=$(( (${value} & 0xff) | (${value} >> 12) & 0xfff00 ))
- major=$(( (${value} >> 8) & 0xfff ))
- ;;
- esac
- ROOT="$(readlink -f /dev/block/${major}:${minor})"
- }
- # Parameter: device node to check
- # Echos fstype to stdout
- # Return value: indicates if an fs could be recognized
- get_fstype ()
- {
- local FS FSTYPE FSSIZE RET
- FS="${1}"
- # blkid has a more complete list of file systems,
- # but fstype is more robust
- FSTYPE="unknown"
- eval $(fstype "${FS}" 2> /dev/null)
- if [ "$FSTYPE" = "unknown" ] && command -v blkid >/dev/null 2>&1 ; then
- FSTYPE=$(blkid -o value -s TYPE "${FS}")
- elif [ "$FSTYPE" = "unknown" ] && [ -x /lib/udev/vol_id ]; then
- FSTYPE=$(/lib/udev/vol_id -t "${FS}" 2> /dev/null)
- fi
- RET=$?
- if [ -z "${FSTYPE}" ]; then
- FSTYPE="unknown"
- fi
- echo "${FSTYPE}"
- return ${RET}
- }
- configure_networking()
- {
- if [ -n "${BOOTIF}" ]; then
- # pxelinux sets BOOTIF to a value based on the mac address of the
- # network card used to PXE boot, so use this value for DEVICE rather
- # than a hard-coded device name from initramfs.conf. this facilitates
- # network booting when machines may have multiple network cards.
- # pxelinux sets BOOTIF to 01-$mac_address
- # strip off the leading "01-", which isn't part of the mac
- # address
- temp_mac=${BOOTIF#*-}
- # convert to typical mac address format by replacing "-" with ":"
- bootif_mac=""
- IFS='-'
- for x in $temp_mac ; do
- if [ -z "$bootif_mac" ]; then
- bootif_mac="$x"
- else
- bootif_mac="$bootif_mac:$x"
- fi
- done
- unset IFS
- # look for devices with matching mac address, and set DEVICE to
- # appropriate value if match is found.
- for device in /sys/class/net/* ; do
- if [ -f "$device/address" ]; then
- current_mac=$(cat "$device/address")
- if [ "$bootif_mac" = "$current_mac" ]; then
- DEVICE=${device##*/}
- break
- fi
- fi
- done
- fi
- # networking already configured thus bail out
- [ -n "${DEVICE}" ] && [ -e /run/net-"${DEVICE}".conf ] && return 0
- wait_for_udev 10
- # support ip options see linux sources
- # Documentation/filesystems/nfs/nfsroot.txt
- # Documentation/frv/booting.txt
- for ROUNDTTT in 2 3 4 6 9 16 25 36 64 100; do
- # The NIC is to be configured if this file does not exist.
- # Ip-Config tries to create this file and when it succeds
- # creating the file, ipconfig is not run again.
- for x in /run/net-"${DEVICE}".conf /run/net-*.conf ; do
- [ -e "$x" ] && break 2
- done
- case ${IP} in
- none|off)
- # Do nothing
- ;;
- ""|on|any)
- # Bring up device
- ipconfig -t ${ROUNDTTT} "${DEVICE}"
- ;;
- dhcp|bootp|rarp|both)
- ipconfig -t ${ROUNDTTT} -c ${IP} -d "${DEVICE}"
- ;;
- *)
- ipconfig -t ${ROUNDTTT} -d $IP
- # grab device entry from ip option
- NEW_DEVICE=${IP#*:*:*:*:*:*}
- if [ "${NEW_DEVICE}" != "${IP}" ]; then
- NEW_DEVICE=${NEW_DEVICE%%:*}
- else
- # wrong parse, possibly only a partial string
- NEW_DEVICE=
- fi
- if [ -n "${NEW_DEVICE}" ]; then
- DEVICE="${NEW_DEVICE}"
- fi
- ;;
- esac
- done
- # source ipconfig output
- if [ -n "${DEVICE}" ]; then
- # source specific bootdevice
- . /run/net-${DEVICE}.conf
- else
- # source any interface...
- # ipconfig should have quit after first response
- . /run/net-*.conf
- fi
- }
- # Wait for queued kernel/udev events
- wait_for_udev()
- {
- command -v udevadm >/dev/null 2>&1 || return 0
- udevadm settle ${1:+--timeout=$1}
- }
- # Find a specific fstab entry
- # $1=mountpoint
- # $2=fstype (optional)
- # returns 0 on success, 1 on failure (not found or no fstab)
- read_fstab_entry() {
- # Not found by default.
- found=1
- for file in ${rootmnt}/etc/fstab; do
- if [ -f "$file" ]; then
- while read MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK; do
- case "$MNT_FSNAME" in
- ""|\#*)
- continue;
- ;;
- esac
- if [ "$MNT_DIR" = "$1" ]; then
- if [ -n "$2" ]; then
- [ "$MNT_TYPE" = "$2" ] || continue;
- fi
- found=0
- break 2
- fi
- done < "$file"
- fi
- done
- return $found
- }
- # Resolve device node from a name. This expands any LABEL or UUID.
- # $1=name
- # Resolved name is echoed.
- resolve_device() {
- DEV="$1"
- local orig="$DEV"
- case "$DEV" in
- LABEL=* | UUID=* | PARTLABEL=* | PARTUUID=*)
- if command -v blkid >/dev/null 2>&1; then
- DEV="$(blkid -l -t "$DEV" -o device)"
- if [ "$?" != 0 ]; then
- DEV="$orig"
- # Support uppercase and lowercase UUIDs -- see RFC#4122:
- # "Each field is treated as an integer and has its value printed as
- # a zero-filled hexadecimal digit string with the most significant
- # digit first. The hexadecimal values "a" through "f" are output as
- # lower case characters and are case insensitive on input."
- #
- # Note: that blkid which we will use to map these assums the input is lower
- # case.
- # Only apply this behaviour to UUIDs.
- case "$DEV" in
- UUID=* | PARTUUID=*) ;;
- *) return 1 ;;
- esac
- # Pull DEV appart and map it.
- local type=$(echo ${DEV} | cut -f 1 -d =)
- local value=$(echo ${DEV} | cut -f 2 -d = | tr '[A-F]' '[a-f]')
- # ... in RFC#4122 format;
- # look for five hexadecimal fragments separated by minus signs.
- local fmt=$( echo "$value" | sed -e 's/[0-9a-fA-F]*//g' )
- if [ "$fmt" != '----' ]; then
- return 1
- fi
- DEV="${type}=${value}"
- # Retry with the lower cased UUID.
- DEV="$(blkid -l -t "$DEV" -o device)" || return 1
- fi
- else
- log_warning_msg "blkid not present, so cannot resolve $DEV"
- return 1
- fi
- ;;
- esac
- [ -e "$DEV" ] && echo "$DEV"
- }
- # Check a file system.
- # $1=device
- # $2=mountpoint (for diagnostics only)
- _checkfs_once()
- {
- DEV="$1"
- NAME="$2"
- if [ "$NAME" = "/" ] ; then
- NAME="root"
- fi
- FSCK_LOGFILE=/run/initramfs/fsck.log
- FSCK_STAMPFILE=/run/initramfs/fsck-${NAME#/}
- TYPE=$(get_fstype "$1")
- FSCKCODE=0
- if ! command -v fsck >/dev/null 2>&1; then
- log_warning_msg "fsck not present, so skipping $NAME file system"
- return
- fi
- if [ "$fastboot" = "y" ] ; then
- log_warning_msg "Fast boot enabled, so skipping $NAME file system check."
- return
- fi
- if [ "$forcefsck" = "y" ]
- then
- force="-f"
- else
- force=""
- fi
- if [ "$fsckfix" = "y" ]
- then
- fix="-y"
- elif [ "$fsckfix" = "n" ]
- then
- fix="-n"
- else
- fix="-a"
- fi
- spinner=""
- if [ -z "${debug}" ]; then
- spinner="-C"
- fi
- if [ "${quiet}" = n ]
- then
- log_begin_msg "Will now check $NAME file system"
- logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $TYPE $DEV
- FSCKCODE=$?
- log_end_msg
- else
- log_begin_msg "Checking $NAME file system"
- logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -T -t $TYPE $DEV
- FSCKCODE=$?
- log_end_msg
- fi
- # NOTE: "failure" is defined as exiting with a return code of
- # 4, possibly or-ed with other flags. A return code of 1
- # indicates that file system errors were corrected but that
- # the boot may proceed.
- #
- if [ "$FSCKCODE" -eq 32 ]
- then
- log_warning_msg "File system check was interrupted by user"
- elif [ $((FSCKCODE & 4)) -eq 4 ]
- then
- log_failure_msg "File system check of the $NAME filesystem failed"
- return 1
- elif [ "$FSCKCODE" -gt 1 ]
- then
- log_warning_msg "File system check failed but did not detect errors"
- sleep 5
- else
- > $FSCK_STAMPFILE
- fi
- return 0
- }
- checkfs()
- {
- while ! _checkfs_once "$@"; do
- panic "The $2 filesystem on $1 requires a manual fsck"
- done
- }
- # Mount a file system. We parse the information from the fstab. This
- # should be overridden by any boot script which can mount arbitrary
- # filesystems such as /usr. This default implementation delegates to
- # local or nfs based upon the filesystem type.
- # $1=mountpoint mount location
- mountfs()
- {
- type=local
- read_fstab_entry "$1"
- if [ "${MNT_TYPE}" = "nfs" ] || [ "${MNT_TYPE}" = "nfs4" ]; then
- type=nfs
- fi
- ${type}_mount_fs "$1"
- }
- # Mount the root file system. It should be overridden by all
- # boot scripts.
- mountroot()
- {
- :
- }
- # Run /scripts/${boot}-top. This should be overridden by all boot
- # scripts.
- mount_top()
- {
- :
- }
- # Run /scripts/${boot}-premount. This should be overridden by all boot
- # scripts.
- mount_premount()
- {
- :
- }
- # Run /scripts/${boot}-bottom. This should be overridden by all boot
- # scripts.
- mount_bottom()
- {
- :
- }
|