kernel-release 5.10.10-1 (znver1;x86_64) 2021-13503
9999

Status published
Submitter bero [@T] lindev.ch
Platform rolling
Repository main
URL https://abf.openmandriva.org/build_lists/978771
Packages
bpftool-5.10.10-1.znver1.binary
cpupower-5.10.10-1.znver1.binary
cpupower-devel-5.10.10-1.znver1.binary
cross-aarch64-openmandriva-linux-android-kernel-release-headers-5.10.10-1.znver1.binary
cross-aarch64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-aarch64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.znver1.binary
cross-aarch64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.znver1.binary
cross-armv7hnl-openmandriva-linux-gnueabihf-kernel-release-headers-5.10.10-1.znver1.binary
cross-armv7hnl-openmandriva-linux-musleabihf-kernel-release-headers-5.10.10-1.znver1.binary
cross-armv7hnl-openmandriva-linux-uclibceabihf-kernel-release-headers-5.10.10-1.znver1.binary
cross-armv7l-openmandriva-linux-androideabi-kernel-release-headers-5.10.10-1.znver1.binary
cross-armv8l-openmandriva-linux-androideabi-kernel-release-headers-5.10.10-1.znver1.binary
cross-i686-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-i686-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.znver1.binary
cross-i686-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.znver1.binary
cross-ppc64le-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-ppc64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv32-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv32-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv32-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.znver1.binary
cross-riscv64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-android-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-gnux32-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-muslx32-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.znver1.binary
cross-x86_64-openmandriva-linux-uclibcx32-kernel-release-headers-5.10.10-1.znver1.binary
kernel-release-5.10.10-1.znver1.source
kernel-release-desktop-5.10.10-1.znver1.binary
kernel-release-desktop-clang-5.10.10-1.znver1.binary
kernel-release-desktop-clang-devel-5.10.10-1.znver1.binary
kernel-release-desktop-devel-5.10.10-1.znver1.binary
kernel-release-headers-1:5.10.10-1.znver1.binary
kernel-release-server-5.10.10-1.znver1.binary
kernel-release-server-clang-5.10.10-1.znver1.binary
kernel-release-server-clang-devel-5.10.10-1.znver1.binary
kernel-release-server-devel-5.10.10-1.znver1.binary
kernel-release-source-5.10.10-1.znver1.binary
lib64bpf0-5.10.10-1.znver1.binary
lib64bpf-devel-5.10.10-1.znver1.binary
turbostat-5.10.10-1.znver1.binary
x86_energy_perf_policy-5.10.10-1.znver1.binary
bpftool-5.10.10-1.x86_64.binary
cpupower-5.10.10-1.x86_64.binary
cpupower-devel-5.10.10-1.x86_64.binary
cross-aarch64-openmandriva-linux-android-kernel-release-headers-5.10.10-1.x86_64.binary
cross-aarch64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-aarch64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.x86_64.binary
cross-aarch64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.x86_64.binary
cross-armv7hnl-openmandriva-linux-gnueabihf-kernel-release-headers-5.10.10-1.x86_64.binary
cross-armv7hnl-openmandriva-linux-musleabihf-kernel-release-headers-5.10.10-1.x86_64.binary
cross-armv7hnl-openmandriva-linux-uclibceabihf-kernel-release-headers-5.10.10-1.x86_64.binary
cross-armv7l-openmandriva-linux-androideabi-kernel-release-headers-5.10.10-1.x86_64.binary
cross-armv8l-openmandriva-linux-androideabi-kernel-release-headers-5.10.10-1.x86_64.binary
cross-i686-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-i686-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.x86_64.binary
cross-i686-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.x86_64.binary
cross-ppc64le-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-ppc64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv32-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv32-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv32-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv64-openmandriva-linux-gnu-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.x86_64.binary
cross-riscv64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-android-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-gnux32-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-musl-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-muslx32-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-uclibc-kernel-release-headers-5.10.10-1.x86_64.binary
cross-x86_64-openmandriva-linux-uclibcx32-kernel-release-headers-5.10.10-1.x86_64.binary
kernel-release-5.10.10-1.x86_64.source
kernel-release-desktop-5.10.10-1.x86_64.binary
kernel-release-desktop-clang-5.10.10-1.x86_64.binary
kernel-release-desktop-clang-devel-5.10.10-1.x86_64.binary
kernel-release-desktop-devel-5.10.10-1.x86_64.binary
kernel-release-headers-1:5.10.10-1.x86_64.binary
kernel-release-server-5.10.10-1.x86_64.binary
kernel-release-server-clang-5.10.10-1.x86_64.binary
kernel-release-server-clang-devel-5.10.10-1.x86_64.binary
kernel-release-server-devel-5.10.10-1.x86_64.binary
kernel-release-source-5.10.10-1.x86_64.binary
lib64bpf0-5.10.10-1.x86_64.binary
lib64bpf-devel-5.10.10-1.x86_64.binary
turbostat-5.10.10-1.x86_64.binary
x86_energy_perf_policy-5.10.10-1.x86_64.binary
Build Date 2021-01-24 01:32:49 +0000 UTC
Last Updated 2021-01-25 04:25:43.56073462 +0000 UTC
$ git diff --patch-with-stat --summary c8b822d29ce1a78dec8070252886d8536383f1c7..18969b7685c0ab5a9401572008504b1ab16f1504

 .abf.yml                                           |   5 +-
 ...ow-unusued-softback_lines-cursor-argument.patch | 150 +++++
 ...evert-fbcon-remove-no-op-fbcon_set_origin.patch |  31 +
 ...-revert-fbcon-remove-soft-scrollback-code.patch | 498 ++++++++++++++
 0501-bootsplash.patch                              | 714 +++++++++++++++++++++
 0502-bootsplash.patch                              | 657 +++++++++++++++++++
 0503-bootsplash.patch                              |  66 ++
 0504-bootsplash.patch                              | 215 +++++++
 0505-bootsplash.patch                              | 327 ++++++++++
 0506-bootsplash.patch                              |  82 +++
 0507-bootsplash.patch                              |  42 ++
 0508-bootsplash.patch                              |  19 +
 0509-bootsplash.patch                              |  21 +
 0510-bootsplash.patch                              | 308 +++++++++
 0511-bootsplash.patch                              | 129 ++++
 0512-bootsplash.patch                              | 499 ++++++++++++++
 0513-bootsplash.gitpatch                           | 162 +++++
 aarch64-desktop-omv-defconfig                      |   3 +-
 aarch64-server-omv-defconfig                       |   3 +-
 armv7hnl-desktop-omv-defconfig                     |   4 +-
 armv7hnl-server-omv-defconfig                      |   4 +-
 i686-desktop-gcc-omv-defconfig                     |   3 +-
 i686-server-gcc-omv-defconfig                      |   3 +-
 kernel-release.spec                                |  37 +-
 linux-5.10.tar.sign                                |  19 -
 linux-5.8.tar.sign                                 |  19 -
 x86_64-desktop-gcc-omv-defconfig                   |   3 +-
 x86_64-server-gcc-omv-defconfig                    |   3 +-
 x86_64-znver-desktop-gcc-omv-defconfig             |   3 +-
 x86_64-znver-server-gcc-omv-defconfig              |   3 +-
 30 files changed, 3978 insertions(+), 54 deletions(-)
 create mode 100644 0401-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
 create mode 100644 0402-revert-fbcon-remove-no-op-fbcon_set_origin.patch
 create mode 100644 0403-revert-fbcon-remove-soft-scrollback-code.patch
 create mode 100644 0501-bootsplash.patch
 create mode 100644 0502-bootsplash.patch
 create mode 100644 0503-bootsplash.patch
 create mode 100644 0504-bootsplash.patch
 create mode 100644 0505-bootsplash.patch
 create mode 100644 0506-bootsplash.patch
 create mode 100644 0507-bootsplash.patch
 create mode 100644 0508-bootsplash.patch
 create mode 100644 0509-bootsplash.patch
 create mode 100644 0510-bootsplash.patch
 create mode 100644 0511-bootsplash.patch
 create mode 100644 0512-bootsplash.patch
 create mode 100644 0513-bootsplash.gitpatch
 delete mode 100644 linux-5.10.tar.sign
 delete mode 100644 linux-5.8.tar.sign

diff --git a/.abf.yml b/.abf.yml
index 4db0049..4c5249f 100644
--- a/.abf.yml
+++ b/.abf.yml
@@ -1,5 +1,6 @@
 sources:
   extra-wifi-drivers-20200301.tar.zst: 3390c738c7d91250714ce0f88d26371e93bc40b8
-  saa716x-driver.tar.xz: f9b6ef1cd6f1f71f53d9a8aadfba2cf6b5c3d7b6
+  linux-5.10.tar.sign: 42168c413497eb431304c83ebdaefe8ac2438ed5
   linux-5.10.tar.xz: be0b909f1fbb760cc2d5cf146e1da3b2af0cf899
-  patch-5.10.6.xz: a0d664cb8188c684ec3a63ea50df070965288336
+  saa716x-driver.tar.xz: f9b6ef1cd6f1f71f53d9a8aadfba2cf6b5c3d7b6
+  patch-5.10.10.xz: a107b535159e5060f048e35339b1b66dba306cd1
diff --git a/0401-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch b/0401-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
new file mode 100644
index 0000000..c126888
--- /dev/null
+++ b/0401-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
@@ -0,0 +1,150 @@
+--- b/drivers/video/fbdev/core/bitblit.c
++++ a/drivers/video/fbdev/core/bitblit.c
+@@ -234,7 +234,7 @@
+ }
+ 
+ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++		       int softback_lines, int fg, int bg)
+-		       int fg, int bg)
+ {
+ 	struct fb_cursor cursor;
+ 	struct fbcon_ops *ops = info->fbcon_par;
+@@ -247,6 +247,15 @@
+ 
+ 	cursor.set = 0;
+ 
++	if (softback_lines) {
++		if (y + softback_lines >= vc->vc_rows) {
++			mode = CM_ERASE;
++			ops->cursor_flash = 0;
++			return;
++		} else
++			y += softback_lines;
++	}
++
+  	c = scr_readw((u16 *) vc->vc_pos);
+ 	attribute = get_attribute(info, c);
+ 	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+--- b/drivers/video/fbdev/core/fbcon.c
++++ a/drivers/video/fbdev/core/fbcon.c
+@@ -394,7 +394,7 @@
+ 	c = scr_readw((u16 *) vc->vc_pos);
+ 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
+ 		CM_ERASE : CM_DRAW;
++	ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
+-	ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+ 		    get_color(vc, info, c, 0));
+ 	console_unlock();
+ }
+@@ -1345,7 +1345,7 @@
+ 
+ 	ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
+ 
++	ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
+-	ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+ 		    get_color(vc, info, c, 0));
+ }
+ 
+--- b/drivers/video/fbdev/core/fbcon.h
++++ a/drivers/video/fbdev/core/fbcon.h
+@@ -62,7 +62,7 @@
+ 	void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
+ 			      int color, int bottom_only);
+ 	void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
++		       int softback_lines, int fg, int bg);
+-		       int fg, int bg);
+ 	int  (*update_start)(struct fb_info *info);
+ 	int  (*rotate_font)(struct fb_info *info, struct vc_data *vc);
+ 	struct fb_var_screeninfo var;  /* copy of the current fb_var_screeninfo */
+--- b/drivers/video/fbdev/core/fbcon_ccw.c
++++ a/drivers/video/fbdev/core/fbcon_ccw.c
+@@ -219,7 +219,7 @@
+ }
+ 
+ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++		       int softback_lines, int fg, int bg)
+-		       int fg, int bg)
+ {
+ 	struct fb_cursor cursor;
+ 	struct fbcon_ops *ops = info->fbcon_par;
+@@ -236,6 +236,15 @@
+ 
+ 	cursor.set = 0;
+ 
++	if (softback_lines) {
++		if (y + softback_lines >= vc->vc_rows) {
++			mode = CM_ERASE;
++			ops->cursor_flash = 0;
++			return;
++		} else
++			y += softback_lines;
++	}
++
+  	c = scr_readw((u16 *) vc->vc_pos);
+ 	attribute = get_attribute(info, c);
+ 	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+--- b/drivers/video/fbdev/core/fbcon_cw.c
++++ a/drivers/video/fbdev/core/fbcon_cw.c
+@@ -202,7 +202,7 @@
+ }
+ 
+ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++		      int softback_lines, int fg, int bg)
+-		      int fg, int bg)
+ {
+ 	struct fb_cursor cursor;
+ 	struct fbcon_ops *ops = info->fbcon_par;
+@@ -219,6 +219,15 @@
+ 
+ 	cursor.set = 0;
+ 
++	if (softback_lines) {
++		if (y + softback_lines >= vc->vc_rows) {
++			mode = CM_ERASE;
++			ops->cursor_flash = 0;
++			return;
++		} else
++			y += softback_lines;
++	}
++
+  	c = scr_readw((u16 *) vc->vc_pos);
+ 	attribute = get_attribute(info, c);
+ 	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+--- b/drivers/video/fbdev/core/fbcon_ud.c
++++ a/drivers/video/fbdev/core/fbcon_ud.c
+@@ -249,7 +249,7 @@
+ }
+ 
+ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++		      int softback_lines, int fg, int bg)
+-		      int fg, int bg)
+ {
+ 	struct fb_cursor cursor;
+ 	struct fbcon_ops *ops = info->fbcon_par;
+@@ -267,6 +267,15 @@
+ 
+ 	cursor.set = 0;
+ 
++	if (softback_lines) {
++		if (y + softback_lines >= vc->vc_rows) {
++			mode = CM_ERASE;
++			ops->cursor_flash = 0;
++			return;
++		} else
++			y += softback_lines;
++	}
++
+  	c = scr_readw((u16 *) vc->vc_pos);
+ 	attribute = get_attribute(info, c);
+ 	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+--- b/drivers/video/fbdev/core/tileblit.c
++++ a/drivers/video/fbdev/core/tileblit.c
+@@ -80,7 +80,7 @@
+ }
+ 
+ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++			int softback_lines, int fg, int bg)
+-			int fg, int bg)
+ {
+ 	struct fb_tilecursor cursor;
+ 	int use_sw = vc->vc_cursor_type & CUR_SW;
diff --git a/0402-revert-fbcon-remove-no-op-fbcon_set_origin.patch b/0402-revert-fbcon-remove-no-op-fbcon_set_origin.patch
new file mode 100644
index 0000000..6491c54
--- /dev/null
+++ b/0402-revert-fbcon-remove-no-op-fbcon_set_origin.patch
@@ -0,0 +1,31 @@
+--- b/drivers/video/fbdev/core/fbcon.c
++++ a/drivers/video/fbdev/core/fbcon.c
+@@ -163,6 +163,8 @@
+ 
+ #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+ 
++static int fbcon_set_origin(struct vc_data *);
++
+ static int fbcon_cursor_noblink;
+ 
+ #define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)
+@@ -2633,6 +2635,11 @@
+ 	}
+ }
+ 
++static int fbcon_set_origin(struct vc_data *vc)
++{
++	return 0;
++}
++
+ void fbcon_suspended(struct fb_info *info)
+ {
+ 	struct vc_data *vc = NULL;
+@@ -3103,6 +3110,7 @@
+ 	.con_font_default	= fbcon_set_def_font,
+ 	.con_font_copy 		= fbcon_copy_font,
+ 	.con_set_palette 	= fbcon_set_palette,
++	.con_set_origin 	= fbcon_set_origin,
+ 	.con_invert_region 	= fbcon_invert_region,
+ 	.con_screen_pos 	= fbcon_screen_pos,
+ 	.con_getxy 		= fbcon_getxy,
diff --git a/0403-revert-fbcon-remove-soft-scrollback-code.patch b/0403-revert-fbcon-remove-soft-scrollback-code.patch
new file mode 100644
index 0000000..716ffe0
--- /dev/null
+++ b/0403-revert-fbcon-remove-soft-scrollback-code.patch
@@ -0,0 +1,498 @@
+diff -up linux-5.10/drivers/video/fbdev/core/fbcon.c.58~ linux-5.10/drivers/video/fbdev/core/fbcon.c
+--- linux-5.10/drivers/video/fbdev/core/fbcon.c.58~	2021-01-19 23:02:34.611103889 +0100
++++ linux-5.10/drivers/video/fbdev/core/fbcon.c	2021-01-19 23:05:28.560860927 +0100
+@@ -122,6 +122,12 @@ static int logo_lines;
+ /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
+    enums.  */
+ static int logo_shown = FBCON_LOGO_CANSHOW;
++/* Software scrollback */
++static int fbcon_softback_size = 32768;
++static unsigned long softback_buf, softback_curr;
++static unsigned long softback_in;
++static unsigned long softback_top, softback_end;
++static int softback_lines;
+ /* console mappings */
+ static int first_fb_vc;
+ static int last_fb_vc = MAX_NR_CONSOLES - 1;
+@@ -161,6 +167,8 @@ static int margin_color;
+ 
+ static const struct consw fb_con;
+ 
++#define CM_SOFTBACK	(8)
++
+ #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+ 
+ static int fbcon_set_origin(struct vc_data *);
+@@ -365,6 +373,18 @@ static int get_color(struct vc_data *vc,
+ 	return color;
+ }
+ 
++static void fbcon_update_softback(struct vc_data *vc)
++{
++	int l = fbcon_softback_size / vc->vc_size_row;
++
++	if (l > 5)
++		softback_end = softback_buf + l * vc->vc_size_row;
++	else
++		/* Smaller scrollback makes no sense, and 0 would screw
++		   the operation totally */
++		softback_top = 0;
++}
++
+ static void fb_flashcursor(struct work_struct *work)
+ {
+ 	struct fb_info *info = container_of(work, struct fb_info, queue);
+@@ -394,7 +414,7 @@ static void fb_flashcursor(struct work_s
+ 	c = scr_readw((u16 *) vc->vc_pos);
+ 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
+ 		CM_ERASE : CM_DRAW;
+-	ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
++	ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
+ 		    get_color(vc, info, c, 0));
+ 	console_unlock();
+ }
+@@ -451,7 +471,13 @@ static int __init fb_console_setup(char
+ 		}
+ 		
+ 		if (!strncmp(options, "scrollback:", 11)) {
+-			pr_warn("Ignoring scrollback size option\n");
++			options += 11;
++			if (*options) {
++				fbcon_softback_size = simple_strtoul(options, &options, 0);
++				if (*options == 'k' || *options == 'K') {
++					fbcon_softback_size *= 1024;
++				}
++			}
+ 			continue;
+ 		}
+ 		
+@@ -996,6 +1022,31 @@ static const char *fbcon_startup(void)
+ 
+ 	set_blitting_type(vc, info);
+ 
++	if (info->fix.type != FB_TYPE_TEXT) {
++		if (fbcon_softback_size) {
++			if (!softback_buf) {
++				softback_buf =
++				    (unsigned long)
++				    kvmalloc(fbcon_softback_size,
++					    GFP_KERNEL);
++				if (!softback_buf) {
++					fbcon_softback_size = 0;
++					softback_top = 0;
++				}
++			}
++		} else {
++			if (softback_buf) {
++				kvfree((void *) softback_buf);
++				softback_buf = 0;
++				softback_top = 0;
++			}
++		}
++		if (softback_buf)
++			softback_in = softback_top = softback_curr =
++			    softback_buf;
++		softback_lines = 0;
++	}
++
+ 	/* Setup default font */
+ 	if (!p->fontdata && !vc->vc_font.data) {
+ 		if (!fontname[0] || !(font = find_font(fontname)))
+@@ -1170,6 +1221,9 @@ static void fbcon_init(struct vc_data *v
+ 	if (logo)
+ 		fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
+ 
++	if (vc == svc && softback_buf)
++		fbcon_update_softback(vc);
++
+ 	if (ops->rotate_font && ops->rotate_font(info, vc)) {
+ 		ops->rotate = FB_ROTATE_UR;
+ 		set_blitting_type(vc, info);
+@@ -1332,6 +1386,7 @@ static void fbcon_cursor(struct vc_data
+ {
+ 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ 	struct fbcon_ops *ops = info->fbcon_par;
++	int y;
+  	int c = scr_readw((u16 *) vc->vc_pos);
+ 
+ 	ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+@@ -1345,8 +1400,16 @@ static void fbcon_cursor(struct vc_data
+ 		fbcon_add_cursor_timer(info);
+ 
+ 	ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
++	if (mode & CM_SOFTBACK) {
++		mode &= ~CM_SOFTBACK;
++		y = softback_lines;
++	} else {
++		if (softback_lines)
++			fbcon_set_origin(vc);
++		y = 0;
++	}
+ 
+-	ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
++	ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
+ 		    get_color(vc, info, c, 0));
+ }
+ 
+@@ -1417,6 +1480,8 @@ static void fbcon_set_disp(struct fb_inf
+ 
+ 	if (con_is_visible(vc)) {
+ 		update_screen(vc);
++		if (softback_buf)
++			fbcon_update_softback(vc);
+ 	}
+ }
+ 
+@@ -1554,6 +1619,99 @@ static __inline__ void ypan_down_redraw(
+ 	scrollback_current = 0;
+ }
+ 
++static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
++				  long delta)
++{
++	int count = vc->vc_rows;
++	unsigned short *d, *s;
++	unsigned long n;
++	int line = 0;
++
++	d = (u16 *) softback_curr;
++	if (d == (u16 *) softback_in)
++		d = (u16 *) vc->vc_origin;
++	n = softback_curr + delta * vc->vc_size_row;
++	softback_lines -= delta;
++	if (delta < 0) {
++		if (softback_curr < softback_top && n < softback_buf) {
++			n += softback_end - softback_buf;
++			if (n < softback_top) {
++				softback_lines -=
++				    (softback_top - n) / vc->vc_size_row;
++				n = softback_top;
++			}
++		} else if (softback_curr >= softback_top
++			   && n < softback_top) {
++			softback_lines -=
++			    (softback_top - n) / vc->vc_size_row;
++			n = softback_top;
++		}
++	} else {
++		if (softback_curr > softback_in && n >= softback_end) {
++			n += softback_buf - softback_end;
++			if (n > softback_in) {
++				n = softback_in;
++				softback_lines = 0;
++			}
++		} else if (softback_curr <= softback_in && n > softback_in) {
++			n = softback_in;
++			softback_lines = 0;
++		}
++	}
++	if (n == softback_curr)
++		return;
++	softback_curr = n;
++	s = (u16 *) softback_curr;
++	if (s == (u16 *) softback_in)
++		s = (u16 *) vc->vc_origin;
++	while (count--) {
++		unsigned short *start;
++		unsigned short *le;
++		unsigned short c;
++		int x = 0;
++		unsigned short attr = 1;
++
++		start = s;
++		le = advance_row(s, 1);
++		do {
++			c = scr_readw(s);
++			if (attr != (c & 0xff00)) {
++				attr = c & 0xff00;
++				if (s > start) {
++					fbcon_putcs(vc, start, s - start,
++						    line, x);
++					x += s - start;
++					start = s;
++				}
++			}
++			if (c == scr_readw(d)) {
++				if (s > start) {
++					fbcon_putcs(vc, start, s - start,
++						    line, x);
++					x += s - start + 1;
++					start = s + 1;
++				} else {
++					x++;
++					start++;
++				}
++			}
++			s++;
++			d++;
++		} while (s < le);
++		if (s > start)
++			fbcon_putcs(vc, start, s - start, line, x);
++		line++;
++		if (d == (u16 *) softback_end)
++			d = (u16 *) softback_buf;
++		if (d == (u16 *) softback_in)
++			d = (u16 *) vc->vc_origin;
++		if (s == (u16 *) softback_end)
++			s = (u16 *) softback_buf;
++		if (s == (u16 *) softback_in)
++			s = (u16 *) vc->vc_origin;
++	}
++}
++
+ static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
+ 			      int line, int count, int dy)
+ {
+@@ -1693,6 +1851,31 @@ static void fbcon_redraw(struct vc_data
+ 	}
+ }
+ 
++static inline void fbcon_softback_note(struct vc_data *vc, int t,
++				       int count)
++{
++	unsigned short *p;
++
++	if (vc->vc_num != fg_console)
++		return;
++	p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
++
++	while (count) {
++		scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
++		count--;
++		p = advance_row(p, 1);
++		softback_in += vc->vc_size_row;
++		if (softback_in == softback_end)
++			softback_in = softback_buf;
++		if (softback_in == softback_top) {
++			softback_top += vc->vc_size_row;
++			if (softback_top == softback_end)
++				softback_top = softback_buf;
++		}
++	}
++	softback_curr = softback_in;
++}
++
+ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+ 		enum con_scroll dir, unsigned int count)
+ {
+@@ -1715,6 +1898,8 @@ static bool fbcon_scroll(struct vc_data
+ 	case SM_UP:
+ 		if (count > vc->vc_rows)	/* Maximum realistic size */
+ 			count = vc->vc_rows;
++		if (softback_top)
++			fbcon_softback_note(vc, t, count);
+ 		if (logo_shown >= 0)
+ 			goto redraw_up;
+ 		switch (p->scrollmode) {
+@@ -2053,6 +2238,14 @@ static int fbcon_switch(struct vc_data *
+ 	info = registered_fb[con2fb_map[vc->vc_num]];
+ 	ops = info->fbcon_par;
+ 
++	if (softback_top) {
++		if (softback_lines)
++			fbcon_set_origin(vc);
++		softback_top = softback_curr = softback_in = softback_buf;
++		softback_lines = 0;
++		fbcon_update_softback(vc);
++	}
++
+ 	if (logo_shown >= 0) {
+ 		struct vc_data *conp2 = vc_cons[logo_shown].d;
+ 
+@@ -2388,6 +2581,9 @@ static int fbcon_do_set_font(struct vc_d
+ 	int cnt;
+ 	char *old_data = NULL;
+ 
++	if (con_is_visible(vc) && softback_lines)
++		fbcon_set_origin(vc);
++
+ 	resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
+ 	if (p->userfont)
+ 		old_data = vc->vc_font.data;
+@@ -2413,6 +2609,8 @@ static int fbcon_do_set_font(struct vc_d
+ 		cols /= w;
+ 		rows /= h;
+ 		vc_resize(vc, cols, rows);
++		if (con_is_visible(vc) && softback_buf)
++			fbcon_update_softback(vc);
+ 	} else if (con_is_visible(vc)
+ 		   && vc->vc_mode == KD_TEXT) {
+ 		fbcon_clear_margins(vc, 0);
+@@ -2571,7 +2769,19 @@ static void fbcon_set_palette(struct vc_
+ 
+ static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset)
+ {
+-	return (u16 *) (vc->vc_origin + offset);
++	unsigned long p;
++	int line;
++	
++	if (vc->vc_num != fg_console || !softback_lines)
++		return (u16 *) (vc->vc_origin + offset);
++	line = offset / vc->vc_size_row;
++	if (line >= softback_lines)
++		return (u16 *) (vc->vc_origin + offset -
++				softback_lines * vc->vc_size_row);
++	p = softback_curr + offset;
++	if (p >= softback_end)
++		p += softback_buf - softback_end;
++	return (u16 *) p;
+ }
+ 
+ static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
+@@ -2585,7 +2795,22 @@ static unsigned long fbcon_getxy(struct
+ 
+ 		x = offset % vc->vc_cols;
+ 		y = offset / vc->vc_cols;
++		if (vc->vc_num == fg_console)
++			y += softback_lines;
+ 		ret = pos + (vc->vc_cols - x) * 2;
++	} else if (vc->vc_num == fg_console && softback_lines) {
++		unsigned long offset = pos - softback_curr;
++
++		if (pos < softback_curr)
++			offset += softback_end - softback_buf;
++		offset /= 2;
++		x = offset % vc->vc_cols;
++		y = offset / vc->vc_cols;
++		ret = pos + (vc->vc_cols - x) * 2;
++		if (ret == softback_end)
++			ret = softback_buf;
++		if (ret == softback_in)
++			ret = vc->vc_origin;
+ 	} else {
+ 		/* Should not happen */
+ 		x = y = 0;
+@@ -2613,11 +2838,106 @@ static void fbcon_invert_region(struct v
+ 			a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
+ 			    (((a) & 0x0700) << 4);
+ 		scr_writew(a, p++);
++		if (p == (u16 *) softback_end)
++			p = (u16 *) softback_buf;
++		if (p == (u16 *) softback_in)
++			p = (u16 *) vc->vc_origin;
++	}
++}
++
++static void fbcon_scrolldelta(struct vc_data *vc, int lines)
++{
++	struct fb_info *info = registered_fb[con2fb_map[fg_console]];
++	struct fbcon_ops *ops = info->fbcon_par;
++	struct fbcon_display *disp = &fb_display[fg_console];
++	int offset, limit, scrollback_old;
++
++	if (softback_top) {
++		if (vc->vc_num != fg_console)
++			return;
++		if (vc->vc_mode != KD_TEXT || !lines)
++			return;
++		if (logo_shown >= 0) {
++			struct vc_data *conp2 = vc_cons[logo_shown].d;
++
++			if (conp2->vc_top == logo_lines
++			    && conp2->vc_bottom == conp2->vc_rows)
++				conp2->vc_top = 0;
++			if (logo_shown == vc->vc_num) {
++				unsigned long p, q;
++				int i;
++
++				p = softback_in;
++				q = vc->vc_origin +
++				    logo_lines * vc->vc_size_row;
++				for (i = 0; i < logo_lines; i++) {
++					if (p == softback_top)
++						break;
++					if (p == softback_buf)
++						p = softback_end;
++					p -= vc->vc_size_row;
++					q -= vc->vc_size_row;
++					scr_memcpyw((u16 *) q, (u16 *) p,
++						    vc->vc_size_row);
++				}
++				softback_in = softback_curr = p;
++				update_region(vc, vc->vc_origin,
++					      logo_lines * vc->vc_cols);
++			}
++			logo_shown = FBCON_LOGO_CANSHOW;
++		}
++		fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
++		fbcon_redraw_softback(vc, disp, lines);
++		fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
++		return;
+ 	}
++
++	if (!scrollback_phys_max)
++		return;
++
++	scrollback_old = scrollback_current;
++	scrollback_current -= lines;
++	if (scrollback_current < 0)
++		scrollback_current = 0;
++	else if (scrollback_current > scrollback_max)
++		scrollback_current = scrollback_max;
++	if (scrollback_current == scrollback_old)
++		return;
++
++	if (fbcon_is_inactive(vc, info))
++		return;
++
++	fbcon_cursor(vc, CM_ERASE);
++
++	offset = disp->yscroll - scrollback_current;
++	limit = disp->vrows;
++	switch (disp->scrollmode) {
++	case SCROLL_WRAP_MOVE:
++		info->var.vmode |= FB_VMODE_YWRAP;
++		break;
++	case SCROLL_PAN_MOVE:
++	case SCROLL_PAN_REDRAW:
++		limit -= vc->vc_rows;
++		info->var.vmode &= ~FB_VMODE_YWRAP;
++		break;
++	}
++	if (offset < 0)
++		offset += limit;
++	else if (offset >= limit)
++		offset -= limit;
++
++	ops->var.xoffset = 0;
++	ops->var.yoffset = offset * vc->vc_font.height;
++	ops->update_start(info);
++
++	if (!scrollback_current)
++		fbcon_cursor(vc, CM_DRAW);
+ }
+ 
+ static int fbcon_set_origin(struct vc_data *vc)
+ {
++	if (softback_lines)
++		fbcon_scrolldelta(vc, softback_lines);
+ 	return 0;
+ }
+ 
+@@ -2681,6 +3001,8 @@ static void fbcon_modechanged(struct fb_
+ 
+ 		fbcon_set_palette(vc, color_table);
+ 		update_screen(vc);
++		if (softback_buf)
++			fbcon_update_softback(vc);
+ 	}
+ }
+ 
+@@ -3091,6 +3413,7 @@ static const struct consw fb_con = {
+ 	.con_font_default	= fbcon_set_def_font,
+ 	.con_font_copy 		= fbcon_copy_font,
+ 	.con_set_palette 	= fbcon_set_palette,
++	.con_scrolldelta 	= fbcon_scrolldelta,
+ 	.con_set_origin 	= fbcon_set_origin,
+ 	.con_invert_region 	= fbcon_invert_region,
+ 	.con_screen_pos 	= fbcon_screen_pos,
+@@ -3325,6 +3648,9 @@ static void fbcon_exit(void)
+ 	}
+ #endif
+ 
++	kvfree((void *)softback_buf);
++	softback_buf = 0UL;
++
+ 	for_each_registered_fb(i) {
+ 		int pending = 0;
+ 
diff --git a/0501-bootsplash.patch b/0501-bootsplash.patch
new file mode 100644
index 0000000..4370f87
--- /dev/null
+++ b/0501-bootsplash.patch
@@ -0,0 +1,714 @@
+diff -up linux-5.10/drivers/video/console/Kconfig.59~ linux-5.10/drivers/video/console/Kconfig
+--- linux-5.10/drivers/video/console/Kconfig.59~	2021-01-19 23:05:51.694607935 +0100
++++ linux-5.10/drivers/video/console/Kconfig	2021-01-19 23:07:32.109742870 +0100
+@@ -115,6 +115,30 @@ config FRAMEBUFFER_CONSOLE_DEFERRED_TAKE
+ 	  by the firmware in place, rather then replacing the contents with a
+ 	  black screen as soon as fbcon loads.
+ 
++config BOOTSPLASH
++	bool "Bootup splash screen"
++	depends on FRAMEBUFFER_CONSOLE
++	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 && HAS_IOMEM
+diff -up linux-5.10/drivers/video/fbdev/core/bootsplash.c.59~ linux-5.10/drivers/video/fbdev/core/bootsplash.c
+--- linux-5.10/drivers/video/fbdev/core/bootsplash.c.59~	2021-01-19 23:05:51.694607935 +0100
++++ linux-5.10/drivers/video/fbdev/core/bootsplash.c	2021-01-19 23:05:51.694607935 +0100
+@@ -0,0 +1,294 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#define pr_fmt(fmt) "bootsplash: " fmt
++
++
++#include <linux/atomic.h>
++#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
++ * instance of the internal state.
++ */
++static struct splash_priv splash_state;
++
++
++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 bool is_fb_compatible(const struct fb_info *info)
++{
++	if (!(info->flags & FBINFO_BE_MATH)
++	    != !fb_be_math((struct fb_info *)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 by fbcon_switch() when an 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)
++{
++	bool was_enabled;
++
++	/* Make sure we have the newest state */
++	smp_rmb();
++
++	was_enabled = test_bit(0, &splash_state.enabled);
++
++	return was_enabled;
++}
++
++void bootsplash_disable(void)
++{
++	int was_enabled;
++
++	was_enabled = test_and_clear_bit(0, &splash_state.enabled);
++
++	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 */
++			schedule_work(&splash_state.work_redraw_vc);
++		}
++	}
++}
++
++void bootsplash_enable(void)
++{
++	bool was_enabled;
++
++	if (oops_in_progress)
++		return;
++
++	was_enabled = test_and_set_bit(0, &splash_state.enabled);
++
++	if (!was_enabled)
++		schedule_work(&splash_state.work_redraw_vc);
++}
++
++
++/*
++ * 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", bootsplash_is_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);
++
++
++
++
++/*
++ * Power management fixup via platform device
++ *
++ * When the system is woken from sleep or restored after hibernating, we
++ * cannot expect the screen contents to still be present in video RAM.
++ * Thus, we have to redraw the splash if we're currently active.
++ */
++static int splash_resume(struct device *device)
++{
++	if (bootsplash_would_render_now())
++		schedule_work(&splash_state.work_redraw_vc);
++
++	return 0;
++}
++
++static int splash_suspend(struct device *device)
++{
++	cancel_work_sync(&splash_state.work_redraw_vc);
++
++	return 0;
++}
++
++
++static const struct dev_pm_ops splash_pm_ops = {
++	.thaw = splash_resume,
++	.restore = splash_resume,
++	.resume = splash_resume,
++	.suspend = splash_suspend,
++	.freeze = splash_suspend,
++};
++
++static struct platform_driver splash_driver = {
++	.driver = {
++		.name = "bootsplash",
++		.pm = &splash_pm_ops,
++	},
++};
++
++
++/*
++ * Main init
++ */
++void bootsplash_init(void)
++{
++	int ret;
++
++	/* Initialized already? */
++	if (splash_state.splash_device)
++		return;
++
++
++	/* Register platform device to export user API */
++	ret = platform_driver_register(&splash_driver);
++	if (ret) {
++		pr_err("platform_driver_register() failed: %d\n", ret);
++		goto err;
++	}
++
++	splash_state.splash_device
++		= platform_device_alloc("bootsplash", 0);
++
++	if (!splash_state.splash_device)
++		goto err_driver;
++
++	splash_state.splash_device->dev.groups = splash_dev_groups;
++
++	ret = platform_device_add(splash_state.splash_device);
++	if (ret) {
++		pr_err("platform_device_add() failed: %d\n", ret);
++		goto err_device;
++	}
++
++
++	INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
++
++	return;
++
++err_device:
++	platform_device_put(splash_state.splash_device);
++	splash_state.splash_device = NULL;
++err_driver:
++	platform_driver_unregister(&splash_driver);
++err:
++	pr_err("Failed to initialize.\n");
++}
+diff -up linux-5.10/drivers/video/fbdev/core/bootsplash_internal.h.59~ linux-5.10/drivers/video/fbdev/core/bootsplash_internal.h
+--- linux-5.10/drivers/video/fbdev/core/bootsplash_internal.h.59~	2021-01-19 23:05:51.697941328 +0100
++++ linux-5.10/drivers/video/fbdev/core/bootsplash_internal.h	2021-01-19 23:05:51.697941328 +0100
+@@ -0,0 +1,55 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Internal data structures used at runtime)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#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>
++
++
++/*
++ * Runtime types
++ */
++struct splash_priv {
++	/*
++	 * Enabled/disabled state, to be used with atomic bit operations.
++	 *   Bit 0: 0 = Splash hidden
++	 *          1 = Splash shown
++	 *
++	 * 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.
++	 */
++	unsigned long enabled;
++
++	/* Our gateway to userland via sysfs */
++	struct platform_device *splash_device;
++
++	struct work_struct work_redraw_vc;
++};
++
++
++
++/*
++ * Rendering functions
++ */
++void bootsplash_do_render_background(struct fb_info *info);
++
++#endif
+diff -up linux-5.10/drivers/video/fbdev/core/bootsplash_render.c.59~ linux-5.10/drivers/video/fbdev/core/bootsplash_render.c
+--- linux-5.10/drivers/video/fbdev/core/bootsplash_render.c.59~	2021-01-19 23:05:51.697941328 +0100
++++ linux-5.10/drivers/video/fbdev/core/bootsplash_render.c	2021-01-19 23:05:51.697941328 +0100
+@@ -0,0 +1,93 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Rendering functions)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#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(const 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 -up linux-5.10/drivers/video/fbdev/core/dummyblit.c.59~ linux-5.10/drivers/video/fbdev/core/dummyblit.c
+--- linux-5.10/drivers/video/fbdev/core/dummyblit.c.59~	2021-01-19 23:05:51.697941328 +0100
++++ linux-5.10/drivers/video/fbdev/core/dummyblit.c	2021-01-19 23:05:51.697941328 +0100
+@@ -0,0 +1,89 @@
++/*
++ *  linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
++ *
++ *  Authors:
++ *  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
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#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_GPL(fbcon_set_dummyops);
++
++MODULE_AUTHOR("Max Staudt <mstaudt@suse.de>");
++MODULE_DESCRIPTION("Dummy Blitting Operation");
++MODULE_LICENSE("GPL");
+diff -up linux-5.10/drivers/video/fbdev/core/fbcon.c.59~ linux-5.10/drivers/video/fbdev/core/fbcon.c
+--- linux-5.10/drivers/video/fbdev/core/fbcon.c.59~	2021-01-19 23:05:51.691274541 +0100
++++ linux-5.10/drivers/video/fbdev/core/fbcon.c	2021-01-19 23:05:51.697941328 +0100
+@@ -81,6 +81,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)
+@@ -585,6 +586,8 @@ static int do_fbcon_takeover(int show_lo
+ 	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);
+ 
+@@ -708,6 +711,9 @@ static void set_blitting_type(struct vc_
+ 	else {
+ 		fbcon_set_rotation(info);
+ 		fbcon_set_bitops(ops);
++
++		if (bootsplash_would_render_now())
++			fbcon_set_dummyops(ops);
+ 	}
+ }
+ 
+@@ -730,6 +736,19 @@ static void set_blitting_type(struct vc_
+ 	ops->p = &fb_display[vc->vc_num];
+ 	fbcon_set_rotation(info);
+ 	fbcon_set_bitops(ops);
++
++	/*
++	 * Note:
++	 * This is *eventually correct*.
++	 * Setting the fbcon operations and drawing the splash happen at
++	 * different points in time. If the splash is enabled/disabled
++	 * in between, then bootsplash_{en,dis}able will schedule a
++	 * redraw, which will again render the splash (or not) and set
++	 * the correct fbcon ops.
++	 * The last run will then be the right one.
++	 */
++	if (bootsplash_would_render_now())
++		fbcon_set_dummyops(ops);
+ }
+ 
+ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+@@ -2238,6 +2257,9 @@ static int fbcon_switch(struct vc_data *
+ 	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 -up linux-5.10/drivers/video/fbdev/core/fbcon.h.59~ linux-5.10/drivers/video/fbdev/core/fbcon.h
+--- linux-5.10/drivers/video/fbdev/core/fbcon.h.59~	2021-01-19 23:05:51.687941149 +0100
++++ linux-5.10/drivers/video/fbdev/core/fbcon.h	2021-01-19 23:05:51.697941328 +0100
+@@ -208,6 +208,11 @@ static inline int attr_col_ec(int shift,
+ #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 -up linux-5.10/drivers/video/fbdev/core/Makefile.59~ linux-5.10/drivers/video/fbdev/core/Makefile
+--- linux-5.10/drivers/video/fbdev/core/Makefile.59~	2020-12-13 23:41:30.000000000 +0100
++++ linux-5.10/drivers/video/fbdev/core/Makefile	2021-01-19 23:05:51.694607935 +0100
+@@ -26,3 +26,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimg
+ 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 -up linux-5.10/include/linux/bootsplash.h.59~ linux-5.10/include/linux/bootsplash.h
+--- linux-5.10/include/linux/bootsplash.h.59~	2021-01-19 23:05:51.697941328 +0100
++++ linux-5.10/include/linux/bootsplash.h	2021-01-19 23:05:51.697941328 +0100
+@@ -0,0 +1,43 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#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
+diff -up linux-5.10/MAINTAINERS.59~ linux-5.10/MAINTAINERS
diff --git a/0502-bootsplash.patch b/0502-bootsplash.patch
new file mode 100644
index 0000000..e8d4cc8
--- /dev/null
+++ b/0502-bootsplash.patch
@@ -0,0 +1,657 @@
+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 e449755af268..843c5400fefc 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -32,6 +32,7 @@
+ #include <linux/workqueue.h>
+ 
+ #include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
+ 
+ 
+ /*
+@@ -102,10 +103,17 @@ static bool is_fb_compatible(const struct fb_info *info)
+  */
+ void bootsplash_render_full(struct fb_info *info)
+ {
++	mutex_lock(&splash_state.data_lock);
++
+ 	if (!is_fb_compatible(info))
+-		return;
++		goto out;
++
++	bootsplash_do_render_background(info, splash_state.file);
++
++	bootsplash_do_render_pictures(info, splash_state.file);
+ 
+-	bootsplash_do_render_background(info);
++out:
++	mutex_unlock(&splash_state.data_lock);
+ }
+ 
+ 
+@@ -116,6 +124,7 @@ bool bootsplash_would_render_now(void)
+ {
+ 	return !oops_in_progress
+ 		&& !console_blanked
++		&& splash_state.file
+ 		&& bootsplash_is_enabled();
+ }
+ 
+@@ -252,6 +261,7 @@ static struct platform_driver splash_driver = {
+ void bootsplash_init(void)
+ {
+ 	int ret;
++	struct splash_file_priv *fp;
+ 
+ 	/* Initialized already? */
+ 	if (splash_state.splash_device)
+@@ -280,8 +290,26 @@ void bootsplash_init(void)
+ 	}
+ 
+ 
++	mutex_init(&splash_state.data_lock);
++	set_bit(0, &splash_state.enabled);
++
+ 	INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
+ 
++
++	if (!splash_state.bootfile || !strlen(splash_state.bootfile))
++		return;
++
++	fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
++				      splash_state.bootfile);
++
++	if (!fp)
++		goto err;
++
++	mutex_lock(&splash_state.data_lock);
++	splash_state.splash_fb = NULL;
++	splash_state.file = fp;
++	mutex_unlock(&splash_state.data_lock);
++
+ 	return;
+ 
+ err_device:
+@@ -292,3 +320,7 @@ void bootsplash_init(void)
+ err:
+ 	pr_err("Failed to initialize.\n");
+ }
++
++
++module_param_named(bootfile, splash_state.bootfile, charp, 0444);
++MODULE_PARM_DESC(bootfile, "Bootsplash file to load on boot");
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index b11da5cb90bf..71e2a27ac0b8 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -15,15 +15,43 @@
+ 
+ #include <linux/types.h>
+ #include <linux/fb.h>
++#include <linux/firmware.h>
+ #include <linux/kernel.h>
+ #include <linux/mutex.h>
+ #include <linux/spinlock.h>
+ 
++#include "uapi/linux/bootsplash_file.h"
++
+ 
+ /*
+  * Runtime types
+  */
++struct splash_blob_priv {
++	struct splash_blob_header *blob_header;
++	const void *data;
++};
++
++
++struct splash_pic_priv {
++	const struct splash_pic_header *pic_header;
++
++	struct splash_blob_priv *blobs;
++	u16 blobs_loaded;
++};
++
++
++struct splash_file_priv {
++	const struct firmware *fw;
++	const struct splash_file_header *header;
++
++	struct splash_pic_priv *pics;
++};
++
++
+ struct splash_priv {
++	/* Bootup and runtime state */
++	char *bootfile;
++
+ 	/*
+ 	 * Enabled/disabled state, to be used with atomic bit operations.
+ 	 *   Bit 0: 0 = Splash hidden
+@@ -43,6 +71,13 @@ struct splash_priv {
+ 	struct platform_device *splash_device;
+ 
+ 	struct work_struct work_redraw_vc;
++
++	/* Splash data structures including lock for everything below */
++	struct mutex data_lock;
++
++	struct fb_info *splash_fb;
++
++	struct splash_file_priv *file;
+ };
+ 
+ 
+@@ -50,6 +85,14 @@ struct splash_priv {
+ /*
+  * Rendering functions
+  */
+-void bootsplash_do_render_background(struct fb_info *info);
++void bootsplash_do_render_background(struct fb_info *info,
++				     const struct splash_file_priv *fp);
++void bootsplash_do_render_pictures(struct fb_info *info,
++				   const struct splash_file_priv *fp);
++
++
++void bootsplash_free_file(struct splash_file_priv *fp);
++struct splash_file_priv *bootsplash_load_firmware(struct device *device,
++						  const char *path);
+ 
+ #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..fd807571ab7d
+--- /dev/null
++++ b/drivers/video/fbdev/core/bootsplash_load.c
+@@ -0,0 +1,225 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Loading and freeing functions)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#define pr_fmt(fmt) "bootsplash: " fmt
++
++
++#include <linux/bootsplash.h>
++#include <linux/fb.h>
++#include <linux/firmware.h>
++#include <linux/kernel.h>
++#include <linux/mutex.h>
++#include <linux/printk.h>
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++
++#include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
++
++
++
++
++/*
++ * Free all vmalloc()'d resources describing a splash file.
++ */
++void bootsplash_free_file(struct splash_file_priv *fp)
++{
++	if (!fp)
++		return;
++
++	if (fp->pics) {
++		unsigned int i;
++
++		for (i = 0; i < fp->header->num_pics; i++) {
++			struct splash_pic_priv *pp = &fp->pics[i];
++
++			if (pp->blobs)
++				vfree(pp->blobs);
++		}
++
++		vfree(fp->pics);
++	}
++
++	release_firmware(fp->fw);
++	vfree(fp);
++}
++
++
++
++
++/*
++ * Load a splash screen from a "firmware" file.
++ *
++ * Parsing, and sanity checks.
++ */
++#ifdef __BIG_ENDIAN
++	#define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_BE
++#else
++	#define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_LE
++#endif
++
++struct splash_file_priv *bootsplash_load_firmware(struct device *device,
++						  const char *path)
++{
++	const struct firmware *fw;
++	struct splash_file_priv *fp;
++	unsigned int i;
++	const u8 *walker;
++
++	if (request_firmware(&fw, path, device))
++		return NULL;
++
++	if (fw->size < sizeof(struct splash_file_header)
++	    || memcmp(fw->data, BOOTSPLASH_MAGIC, sizeof(fp->header->id))) {
++		pr_err("Not a bootsplash file.\n");
++
++		release_firmware(fw);
++		return NULL;
++	}
++
++	fp = vzalloc(sizeof(struct splash_file_priv));
++	if (!fp) {
++		release_firmware(fw);
++		return NULL;
++	}
++
++	pr_info("Loading splash file (%li bytes)\n", fw->size);
++
++	fp->fw = fw;
++	fp->header = (struct splash_file_header *)fw->data;
++
++	/* Sanity checks */
++	if (fp->header->version != BOOTSPLASH_VERSION) {
++		pr_err("Loaded v%d file, but we only support version %d\n",
++			fp->header->version,
++			BOOTSPLASH_VERSION);
++
++		goto err;
++	}
++
++	if (fw->size < sizeof(struct splash_file_header)
++		+ fp->header->num_pics
++			* sizeof(struct splash_pic_header)
++		+ fp->header->num_blobs
++			* sizeof(struct splash_blob_header)) {
++		pr_err("File incomplete.\n");
++
++		goto err;
++	}
++
++	/* Read picture headers */
++	if (fp->header->num_pics) {
++		fp->pics = vzalloc(fp->header->num_pics
++				   * sizeof(struct splash_pic_priv));
++		if (!fp->pics)
++			goto err;
++	}
++
++	walker = fw->data + sizeof(struct splash_file_header);
++	for (i = 0; i < fp->header->num_pics; i++) {
++		struct splash_pic_priv *pp = &fp->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)
++			goto err;
++
++		walker += sizeof(struct splash_pic_header);
++	}
++
++	/* Read blob headers */
++	for (i = 0; i < fp->header->num_blobs; i++) {
++		struct splash_blob_header *bh = (void *)walker;
++		struct splash_pic_priv *pp;
++
++		if (walker + sizeof(struct splash_blob_header)
++		    > fw->data + fw->size)
++			goto err;
++
++		walker += sizeof(struct splash_blob_header);
++
++		if (walker + bh->length > fw->data + fw->size)
++			goto err;
++
++		if (bh->picture_id >= fp->header->num_pics)
++			goto nextblob;
++
++		pp = &fp->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 != fw->data + fw->size)
++		pr_warn("Trailing data in splash file.\n");
++
++	/* Walk over pictures and ensure all blob slots are filled */
++	for (i = 0; i < fp->header->num_pics; i++) {
++		struct splash_pic_priv *pp = &fp->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;
++		}
++	}
++
++	pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
++		fw->size,
++		fp->header->num_pics,
++		fp->header->num_blobs);
++
++	return fp;
++
++
++err:
++	bootsplash_free_file(fp);
++	return NULL;
++}
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 4d7e0117f653..2ae36949d0e3 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -19,6 +19,7 @@
+ #include <linux/types.h>
+ 
+ #include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
+ 
+ 
+ 
+@@ -70,16 +71,69 @@ static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
+ }
+ 
+ 
+-void bootsplash_do_render_background(struct fb_info *info)
++/*
++ * 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,
++				const struct fb_var_screeninfo *dst_var,
++				unsigned int dst_stride,
++				unsigned int dst_xoff,
++				unsigned int dst_yoff,
++				const 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++) {
++		const 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,
++				     const struct splash_file_priv *fp)
+ {
+ 	unsigned int x, y;
+ 	u32 dstpix;
+ 	u32 dst_octpp = info->var.bits_per_pixel / 8;
+ 
+ 	dstpix = pack_pixel(&info->var,
+-			    0,
+-			    0,
+-			    0);
++			    fp->header->bg_red,
++			    fp->header->bg_green,
++			    fp->header->bg_blue);
+ 
+ 	for (y = 0; y < info->var.yres_virtual; y++) {
+ 		u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
+@@ -91,3 +145,44 @@ void bootsplash_do_render_background(struct fb_info *info)
+ 		}
+ 	}
+ }
++
++
++void bootsplash_do_render_pictures(struct fb_info *info,
++				   const struct splash_file_priv *fp)
++{
++	unsigned int i;
++
++	for (i = 0; i < fp->header->num_pics; i++) {
++		struct splash_blob_priv *bp;
++		struct splash_pic_priv *pp = &fp->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_info_once("Picture %u is out of bounds at current resolution: %dx%d\n"
++				     "(this will only be printed once every reboot)\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);
++	}
++}
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+new file mode 100644
+index 000000000000..89dc9cca8f0c
+--- /dev/null
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -0,0 +1,118 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (File format)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
++ */
++
++#ifndef __BOOTSPLASH_FILE_H
++#define __BOOTSPLASH_FILE_H
++
++
++#define BOOTSPLASH_VERSION 55561
++
++
++#include <linux/kernel.h>
++#include <linux/types.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 in the native format
++ * expected by the system the file will be used on.
++ */
++#define BOOTSPLASH_MAGIC_BE "Linux bootsplash"
++#define BOOTSPLASH_MAGIC_LE "hsalpstoob xuniL"
++
++struct splash_file_header {
++	uint8_t  id[16]; /* "Linux bootsplash" (no trailing NUL) */
++
++	/* Splash file format version to avoid clashes */
++	uint16_t version;
++
++	/* The background color */
++	uint8_t bg_red;
++	uint8_t bg_green;
++	uint8_t bg_blue;
++	uint8_t bg_reserved;
++
++	/*
++	 * Number of pic/blobs so we can allocate memory for internal
++	 * structures ahead of time when reading the file
++	 */
++	uint16_t num_blobs;
++	uint8_t num_pics;
++
++	uint8_t padding[103];
++} __attribute__((__packed__));
++
++
++struct splash_pic_header {
++	uint16_t width;
++	uint16_t height;
++
++	/*
++	 * Number of data packages associated with this picture.
++	 * Currently, the only use for more than 1 is for animations.
++	 */
++	uint8_t num_blobs;
++
++	uint8_t padding[27];
++} __attribute__((__packed__));
++
++
++struct splash_blob_header {
++	/* Length of the data block in bytes. */
++	uint32_t length;
++
++	/*
++	 * Type of the contents.
++	 *  0 - Raw RGB data.
++	 */
++	uint16_t type;
++
++	/*
++	 * Picture this blob is associated with.
++	 * Blobs will be added to a picture in the order they are
++	 * found in the file.
++	 */
++	uint8_t picture_id;
++
++	uint8_t padding[9];
++} __attribute__((__packed__));
++
++#endif
diff --git a/0503-bootsplash.patch b/0503-bootsplash.patch
new file mode 100644
index 0000000..2169537
--- /dev/null
+++ b/0503-bootsplash.patch
@@ -0,0 +1,66 @@
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 843c5400fefc..815b007f81ca 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -112,6 +112,8 @@ void bootsplash_render_full(struct fb_info *info)
+ 
+ 	bootsplash_do_render_pictures(info, splash_state.file);
+ 
++	bootsplash_do_render_flush(info);
++
+ out:
+ 	mutex_unlock(&splash_state.data_lock);
+ }
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index 71e2a27ac0b8..0acb383aa4e3 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -89,6 +89,7 @@ void bootsplash_do_render_background(struct fb_info *info,
+ 				     const struct splash_file_priv *fp);
+ void bootsplash_do_render_pictures(struct fb_info *info,
+ 				   const struct splash_file_priv *fp);
++void bootsplash_do_render_flush(struct fb_info *info);
+ 
+ 
+ void bootsplash_free_file(struct splash_file_priv *fp);
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 2ae36949d0e3..8c09c306ff67 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -186,3 +186,36 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ 				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
++	 * 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);
++	}
++}
diff --git a/0504-bootsplash.patch b/0504-bootsplash.patch
new file mode 100644
index 0000000..7eb54af
--- /dev/null
+++ b/0504-bootsplash.patch
@@ -0,0 +1,215 @@
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 8c09c306ff67..07e3a4eab811 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -155,6 +155,7 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ 	for (i = 0; i < fp->header->num_pics; i++) {
+ 		struct splash_blob_priv *bp;
+ 		struct splash_pic_priv *pp = &fp->pics[i];
++		const struct splash_pic_header *ph = pp->pic_header;
+ 		long dst_xoff, dst_yoff;
+ 
+ 		if (pp->blobs_loaded < 1)
+@@ -165,8 +166,139 @@ 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->position) {
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_LEFT:
++			dst_xoff = 0;
++			dst_yoff = 0;
++
++			dst_xoff += ph->position_offset;
++			dst_yoff += ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = 0;
++
++			dst_yoff += ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_yoff = 0;
++
++			dst_xoff -= ph->position_offset;
++			dst_yoff += ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff -= ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++
++			dst_xoff -= ph->position_offset;
++			dst_yoff -= ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++
++			dst_yoff -= ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_LEFT:
++			dst_xoff = 0 + ph->position_offset;
++			dst_yoff = info->var.yres - pp->pic_header->height
++						  - ph->position_offset;
++			break;
++		case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_LEFT:
++			dst_xoff = 0;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff += ph->position_offset;
++			break;
++
++		case SPLASH_CORNER_TOP_LEFT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff -= ph->position_offset;
++			dst_yoff -= ph->position_offset;
++			break;
++		case SPLASH_CORNER_TOP:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_yoff -= ph->position_offset;
++			break;
++		case SPLASH_CORNER_TOP_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff += ph->position_offset;
++			dst_yoff -= ph->position_offset;
++			break;
++		case SPLASH_CORNER_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff += ph->position_offset;
++			break;
++		case SPLASH_CORNER_BOTTOM_RIGHT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff += ph->position_offset;
++			dst_yoff += ph->position_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;
++			dst_yoff /= 2;
++
++			dst_yoff += ph->position_offset;
++			break;
++		case SPLASH_CORNER_BOTTOM_LEFT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff -= ph->position_offset;
++			dst_yoff += ph->position_offset;
++			break;
++		case SPLASH_CORNER_LEFT:
++			dst_xoff = info->var.xres - pp->pic_header->width;
++			dst_xoff /= 2;
++			dst_yoff = info->var.yres - pp->pic_header->height;
++			dst_yoff /= 2;
++
++			dst_xoff -= ph->position_offset;
++			break;
++
++		default:
++			/* As a fallback, center the picture. */
++			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
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+index 89dc9cca8f0c..71cedcc68933 100644
+--- a/include/uapi/linux/bootsplash_file.h
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -91,7 +91,32 @@ struct splash_pic_header {
+ 	 */
+ 	uint8_t num_blobs;
+ 
+-	uint8_t padding[27];
++	/*
++	 * Corner to move the picture to / from.
++	 *  0x00 - Top left
++	 *  0x01 - Top
++	 *  0x02 - Top right
++	 *  0x03 - Right
++	 *  0x04 - Bottom right
++	 *  0x05 - Bottom
++	 *  0x06 - Bottom left
++	 *  0x07 - Left
++	 *
++	 * Flags:
++	 *  0x10 - Calculate offset from the corner towards the center,
++	 *         rather than from the center towards the corner
++	 */
++	uint8_t position;
++
++	/*
++	 * Pixel offset from the selected position.
++	 * Example: If the picture is in the top right corner, it will
++	 *          be placed position_offset pixels from the top and
++	 *          position_offset pixels from the right margin.
++	 */
++	uint16_t position_offset;
++
++	uint8_t padding[24];
+ } __attribute__((__packed__));
+ 
+ 
+@@ -115,4 +140,22 @@ struct splash_blob_header {
+ 	uint8_t padding[9];
+ } __attribute__((__packed__));
+ 
++
++
++
++/*
++ * Enums for on-disk types
++ */
++enum splash_position {
++	SPLASH_CORNER_TOP_LEFT = 0,
++	SPLASH_CORNER_TOP = 1,
++	SPLASH_CORNER_TOP_RIGHT = 2,
++	SPLASH_CORNER_RIGHT = 3,
++	SPLASH_CORNER_BOTTOM_RIGHT = 4,
++	SPLASH_CORNER_BOTTOM = 5,
++	SPLASH_CORNER_BOTTOM_LEFT = 6,
++	SPLASH_CORNER_LEFT = 7,
++	SPLASH_POS_FLAG_CORNER = 0x10,
++};
++
+ #endif
diff --git a/0505-bootsplash.patch b/0505-bootsplash.patch
new file mode 100644
index 0000000..2785c5e
--- /dev/null
+++ b/0505-bootsplash.patch
@@ -0,0 +1,327 @@
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 815b007f81ca..c8642142cfea 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
+ 	console_unlock();
+ }
+ 
++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 bool is_fb_compatible(const struct fb_info *info)
+ {
+@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)
+  */
+ void bootsplash_render_full(struct fb_info *info)
+ {
++	bool is_update = false;
++
+ 	mutex_lock(&splash_state.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_state.splash_fb == info)
++		is_update = true;
++
++
++	if (!is_update) {
++		/* Check whether we actually support this FB. */
++		splash_state.splash_fb = NULL;
++
++		if (!is_fb_compatible(info))
++			goto out;
++
++		/* Draw the background only once */
++		bootsplash_do_render_background(info, splash_state.file);
+ 
+-	bootsplash_do_render_background(info, splash_state.file);
++		/* Mark this FB as last seen */
++		splash_state.splash_fb = info;
++	}
+ 
+-	bootsplash_do_render_pictures(info, splash_state.file);
++	bootsplash_do_render_pictures(info, splash_state.file, is_update);
+ 
+ 	bootsplash_do_render_flush(info);
+ 
++	bootsplash_do_step_animations(splash_state.file);
++
++	/* Schedule update for animated splash screens */
++	if (splash_state.file->frame_ms > 0)
++		schedule_delayed_work(&splash_state.dwork_animation,
++				      msecs_to_jiffies(
++				      splash_state.file->frame_ms));
++
+ out:
+ 	mutex_unlock(&splash_state.data_lock);
+ }
+@@ -169,8 +204,14 @@ void bootsplash_enable(void)
+ 
+ 	was_enabled = test_and_set_bit(0, &splash_state.enabled);
+ 
+-	if (!was_enabled)
++	if (!was_enabled) {
++		/* Force a full redraw when the splash is re-activated */
++		mutex_lock(&splash_state.data_lock);
++		splash_state.splash_fb = NULL;
++		mutex_unlock(&splash_state.data_lock);
++
+ 		schedule_work(&splash_state.work_redraw_vc);
++	}
+ }
+ 
+ 
+@@ -227,6 +268,14 @@ 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_state.data_lock);
++	splash_state.splash_fb = NULL;
++	mutex_unlock(&splash_state.data_lock);
++
+ 	if (bootsplash_would_render_now())
+ 		schedule_work(&splash_state.work_redraw_vc);
+ 
+@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)
+ 
+ static int splash_suspend(struct device *device)
+ {
++	cancel_delayed_work_sync(&splash_state.dwork_animation);
+ 	cancel_work_sync(&splash_state.work_redraw_vc);
+ 
+ 	return 0;
+@@ -296,6 +346,8 @@ void bootsplash_init(void)
+ 	set_bit(0, &splash_state.enabled);
+ 
+ 	INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
++	INIT_DELAYED_WORK(&splash_state.dwork_animation,
++			  splash_callback_animation);
+ 
+ 
+ 	if (!splash_state.bootfile || !strlen(splash_state.bootfile))
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index 0acb383aa4e3..b3a74835d90f 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -37,6 +37,8 @@ struct splash_pic_priv {
+ 
+ 	struct splash_blob_priv *blobs;
+ 	u16 blobs_loaded;
++
++	u16 anim_nextframe;
+ };
+ 
+ 
+@@ -45,6 +47,12 @@ struct splash_file_priv {
+ 	const struct splash_file_header *header;
+ 
+ 	struct splash_pic_priv *pics;
++
++	/*
++	 * A local copy of the frame delay in the header.
++	 * We modify it to keep the code simple.
++	 */
++	u16 frame_ms;
+ };
+ 
+ 
+@@ -71,6 +79,7 @@ struct splash_priv {
+ 	struct platform_device *splash_device;
+ 
+ 	struct work_struct work_redraw_vc;
++	struct delayed_work dwork_animation;
+ 
+ 	/* Splash data structures including lock for everything below */
+ 	struct mutex data_lock;
+@@ -88,8 +97,10 @@ struct splash_priv {
+ void bootsplash_do_render_background(struct fb_info *info,
+ 				     const struct splash_file_priv *fp);
+ void bootsplash_do_render_pictures(struct fb_info *info,
+-				   const struct splash_file_priv *fp);
++				   const struct splash_file_priv *fp,
++				   bool is_update);
+ void bootsplash_do_render_flush(struct fb_info *info);
++void bootsplash_do_step_animations(struct splash_file_priv *fp);
+ 
+ 
+ void bootsplash_free_file(struct splash_file_priv *fp);
+diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
+index fd807571ab7d..1f661b2d4cc9 100644
+--- a/drivers/video/fbdev/core/bootsplash_load.c
++++ b/drivers/video/fbdev/core/bootsplash_load.c
+@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ {
+ 	const struct firmware *fw;
+ 	struct splash_file_priv *fp;
++	bool have_anim = false;
+ 	unsigned int i;
+ 	const u8 *walker;
+ 
+@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ 			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));
+@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ 	/* Walk over pictures and ensure all blob slots are filled */
+ 	for (i = 0; i < fp->header->num_pics; i++) {
+ 		struct splash_pic_priv *pp = &fp->pics[i];
++		const 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",
+@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ 
+ 			goto err;
+ 		}
++
++		if (ph->anim_type
++		    && ph->num_blobs > 1
++		    && ph->anim_loop < pp->blobs_loaded)
++			have_anim = true;
+ 	}
+ 
++	if (!have_anim)
++		/* Disable animation timer if there is nothing to animate */
++		fp->frame_ms = 0;
++	else
++		/* Enforce minimum delay between frames */
++		fp->frame_ms = max((u16)20, fp->header->frame_ms);
++
+ 	pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
+ 		fw->size,
+ 		fp->header->num_pics,
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 07e3a4eab811..76033606ca8a 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,
+ 
+ 
+ void bootsplash_do_render_pictures(struct fb_info *info,
+-				   const struct splash_file_priv *fp)
++				   const struct splash_file_priv *fp,
++				   bool is_update)
+ {
+ 	unsigned int i;
+ 
+@@ -161,7 +162,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;
+@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)
+ 		info->fbops->fb_copyarea(info, &area);
+ 	}
+ }
++
++
++void bootsplash_do_step_animations(struct splash_file_priv *fp)
++{
++	unsigned int i;
++
++	/* Step every animation once */
++	for (i = 0; i < fp->header->num_pics; i++) {
++		struct splash_pic_priv *pp = &fp->pics[i];
++
++		if (pp->blobs_loaded < 2
++		    || pp->pic_header->anim_loop > pp->blobs_loaded)
++			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;
++		}
++	}
++}
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+index 71cedcc68933..b3af0a3c6487 100644
+--- a/include/uapi/linux/bootsplash_file.h
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -77,7 +77,17 @@ struct splash_file_header {
+ 	uint16_t num_blobs;
+ 	uint8_t num_pics;
+ 
+-	uint8_t padding[103];
++	uint8_t unused_1;
++
++	/*
++	 * 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.
++	 */
++	uint16_t frame_ms;
++
++	uint8_t padding[100];
+ } __attribute__((__packed__));
+ 
+ 
+@@ -116,7 +126,23 @@ struct splash_pic_header {
+ 	 */
+ 	uint16_t position_offset;
+ 
+-	uint8_t padding[24];
++	/*
++	 * Animation type.
++	 *  0 - off
++	 *  1 - forward loop
++	 */
++	uint8_t 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)
++	 */
++	uint8_t anim_loop;
++
++	uint8_t padding[22];
+ } __attribute__((__packed__));
+ 
+ 
+@@ -158,4 +184,9 @@ enum splash_position {
+ 	SPLASH_POS_FLAG_CORNER = 0x10,
+ };
+ 
++enum splash_anim_type {
++	SPLASH_ANIM_NONE = 0,
++	SPLASH_ANIM_LOOP_FORWARD = 1,
++};
++
+ #endif
diff --git a/0506-bootsplash.patch b/0506-bootsplash.patch
new file mode 100644
index 0000000..d6c6db6
--- /dev/null
+++ b/0506-bootsplash.patch
@@ -0,0 +1,82 @@
+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
+@@ -105,6 +105,7 @@
+ #include <linux/ctype.h>
+ #include <linux/bsearch.h>
+ #include <linux/gcd.h>
++#include <linux/bootsplash.h>
+ 
+ #define MAX_NR_CON_DRIVER 16
+ 
+@@ -4235,6 +4236,7 @@ void do_unblank_screen(int leaving_gfx)
+ 	}
+ 
+ 	console_blanked = 0;
++	bootsplash_mark_dirty();
+ 	if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
+ 		/* 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 c8642142cfea..13fcaabbc2ca 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -165,6 +165,13 @@ bool bootsplash_would_render_now(void)
+ 		&& bootsplash_is_enabled();
+ }
+ 
++void bootsplash_mark_dirty(void)
++{
++	mutex_lock(&splash_state.data_lock);
++	splash_state.splash_fb = NULL;
++	mutex_unlock(&splash_state.data_lock);
++}
++
+ bool bootsplash_is_enabled(void)
+ {
+ 	bool was_enabled;
+@@ -206,9 +213,7 @@ void bootsplash_enable(void)
+ 
+ 	if (!was_enabled) {
+ 		/* Force a full redraw when the splash is re-activated */
+-		mutex_lock(&splash_state.data_lock);
+-		splash_state.splash_fb = NULL;
+-		mutex_unlock(&splash_state.data_lock);
++		bootsplash_mark_dirty();
+ 
+ 		schedule_work(&splash_state.work_redraw_vc);
+ 	}
+@@ -272,9 +277,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_state.data_lock);
+-	splash_state.splash_fb = NULL;
+-	mutex_unlock(&splash_state.data_lock);
++	bootsplash_mark_dirty();
+ 
+ 	if (bootsplash_would_render_now())
+ 		schedule_work(&splash_state.work_redraw_vc);
+diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
+index c6dd0b43180d..4075098aaadd 100644
+--- a/include/linux/bootsplash.h
++++ b/include/linux/bootsplash.h
+@@ -19,6 +19,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);
+@@ -31,6 +33,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()
diff --git a/0507-bootsplash.patch b/0507-bootsplash.patch
new file mode 100644
index 0000000..e8cd479
--- /dev/null
+++ b/0507-bootsplash.patch
@@ -0,0 +1,42 @@
+diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
+index f4166263bb3a..a248429194bb 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,28 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+ 	}
+ #endif
+ 
++	/* Trap keys when bootsplash is shown */
++	if (bootsplash_would_render_now()) {
++		/* Deactivate bootsplash on ESC or Alt+Fxx VT switch */
++		if (keycode >= KEY_F1 && keycode <= KEY_F12) {
++			bootsplash_disable();
++
++			/*
++			 * No return here since we want to actually
++			 * perform the VT switch.
++			 */
++		} else {
++			if (keycode == KEY_ESC)
++				bootsplash_disable();
++
++			/*
++			 * Just drop any other keys.
++			 * Their effect would be hidden by the splash.
++			 */
++			return;
++		}
++	}
++
+ 	if (kbd->kbdmode == VC_MEDIUMRAW) {
+ 		/*
+ 		 * This is extended medium raw mode, with keys above 127
diff --git a/0508-bootsplash.patch b/0508-bootsplash.patch
new file mode 100644
index 0000000..09bd4c3
--- /dev/null
+++ b/0508-bootsplash.patch
@@ -0,0 +1,19 @@
+diff -up linux-5.10/drivers/tty/sysrq.c.66~ linux-5.10/drivers/tty/sysrq.c
+--- linux-5.10/drivers/tty/sysrq.c.66~	2020-12-13 23:41:30.000000000 +0100
++++ linux-5.10/drivers/tty/sysrq.c	2021-01-19 23:09:45.408605180 +0100
+@@ -51,6 +51,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>
+@@ -119,6 +120,7 @@ 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 const struct sysrq_key_op sysrq_SAK_op = {
+ 	.handler	= sysrq_handle_SAK,
diff --git a/0509-bootsplash.patch b/0509-bootsplash.patch
new file mode 100644
index 0000000..add68e7
--- /dev/null
+++ b/0509-bootsplash.patch
@@ -0,0 +1,21 @@
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 9a39a6fcfe98..8a9c67e1c5d8 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -1343,6 +1343,16 @@ 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)
diff --git a/0510-bootsplash.patch b/0510-bootsplash.patch
new file mode 100644
index 0000000..c74b4da
--- /dev/null
+++ b/0510-bootsplash.patch
@@ -0,0 +1,308 @@
+diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
+new file mode 100644
+index 000000000000..742c7b035ded
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
+@@ -0,0 +1,11 @@
++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.
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+new file mode 100644
+index 000000000000..611f0c558925
+--- /dev/null
++++ b/Documentation/bootsplash.rst
+@@ -0,0 +1,285 @@
++====================
++The Linux bootsplash
++====================
++
++:Date: November, 2017
++:Author: Max Staudt <mstaudt@suse.de>
++
++
++The Linux bootsplash is a graphical replacement for the '``quiet``' boot
++option, typically showing a logo and a spinner animation as the system starts.
++
++Currently, it is a part of the Framebuffer Console support, and can be found
++as ``CONFIG_BOOTSPLASH`` in the kernel configuration. This means that as long
++as it is enabled, it hijacks fbcon's output and draws a splash screen instead.
++
++Purely compiling in the bootsplash will not render it functional - to actually
++render a splash, you will also need a splash theme file. See the example
++utility and script in ``tools/bootsplash`` for a live demo.
++
++
++
++Motivation
++==========
++
++- The '``quiet``' boot option only suppresses most messages during boot, but
++  errors are still shown.
++
++- A user space implementation can only show a logo once user space has been
++  initialized far enough to allow this. A kernel splash can display a splash
++  immediately as soon as fbcon can be displayed.
++
++- Implementing a splash screen in user space (e.g. Plymouth) is problematic
++  due to resource conflicts.
++
++  For example, if Plymouth is keeping ``/dev/fb0`` (provided via vesafb/efifb)
++  open, then most DRM drivers can't replace it because the address space is
++  still busy - thus leading to a VRAM reservation error.
++
++  See: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
++
++
++
++Command line arguments
++======================
++
++``bootsplash.bootfile``
++  Which file in the initramfs to load.
++
++  The splash theme is loaded via request_firmware(), thus to load
++  ``/lib/firmware/bootsplash/mytheme`` pass the command line:
++
++  ``bootsplash.bootfile=bootsplash/mytheme``
++
++  Note: The splash file *has to be* in the initramfs, as it needs to be
++  available when the splash is initialized early on.
++
++  Default: none, i.e. a non-functional splash, falling back to showing text.
++
++
++
++sysfs run-time configuration
++============================
++
++``/sys/devices/platform/bootsplash.0/enabled``
++  Enable/disable the bootsplash.
++  The system boots with this set to 1, but will not show a splash unless
++  a splash theme file is also loaded.
++
++
++
++Kconfig
++=======
++
++``BOOTSPLASH``
++  Whether to compile in bootsplash support
++  (depends on fbcon compiled in, i.e. ``FRAMEBUFFER_CONSOLE=y``)
++
++
++
++Bootsplash file format
++======================
++
++A file specified in the kernel configuration as ``CONFIG_BOOTSPLASH_FILE``
++or specified on the command line as ``bootsplash.bootfile`` will be loaded
++and displayed as soon as fbcon is initialized.
++
++
++Main blocks
++-----------
++
++There are 3 main blocks in each file:
++
++  - one File header
++  -   n Picture headers
++  -   m (Blob header + payload) blocks
++
++
++Structures
++----------
++
++The on-disk structures are defined in
++``drivers/video/fbdev/core/bootsplash_file.h`` and represent these blocks:
++
++  - ``struct splash_file_header``
++
++    Represents the file header, with splash-wide information including:
++
++      - The magic string "``Linux bootsplash``" on big-endian platforms
++        (the reverse on little endian)
++      - The file format version (for incompatible updates, hopefully never)
++      - The background color
++      - Number of picture and blob blocks
++      - Animation speed (we only allow one delay for all animations)
++
++    The file header is followed by the first picture header.
++
++
++  - ``struct splash_picture_header``
++
++    Represents an object (picture) drawn on screen, including its immutable
++    properties:
++      - Width, height
++      - Positioning relative to screen corners or in the center
++      - Animation, if any
++      - Animation type
++      - Number of blobs
++
++    The picture header is followed by another picture header, up until n
++    picture headers (as defined in the file header) have been read. Then,
++    the (blob header, payload) pairs follow.
++
++
++  - ``struct splash_blob_header``
++    (followed by payload)
++
++    Represents one raw data stream. So far, only picture data is defined.
++
++    The blob header is followed by a payload, then padding to n*16 bytes,
++    then (if further blobs are defined in the file header) a further blob
++    header.
++
++
++Alignment
++---------
++
++The bootsplash file is designed to be loaded into memory as-is.
++
++All structures are a multiple of 16 bytes long, all elements therein are
++aligned to multiples of their length, and the payloads are always padded
++up to multiples of 16 bytes. This is to allow aligned accesses in all
++cases while still simply mapping the structures over an in-memory copy of
++the bootsplash file.
++
++
++Further information
++-------------------
++
++Please see ``drivers/video/fbdev/core/bootsplash_file.h`` for further
++details and possible values in the file.
++
++
++
++Hooks - how the bootsplash is integrated
++========================================
++
++``drivers/video/fbdev/core/fbcon.c``
++  ``fbcon_init()`` calls ``bootsplash_init()``, which loads the default
++  bootsplash file or the one specified on the kernel command line.
++
++  ``fbcon_switch()`` draws the bootsplash when it's active, and is also
++  one of the callers of ``set_blitting_type()``.
++
++  ``set_blitting_type()`` calls ``fbcon_set_dummyops()`` when the
++  bootsplash is active, overriding the text rendering functions.
++
++  ``fbcon_cursor()`` will call ``bootsplash_disable()`` when an oops is
++  being printed in order to make a kernel panic visible.
++
++``drivers/video/fbdev/core/dummyblit.c``
++  This contains the dummy text rendering functions used to suppress text
++  output while the bootsplash is shown.
++
++``drivers/tty/vt/keyboard.c``
++  ``kbd_keycode()`` can call ``bootsplash_disable()`` when the user
++  presses ESC or F1-F12 (changing VT). This is to provide a built-in way
++  of disabling the splash manually at any time.
++
++
++
++FAQ: Frequently Asked Questions
++===============================
++
++I want to see the log! How do I show the log?
++---------------------------------------------
++
++Press ESC while the splash is shown, or remove the ``bootsplash.bootfile``
++parameter from the kernel cmdline. Without that parameter, the bootsplash
++will boot disabled.
++
++
++Why use FB instead of modern DRM/KMS?
++-------------------------------------
++
++This is a semantic problem:
++ - What memory to draw the splash to?
++ - And what mode will the screen be set to?
++
++Using the fbdev emulation solves these issues.
++
++Let's start from a bare KMS system, without fbcon, and without fbdev
++emulation. In this case, as long as userspace doesn't open the KMS
++device, the state of the screen is undefined. No framebuffer is
++allocated in video RAM, and no particular mode is set.
++
++In this case, we'd have to allocate a framebuffer to show the splash,
++and set our mode ourselves. This either wastes a screenful of video RAM
++if the splash is to co-exist with the userspace program's own allocated
++framebuffer, or there is a flicker as we deactivate and delete the
++bootsplash's framebuffer and hand control over to userspace. Since we
++may set a different mode than userspace, we'd also have flicker due
++to mode switching.
++
++This logic is already contained in every KMS driver that performs fbdev
++emulation. So we might as well use that. And the correct API to do so is
++fbdev. Plus, we get compatibility with old, pure fbdev drivers for free.
++With the fbdev emulation, there is *always* a well-defined framebuffer
++to draw on. And the selection of mode has already been done by the
++graphics driver, so we don't need to reinvent that wheel, either.
++Finally, if userspace decides to use /dev/fbX, we don't have to worry
++about wasting video RAM, either.
++
++
++Why is the bootsplash integrated in fbcon?
++------------------------------------------
++
++Right now, the bootsplash is drawn from within fbcon, as this allows us
++to easily know *when* to draw - i.e. when we're safe from fbcon and
++userspace drawing all over our beautiful splash logo.
++
++Separating them is not easy - see the to-do list below.
++
++
++
++TO DO list for future development
++=================================
++
++Second enable/disable switch for the system
++-------------------------------------------
++
++It may be helpful to differentiate between the system and the user
++switching off the bootsplash. Thus, the system may make it disappear and
++reappear e.g. for a password prompt, yet once the user has pressed ESC,
++it could stay gone.
++
++
++Fix buggy DRM/KMS drivers
++-------------------------
++
++Currently, the splash code manually checks for fbdev emulation provided by
++the ast, cirrus, and mgag200 DRM/KMS drivers.
++These drivers use a manual mechanism similar to deferred I/O for their FB
++emulation, and thus need to be manually flushed onto the screen in the same
++way.
++
++This may be improved upon in several ways:
++
++1. Changing these drivers to expose the fbdev BO's memory directly, like
++   bochsdrmfb does.
++2. Creating a new fb_ops->fb_flush() API to allow the kernel to flush the
++   framebuffer once the bootsplash has been drawn into it.
++
++
++Separating from fbcon
++---------------------
++
++Separating these two components would yield independence from fbcon being
++compiled into the kernel, and thus lowering code size in embedded
++applications.
++
++To do this cleanly will involve a clean separation of users of an FB device
++within the kernel, i.e. fbcon, bootsplash, and userspace. Right now, the
++legacy fbcon code and VT code co-operate to switch between fbcon and
++userspace (by setting the VT into KD_GRAPHICS mode). Installing a muxer
++between these components ensues refactoring of old code and checking for
++correct locking.
diff --git a/0511-bootsplash.patch b/0511-bootsplash.patch
new file mode 100644
index 0000000..8e87eb4
--- /dev/null
+++ b/0511-bootsplash.patch
@@ -0,0 +1,129 @@
+diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
+index 742c7b035ded..f8f4b259220e 100644
+--- a/Documentation/ABI/testing/sysfs-platform-bootsplash
++++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
+@@ -9,3 +9,35 @@ Description:
+ 		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 current splash theme file
++		to be unloaded and the text console to be redrawn.
++
++What:		/sys/devices/platform/bootsplash.0/load_file
++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.
++
++		A firmware path written will cause a new theme file to be
++		loaded and the current bootsplash to be replaced.
++		The current enabled/disabled status is not touched.
++		If the splash is already active, it will be redrawn.
++
++		The path has to be a path in /lib/firmware since
++		request_firmware() is used to fetch the data.
++
++		When setting the splash from the shell, echo -n has to be
++		used as any trailing '\n' newline will be interpreted as
++		part of the path.
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+index 611f0c558925..b35aba5093e8 100644
+--- a/Documentation/bootsplash.rst
++++ b/Documentation/bootsplash.rst
+@@ -67,6 +67,14 @@ sysfs run-time configuration
+   a splash theme file is also loaded.
+ 
+ 
++``/sys/devices/platform/bootsplash.0/drop_splash``
++  Unload splash data and free memory.
++
++``/sys/devices/platform/bootsplash.0/load_file``
++  Load a splash file from ``/lib/firmware/``.
++  Note that trailing newlines will be interpreted as part of the file name.
++
++
+ 
+ Kconfig
+ =======
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 13fcaabbc2ca..16cb0493629d 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -251,11 +251,65 @@ 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)
++{
++	struct splash_file_priv *fp;
++
++	if (!buf || !count || !splash_state.file)
++		return count;
++
++	mutex_lock(&splash_state.data_lock);
++	fp = splash_state.file;
++	splash_state.file = NULL;
++	mutex_unlock(&splash_state.data_lock);
++
++	/* Redraw the text console */
++	schedule_work(&splash_state.work_redraw_vc);
++
++	bootsplash_free_file(fp);
++
++	return count;
++}
++
++static ssize_t splash_store_load_file(struct device *device,
++				      struct device_attribute *attr,
++				      const char *buf, size_t count)
++{
++	struct splash_file_priv *fp, *fp_old;
++
++	if (!count)
++		return 0;
++
++	fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
++				      buf);
++
++	if (!fp)
++		return -ENXIO;
++
++	mutex_lock(&splash_state.data_lock);
++	fp_old = splash_state.file;
++	splash_state.splash_fb = NULL;
++	splash_state.file = fp;
++	mutex_unlock(&splash_state.data_lock);
++
++	/* Update the splash or text console */
++	schedule_work(&splash_state.work_redraw_vc);
++
++	bootsplash_free_file(fp_old);
++	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 DEVICE_ATTR(load_file, 0200, NULL, splash_store_load_file);
+ 
+ 
+ static struct attribute *splash_dev_attrs[] = {
+ 	&dev_attr_enabled.attr,
++	&dev_attr_drop_splash.attr,
++	&dev_attr_load_file.attr,
+ 	NULL
+ };
+ 
diff --git a/0512-bootsplash.patch b/0512-bootsplash.patch
new file mode 100644
index 0000000..4e0c98f
--- /dev/null
+++ b/0512-bootsplash.patch
@@ -0,0 +1,499 @@
+diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
+new file mode 100644
+index 000000000000..091b99a17567
+--- /dev/null
++++ b/tools/bootsplash/.gitignore
+@@ -0,0 +1 @@
++bootsplash-packer
+diff --git a/tools/bootsplash/Makefile b/tools/bootsplash/Makefile
+new file mode 100644
+index 000000000000..0ad8e8a84942
+--- /dev/null
++++ b/tools/bootsplash/Makefile
+@@ -0,0 +1,9 @@
++CC := $(CROSS_COMPILE)gcc
++CFLAGS := -I../../usr/include
++
++PROGS := bootsplash-packer
++
++all: $(PROGS)
++
++clean:
++	rm -fr $(PROGS)
+diff --git a/tools/bootsplash/bootsplash-packer.c b/tools/bootsplash/bootsplash-packer.c
+new file mode 100644
+index 000000000000..ffb6a8b69885
+--- /dev/null
++++ b/tools/bootsplash/bootsplash-packer.c
+@@ -0,0 +1,471 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Splash file packer tool)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#include <endian.h>
++#include <getopt.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <linux/bootsplash_file.h>
++
++
++static void print_help(char *progname)
++{
++	printf("Usage: %s [OPTIONS] outfile\n", progname);
++	printf("\n"
++	       "Options, executed in order given:\n"
++	       "  -h, --help                   Print this help message\n"
++	       "\n"
++	       "  --bg_red <u8>                Background color (red part)\n"
++	       "  --bg_green <u8>              Background color (green part)\n"
++	       "  --bg_blue <u8>               Background color (blue part)\n"
++	       "  --bg_reserved <u8>           (do not use)\n"
++	       "  --frame_ms <u16>             Minimum milliseconds between animation steps\n"
++	       "\n"
++	       "  --picture                    Start describing the next picture\n"
++	       "  --pic_width <u16>            Picture width in pixels\n"
++	       "  --pic_height <u16>           Picture height in pixels\n"
++	       "  --pic_position <u8>             Coarse picture placement:\n"
++	       "                                  0x00 - Top left\n"
++	       "                                  0x01 - Top\n"
++	       "                                  0x02 - Top right\n"
++	       "                                  0x03 - Right\n"
++	       "                                  0x04 - Bottom right\n"
++	       "                                  0x05 - Bottom\n"
++	       "                                  0x06 - Bottom left\n"
++	       "                                  0x07 - Left\n"
++	       "\n"
++	       "                                Flags:\n"
++	       "                                 0x10 - Calculate offset from corner towards center,\n"
++	       "                                         rather than from center towards corner\n"
++	       "  --pic_position_offset <u16>  Distance from base position in pixels\n"
++	       "  --pic_anim_type <u8>         Animation type:\n"
++	       "                                 0 - None\n"
++	       "                                 1 - Forward loop\n"
++	       "  --pic_anim_loop <u8>         Loop point for animation\n"
++	       "\n"
++	       "  --blob <filename>            Include next data stream\n"
++	       "  --blob_type <u16>            Type of data\n"
++	       "  --blob_picture_id <u8>       Picture to associate this blob with, starting at 0\n"
++	       "                                 (default: number of last --picture)\n"
++	       "\n");
++	printf("This tool will write %s files.\n\n",
++#if __BYTE_ORDER == __BIG_ENDIAN
++	       "Big Endian (BE)");
++#elif __BYTE_ORDER == __LITTLE_ENDIAN
++	       "Little Endian (LE)");
++#else
++#error
++#endif
++}
++
++
++struct blob_entry {
++	struct blob_entry *next;
++
++	char *fn;
++
++	struct splash_blob_header header;
++};
++
++
++static void dump_file_header(struct splash_file_header *h)
++{
++	printf(" --- File header ---\n");
++	printf("\n");
++	printf("  version:     %5u\n", h->version);
++	printf("\n");
++	printf("  bg_red:      %5u\n", h->bg_red);
++	printf("  bg_green:    %5u\n", h->bg_green);
++	printf("  bg_blue:     %5u\n", h->bg_blue);
++	printf("  bg_reserved: %5u\n", h->bg_reserved);
++	printf("\n");
++	printf("  num_blobs:   %5u\n", h->num_blobs);
++	printf("  num_pics:    %5u\n", h->num_pics);
++	printf("\n");
++	printf("  frame_ms:    %5u\n", h->frame_ms);
++	printf("\n");
++}
++
++static void dump_pic_header(struct splash_pic_header *ph)
++{
++	printf(" --- Picture header ---\n");
++	printf("\n");
++	printf("  width:           %5u\n", ph->width);
++	printf("  height:          %5u\n", ph->height);
++	printf("\n");
++	printf("  num_blobs:       %5u\n", ph->num_blobs);
++	printf("\n");
++	printf("  position:        %0x3x\n", ph->position);
++	printf("  position_offset: %5u\n", ph->position_offset);
++	printf("\n");
++	printf("  anim_type:       %5u\n", ph->anim_type);
++	printf("  anim_loop:       %5u\n", ph->anim_loop);
++	printf("\n");
++}
++
++static void dump_blob(struct blob_entry *b)
++{
++	printf(" --- Blob header ---\n");
++	printf("\n");
++	printf("  length:     %7u\n", b->header.length);
++	printf("  type:       %7u\n", b->header.type);
++	printf("\n");
++	printf("  picture_id: %7u\n", b->header.picture_id);
++	printf("\n");
++}
++
++
++#define OPT_MAX(var, max) \
++	do { \
++		if ((var) > max) { \
++			fprintf(stderr, "--%s: Invalid value\n", \
++			long_options[option_index].name); \
++			break; \
++		} \
++	} while (0)
++
++static struct option long_options[] = {
++	{"help", 0, 0, 'h'},
++	{"bg_red", 1, 0, 10001},
++	{"bg_green", 1, 0, 10002},
++	{"bg_blue", 1, 0, 10003},
++	{"bg_reserved", 1, 0, 10004},
++	{"frame_ms", 1, 0, 10005},
++	{"picture", 0, 0, 20000},
++	{"pic_width", 1, 0, 20001},
++	{"pic_height", 1, 0, 20002},
++	{"pic_position", 1, 0, 20003},
++	{"pic_position_offset", 1, 0, 20004},
++	{"pic_anim_type", 1, 0, 20005},
++	{"pic_anim_loop", 1, 0, 20006},
++	{"blob", 1, 0, 30000},
++	{"blob_type", 1, 0, 30001},
++	{"blob_picture_id", 1, 0, 30002},
++	{NULL, 0, NULL, 0}
++};
++
++
++int main(int argc, char **argv)
++{
++	FILE *of;
++	char *ofn;
++	int c;
++	int option_index = 0;
++
++	unsigned long ul;
++	struct splash_file_header fh = {};
++	struct splash_pic_header ph[255];
++	struct blob_entry *blob_first = NULL;
++	struct blob_entry *blob_last = NULL;
++	struct blob_entry *blob_cur = NULL;
++
++	if (argc < 2) {
++		print_help(argv[0]);
++		return EXIT_FAILURE;
++	}
++
++
++	/* Parse and and execute user commands */
++	while ((c = getopt_long(argc, argv, "h",
++			  long_options, &option_index)) != -1) {
++		switch (c) {
++		case 10001:	/* bg_red */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			fh.bg_red = ul;
++			break;
++		case 10002:	/* bg_green */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			fh.bg_green = ul;
++			break;
++		case 10003:	/* bg_blue */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			fh.bg_blue = ul;
++			break;
++		case 10004:	/* bg_reserved */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			fh.bg_reserved = ul;
++			break;
++		case 10005:	/* frame_ms */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 65535);
++			fh.frame_ms = ul;
++			break;
++
++
++		case 20000:	/* picture */
++			if (fh.num_pics >= 255) {
++				fprintf(stderr, "--%s: Picture array full\n",
++					long_options[option_index].name);
++				break;
++			}
++
++			fh.num_pics++;
++			break;
++
++		case 20001:	/* pic_width */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 65535);
++			ph[fh.num_pics - 1].width = ul;
++			break;
++
++		case 20002:	/* pic_height */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 65535);
++			ph[fh.num_pics - 1].height = ul;
++			break;
++
++		case 20003:	/* pic_position */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			ph[fh.num_pics - 1].position = ul;
++			break;
++
++		case 20004:	/* pic_position_offset */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			ph[fh.num_pics - 1].position_offset = ul;
++			break;
++
++		case 20005:	/* pic_anim_type */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			ph[fh.num_pics - 1].anim_type = ul;
++			break;
++
++		case 20006:	/* pic_anim_loop */
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			ph[fh.num_pics - 1].anim_loop = ul;
++			break;
++
++
++		case 30000:	/* blob */
++			if (fh.num_blobs >= 65535) {
++				fprintf(stderr, "--%s: Blob array full\n",
++					long_options[option_index].name);
++				break;
++			}
++
++			blob_cur = calloc(1, sizeof(struct blob_entry));
++			if (!blob_cur) {
++				fprintf(stderr, "--%s: Out of memory\n",
++					long_options[option_index].name);
++				break;
++			}
++
++			blob_cur->fn = optarg;
++			if (fh.num_pics)
++				blob_cur->header.picture_id = fh.num_pics - 1;
++
++			if (!blob_first)
++				blob_first = blob_cur;
++			if (blob_last)
++				blob_last->next = blob_cur;
++			blob_last = blob_cur;
++			fh.num_blobs++;
++			break;
++
++		case 30001:	/* blob_type */
++			if (!blob_cur) {
++				fprintf(stderr, "--%s: No blob selected\n",
++					long_options[option_index].name);
++				break;
++			}
++
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			blob_cur->header.type = ul;
++			break;
++
++		case 30002:	/* blob_picture_id */
++			if (!blob_cur) {
++				fprintf(stderr, "--%s: No blob selected\n",
++					long_options[option_index].name);
++				break;
++			}
++
++			ul = strtoul(optarg, NULL, 0);
++			OPT_MAX(ul, 255);
++			blob_cur->header.picture_id = ul;
++			break;
++
++
++
++		case 'h':
++		case '?':
++		default:
++			print_help(argv[0]);
++			goto EXIT;
++		} /* switch (c) */
++	} /* while ((c = getopt_long(...)) != -1) */
++
++	/* Consume and drop lone arguments */
++	while (optind < argc) {
++		ofn = argv[optind];
++		optind++;
++	}
++
++
++	/* Read file lengths */
++	for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
++		FILE *f;
++		long pos;
++		int i;
++
++		if (!blob_cur->fn)
++			continue;
++
++		f = fopen(blob_cur->fn, "rb");
++		if (!f)
++			goto ERR_FILE_LEN;
++
++		if (fseek(f, 0, SEEK_END))
++			goto ERR_FILE_LEN;
++
++		pos = ftell(f);
++		if (pos < 0 || pos > (1 << 30))
++			goto ERR_FILE_LEN;
++
++		blob_cur->header.length = pos;
++
++		fclose(f);
++		continue;
++
++ERR_FILE_LEN:
++		fprintf(stderr, "Error getting file length (or too long): %s\n",
++			blob_cur->fn);
++		if (f)
++			fclose(f);
++		continue;
++	}
++
++
++	/* Set magic headers */
++#if __BYTE_ORDER == __BIG_ENDIAN
++	memcpy(&fh.id[0], BOOTSPLASH_MAGIC_BE, 16);
++#elif __BYTE_ORDER == __LITTLE_ENDIAN
++	memcpy(&fh.id[0], BOOTSPLASH_MAGIC_LE, 16);
++#else
++#error
++#endif
++	fh.version = BOOTSPLASH_VERSION;
++
++	/* Set blob counts */
++	for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
++		if (blob_cur->header.picture_id < fh.num_pics)
++			ph[blob_cur->header.picture_id].num_blobs++;
++	}
++
++
++	/* Dump structs */
++	dump_file_header(&fh);
++
++	for (ul = 0; ul < fh.num_pics; ul++)
++		dump_pic_header(&ph[ul]);
++
++	for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next)
++		dump_blob(blob_cur);
++
++
++	/* Write to file */
++	printf("Writing splash to file: %s\n", ofn);
++	of = fopen(ofn, "wb");
++	if (!of)
++		goto ERR_WRITING;
++
++	if (fwrite(&fh, sizeof(struct splash_file_header), 1, of) != 1)
++		goto ERR_WRITING;
++
++	for (ul = 0; ul < fh.num_pics; ul++) {
++		if (fwrite(&ph[ul], sizeof(struct splash_pic_header), 1, of)
++		    != 1)
++			goto ERR_WRITING;
++	}
++
++	blob_cur = blob_first;
++	while (blob_cur) {
++		struct blob_entry *blob_old = blob_cur;
++		FILE *f;
++		char *buf[256];
++		uint32_t left;
++
++		if (fwrite(&blob_cur->header,
++			   sizeof(struct splash_blob_header), 1, of) != 1)
++			goto ERR_WRITING;
++
++		if (!blob_cur->header.length || !blob_cur->fn)
++			continue;
++
++		f = fopen(blob_cur->fn, "rb");
++		if (!f)
++			goto ERR_FILE_COPY;
++
++		left = blob_cur->header.length;
++		while (left >= sizeof(buf)) {
++			if (fread(buf, sizeof(buf), 1, f) != 1)
++				goto ERR_FILE_COPY;
++			if (fwrite(buf, sizeof(buf), 1, of) != 1)
++				goto ERR_FILE_COPY;
++			left -= sizeof(buf);
++		}
++		if (left) {
++			if (fread(buf, left, 1, f) != 1)
++				goto ERR_FILE_COPY;
++			if (fwrite(buf, left, 1, of) != 1)
++				goto ERR_FILE_COPY;
++		}
++
++		/* Pad data stream to 16 bytes */
++		if (left % 16) {
++			if (fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
++					16 - (left % 16), 1, of) != 1)
++				goto ERR_FILE_COPY;
++		}
++
++		fclose(f);
++		blob_cur = blob_cur->next;
++		free(blob_old);
++		continue;
++
++ERR_FILE_COPY:
++		if (f)
++			fclose(f);
++		goto ERR_WRITING;
++	}
++
++	fclose(of);
++
++EXIT:
++	return EXIT_SUCCESS;
++
++
++ERR_WRITING:
++	fprintf(stderr, "Error writing splash.\n");
++	fprintf(stderr, "The output file is probably corrupt.\n");
++	if (of)
++		fclose(of);
++
++	while (blob_cur) {
++		struct blob_entry *blob_old = blob_cur;
++
++		blob_cur = blob_cur->next;
++		free(blob_old);
++	}
++
++	return EXIT_FAILURE;
++}
diff --git a/0513-bootsplash.gitpatch b/0513-bootsplash.gitpatch
new file mode 100644
index 0000000..124ad07
--- /dev/null
+++ b/0513-bootsplash.gitpatch
@@ -0,0 +1,162 @@
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+index b35aba5093e8..d4f132eca615 100644
+--- a/Documentation/bootsplash.rst
++++ b/Documentation/bootsplash.rst
+@@ -195,6 +195,16 @@ Hooks - how the bootsplash is integrated
+ 
+ 
+ 
++Crating a bootsplash theme file
++===============================
++
++A simple tool for theme file creation is included in ``tools/bootsplash``.
++
++There is also an example shell script, as an example on how to use the tool
++and in order to generate a reference bootsplash file.
++
++
++
+ FAQ: Frequently Asked Questions
+ ===============================
+ 
+diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
+index 091b99a17567..5dfced41ba82 100644
+--- a/tools/bootsplash/.gitignore
++++ b/tools/bootsplash/.gitignore
+@@ -1 +1,4 @@
+ bootsplash-packer
++bootsplash
++logo.rgb
++throbber*.rgb
+diff --git a/tools/bootsplash/ajax-loader.gif b/tools/bootsplash/ajax-loader.gif
+new file mode 100644
+index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29
+GIT binary patch
+literal 3208
+zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC;
+z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc<bJ}b<Y2s
+zU)AOL`#QVCGXW;>9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg
+zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>*
+z2CROCDAbu#D`)S|J_<lj7Yz9)#_Og>o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5
+zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF
+zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT<ZMc0Y;&y4jY1%TT3z!|H=R-GXDHPiKcVWh
+zY+!etO=DI2rIs8{iFWtPv(Lu|O3u|$F3Sbq;+xF{gTX$#T%m?MUUZy&ug3$=zXgXj
+zrxrf}reg*D3HB~8JyLgl$UCyV?EQ`@OKjW@tGrvh6ZqPD#+m=rK0T{FT01>*EZWzJ
+zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#<L1VKWYjwV^JDyeS;Y$p1xw*
+z#3VzfAV>P|%fkvg<hUP3U1Q=Hdgg~ik+2zyAc79kpuA<f*-~l+ZBH3*S2jBrEOF0w
+zrxe9#Vx$SxnL0JE4WeeXY1)ppOIy3@Vvexu&oeIa&QvoD`jBE#Gd7rT{j&OMLz1Wu
+zOEj;)PR^=mxjCG0NOUJb&U;ui6*-`3&wmcQ>Uj~HfIp3CuXqCtYGtJ#me+n+-LmP(
+z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{
+zpt8rzY$aw?W?=Ustv{jo?Ow@<k6~~d?F>ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^
+zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ
+z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7
+z_REZy&hMT^ySJB3W7l<L=l9ZMvC<Gz>$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^
+zTEe99ig2$5_qFr!$;<oK+H}=wcaT3=%Nm!;Kw7MHnU5paWS{tI1+DOU?!7xefZ57L
+ze_iPrUrRQct0FSCtTFLtg*<#jo}Z3{E?T{skj>7A6CJ}PJmRhli>w?LC}Y`#HLGy6
+zMU4<C6_PR!wGq`HQyoWJb;nj8>EhL~dKCN5Ut;U2jd*83ShB<kA1Y@1U)Ar;N|HhS
+znIkwkT(&i5XhkI;xwmC%DvPhGNIi?aY<|8rajSt<ap(2E-#qSPQxAp@jIY@-@>Niu
+zcJB0l9>1Modc?-oM<<M{t-|U0{*W+=Ct2ZY_02y-De{7vW<f^HJQhd1l&4)Gw2oOS
+zm46KASlsKI@J$sA#$$|7D5QMbewIaFv4fXyNbL5Ac~kS&g^#5XHaYBvNxbF3Y2L*6
+ztrn?JmgOFAo1lh99BEb^pp>R<Z&2wFwWd*z2wF6&nmW9}nyMfWMO`hc&zkr2AeBP3
+zj75NZQ8-VthLviI^j@e=FN6wxR@1uCRv<b;Y<3t(dr<e}N%b}FQtKxHi9xU2C!#0Z
+zO2<#(;s&964KtWfkQVi``vIFT7kbT~d;ITb0T9+U1AwIgET*ciil)~4gl;xgoy5M!
+z-UJHerGNh_`lO!vA)%ly=~<}ykhlnQnoP$oqido+`qK(cOpmt^pbhf`n-FQaIK5ix
+zq@=#Sl2Y&s<pe8B!1!YA78W7dA?2Xu9v7QHc?}NN)sx(o6iZ#|kHX64nijZG(yB1J
+zfMQm;1rb5O!-+1Pov;csFu7z>4?<d6>}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8
+zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY
+z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RX<yi^Bg0BS3UHmG;U4d
+z`2QlHs<l7ezUo)s<V^9ZccYv>vDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5|
+zR?GRdU}d6+Q`+JRW)|=v7$)X<at#L3(d9WVd8CstDNPh>Nkn3yE`!nAiSCvOB1jKT
+zG<1aK3s<0b0m==egTD#8i(<nFTpHvxfx|aIng5yR81z6E<naz8-Ow^p@sCs8mz=%h
+zO$v$X0NS?ofjnp~62AE}^z%gY8Nsqj=NwUqyj+o6s$@kK@d+U4Vp-^_G32vzv@8nI
+z01{`FL$DXQL%WB*9R<xn7$ya31flsbiVh+-0m=YeB_ocaW;YRxI51d(jP?N!ane91
+z9~^yzJ;S;OWRKC8PrrXYkZCaruNYE>Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg
+z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S
+zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^<m)Ax^m58MY|zev&92(G7#vQU
+zn~8r)5oUrwM9`}05|I<Nx*n}jlvg&C9_310Dd4OT2txd91Z*_U8bRtrNaq+nGd{E#
+zVGckZFpr^;mv}%%T{jHtz<a=^%;mPXVY7SR`@6_Uw@(0*>yx>}+a!ECd>#MMwddow
+z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k
+zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b
+zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq
+zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{<mZ_TMxh0{w%6lzzG*pm+Dj4XaZ5
+zoJwkk5)~fyUmzYbwMERR3j)XePHj^2P!5GK`~^RXuEz>rwsgqtIU3<910$CJi)s??
+z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt
+zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W
+z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M
+Bt<?Yk
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/bootsplash/bootsplash-tux.sh b/tools/bootsplash/bootsplash-tux.sh
+new file mode 100755
+index 000000000000..1078f87644b9
+--- /dev/null
++++ b/tools/bootsplash/bootsplash-tux.sh
+@@ -0,0 +1,66 @@
++#!/bin/bash
++#
++# A simple script to show how to create a bootsplash.
++# Do with it whatever you wish.
++#
++# This needs ImageMagick for the 'convert' and 'identify' tools.
++#
++
++LOGO=../../Documentation/logo.gif
++LOGO_WIDTH=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 1)
++LOGO_HEIGHT=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 2)
++
++THROBBER=ajax-loader.gif
++THROBBER_WIDTH=$(identify $THROBBER | head -1 | cut -d " " -f 3 | \
++						cut -d x -f 1)
++THROBBER_HEIGHT=$(identify $THROBBER | head -1 | cut -d " " -f 3 | \
++						 cut -d x -f 2)
++
++convert -alpha remove \
++	-background "#ff3a40" \
++	$LOGO \
++	logo.rgb
++
++convert -alpha remove \
++	-background "#ff3a40" \
++	$THROBBER \
++	throbber%02d.rgb
++
++
++make clean
++make bootsplash-packer
++
++
++# Let's put Tux in the center of an orange background.
++./bootsplash-packer \
++	--bg_red 0xff \
++	--bg_green 0x3a \
++	--bg_blue 0x40 \
++	--frame_ms 48 \
++	--picture \
++	--pic_width $LOGO_WIDTH \
++	--pic_height $LOGO_HEIGHT \
++	--pic_position 0 \
++	--blob logo.rgb \
++	--picture \
++	--pic_width $THROBBER_WIDTH \
++	--pic_height $THROBBER_HEIGHT \
++	--pic_position 0x14 \
++	--pic_position_offset 20 \
++	--pic_anim_type 1 \
++	--pic_anim_loop 0 \
++	--blob throbber00.rgb \
++	--blob throbber01.rgb \
++	--blob throbber02.rgb \
++	--blob throbber03.rgb \
++	--blob throbber04.rgb \
++	--blob throbber05.rgb \
++	--blob throbber06.rgb \
++	--blob throbber07.rgb \
++	--blob throbber08.rgb \
++	--blob throbber09.rgb \
++	--blob throbber10.rgb \
++	--blob throbber11.rgb \
++	bootsplash
++
++rm *.rgb
diff --git a/aarch64-desktop-omv-defconfig b/aarch64-desktop-omv-defconfig
index ba02a98..12df697 100644
--- a/aarch64-desktop-omv-defconfig
+++ b/aarch64-desktop-omv-defconfig
@@ -149,7 +149,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_UCLAMP_TASK_GROUP=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
@@ -6478,6 +6478,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 CONFIG_LOGO=y
diff --git a/aarch64-server-omv-defconfig b/aarch64-server-omv-defconfig
index 7112a0c..fda30b4 100644
--- a/aarch64-server-omv-defconfig
+++ b/aarch64-server-omv-defconfig
@@ -149,7 +149,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_UCLAMP_TASK_GROUP=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
@@ -6478,6 +6478,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 CONFIG_LOGO=y
diff --git a/armv7hnl-desktop-omv-defconfig b/armv7hnl-desktop-omv-defconfig
index 901ca4d..9bc8ab7 100644
--- a/armv7hnl-desktop-omv-defconfig
+++ b/armv7hnl-desktop-omv-defconfig
@@ -152,7 +152,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -7234,6 +7234,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 CONFIG_LOGO=y
@@ -11603,6 +11604,7 @@ CONFIG_BRANCH_PROFILE_NONE=y
 # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_KPROBE_EVENTS=y
+# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set
 # CONFIG_UPROBE_EVENTS is not set
 CONFIG_BPF_EVENTS=y
 CONFIG_DYNAMIC_EVENTS=y
diff --git a/armv7hnl-server-omv-defconfig b/armv7hnl-server-omv-defconfig
index 512597b..4a17126 100644
--- a/armv7hnl-server-omv-defconfig
+++ b/armv7hnl-server-omv-defconfig
@@ -152,7 +152,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -7234,6 +7234,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 CONFIG_LOGO=y
@@ -11603,6 +11604,7 @@ CONFIG_BRANCH_PROFILE_NONE=y
 # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_KPROBE_EVENTS=y
+# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set
 # CONFIG_UPROBE_EVENTS is not set
 CONFIG_BPF_EVENTS=y
 CONFIG_DYNAMIC_EVENTS=y
diff --git a/i686-desktop-gcc-omv-defconfig b/i686-desktop-gcc-omv-defconfig
index a496c17..9323789 100644
--- a/i686-desktop-gcc-omv-defconfig
+++ b/i686-desktop-gcc-omv-defconfig
@@ -160,7 +160,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6555,6 +6555,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
diff --git a/i686-server-gcc-omv-defconfig b/i686-server-gcc-omv-defconfig
index f034eaf..80e0d52 100644
--- a/i686-server-gcc-omv-defconfig
+++ b/i686-server-gcc-omv-defconfig
@@ -157,7 +157,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6554,6 +6554,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
diff --git a/kernel-release.spec b/kernel-release.spec
index 55a86c6..6e3e0ae 100644
--- a/kernel-release.spec
+++ b/kernel-release.spec
@@ -22,7 +22,7 @@
 # compose tar.xz name and release
 %define kernelversion	5
 %define patchlevel	10
-%define sublevel	6
+%define sublevel	10
 %define relc		%{nil}
 # Only ever wrong on x.0 releases...
 %define previous	%{kernelversion}.%(echo $((%{patchlevel}-1)))
@@ -369,6 +369,25 @@ Patch307:	PATCH-v16-08-10-fs-ntfs3-Add-Kconfig-Makefile-and-doc.patch
 Patch308:	PATCH-v16-09-10-fs-ntfs3-Add-NTFS3-in-fs-Kconfig-and-fs-Makefile.patch
 Patch309:	PATCH-v16-10-10-fs-ntfs3-Add-MAINTAINERS.patch
 
+# Bootsplash support
+# based on https://gitlab.manjaro.org/packages/core/linux510/-/tree/master
+Patch401:	0401-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
+Patch402:	0402-revert-fbcon-remove-no-op-fbcon_set_origin.patch
+Patch403:	0403-revert-fbcon-remove-soft-scrollback-code.patch
+Patch501:	0501-bootsplash.patch
+Patch502:	0502-bootsplash.patch
+Patch503:	0503-bootsplash.patch
+Patch504:	0504-bootsplash.patch
+Patch505:	0505-bootsplash.patch
+Patch506:	0506-bootsplash.patch
+Patch507:	0507-bootsplash.patch
+Patch508:	0508-bootsplash.patch
+Patch509:	0509-bootsplash.patch
+Patch510:	0510-bootsplash.patch
+Patch511:	0511-bootsplash.patch
+Patch512:	0512-bootsplash.patch
+Source513:	0513-bootsplash.gitpatch
+
 # Patches to external modules
 # Marked SourceXXX instead of PatchXXX because the modules
 # being touched aren't in the tree at the time %%autopatch -p1
@@ -891,6 +910,9 @@ xzcat %{SOURCE1000} |git apply - || git apply %{SOURCE1000}
 rm -rf .git
 %endif
 %autopatch -p1
+git apply %{SOURCE513}
+
+sed -i -e "s,' ' -f 2,' ' -f 4," scripts/lld-version.sh
 
 %ifarch %{aarch64}
 # FIXME SynQuacer workaround
@@ -1000,7 +1022,7 @@ find . -name "*.g*ignore" -delete
 chmod 755 tools/objtool/sync-check.sh
 
 %build
-%setup_compile_flags
+%set_build_flags
 
 ############################################################
 ###  Linker end2 > Check point to build for omv or rosa ###
@@ -1019,13 +1041,20 @@ chmod 755 tools/objtool/sync-check.sh
 
 
 CheckConfig() {
-
 	if [ ! -e $(pwd)/.config ]; then
 		printf '%s\n' "Kernel config in $(pwd) missing, killing the build."
 		exit 1
 	fi
 }
 
+VerifyConfig() {
+# (tpg) please add CONFIG that were carelessly enabled, while it is known these MUST be disabled
+    if grep -Fxq "CONFIG_RT_GROUP_SCHED=y" $(pwd)/.config $(pwd)/*-defconfig; then
+	printf '%s\n' "Please stop enabling CONFIG_RT_GROUP_SCHED - this option is not recommended with systemd systemd/systemd#553, killing the build."
+	exit 1
+    fi
+}
+
 clangify() {
 	sed -i \
 		-e '/^CONFIG_CC_VERSION_TEXT=/d' \
@@ -1057,7 +1086,6 @@ CreateConfig() {
 	CONFIGS=""
 	rm -fv .config
 
-
 	if echo $type |grep -q clang; then
 		# (crazy) we could use LLVM=1 this will take care of all the clang stuff
 		# however on bugs where we have to change LD or some other tool we cannot do that
@@ -1228,6 +1256,7 @@ PrepareKernel() {
 	extension=$2
 	config_dir=%{_sourcedir}
 	printf '%s\n' "Make config for kernel $extension"
+	VerifyConfig
 	%make_build -s mrproper
 %ifarch znver1
 	CreateConfig %{_target_cpu} ${flavour}
diff --git a/linux-5.10.tar.sign b/linux-5.10.tar.sign
deleted file mode 100644
index d62c35d..0000000
--- a/linux-5.10.tar.sign
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Comment: This signature is for the .tar version of the archive
-Comment: git archive --format tar --prefix=linux-5.10/ v5.10
-Comment: git version 2.29.2
-
-iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl/W/LUACgkQONu9yGCS
-aT6/cBAAqwOUE+4DCHuYnqLPO23Elg46TPPO+K/c49mEq4Z2NimoNeiguHns/aeA
-TLxuysw/YJKA+Yvv27jtf+g+dlrvr8QeWwl8GN8p0qWPwRHclcg1hkvQ0jD+tCz7
-uKpKF06P4oLhn/XxKbhvagZaea0fzrr7BWVsc91X5F7sCDZQzkKFkeCpUyCRyWEw
-0GIbc09MnpqT1iInSKYoGc7LxmZLD43jOK0eNtq4xJNPELqJhw0t24ubwOwOWKEk
-yBd4bRWIl+wrDQAzVBrAnIAtUGgL5OIIakoSrUi/kqf95sUqW8vlBxBcVruQ+kRf
-b8cpLfe1z84Vwrra5zf8ZEBoKLQV5eGYsrQgc/D37lHFGcrk3Q95AH4s+NHTkCPi
-UP61aZM3Td29IpBY/J6l33XWL7r8fTNYTnlCx5LzrmFXE/VnCZ6slZcoxDyC4NR3
-2UBS2xBcc/7xIFh0+IJecC7zfGZIQ+aXwgAwROft6SzRcQjgnV+zZSlemuJZDQR2
-eMCz7vfD7XJqeZ/Mpbm3u7zJ8em2hJj0O1ObFRuJ3l2peH/+grIkIaiikPhhvIur
-I2oPIgcmDkM+DsIP8bip+M4iFSHc2ciriER5PaJDz757rc4oupvqXeGM4lMZ5dJq
-ra7Q6eBLoTw5VCOYvyvKQhvSvfwT8utxPEKbCKxAtLsNA8lkBV0=
-=RzX+
------END PGP SIGNATURE-----
diff --git a/linux-5.8.tar.sign b/linux-5.8.tar.sign
deleted file mode 100644
index c243088..0000000
--- a/linux-5.8.tar.sign
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Comment: This signature is for the .tar version of the archive
-Comment: git archive --format tar --prefix=linux-5.8/ v5.8
-Comment: git version 2.28.0
-
-iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAl8nkEEACgkQONu9yGCS
-aT5S2g/+Ndv+CYgXJA6pPq4OCPek7uLGS8ACKhOZLmCqGWeYHHI4cFqMG8ly8Q4h
-C41SbQ02IqHTYZO8MCbrEXSO7CygxWofneTFWA7VByG4pELpC8CPg9+Vd0+9beCE
-uE+iBDnVfQi02Rd4LJZhZms1U1ZXFvfoHzAHwwc3v9ocxu3e2BVmE/cdI0AkxJv1
-xwh6wh+ppI/yUdrru2iQdN+hQ+uLrxE5HJezS/cTuI8RNop0CvwxIodfXn5o9xab
-av+CI/V6CpUVXztipTTsL2xpkI6O67jFdpgYwIylO1wnyyzi4uGGQLQ16C8aiCX2
-omaF4DpKyshkJKfiChEs6f9+9lmc1eMzALY54LgczZP3Qr6vEOPEuFc2hw69hndI
-lNIB5Kw3N3Tm06tl1QaW4KypulUzXueKV0K8GD5r9+z+R+r2z9DWadNLTslACBnI
-dgg4KlNrMoY8/reguTSv02rdOLWKJI5UV/8OO3urjs11OtYs1uW8p8h8des73k7Z
-SfLj/T/bcDzymN5G8prLM8WIvihxc/nQHGmICWNRqoFns6EEvprZeA9RWFBvn3x3
-8e10uR18P+rBiaIyxn4IzLxxKUP7SvKhWdIxySwaEZZhDo5KxOpLgQEKQCZgFXXQ
-/IqseyAItaAFoI5UxVopUUPQzzZLveLraAweB9aOfiBAshIZWGI=
-=pEA9
------END PGP SIGNATURE-----
diff --git a/x86_64-desktop-gcc-omv-defconfig b/x86_64-desktop-gcc-omv-defconfig
index 3e61da2..d4bfee4 100644
--- a/x86_64-desktop-gcc-omv-defconfig
+++ b/x86_64-desktop-gcc-omv-defconfig
@@ -169,7 +169,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6517,6 +6517,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
diff --git a/x86_64-server-gcc-omv-defconfig b/x86_64-server-gcc-omv-defconfig
index 2e0b36d..14674b7 100644
--- a/x86_64-server-gcc-omv-defconfig
+++ b/x86_64-server-gcc-omv-defconfig
@@ -166,7 +166,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6438,6 +6438,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
diff --git a/x86_64-znver-desktop-gcc-omv-defconfig b/x86_64-znver-desktop-gcc-omv-defconfig
index b0a69dc..c083563 100644
--- a/x86_64-znver-desktop-gcc-omv-defconfig
+++ b/x86_64-znver-desktop-gcc-omv-defconfig
@@ -169,7 +169,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6439,6 +6439,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
diff --git a/x86_64-znver-server-gcc-omv-defconfig b/x86_64-znver-server-gcc-omv-defconfig
index 272ad4a..54b773f 100644
--- a/x86_64-znver-server-gcc-omv-defconfig
+++ b/x86_64-znver-server-gcc-omv-defconfig
@@ -166,7 +166,7 @@ CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -6437,6 +6437,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+# CONFIG_BOOTSPLASH is not set
 # end of Console display driver support
 
 # CONFIG_LOGO is not set
Not Available

benbullard79 [@T] cox.netNo Comment.1180d 04hrs
benbullard79 [@T] cox.netNo Comment.1180d 04hrs