usplash-v1 version 0.1 20040826-1705 Ubuntu Splash / Userspace Splash / Micro Splash =============================================== Copyright (C) 2004 Paul Sladen Copyright (C) 2004 Nathaniel McCallum Designed and built in a couple of days at the Canonical/Ubuntu Oxford (GB) conference in August 2004 as a proof-of-concept demonstration. Please contact Paul Sladen with questions. Demo code ========= To run this demo as provided you will need the following setup: * 16-bit framebuffer (eg. vga=791 for 1024x768x16 vesafb on i386) * sudo configured * running in X From a terminal in X, be in the root directory of usplash-v1 and run: $ ./bin/demo.sh Which will run through the following components; 1. usplat 'usplat' is a minimal 'image-splatter' designed to get an image onto the screen as quickly as possible from initrd. 2. usplashd 'usplashd' is the main daemon that runs from early rc.d or from an extra entry in '/etc/inittab'. 3. usquirt 'usquirt' sends messages to usplashd, for extra to show a daemon starting or updating a progress-bar. Background ========== Most graphical boot systems rely on some level of kernel patches, in the most extreme form a single path from bootloader through to boot- sequence. The most common splash solution at the time was a series of patches called 'bootsplash', one of the features of which is embedding a megabyte of JPEG decoder directly into the kernel. With respect to Ubuntu the demand was: A cross-platform 100% userspace graphical bootup system and ideally something which would blow away the competition! Alternatives ============ * Xandros splashfx * SuSE/etc Bootsplash * Red Hat Graphical Boot (RHGB) * Gentoo fbsplash SplashFX -------- splashfx, as used by Xandros is one of the smoothest around: http://xandros.jammys.net/3.x/patches-2.6.9/001splashFX.2.6.diff it also one of the sickest. The basic gist is: 1. Get LILO (bootloader) to switch to legacy VGA mode 13h (320x200x8) 2. Whack up pretty image from LILO 3. Userspace sends commands to '/proc/splashFX' 4. Kernel hack writes straight to address 64kB @ 0xa0000 It's not that big, it is VGA (i386) only, it avoids video-mode changes and it is the smoothest greased polish I've seen. Did I mention it is sick(tm) :-) Bootsplash ---------- The most wide-spread patches in use; SuSE ship with it and most roll- your-own people love it: http://www.bootsplash.org/kernel.html The patching howto on the website shows the following: patching file drivers/char/console.c patching file drivers/char/keyboard.c patching file drivers/char/n_tty.c patching file drivers/video/Config.in patching file drivers/video/Makefile patching file drivers/video/fbcon-jpegdec.c patching file drivers/video/fbcon-jpegdec.h patching file drivers/video/fbcon-splash.c patching file drivers/video/fbcon-splash.h patching file drivers/video/fbcon-splash16.c patching file drivers/video/fbcon.c patching file include/video/fbcon.h patching file kernel/panic.c The most significant is new framebuffer drivers, these load in a .jpg image straight into the kernel and use it as a background, modifying the fbcon text routines so that instead of drawing a black background, they fetch from the image as a backbuffer. This creates an effect of apparent transparency where text is text and anything not text is the background. The userspace tools include some handy tools for: Drawing a progress bar. Drawing an MNG animation. ('fbmngplay') Drawing Truetype-rendered text ('fbtruetype') Both of which talk to a '/dev/fb*'. One of the more interesting off-shoots is the obsession with themeing the displayed boot images and bootsplash provides a well specified configuration file format for drop-in 'themes'. http://www.bootsplash.org/themeinfo.html Bootsplash does not support 8-bit framebuffers. RHGB ---- Perhaps the technically 'cleanest' way of doing things is just to start X to display stuff! http://fedora.redhat.com/projects/additional-projects/rhgb/ Red-Hat Graphical Boot on i386 starts the following software stack: v rhgb Application v VTE (Virtual Terminal Emulation) v GTK+ v Xvesafb v vesafb + tmpfs This means that a copy of X is started 20 seconds into the boot process and then a second copy of X is started 30-60 seconds later. The GTK+/X approach does have several positive aspects: * Interactive rather than Passive (the mouse works) * Silent and Verbose are just GTK+ 'notebook' tabs This is basically a userspace solution; 'init' is patched to allow redirecting console output to the GTK-based virtual console via the 'change_console' command. RHGB also uses a ''message watchdog'', so that in the absence of updates ('-ping's) for 10 seconds [fsck running], the console can be switched first to verbose mode and then back to the text-TTY. fbsplash / gensplash -------------------- fbsplash (Framebuffer Splash) is a recent entrant and has goals of removing as much of the ugly kernel patches of 'bootsplash' as possible but maintaining userspace (or end-user) compatibility to some degree: http://dev.gentoo.org/~spock/projects/gensplash/faq.php The software stack considers of: * fbsplash (better kernel patch) * splashutils (userspace control) * gensplash (high level XML toolset using 'splashutils') The JPEG/PNG decoding is moved to userspace with a raw uncompressed image being passed onto the kernel. There is also a related project that aiming to provide a better i386 'vesafb' framebuffer driver. One of the current limitations of the existing 'vesafb' is that the BIOS call to select the video-mode is made is the 16-bit i386 setup.S code before the kernel-proper is loaded. This separate, but related project is: * vesa-tng (vesafb -- 'The Next Generation') This project is probably the most /interesting/ of other graphical boot-techniques and provides a sensible trade-off between kernel and userspace tricks but it is currently known not to be SMP safe. Challenges and Design ===================== Daniel Silverstone (Kinnison), Daniel Stone (daniels), Scott-James Remnant (Keybuk), Dafydd Harries (daf) and anyone else not busy playing the Mao! card-game all brought their ideas and scribbled on the big Whiteboard between 00:00 and 03:00 in the morning. Q: ''100% userspace graphical boot system please'' A: ''...But we can do it with 3 smallish patches'' A: ''...Urm, maybe able to do with 2 small patches'' A: ''...Perhaps even just 1, small, wafer-thin patch'' A: ''...Hey, we can do it with ZERO PATCHES!'' The kernel-guys looked immensely pleased at this point. Here's the result of that various design work: http://www.ubuntulinux.org/wiki/USplash http://www.ubuntulinux.org/wiki/UsplashTodo Thoughts and Priorities ======================= * Must not break anything * Must not leave the machine in a 'weird' state * Don't make the boot-up process more than 10% longer. Bootsplash works by placing an image on the /same/ screen as the kernel and init messages. The first idea was to switch to another virtual-terminal (VT) and we choose 'tty8', leaving the text messages all scrolling up on the first 'tty1' where they would normally be. * chvt 8 One probably we found here was that the kernel was writing to '/dev/console' which was following-us around and writing to whatever VT was at the front, this case, spewing all over the graphics. * linux ... console=tty1 This mostly solved the problem by hard-coding output to be 'redirected' to where we wanted it and leaving our 'tty8' clean. This interacts well with serial-console since in that case, console= will be overridden and specified to something different. But the kernel still outputs to the screen before userspace is loaded. * linux ... quiet This informs the kernel we'd like it not to print anything before initrd is loaded and we have a chance to take over and swap VT. When initrd loaded, this printed 'Inittool-1.0.4...', we hacked this to print: * Starting Ubuntu... On most architectures and framebuffer is also setup and used for the boot-firmware, however on i386/amd64 we actually have a text-console on boot instead of a graphical framebuffer. We can get graphics by using the 'vesafb' drivers as a VESA interface is provided on most graphics hardware used on i386. There are two parts: * linux ... vga= * insmod vesafb The actual video-mode change is done in 16-bit code early, before the main Linux kernel main() code takes over. As a result of this the video mode must be pre-selected and specified on the command-line: 640x480 800x600 1024x768 Dec Hex Dec Hex Dec Hex 8-bit 769 0x301 771 0x303 773 0x305 16-bit 785 0x311 788 0x314 791 0x317 24-bit 786 0x312 789 0x315 792 0x318 Either the Hex (vga=0x317) or the Decimal (vga=791) form can be used. Note that other modes do exist, my Libretto 100CT which has an 800x480 widescreen display uses modes 0x126 (8-bit), 0x127 (16-bit) and 0x128 (24-bit). This modes are probably custom and should be probed for availability on the device. We can abuse the 'xresprobe' detection and use the mode selected by 'xserver-xorg' as a guide to finding the closest VESA mode On other platforms such as PowerPC we can just use whatever framebuffer is provided as the driver is compiled into the kernel and text-output is often performed by BIOS/Firmware routines. Usplat ====== Usplat comes onto the scene here and runs for approximately 1 second to perform the following: * Check for a framebuffer that we support * Check we can load an image to display * Disable flashing cursor on alternate VT (tty8) * Switch to alternate VT (tty8) * mmap() '/dev/fb0' * Fade in image onto the screen * Close, removing all file descriptors The last step (exiting) is taken so that 'pivot_root' can function and swap between the 'initrd' filesystem and the main root filesystem. Usplashd ======== Usplashd is a daemon, it lives remains in the background whilst the boot is taking place and 'manages' drawing on the display. Since 'usplashd' is a daemon, it needs a form of IPC (Inter-Process Control). This is a challenge since at the point Usplashd is loaded the root filesystem has not been checked and is therefore read-only. A way around this is to first mount an in-memory filesystem ('tmpfs') on '/etc/usplash/' and then create a FIFO within that. mount /dev/shm -t tmpfs /etc/usplash mkfifo /etc/usplash/.control This is abstracted away from the user (init scripts) but the 'usquirt' tool. This locates the communication pipe/fifo and uses it if it's available, or just returns with a failure and if it doesn't exist. Therefore, the existence of the FIFO is used as a flag to detect whether usplash is running and fail safely. It's not possible to delete a fifo with data still 'inside it', the data must be read out first. Also, it's not possible to delete a fifo that somebody has select()ed on to listen to incoming data. (NOTE: Amusingly, 1 month later RHGB changed to use a separate 'rhgb-client' program after it was found they were wasting 100% through problems reading/writing their control pipe. :-) * Usplash parent (privileged) * Usplash child (unprivileged) After opening the Framebuffer device and mounting/creating the communications pipe, usplashd fork()s, leaving a privileged parent process to act as a watchdog. All drawing and message-parsing is handled by the unprivileged child process which also ensures that exploits in external libraries such as libpng/libjpeg do not cause a security issue. If the child dies, the pipe is removed and a 'chvt' back to tty1 is performed. If the child exits, the pipe is cleaned up and a 'chvt' is performed to the terminal specified in the child exit_code. This allows the child to receive a message that X has loaded and that a switch away to that VT (normally tty7) should be performed. As switching VT requires a privileged ioctl(), this is done by the parent. If the parent is asked to terminate, it kills the child and exits as required. Drawing Code ============ The code is not nice and not efficient---the mmap() filehandle is not cached. The code only knows about 16-bit. PCX is used as an image format. It is 8-bit, supports simple compression and I could remember how to decode the format in my head! Icons and progress-bars are hacks. In a version two, X integration ============= DanielS added an option to X called: * -novtswitch which starts the X server, allowing it to accept connections, but doesn't perform an actual VT switch. It helps to cut down the time between usplash disappearing from view and GDM/GNOME appearing as some of the initialisation code can be done in the background. We noticed that Fading (even 0.5 seconds) is the key to making the process look really smooth. It would be nice to fade the X server up and down as well. Some nice abstracted code exists in xscreensaver to perform this either by palette modification (8-bit) or gamma-sliding (16/24-bit) if the X server supports gamma. This needs to be added as a patch to either GDM (GNOME Display/Login Manager), or as a separate program ('ushade'?) that communicates with usplashd and accepts a signal to fade-in/fade-out. Also discussed is the possibility of adding an X extension to allow notification when a chvt() in, or out occurs. This can be used for: * Fading up the screen (switch to X) * Locking the screen (switch away from X) Argumenting GDM would allow GDM to display extra icons whilst the system continues to boot. Message-painting ================ init-scripts output is now performed through the LSB (Linux Standard Base) functions. This means that if we want to display messages, rather than just simple start/stop information such as icons on the screen we can redirect/'tee' them off at this stage. This can then be drawn ''by hand'' onto the framebuffer device, using code such as 'fbtruetype' that does performs fbcon like functions entirely in userspace and without reference to the kernel display/output routines. Fsck and SU-login ================= Fsck (Filesystem Check) and Single-User login both require attention if something goes wrong. If they are run, if user input is required they need to be brought to the front (chvt to 'tty1'). Fsck also is the only major part of the boot-process that isn't predictable in the amount of time it will take. Normally 'fsck' exits quickly after just checking that the filesystem was unmounted cleanly. For journaling filesystems (Ext3fs, XFS, JFS), 'fsck' may need to perform either a quick journal-replay or a much longer and full filesystem check as with normal filesystems such as 'ext2'. This full-check is normally forced for approximate once every 30 times the partition is mounted read-write, this can take several minutes and this delay must be signalled to the user so that they understand what is happening. The low-level fsck functions (fsck.ext2) have an option '-C' which causes completion (percentage) information to be sent to an extra filehandle. This information is used by the high-level 'fsck' program to display an ASCII (text) bar on the screen. Ideally the high-level 'fsck' should be patched to allow passing on this percentage so that it can be displayed by 'usplashd' as a progress-bar. Author ====== Copyright (C) 2005 Paul Sladen You may modify and distribute this document under the terms of the GNU GPL Version 2. Written 2005-02-08. Thank you to '' and the Debsplash team for constantly pestering me to write this documentation and get this code released. Apologies it took so long. Poking Fun at Red Hat Graphical Boot ===================================== I hope the above has been unbiased and informative, so far. This is my chance to poke fun at Red Hat! :-) RHGB uses two X servers---something that might be considered a little extreme---starting one copy of X just to start another one 30seconds later... http://www.bootchart.org/images/bootchart.initial.png Especially if the bootup splash (a) doesn't start until 25 seconds into the boot sequence, (b) takes 10 seconds to start, then (c) extends the system boot time by 45 seconds whilst consuming 100% CPU. Perhaps it'd be worth spending some development time optimising the boot-process to just be quicker in the first place: http://www.planetarytramp.net/bootchart/bootchart-20041210-1934.png Yes, that is an Ubuntu (hoary) boot process at Mataro, Spain. It takes 20 seconds until main X (and 29 seconds to GDM login). No, not a fast machine; An IBM X40 1.1Ghz laptop with a slow 1.8" Hard disk. If usplash added more than 2-3 seconds (making boot-up 10% longer) it's not going to be worth running it! Confusion ========= For fun, these extra 89bytes equal the length of the GPL License! Emacs Dictionary ================ LocalWords: Ubuntu McCallum JPEG Xandros themeing ping's pre CT framebuffer LocalWords: eg vga vesafb sudo usplat splatter initrd usplashd rc usquirt tm LocalWords: bootloader bootsplash bootup splashfx SuSE RHGB Gentoo fbsplash LocalWords: SplashFX howto jpg fbcon backbuffer MNG fbmngplay fbtruetype rhgb LocalWords: VTE GTK Xvesafb tmpfs init gensplash splashutils XML toolset vesa LocalWords: tng SMP Silverstone Kinnison daniels Keybuk Dafydd Harries daf VT LocalWords: Whiteboard chvt linux amd insmod xresprobe xserver xorg PowerPC LocalWords: mmap filesystem IPC mkfifo fifo libpng libjpeg filehandle PCX GDM LocalWords: DanielS novtswitch xscreensaver ushade Argumenting LSB SU Ext fs LocalWords: journaling filesystems XFS JFS ext GPL Debsplash Mataro Ghz