From bea808544487065a27aeadd353b138fc3dc0e44d Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Mon, 6 May 2013 17:06:40 +0200 Subject: [PATCH] Introduce initial support to Plymouth --- arch/x86/modules_load | 3 + arch/x86_64/modules_load | 3 + defaults/initrd.defaults | 5 +- defaults/initrd.scripts | 227 ++++++++++++++++++++++++++++++++++++--- defaults/linuxrc | 49 +++++---- defaults/modules_load | 3 + doc/genkernel.8.txt | 7 ++ gen_cmdline.sh | 14 +++ gen_determineargs.sh | 1 + gen_initramfs.sh | 85 ++++++++++++++- genkernel.conf | 6 ++ 11 files changed, 363 insertions(+), 40 deletions(-) diff --git a/arch/x86/modules_load b/arch/x86/modules_load index 3469170..12a54a5 100644 --- a/arch/x86/modules_load +++ b/arch/x86/modules_load @@ -30,3 +30,6 @@ MODULES_FS="ext2 ext3 ext4 btrfs reiserfs jfs nfs xfs zfs fuse" # Crypto MODULES_CRYPTO="sha256_generic cbc aes_generic aes_586 aesni-intel xts" + +# DRM (Plymouth support) +MODULES_PLYMOUTH="radeon nouveau uvesafb" \ No newline at end of file diff --git a/arch/x86_64/modules_load b/arch/x86_64/modules_load index c202c30..883bc2d 100644 --- a/arch/x86_64/modules_load +++ b/arch/x86_64/modules_load @@ -29,3 +29,6 @@ MODULES_FS="ext2 ext3 ext4 btrfs reiserfs jfs nfs xfs zfs fuse" # Crypto MODULES_CRYPTO="sha256_generic cbc aes_generic aes-x86_64 aesni-intel xts" + +# DRM (Plymouth support) +MODULES_PLYMOUTH="radeon nouveau uvesafb" \ No newline at end of file diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults index 217a413..627f4c4 100755 --- a/defaults/initrd.defaults +++ b/defaults/initrd.defaults @@ -57,6 +57,9 @@ KSUFF='.ko' UDEVD='/sbin/udevd' MDEVD='/sbin/mdev' +INITRD_SPLASH='/etc/initrd.splash' +PLYMOUTHD_BIN='/sbin/plymouthd' +PLYMOUTH_BIN='/bin/plymouth' REAL_ROOT='' CONSOLE='/dev/console' NEW_ROOT='/newroot' @@ -75,4 +78,4 @@ DEFAULT_NFSOPTIONS="ro,nolock,rsize=1024,wsize=1024" # Only sections that are in by default or those that # are not module groups need to be defined here... HWOPTS='keymap cache modules pata sata scsi usb firewire waitscan lvm dmraid mdadm fs net' -MY_HWOPTS='modules pata sata scsi usb firewire waitscan dmraid mdadm fs net iscsi crypto' +MY_HWOPTS='modules pata sata scsi usb firewire waitscan dmraid mdadm fs net iscsi crypto plymouth' diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts index 551bea3..7405aa5 100644 --- a/defaults/initrd.scripts +++ b/defaults/initrd.scripts @@ -2,6 +2,113 @@ . /etc/initrd.defaults +splash() { + return 0 +} + +is_fbsplash() { + if [ -e "${INITRD_SPLASH}" ] && [ "${FBSPLASH}" = '1' ] + then + return 0 + fi + return 1 +} + +is_plymouth() { + if [ "${PLYMOUTH}" = '1' ] && [ "${QUIET}" = '1' ] \ + && [ -e "${PLYMOUTHD_BIN}" ] + then + return 0 + fi + return 1 +} + +is_plymouth_started() { + [ -n "${PLYMOUTH_FAILURE}" ] && return 1 + is_plymouth && "${PLYMOUTH_BIN}" --ping 2>/dev/null && return 0 + return 1 +} + +is_fbsplash && . "${INITRD_SPLASH}" + +splashcmd() { + # plymouth support + local cmd="${1}" + shift + + case "${cmd}" in + init) + is_fbsplash && splash init + is_plymouth && plymouth_init + ;; + + verbose) + is_fbsplash && splash verbose + plymouth_hide + ;; + + quiet) + # no fbsplash support + plymouth_show + ;; + + set_msg) + is_fbsplash && splash set_msg "${1}" + plymouth_message "${1}" + ;; + + hasroot) + # no fbsplash support + plymouth_newroot "${1}" + ;; + esac +} + +plymouth_init() { + good_msg "Enabling Plymouth" + mkdir -p /run/plymouth || return 1 + + # Make sure that udev is done loading tty and drm + if is_udev + then + udevadm trigger --action=add --attr-match=class=0x030000 \ + >/dev/null 2>&1 + udevadm trigger --action=add --subsystem-match=graphics \ + --subsystem-match=drm --subsystem-match=tty \ + >/dev/null 2>&1 + udevadm settle + fi + + local consoledev= + local other= + read consoledev other < /sys/class/tty/console/active + consoledev=${consoledev:-tty0} + "${PLYMOUTHD_BIN}" --attach-to-session --pid-file /run/plymouth/pid \ + || { + bad_msg "Plymouth load error"; + PLYMOUTH_FAILURE=1 + return 1; + } + plymouth_show + good_msg "Plymouth enabled" +} + +plymouth_hide() { + is_plymouth_started && "${PLYMOUTH_BIN}" --hide-splash +} + +plymouth_show() { + is_plymouth_started && "${PLYMOUTH_BIN}" --show-splash +} + +plymouth_message() { + is_plymouth_started && "${PLYMOUTH_BIN}" --update="${1}" +} + +plymouth_newroot() { + is_plymouth_started && "${PLYMOUTH_BIN}" --newroot="${1}" +} + modules_load() { for module in $* do @@ -408,7 +515,7 @@ bad_msg() { msg_string="${msg_string:-...}" if [ "$2" != 1 ] then - splash 'verbose' > /dev/null & + splashcmd verbose echo -e "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}" fi } @@ -419,19 +526,101 @@ warn_msg() { [ "$2" != 1 ] && echo -e "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}" } -crypt_filter() { +# Courtesy of dracut. Licensed under GPL-2. +# Taken from: dracut/modules.d/90crypt/crypt-lib.sh +# ask_for_password +# +# Wraps around plymouth ask-for-password and adds fallback to tty password ask +# if plymouth is not present. +# +# --cmd command +# Command to execute. Required. +# --prompt prompt +# Password prompt. Note that function already adds ':' at the end. +# Recommended. +# --tries n +# How many times repeat command on its failure. Default is 3. +# --ply-[cmd|prompt|tries] +# Command/prompt/tries specific for plymouth password ask only. +# --tty-[cmd|prompt|tries] +# Command/prompt/tries specific for tty password ask only. +# --tty-echo-off +# Turn off input echo before tty command is executed and turn on after. +# It's useful when password is read from stdin. +ask_for_password() { + local cmd; local prompt; local tries=3 + local ply_cmd; local ply_prompt; local ply_tries=3 + local tty_cmd; local tty_prompt; local tty_tries=3 + local ret + + while [ $# -gt 0 ]; do + case "$1" in + --cmd) ply_cmd="$2"; tty_cmd="$2" shift;; + --ply-cmd) ply_cmd="$2"; shift;; + --tty-cmd) tty_cmd="$2"; shift;; + --prompt) ply_prompt="$2"; tty_prompt="$2" shift;; + --ply-prompt) ply_prompt="$2"; shift;; + --tty-prompt) tty_prompt="$2"; shift;; + --tries) ply_tries="$2"; tty_tries="$2"; shift;; + --ply-tries) ply_tries="$2"; shift;; + --tty-tries) tty_tries="$2"; shift;; + --tty-echo-off) tty_echo_off=yes;; + esac + shift + done + + { flock -s 9; + # Prompt for password with plymouth, if installed and running. + if is_plymouth_started + then + "${PLYMOUTH_BIN}" ask-for-password \ + --prompt "$ply_prompt" \ + --number-of-tries=$ply_tries \ + --command="$ply_cmd" + ret=$? + else + splashcmd verbose + if [ "$tty_echo_off" = yes ]; then + stty_orig="$(stty -g)" + stty -echo + fi + + local i=1 + while [ $i -le $tty_tries ]; do + [ -n "$tty_prompt" ] && \ + printf "$tty_prompt [$i/$tty_tries]:" >&2 + eval "$tty_cmd" && ret=0 && break + ret=$? + i=$(($i+1)) + [ -n "$tty_prompt" ] && printf '\n' >&2 + done + + [ "$tty_echo_off" = yes ] && stty $stty_orig + + # no need for: splashcmd quiet + # since fbsplash does not support it + if [ $ret -ne 0 ] && is_fbsplash + then + splashcmd set_msg 'Disk unlocked.' + fi + fi + } 9>/.console_lock + + [ $ret -ne 0 ] && bad_msg "Wrong password" + return $ret +} + +crypt_exec() { if [ "${CRYPT_SILENT}" = '1' ] then - eval $1 >/dev/null 2>/dev/null + eval ${1} >/dev/null 2>/dev/null else - splash 'verbose' > /dev/null & - eval $1 - res=$? - if [ ${res} -eq 0 ] - then - splash set_msg 'Disk unlocked.' - fi - return ${res} + ask_for_password --ply-tries 1 \ + --ply-cmd "${1}" \ + --ply-prompt "Password (${LUKS_DEVICE})" \ + --tty-tries 1 \ + --tty-cmd "${1}" || return 1 + return 0 fi } @@ -448,6 +637,7 @@ prompt_user(){ bad_msg "Please file a bug report with this message" && exit 1 [ -n "${3}" ] && local explnt=" or : ${3}" || local explnt="." + splashcmd verbose bad_msg "Could not find the ${2} in ${oldvalue}${explnt}" bad_msg "Please specify another value or:" bad_msg "- press Enter for the same" @@ -470,6 +660,7 @@ prompt_user(){ eval ${1}'='${oldvalue} ;; esac + splashcmd quiet } cmdline_hwopts() { @@ -558,7 +749,7 @@ chooseKeymap() { good_msg "Loading keymaps" if [ -z "${keymap}" ] then - splash 'verbose' > /dev/null & + splashcmd verbose cat /lib/keymaps/keymapList read -t 10 -p '<< Load keymap (Enter for default): ' keymap case ${keymap} in @@ -613,12 +804,12 @@ chooseKeymap() { loadkmap < /lib/keymaps/${keymap}.map mkdir -p /etc/sysconfig echo "XKEYBOARD=${keymap}" > /etc/sysconfig/keyboard - splash set_msg "Set keymap to ${keymap}" + splashcmd set_msg "Set keymap to ${keymap}" elif [ -z "${keymap}" ] then good_msg good_msg "Keeping default keymap" - splash set_msg "Keeping default keymap" + splashcmd set_msg "Keeping default keymap" else bad_msg "Sorry, but keymap ''${keymap}'' is invalid!" unset keymap @@ -939,14 +1130,14 @@ openLUKS() { fi fi # At this point, keyfile or not, we're ready! - crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}" - crypt_filter_ret=$? + crypt_exec "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}" + crypt_exec_ret=$? [ -e /dev/tty.org ] \ && rm -f /dev/tty \ && mv /dev/tty.org /dev/tty - if [ ${crypt_filter_ret} -eq 0 ] + if [ ${crypt_exec_ret} -eq 0 ] then good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT} break @@ -1061,8 +1252,10 @@ setup_md_device() { } do_rundebugshell() { + splashcmd verbose good_msg 'Type "exit" to continue with normal bootup.' [ -x /bin/sh ] && /bin/sh || /bin/ash + splashcmd quiet } rundebugshell() { diff --git a/defaults/linuxrc b/defaults/linuxrc index ed40cb3..5cf73ff 100644 --- a/defaults/linuxrc +++ b/defaults/linuxrc @@ -3,12 +3,6 @@ . /etc/initrd.defaults . /etc/initrd.scripts -splash() { - return 0 -} - -[ -e /etc/initrd.splash ] && . /etc/initrd.splash - # Clean input/output exec >${CONSOLE} <${CONSOLE} 2>&1 @@ -153,6 +147,12 @@ do CONSOLE=${x#*=} CONSOLE=$(basename ${CONSOLE}) ;; + splash) + PLYMOUTH=1 + ;; + splash=*) + FBSPLASH=1 + ;; # /dev/md lvmraid=*) RAID_DEVICES="${x#*=}" @@ -308,8 +308,6 @@ then fi fi -splash 'init' - cmdline_hwopts # Mount devfs @@ -324,11 +322,26 @@ then good_msg 'Activating udev' echo "${UDEVD}" > /proc/sys/kernel/hotplug echo "" > /sys/kernel/uevent_helper -else + "${UDEVD}" --daemon --resolve-names=never && \ + udevadm trigger --action=add && \ + udevadm settle || bad_msg "udevd failed to run" +elif is_mdev +then good_msg 'Activating mdev' # Serialize hotplug events touch /dev/mdev.seq echo "${MDEVD}" > /proc/sys/kernel/hotplug + # Ensure that device nodes are properly configured + "${MDEVD}" -s || bad_msg "mdev -s failed" +else + bad_msg "Cannot find either udev or mdev" +fi + +if is_udev +then + # if udev, we can load the splash earlier + # In the plymouth case, udev will load KMS automatically + splashcmd init fi # Load modules listed in MY_HWOPTS if /lib/modules exists for the running kernel @@ -352,18 +365,10 @@ else good_msg 'Skipping module load; no modules in the ramdisk!' fi -if is_udev +# If we're mdev, we better wait for all the modules to be loaded. +if is_mdev then - # Initialize udev - "${UDEVD}" --daemon --resolve-names=never && \ - udevadm trigger --action=add && \ - udevadm settle || bad_msg "udevd failed to run" -elif is_mdev -then - # Ensure that device nodes are properly configured - "${MDEVD}" -s || bad_msg "mdev -s failed" -else - bad_msg "Cannot find either udev or mdev" + splashcmd init fi # Apply scan delay if specified @@ -880,6 +885,8 @@ for fs in $fslist; do fi done +splashcmd hasroot "${NEW_ROOT}" + # Execute script on the cdrom just before boot to update things if necessary cdupdate @@ -931,7 +938,7 @@ rundebugshell "before entering switch_root" exec /sbin/switch_root -c "/dev/console" "${CHROOT}" "${REAL_INIT:-/sbin/init}" "${INIT_OPTS}" # If we get here, something bad has happened -splash 'verbose' +splashcmd verbose bad_msg "A fatal error has occured since ${REAL_INIT:-/sbin/init} did not" bad_msg "boot correctly. Trying to open a shell..." diff --git a/defaults/modules_load b/defaults/modules_load index 7229990..cc91ff0 100644 --- a/defaults/modules_load +++ b/defaults/modules_load @@ -29,3 +29,6 @@ MODULES_FS="ext2 ext3 ext4 btrfs reiserfs jfs nfs xfs zfs fuse" # Crypto MODULES_CRYPTO="sha256_generic cbc aes_generic xts" + +# DRM (Plymouth support) +MODULES_PLYMOUTH="radeon nouveau uvesafb" \ No newline at end of file diff --git a/doc/genkernel.8.txt b/doc/genkernel.8.txt index 61edda4..ff04a8e 100644 --- a/doc/genkernel.8.txt +++ b/doc/genkernel.8.txt @@ -235,6 +235,13 @@ INITIALIZATION rather than the default theme specified in your splash configuration. If *--no-splash* is specified, then splash is disabled. +*--*[*no-*]*plymouth*:: + Installs, or not, plymouth into the initramfs. If "splash" will be + passed at boot, plymouth will be activated. + +*--plymouth-theme*=:: + Embeds the given plymouth theme into the initramfs. + *--do-keymap-auto*:: Force keymap selection at boot. diff --git a/gen_cmdline.sh b/gen_cmdline.sh index b992730..e491913 100755 --- a/gen_cmdline.sh +++ b/gen_cmdline.sh @@ -40,6 +40,8 @@ longusage() { echo " --no-mrproper Do not run make mrproper before compilation" echo " --splash Install framebuffer splash support into initramfs" echo " --no-splash Do not install framebuffer splash" + echo " --plymouth Install plymouth" + echo " --no-plymouth DO not install plymouth" echo " --install Install the kernel after building" echo " --no-install Do not install the kernel after building" echo " --symlink Manage symlinks in /boot for installed images" @@ -81,6 +83,7 @@ longusage() { echo " --splash-res= Select splash theme resolutions to install" echo " --splash= Enable framebuffer splash using " echo " --splash-res= Select splash theme resolutions to install" + echo " --plymouth-theme= Embed the given plymouth theme" echo " --do-keymap-auto Forces keymap selection at boot" echo " --keymap Enables keymap selection support" echo " --no-keymap Disables keymap selection support" @@ -415,6 +418,17 @@ parse_cmdline() { SPLASH_RES=`parse_opt "$*"` print_info 2 "SPLASH_RES: ${SPLASH_RES}" ;; + --plymouth) + CMD_PLYMOUTH=1 + PLYMOUTH_THEME='text' + print_info 2 "CMD_PLYMOUTH: ${CMD_PLYMOUTH}" + ;; + --plymouth-theme=*) + CMD_PLYMOUTH=1 + PLYMOUTH_THEME=`parse_opt "$*"` + print_info 2 "CMD_PLYMOUTH: ${CMD_PLYMOUTH}" + print_info 2 "PLYMOUTH_THEME: ${PLYMOUTH_THEME}" + ;; --install|--no-install) CMD_INSTALL=`parse_optbool "$*"` print_info 2 "CMD_INSTALL: ${CMD_INSTALL}" diff --git a/gen_determineargs.sh b/gen_determineargs.sh index 954d79d..fbe7d95 100755 --- a/gen_determineargs.sh +++ b/gen_determineargs.sh @@ -92,6 +92,7 @@ determine_real_args() { set_config_with_override STRING MODPROBEDIR CMD_MODPROBEDIR "/etc/modprobe.d" set_config_with_override BOOL SPLASH CMD_SPLASH + set_config_with_override BOOL PLYMOUTH CMD_PLYMOUTH set_config_with_override BOOL POSTCLEAR CMD_POSTCLEAR set_config_with_override BOOL MRPROPER CMD_MRPROPER set_config_with_override BOOL MENUCONFIG CMD_MENUCONFIG diff --git a/gen_initramfs.sh b/gen_initramfs.sh index 9d6478a..0002533 100755 --- a/gen_initramfs.sh +++ b/gen_initramfs.sh @@ -80,7 +80,10 @@ append_base_layout() { mkdir -p ${TEMP}/initramfs-base-temp/sbin mkdir -p ${TEMP}/initramfs-base-temp/usr/bin mkdir -p ${TEMP}/initramfs-base-temp/usr/sbin + mkdir -p ${TEMP}/initramfs-base-temp/usr/share + mkdir -p ${TEMP}/initramfs-base-temp/usr/lib ln -s lib ${TEMP}/initramfs-base-temp/lib64 + ln -s lib ${TEMP}/initramfs-base-temp/usr/lib64 echo "/dev/ram0 / ext2 defaults 0 0" > ${TEMP}/initramfs-base-temp/etc/fstab echo "proc /proc proc defaults 0 0" >> ${TEMP}/initramfs-base-temp/etc/fstab @@ -120,7 +123,8 @@ append_busybox() { chmod +x "${TEMP}/initramfs-busybox-temp/usr/share/udhcpc/default.script" # Set up a few default symlinks - local default_applets="[ ash sh mount uname echo cut cat" + local default_applets="[ ash sh mount uname ls echo cut cat flock stty" + default_applets+=" readlink" for i in ${BUSYBOX_APPLETS:-${default_applets}}; do rm -f ${TEMP}/initramfs-busybox-temp/bin/$i ln -s busybox ${TEMP}/initramfs-busybox-temp/bin/$i || @@ -382,6 +386,83 @@ append_splash(){ fi } +append_plymouth() { + [ -z "${PLYMOUTH_THEME}" ] && \ + PLYMOUTH_THEME=$(plymouth-set-default-theme) + [ -z "${PLYMOUTH_THEME}" ] && PLYMOUTH_THEME=text + + if [ -d "${TEMP}/initramfs-ply-temp" ] + then + rm -r "${TEMP}/initramfs-ply-temp" + fi + + mkdir -p "${TEMP}/initramfs-ply-temp/usr/share/plymouth/themes" + mkdir -p "${TEMP}/initramfs-ply-temp/etc/plymouth" + mkdir -p "${TEMP}/initramfs-ply-temp/"{bin,sbin} + + cd "${TEMP}/initramfs-ply-temp" + + local theme_dir="/usr/share/plymouth/themes" + local t= + + local p= + local ply="${theme_dir}/${PLYMOUTH_THEME}/${PLYMOUTH_THEME}.plymouth" + local plugin=$(grep "^ModuleName=" "${ply}" | cut -d= -f2-) + local plugin_binary= + if [ -n "${plugin}" ] + then + plugin_binary="$(plymouth --get-splash-plugin-path)/${plugin}.so" + fi + + print_info 1 " >> Installing plymouth [ using the ${PLYMOUTH_THEME} theme and plugin: \"${plugin}\" ]..." + + for t in text details ${PLYMOUTH_THEME}; do + cp -R "${theme_dir}/${t}" \ + "${TEMP}/initramfs-ply-temp${theme_dir}/" || \ + gen_die "cannot copy ${theme_dir}/details" + done + cp /usr/share/plymouth/{bizcom.png,plymouthd.defaults} \ + "${TEMP}/initramfs-ply-temp/usr/share/plymouth/" || \ + gen_die "cannot copy bizcom.png and plymouthd.defaults" + + # Do both config setup + echo -en "[Daemon]\nTheme=${PLYMOUTH_THEME}\n" > \ + "${TEMP}/initramfs-ply-temp/etc/plymouth/plymouthd.conf" || \ + gen_die "Cannot create /etc/plymouth/plymouthd.conf" + ln -sf "${PLYMOUTH_THEME}/${PLYMOUTH_THEME}.plymouth" \ + "${TEMP}/initramfs-ply-temp${theme_dir}/default.plymouth" || \ + gen_die "cannot setup the default plymouth theme" + + local libs=( + "/lib*/libply-splash-core.so*" + "/usr/lib*/libply-splash-graphics.so*" + "/usr/lib*/plymouth/text.so" + "/usr/lib*/plymouth/details.so" + "/usr/lib*/plymouth/renderers/frame-buffer.so" + "/usr/lib*/plymouth/renderers/drm.so" + "${plugin_binary}" + ) + # lib64 must take the precedence or all the cpio archive + # symlinks will be fubared + local slib= lib= final_lib= final_libs=() + for slib in "${libs[@]}"; do + lib=( ${slib} ) + final_lib="${lib[0]}" + final_libs+=( "${final_lib}" ) + done + + copy_binaries "${TEMP}/initramfs-ply-temp" \ + /sbin/plymouthd /bin/plymouth \ + "${final_libs[@]}" || gen_die "cannot copy plymouth" + + log_future_cpio_content + find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \ + || gen_die "appending plymouth to cpio" + + cd "${TEMP}" + rm -r "${TEMP}/initramfs-ply-temp/" +} + append_overlay(){ cd ${INITRAMFS_OVERLAY} log_future_cpio_content @@ -749,6 +830,8 @@ create_initramfs() { append_data 'splash' "${SPLASH}" + append_data 'plymouth' "${PLYMOUTH}" + append_data 'modprobed' if isTrue "${FIRMWARE}" && [ -n "${FIRMWARE_DIR}" ] diff --git a/genkernel.conf b/genkernel.conf index 0d7d3a9..306e848 100644 --- a/genkernel.conf +++ b/genkernel.conf @@ -111,6 +111,12 @@ DISKLABEL="yes" # This supersedes the "SPLASH_THEME" option of /etc/conf.d/splash (in early space). #SPLASH_THEME="gentoo" +# Installs, or not, plymouth into the initramfs. If "splash" will be +# passed at boot, plymouth will be activated. +# PLYMOUTH="yes" + +# Embeds the given plymouth theme into the initramfs. +# PLYMOUTH_THEME="text" # =========Keymap Settings========= #