| #!/bin/sh |
| # |
| # Licensed under the GPLv2 |
| # |
| # Copyright 2008, Red Hat, Inc. |
| # Jeremy Katz <katzj@redhat.com> |
| |
| emergency_shell() |
| { |
| exec >/dev/console 2>&1 </dev/console |
| echo ; echo |
| echo $@ |
| source_all emergency |
| echo |
| if getarg rdshell || getarg rdbreak; then |
| echo "Dropping to debug shell." |
| echo |
| sh -i |
| else |
| echo "Boot has failed, sleeping forever." |
| while :; do sleep 365d;done |
| fi |
| } |
| |
| export PATH=/sbin:/bin:/usr/sbin:/usr/bin |
| export TERM=linux |
| NEWROOT="/sysroot" |
| |
| trap "emergency_shell Signal caught!" 0 |
| |
| . /lib/dracut-lib.sh |
| |
| mknod /dev/null c 1 3 |
| |
| # mount some important things |
| mount -t proc /proc /proc >/dev/null 2>&1 |
| mount -t sysfs /sys /sys >/dev/null 2>&1 |
| |
| if [ ! -c /dev/ptmx ]; then |
| # try to mount devtmpfs |
| if ! mount -t devtmpfs -omode=0755 udev /dev >/dev/null 2>&1; then |
| # if it failed fall back to normal tmpfs |
| mount -t tmpfs -omode=0755 udev /dev >/dev/null 2>&1 |
| # Make some basic devices first, let udev handle the rest |
| mknod /dev/null c 1 3 |
| mknod /dev/ptmx c 5 2 |
| mknod /dev/console c 5 1 |
| mknod /dev/kmsg c 1 11 |
| fi |
| fi |
| |
| if getarg rdinitdebug; then |
| set -x |
| fi |
| |
| mkdir /dev/shm |
| mkdir /dev/pts |
| mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts >/dev/null 2>&1 |
| |
| UDEVVERSION=$(udevadm --version) |
| |
| source_conf /etc/conf.d |
| |
| # run scriptlets to parse the command line |
| getarg 'rdbreak=cmdline' && emergency_shell "Break before cmdline" |
| source_all cmdline |
| |
| [ -z "$root" ] && die "No or empty root= argument" |
| [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'" |
| |
| # Network root scripts may need updated root= options, |
| # so deposit them where they can see them (udev purges the env) |
| { |
| echo "root='$root'" |
| echo "rflags='$rflags'" |
| echo "fstype='$fstype'" |
| echo "netroot='$netroot'" |
| echo "NEWROOT='$NEWROOT'" |
| } > /tmp/root.info |
| |
| # pre-udev scripts run before udev starts, and are run only once. |
| getarg 'rdbreak=pre-udev' && emergency_shell "Break before pre-udev" |
| source_all pre-udev |
| |
| # start up udev and trigger cold plugs |
| udevd --daemon |
| |
| UDEV_LOG_PRIO_ARG=--log-priority |
| UDEV_QUEUE_EMPTY="udevadm settle --timeout=0" |
| |
| if [ $UDEVVERSION -lt 140 ]; then |
| UDEV_LOG_PRIO_ARG=--log_priority |
| UDEV_QUEUE_EMPTY="udevadm settle --timeout=1" |
| fi |
| |
| getarg rdudevinfo && udevadm control $UDEV_LOG_PRIO_ARG=info |
| getarg rdudevdebug && udevadm control $UDEV_LOG_PRIO_ARG=debug |
| |
| getarg 'rdbreak=pre-trigger' && emergency_shell "Break before pre-trigger" |
| source_all pre-trigger |
| |
| # then the rest |
| udevadm trigger $udevtriggeropts >/dev/null 2>&1 |
| |
| getarg 'rdbreak=initqueue' && emergency_shell "Break before initqueue" |
| |
| i=0 |
| while :; do |
| # bail out, if we have mounted the root filesystem |
| [ -d "$NEWROOT/proc" ] && break; |
| |
| # check if root can be mounted |
| [ -e /dev/root ] && break; |
| |
| if [ $UDEVVERSION -ge 143 ]; then |
| udevadm settle --exit-if-exists=/initqueue/work --exit-if-exists=/dev/root |
| else |
| udevadm settle --timeout=30 |
| fi |
| |
| # bail out, if we have mounted the root filesystem |
| [ -d "$NEWROOT/proc" ] && break; |
| # check if root can be mounted |
| [ -e /dev/root ] && break; |
| |
| unset queuetriggered |
| if [ -f /initqueue/work ]; then |
| rm /initqueue/work |
| queuetriggered="1" |
| fi |
| |
| for job in /initqueue/*.sh; do |
| [ -e "$job" ] || break |
| job=$job . $job |
| |
| # bail out, if we have mounted the root filesystem |
| [ -d "$NEWROOT/proc" ] && break; |
| # check if root can be mounted |
| [ -e /dev/root ] && break; |
| done |
| |
| [ -n "$queuetriggered" ] && continue |
| |
| if $UDEV_QUEUE_EMPTY >/dev/null 2>&1; then |
| # no more udev jobs |
| sleep 0.5 |
| i=$(($i+1)) |
| [ $i -gt 20 ] \ |
| && { flock -s 9 ; emergency_shell "No root device found"; } 9>/.console_lock |
| fi |
| done |
| unset job |
| unset queuetriggered |
| |
| # pre-mount happens before we try to mount the root filesystem, |
| # and happens once. |
| getarg 'rdbreak=pre-mount' && emergency_shell "Break pre-mount" |
| source_all pre-mount |
| |
| |
| getarg 'rdbreak=mount' && emergency_shell "Break mount" |
| # mount scripts actually try to mount the root filesystem, and may |
| # be sourced any number of times. As soon as one suceeds, no more are sourced. |
| i=0 |
| while :; do |
| [ -d "$NEWROOT/proc" ] && break; |
| for f in /mount/*.sh; do |
| [ -f "$f" ] && . "$f" |
| [ -d "$NEWROOT/proc" ] && break; |
| done |
| |
| i=$(($i+1)) |
| [ $i -gt 20 ] \ |
| && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock |
| done |
| |
| # pre pivot scripts are sourced just before we switch over to the new root. |
| getarg 'rdbreak=pre-pivot' && emergency_shell "Break pre-pivot" |
| source_all pre-pivot |
| |
| # by the time we get here, the root filesystem should be mounted. |
| # Try to find init. |
| for i in "$(getarg init=)" /sbin/init /etc/init /init /bin/sh; do |
| [ -f "$NEWROOT$i" -a -x "$NEWROOT$i" ] && { INIT="$i"; break; } |
| done |
| [ "$INIT" ] || { |
| echo "Cannot find init!" |
| echo "Please check to make sure you passed a valid root filesystem!" |
| emergency_shell |
| } |
| |
| getarg rdbreak && emergency_shell "Break before switch_root" |
| |
| HARD="" |
| while pidof udevd >/dev/null 2>&1; do |
| for pid in $(pidof udevd); do |
| kill $HARD $pid >/dev/null 2>&1 |
| done |
| HARD="-9" |
| done |
| |
| # Clean up the environment |
| for i in $(export -p); do |
| i=${i#declare -x} |
| i=${i#export} |
| i=${i%%=*} |
| [ "$i" = "root" -o "$i" = "PATH" -o "$i" = "HOME" -o "$i" = "TERM" ] || unset $i |
| done |
| |
| initargs="" |
| initrdargs="$initrdargs console BOOT_IMAGE rdbreak rdinitdebug rdudevinfo rdudevdebug rdnetdebug rdcopystate rdshell" |
| |
| for x in "$@"; do |
| for s in $initrdargs; do |
| [ "${x%%=*}" = $s ] && continue 2 |
| done |
| initargs="$initargs $x" |
| done |
| |
| # Copy state |
| mkdir /dev/.initramfs/ |
| if getarg rdcopystate; then |
| cp /tmp/* /dev/.initramfs/ >/dev/null 2>&1 |
| else |
| cp /tmp/net.* /dev/.initramfs/ >/dev/null 2>&1 |
| cp /tmp/resolv.conf /dev/.initramfs/ >/dev/null 2>&1 |
| cp -a /tmp/ifcfg/ /dev/.initramfs/ >/dev/null 2>&1 |
| fi |
| |
| exec switch_root "$NEWROOT" "$INIT" $initargs || { |
| # davej doesn't like initrd bugs |
| echo "Something went very badly wrong in the initrd. Please " |
| echo "file a bug against mkinitrd." |
| emergency_shell |
| } |