The Linux bootsplash ==================== Date: November, 2017 Author: Max Staudt The Linux bootsplash is a graphical replacement for the '``quiet``' boot option, typically showing a logo and a spinner animation as the system starts. Currently, it is a part of the Framebuffer Console support, and can be found as ``CONFIG_BOOTSPLASH`` in the kernel configuration. This means that as long as it is enabled, it hijacks fbcon's output and draws a splash screen instead. Purely compiling in the bootsplash will not render it functional - to actually render a splash, you will also need a splash theme file. See the example utility and script in ``tools/bootsplash`` for a live demo. Motivation ========== - The '``quiet``' boot option only suppresses most messages during boot, but errors are still shown. - A user space implementation can only show a logo once user space has been initialized far enough to allow this. A kernel splash can display a splash immediately as soon as fbcon can be displayed. - Implementing a splash screen in user space (e.g. Plymouth) is problematic due to resource conflicts. For example, if Plymouth is keeping ``/dev/fb0`` (provided via vesafb/efifb) open, then most DRM drivers can't replace it because the address space is still busy - thus leading to a VRAM reservation error. See: https://bugzilla.opensuse.org/show_bug.cgi?id=980750 Command line arguments ====================== ``bootsplash.bootfile`` Which file in the initramfs to load. The splash theme is loaded via request_firmware(), thus to load ``/lib/firmware/bootsplash/mytheme`` pass the command line: ``bootsplash.bootfile=bootsplash/mytheme`` Note: The splash file *has to be* in the initramfs, as it needs to be available when the splash is initialized early on. Default: none, i.e. a non-functional splash, falling back to showing text. sysfs run-time configuration ============================ ``/sys/devices/platform/bootsplash.0/enabled`` Enable/disable the bootsplash. The system boots with this set to 1, but will not show a splash unless a splash theme file is also loaded. ``/sys/devices/platform/bootsplash.0/drop_splash`` Unload splash data and free memory. ``/sys/devices/platform/bootsplash.0/load_file`` Load a splash file from ``/lib/firmware/``. Note that trailing newlines will be interpreted as part of the file name. Kconfig ======= ``BOOTSPLASH`` Whether to compile in bootsplash support (depends on fbcon compiled in, i.e. ``FRAMEBUFFER_CONSOLE=y``) Bootsplash file format ====================== A file specified in the kernel configuration as ``CONFIG_BOOTSPLASH_FILE`` or specified on the command line as ``bootsplash.bootfile`` will be loaded and displayed as soon as fbcon is initialized. Main blocks ----------- There are 3 main blocks in each file: - one File header - n Picture headers - m (Blob header + payload) blocks Structures ---------- The on-disk structures are defined in ``drivers/video/fbdev/core/bootsplash_file.h`` and represent these blocks: - ``struct splash_file_header`` Represents the file header, with splash-wide information including: - The magic string "``Linux bootsplash``" on big-endian platforms (the reverse on little endian) - The file format version (for incompatible updates, hopefully never) - The background color - Number of picture and blob blocks - Animation speed (we only allow one delay for all animations) The file header is followed by the first picture header. - ``struct splash_picture_header`` Represents an object (picture) drawn on screen, including its immutable properties: - Width, height - Positioning relative to screen corners or in the center - Animation, if any - Animation type - Number of blobs The picture header is followed by another picture header, up until n picture headers (as defined in the file header) have been read. Then, the (blob header, payload) pairs follow. - ``struct splash_blob_header`` (followed by payload) Represents one raw data stream. So far, only picture data is defined. The blob header is followed by a payload, then padding to n*16 bytes, then (if further blobs are defined in the file header) a further blob header. Alignment --------- The bootsplash file is designed to be loaded into memory as-is. All structures are a multiple of 16 bytes long, all elements therein are aligned to multiples of their length, and the payloads are always padded up to multiples of 16 bytes. This is to allow aligned accesses in all cases while still simply mapping the structures over an in-memory copy of the bootsplash file. Further information ------------------- Please see ``drivers/video/fbdev/core/bootsplash_file.h`` for further details and possible values in the file. Hooks - how the bootsplash is integrated ======================================== ``drivers/video/fbdev/core/fbcon.c`` ``fbcon_init()`` calls ``bootsplash_init()``, which loads the default bootsplash file or the one specified on the kernel command line. ``fbcon_switch()`` draws the bootsplash when it's active, and is also one of the callers of ``set_blitting_type()``. ``set_blitting_type()`` calls ``fbcon_set_dummyops()`` when the bootsplash is active, overriding the text rendering functions. ``fbcon_cursor()`` will call ``bootsplash_disable()`` when an oops is being printed in order to make a kernel panic visible. ``drivers/video/fbdev/core/dummyblit.c`` This contains the dummy text rendering functions used to suppress text output while the bootsplash is shown. ``drivers/tty/vt/keyboard.c`` ``kbd_keycode()`` can call ``bootsplash_disable()`` when the user presses ESC or F1-F12 (changing VT). This is to provide a built-in way of disabling the splash manually at any time. FAQ: Frequently Asked Questions =============================== I want to see the log! How do I show the log? --------------------------------------------- Press ESC while the splash is shown, or remove the ``bootsplash.bootfile`` parameter from the kernel cmdline. Without that parameter, the bootsplash will boot disabled. Why use FB instead of modern DRM/KMS? ------------------------------------- This is a semantic problem: - What memory to draw the splash to? - And what mode will the screen be set to? Using the fbdev emulation solves these issues. Let's start from a bare KMS system, without fbcon, and without fbdev emulation. In this case, as long as userspace doesn't open the KMS device, the state of the screen is undefined. No framebuffer is allocated in video RAM, and no particular mode is set. In this case, we'd have to allocate a framebuffer to show the splash, and set our mode ourselves. This either wastes a screenful of video RAM if the splash is to co-exist with the userspace program's own allocated framebuffer, or there is a flicker as we deactivate and delete the bootsplash's framebuffer and hand control over to userspace. Since we may set a different mode than userspace, we'd also have flicker due to mode switching. This logic is already contained in every KMS driver that performs fbdev emulation. So we might as well use that. And the correct API to do so is fbdev. Plus, we get compatibility with old, pure fbdev drivers for free. With the fbdev emulation, there is *always* a well-defined framebuffer to draw on. And the selection of mode has already been done by the graphics driver, so we don't need to reinvent that wheel, either. Finally, if userspace decides to use /dev/fbX, we don't have to worry about wasting video RAM, either. Why is the bootsplash integrated in fbcon? ------------------------------------------ Right now, the bootsplash is drawn from within fbcon, as this allows us to easily know *when* to draw - i.e. when we're safe from fbcon and userspace drawing all over our beautiful splash logo. Separating them is not easy - see the to-do list below. TO DO list for future development ================================= Second enable/disable switch for the system ------------------------------------------- It may be helpful to differentiate between the system and the user switching off the bootsplash. Thus, the system may make it disappear and reappear e.g. for a password prompt, yet once the user has pressed ESC, it could stay gone. Fix buggy DRM/KMS drivers ------------------------- Currently, the splash code manually checks for fbdev emulation provided by the ast, cirrus, and mgag200 DRM/KMS drivers. These drivers use a manual mechanism similar to deferred I/O for their FB emulation, and thus need to be manually flushed onto the screen in the same way. This may be improved upon in several ways: 1. Changing these drivers to expose the fbdev BO's memory directly, like bochsdrmfb does. 2. Creating a new fb_ops->fb_flush() API to allow the kernel to flush the framebuffer once the bootsplash has been drawn into it. Separating from fbcon --------------------- Separating these two components would yield independence from fbcon being compiled into the kernel, and thus lowering code size in embedded applications. To do this cleanly will involve a clean separation of users of an FB device within the kernel, i.e. fbcon, bootsplash, and userspace. Right now, the legacy fbcon code and VT code co-operate to switch between fbcon and userspace (by setting the VT into KD_GRAPHICS mode). Installing a muxer between these components ensues refactoring of old code and checking for correct locking.