#!/bin/bash


# first get helper functions (e.g. DEBUG, load_scheme, ...)
. "/usr/lib/powersave/scripts/helper_functions"
. "/usr/lib/powersave/scripts/sleep_helper_functions"

set_variables "suspend2disk"

EV_ID="$4" # event id, needed for SCRIPT_RETURN

$SCRIPT_RETURN "$EV_ID|4|0"

#############################################################################
# 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 ;-)

declare -a KERNELS MENU_ENTRIES
declare -i DEFAULT_BOOT
eval `get_kernels`  # works only with grub, but we have no other
                    # choice anyway for now.
NEXT_BOOT=""
RUNNING=`uname -r`
if [ "$POWERSAVE_BOOT_LOADER" == "GRUB" ]; then
    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
        BOOTING="${BOOTING#vmlinuz-}"
        if [ "$RUNNING" == "$BOOTING" ]; then
            NEXT_BOOT=${MENU_ENTRIES[$I]}
            DEBUG "running kernel corresponds to grub menu entry $NEXT_BOOT" DIAG
            DEBUG "kernel filename: '${KERNELS[$I]}'" DIAG
            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 [ -z "$NEXT_BOOT" ]; then
        DEBUG "no kernelfile matching the running kernel found" WARN
    fi
fi

$SCRIPT_RETURN "$EV_ID|4|5"

#############################################################################
# if we did not find a kernel (or POWERSAVE_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"
if [ -z "$NEXT_BOOT" \
     -a "$POWERSAVE_SUSPEND2DISK_IGNORE_KERNEL_MISMATCH" != "yes" ]; then
    # which kernel is booted with the default entry?
    BOOTING="${KERNELS[$DEFAULT_BOOT]}"
    # if there is no default entry (no menu.lst? Using LILO?) 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-}"
    DEBUG "running kernel: '$RUNNING', (probably) booting kernel: '$BOOTING'" DIAG
    if [ "$BOOTING" != "$RUNNING" ]; then
        notify 'The kernel version "'$BOOTING'" in /boot does not match the running kernel
version "'$RUNNING'". Resuming with this kernel will not work. If you know
what you are doing, you can override this in /etc/sysconfig/powersave/sleep
with the variable POWERSAVE_SUSPEND2DISK_IGNORE_KERNEL_MISMATCH=yes.' ERROR CONTINUE "$EV_ID"
        $SCRIPT_RETURN "$EV_ID|4|101"
        $SCRIPT_RETURN "$EV_ID|1|kernel version mismatch, cannot suspend to disk."
        exit 1
    fi
fi

$SCRIPT_RETURN "$EV_ID|4|10"

################################################################
# we need exactly one swap partition. Now that APM also uses
# swsusp, this can be tested unconditionally.
#
# do we have a swap partition?
if ! grep -q partition /proc/swaps ; then # no partition to swap to.
    DEBUG "swsusp needs a swap partition, none available." ERROR
    notify "No swap partition, cannot suspend to disk." ERROR CONTINUE "$EV_ID"
    $SCRIPT_RETURN "$EV_ID|4|101"
    $SCRIPT_RETURN "$EV_ID|1|No swap partition, cannot suspend to disk."
    exit 1
#
# do we have more than one swap partition or a partition and a swapfile?
elif [ `egrep -c 'partition|file' /proc/swaps` -ne 1 ]; then
    DEBUG "swsusp needs exactly one swap partiton to suspend." ERROR
    notify "More than one swap partition, cannot suspend to disk." ERROR CONTINUE "$EV_ID" 
    $SCRIPT_RETURN "$EV_ID|4|101"
    $SCRIPT_RETURN "$EV_ID|1|More than one swap partition, cannot suspend to disk."
    rm -f $STATE
    exit 1
fi

$SCRIPT_RETURN "$EV_ID|4|15"
prepare_sleep "suspend2disk"
$SCRIPT_RETURN "$EV_ID|4|40"

# set the bootloader to the running kernel
if [ -n "$NEXT_BOOT" ]; then
    echo "preparing boot-loader: selecting entry $NEXT_BOOT, kernel /boot/$BOOTING" >> $LSMOD_LOG
    T1=`date +"%s%N"`
    sync; sync; sync # this is needed to speed up grub-once on reiserfs
    T2=`date +"%s%N"`
    grub-once $NEXT_BOOT > /dev/null 2>&1
    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." >> $LSMOD_LOG
fi

$SCRIPT_RETURN "$EV_ID|4|50"

# SET THE SHUTDOWN METHOD ######################################
# "platform" -> "real" S4
# "shutdown" -> S5
# "firmware" -> S4bios, not really supported.
# "reboot" -> just reboot, only useful for debugging
# we do a sanity check after setting this since there are still
# kernels out there getting this wrong.
if [ -n "POWERSAVE_SUSPEND2DISK_SHUTDOWN_MODE" ]; then
    echo -n "$POWERSAVE_SUSPEND2DISK_SHUTDOWN_MODE" > /sys/power/disk
    RET=$?
    if [ $RET -ne 0 ]; then
        DEBUG "could not set shutdown mode. errno: '$RET'" WARN
    fi
fi

$SCRIPT_RETURN "$EV_ID|4|101"
$SCRIPT_RETURN "$EV_ID|0|prepare_sleep finished successfully for $1"

exit 0
