Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/patch/misc/0001-bootsplash.patch
Views: 3959
diff --git a/MAINTAINERS b/MAINTAINERS1index a74227ad082e..b5633b56391e 1006442--- a/MAINTAINERS3+++ b/MAINTAINERS4@@ -2705,6 +2705,14 @@ S: Supported5F: drivers/net/bonding/6F: include/uapi/linux/if_bonding.h78+BOOTSPLASH9+M: Max Staudt <[email protected]>10+L: [email protected]11+S: Maintained12+F: drivers/video/fbdev/core/bootsplash*.*13+F: drivers/video/fbdev/core/dummycon.c14+F: include/linux/bootsplash.h15+16BPF (Safe dynamic programs and tools)17M: Alexei Starovoitov <[email protected]>18M: Daniel Borkmann <[email protected]>19diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig20index 7f1f1fbcef9e..f3ff976266fe 10064421--- a/drivers/video/console/Kconfig22+++ b/drivers/video/console/Kconfig23@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION24such that other users of the framebuffer will remain normally25oriented.2627+config BOOTSPLASH28+ bool "Bootup splash screen"29+ depends on FRAMEBUFFER_CONSOLE30+ ---help---31+ This option enables the Linux bootsplash screen.32+33+ The bootsplash is a full-screen logo or animation indicating a34+ booting system. It replaces the classic scrolling text with a35+ graphical alternative, similar to other systems.36+37+ Since this is technically implemented as a hook on top of fbcon,38+ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a39+ framebuffer driver is active. Thus, to get a text-free boot,40+ the system needs to boot with vesafb, efifb, or similar.41+42+ Once built into the kernel, the bootsplash needs to be enabled43+ with bootsplash.enabled=1 and a splash file needs to be supplied.44+45+ Further documentation can be found in:46+ Documentation/fb/bootsplash.txt47+48+ If unsure, say N.49+ This is typically used by distributors and system integrators.50+51config STI_CONSOLE52bool "STI text console"53depends on PARISC54diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile55index 73493bbd7a15..66895321928e 10064456--- a/drivers/video/fbdev/core/Makefile57+++ b/drivers/video/fbdev/core/Makefile58@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o59obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o60obj-$(CONFIG_FB_SVGALIB) += svgalib.o61obj-$(CONFIG_FB_DDC) += fb_ddc.o62+63+obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \64+ dummyblit.o65diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c66new file mode 10064467index 000000000000..e449755af26868--- /dev/null69+++ b/drivers/video/fbdev/core/bootsplash.c70@@ -0,0 +1,294 @@71+/*72+ * Kernel based bootsplash.73+ *74+ * (Main file: Glue code, workers, timer, PM, kernel and userland API)75+ *76+ * Authors:77+ * Max Staudt <[email protected]>78+ *79+ * SPDX-License-Identifier: GPL-2.080+ */81+82+#define pr_fmt(fmt) "bootsplash: " fmt83+84+85+#include <linux/atomic.h>86+#include <linux/bootsplash.h>87+#include <linux/console.h>88+#include <linux/device.h> /* dev_warn() */89+#include <linux/fb.h>90+#include <linux/fs.h>91+#include <linux/kernel.h>92+#include <linux/jiffies.h>93+#include <linux/module.h>94+#include <linux/mutex.h>95+#include <linux/platform_device.h>96+#include <linux/printk.h>97+#include <linux/selection.h> /* console_blanked */98+#include <linux/stringify.h>99+#include <linux/types.h>100+#include <linux/vmalloc.h>101+#include <linux/vt_kern.h>102+#include <linux/workqueue.h>103+104+#include "bootsplash_internal.h"105+106+107+/*108+ * We only have one splash screen, so let's keep a single109+ * instance of the internal state.110+ */111+static struct splash_priv splash_state;112+113+114+static void splash_callback_redraw_vc(struct work_struct *ignored)115+{116+ if (console_blanked)117+ return;118+119+ console_lock();120+ if (vc_cons[fg_console].d)121+ update_screen(vc_cons[fg_console].d);122+ console_unlock();123+}124+125+126+static bool is_fb_compatible(const struct fb_info *info)127+{128+ if (!(info->flags & FBINFO_BE_MATH)129+ != !fb_be_math((struct fb_info *)info)) {130+ dev_warn(info->device,131+ "Can't draw on foreign endianness framebuffer.\n");132+133+ return false;134+ }135+136+ if (info->flags & FBINFO_MISC_TILEBLITTING) {137+ dev_warn(info->device,138+ "Can't draw splash on tiling framebuffer.\n");139+140+ return false;141+ }142+143+ if (info->fix.type != FB_TYPE_PACKED_PIXELS144+ || (info->fix.visual != FB_VISUAL_TRUECOLOR145+ && info->fix.visual != FB_VISUAL_DIRECTCOLOR)) {146+ dev_warn(info->device,147+ "Can't draw splash on non-packed or non-truecolor framebuffer.\n");148+149+ dev_warn(info->device,150+ " type: %u visual: %u\n",151+ info->fix.type, info->fix.visual);152+153+ return false;154+ }155+156+ if (info->var.bits_per_pixel != 16157+ && info->var.bits_per_pixel != 24158+ && info->var.bits_per_pixel != 32) {159+ dev_warn(info->device,160+ "We only support drawing on framebuffers with 16, 24, or 32 bpp, not %d.\n",161+ info->var.bits_per_pixel);162+163+ return false;164+ }165+166+ return true;167+}168+169+170+/*171+ * Called by fbcon_switch() when an instance is activated or refreshed.172+ */173+void bootsplash_render_full(struct fb_info *info)174+{175+ if (!is_fb_compatible(info))176+ return;177+178+ bootsplash_do_render_background(info);179+}180+181+182+/*183+ * External status enquiry and on/off switch184+ */185+bool bootsplash_would_render_now(void)186+{187+ return !oops_in_progress188+ && !console_blanked189+ && bootsplash_is_enabled();190+}191+192+bool bootsplash_is_enabled(void)193+{194+ bool was_enabled;195+196+ /* Make sure we have the newest state */197+ smp_rmb();198+199+ was_enabled = test_bit(0, &splash_state.enabled);200+201+ return was_enabled;202+}203+204+void bootsplash_disable(void)205+{206+ int was_enabled;207+208+ was_enabled = test_and_clear_bit(0, &splash_state.enabled);209+210+ if (was_enabled) {211+ if (oops_in_progress) {212+ /* Redraw screen now so we can see a panic */213+ if (vc_cons[fg_console].d)214+ update_screen(vc_cons[fg_console].d);215+ } else {216+ /* No urgency, redraw at next opportunity */217+ schedule_work(&splash_state.work_redraw_vc);218+ }219+ }220+}221+222+void bootsplash_enable(void)223+{224+ bool was_enabled;225+226+ if (oops_in_progress)227+ return;228+229+ was_enabled = test_and_set_bit(0, &splash_state.enabled);230+231+ if (!was_enabled)232+ schedule_work(&splash_state.work_redraw_vc);233+}234+235+236+/*237+ * Userland API via platform device in sysfs238+ */239+static ssize_t splash_show_enabled(struct device *dev,240+ struct device_attribute *attr, char *buf)241+{242+ return sprintf(buf, "%d\n", bootsplash_is_enabled());243+}244+245+static ssize_t splash_store_enabled(struct device *device,246+ struct device_attribute *attr,247+ const char *buf, size_t count)248+{249+ bool enable;250+ int err;251+252+ if (!buf || !count)253+ return -EFAULT;254+255+ err = kstrtobool(buf, &enable);256+ if (err)257+ return err;258+259+ if (enable)260+ bootsplash_enable();261+ else262+ bootsplash_disable();263+264+ return count;265+}266+267+static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);268+269+270+static struct attribute *splash_dev_attrs[] = {271+ &dev_attr_enabled.attr,272+ NULL273+};274+275+ATTRIBUTE_GROUPS(splash_dev);276+277+278+279+280+/*281+ * Power management fixup via platform device282+ *283+ * When the system is woken from sleep or restored after hibernating, we284+ * cannot expect the screen contents to still be present in video RAM.285+ * Thus, we have to redraw the splash if we're currently active.286+ */287+static int splash_resume(struct device *device)288+{289+ if (bootsplash_would_render_now())290+ schedule_work(&splash_state.work_redraw_vc);291+292+ return 0;293+}294+295+static int splash_suspend(struct device *device)296+{297+ cancel_work_sync(&splash_state.work_redraw_vc);298+299+ return 0;300+}301+302+303+static const struct dev_pm_ops splash_pm_ops = {304+ .thaw = splash_resume,305+ .restore = splash_resume,306+ .resume = splash_resume,307+ .suspend = splash_suspend,308+ .freeze = splash_suspend,309+};310+311+static struct platform_driver splash_driver = {312+ .driver = {313+ .name = "bootsplash",314+ .pm = &splash_pm_ops,315+ },316+};317+318+319+/*320+ * Main init321+ */322+void bootsplash_init(void)323+{324+ int ret;325+326+ /* Initialized already? */327+ if (splash_state.splash_device)328+ return;329+330+331+ /* Register platform device to export user API */332+ ret = platform_driver_register(&splash_driver);333+ if (ret) {334+ pr_err("platform_driver_register() failed: %d\n", ret);335+ goto err;336+ }337+338+ splash_state.splash_device339+ = platform_device_alloc("bootsplash", 0);340+341+ if (!splash_state.splash_device)342+ goto err_driver;343+344+ splash_state.splash_device->dev.groups = splash_dev_groups;345+346+ ret = platform_device_add(splash_state.splash_device);347+ if (ret) {348+ pr_err("platform_device_add() failed: %d\n", ret);349+ goto err_device;350+ }351+352+353+ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);354+355+ return;356+357+err_device:358+ platform_device_put(splash_state.splash_device);359+ splash_state.splash_device = NULL;360+err_driver:361+ platform_driver_unregister(&splash_driver);362+err:363+ pr_err("Failed to initialize.\n");364+}365diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h366new file mode 100644367index 000000000000..b11da5cb90bf368--- /dev/null369+++ b/drivers/video/fbdev/core/bootsplash_internal.h370@@ -0,0 +1,55 @@371+/*372+ * Kernel based bootsplash.373+ *374+ * (Internal data structures used at runtime)375+ *376+ * Authors:377+ * Max Staudt <[email protected]>378+ *379+ * SPDX-License-Identifier: GPL-2.0380+ */381+382+#ifndef __BOOTSPLASH_INTERNAL_H383+#define __BOOTSPLASH_INTERNAL_H384+385+386+#include <linux/types.h>387+#include <linux/fb.h>388+#include <linux/kernel.h>389+#include <linux/mutex.h>390+#include <linux/spinlock.h>391+392+393+/*394+ * Runtime types395+ */396+struct splash_priv {397+ /*398+ * Enabled/disabled state, to be used with atomic bit operations.399+ * Bit 0: 0 = Splash hidden400+ * 1 = Splash shown401+ *402+ * Note: fbcon.c uses this twice, by calling403+ * bootsplash_would_render_now() in set_blitting_type() and404+ * in fbcon_switch().405+ * This is racy, but eventually consistent: Turning the406+ * splash on/off will cause a redraw, which calls407+ * fbcon_switch(), which calls set_blitting_type().408+ * So the last on/off toggle will make things consistent.409+ */410+ unsigned long enabled;411+412+ /* Our gateway to userland via sysfs */413+ struct platform_device *splash_device;414+415+ struct work_struct work_redraw_vc;416+};417+418+419+420+/*421+ * Rendering functions422+ */423+void bootsplash_do_render_background(struct fb_info *info);424+425+#endif426diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c427new file mode 100644428index 000000000000..4d7e0117f653429--- /dev/null430+++ b/drivers/video/fbdev/core/bootsplash_render.c431@@ -0,0 +1,93 @@432+/*433+ * Kernel based bootsplash.434+ *435+ * (Rendering functions)436+ *437+ * Authors:438+ * Max Staudt <[email protected]>439+ *440+ * SPDX-License-Identifier: GPL-2.0441+ */442+443+#define pr_fmt(fmt) "bootsplash: " fmt444+445+446+#include <linux/bootsplash.h>447+#include <linux/fb.h>448+#include <linux/kernel.h>449+#include <linux/printk.h>450+#include <linux/types.h>451+452+#include "bootsplash_internal.h"453+454+455+456+457+/*458+ * Rendering: Internal drawing routines459+ */460+461+462+/*463+ * Pack pixel into target format and do Big/Little Endian handling.464+ * This would be a good place to handle endianness conversion if necessary.465+ */466+static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,467+ u8 red, u8 green, u8 blue)468+{469+ u32 dstpix;470+471+ /* Quantize pixel */472+ red = red >> (8 - dst_var->red.length);473+ green = green >> (8 - dst_var->green.length);474+ blue = blue >> (8 - dst_var->blue.length);475+476+ /* Pack pixel */477+ dstpix = red << (dst_var->red.offset)478+ | green << (dst_var->green.offset)479+ | blue << (dst_var->blue.offset);480+481+ /*482+ * Move packed pixel to the beginning of the memory cell,483+ * so we can memcpy() it out easily484+ */485+#ifdef __BIG_ENDIAN486+ switch (dst_var->bits_per_pixel) {487+ case 16:488+ dstpix <<= 16;489+ break;490+ case 24:491+ dstpix <<= 8;492+ break;493+ case 32:494+ break;495+ }496+#else497+ /* This is intrinsically unnecessary on Little Endian */498+#endif499+500+ return dstpix;501+}502+503+504+void bootsplash_do_render_background(struct fb_info *info)505+{506+ unsigned int x, y;507+ u32 dstpix;508+ u32 dst_octpp = info->var.bits_per_pixel / 8;509+510+ dstpix = pack_pixel(&info->var,511+ 0,512+ 0,513+ 0);514+515+ for (y = 0; y < info->var.yres_virtual; y++) {516+ u8 *dstline = info->screen_buffer + (y * info->fix.line_length);517+518+ for (x = 0; x < info->var.xres_virtual; x++) {519+ memcpy(dstline, &dstpix, dst_octpp);520+521+ dstline += dst_octpp;522+ }523+ }524+}525diff --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c526new file mode 100644527index 000000000000..8c22ff92ce24528--- /dev/null529+++ b/drivers/video/fbdev/core/dummyblit.c530@@ -0,0 +1,89 @@531+/*532+ * linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation533+ *534+ * Authors:535+ * Max Staudt <[email protected]>536+ *537+ * These functions are used in place of blitblit/tileblit to suppress538+ * fbcon's text output while a splash is shown.539+ *540+ * Only suppressing actual rendering keeps the text buffer in the VC layer541+ * intact and makes it easy to switch back from the bootsplash to a full542+ * text console with a simple redraw (with the original functions in place).543+ *544+ * Based on linux/drivers/video/fbdev/core/bitblit.c545+ * and linux/drivers/video/fbdev/core/tileblit.c546+ *547+ * SPDX-License-Identifier: GPL-2.0548+ */549+550+#include <linux/module.h>551+#include <linux/fb.h>552+#include <linux/vt_kern.h>553+#include <linux/console.h>554+#include <asm/types.h>555+#include "fbcon.h"556+557+static void dummy_bmove(struct vc_data *vc, struct fb_info *info, int sy,558+ int sx, int dy, int dx, int height, int width)559+{560+ ;561+}562+563+static void dummy_clear(struct vc_data *vc, struct fb_info *info, int sy,564+ int sx, int height, int width)565+{566+ ;567+}568+569+static void dummy_putcs(struct vc_data *vc, struct fb_info *info,570+ const unsigned short *s, int count, int yy, int xx,571+ int fg, int bg)572+{573+ ;574+}575+576+static void dummy_clear_margins(struct vc_data *vc, struct fb_info *info,577+ int color, int bottom_only)578+{579+ ;580+}581+582+static void dummy_cursor(struct vc_data *vc, struct fb_info *info, int mode,583+ int softback_lines, int fg, int bg)584+{585+ ;586+}587+588+static int dummy_update_start(struct fb_info *info)589+{590+ /*591+ * Copied from bitblit.c and tileblit.c592+ *593+ * As of Linux 4.12, nobody seems to care about our return value.594+ */595+ struct fbcon_ops *ops = info->fbcon_par;596+ int err;597+598+ err = fb_pan_display(info, &ops->var);599+ ops->var.xoffset = info->var.xoffset;600+ ops->var.yoffset = info->var.yoffset;601+ ops->var.vmode = info->var.vmode;602+ return err;603+}604+605+void fbcon_set_dummyops(struct fbcon_ops *ops)606+{607+ ops->bmove = dummy_bmove;608+ ops->clear = dummy_clear;609+ ops->putcs = dummy_putcs;610+ ops->clear_margins = dummy_clear_margins;611+ ops->cursor = dummy_cursor;612+ ops->update_start = dummy_update_start;613+ ops->rotate_font = NULL;614+}615+EXPORT_SYMBOL_GPL(fbcon_set_dummyops);616+617+MODULE_AUTHOR("Max Staudt <[email protected]>");618+MODULE_DESCRIPTION("Dummy Blitting Operation");619+MODULE_LICENSE("GPL");620diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c621index 04612f938bab..9a39a6fcfe98 100644622--- a/drivers/video/fbdev/core/fbcon.c623+++ b/drivers/video/fbdev/core/fbcon.c624@@ -80,6 +80,7 @@625#include <asm/irq.h>626627#include "fbcon.h"628+#include <linux/bootsplash.h>629630#ifdef FBCONDEBUG631# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)632@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)633for (i = first_fb_vc; i <= last_fb_vc; i++)634con2fb_map[i] = info_idx;635636+ bootsplash_init();637+638err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,639fbcon_is_default);640641@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)642else {643fbcon_set_rotation(info);644fbcon_set_bitops(ops);645+646+ if (bootsplash_would_render_now())647+ fbcon_set_dummyops(ops);648}649}650651@@ -683,6 +689,19 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)652ops->p = &fb_display[vc->vc_num];653fbcon_set_rotation(info);654fbcon_set_bitops(ops);655+656+ /*657+ * Note:658+ * This is *eventually correct*.659+ * Setting the fbcon operations and drawing the splash happen at660+ * different points in time. If the splash is enabled/disabled661+ * in between, then bootsplash_{en,dis}able will schedule a662+ * redraw, which will again render the splash (or not) and set663+ * the correct fbcon ops.664+ * The last run will then be the right one.665+ */666+ if (bootsplash_would_render_now())667+ fbcon_set_dummyops(ops);668}669670static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)671@@ -2184,6 +2203,9 @@ static int fbcon_switch(struct vc_data *vc)672info = registered_fb[con2fb_map[vc->vc_num]];673ops = info->fbcon_par;674675+ if (bootsplash_would_render_now())676+ bootsplash_render_full(info);677+678if (softback_top) {679if (softback_lines)680fbcon_set_origin(vc);681diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h682index 18f3ac144237..45f94347fe5e 100644683--- a/drivers/video/fbdev/core/fbcon.h684+++ b/drivers/video/fbdev/core/fbcon.h685@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,686#define SCROLL_REDRAW 0x004687#define SCROLL_PAN_REDRAW 0x005688689+#ifdef CONFIG_BOOTSPLASH690+extern void fbcon_set_dummyops(struct fbcon_ops *ops);691+#else /* CONFIG_BOOTSPLASH */692+#define fbcon_set_dummyops(x)693+#endif /* CONFIG_BOOTSPLASH */694#ifdef CONFIG_FB_TILEBLITTING695extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);696#endif697diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h698new file mode 100644699index 000000000000..c6dd0b43180d700--- /dev/null701+++ b/include/linux/bootsplash.h702@@ -0,0 +1,43 @@703+/*704+ * Kernel based bootsplash.705+ *706+ * Authors:707+ * Max Staudt <[email protected]>708+ *709+ * SPDX-License-Identifier: GPL-2.0710+ */711+712+#ifndef __LINUX_BOOTSPLASH_H713+#define __LINUX_BOOTSPLASH_H714+715+#include <linux/fb.h>716+717+718+#ifdef CONFIG_BOOTSPLASH719+720+extern void bootsplash_render_full(struct fb_info *info);721+722+extern bool bootsplash_would_render_now(void);723+724+extern bool bootsplash_is_enabled(void);725+extern void bootsplash_disable(void);726+extern void bootsplash_enable(void);727+728+extern void bootsplash_init(void);729+730+#else /* CONFIG_BOOTSPLASH */731+732+#define bootsplash_render_full(x)733+734+#define bootsplash_would_render_now() (false)735+736+#define bootsplash_is_enabled() (false)737+#define bootsplash_disable()738+#define bootsplash_enable()739+740+#define bootsplash_init()741+742+#endif /* CONFIG_BOOTSPLASH */743+744+745+#endif746747748