From: Max Staudt <hidden> Date: 2017-10-25 12:46:31
Dear fbdev and fbcon developers,
Could you please voice your opinion on the following patch series?
This series adds simple bootsplash functionality on top of fbcon.
A (simple!) kernel based bootsplash allows system integrators to show an
earlier and more reliable bootsplash, completely hiding the kernel's
text output and VT (the 'quiet' option still displays warnings and a
blinking cursor).
Over the years, there have been many issues with a splash in userspace,
and the easiest fix is to show the splash in the kernel - see the first
commit for details. This is a huge simplification for embedded systems
and desktops alike.
As it is now, the bootsplash is implemented as a modification of fbcon,
but since the userspace ABI is a platform device, it can be moved
elsewhere in the future without breaking userspace.
If you would like an example splash file to test the code with, or even
a tool to generate it, I'm happy to provide them.
Finally, I will re-send the patch with the TODOs removed as soon as the
file format is accepted.
Many thanks to Takashi Iwai and Oliver Neukum for their continuous
feedback on the code during development of this series.
Max Staudt
From: Max Staudt <hidden> Date: 2017-10-25 12:46:34
When the system is woken from sleep or restored after hibernating, we
cannot expect the screen contents to still be present in VRAM. Thus,
we have to redraw the splash if we're currently active.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/fbdev/core/bootsplash.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
From: Max Staudt <hidden> Date: 2017-10-25 12:46:36
Framebuffers with deferred I/O need to be flushed to the screen
explicitly, since we use neither the mmap nor the file I/O abstractions
that handle this for userspace FB clients.
Example: xenfb
Some framebuffer drivers implement lazy access to the screen without
actually exposing a fbdefio interface - we also match some known ones,
currently:
- ast
- cirrus
- mgag200
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/fbdev/core/bootsplash.c | 2 ++
drivers/video/fbdev/core/bootsplash_internal.h | 1 +
drivers/video/fbdev/core/bootsplash_render.c | 32 ++++++++++++++++++++++++++
3 files changed, 35 insertions(+)
@@ -91,3 +91,35 @@ void bootsplash_do_render_background(struct fb_info *info)}}}+++voidbootsplash_do_render_flush(structfb_info*info)+{+/* FB drivers using deferred_io (such as Xen) need to sync the+*screenaftermodifyingitscontents.WhentheFBismmap()ed+*fromuserspace,thishappensviaadirtypagescallback,but+*whenmodifyingtheFBfromthekernel,thereisnosuchthing.+*+*Solet'sissueafakefb_copyarea(copyingtheFBontoitself)+*totricktheFBdriverintosyncingthescreen.+*+*AfewDRMdrivers'FBimplementationsarebrokenbynotusing+*deferred_iowhentheyreallyshould-wematchontheknown+*badonesmanuallyfornow.+*/+if(info->fbdefio+||!strcmp(info->fix.id,"astdrmfb")+||!strcmp(info->fix.id,"cirrusdrmfb")+||!strcmp(info->fix.id,"mgadrmfb")){+structfb_copyareaarea;++area.dx=0;+area.dy=0;+area.width=info->var.xres;+area.height=info->var.yres;+area.sx=0;+area.sy=0;++info->fbops->fb_copyarea(info,&area);+}+}
@@ -0,0 +1,169 @@+What is the Linux bootsplash?+===============++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.++++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 holding /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˜0750++++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.++drivers/tty/vt/vt_ioctl.c++ vt_ioctl() will call bootsplash_disable() when a graphical application+ such as the X server is started (i.e. when setting the VT to KD_GRAPHICS).++++Command line arguments+===========++bool bootsplash.enable Whether to show a splash screen during boot+ (default: off)++string bootsplash.filename Which file in the initrd to load+ (default: /bootsplash)++++sysfs run-time configuration+==============++bool /sys/devices/platform/bootsplash.0/enabled Enable/disable++trigger /sys/devices/platform/bootsplash.0/drop_splash Unload splash data+ and free memory+++Kconfig+====++bool BOOTSPLASH Whether to compile in bootsplash support+ (depends on fbcon compiled in, i.e.+ FRAMEBUFFER_CONSOLE=y)++string BOOTSPLASH_FILE Which file in the initrd to load+ (default: /bootsplash)++++Bootsplash file format+===========++A file specified in the kernel configuration as CONFIG_BOOTSPLASH_FILE or+specified on the command line as bootsplash.filename will be loaded and+displayed as soon as fbcon is initialized.+++There are 3 main blocks in each file:++ - one File header+ - n Picture headers+ - m (Blob header + payload) blocks+++The 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"+ -> The file format version (for incompatible updates, hopefully never)+ -> The background color+ -> Number of picture and blob blocks+ -> Animation speed (we only allow one speed 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.+++A note about alignment:++The bootsplash file is designed to be loaded into memory as-is (plus+performing an endianness conversion before further processing).++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.+++Please see drivers/video/fbdev/core/bootsplash_file.h for further details and+possible values in the file.
From: Max Staudt <hidden> Date: 2017-10-25 12:47:28
This allows showing multiple logos, each in its own position,
relative to the eight screen corners.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/fbdev/core/bootsplash_file.h | 42 ++++++++++++++++++++-
drivers/video/fbdev/core/bootsplash_render.c | 55 +++++++++++++++++++++++++++-
2 files changed, 94 insertions(+), 3 deletions(-)
@@ -87,7 +87,28 @@ struct splash_pic_header {*/u8num_blobs;-u8padding[11];++/* Corner to paint the picture in.+*0-Center+*1-Topleft+*2-Top+*3-Topright+*4-Right+*5-Bottomright+*6-Bottom+*7-Bottomleft+*8-Left+*/+u8corner;++/* Pixel offset from the screen margins.+*Example:Ifthepictureisinthetoprightcorner,itwill+*beplacescorner_offsetpixelsfromthetopand+*corner_pixelsfromtherightmargin.+*/+u8corner_offset;++u8padding[9];}__attribute__((__packed__));
From: Max Staudt <hidden> Date: 2017-10-25 12:47:31
After exiting a KD_GRAPHICS program and falling back to the text
console, a previously enabled splash needs to be fully redrawn.
Without this patch, the following fails:
1. Switch to a text console
2. Enable splash
3. Start X (or any other KD_GRAPHICS program)
4. Exit X
5. Splash is not seen, apart from animations
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/tty/vt/vt.c | 2 ++
drivers/video/fbdev/core/bootsplash.c | 15 +++++++++------
include/linux/bootsplash.h | 4 ++++
3 files changed, 15 insertions(+), 6 deletions(-)
@@ -242,9 +249,7 @@ void bootsplash_enable(void)if(!was_enabled){/* Force a full redraw when the splash is re-activated */-mutex_lock(&splash_global.data_lock);-splash_global.splash_fb=NULL;-mutex_unlock(&splash_global.data_lock);+bootsplash_mark_dirty();queue_work(splash_global.wq,&splash_work_redraw_vc);}
@@ -329,9 +334,7 @@ static int splash_resume(struct device *device)/* Force full redraw on resume since we've probably lost the*framebuffer'scontentsmeanwhile*/-mutex_lock(&splash_global.data_lock);-splash_global.splash_fb=NULL;-mutex_unlock(&splash_global.data_lock);+bootsplash_mark_dirty();if(bootsplash_would_render_now())queue_work(splash_global.wq,&splash_work_redraw_vc);
@@ -1333,6 +1333,15 @@ static void fbcon_cursor(struct vc_data *vc, int mode)inty;intc=scr_readw((u16*)vc->vc_pos);+/* Disable the splash here so we don't have to hook into+*vt_console_print()indrivers/tty/vt/vt.c+*+*We'ddisablethesplashjustbeforethecallto+*hide_cursor()anyway,sothisspotisjustfine.+*/+if(oops_in_progress)+bootsplash_disable();+ops->cur_blink_jiffies=msecs_to_jiffies(vc->vc_cur_blink_ms);if(fbcon_is_inactive(vc,info)||vc->vc_deccm!=1)
@@ -0,0 +1,21 @@+What: /sys/devices/platform/bootsplash.0/enabled+Date: Oct 2017+KernelVersion: 4.14+Contact: Max Staudt <mstaudt@suse.de>+Description:+ Can be set and read.++ 0: Splash is disabled.+ 1: Splash is shown whenever fbcon would show a text console+ (i.e. no graphical application is running), and a splash+ file is loaded.++What: /sys/devices/platform/bootsplash.0/drop_splash+Date: Oct 2017+KernelVersion: 4.14+Contact: Max Staudt <mstaudt@suse.de>+Description:+ Can only be set.++ Any value written will cause the splash to be disabled and+ internal memory structures to be freed.
From: Max Staudt <hidden> Date: 2017-10-25 12:47:59
Load logo(s) from a file and render them in the center of the screen.
This removes the "black screen" functionality, which can now be emulated
by providing a splash file with no pictures and a black background.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/console/Kconfig | 8 +
drivers/video/fbdev/core/Makefile | 2 +-
drivers/video/fbdev/core/bootsplash.c | 57 +++++-
drivers/video/fbdev/core/bootsplash_file.h | 112 ++++++++++++
drivers/video/fbdev/core/bootsplash_internal.h | 36 ++++
drivers/video/fbdev/core/bootsplash_load.c | 242 +++++++++++++++++++++++++
drivers/video/fbdev/core/bootsplash_render.c | 106 ++++++++++-
7 files changed, 557 insertions(+), 6 deletions(-)
create mode 100644 drivers/video/fbdev/core/bootsplash_file.h
create mode 100644 drivers/video/fbdev/core/bootsplash_load.c
@@ -175,6 +175,14 @@ config BOOTSPLASHIfunsure,sayN.Thisistypicallyusedbydistributorsandsystemintegrators.+configBOOTSPLASH_FILE+string"Default full path to bootsplash file"+depends onBOOTSPLASH+default"/bootsplash"+help+Thisfilewillbelookedforintheinitramfsand,iffound,loaded+andusedasabootsplash.+configSTI_CONSOLEbool"STI text console"depends onPARISC
@@ -231,11 +240,33 @@ static ssize_t splash_store_enabled(struct device *device,returncount;}+staticssize_tsplash_store_drop_splash(structdevice*device,+structdevice_attribute*attr,+constchar*buf,size_tcount)+{+if(!buf||!count||!splash_global.filebuf)+returncount;++/* Stop the splash first so we get our text console+*ifwe'recurrentlyonone.+*/+mutex_lock(&splash_global.data_lock);++bootsplash_disable();+bootsplash_free_locked();++mutex_unlock(&splash_global.data_lock);++returncount;+}+staticDEVICE_ATTR(enabled,0644,splash_show_enabled,splash_store_enabled);+staticDEVICE_ATTR(drop_splash,0200,NULL,splash_store_drop_splash);staticstructattribute*splash_dev_attrs[]={&dev_attr_enabled.attr,+&dev_attr_drop_splash.attr,NULL};
@@ -320,6 +355,21 @@ void bootsplash_init(void)gotoerr;}+/* Default splash file to load */+if(!splash_global.filename)+splash_global.filename=CONFIG_BOOTSPLASH_FILE+"."__stringify(BOOTSPLASH_VERSION);+// TODO: Remove the version suffix when upstreaming++/* Load splash from file in initramfs */+if(kernel_read_file_from_path(splash_global.filename,&mem,+&len,2*1024*1024,READING_UNKNOWN)){+pr_err("Failed to read file: %s\n",splash_global.filename);+gotoerr;+}++bootsplash_activate_buf(mem,len);+return;err_device:
@@ -0,0 +1,112 @@+/*+*Kernelbasedbootsplash.+*+*Authors:+*MaxStaudt<mstaudt@suse.com>+*+*+*Verylooselybasedontheoldkernelsplashprojectat+*http://www.bootsplash.org/ and SUSE improvements.+*/++#ifndef __BOOTSPLASH_FILE_H+#define __BOOTSPLASH_FILE_H+++#define BOOTSPLASH_VERSION 55559+++#include<linux/types.h>+#include<linux/kernel.h>+++/*+*On-disktypes+*+*Asplashfileconsistsof:+*-Onesingle'structsplash_file_header'+*-Anarrayof'structsplash_pic_header'+*-Anarrayofrawdatablocks,eachpaddedto16bytesand+*precededbya'structsplash_blob_header'+*+*Asingle-framesplashmaylooklikethis:+*+*+--------------------++*||+*|splash_file_header|+*|->num_blobs=1|+*|->num_pics=1|+*||+*+--------------------++*||+*|splash_pic_header|+*||+*+--------------------++*||+*|splash_blob_header|+*|->type=0|+*|->picture_id=0|+*||+*|(rawRGBdata)|+*|(padto16bytes)|+*||+*+--------------------++*+*Allmulti-bytevaluesarestoredondiskasbigendian,and+*willbeconvertedtoCPUendiannessin-memoryduringloading.+*/++structsplash_file_header{+u8id[16];/* "Linux bootsplash" (no trailing NUL) */++/* Splash file format version to avoid clashes */+u16version;++/* The background color */+u8bg_red;+u8bg_green;+u8bg_blue;+u8bg_reserved;++/* Number of pic/blobs so we can allocate memory for internal+*structuresaheadoftimewhenreadingthefile+*/+u16num_blobs;+u8num_pics;++u8padding[103];+}__attribute__((__packed__));+++structsplash_pic_header{+u16width;+u16height;++/* Number of data packages associated with this picture.+*Currently,theonlyuseformorethan1isforanimations.+*/+u8num_blobs;++u8padding[11];+}__attribute__((__packed__));+++structsplash_blob_header{+/* Length of the data block in bytes. */+u32length;++/* Type of the contents.+*0-RawRGBdata.+*/+u16type;++/* Picture this blob is associated with.+*Blobswillbeaddedtoapictureintheordertheyare+*foundinthefile.+*/+u8picture_id;++u8padding[9];+}__attribute__((__packed__));++#endif
@@ -22,12 +22,31 @@#include<linux/spinlock.h>#include<linux/workqueue.h>+#include"bootsplash_file.h"+/**Runtimetypes*/+structsplash_blob_priv{+structsplash_blob_header*blob_header;+void*data;+};+++structsplash_pic_priv{+structsplash_pic_header*pic_header;++structsplash_blob_priv*blobs;+u16blobs_loaded;+};++structsplash_priv{+/* Bootup and runtime state */+char*filename;+/* This lock only synchronizes the enabled/disabled state**Note:fbcon.cusesthistwice,bycalling
@@ -49,6 +68,18 @@ struct splash_priv {*duringsuspend.*/structworkqueue_struct*wq;++/* Splash data structures including lock for everything below */+structmutexdata_lock;++structfb_info*splash_fb;++union{+u8*filebuf;+structsplash_file_header*header;+};++structsplash_pic_priv*pics;};
@@ -0,0 +1,242 @@+/*+*Kernelbasedbootsplash.+*+*(Loadingandfreeingfunctions)+*+*Authors:+*MaxStaudt<mstaudt@suse.com>+*+*+*Verylooselybasedontheoldkernelsplashprojectat+*http://www.bootsplash.org/ and SUSE improvements.+*/++#define pr_fmt(fmt) "bootsplash: " fmt+++#include<linux/bootsplash.h>+#include<linux/fb.h>+#include<linux/kernel.h>+#include<linux/mutex.h>+#include<linux/printk.h>+#include<linux/types.h>+#include<linux/vmalloc.h>++#include"bootsplash_file.h"+#include"bootsplash_internal.h"+++++/* Free all vmalloc()'d resources.+*+*Tobecalledwiththebootsplashdata_lockheld.+*/+voidbootsplash_free_locked(void)+{+if(splash_global.filebuf&&splash_global.pics){+unsignedinti;++for(i=0;i<splash_global.header->num_pics;i++){+structsplash_pic_priv*pp=&splash_global.pics[i];++vfree(pp->blobs);+}++vfree(splash_global.pics);+splash_global.pics=NULL;+}++if(splash_global.filebuf){+vfree(splash_global.filebuf);+splash_global.filebuf=NULL;+}+}+++++/*+*Loadasplashscreenfromamemorybuffer.+*+*Parsing,andsanitychecks.+*+*Onceavmalloc'dbufferispassedtothisfunction,thebootsplash+*codeisresponsibleforfreeingit-eveninanerrorcase.+*/++intbootsplash_activate_buf(char*buf,longbuflen)+{+unsignedinti;+char*walker;++if(splash_global.filebuf){+pr_err("Won't load splash screen on top of another one.\n");++vfree(buf);+return-ENOMEM;+}+++if(buflen<sizeof(structsplash_file_header)+#ifdef __BIG_ENDIAN+||memcmp(buf,"Linux bootsplash",+#else+||memcmp(buf,"hsalpstoob xuniL",+#endif+sizeof(splash_global.header->id))){+pr_err("Not a bootsplash file.\n");++vfree(buf);+return-EINVAL;+}++pr_info("Loading splash file (%li bytes)\n",buflen);+++mutex_lock(&splash_global.data_lock);++splash_global.filebuf=buf;+++/* Sanity checks */+if(splash_global.header->version!=BOOTSPLASH_VERSION){+pr_err("Loaded v%d file, but we only support version %d\n",+splash_global.header->version,+BOOTSPLASH_VERSION);++gotoerr;+}++if(buflen<sizeof(structsplash_file_header)++splash_global.header->num_pics+*sizeof(structsplash_pic_header)++splash_global.header->num_blobs+*sizeof(structsplash_blob_header)){+pr_err("File incomplete.\n");++gotoerr;+}+++/* Read picture headers */++if(splash_global.header->num_pics){+splash_global.pics=vzalloc(splash_global.header->num_pics+*sizeof(structsplash_pic_priv));+if(!splash_global.pics)+gotoerr;+}++walker=splash_global.filebuf+sizeof(structsplash_file_header);+for(i=0;i<splash_global.header->num_pics;i++){+structsplash_pic_priv*pp=&splash_global.pics[i];+structsplash_pic_header*ph=(void*)walker;++pr_debug("Picture %u: Size %ux%u\n",i,ph->width,ph->height);++if(ph->num_blobs<1){+pr_err("Picture %u: Zero blobs? Aborting load.\n",i);++gotoerr;+}++pp->pic_header=ph;+pp->blobs=vzalloc(ph->num_blobs+*sizeof(structsplash_blob_priv));+if(!pp->blobs){+pr_err("Could not allocate pointer array for picture %d.\n",+i);++ph->num_blobs=0;+}++walker+=sizeof(structsplash_pic_header);+}++++/* Read blob headers */+for(i=0;i<splash_global.header->num_blobs;i++){+structsplash_blob_header*bh=(void*)walker;+structsplash_pic_priv*pp;++if(walker+sizeof(structsplash_blob_header)>buf+buflen)+gotoerr;++walker+=sizeof(structsplash_blob_header);++if(walker+bh->length>buf+buflen)+gotoerr;++if(bh->picture_id>=splash_global.header->num_pics)+gotonextblob;++pp=&splash_global.pics[bh->picture_id];++pr_debug("Blob %u, pic %u, blobs_loaded %u, num_blobs %u.\n",+i,bh->picture_id,+pp->blobs_loaded,pp->pic_header->num_blobs);++if(pp->blobs_loaded>=pp->pic_header->num_blobs)+gotonextblob;++switch(bh->type){+case0:+/* Raw 24-bit packed pixels */+if(bh->length!=pp->pic_header->width+*pp->pic_header->height*3){+pr_err("Blob %u, type 1: Length doesn't match picture.\n",+i);++gotoerr;+}+break;+default:+pr_warn("Blob %u, unknown type %u.\n",i,bh->type);+gotonextblob;+}++pp->blobs[pp->blobs_loaded].blob_header=bh;+pp->blobs[pp->blobs_loaded].data=walker;+pp->blobs_loaded++;++nextblob:+walker+=bh->length;+if(bh->length%16)+walker+=16-(bh->length%16);+}++if(walker!=buf+buflen)+pr_warn("Trailing data in splash file.\n");++/* Walk over pictures and ensure all blob slots are filled */+for(i=0;i<splash_global.header->num_pics;i++){+structsplash_pic_priv*pp=&splash_global.pics[i];++if(pp->blobs_loaded!=pp->pic_header->num_blobs){+pr_err("Picture %u doesn't have all blob slots filled.\n",+i);++gotoerr;+}+}+++/* Force a full redraw when the splash is re-activated */+splash_global.splash_fb=NULL;++pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",+buflen,splash_global.header->num_pics,+splash_global.header->num_blobs);++mutex_unlock(&splash_global.data_lock);++return0;+++err:+bootsplash_free_locked();+mutex_unlock(&splash_global.data_lock);+return-EINVAL;+}
@@ -93,6 +151,48 @@ void bootsplash_do_render_background(struct fb_info *info)}+voidbootsplash_do_render_pictures(structfb_info*info)+{+unsignedinti;++if(!splash_global.filebuf)+return;++for(i=0;i<splash_global.header->num_pics;i++){+structsplash_blob_priv*bp;+structsplash_pic_priv*pp=&splash_global.pics[i];+longdst_xoff,dst_yoff;++if(pp->blobs_loaded<1)+continue;++bp=&pp->blobs[0];++if(!bp||bp->blob_header->type!=0)+continue;++dst_xoff=(info->var.xres-pp->pic_header->width)/2;+dst_yoff=(info->var.yres-pp->pic_header->height)/2;++if(dst_xoff<0+||dst_yoff<0+||dst_xoff+pp->pic_header->width>info->var.xres+||dst_yoff+pp->pic_header->height>info->var.yres){+pr_warn("Picture %u is out of bounds at current resolution: %dx%d\n",+i,info->var.xres,info->var.yres);++continue;+}++/* Draw next splash frame */+splash_convert_to_fb(info->screen_buffer,&info->var,+info->fix.line_length,dst_xoff,dst_yoff,+bp->data,+pp->pic_header->width,pp->pic_header->height);+}+}++voidbootsplash_do_render_flush(structfb_info*info){/* FB drivers using deferred_io (such as Xen) need to sync the
From: Max Staudt <hidden> Date: 2017-10-25 12:48:00
Each 'picture' in the splash file can consist of multiple 'blobs'.
If animation is enabled, these blobs become the frames of an animation,
in the order in which they are stored in the file.
Note: There is only one global timer, so all animations happen at
the same frame rate. It doesn't really make sense to animate
more than one object at a time anyway.
Furthermore, this patch introduces a check for reusing a framebuffer
where the splash has recently been painted on - in this case, we only
redraw the objects that are animated.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/fbdev/core/bootsplash.c | 62 +++++++++++++++++++++++---
drivers/video/fbdev/core/bootsplash_file.h | 31 ++++++++++++-
drivers/video/fbdev/core/bootsplash_internal.h | 5 ++-
drivers/video/fbdev/core/bootsplash_load.c | 24 ++++++++++
drivers/video/fbdev/core/bootsplash_render.c | 28 +++++++++++-
5 files changed, 140 insertions(+), 10 deletions(-)
@@ -64,6 +64,17 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)staticDECLARE_WORK(splash_work_redraw_vc,splash_callback_redraw_vc);+staticvoidsplash_callback_animation(structwork_struct*ignored)+{+if(bootsplash_would_render_now()){+/* This will also re-schedule this delayed worker */+splash_callback_redraw_vc(ignored);+}+}++staticDECLARE_DELAYED_WORK(splash_dwork_animation,splash_callback_animation);++/*
@@ -117,17 +128,45 @@ static bool is_fb_compatible(struct fb_info *info)*/voidbootsplash_render_full(structfb_info*info){+boolis_update=false;+mutex_lock(&splash_global.data_lock);-if(!is_fb_compatible(info))-gotoout;+/* If we've painted on this FB recently, we don't have to do+*thesanitychecksandbackgrounddrawingagain.+*/+if(splash_global.splash_fb=info)+is_update=true;+++if(!is_update){+/* Check whether we actually support this FB. */+splash_global.splash_fb=NULL;++if(!is_fb_compatible(info))+gotoout;-bootsplash_do_render_background(info);+/* Draw the background only once */+bootsplash_do_render_background(info);-bootsplash_do_render_pictures(info);+/* Mark this FB as last seen */+splash_global.splash_fb=info;+}+++bootsplash_do_render_pictures(info,is_update);bootsplash_do_render_flush(info);+bootsplash_do_step_animations();++/* Schedule update for animated splash screens */+if(splash_global.header->frame_ms>0)+queue_delayed_work(splash_global.wq,+&splash_dwork_animation,+msecs_to_jiffies(+splash_global.header->frame_ms));+out:mutex_unlock(&splash_global.data_lock);}
@@ -201,8 +240,14 @@ void bootsplash_enable(void)spin_unlock_irqrestore(&splash_global.state_lock,flags);-if(!was_enabled)+if(!was_enabled){+/* Force a full redraw when the splash is re-activated */+mutex_lock(&splash_global.data_lock);+splash_global.splash_fb=NULL;+mutex_unlock(&splash_global.data_lock);+queue_work(splash_global.wq,&splash_work_redraw_vc);+}}
@@ -281,6 +326,13 @@ ATTRIBUTE_GROUPS(splash_dev);staticintsplash_resume(structdevice*device){+/* Force full redraw on resume since we've probably lost the+*framebuffer'scontentsmeanwhile+*/+mutex_lock(&splash_global.data_lock);+splash_global.splash_fb=NULL;+mutex_unlock(&splash_global.data_lock);+if(bootsplash_would_render_now())queue_work(splash_global.wq,&splash_work_redraw_vc);
@@ -74,7 +74,14 @@ struct splash_file_header {u16num_blobs;u8num_pics;-u8padding[103];+/* Milliseconds to wait before painting the next frame in+*ananimation.+*Thisisactuallyaminimum,asthesystemisallowedto+*stallforlongerbetweenframes.+*/+u16frame_ms;++u8padding[101];}__attribute__((__packed__));
@@ -141,6 +142,13 @@ int bootsplash_activate_buf(char *buf, long buflen)gotoerr;}+if(ph->anim_type>SPLASH_ANIM_LOOP_FORWARD){+pr_warn("Picture %u: Unsupported animation type %u.\n",+i,ph->anim_type);++ph->anim_type=SPLASH_ANIM_NONE;+}+pp->pic_header=ph;pp->blobs=vzalloc(ph->num_blobs*sizeof(structsplash_blob_priv));
@@ -213,6 +221,7 @@ int bootsplash_activate_buf(char *buf, long buflen)/* Walk over pictures and ensure all blob slots are filled */for(i=0;i<splash_global.header->num_pics;i++){structsplash_pic_priv*pp=&splash_global.pics[i];+structsplash_pic_header*ph=pp->pic_header;if(pp->blobs_loaded!=pp->pic_header->num_blobs){pr_err("Picture %u doesn't have all blob slots filled.\n",
@@ -220,9 +229,24 @@ int bootsplash_activate_buf(char *buf, long buflen)gotoerr;}++if(ph->num_blobs<2||ph->anim_loop>pp->blobs_loaded)+/* Nothing to animate or loading error */+ph->anim_type=SPLASH_ANIM_NONE;+elseif(ph->anim_type)+have_anim=true;}+/* Disable animation timer if there is nothing to animate */+if(!have_anim)+splash_global.header->frame_ms=0;++/* Enforce minimum delay between frames */+if(splash_global.header->frame_ms>0+&&splash_global.header->frame_ms<20)+splash_global.header->frame_ms=20;+/* Force a full redraw when the splash is re-activated */splash_global.splash_fb=NULL;
From: Max Staudt <hidden> Date: 2017-10-25 12:48:02
Let's disable the splash if the user presses ESC or F1-F12 on a VT.
The F1-F12 check is to disable the splash on VT switches.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/tty/vt/keyboard.c | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -1353,6 +1355,15 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)}#endif+/* Deactivate bootsplash on ESC or Alt+Fxx VT switch */+if(((keycode>=KEY_F1&&keycode<=KEY_F12)||keycode=KEY_ESC)+&&bootsplash_is_enabled()){+bootsplash_disable();++if(keycode=KEY_ESC)+return;+}+if(kbd->kbdmode=VC_MEDIUMRAW){/**Thisisextendedmediumrawmode,withkeysabove127
From: Max Staudt <hidden> Date: 2017-10-25 12:48:06
When the user requests a clean TTY via the SAK SysRq, that means he
really wants to use the console.
Let's disable the bootsplash, even if the request is not on a VT, as
the user probably knows what he's doing and it's more helpful to get
out of his way.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/tty/sysrq.c | 3 +++
1 file changed, 3 insertions(+)
From: Max Staudt <hidden> Date: 2017-10-25 12:49:18
This is the initial prototype for a lean Linux kernel bootsplash.
It works by replacing fbcon's FB manipulation routines (such as
bitblit, tileblit) with dummy functions, effectively disabling text
output, and drawing the splash directly onto the FB device.
As it is now, it will show a black screen rather than a logo, and
only if manually enabled via the kernel cmdline:
bootsplash.enable=1
The reasons for implementing a bootsplash in kernel space are:
- Quieting things more and nicer than with the quiet boot option:
Currently the 'quiet' boot option does not remove the blinking cursor
and errors are still printed. There are use cases where this is not
desirable (such as embedded and desktop systems, digital signage,
etc.) and a vendor logo is preferable.
- Showing graphics, and never text, when the GUI crashes:
This is an extension of the above use case, where recovery is meant
to happen as invisibly to the user as possible. A system integrator
needs the flexibility to hide "scary text" from users in all cases
other than a panic.
This is especially desirable in embedded systems such as digital
signage.
- Racy VT API:
Userspace bootsplashes and GUIs (e.g. plymouth and X) tend to kick
each other out via the non-exclusive KDSETMODE ioctl. This can
result in situations such as the user being stuck in X with chvt
and Ctrl-Alt-Fx no longer working.
- Mode switching from FB to KMS:
We cannot switch from a generic framebuffer (vesafb, efifb) to a
KMS driver while a userspace splash keeps /dev/fb0 open. The device
will vanish, but the address space is still busy, so the KMS driver
cannot reserve its VRAM.
- Simplification of userspace integration:
Right now, hooking up a splash screen in userspace is quite complex.
Having it in the kernel makes this a breeze, as hooks for
switch_root, remounting r/w, etc. become obsolete.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/console/Kconfig | 24 +++
drivers/video/fbdev/core/Makefile | 3 +
drivers/video/fbdev/core/bootsplash.c | 230 +++++++++++++++++++++++++
drivers/video/fbdev/core/bootsplash_internal.h | 68 ++++++++
drivers/video/fbdev/core/bootsplash_render.c | 93 ++++++++++
drivers/video/fbdev/core/dummyblit.c | 89 ++++++++++
drivers/video/fbdev/core/fbcon.c | 12 ++
drivers/video/fbdev/core/fbcon.h | 5 +
include/linux/bootsplash.h | 45 +++++
9 files changed, 569 insertions(+)
create mode 100644 drivers/video/fbdev/core/bootsplash.c
create mode 100644 drivers/video/fbdev/core/bootsplash_internal.h
create mode 100644 drivers/video/fbdev/core/bootsplash_render.c
create mode 100644 drivers/video/fbdev/core/dummyblit.c
create mode 100644 include/linux/bootsplash.h
@@ -0,0 +1,230 @@+/*+*Kernelbasedbootsplash.+*+*(Mainfile:Gluecode,workers,timer,PM,kernelanduserlandAPI)+*+*Authors:+*MaxStaudt<mstaudt@suse.com>+*+*+*Verylooselybasedontheoldkernelsplashprojectat+*http://www.bootsplash.org/ and SUSE improvements.+*/++#define pr_fmt(fmt) "bootsplash: " fmt+++#include<linux/bootsplash.h>+#include<linux/console.h>+#include<linux/device.h>/* dev_warn() */+#include<linux/fb.h>+#include<linux/fs.h>+#include<linux/kernel.h>+#include<linux/jiffies.h>+#include<linux/module.h>+#include<linux/mutex.h>+#include<linux/platform_device.h>+#include<linux/printk.h>+#include<linux/selection.h>/* console_blanked */+#include<linux/stringify.h>+#include<linux/types.h>+#include<linux/vmalloc.h>+#include<linux/vt_kern.h>+#include<linux/workqueue.h>++#include"bootsplash_internal.h"++++/* We only have one splash screen, so let's keep a single+*globalinstanceoftheinternalstate.+*/+structsplash_privsplash_global;++++++/*+*Workercallbacks+*/++staticvoidsplash_callback_redraw_vc(structwork_struct*ignored)+{+if(console_blanked)+return;++console_lock();+if(vc_cons[fg_console].d)+update_screen(vc_cons[fg_console].d);+console_unlock();+}++staticDECLARE_WORK(splash_work_redraw_vc,splash_callback_redraw_vc);+++++/*+*Rendering:ExternalAPI+*/++staticboolis_fb_compatible(structfb_info*info)+{+if(!(info->flags&FBINFO_BE_MATH)!=!fb_be_math(info)){+dev_warn(info->device,+"Can't draw on foreign endianness framebuffer.\n");++returnfalse;+}++if(info->flags&FBINFO_MISC_TILEBLITTING){+dev_warn(info->device,+"Can't draw splash on tiling framebuffer.\n");++returnfalse;+}++if(info->fix.type!=FB_TYPE_PACKED_PIXELS+||(info->fix.visual!=FB_VISUAL_TRUECOLOR+&&info->fix.visual!=FB_VISUAL_DIRECTCOLOR)){+dev_warn(info->device,+"Can't draw splash on non-packed or non-truecolor framebuffer.\n");++dev_warn(info->device,+" type: %u visual: %u\n",+info->fix.type,info->fix.visual);++returnfalse;+}++if(info->var.bits_per_pixel!=16+&&info->var.bits_per_pixel!=24+&&info->var.bits_per_pixel!=32){+dev_warn(info->device,+"We only support drawing on framebuffers with 16, 24, or 32 bpp, not %d.\n",+info->var.bits_per_pixel);++returnfalse;+}++returntrue;+}++/*+*Calledwhenanfbconinstanceisactivatedorrefreshed.+*/+voidbootsplash_render_full(structfb_info*info)+{+if(!is_fb_compatible(info))+return;++bootsplash_do_render_background(info);+}+++++/*+*Externalstatusenquiryandon/offswitch+*/++boolbootsplash_would_render_now(void)+{+return!oops_in_progress+&&!console_blanked+&&bootsplash_is_enabled();+}++boolbootsplash_is_enabled(void)+{+unsignedlongflags;+boolwas_enabled;++/* Take the lock as a memory barrier around splash_global.enabled */+spin_lock_irqsave(&splash_global.state_lock,flags);+was_enabled=splash_global.enabled;+spin_unlock_irqrestore(&splash_global.state_lock,flags);++returnwas_enabled;+}++voidbootsplash_disable(void)+{+unsignedlongflags;+boolwas_enabled;++spin_lock_irqsave(&splash_global.state_lock,flags);++was_enabled=splash_global.enabled;+splash_global.enabled=false;++spin_unlock_irqrestore(&splash_global.state_lock,flags);+++if(was_enabled){+if(oops_in_progress){+/* Redraw screen now so we can see a panic */+if(vc_cons[fg_console].d)+update_screen(vc_cons[fg_console].d);+}else{+/* No urgency, redraw at next opportunity */+queue_work(splash_global.wq,&splash_work_redraw_vc);+}+}+}++voidbootsplash_enable(void)+{+unsignedlongflags;+boolwas_enabled;++if(oops_in_progress)+return;++spin_lock_irqsave(&splash_global.state_lock,flags);++was_enabled=splash_global.enabled;+splash_global.enabled=true;++spin_unlock_irqrestore(&splash_global.state_lock,flags);+++if(!was_enabled)+queue_work(splash_global.wq,&splash_work_redraw_vc);+}+++++/*+*Maininit/exitfunctions+*/++voidbootsplash_init(void)+{+/* Initialized already? */+if(splash_global.wq)+return;+++spin_lock_init(&splash_global.state_lock);+if(!splash_global.wq)+splash_global.wq=alloc_workqueue("bootsplash",+WQ_UNBOUND|WQ_FREEZABLE,+1);+if(!splash_global.wq){+pr_err("Failed to allocate work queue.\n");+gotoerr;+}++return;++err:+pr_err("Failed to initialize.\n");+}++++module_param_named(enable,splash_global.enabled,bool,0444);+MODULE_PARM_DESC(enable,"Enable/disable kernel bootsplash");
@@ -0,0 +1,68 @@+/*+*Kernelbasedbootsplash.+*+*(Internaldatastructuresusedatruntime)+*+*Authors:+*MaxStaudt<mstaudt@suse.com>+*+*+*Verylooselybasedontheoldkernelsplashprojectat+*http://www.bootsplash.org/ and SUSE improvements.+*/++#ifndef __BOOTSPLASH_INTERNAL_H+#define __BOOTSPLASH_INTERNAL_H+++#include<linux/types.h>+#include<linux/fb.h>+#include<linux/kernel.h>+#include<linux/mutex.h>+#include<linux/spinlock.h>+#include<linux/workqueue.h>+++/*+*Runtimetypes+*/++structsplash_priv{+/* This lock only synchronizes the enabled/disabled state+*+*Note:fbcon.cusesthistwice,bycalling+*bootsplash_would_render_now()inset_blitting_type()and+*infbcon_switch().+*Thisisracy,buteventuallyconsistent:Turningthe+*splashon/offwillcausearedraw,whichcalls+*fbcon_switch(),whichcallsset_blitting_type().+*Sothelaston/offtogglewillmakethingsconsistent.+*/+spinlock_tstate_lock;+boolenabled;++/* We use our own workqueue so we don't have to worry about blocking+*onconsole_lock()whileanimatingandthusfreezingthesystem+*duringsuspend.+*/+structworkqueue_struct*wq;+};+++++/*+*Internalglobalvariables+*/+externstructsplash_privsplash_global;+++++/*+*Renderingfunctions+*/++voidbootsplash_do_render_background(structfb_info*info);++#endif
@@ -0,0 +1,93 @@+/*+*Kernelbasedbootsplash.+*+*(Renderingfunctions)+*+*Authors:+*MaxStaudt<mstaudt@suse.com>+*+*+*Verylooselybasedontheoldkernelsplashprojectat+*http://www.bootsplash.org/ and SUSE improvements.+*/++#define pr_fmt(fmt) "bootsplash: " fmt+++#include<linux/bootsplash.h>+#include<linux/fb.h>+#include<linux/kernel.h>+#include<linux/printk.h>+#include<linux/types.h>++#include"bootsplash_internal.h"+++++/*+*Rendering:Internaldrawingroutines+*/+++/* Pack pixel into target format and do Big/Little Endian handling.+*Thiswouldbeagoodplacetohandleendiannessconversionifnecessary.+*/+staticinlineu32pack_pixel(structfb_var_screeninfo*dst_var,+u8red,u8green,u8blue)+{+u32dstpix;++/* Quantize pixel */+red=red>>(8-dst_var->red.length);+green=green>>(8-dst_var->green.length);+blue=blue>>(8-dst_var->blue.length);++/* Pack pixel */+dstpix=red<<(dst_var->red.offset)+|green<<(dst_var->green.offset)+|blue<<(dst_var->blue.offset);++/* Move packed pixel to the beginning of the memory cell,+*sowecanmemcpy()itouteasily+*/+#ifdef __BIG_ENDIAN+switch(dst_var->bits_per_pixel){+case16:+dstpix<<=16;+break;+case24:+dstpix<<=8;+break;+case32:+break;+}+#else+/* This is intrinsically unnecessary on Little Endian */+#endif++returndstpix;+}+++voidbootsplash_do_render_background(structfb_info*info)+{+unsignedintx,y;+u32dstpix;+u32dst_octpp=info->var.bits_per_pixel/8;++dstpix=pack_pixel(&info->var,+0,+0,+0);++for(y=0;y<info->var.yres_virtual;y++){+u8*dstline=info->screen_buffer+(y*info->fix.line_length);++for(x=0;x<info->var.xres_virtual;x++){+memcpy(dstline,&dstpix,dst_octpp);++dstline+=dst_octpp;+}+}+}
From: Max Staudt <hidden> Date: 2017-10-25 12:49:23
This allows us to export a userland API via sysfs, showing/hiding the
splash on request by dracut, systemd, or other init systems.
Signed-off-by: Max Staudt <redacted>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
drivers/video/fbdev/core/bootsplash.c | 83 ++++++++++++++++++++++++++
drivers/video/fbdev/core/bootsplash_internal.h | 3 +
2 files changed, 86 insertions(+)
@@ -41,6 +41,9 @@ struct splash_priv {spinlock_tstate_lock;boolenabled;+/* Our gateway to userland via sysfs */+structplatform_device*splash_device;+/* We use our own workqueue so we don't have to worry about blocking*onconsole_lock()whileanimatingandthusfreezingthesystem*duringsuspend.
Fix "help" indentation: (from process/coding-style:)
Lines under a ``config`` definition
are indented with one tab, while help text is indented an additional two
spaces.
quoted hunk
+ ---help---+ This option enables the Linux bootsplash screen.++ The bootsplash is a full-screen logo or animation indicating a+ booting system. It replaces the classic scrolling text with a+ graphical alternative, similar to other systems.++ Since this is technically implemented as a hook on top of fbcon,+ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a+ framebuffer driver is active. Thus, to get a text-free boot,+ the system needs to boot with vesafb, efifb, or similar.++ Once built into the kernel, the bootsplash needs to be enabled+ with bootsplash.enabled=1 and a splash file needs to be supplied.++ Further documentation can be found in:+ Documentation/fb/bootsplash.txt++ If unsure, say N.+ This is typically used by distributors and system integrators.+ config STI_CONSOLE bool "STI text console" depends on PARISC
@@ -175,6 +175,14 @@ config BOOTSPLASHIfunsure,sayN.Thisistypicallyusedbydistributorsandsystemintegrators.+configBOOTSPLASH_FILE+string"Default full path to bootsplash file"+depends onBOOTSPLASH+default"/bootsplash"+help+Thisfilewillbelookedforintheinitramfsand,iffound,loaded+andusedasabootsplash.
Some people try to avoid using initramfs.
Can one have a bootsplash without initramfs?
or maybe this is just for distros, who expect the initramfs to be there.
--
~Randy
@@ -0,0 +1,169 @@++Bootsplash file format+===========> ++A file specified in the kernel configuration as CONFIG_BOOTSPLASH_FILE or+specified on the command line as bootsplash.filename will be loaded and+displayed as soon as fbcon is initialized.
How do you create or edit such a file? Do you have a program especially for
this? Hopefully not just a hex editor...
--
~Randy
@@ -175,6 +175,14 @@ config BOOTSPLASHIfunsure,sayN.Thisistypicallyusedbydistributorsandsystemintegrators.+configBOOTSPLASH_FILE+string"Default full path to bootsplash file"+depends onBOOTSPLASH+default"/bootsplash"+help+Thisfilewillbelookedforintheinitramfsand,iffound,loaded+andusedasabootsplash.
Some people try to avoid using initramfs.
Can one have a bootsplash without initramfs?
The current code is apparently not capable, but it shouldn't be too
difficult to re-use the built-in firmware. i.e. essentially copying
fw_get_builtin_firmware() in drivers/base/firmware_class.c.
Also the bootsplash can appear after mounting the rootfs, too. Before
that, it's simply a blank screen. So it's not entirely useless even
without initrd / initramfs.
thanks,
Takashi
@@ -0,0 +1,169 @@++Bootsplash file format+===========>> ++A file specified in the kernel configuration as CONFIG_BOOTSPLASH_FILE or+specified on the command line as bootsplash.filename will be loaded and+displayed as soon as fbcon is initialized.
How do you create or edit such a file? Do you have a program especially for
this? Hopefully not just a hex editor...
Very good question.
I definitely already have a primitive tool for this. However I'm unsure where to put it - it's a fairly low-level tool, so should I add it to the kernel tree?
How about bootsplash_file.h - I guess I should I move it to include/uapi/linux/ so external tools can use it?
Thanks
Max
@@ -175,6 +175,14 @@ config BOOTSPLASHIfunsure,sayN.Thisistypicallyusedbydistributorsandsystemintegrators.+configBOOTSPLASH_FILE+string"Default full path to bootsplash file"+depends onBOOTSPLASH+default"/bootsplash"+help+Thisfilewillbelookedforintheinitramfsand,iffound,loaded+andusedasabootsplash.
Some people try to avoid using initramfs.
Can one have a bootsplash without initramfs?
The current code is apparently not capable, but it shouldn't be too
difficult to re-use the built-in firmware. i.e. essentially copying
fw_get_builtin_firmware() in drivers/base/firmware_class.c.
Also the bootsplash can appear after mounting the rootfs, too. Before
that, it's simply a blank screen. So it's not entirely useless even
without initrd / initramfs.
@@ -0,0 +1,169 @@++Bootsplash file format+===========>>> ++A file specified in the kernel configuration as CONFIG_BOOTSPLASH_FILE or+specified on the command line as bootsplash.filename will be loaded and+displayed as soon as fbcon is initialized.
How do you create or edit such a file? Do you have a program especially for
this? Hopefully not just a hex editor...
Very good question.
I definitely already have a primitive tool for this. However I'm unsure where to put it - it's a fairly low-level tool, so should I add it to the kernel tree?
maybe in $kernel/tools/
How about bootsplash_file.h - I guess I should I move it to include/uapi/linux/ so external tools can use it?
From: Pavel Machek <hidden> Date: 2017-11-09 11:56:58
Hi!
Dear fbdev and fbcon developers,
Could you please voice your opinion on the following patch series?
This series adds simple bootsplash functionality on top of fbcon.
A (simple!) kernel based bootsplash allows system integrators to show an
earlier and more reliable bootsplash, completely hiding the kernel's
text output and VT (the 'quiet' option still displays warnings and a
blinking cursor).
"More reliable bootsplash" seems like an anti-goal. More reliable boot
should be the goal...
You should be able to display nice splash screen from initrd...
We may want to fix the blinking cursor.
But if there are warnings, it is better to see the warnings then to
hide them. If root filesystem can't be mounted (for example) it is
good to know the reason, not to stare at the blank screen (or at boot splash).
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
From: Oliver Neukum <oneukum@suse.com> Date: 2017-11-09 12:40:21
Am Donnerstag, den 09.11.2017, 12:56 +0100 schrieb Pavel Machek:
"More reliable bootsplash" seems like an anti-goal. More reliable boot
should be the goal...
You should be able to display nice splash screen from initrd...
We may want to fix the blinking cursor.
But if there are warnings, it is better to see the warnings then to
hide them. If root filesystem can't be mounted (for example) it is
good to know the reason, not to stare at the blank screen (or at boot splash).
Hi,
well you are not required to use a boot splash. Though I note that
many people want a boot splash. However, if you use a boot splash
at all, you will not see the messages, so how does it matter to you
if it comes out of the initrd?
And of course we want a reliable boot, but that is an orthogonal issue.
And this solution is more reliable than plymouth.
Regards
Oliver
On Thu, 09 Nov 2017 12:56:55 +0100,
Pavel Machek wrote:
Hi!
quoted
Dear fbdev and fbcon developers,
Could you please voice your opinion on the following patch series?
This series adds simple bootsplash functionality on top of fbcon.
A (simple!) kernel based bootsplash allows system integrators to show an
earlier and more reliable bootsplash, completely hiding the kernel's
text output and VT (the 'quiet' option still displays warnings and a
blinking cursor).
"More reliable bootsplash" seems like an anti-goal. More reliable boot
should be the goal...
You should be able to display nice splash screen from initrd...
We may want to fix the blinking cursor.
But if there are warnings, it is better to see the warnings then to
hide them. If root filesystem can't be mounted (for example) it is
good to know the reason, not to stare at the blank screen (or at boot splash).
In theory, we can put a bootsplash_disable() call automatically when
the certain level of kernel message appears, too. It's a question
whether such behavior should be dynamically configurable or not,
though.
BTW, one thing that is bad with quiet boot option is that it hides
always messages and shows only errors. With this bootsplash scenario,
you can boot without quiet option. Once when the splash turned off
(either by user action like key input or by some kernel trigger),
you'll see the whole messages, thus have far more information there.
thanks,
Takashi
From: Pavel Machek <hidden> Date: 2017-11-09 18:45:26
On Thu 2017-11-09 13:36:16, Oliver Neukum wrote:
Am Donnerstag, den 09.11.2017, 12:56 +0100 schrieb Pavel Machek:
quoted
"More reliable bootsplash" seems like an anti-goal. More reliable boot
should be the goal...
You should be able to display nice splash screen from initrd...
We may want to fix the blinking cursor.
But if there are warnings, it is better to see the warnings then to
hide them. If root filesystem can't be mounted (for example) it is
good to know the reason, not to stare at the blank screen (or at boot splash).
Hi,
well you are not required to use a boot splash. Though I note that
many people want a boot splash. However, if you use a boot splash
at all, you will not see the messages, so how does it matter to you
if it comes out of the initrd?
On Thu, 09 Nov 2017 19:45:23 +0100,
Pavel Machek wrote:
On Thu 2017-11-09 13:36:16, Oliver Neukum wrote:
quoted
Am Donnerstag, den 09.11.2017, 12:56 +0100 schrieb Pavel Machek:
quoted
"More reliable bootsplash" seems like an anti-goal. More reliable boot
should be the goal...
You should be able to display nice splash screen from initrd...
We may want to fix the blinking cursor.
But if there are warnings, it is better to see the warnings then to
hide them. If root filesystem can't be mounted (for example) it is
good to know the reason, not to stare at the blank screen (or at boot splash).
Hi,
well you are not required to use a boot splash. Though I note that
many people want a boot splash. However, if you use a boot splash
at all, you will not see the messages, so how does it matter to you
if it comes out of the initrd?
Of course I'm not required to use it.
OTOH you don't need to patch kernel to get nice bootsplash. If it
means improving "quiet" option to hide the cursor, so be it.
We can achieve this even now by passing vt.global_cursor_default=0
boot option. But you'd need to reset the cursor explicitly before
starting the login prompt, though.
Also, the whole kernel messages can be suppressed by passing
console_loglevel=1 option, too.
So far, so good. However...
You
should be able to do the rest, already.
... the devils are in details. We have lots of issues with the most
commonly used bootsplash, plymouth, which should have been "nice".
The most notable one is that it blocks the switching to KMS driver.
It's basically a long-standing kernel bug, and you can see it easily
on your machine, even on VM.
- Boot with VESA or EFI FB. DRM driver isn't loaded yet.
- Run some app (splash) to open /dev/fb0 and keep it opened.
- Load the native DRM driver (i915, cirrus and whatever) now.
At this point, your screen freezes. It's because the KMS driver
load fails due to the process opening /dev/fb* of the old FB to be
kicked out.
For avoiding such a situation, many distros disable the bootsplash on
FB but only run on DRM mode (so the splash on the first FB is
skipped). But it means you'll have no splash for non-KMS systems.
Also, when plymouth runs DRM mode, this itself conflicts with the
invocation of X, which requires the DRM exclusively again. Such a DRM
device management mechanism is missing in the whole picture. Maybe we
need some helper along with logind or such...
Last but not least, plymouth grabs the whole input because it needs to
capture the input for turning on/off splash and for allowing the
decrypt password prompt; this often leads to a stall at boot when
plymouth doesn't react properly.
That said, quite lots of issues come from plymouth itself, but yet
some fundamental issues need to be addressed in the kernel, too.
Takashi