123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #!/bin/bash
- #
- # Stefan Seyfried, SUSE Linux Products GmbH 2006, GPL v2
- # mostly taken from the powersave project.
- GRUBONCE="/usr/sbin/grubonce"
- GRUBDEFAULT="/boot/grub/default"
- GRUBDEFSAVE="/run/suspend.grubonce.default"
- #####################################################################
- # gets a list of available kernels from /boot/grub/menu.lst
- # kernels are in the array $KERNELS, output to stdout to be eval-ed.
- getkernels()
- {
- # DEBUG "Running getkernels()" INFO
- local MENU_LST="/boot/grub/menu.lst"
- local I DUMMY MNT ROOTDEV
- declare -i I=0 J=-1
-
- # we need the root partition later to decide if this is the kernel to select
- while read ROOTDEV MNT DUMMY; do
- [ "$ROOTDEV" = "rootfs" ] && continue # not what we are searching for
- if [ "$MNT" = "/" ]; then
- break
- fi
- done < /proc/mounts
-
- # build an array KERNELS with all the kernels in /boot/grub/menu.lst
- # the array MENU_ENTRIES contains the corresponding menu entry numbers
- # DEFAULT_BOOT contains the default entry.
- while read LINE; do
- case $LINE in
- title*)
- let J++ # increase for every menu entry, even for non-linux
- # DEBUG "Found grub menu entry #${J}: '${LINE}'" INFO
- ;;
- default*)
- DUMMY=($LINE) # "default 0 #maybe a comment"
- echo "DEFAULT_BOOT=${DUMMY[1]}" # ^^[0]^^ 1 ^^[2]^ 3 ^^[4]^^
- # DEBUG "Default boot entry is '${DUMMY[1]}'" INFO
- ;;
- kernel*noresume*)
- # we probably found the "failsafe" kernel that won't resume...
- echo " Skipping grub entry #${J}, because it has the noresume option" >&2
- ;;
- kernel*root=*)
- local ROOT
- ROOT=${LINE#*root=}
- DUMMY=($ROOT)
- ROOT=${DUMMY[0]}
- if [ "$(echo $ROOT | grep LABEL)" ]; then
- LABEL=`echo $ROOT | cut -d"=" -f2`
- ROOT=`readlink -f /dev/disk/by-label/$LABEL`
- elif [ "$(echo $ROOT | grep UUID)" ]; then
- UUID=`echo $ROOT | cut -d"=" -f2`
- ROOT=`readlink -f /dev/disk/by-uuid/$UUID`
- fi
- if [ "$(stat -Lc '%t:%T' $ROOT)" != "$(stat -Lc '%t:%T' $ROOTDEV)" ]; then
- echo " Skipping grub entry #${J}, because its root= parameter ($ROOT)" >&2
- echo " does not match the current root device ($ROOTDEV)." >&2
- continue
- fi
- DUMMY=($LINE) # kernel (hd0,1)/boot/latestkernel-ABC root=/dev/hda2
- echo "KERNELS[$I]='${DUMMY[1]##*/}'" # latestkernel-ABC
- echo "MENU_ENTRIES[$I]=$J"
- # DEBUG "Found kernel entry #${I}: '${DUMMY[1]##*/}'" INFO
- let I++
- ;;
- kernel*)
- # a kernel without "root="? We better skip that one...
- echo " Skipping grub entry #${J}, because it has no root= option" >&2
- ;;
- *) ;;
- esac
- done < $MENU_LST
- }
- #############################################################
- # runs grubonce from the grub package to select which kernel
- # to boot on next startup
- grub-once()
- {
- if [ -x "$GRUBONCE" ]; then
- rm -f "$GRUBDEFSAVE"
- if [ -e "$GRUBDEFAULT" ]; then
- echo " saving original $GRUBDEFAULT"
- cp "$GRUBDEFAULT" "$GRUBDEFSAVE"
- fi
- echo " running '$GRUBONCE $1'"
- $GRUBONCE $1
- else
- echo "WARNING: $GRUBONCE not found, not preparing bootloader"
- fi
- }
- #############################################################
- # restore grub default after (eventually failed) resume
- grub-once-restore()
- {
- echo "INFO: running grub-once-restore"
- rm -f "$GRUBDEFAULT"
- if [ -e "$GRUBDEFSAVE" ]; then
- echo " restoring original $GRUBDEFAULT"
- mv "$GRUBDEFSAVE" "$GRUBDEFAULT"
- fi
- }
- #############################################################################
- # try to find a kernel image that matches the actually running kernel.
- # We need this, if more than one kernel is installed. This works reasonably
- # well with grub, if all kernels are named "kernel-`uname -r`" and are
- # located in /boot. If they are not, good luck ;-)
- find-kernel-entry()
- {
- NEXT_BOOT=-1
- ARCH=`uname -m`
- declare -i I=0
- # DEBUG "running kernel: $RUNNING" DIAG
- while [ -n "${KERNELS[$I]}" ]; do
- BOOTING="${KERNELS[$I]}"
- if IMAGE=`readlink /boot/$BOOTING` && [ -e "/boot/${IMAGE##*/}" ]; then
- # DEBUG "Found kernel symlink $BOOTING => $IMAGE" INFO
- BOOTING=$IMAGE
- fi
- case $ARCH in
- ppc*) BOOTING="${BOOTING#*vmlinux-}" ;;
- *) BOOTING="${BOOTING#*kernel-}" ;;
- esac
- if [ "$RUNNING" == "$BOOTING" ]; then
- NEXT_BOOT=${MENU_ENTRIES[$I]}
- echo " running kernel is grub menu entry $NEXT_BOOT (${KERNELS[$I]})"
- break
- fi
- let I++
- done
- # if we have not found a kernel, issue a warning.
- # if we have found a kernel, we'll do "grub-once" later, after
- # prepare_suspend finished.
- if [ $NEXT_BOOT -eq -1 ]; then
- echo "WARNING: no kernelfile matching the running kernel found"
- fi
- }
- #############################################################################
- # if we did not find a kernel (or BOOT_LOADER is not GRUB) check,
- # if the running kernel is still the one that will (probably) be booted for
- # resume (default entry in menu.lst or, if there is none, the kernel file
- # /boot/latestkernel points to.)
- # This will only work, if you use "original" SUSE kernels.
- # you can always override with the config variable set to "yes"
- prepare-grub()
- {
- echo "INFO: running prepare-grub"
- eval `getkernels`
- RUNNING=`uname -r`
- find-kernel-entry
- RET=0
- if [ $NEXT_BOOT -eq -1 ]; then
- # which kernel is booted with the default entry?
- BOOTING="${KERNELS[$DEFAULT_BOOT]}"
- # if there is no default entry (no menu.lst?) we fall back to
- # the default of /boot/latestkernel.
- [ -z "$BOOTING" ] && BOOTING="latestkernel"
- if IMAGE=`readlink /boot/$BOOTING` && [ -e "/boot/${IMAGE##*/}" ]; then
- BOOTING=$IMAGE
- fi
- BOOTING="${BOOTING#*kernel-}"
- echo "running kernel: '$RUNNING', probably booting kernel: '$BOOTING'"
- if [ "$BOOTING" != "$RUNNING" ]; then
- echo "ERROR: kernel version mismatch, cannot suspend to disk"
- echo "running: $RUNNING booting: $BOOTING" >> $INHIBIT
- RET=1
- fi
- else
- # set the bootloader to the running kernel
- echo " preparing boot-loader: selecting entry $NEXT_BOOT, kernel /boot/$BOOTING"
- T1=`date +"%s%N"`
- sync; sync; sync # this is needed to speed up grub-once on reiserfs
- T2=`date +"%s%N"`
- echo " grub-once: `grub-once $NEXT_BOOT`"
- T3=`date +"%s%N"`
- S=$(((T2-T1)/100000000)); S="$((S/10)).${S:0-1}"
- G=$(((T3-T2)/100000000)); G="$((G/10)).${G:0-1}"
- echo " time needed for sync: $S seconds, time needed for grub: $G seconds."
- fi
- return $RET
- }
- ###### main()
- case $1 in
- hibernate)
- prepare-grub
- ;;
- thaw)
- grub-once-restore
- ;;
- esac
|