linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/14] Kernel based bootsplash
@ 2017-10-25 12:45 Max Staudt
  2017-10-25 12:45 ` [RFC 01/14] bootsplash: Initial implementation showing black screen Max Staudt
                   ` (14 more replies)
  0 siblings, 15 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [RFC 01/14] bootsplash: Initial implementation showing black screen
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 17:26   ` Randy Dunlap
  2017-10-25 12:45 ` [RFC 02/14] bootsplash: Add platform device Max Staudt
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 7f1f1fbcef9e..a6617c07229a 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
          such that other users of the framebuffer will remain normally
          oriented.
 
+config BOOTSPLASH
+	bool "Bootup splash screen"
+	depends on FRAMEBUFFER_CONSOLE=y
+        ---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
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index 73493bbd7a15..66895321928e 100644
--- a/drivers/video/fbdev/core/Makefile
+++ b/drivers/video/fbdev/core/Makefile
@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
 obj-$(CONFIG_FB_SYS_FOPS)      += fb_sys_fops.o
 obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
+
+obj-$(CONFIG_BOOTSPLASH)       += bootsplash.o bootsplash_render.o \
+                                  dummyblit.o
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
new file mode 100644
index 000000000000..7a6fd6f8076a
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -0,0 +1,230 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * 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
+ * global instance of the internal state.
+ */
+struct splash_priv splash_global;
+
+
+
+
+
+/*
+ * Worker callbacks
+ */
+
+static void splash_callback_redraw_vc(struct work_struct *ignored)
+{
+	if (console_blanked)
+		return;
+
+	console_lock();
+	if (vc_cons[fg_console].d)
+		update_screen(vc_cons[fg_console].d);
+	console_unlock();
+}
+
+static DECLARE_WORK(splash_work_redraw_vc, splash_callback_redraw_vc);
+
+
+
+
+/*
+ * Rendering: External API
+ */
+
+static bool is_fb_compatible(struct fb_info *info)
+{
+	if (!(info->flags & FBINFO_BE_MATH) != !fb_be_math(info)) {
+		dev_warn(info->device,
+			 "Can't draw on foreign endianness framebuffer.\n");
+
+		return false;
+	}
+
+	if (info->flags & FBINFO_MISC_TILEBLITTING) {
+		dev_warn(info->device,
+			 "Can't draw splash on tiling framebuffer.\n");
+
+		return false;
+	}
+
+	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);
+
+		return false;
+	}
+
+	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);
+
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Called when an fbcon instance is activated or refreshed.
+ */
+void bootsplash_render_full(struct fb_info *info)
+{
+	if (!is_fb_compatible(info))
+		return;
+
+	bootsplash_do_render_background(info);
+}
+
+
+
+
+/*
+ * External status enquiry and on/off switch
+ */
+
+bool bootsplash_would_render_now(void)
+{
+	return !oops_in_progress
+		&& !console_blanked
+		&& bootsplash_is_enabled();
+}
+
+bool bootsplash_is_enabled(void)
+{
+	unsigned long flags;
+	bool was_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);
+
+	return was_enabled;
+}
+
+void bootsplash_disable(void)
+{
+	unsigned long flags;
+	bool was_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);
+		}
+	}
+}
+
+void bootsplash_enable(void)
+{
+	unsigned long flags;
+	bool was_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);
+}
+
+
+
+
+/*
+ * Main init/exit functions
+ */
+
+void bootsplash_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");
+		goto err;
+	}
+
+	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");
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
new file mode 100644
index 000000000000..4cec02774652
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -0,0 +1,68 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Internal data structures used at runtime)
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * 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>
+
+
+/*
+ * Runtime types
+ */
+
+struct splash_priv {
+	/* This lock only synchronizes the enabled/disabled state
+	 *
+	 * Note: fbcon.c uses this twice, by calling
+	 *       bootsplash_would_render_now() in set_blitting_type() and
+	 *       in fbcon_switch().
+	 *       This is racy, but eventually consistent: Turning the
+	 *       splash on/off will cause a redraw, which calls
+	 *       fbcon_switch(), which calls set_blitting_type().
+	 *       So the last on/off toggle will make things consistent.
+	 */
+	spinlock_t state_lock;
+	bool enabled;
+
+	/* We use our own workqueue so we don't have to worry about blocking
+	 * on console_lock() while animating and thus freezing the system
+	 * during suspend.
+	 */
+	struct workqueue_struct *wq;
+};
+
+
+
+
+/*
+ * Internal global variables
+ */
+extern struct splash_priv splash_global;
+
+
+
+
+/*
+ * Rendering functions
+ */
+
+void bootsplash_do_render_background(struct fb_info *info);
+
+#endif
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
new file mode 100644
index 000000000000..ceb19c34fd61
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -0,0 +1,93 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Rendering functions)
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * 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: Internal drawing routines
+ */
+
+
+/* Pack pixel into target format and do Big/Little Endian handling.
+ * This would be a good place to handle endianness conversion if necessary.
+ */
+static inline u32 pack_pixel(struct fb_var_screeninfo *dst_var,
+				u8 red, u8 green, u8 blue)
+{
+	u32 dstpix;
+
+	/* 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,
+	 * so we can memcpy() it out easily
+	 */
+#ifdef __BIG_ENDIAN
+	switch (dst_var->bits_per_pixel) {
+	case 16:
+		dstpix <<= 16;
+		break;
+	case 24:
+		dstpix <<= 8;
+		break;
+	case 32:
+		break;
+	}
+#else
+	/* This is intrinsically unnecessary on Little Endian */
+#endif
+
+	return dstpix;
+}
+
+
+void bootsplash_do_render_background(struct fb_info *info)
+{
+	unsigned int x, y;
+	u32 dstpix;
+	u32 dst_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;
+		}
+	}
+}
diff --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c
new file mode 100644
index 000000000000..1c574caa94e4
--- /dev/null
+++ b/drivers/video/fbdev/core/dummyblit.c
@@ -0,0 +1,89 @@
+/*
+ *  linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
+ *
+ *      Copyright (C) 2017 Max Staudt <mstaudt@suse.de>
+ *
+ *  These functions are used in place of blitblit/tileblit to suppress
+ *  fbcon's text output while a splash is shown.
+ *
+ *  Only suppressing actual rendering keeps the text buffer in the VC layer
+ *  intact and makes it easy to switch back from the bootsplash to a full
+ *  text console with a simple redraw (with the original functions in place).
+ *
+ *  Based on linux/drivers/video/fbdev/core/bitblit.c
+ *       and linux/drivers/video/fbdev/core/tileblit.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <asm/types.h>
+#include "fbcon.h"
+
+static void dummy_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+			int sx, int dy, int dx, int height, int width)
+{
+	;
+}
+
+static void dummy_clear(struct vc_data *vc, struct fb_info *info, int sy,
+			int sx, int height, int width)
+{
+	;
+}
+
+static void dummy_putcs(struct vc_data *vc, struct fb_info *info,
+			const unsigned short *s, int count, int yy, int xx,
+			int fg, int bg)
+{
+	;
+}
+
+static void dummy_clear_margins(struct vc_data *vc, struct fb_info *info,
+				int color, int bottom_only)
+{
+	;
+}
+
+static void dummy_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+			int softback_lines, int fg, int bg)
+{
+	;
+}
+
+static int dummy_update_start(struct fb_info *info)
+{
+	/* Copied from bitblit.c and tileblit.c
+	 *
+	 * As of Linux 4.12, nobody seems to care about our return value.
+	 */
+	struct fbcon_ops *ops = info->fbcon_par;
+	int err;
+
+	err = fb_pan_display(info, &ops->var);
+	ops->var.xoffset = info->var.xoffset;
+	ops->var.yoffset = info->var.yoffset;
+	ops->var.vmode = info->var.vmode;
+	return err;
+}
+
+void fbcon_set_dummyops(struct fbcon_ops *ops)
+{
+	ops->bmove = dummy_bmove;
+	ops->clear = dummy_clear;
+	ops->putcs = dummy_putcs;
+	ops->clear_margins = dummy_clear_margins;
+	ops->cursor = dummy_cursor;
+	ops->update_start = dummy_update_start;
+	ops->rotate_font = NULL;
+}
+EXPORT_SYMBOL(fbcon_set_dummyops);
+
+MODULE_AUTHOR("Max Staudt <mstaudt@suse.de>");
+MODULE_DESCRIPTION("Dummy Blitting Operation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 04612f938bab..4ac1a33be418 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -80,6 +80,7 @@
 #include <asm/irq.h>
 
 #include "fbcon.h"
+#include <linux/bootsplash.h>
 
 #ifdef FBCONDEBUG
 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)
 	for (i = first_fb_vc; i <= last_fb_vc; i++)
 		con2fb_map[i] = info_idx;
 
+	bootsplash_init();
+
 	err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
 				fbcon_is_default);
 
@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 	else {
 		fbcon_set_rotation(info);
 		fbcon_set_bitops(ops);
+
+		if (bootsplash_would_render_now())
+			fbcon_set_dummyops(ops);
 	}
 }
 
@@ -683,6 +689,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 	ops->p = &fb_display[vc->vc_num];
 	fbcon_set_rotation(info);
 	fbcon_set_bitops(ops);
+
+	if (bootsplash_would_render_now())
+		fbcon_set_dummyops(ops);
 }
 
 static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
@@ -2184,6 +2193,9 @@ static int fbcon_switch(struct vc_data *vc)
 	info = registered_fb[con2fb_map[vc->vc_num]];
 	ops = info->fbcon_par;
 
+	if (bootsplash_would_render_now())
+		bootsplash_render_full(info);
+
 	if (softback_top) {
 		if (softback_lines)
 			fbcon_set_origin(vc);
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 18f3ac144237..45f94347fe5e 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
 #define SCROLL_REDRAW	   0x004
 #define SCROLL_PAN_REDRAW  0x005
 
+#ifdef CONFIG_BOOTSPLASH
+extern void fbcon_set_dummyops(struct fbcon_ops *ops);
+#else /* CONFIG_BOOTSPLASH */
+#define fbcon_set_dummyops(x)
+#endif /* CONFIG_BOOTSPLASH */
 #ifdef CONFIG_FB_TILEBLITTING
 extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
 #endif
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
new file mode 100644
index 000000000000..101e70818363
--- /dev/null
+++ b/include/linux/bootsplash.h
@@ -0,0 +1,45 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * http://www.bootsplash.org/ and SUSE improvements.
+ */
+
+#ifndef __LINUX_BOOTSPLASH_H
+#define __LINUX_BOOTSPLASH_H
+
+#include <linux/fb.h>
+
+
+#ifdef CONFIG_BOOTSPLASH
+
+extern void bootsplash_render_full(struct fb_info *info);
+
+extern bool bootsplash_would_render_now(void);
+
+extern bool bootsplash_is_enabled(void);
+extern void bootsplash_disable(void);
+extern void bootsplash_enable(void);
+
+extern void bootsplash_init(void);
+
+#else /* CONFIG_BOOTSPLASH */
+
+#define bootsplash_render_full(x)
+
+#define bootsplash_would_render_now() (false)
+
+#define bootsplash_is_enabled() (false)
+#define bootsplash_disable()
+#define bootsplash_enable()
+
+#define bootsplash_init()
+
+#endif /* CONFIG_BOOTSPLASH */
+
+
+#endif
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 02/14] bootsplash: Add platform device
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
  2017-10-25 12:45 ` [RFC 01/14] bootsplash: Initial implementation showing black screen Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 03/14] bootsplash: Flush framebuffer after drawing Max Staudt
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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(+)

diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index 7a6fd6f8076a..7eb2126c3a31 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -198,6 +198,58 @@ void bootsplash_enable(void)
 
 
 /*
+ * Userland API via platform device in sysfs
+ */
+
+static ssize_t splash_show_enabled(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", splash_global.enabled);
+}
+
+static ssize_t splash_store_enabled(struct device *device,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	bool enable;
+	int err;
+
+	if (!buf || !count)
+		return -EFAULT;
+
+	err = kstrtobool(buf, &enable);
+	if (err)
+		return err;
+
+	if (enable)
+		bootsplash_enable();
+	else
+		bootsplash_disable();
+
+	return count;
+}
+
+static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
+
+
+static struct attribute *splash_dev_attrs[] = {
+	&dev_attr_enabled.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(splash_dev);
+
+
+static struct platform_driver splash_driver = {
+	.driver = {
+		.name = "bootsplash",
+	},
+};
+
+
+
+
+/*
  * Main init/exit functions
  */
 
@@ -208,6 +260,32 @@ void bootsplash_init(void)
 		return;
 
 
+	/* Register platform device to export user API */
+	if (!splash_global.splash_device) {
+		int ret;
+
+		ret = platform_driver_register(&splash_driver);
+		if (ret) {
+			pr_err("platform_driver_register() failed: %d\n", ret);
+			goto err;
+		}
+
+		splash_global.splash_device
+			= platform_device_alloc("bootsplash", 0);
+
+		if (!splash_global.splash_device) {
+			goto err_driver;
+		}
+
+		splash_global.splash_device->dev.groups = splash_dev_groups;
+
+		platform_device_add(splash_global.splash_device);
+		if (ret) {
+			pr_err("platform_device_add() failed: %d\n", ret);
+			goto err_device;
+		}
+	}
+
 	spin_lock_init(&splash_global.state_lock);
 	if (!splash_global.wq)
 		splash_global.wq = alloc_workqueue("bootsplash",
@@ -220,6 +298,11 @@ void bootsplash_init(void)
 
 	return;
 
+err_device:
+	platform_device_put(splash_global.splash_device);
+	splash_global.splash_device = NULL;
+err_driver:
+	platform_driver_unregister(&splash_driver);
 err:
 	pr_err("Failed to initialize.\n");
 }
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
index 4cec02774652..41d519d88baa 100644
--- a/drivers/video/fbdev/core/bootsplash_internal.h
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -41,6 +41,9 @@ struct splash_priv {
 	spinlock_t state_lock;
 	bool enabled;
 
+	/* Our gateway to userland via sysfs */
+	struct platform_device *splash_device;
+
 	/* We use our own workqueue so we don't have to worry about blocking
 	 * on console_lock() while animating and thus freezing the system
 	 * during suspend.
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 03/14] bootsplash: Flush framebuffer after drawing
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
  2017-10-25 12:45 ` [RFC 01/14] bootsplash: Initial implementation showing black screen Max Staudt
  2017-10-25 12:45 ` [RFC 02/14] bootsplash: Add platform device Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 04/14] bootsplash: Redraw on suspend/hibernate Max Staudt
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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(+)

diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index 7eb2126c3a31..8f1c1c165401 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -120,6 +120,8 @@ void bootsplash_render_full(struct fb_info *info)
 		return;
 
 	bootsplash_do_render_background(info);
+
+	bootsplash_do_render_flush(info);
 }
 
 
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
index 41d519d88baa..c0653dd7807b 100644
--- a/drivers/video/fbdev/core/bootsplash_internal.h
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -67,5 +67,6 @@ extern struct splash_priv splash_global;
  */
 
 void bootsplash_do_render_background(struct fb_info *info);
+void bootsplash_do_render_flush(struct fb_info *info);
 
 #endif
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
index ceb19c34fd61..460ae0168cb0 100644
--- a/drivers/video/fbdev/core/bootsplash_render.c
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -91,3 +91,35 @@ void bootsplash_do_render_background(struct fb_info *info)
 		}
 	}
 }
+
+
+void bootsplash_do_render_flush(struct fb_info *info)
+{
+	/* FB drivers using deferred_io (such as Xen) need to sync the
+	 * screen after modifying its contents. When the FB is mmap()ed
+	 * from userspace, this happens via a dirty pages callback, but
+	 * when modifying the FB from the kernel, there is no such thing.
+	 *
+	 * So let's issue a fake fb_copyarea (copying the FB onto itself)
+	 * to trick the FB driver into syncing the screen.
+	 *
+	 * A few DRM drivers' FB implementations are broken by not using
+	 * deferred_io when they really should - we match on the known
+	 * bad ones manually for now.
+	 */
+	if (info->fbdefio
+	    || !strcmp(info->fix.id, "astdrmfb")
+	    || !strcmp(info->fix.id, "cirrusdrmfb")
+	    || !strcmp(info->fix.id, "mgadrmfb")) {
+		struct fb_copyarea area;
+
+		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);
+	}
+}
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 04/14] bootsplash: Redraw on suspend/hibernate
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (2 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 03/14] bootsplash: Flush framebuffer after drawing Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 05/14] bootsplash: Disable splash on oops Max Staudt
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/video/fbdev/core/bootsplash.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index 8f1c1c165401..e98c05dd8bc0 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -242,9 +242,31 @@ static struct attribute *splash_dev_attrs[] = {
 ATTRIBUTE_GROUPS(splash_dev);
 
 
+
+
+/*
+ * Power management fixup via platform device
+ */
+
+static int splash_resume(struct device *device)
+{
+	if (bootsplash_would_render_now())
+		queue_work(splash_global.wq, &splash_work_redraw_vc);
+
+	return 0;
+}
+
+
+static const struct dev_pm_ops splash_pm_ops = {
+	.thaw = splash_resume,
+	.restore = splash_resume,
+	.resume = splash_resume,
+};
+
 static struct platform_driver splash_driver = {
 	.driver = {
 		.name = "bootsplash",
+		.pm = &splash_pm_ops,
 	},
 };
 
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 05/14] bootsplash: Disable splash on oops
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (3 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 04/14] bootsplash: Redraw on suspend/hibernate Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 06/14] bootsplash: Disable on SysRq SAK Max Staudt
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

Signed-off-by: Max Staudt <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/video/fbdev/core/fbcon.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 4ac1a33be418..cbe8a4480037 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1333,6 +1333,15 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 	int y;
  	int c = scr_readw((u16 *) vc->vc_pos);
 
+	/* Disable the splash here so we don't have to hook into
+	 * vt_console_print() in drivers/tty/vt/vt.c
+	 *
+	 * We'd disable the splash just before the call to
+	 * hide_cursor() anyway, so this spot is just fine.
+	 */
+	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)
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 06/14] bootsplash: Disable on SysRq SAK
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (4 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 05/14] bootsplash: Disable splash on oops Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 07/14] bootsplash: Add VT keyboard hook Max Staudt
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/tty/sysrq.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 3ffc1ce29023..bc6a24c9dfa8 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -49,6 +49,7 @@
 #include <linux/syscalls.h>
 #include <linux/of.h>
 #include <linux/rcupdate.h>
+#include <linux/bootsplash.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -104,6 +105,8 @@ static void sysrq_handle_SAK(int key)
 {
 	struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
 	schedule_work(SAK_work);
+
+	bootsplash_disable();
 }
 static struct sysrq_key_op sysrq_SAK_op = {
 	.handler	= sysrq_handle_SAK,
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 07/14] bootsplash: Add VT keyboard hook
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (5 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 06/14] bootsplash: Disable on SysRq SAK Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 08/14] bootsplash: Add file reading and picture rendering Max Staudt
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/tty/vt/keyboard.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index f4166263bb3a..177b35182b7c 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -47,6 +47,8 @@
 
 #include <asm/irq_regs.h>
 
+#include <linux/bootsplash.h>
+
 extern void ctrl_alt_del(void);
 
 /*
@@ -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) {
 		/*
 		 * This is extended medium raw mode, with keys above 127
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 08/14] bootsplash: Add file reading and picture rendering
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (6 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 07/14] bootsplash: Add VT keyboard hook Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 17:32   ` Randy Dunlap
  2017-10-25 12:45 ` [RFC 09/14] bootsplash: Add corner positioning Max Staudt
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index a6617c07229a..c3496c5ac2bb 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -175,6 +175,14 @@ config BOOTSPLASH
           If unsure, say N.
           This is typically used by distributors and system integrators.
 
+config BOOTSPLASH_FILE
+        string "Default full path to bootsplash file"
+        depends on BOOTSPLASH
+        default "/bootsplash"
+        help
+          This file will be looked for in the initramfs and, if found, loaded
+          and used as a bootsplash.
+
 config STI_CONSOLE
         bool "STI text console"
         depends on PARISC
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index 66895321928e..6a8d1bab8a01 100644
--- a/drivers/video/fbdev/core/Makefile
+++ b/drivers/video/fbdev/core/Makefile
@@ -31,4 +31,4 @@ obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 
 obj-$(CONFIG_BOOTSPLASH)       += bootsplash.o bootsplash_render.o \
-                                  dummyblit.o
+                                  bootsplash_load.o dummyblit.o
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index e98c05dd8bc0..3253506d26a7 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -32,6 +32,7 @@
 #include <linux/vt_kern.h>
 #include <linux/workqueue.h>
 
+#include "bootsplash_file.h"
 #include "bootsplash_internal.h"
 
 
@@ -116,12 +117,19 @@ static bool is_fb_compatible(struct fb_info *info)
  */
 void bootsplash_render_full(struct fb_info *info)
 {
+	mutex_lock(&splash_global.data_lock);
+
 	if (!is_fb_compatible(info))
-		return;
+		goto out;
 
 	bootsplash_do_render_background(info);
 
+	bootsplash_do_render_pictures(info);
+
 	bootsplash_do_render_flush(info);
+
+out:
+	mutex_unlock(&splash_global.data_lock);
 }
 
 
@@ -135,6 +143,7 @@ bool bootsplash_would_render_now(void)
 {
 	return !oops_in_progress
 		&& !console_blanked
+		&& splash_global.filebuf
 		&& bootsplash_is_enabled();
 }
 
@@ -231,11 +240,33 @@ static ssize_t splash_store_enabled(struct device *device,
 	return count;
 }
 
+static ssize_t splash_store_drop_splash(struct device *device,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	if (!buf || !count || !splash_global.filebuf)
+		return count;
+
+	/* Stop the splash first so we get our text console
+	 * if we're currently on one.
+	 */
+	mutex_lock(&splash_global.data_lock);
+
+	bootsplash_disable();
+	bootsplash_free_locked();
+
+	mutex_unlock(&splash_global.data_lock);
+
+	return count;
+}
+
 static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
+static DEVICE_ATTR(drop_splash, 0200, NULL, splash_store_drop_splash);
 
 
 static struct attribute *splash_dev_attrs[] = {
 	&dev_attr_enabled.attr,
+	&dev_attr_drop_splash.attr,
 	NULL
 };
 
@@ -279,8 +310,11 @@ static struct platform_driver splash_driver = {
 
 void bootsplash_init(void)
 {
+	loff_t len;
+	void *mem;
+
 	/* Initialized already? */
-	if (splash_global.wq)
+	if (splash_global.filebuf)
 		return;
 
 
@@ -311,6 +345,7 @@ void bootsplash_init(void)
 	}
 
 	spin_lock_init(&splash_global.state_lock);
+	mutex_init(&splash_global.data_lock);
 	if (!splash_global.wq)
 		splash_global.wq = alloc_workqueue("bootsplash",
 						WQ_UNBOUND | WQ_FREEZABLE,
@@ -320,6 +355,21 @@ void bootsplash_init(void)
 		goto err;
 	}
 
+	/* 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);
+		goto err;
+	}
+
+	bootsplash_activate_buf(mem, len);
+
 	return;
 
 err_device:
@@ -335,3 +385,6 @@ void bootsplash_init(void)
 
 module_param_named(enable, splash_global.enabled, bool, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable kernel bootsplash");
+
+module_param_named(filename, splash_global.filename, charp, 0444);
+MODULE_PARM_DESC(filename, "Bootsplash file");
diff --git a/drivers/video/fbdev/core/bootsplash_file.h b/drivers/video/fbdev/core/bootsplash_file.h
new file mode 100644
index 000000000000..f33577e062ca
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_file.h
@@ -0,0 +1,112 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * 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-disk types
+ *
+ * A splash file consists of:
+ *  - One single 'struct splash_file_header'
+ *  - An array of 'struct splash_pic_header'
+ *  - An array of raw data blocks, each padded to 16 bytes and
+ *    preceded by a 'struct splash_blob_header'
+ *
+ * A single-frame splash may look like this:
+ *
+ * +--------------------+
+ * |                    |
+ * | splash_file_header |
+ * |  -> num_blobs = 1  |
+ * |  -> num_pics = 1   |
+ * |                    |
+ * +--------------------+
+ * |                    |
+ * | splash_pic_header  |
+ * |                    |
+ * +--------------------+
+ * |                    |
+ * | splash_blob_header |
+ * |  -> type = 0       |
+ * |  -> picture_id = 0 |
+ * |                    |
+ * | (raw RGB data)     |
+ * | (pad to 16 bytes)  |
+ * |                    |
+ * +--------------------+
+ *
+ * All multi-byte values are stored on disk as big endian, and
+ * will be converted to CPU endianness in-memory during loading.
+ */
+
+struct splash_file_header {
+	u8  id[16]; /* "Linux bootsplash" (no trailing NUL) */
+
+	/* Splash file format version to avoid clashes */
+	u16 version;
+
+	/* The background color */
+	u8 bg_red;
+	u8 bg_green;
+	u8 bg_blue;
+	u8 bg_reserved;
+
+	/* Number of pic/blobs so we can allocate memory for internal
+	 * structures ahead of time when reading the file
+	 */
+	u16 num_blobs;
+	u8 num_pics;
+
+	u8 padding[103];
+} __attribute__((__packed__));
+
+
+struct splash_pic_header {
+	u16 width;
+	u16 height;
+
+	/* Number of data packages associated with this picture.
+	 * Currently, the only use for more than 1 is for animations.
+	 */
+	u8 num_blobs;
+
+	u8 padding[11];
+} __attribute__((__packed__));
+
+
+struct splash_blob_header {
+	/* Length of the data block in bytes. */
+	u32 length;
+
+	/* Type of the contents.
+	 *  0 - Raw RGB data.
+	 */
+	u16 type;
+
+	/* Picture this blob is associated with.
+	 * Blobs will be added to a picture in the order they are
+	 * found in the file.
+	 */
+	u8 picture_id;
+
+	u8 padding[9];
+} __attribute__((__packed__));
+
+#endif
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
index c0653dd7807b..791591d10d6b 100644
--- a/drivers/video/fbdev/core/bootsplash_internal.h
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -22,12 +22,31 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
+#include "bootsplash_file.h"
+
 
 /*
  * Runtime types
  */
 
+struct splash_blob_priv {
+	struct splash_blob_header *blob_header;
+	void *data;
+};
+
+
+struct splash_pic_priv {
+	struct splash_pic_header *pic_header;
+
+	struct splash_blob_priv *blobs;
+	u16 blobs_loaded;
+};
+
+
 struct splash_priv {
+	/* Bootup and runtime state */
+	char *filename;
+
 	/* This lock only synchronizes the enabled/disabled state
 	 *
 	 * Note: fbcon.c uses this twice, by calling
@@ -49,6 +68,18 @@ struct splash_priv {
 	 * during suspend.
 	 */
 	struct workqueue_struct *wq;
+
+	/* Splash data structures including lock for everything below */
+	struct mutex data_lock;
+
+	struct fb_info *splash_fb;
+
+	union {
+		u8 *filebuf;
+		struct splash_file_header *header;
+	};
+
+	struct splash_pic_priv *pics;
 };
 
 
@@ -67,6 +98,11 @@ extern struct splash_priv splash_global;
  */
 
 void bootsplash_do_render_background(struct fb_info *info);
+void bootsplash_do_render_pictures(struct fb_info *info);
 void bootsplash_do_render_flush(struct fb_info *info);
 
+
+void bootsplash_free_locked(void);
+int bootsplash_activate_buf(char *buf, long buflen);
+
 #endif
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
new file mode 100644
index 000000000000..2f983a74664c
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_load.c
@@ -0,0 +1,242 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Loading and freeing functions)
+ *
+ * Authors:
+ * Max Staudt <mstaudt@suse.com>
+ *
+ *
+ * Very loosely based on the old kernel splash project at
+ * 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.
+ *
+ * To be called with the bootsplash data_lock held.
+ */
+void bootsplash_free_locked(void)
+{
+	if (splash_global.filebuf && splash_global.pics) {
+		unsigned int i;
+
+		for (i = 0; i < splash_global.header->num_pics; i++) {
+			struct splash_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;
+	}
+}
+
+
+
+
+/*
+ * Load a splash screen from a memory buffer.
+ *
+ * Parsing, and sanity checks.
+ *
+ * Once a vmalloc'd buffer is passed to this function, the bootsplash
+ * code is responsible for freeing it - even in an error case.
+ */
+
+int bootsplash_activate_buf(char *buf, long buflen)
+{
+	unsigned int i;
+	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(struct splash_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);
+
+		goto err;
+	}
+
+	if (buflen < sizeof(struct splash_file_header)
+		+ splash_global.header->num_pics
+			* sizeof(struct splash_pic_header)
+		+ splash_global.header->num_blobs
+			* sizeof(struct splash_blob_header)) {
+		pr_err("File incomplete.\n");
+
+		goto err;
+	}
+
+
+	/* Read picture headers */
+
+	if (splash_global.header->num_pics) {
+		splash_global.pics = vzalloc(splash_global.header->num_pics
+					     * sizeof(struct splash_pic_priv));
+		if (!splash_global.pics)
+			goto err;
+	}
+
+	walker = splash_global.filebuf + sizeof(struct splash_file_header);
+	for (i = 0; i < splash_global.header->num_pics; i++) {
+		struct splash_pic_priv *pp = &splash_global.pics[i];
+		struct splash_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);
+
+			goto err;
+		}
+
+		pp->pic_header = ph;
+		pp->blobs = vzalloc(ph->num_blobs
+					* sizeof(struct splash_blob_priv));
+		if (!pp->blobs) {
+			pr_err("Could not allocate pointer array for picture %d.\n",
+			       i);
+
+			ph->num_blobs = 0;
+		}
+
+		walker += sizeof(struct splash_pic_header);
+	}
+
+
+
+	/* Read blob headers */
+	for (i = 0; i < splash_global.header->num_blobs; i++) {
+		struct splash_blob_header *bh = (void *)walker;
+		struct splash_pic_priv *pp;
+
+		if (walker + sizeof(struct splash_blob_header) > buf + buflen)
+			goto err;
+
+		walker += sizeof(struct splash_blob_header);
+
+		if (walker + bh->length > buf + buflen)
+			goto err;
+
+		if (bh->picture_id >= splash_global.header->num_pics)
+			goto nextblob;
+
+		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)
+			goto nextblob;
+
+		switch (bh->type) {
+		case 0:
+			/* 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);
+
+				goto err;
+			}
+			break;
+		default:
+			pr_warn("Blob %u, unknown type %u.\n", i, bh->type);
+			goto nextblob;
+		}
+
+		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++) {
+		struct splash_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);
+
+			goto err;
+		}
+	}
+
+
+	/* 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);
+
+	return 0;
+
+
+err:
+	bootsplash_free_locked();
+	mutex_unlock(&splash_global.data_lock);
+	return -EINVAL;
+}
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
index 460ae0168cb0..72d9867c4656 100644
--- a/drivers/video/fbdev/core/bootsplash_render.c
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -20,6 +20,7 @@
 #include <linux/printk.h>
 #include <linux/types.h>
 
+#include "bootsplash_file.h"
 #include "bootsplash_internal.h"
 
 
@@ -70,16 +71,73 @@ static inline u32 pack_pixel(struct fb_var_screeninfo *dst_var,
 }
 
 
+/*
+ * Copy from source and blend into the destination picture.
+ * Currently assumes that the source picture is 24bpp.
+ * Currently assumes that the destination is <= 32bpp.
+ */
+static int splash_convert_to_fb(u8 *dst,
+				struct fb_var_screeninfo *dst_var,
+				unsigned int dst_stride,
+				unsigned int dst_xoff,
+				unsigned int dst_yoff,
+				u8 *src,
+				unsigned int src_width,
+				unsigned int src_height)
+{
+	unsigned int x, y;
+	unsigned int src_stride = 3 * src_width; /* Assume 24bpp packed */
+	u32 dst_octpp = dst_var->bits_per_pixel / 8;
+
+	dst_xoff += dst_var->xoffset;
+	dst_yoff += dst_var->yoffset;
+
+	/* Copy with stride and pixel size adjustment */
+	for (y = 0;
+	     y < src_height && y + dst_yoff < dst_var->yres_virtual;
+	     y++) {
+		u8 *srcline = src
+				+ (y * src_stride);
+		u8 *dstline = dst
+				+ ((y + dst_yoff) * dst_stride)
+				+ (dst_xoff * dst_octpp);
+
+		for (x = 0;
+		     x < src_width && x + dst_xoff < dst_var->xres_virtual;
+		     x++) {
+			u8 red, green, blue;
+			u32 dstpix;
+
+			/* Read pixel */
+			red = *srcline++;
+			green = *srcline++;
+			blue = *srcline++;
+
+			/* Write pixel */
+			dstpix = pack_pixel(dst_var, red, green, blue);
+			memcpy(dstline, &dstpix, dst_octpp);
+
+			dstline += dst_octpp;
+		}
+	}
+
+	return 0;
+}
+
+
 void bootsplash_do_render_background(struct fb_info *info)
 {
 	unsigned int x, y;
 	u32 dstpix;
 	u32 dst_octpp = info->var.bits_per_pixel / 8;
 
+	if (!splash_global.filebuf)
+		return;
+
 	dstpix = pack_pixel(&info->var,
-			    0,
-			    0,
-			    0);
+			    splash_global.header->bg_red,
+			    splash_global.header->bg_green,
+			    splash_global.header->bg_blue);
 
 	for (y = 0; y < info->var.yres_virtual; y++) {
 		u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
@@ -93,6 +151,48 @@ void bootsplash_do_render_background(struct fb_info *info)
 }
 
 
+void bootsplash_do_render_pictures(struct fb_info *info)
+{
+	unsigned int i;
+
+	if (!splash_global.filebuf)
+		return;
+
+	for (i = 0; i < splash_global.header->num_pics; i++) {
+		struct splash_blob_priv *bp;
+		struct splash_pic_priv *pp = &splash_global.pics[i];
+		long dst_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);
+	}
+}
+
+
 void bootsplash_do_render_flush(struct fb_info *info)
 {
 	/* FB drivers using deferred_io (such as Xen) need to sync the
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 09/14] bootsplash: Add corner positioning
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (7 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 08/14] bootsplash: Add file reading and picture rendering Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:45 ` [RFC 10/14] bootsplash: Add animation support Max Staudt
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

This allows showing multiple logos, each in its own position,
relative to the eight screen corners.

Signed-off-by: Max Staudt <mstaudt@suse.de>
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(-)

diff --git a/drivers/video/fbdev/core/bootsplash_file.h b/drivers/video/fbdev/core/bootsplash_file.h
index f33577e062ca..59a084a05171 100644
--- a/drivers/video/fbdev/core/bootsplash_file.h
+++ b/drivers/video/fbdev/core/bootsplash_file.h
@@ -87,7 +87,28 @@ struct splash_pic_header {
 	 */
 	u8 num_blobs;
 
-	u8 padding[11];
+
+	/* Corner to paint the picture in.
+	 *  0 - Center
+	 *  1 - Top left
+	 *  2 - Top
+	 *  3 - Top right
+	 *  4 - Right
+	 *  5 - Bottom right
+	 *  6 - Bottom
+	 *  7 - Bottom left
+	 *  8 - Left
+	 */
+	u8 corner;
+
+	/* Pixel offset from the screen margins.
+	 * Example: If the picture is in the top right corner, it will
+	 *          be places corner_offset pixels from the top and
+	 *          corner_pixels from the right margin.
+	 */
+	u8 corner_offset;
+
+	u8 padding[9];
 } __attribute__((__packed__));
 
 
@@ -109,4 +130,23 @@ struct splash_blob_header {
 	u8 padding[9];
 } __attribute__((__packed__));
 
+
+
+
+/*
+ * Enums for on-disk types
+ */
+
+enum splash_corner {
+	SPLASH_CORNER_CENTER = 0,
+	SPLASH_CORNER_TOP_LEFT = 1,
+	SPLASH_CORNER_TOP = 2,
+	SPLASH_CORNER_TOP_RIGHT = 3,
+	SPLASH_CORNER_RIGHT = 4,
+	SPLASH_CORNER_BOTTOM_RIGHT = 5,
+	SPLASH_CORNER_BOTTOM = 6,
+	SPLASH_CORNER_BOTTOM_LEFT = 7,
+	SPLASH_CORNER_LEFT = 8,
+};
+
 #endif
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
index 72d9867c4656..444233583f6f 100644
--- a/drivers/video/fbdev/core/bootsplash_render.c
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -161,6 +161,7 @@ void bootsplash_do_render_pictures(struct fb_info *info)
 	for (i = 0; i < splash_global.header->num_pics; i++) {
 		struct splash_blob_priv *bp;
 		struct splash_pic_priv *pp = &splash_global.pics[i];
+		struct splash_pic_header *ph = pp->pic_header;
 		long dst_xoff, dst_yoff;
 
 		if (pp->blobs_loaded < 1)
@@ -171,8 +172,58 @@ void bootsplash_do_render_pictures(struct fb_info *info)
 		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;
+		switch (ph->corner) {
+		case SPLASH_CORNER_TOP_LEFT:
+			dst_xoff = 0 + ph->corner_offset;
+			dst_yoff = 0 + ph->corner_offset;
+			break;
+		case SPLASH_CORNER_TOP:
+			dst_xoff = info->var.xres - pp->pic_header->width;
+			dst_xoff /= 2;
+			dst_yoff = 0 + ph->corner_offset;
+			break;
+		case SPLASH_CORNER_TOP_RIGHT:
+			dst_xoff = info->var.xres - pp->pic_header->width
+						  - ph->corner_offset;
+			dst_yoff = 0 + ph->corner_offset;
+			break;
+		case SPLASH_CORNER_RIGHT:
+			dst_xoff = info->var.xres - pp->pic_header->width
+						  - ph->corner_offset;
+			dst_yoff = info->var.yres - pp->pic_header->height;
+			dst_yoff /= 2;
+			break;
+		case SPLASH_CORNER_BOTTOM_RIGHT:
+			dst_xoff = info->var.xres - pp->pic_header->width
+						  - ph->corner_offset;
+			dst_yoff = info->var.yres - pp->pic_header->height
+						  - ph->corner_offset;
+			break;
+		case SPLASH_CORNER_BOTTOM:
+			dst_xoff = info->var.xres - pp->pic_header->width;
+			dst_xoff /= 2;
+			dst_yoff = info->var.yres - pp->pic_header->height
+						  - ph->corner_offset;
+			break;
+		case SPLASH_CORNER_BOTTOM_LEFT:
+			dst_xoff = 0 + ph->corner_offset;
+			dst_yoff = info->var.yres - pp->pic_header->height
+						  - ph->corner_offset;
+			break;
+		case SPLASH_CORNER_LEFT:
+			dst_xoff = 0 + ph->corner_offset;
+			dst_yoff = info->var.yres - pp->pic_header->height;
+			dst_yoff /= 2;
+			break;
+
+		case SPLASH_CORNER_CENTER:
+		default:
+			dst_xoff = info->var.xres - pp->pic_header->width;
+			dst_xoff /= 2;
+			dst_yoff = info->var.yres - pp->pic_header->height;
+			dst_yoff /= 2;
+			break;
+		}
 
 		if (dst_xoff < 0
 		    || dst_yoff < 0
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 10/14] bootsplash: Add animation support
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (8 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 09/14] bootsplash: Add corner positioning Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 17:20   ` Randy Dunlap
  2017-10-25 12:45 ` [RFC 11/14] bootsplash: Redraw fully on console_unblank Max Staudt
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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(-)

diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index 3253506d26a7..e44376d89750 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -64,6 +64,17 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
 static DECLARE_WORK(splash_work_redraw_vc, splash_callback_redraw_vc);
 
 
+static void splash_callback_animation(struct work_struct *ignored)
+{
+	if (bootsplash_would_render_now()) {
+		/* This will also re-schedule this delayed worker */
+		splash_callback_redraw_vc(ignored);
+	}
+}
+
+static DECLARE_DELAYED_WORK(splash_dwork_animation, splash_callback_animation);
+
+
 
 
 /*
@@ -117,17 +128,45 @@ static bool is_fb_compatible(struct fb_info *info)
  */
 void bootsplash_render_full(struct fb_info *info)
 {
+	bool is_update = false;
+
 	mutex_lock(&splash_global.data_lock);
 
-	if (!is_fb_compatible(info))
-		goto out;
+	/* If we've painted on this FB recently, we don't have to do
+	 * the sanity checks and background drawing again.
+	 */
+	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))
+			goto out;
 
-	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);
 
 static int splash_resume(struct device *device)
 {
+	/* Force full redraw on resume since we've probably lost the
+	 * framebuffer's contents meanwhile
+	 */
+	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);
 
diff --git a/drivers/video/fbdev/core/bootsplash_file.h b/drivers/video/fbdev/core/bootsplash_file.h
index 59a084a05171..367d55888ab4 100644
--- a/drivers/video/fbdev/core/bootsplash_file.h
+++ b/drivers/video/fbdev/core/bootsplash_file.h
@@ -74,7 +74,14 @@ struct splash_file_header {
 	u16 num_blobs;
 	u8 num_pics;
 
-	u8 padding[103];
+	/* Milliseconds to wait before painting the next frame in
+	 * an animation.
+	 * This is actually a minimum, as the system is allowed to
+	 * stall for longer between frames.
+	 */
+	u16 frame_ms;
+
+	u8 padding[101];
 } __attribute__((__packed__));
 
 
@@ -108,7 +115,22 @@ struct splash_pic_header {
 	 */
 	u8 corner_offset;
 
-	u8 padding[9];
+
+	/* Animation type.
+	 *  0 - off
+	 *  1 - forward loop
+	 */
+	u8 anim_type;
+
+	/* Animation loop point.
+	 * Actual meaning depends on animation type:
+	 * Type 0 - Unused
+	 *      1 - Frame at which to restart the forward loop
+	 *          (allowing for "intro" frames)
+	 */
+	u8 anim_loop;
+
+	u8 padding[7];
 } __attribute__((__packed__));
 
 
@@ -137,6 +159,11 @@ struct splash_blob_header {
  * Enums for on-disk types
  */
 
+enum splash_anim_type {
+	SPLASH_ANIM_NONE = 0,
+	SPLASH_ANIM_LOOP_FORWARD = 1,
+};
+
 enum splash_corner {
 	SPLASH_CORNER_CENTER = 0,
 	SPLASH_CORNER_TOP_LEFT = 1,
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
index 791591d10d6b..ba63f3eb99ec 100644
--- a/drivers/video/fbdev/core/bootsplash_internal.h
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -40,6 +40,8 @@ struct splash_pic_priv {
 
 	struct splash_blob_priv *blobs;
 	u16 blobs_loaded;
+
+	u16 anim_nextframe;
 };
 
 
@@ -98,8 +100,9 @@ extern struct splash_priv splash_global;
  */
 
 void bootsplash_do_render_background(struct fb_info *info);
-void bootsplash_do_render_pictures(struct fb_info *info);
+void bootsplash_do_render_pictures(struct fb_info *info, bool is_update);
 void bootsplash_do_render_flush(struct fb_info *info);
+void bootsplash_do_step_animations(void);
 
 
 void bootsplash_free_locked(void);
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
index 2f983a74664c..da171cc961a4 100644
--- a/drivers/video/fbdev/core/bootsplash_load.c
+++ b/drivers/video/fbdev/core/bootsplash_load.c
@@ -67,6 +67,7 @@ void bootsplash_free_locked(void)
 
 int bootsplash_activate_buf(char *buf, long buflen)
 {
+	bool have_anim = false;
 	unsigned int i;
 	char *walker;
 
@@ -141,6 +142,13 @@ int bootsplash_activate_buf(char *buf, long buflen)
 			goto err;
 		}
 
+		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(struct splash_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++) {
 		struct splash_pic_priv *pp = &splash_global.pics[i];
+		struct splash_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)
 
 			goto err;
 		}
+
+		if (ph->num_blobs < 2 || ph->anim_loop > pp->blobs_loaded)
+			/* Nothing to animate or loading error */
+			ph->anim_type = SPLASH_ANIM_NONE;
+		else if (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;
 
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
index 444233583f6f..b3667a0f067b 100644
--- a/drivers/video/fbdev/core/bootsplash_render.c
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -151,7 +151,7 @@ void bootsplash_do_render_background(struct fb_info *info)
 }
 
 
-void bootsplash_do_render_pictures(struct fb_info *info)
+void bootsplash_do_render_pictures(struct fb_info *info, bool is_update)
 {
 	unsigned int i;
 
@@ -167,7 +167,11 @@ void bootsplash_do_render_pictures(struct fb_info *info)
 		if (pp->blobs_loaded < 1)
 			continue;
 
-		bp = &pp->blobs[0];
+		/* Skip static pictures when refreshing animations */
+		if (ph->anim_type == SPLASH_ANIM_NONE && is_update)
+			continue;
+
+		bp = &pp->blobs[pp->anim_nextframe];
 
 		if (!bp || bp->blob_header->type != 0)
 			continue;
@@ -274,3 +278,23 @@ void bootsplash_do_render_flush(struct fb_info *info)
 		info->fbops->fb_copyarea(info, &area);
 	}
 }
+
+
+void bootsplash_do_step_animations(void)
+{
+	unsigned int i;
+
+	/* Step every animation once */
+	for (i = 0; i < splash_global.header->num_pics; i++) {
+		struct splash_pic_priv *pp = &splash_global.pics[i];
+
+		if (pp->blobs_loaded < 1)
+			continue;
+
+		if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {
+			pp->anim_nextframe++;
+			if (pp->anim_nextframe >= pp->pic_header->num_blobs)
+				pp->anim_nextframe = pp->pic_header->anim_loop;
+		}
+	}
+}
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 11/14] bootsplash: Redraw fully on console_unblank
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (9 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 10/14] bootsplash: Add animation support Max Staudt
@ 2017-10-25 12:45 ` Max Staudt
  2017-10-25 12:46 ` [RFC 12/14] bootsplash: Add sysfs ABI documentation Max Staudt
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:45 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

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 <mstaudt@suse.de>
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(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 2ebaba16f785..416735ab6dc1 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -102,6 +102,7 @@
 #include <linux/uaccess.h>
 #include <linux/kdb.h>
 #include <linux/ctype.h>
+#include <linux/bootsplash.h>
 
 #define MAX_NR_CON_DRIVER 16
 
@@ -3903,6 +3904,7 @@ void do_unblank_screen(int leaving_gfx)
 	}
 
 	console_blanked = 0;
+	bootsplash_mark_dirty();
 	if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
 		/* Low-level driver cannot restore -> do it ourselves */
 		update_screen(vc);
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index e44376d89750..df2757d6e422 100644
--- a/drivers/video/fbdev/core/bootsplash.c
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -186,6 +186,13 @@ bool bootsplash_would_render_now(void)
 		&& bootsplash_is_enabled();
 }
 
+void bootsplash_mark_dirty(void)
+{
+	mutex_lock(&splash_global.data_lock);
+	splash_global.splash_fb = NULL;
+	mutex_unlock(&splash_global.data_lock);
+}
+
 bool bootsplash_is_enabled(void)
 {
 	unsigned long flags;
@@ -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's contents meanwhile
 	 */
-	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);
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
index 101e70818363..a7f36043e6f6 100644
--- a/include/linux/bootsplash.h
+++ b/include/linux/bootsplash.h
@@ -21,6 +21,8 @@ extern void bootsplash_render_full(struct fb_info *info);
 
 extern bool bootsplash_would_render_now(void);
 
+extern void bootsplash_mark_dirty(void);
+
 extern bool bootsplash_is_enabled(void);
 extern void bootsplash_disable(void);
 extern void bootsplash_enable(void);
@@ -33,6 +35,8 @@ extern void bootsplash_init(void);
 
 #define bootsplash_would_render_now() (false)
 
+#define bootsplash_mark_dirty()
+
 #define bootsplash_is_enabled() (false)
 #define bootsplash_disable()
 #define bootsplash_enable()
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 12/14] bootsplash: Add sysfs ABI documentation
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (10 preceding siblings ...)
  2017-10-25 12:45 ` [RFC 11/14] bootsplash: Redraw fully on console_unblank Max Staudt
@ 2017-10-25 12:46 ` Max Staudt
  2017-10-25 12:46 ` [RFC 13/14] bootsplash: Add main documentation Max Staudt
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:46 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

Signed-off-by: Max Staudt <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 Documentation/ABI/testing/sysfs-platform-bootsplash | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-bootsplash

diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
new file mode 100644
index 000000000000..70c70d018d59
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
@@ -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.
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 13/14] bootsplash: Add main documentation
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (11 preceding siblings ...)
  2017-10-25 12:46 ` [RFC 12/14] bootsplash: Add sysfs ABI documentation Max Staudt
@ 2017-10-25 12:46 ` Max Staudt
  2017-10-25 17:43   ` Randy Dunlap
  2017-10-25 12:46 ` [RFC 14/14] bootsplash: Update MAINTAINERS Max Staudt
  2017-11-09 11:56 ` [RFC 00/14] Kernel based bootsplash Pavel Machek
  14 siblings, 1 reply; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:46 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

Signed-off-by: Max Staudt <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 Documentation/fb/bootsplash.txt | 169 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)
 create mode 100644 Documentation/fb/bootsplash.txt

diff --git a/Documentation/fb/bootsplash.txt b/Documentation/fb/bootsplash.txt
new file mode 100644
index 000000000000..e2b7c956e6c2
--- /dev/null
+++ b/Documentation/fb/bootsplash.txt
@@ -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=980750
+
+
+
+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.
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [RFC 14/14] bootsplash: Update MAINTAINERS
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (12 preceding siblings ...)
  2017-10-25 12:46 ` [RFC 13/14] bootsplash: Add main documentation Max Staudt
@ 2017-10-25 12:46 ` Max Staudt
  2017-11-09 11:56 ` [RFC 00/14] Kernel based bootsplash Pavel Machek
  14 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 12:46 UTC (permalink / raw)
  To: b.zolnierkie, linux-fbdev
  Cc: mstaudt, tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

Signed-off-by: Max Staudt <mstaudt@suse.de>
Reviewed-by: Oliver Neukum <oneukum@suse.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a74227ad082e..ee792797cee9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2705,6 +2705,15 @@ S:	Supported
 F:	drivers/net/bonding/
 F:	include/uapi/linux/if_bonding.h
 
+BOOTSPLASH
+M:	Max Staudt <mstaudt@suse.de>
+L:	linux-fbdev@vger.kernel.org
+S:	Maintained
+F:	Documentation/fb/bootsplash.txt
+F:	drivers/video/fbdev/core/bootsplash*.*
+F:	drivers/video/fbdev/core/dummycon.c
+F:	include/linux/bootsplash.h
+
 BPF (Safe dynamic programs and tools)
 M:	Alexei Starovoitov <ast@kernel.org>
 M:	Daniel Borkmann <daniel@iogearbox.net>
-- 
2.12.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [RFC 10/14] bootsplash: Add animation support
  2017-10-25 12:45 ` [RFC 10/14] bootsplash: Add animation support Max Staudt
@ 2017-10-25 17:20   ` Randy Dunlap
  2017-10-25 17:23     ` Max Staudt
  0 siblings, 1 reply; 29+ messages in thread
From: Randy Dunlap @ 2017-10-25 17:20 UTC (permalink / raw)
  To: Max Staudt, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/17 05:45, Max Staudt wrote:
> @@ -117,17 +128,45 @@ static bool is_fb_compatible(struct fb_info *info)
>   */
>  void bootsplash_render_full(struct fb_info *info)
>  {
> +	bool is_update = false;
> +
>  	mutex_lock(&splash_global.data_lock);
>  
> -	if (!is_fb_compatible(info))
> -		goto out;
> +	/* If we've painted on this FB recently, we don't have to do
> +	 * the sanity checks and background drawing again.
> +	 */

multi-line comment style needs to be corrected in multiple places (in
several of the patches).


-- 
~Randy

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 10/14] bootsplash: Add animation support
  2017-10-25 17:20   ` Randy Dunlap
@ 2017-10-25 17:23     ` Max Staudt
  0 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-25 17:23 UTC (permalink / raw)
  To: Randy Dunlap, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/2017 07:20 PM, Randy Dunlap wrote:
> On 10/25/17 05:45, Max Staudt wrote:
>> @@ -117,17 +128,45 @@ static bool is_fb_compatible(struct fb_info *info)
>>   */
>>  void bootsplash_render_full(struct fb_info *info)
>>  {
>> +	bool is_update = false;
>> +
>>  	mutex_lock(&splash_global.data_lock);
>>  
>> -	if (!is_fb_compatible(info))
>> -		goto out;
>> +	/* If we've painted on this FB recently, we don't have to do
>> +	 * the sanity checks and background drawing again.
>> +	 */
> 
> multi-line comment style needs to be corrected in multiple places (in
> several of the patches).

Sorry, I'll fix that. Thanks.


Max

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 01/14] bootsplash: Initial implementation showing black screen
  2017-10-25 12:45 ` [RFC 01/14] bootsplash: Initial implementation showing black screen Max Staudt
@ 2017-10-25 17:26   ` Randy Dunlap
  0 siblings, 0 replies; 29+ messages in thread
From: Randy Dunlap @ 2017-10-25 17:26 UTC (permalink / raw)
  To: Max Staudt, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/17 05:45, Max Staudt wrote:

> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index 7f1f1fbcef9e..a6617c07229a 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
>           such that other users of the framebuffer will remain normally
>           oriented.
>  
> +config BOOTSPLASH
> +	bool "Bootup splash screen"
> +	depends on FRAMEBUFFER_CONSOLE=y

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.

> +        ---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

-- 
~Randy

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 08/14] bootsplash: Add file reading and picture rendering
  2017-10-25 12:45 ` [RFC 08/14] bootsplash: Add file reading and picture rendering Max Staudt
@ 2017-10-25 17:32   ` Randy Dunlap
  2017-10-25 20:27     ` Takashi Iwai
  0 siblings, 1 reply; 29+ messages in thread
From: Randy Dunlap @ 2017-10-25 17:32 UTC (permalink / raw)
  To: Max Staudt, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/17 05:45, Max Staudt wrote:

> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index a6617c07229a..c3496c5ac2bb 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -175,6 +175,14 @@ config BOOTSPLASH
>            If unsure, say N.
>            This is typically used by distributors and system integrators.
>  
> +config BOOTSPLASH_FILE
> +        string "Default full path to bootsplash file"
> +        depends on BOOTSPLASH
> +        default "/bootsplash"
> +        help
> +          This file will be looked for in the initramfs and, if found, loaded
> +          and used as a bootsplash.


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 13/14] bootsplash: Add main documentation
  2017-10-25 12:46 ` [RFC 13/14] bootsplash: Add main documentation Max Staudt
@ 2017-10-25 17:43   ` Randy Dunlap
  2017-10-27 11:19     ` Max Staudt
  0 siblings, 1 reply; 29+ messages in thread
From: Randy Dunlap @ 2017-10-25 17:43 UTC (permalink / raw)
  To: Max Staudt, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/17 05:46, Max Staudt wrote:
> Signed-off-by: Max Staudt <mstaudt@suse.de>
> Reviewed-by: Oliver Neukum <oneukum@suse.com>
> ---
>  Documentation/fb/bootsplash.txt | 169 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
>  create mode 100644 Documentation/fb/bootsplash.txt
> 
> diff --git a/Documentation/fb/bootsplash.txt b/Documentation/fb/bootsplash.txt
> new file mode 100644
> index 000000000000..e2b7c956e6c2
> --- /dev/null
> +++ b/Documentation/fb/bootsplash.txt
> @@ -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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 08/14] bootsplash: Add file reading and picture rendering
  2017-10-25 17:32   ` Randy Dunlap
@ 2017-10-25 20:27     ` Takashi Iwai
  2017-10-27 11:21       ` Max Staudt
  0 siblings, 1 reply; 29+ messages in thread
From: Takashi Iwai @ 2017-10-25 20:27 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: b.zolnierkie, Max Staudt, linux-fbdev, michal, Michal Srb,
	Oliver Neukum, Stefan Dirsch, linux-kernel

On Wed, 25 Oct 2017 19:32:53 +0200,
Randy Dunlap wrote:
> 
> On 10/25/17 05:45, Max Staudt wrote:
> 
> > diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> > index a6617c07229a..c3496c5ac2bb 100644
> > --- a/drivers/video/console/Kconfig
> > +++ b/drivers/video/console/Kconfig
> > @@ -175,6 +175,14 @@ config BOOTSPLASH
> >            If unsure, say N.
> >            This is typically used by distributors and system integrators.
> >  
> > +config BOOTSPLASH_FILE
> > +        string "Default full path to bootsplash file"
> > +        depends on BOOTSPLASH
> > +        default "/bootsplash"
> > +        help
> > +          This file will be looked for in the initramfs and, if found, loaded
> > +          and used as a bootsplash.
> 
> 
> 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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 13/14] bootsplash: Add main documentation
  2017-10-25 17:43   ` Randy Dunlap
@ 2017-10-27 11:19     ` Max Staudt
  2017-10-27 16:48       ` Randy Dunlap
  0 siblings, 1 reply; 29+ messages in thread
From: Max Staudt @ 2017-10-27 11:19 UTC (permalink / raw)
  To: Randy Dunlap, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/25/2017 07:43 PM, Randy Dunlap wrote:
> On 10/25/17 05:46, Max Staudt wrote:
>> Signed-off-by: Max Staudt <mstaudt@suse.de>
>> Reviewed-by: Oliver Neukum <oneukum@suse.com>
>> ---
>>  Documentation/fb/bootsplash.txt | 169 ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 169 insertions(+)
>>  create mode 100644 Documentation/fb/bootsplash.txt
>>
>> diff --git a/Documentation/fb/bootsplash.txt b/Documentation/fb/bootsplash.txt
>> new file mode 100644
>> index 000000000000..e2b7c956e6c2
>> --- /dev/null
>> +++ b/Documentation/fb/bootsplash.txt
>> @@ -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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 08/14] bootsplash: Add file reading and picture rendering
  2017-10-25 20:27     ` Takashi Iwai
@ 2017-10-27 11:21       ` Max Staudt
  0 siblings, 0 replies; 29+ messages in thread
From: Max Staudt @ 2017-10-27 11:21 UTC (permalink / raw)
  To: Takashi Iwai, Randy Dunlap
  Cc: b.zolnierkie, linux-fbdev, michal, Michal Srb, Oliver Neukum,
	Stefan Dirsch, linux-kernel

On 10/25/2017 10:27 PM, Takashi Iwai wrote:
> On Wed, 25 Oct 2017 19:32:53 +0200,
> Randy Dunlap wrote:
>>
>> On 10/25/17 05:45, Max Staudt wrote:
>>
>>> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
>>> index a6617c07229a..c3496c5ac2bb 100644
>>> --- a/drivers/video/console/Kconfig
>>> +++ b/drivers/video/console/Kconfig
>>> @@ -175,6 +175,14 @@ config BOOTSPLASH
>>>            If unsure, say N.
>>>            This is typically used by distributors and system integrators.
>>>  
>>> +config BOOTSPLASH_FILE
>>> +        string "Default full path to bootsplash file"
>>> +        depends on BOOTSPLASH
>>> +        default "/bootsplash"
>>> +        help
>>> +          This file will be looked for in the initramfs and, if found, loaded
>>> +          and used as a bootsplash.
>>
>>
>> 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.

Good point, I'll look into this.


Thanks

Max

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 13/14] bootsplash: Add main documentation
  2017-10-27 11:19     ` Max Staudt
@ 2017-10-27 16:48       ` Randy Dunlap
  0 siblings, 0 replies; 29+ messages in thread
From: Randy Dunlap @ 2017-10-27 16:48 UTC (permalink / raw)
  To: Max Staudt, b.zolnierkie, linux-fbdev
  Cc: tiwai, oneukum, msrb, sndirsch, michal, linux-kernel

On 10/27/17 04:19, Max Staudt wrote:
> On 10/25/2017 07:43 PM, Randy Dunlap wrote:
>> On 10/25/17 05:46, Max Staudt wrote:
>>> Signed-off-by: Max Staudt <mstaudt@suse.de>
>>> Reviewed-by: Oliver Neukum <oneukum@suse.com>
>>> ---
>>>  Documentation/fb/bootsplash.txt | 169 ++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 169 insertions(+)
>>>  create mode 100644 Documentation/fb/bootsplash.txt
>>>
>>> diff --git a/Documentation/fb/bootsplash.txt b/Documentation/fb/bootsplash.txt
>>> new file mode 100644
>>> index 000000000000..e2b7c956e6c2
>>> --- /dev/null
>>> +++ b/Documentation/fb/bootsplash.txt
>>> @@ -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?

That sounds correct.

thanks.
-- 
~Randy

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 00/14] Kernel based bootsplash
  2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
                   ` (13 preceding siblings ...)
  2017-10-25 12:46 ` [RFC 14/14] bootsplash: Update MAINTAINERS Max Staudt
@ 2017-11-09 11:56 ` Pavel Machek
  2017-11-09 12:36   ` Oliver Neukum
  2017-11-09 12:42   ` Takashi Iwai
  14 siblings, 2 replies; 29+ messages in thread
From: Pavel Machek @ 2017-11-09 11:56 UTC (permalink / raw)
  To: Max Staudt
  Cc: b.zolnierkie, linux-fbdev, tiwai, oneukum, msrb, sndirsch,
	michal, linux-kernel

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 00/14] Kernel based bootsplash
  2017-11-09 11:56 ` [RFC 00/14] Kernel based bootsplash Pavel Machek
@ 2017-11-09 12:36   ` Oliver Neukum
  2017-11-09 18:45     ` Pavel Machek
  2017-11-09 12:42   ` Takashi Iwai
  1 sibling, 1 reply; 29+ messages in thread
From: Oliver Neukum @ 2017-11-09 12:36 UTC (permalink / raw)
  To: Pavel Machek, Max Staudt
  Cc: michal, b.zolnierkie, Michal Srb, Stefan Dirsch, Takashi Iwai,
	linux-fbdev, linux-kernel

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 00/14] Kernel based bootsplash
  2017-11-09 11:56 ` [RFC 00/14] Kernel based bootsplash Pavel Machek
  2017-11-09 12:36   ` Oliver Neukum
@ 2017-11-09 12:42   ` Takashi Iwai
  1 sibling, 0 replies; 29+ messages in thread
From: Takashi Iwai @ 2017-11-09 12:42 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Max Staudt, michal, b.zolnierkie, Michal Srb, Oliver Neukum,
	Stefan Dirsch, linux-fbdev, linux-kernel

On Thu, 09 Nov 2017 12:56:55 +0100,
Pavel Machek wrote:
> 
> 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).

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 00/14] Kernel based bootsplash
  2017-11-09 12:36   ` Oliver Neukum
@ 2017-11-09 18:45     ` Pavel Machek
  2017-11-10 16:53       ` Takashi Iwai
  0 siblings, 1 reply; 29+ messages in thread
From: Pavel Machek @ 2017-11-09 18:45 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Max Staudt, michal, b.zolnierkie, Michal Srb, Stefan Dirsch,
	Takashi Iwai, linux-fbdev, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1221 bytes --]

On Thu 2017-11-09 13:36:16, Oliver Neukum wrote:
> 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?

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. You
should be able to do the rest, already.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [RFC 00/14] Kernel based bootsplash
  2017-11-09 18:45     ` Pavel Machek
@ 2017-11-10 16:53       ` Takashi Iwai
  0 siblings, 0 replies; 29+ messages in thread
From: Takashi Iwai @ 2017-11-10 16:53 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Oliver Neukum, michal, b.zolnierkie, Michal Srb, Stefan Dirsch,
	Max Staudt, linux-fbdev, linux-kernel

On Thu, 09 Nov 2017 19:45:23 +0100,
Pavel Machek wrote:
> 
> On Thu 2017-11-09 13:36:16, Oliver Neukum wrote:
> > 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?
> 
> 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

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2017-11-10 16:53 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-25 12:45 [RFC 00/14] Kernel based bootsplash Max Staudt
2017-10-25 12:45 ` [RFC 01/14] bootsplash: Initial implementation showing black screen Max Staudt
2017-10-25 17:26   ` Randy Dunlap
2017-10-25 12:45 ` [RFC 02/14] bootsplash: Add platform device Max Staudt
2017-10-25 12:45 ` [RFC 03/14] bootsplash: Flush framebuffer after drawing Max Staudt
2017-10-25 12:45 ` [RFC 04/14] bootsplash: Redraw on suspend/hibernate Max Staudt
2017-10-25 12:45 ` [RFC 05/14] bootsplash: Disable splash on oops Max Staudt
2017-10-25 12:45 ` [RFC 06/14] bootsplash: Disable on SysRq SAK Max Staudt
2017-10-25 12:45 ` [RFC 07/14] bootsplash: Add VT keyboard hook Max Staudt
2017-10-25 12:45 ` [RFC 08/14] bootsplash: Add file reading and picture rendering Max Staudt
2017-10-25 17:32   ` Randy Dunlap
2017-10-25 20:27     ` Takashi Iwai
2017-10-27 11:21       ` Max Staudt
2017-10-25 12:45 ` [RFC 09/14] bootsplash: Add corner positioning Max Staudt
2017-10-25 12:45 ` [RFC 10/14] bootsplash: Add animation support Max Staudt
2017-10-25 17:20   ` Randy Dunlap
2017-10-25 17:23     ` Max Staudt
2017-10-25 12:45 ` [RFC 11/14] bootsplash: Redraw fully on console_unblank Max Staudt
2017-10-25 12:46 ` [RFC 12/14] bootsplash: Add sysfs ABI documentation Max Staudt
2017-10-25 12:46 ` [RFC 13/14] bootsplash: Add main documentation Max Staudt
2017-10-25 17:43   ` Randy Dunlap
2017-10-27 11:19     ` Max Staudt
2017-10-27 16:48       ` Randy Dunlap
2017-10-25 12:46 ` [RFC 14/14] bootsplash: Update MAINTAINERS Max Staudt
2017-11-09 11:56 ` [RFC 00/14] Kernel based bootsplash Pavel Machek
2017-11-09 12:36   ` Oliver Neukum
2017-11-09 18:45     ` Pavel Machek
2017-11-10 16:53       ` Takashi Iwai
2017-11-09 12:42   ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).