diff options
Diffstat (limited to 'abs/core-testing/fbsplash/splash-functions.sh')
-rw-r--r-- | abs/core-testing/fbsplash/splash-functions.sh | 618 |
1 files changed, 618 insertions, 0 deletions
diff --git a/abs/core-testing/fbsplash/splash-functions.sh b/abs/core-testing/fbsplash/splash-functions.sh new file mode 100644 index 0000000..1c17663 --- /dev/null +++ b/abs/core-testing/fbsplash/splash-functions.sh @@ -0,0 +1,618 @@ +# Distributed under the terms of the GNU General Public License v2 + +# Author: Michal Januszewski <spock@gentoo.org> +# Maintainer: Michal Januszewski <spock@gentoo.org> + +# This file is a part of splashutils. The functions contained in this +# file are meant to be used by hook scripts in splash themes or by +# initscript systems. The code will be kept distro-agnostic to facilitate +# portability. It should also contain POSIX compatible code. No bashisms +# allowed! + +# #################################################################### +# Change any settings ONLY if you are sure what you're doing. +# Don't cry if it breaks afterwards. +# #################################################################### + +# The splash scripts need a cache which can be guaranteed to be +# both readable and writable at all times, even when the root fs +# is mounted read-only. To that end, an in-RAM fs is used. Valid +# values for spl_cachetype are 'tmpfs' and 'ramfs'. spl_cachesize +# is a size limit in KB, and it should probably be left with the +# default value. +export spl_cachesize="4096" +export spl_cachetype="tmpfs" +export spl_cachedir="//lib/splash/cache" +export spl_tmpdir="//lib/splash/tmp" +export spl_fifo="${spl_cachedir}/.splash" +export spl_pidfile="${spl_cachedir}/daemon.pid" +export spl_util="//bin/splash_util.static" +export spl_daemon="//sbin/fbsplashd.static" +export spl_decor="//sbin/fbcondecor_ctl.static" +export spl_bindir="//lib/splash/bin" + +# This is the main function which handles all events. +# Accepted parameters: +# svc_start <name> +# svc_stop <name> +# svc_started <name> +# svc_stopped <name> +# svc_start_failed <name> +# svc_stop_failed <name> +# svc_input_begin <name> +# svc_input_end <name> +# rc_init <internal_runlevel> - used to distinguish between 'boot' and 'sysinit' +# rc_exit +# critical +splash() { + local event="$1" + shift + + # Reload the splash settings in rc_init. We could have set them wrong the + # first time splash_setup was called (when splash-functions.sh was first + # sourced) if /proc wasn't mounted. + if [ "${event}" = "rc_init" ]; then + splash_setup "force" + else + splash_setup + fi + + [ "${SPLASH_MODE_REQ}" = "off" ] && return + + # Prepare the cache here -- rc_init-pre might want to use it + if [ "${event}" = "rc_init" ]; then + if [ "${RUNLEVEL}" = "S" -a "$1" = "sysinit" ]; then + splash_cache_prep 'start' || return + elif [ "${RUNLEVEL}" = "6" -o "${RUNLEVEL}" = "0" ]; then + # Check if the splash cachedir is mounted readonly. If it is, + # we need to mount a tmpfs over it. + if ! touch "${spl_cachedir}/message" 2>/dev/null ; then + splash_cache_prep 'stop' || return + fi + fi + fi + + local args="" + + if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then + args="$* ${RUNLEVEL}" + elif [ "${event}" = "svc_started" -o "${event}" = "svc_stopped" ]; then + if [ -z "$2" ]; then + # Backwards compatibility hack. Add a 0 to the arguments to simulate + # an error code. + args="$* 0" + else + args="$*" + + # Backwards compatibility: translate an error condition (non-zero + # error code) into an appropriate event. + if [ "$2" != "0" ]; then + if [ "${event}" = "svc_started" ]; then + event="svc_start_failed" + else + event="svc_stop_failed" + fi + fi + fi + else + args="$*" + fi + + splash_profile "pre ${event} ${args}" + + # Handle -pre event hooks + if [ -x "/etc/splash/${SPLASH_THEME}/scripts/${event}-pre" ]; then + /etc/splash/"${SPLASH_THEME}"/scripts/${event}-pre ${args} + fi + + case "$event" in + svc_start) splash_svc_start "$1";; + svc_stop) splash_svc_stop "$1";; + svc_started) splash_svc "$1" "start";; + svc_stopped) splash_svc "$1" "stop";; + svc_start_failed) splash_svc_fail "$1" "start";; + svc_stop_failed) splash_svc_fail "$1" "stop";; + svc_input_begin) splash_input_begin "$1";; + svc_input_end) splash_input_end "$1";; + rc_init) splash_init "$1" "${RUNLEVEL}";; + rc_exit) splash_exit "${RUNLEVEL}";; + critical) splash_verbose;; + esac + + splash_profile "post ${event} ${args}" + + # Handle -post event hooks + if [ -x "/etc/splash/${SPLASH_THEME}/scripts/${event}-post" ]; then + /etc/splash/"${SPLASH_THEME}"/scripts/${event}-post ${args} + fi + + return 0 +} + +splash_setup() { + # If it's already set up, let's not waste time on parsing the config + # files again + if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then + return 0 + fi + + export SPLASH_EFFECTS="" + export SPLASH_SANITY="" + export SPLASH_TEXTBOX="no" + export SPLASH_MODE_REQ="off" + export SPLASH_PROFILE="off" + export SPLASH_THEME="default" + export SPLASH_TTY="16" + export SPLASH_KDMODE="TEXT" + export SPLASH_AUTOVERBOSE="0" + export SPLASH_BOOT_MESSAGE="Booting the system (\$progress%)... Press F2 for verbose mode." + export SPLASH_SHUTDOWN_MESSAGE="Shutting down the system (\$progress%)... Press F2 for verbose mode." + export SPLASH_REBOOT_MESSAGE="Rebooting the system (\$progress%)... Press F2 for verbose mode." + export SPLASH_XSERVICE="xdm" + + [ -f /etc/splash/splash ] && . /etc/splash/splash + [ -f /etc/conf.d/splash ] && . /etc/conf.d/splash + [ -f /etc/conf.d/fbcondecor ] && . /etc/conf.d/fbcondecor + + if [ -f /proc/cmdline ]; then + options=$(grep -o 'splash=[^ ]*' /proc/cmdline) + + # Execute this loop over $options so that we can process multiple + # splash= arguments on the kernel command line. Useful for adjusting + # splash parameters from ISOLINUX. + for opt in ${options} ; do + options=${opt#*=} + + for i in $(echo "${options}" | sed -e 's/,/ /g') ; do + case ${i%:*} in + theme) SPLASH_THEME=${i#*:} ;; + tty) SPLASH_TTY=${i#*:} ;; + verbose) SPLASH_MODE_REQ="verbose" ;; + silent) SPLASH_MODE_REQ="silent" ;; + kdgraphics) SPLASH_KDMODE="GRAPHICS" ;; + profile) SPLASH_PROFILE="on" ;; + insane) SPLASH_SANITY="insane" ;; + esac + done + done + fi +} + +splash_get_boot_message() { + if [ "${RUNLEVEL}" = "6" ]; then + echo "${SPLASH_REBOOT_MESSAGE}" + elif [ "${RUNLEVEL}" = "0" ]; then + echo "${SPLASH_SHUTDOWN_MESSAGE}" + else + echo "${SPLASH_BOOT_MESSAGE}" + fi +} + +splash_start() { + if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then + ${spl_decor} -c on 2>/dev/null + return 0 + elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then + return 0 + fi + + # Display a warning if the system is not configured to display init messages + # on tty1. This can cause a lot of problems if it's not handled correctly, so + # we don't allow silent splash to run on incorrectly configured systems. + if [ "${SPLASH_MODE_REQ}" = "silent" -a "${SPLASH_SANITY}" != "insane" ]; then + if [ -z "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" -a \ + -z "$(grep -E '(^| )console=tty1( |$)' /proc/cmdline)" ]; then + clear + splash_warn "You don't appear to have a correct console= setting on your kernel" + splash_warn "command line. Silent splash will not be enabled. Please add" + splash_warn "console=tty1 or CONSOLE=/dev/tty1 to your kernel command line" + splash_warn "to avoid this message." + if [ -n "$(grep 'CONSOLE=/dev/tty1' /proc/cmdline)" -o \ + -n "$(grep 'console=tty1' /proc/cmdline)" ]; then + splash_warn "Note that CONSOLE=/dev/tty1 and console=tty1 are general parameters and" + splash_warn "not splash= settings." + fi + return 1 + fi + + if [ -n "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" ]; then + mount -n --bind / ${spl_tmpdir} + if [ ! -c "${spl_tmpdir}/dev/tty1" ]; then + umount -n ${spl_tmpdir} + splash_warn "The filesystem mounted on / doesn't contain the /dev/tty1 device" + splash_warn "which is required for the silent splash to function properly." + splash_warn "Silent splash will not be enabled. Please create the appropriate" + splash_warn "device node to avoid this message." + return 1 + fi + umount -n ${spl_tmpdir} + fi + fi + + rm -f "${spl_pidfile}" + + # Prepare the communications FIFO + rm -f "${spl_fifo}" 2>/dev/null + mkfifo "${spl_fifo}" + + local options="" + [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options="--kdgraphics" + [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}" + [ "${SPLASH_TEXTBOX}" = "yes" ] && options="${options} --textbox" + + local ttype="bootup" + if [ "${RUNLEVEL}" = "6" ]; then + ttype="reboot" + elif [ "${RUNLEVEL}" = "0" ]; then + ttype="shutdown" + fi + + # Start the splash daemon + BOOT_MSG="$(splash_get_boot_message)" ${spl_daemon} --theme="${SPLASH_THEME}" --pidfile="${spl_pidfile}" --type=${ttype} ${options} + + # Set the silent TTY and boot message + splash_comm_send "set tty silent ${SPLASH_TTY}" + + if [ "${SPLASH_MODE_REQ}" = "silent" ]; then + splash_comm_send "set mode silent" + splash_comm_send "repaint" + ${spl_decor} -c on 2>/dev/null + fi + + splash_comm_send "set autoverbose ${SPLASH_AUTOVERBOSE}" + + splash_set_event_dev + + return 0 +} + +########################################################################### +# Cache-related functions +########################################################################### + +splash_cache_prep() { + # Mount an in-RAM filesystem at spl_cachedir + mount -ns -t "${spl_cachetype}" cachedir "${spl_cachedir}" \ + -o rw,mode=0644,size="${spl_cachesize}"k + + retval="$?" + + if [ ${retval} -ne 0 ]; then + splash_err "Unable to create splash cache - switching to verbose." + splash_verbose + return "${retval}" + fi +} + +# args: list of files to save when the cache is umounted +# Note that the 'profile' file is already handled and thus shouldn't +# be included in the list. +splash_cache_cleanup() { + # Don't try to clean anything up if the cachedir is not mounted. + [ -z "$(grep ${spl_cachedir} /proc/mounts)" ] && return; + + # Create the temp dir if necessary. + if [ ! -d "${spl_tmpdir}" ]; then + mkdir -p "${spl_tmpdir}" 2>/dev/null + [ "$?" != "0" ] && return + fi + + # Make sure the splash daemon is dead. + if [ -n "$(pgrep fbsplashd)" ]; then + sleep 1 + killall -9 "${spl_daemon##*/}" 2>/dev/null + fi + + # If /etc is not writable, don't update /etc/mtab. If it is + # writable, update it to avoid stale mtab entries (bug #121827). + local mntopt="" + [ -w /etc/mtab ] || mntopt="-n" + mount ${mntopt} --move "${spl_cachedir}" "${spl_tmpdir}" 2>/dev/null + + # Don't try to copy anything if the cachedir is not writable. + [ -w "${spl_cachedir}" ] || return + + if [ "${SPLASH_PROFILE}" != "off" ]; then + cp -a "${spl_tmpdir}/profile" "${spl_cachedir}" 2>/dev/null + fi + + while [ -n "$1" ]; do + cp -a "${spl_tmpdir}/$1" "${spl_cachedir}" 2>/dev/null + shift + done + + umount -l "${spl_tmpdir}" 2>/dev/null +} + +########################################################################### +# Common functions +########################################################################### + +# Sends data to the splash FIFO after making sure there's someone +# alive on the other end to receive it. +splash_comm_send() { + if [ -z "`pidof $(basename ${spl_daemon})`" ]; then + return 1 + else + splash_profile "comm $*" + echo "$*" > "${spl_fifo}" & + fi +} + +# Returns the current splash mode. +splash_get_mode() { + local ctty="${spl_bindir}/fgconsole" + local mode="$(${spl_util})" + + if [ "${mode}" = "silent" ]; then + echo "silent" + else + if [ -z "$(${spl_decor} -c getstate --tty=${ctty} 2>/dev/null | grep off)" ]; then + echo "verbose" + else + echo "off" + fi + fi +} + +# chvt <n> +# -------- +# Switches to the n-th tty. +chvt() { + local ntty=$1 + +# if [ -x /usr/bin/chvt ] ; then +# /usr/bin/chvt ${ntty} +# else + printf "\e[12;${ntty}]" +# fi +} + +# Switches to verbose mode. +splash_verbose() { +# chvt 1 +/bin/true +} + +# Switches to silent mode. +splash_silent() { + splash_comm_send "set mode silent" +} + +# Saves profiling information +splash_profile() { + if [ "${SPLASH_PROFILE}" = "on" ]; then + echo "$(cat /proc/uptime | cut -f1 -d' '): $*" >> "${spl_cachedir}/profile" + fi +} + +# Set the input device if it exists. This will make it possible to use F2 to +# switch from verbose to silent. +splash_set_event_dev() { + local t="$(grep -Hsi keyboard /sys/class/input/input*/name | sed -e 's#.*input\([0-9]*\)/name.*#event\1#')" + if [ -z "${t}" ]; then + t="$(grep -Hsi keyboard /sys/class/input/event*/device/driver/description | grep -o 'event[0-9]\+')" + if [ -z "${t}" ]; then + for i in /sys/class/input/input* ; do + if [ "$((0x$(cat $i/capabilities/ev) & 0x100002))" = "1048578" ]; then + t="$(echo $i | sed -e 's#.*input\([0-9]*\)#event\1#')" + fi + done + + if [ -z "${t}" ]; then + # Try an alternative method of finding the event device. The idea comes + # from Bombadil <bombadil(at)h3c.de>. We're couting on the keyboard controller + # being the first device handled by kbd listed in input/devices. + t="$(/bin/grep -s -m 1 '^H: Handlers=kbd' /proc/bus/input/devices | grep -o 'event[0-9]*')" + fi + fi + fi + [ -n "${t}" ] && splash_comm_send "set event dev /dev/input/${t}" +} + +########################################################################### +# Service +########################################################################### + +# args: <svc> <action> +splash_svc() { + local srv="$1" + local act="$2" + + if [ "${act}" = "start" ]; then + splash_svc_update "${srv}" "svc_started" + if [ "${srv}" = "gpm" ]; then + splash_comm_send "set gpm" + splash_comm_send "repaint" + fi + splash_comm_send "log Service '${srv}' started." + else + splash_svc_update "${srv}" "svc_stopped" + splash_comm_send "log Service '${srv}' stopped." + fi + + splash_update_progress "${srv}" +} + +# args: <svc> <action> +splash_svc_fail() { + local srv="$1" + local act="$2" + + if [ "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then + splash_verbose + return 1 + fi + + if [ "${act}" = "start" ]; then + splash_svc_update "${srv}" "svc_start_failed" + splash_comm_send "log Service '${srv}' failed to start." + else + splash_svc_update "${srv}" "svc_stop_failed" + splash_comm_send "log Service '${srv}' failed to stop." + fi + + splash_update_progress "${srv}" +} + +# args: <svc> <state> +# +# Inform the splash daemon about service status changes. +splash_svc_update() { + splash_comm_send "update_svc $1 $2" +} + +# args: <svc> +splash_svc_start() { + local svc="$1" + + splash_svc_update "${svc}" "svc_start" + splash_comm_send "paint" +} + +# args: <svc> +splash_svc_stop() { + local svc="$1" + + splash_svc_update "${svc}" "svc_stop" + splash_comm_send "paint" +} + +# args: <svc> +splash_input_begin() { + local svc="$1" + + if [ "$(splash_get_mode)" = "silent" ]; then + splash_verbose + export SPL_SVC_INPUT_SILENT="${svc}" + fi +} + +# args: <svc> +splash_input_end() { + local svc="$1" + + if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then + splash_silent + unset SPL_SVC_INPUT_SILENT + fi +} + +########################################################################### +# Framebuffer Console Decorations functions +########################################################################### + +fbcondecor_supported() +{ + [ -e /dev/fbsplash -o -e /dev/fbcondecor ] +} + +# args: <theme> <tty> +fbcondecor_set_theme() +{ + local theme=$1 + local tty=$2 + + [ -x ${spl_decor} ] || return 1 + + ${spl_decor} --tty="${tty}" -t "${theme}" -c setcfg || return 1 + ${spl_decor} --tty="${tty}" -t "${theme}" -c setpic -q + ${spl_decor} --tty="${tty}" -c on +} + +########################################################################### +# Service list +########################################################################### + +# splash_svclist_get <type> +# ------------------------- +# type: +# - start - to get a list of services to be started during bootup +# - stop - to get a list of services to be stopped during shutdown/reboot +splash_svclist_get() { + if [ "$1" = "start" -a -r "${spl_cachedir}/svcs_start" ]; then + cat "${spl_cachedir}/svcs_start" + elif [ "$1" = "stop" -a -r "${spl_cachedir}/svcs_stop" ]; then + cat "${spl_cachedir}/svcs_stop" + fi +} + +splash_warn() { + echo "$*" +} + +splash_err() { + echo "$*" +} + +############################################################################ +# Functions to be overridden by distro-specific code +########################################################################### + +# args: <internal_runlevel> <runlevel> +# +# This function is called when an 'rc_init' event takes place, +# i.e. when the runlevel is changed. + +# It is normally used to initialize any internal splash-related +# variables (e.g. ones used to track the boot progress), calculate +# and save the service list and call `splash_start` in appropriate +# runlevels. +# +# Note that the splash cache is already intialized when this +# function is called. +splash_init() { + if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S" -a "$1" = "sysinit" ]; then + splash_start + fi +} + +# args: <runlevel> +# +# This function is called when an 'rc_exit' event takes place, +# i.e. at the end of processes all initscript from a runlevel. +splash_exit() { + # If we're in sysinit or rebooting, do nothing. + [ "$1" = "S" -o "$1" = "6" -o "$1" = "0" ] && return 0 + + splash_comm_send "exit" + splash_cache_cleanup +} + +# args: <svc> +# +# This function is called whenever the progress variable should be +# updated. It should recalculate the progress and send it to the +# splash daemon. +splash_update_progress() { + # splash_comm_send "progress ${progress}" + # splash_comm_send "paint" + return +} + +# Export functions if we're running bash. +if [ -n "${BASH}" ]; then + export -f splash + export -f splash_setup + export -f splash_get_boot_message + export -f splash_start + export -f splash_cache_prep + export -f splash_cache_cleanup + export -f splash_comm_send + export -f splash_get_mode + export -f chvt + export -f splash_verbose + export -f splash_silent + export -f splash_profile + export -f splash_set_event_dev + export -f splash_svclist_get +fi + +# Load any supplementary splash functions. +for i in /sbin/splash-functions-*.sh ; do + [ -r "${i}" ] && . "${i}" +done + +splash_setup + +# vim:ts=4 |