ACC SHELL
#!/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="/var/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 [ "$(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/vmlinuz-ABC root=/dev/hda2
echo "KERNELS[$I]='${DUMMY[1]##*/}'" # vmlinuz-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 "vmlinuz-`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#*vmlinuz-}" ;;
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/vmlinuz 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/vmlinuz.
[ -z "$BOOTING" ] && BOOTING="vmlinuz"
if IMAGE=`readlink /boot/$BOOTING` && [ -e "/boot/${IMAGE##*/}" ]; then
BOOTING=$IMAGE
fi
BOOTING="${BOOTING#*vmlinuz-}"
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()
if [ "$1" = hibernate ] || [ "$1" = suspend -a "$2" = suspend_hybrid ]; then
prepare-grub
fi
if [ "$1" = thaw ] || [ "$1" = resume -a "$2" = suspend_hybrid ]; then
grub-once-restore
fi
ACC SHELL 2018