Dear fbdev and fbcon developers,
Thank you very much for your input for the first patch series.
I've included your feedback into this second roll, and kindly ask for
your opinion on the new patch series.
Changes from v1 to v2:
+ Added a user space tool to create splash theme files
+ Bumped the file format version:
- Larger structs for easy future expansion
- 2-byte corner offset
- Offset either from corner or from center
- Fixed padding before header->frame_ms
+ Moved bootsplash_file.h to uapi/linux
+ Merged several patches
+ Theme files are now loaded via request_firmware()
+ sysfs hook to allow loading of theme files via request_firmware()
+ Dropped the .enable cmdline option and the default file name.
The splash will be shown as soon as a file is specified.
+ Dropped custom workqueue in favor of the kernel queue
and cancel_delayed_work_sync()
+ Marked loaded data as const, and load/enable it atomically
+ Reduced global state by moving data into other structures
+ EXPORT_SYMBOL_GPL for fbcon_set_dummyops()
+ Atomic and barrier for splash enabled state instead of spinlock
+ Reduced warnings to infos
+ Rate limited printk
+ Changed the multi-line comment layout to kernel style
+ Simplified the file headers
+ reST-ed the documentation
Max
This allows showing multiple logos, each in its own position,
relative to the eight screen corners.
Signed-off-by: Max Staudt <[email protected]>
---
drivers/video/fbdev/core/bootsplash_render.c | 136 ++++++++++++++++++++++++++-
include/uapi/linux/bootsplash_file.h | 45 ++++++++-
2 files changed, 178 insertions(+), 3 deletions(-)
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
--
2.12.3
After exiting a KD_GRAPHICS program and falling back to the text
console, a previously enabled splash needs to be fully redrawn.
This corner case was introduced with selective re-drawing while
implementing animations.
Without this patch, the following happens:
1. Switch to a text console
2. Enable splash
3. Start X (or any other KD_GRAPHICS program)
4. Exit X
5. Splash is not seen, apart from animations
Signed-off-by: Max Staudt <[email protected]>
Reviewed-by: Oliver Neukum <[email protected]>
---
drivers/tty/vt/vt.c | 2 ++
drivers/video/fbdev/core/bootsplash.c | 15 +++++++++------
include/linux/bootsplash.h | 4 ++++
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 2ebaba16f785..416735ab6dc1 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -102,6 +102,7 @@
#include <linux/uaccess.h>
#include <linux/kdb.h>
#include <linux/ctype.h>
+#include <linux/bootsplash.h>
#define MAX_NR_CON_DRIVER 16
@@ -3903,6 +3904,7 @@ void do_unblank_screen(int leaving_gfx)
}
console_blanked = 0;
+ bootsplash_mark_dirty();
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(vc);
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
index 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()
--
2.12.3
Also, mention this in the bootsplash documentation.
Signed-off-by: Max Staudt <[email protected]>
---
Documentation/bootsplash.rst | 10 ++++++
tools/bootsplash/.gitignore | 3 ++
tools/bootsplash/ajax-loader.gif | Bin 0 -> 3208 bytes
tools/bootsplash/bootsplash-tux.sh | 66 +++++++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+)
create mode 100644 tools/bootsplash/ajax-loader.gif
create mode 100755 tools/bootsplash/bootsplash-tux.sh
diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
index d793612ebf2e..3ace027de357 100644
--- a/Documentation/bootsplash.rst
+++ b/Documentation/bootsplash.rst
@@ -183,3 +183,13 @@ Hooks - how the bootsplash is integrated
``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.
+
+
+
+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.
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
--
2.12.3
Signed-off-by: Max Staudt <[email protected]>
---
.../ABI/testing/sysfs-platform-bootsplash | 11 ++
Documentation/bootsplash.rst | 177 +++++++++++++++++++++
MAINTAINERS | 2 +
3 files changed, 190 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-platform-bootsplash
create mode 100644 Documentation/bootsplash.rst
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 <[email protected]>
+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..8bd6805af6bf
--- /dev/null
+++ b/Documentation/bootsplash.rst
@@ -0,0 +1,177 @@
+====================
+The Linux bootsplash
+====================
+
+:Date: November, 2017
+:Author: Max Staudt <[email protected]>
+
+
+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 initrd to load.
+ 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.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5c237445761e..7ffac272434e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2709,6 +2709,8 @@ BOOTSPLASH
M: Max Staudt <[email protected]>
L: [email protected]
S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-bootsplash
+F: Documentation/bootsplash.rst
F: drivers/video/fbdev/core/bootsplash*.*
F: drivers/video/fbdev/core/dummycon.c
F: include/linux/bootsplash.h
--
2.12.3
Signed-off-by: Max Staudt <[email protected]>
---
MAINTAINERS | 1 +
tools/bootsplash/.gitignore | 1 +
tools/bootsplash/Makefile | 9 +
tools/bootsplash/bootsplash-packer.c | 471 +++++++++++++++++++++++++++++++++++
4 files changed, 482 insertions(+)
create mode 100644 tools/bootsplash/.gitignore
create mode 100644 tools/bootsplash/Makefile
create mode 100644 tools/bootsplash/bootsplash-packer.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7ffac272434e..ddff07cd794c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2715,6 +2715,7 @@ F: drivers/video/fbdev/core/bootsplash*.*
F: drivers/video/fbdev/core/dummycon.c
F: include/linux/bootsplash.h
F: include/uapi/linux/bootsplash_file.h
+F: tools/bootsplash/*
BPF (Safe dynamic programs and tools)
M: Alexei Starovoitov <[email protected]>
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 <[email protected]>
+ *
+ * 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;
+}
--
2.12.3
Signed-off-by: Max Staudt <[email protected]>
Reviewed-by: Oliver Neukum <[email protected]>
---
drivers/video/fbdev/core/fbcon.c | 10 ++++++++++
1 file changed, 10 insertions(+)
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)
--
2.12.3
Users can use this to replace their splash screen at runtime by writing
a path and filename to /sys/devices/platform/bootsplash.0/load_file and
making sure the splash is enabled.
Notes:
- 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.
Writes to /sys/devices/platform/bootsplash.0/drop_splash will cause the
current splash theme to be freed and the console to switch to text mode,
Signed-off-by: Max Staudt <[email protected]>
---
.../ABI/testing/sysfs-platform-bootsplash | 32 +++++++++++++
Documentation/bootsplash.rst | 8 ++++
drivers/video/fbdev/core/bootsplash.c | 54 ++++++++++++++++++++++
3 files changed, 94 insertions(+)
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 <[email protected]>
+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 <[email protected]>
+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 8bd6805af6bf..d793612ebf2e 100644
--- a/Documentation/bootsplash.rst
+++ b/Documentation/bootsplash.rst
@@ -58,6 +58,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
};
--
2.12.3
Each 'picture' in the splash file can consist of multiple 'blobs'.
If animation is enabled, these blobs become the frames of an animation,
in the order in which they are stored in the file.
Note: There is only one global timer, so all animations happen at
the same frame rate. It doesn't really make sense to animate
more than one object at a time anyway.
Furthermore, this patch introduces a check for reusing a framebuffer
where the splash has recently been painted on - in this case, we only
redraw the objects that are animated.
Signed-off-by: Max Staudt <[email protected]>
---
drivers/video/fbdev/core/bootsplash.c | 62 +++++++++++++++++++++++---
drivers/video/fbdev/core/bootsplash_internal.h | 13 +++++-
drivers/video/fbdev/core/bootsplash_load.c | 21 +++++++++
drivers/video/fbdev/core/bootsplash_render.c | 30 ++++++++++++-
include/uapi/linux/bootsplash_file.h | 35 ++++++++++++++-
5 files changed, 151 insertions(+), 10 deletions(-)
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
--
2.12.3
When the user requests a clean TTY via the SAK SysRq, that means he
really wants to use the console.
Let's disable the bootsplash, even if the request is not on a VT, as
the user probably knows what he's doing and it's more helpful to get
out of his way.
Signed-off-by: Max Staudt <[email protected]>
Reviewed-by: Oliver Neukum <[email protected]>
---
drivers/tty/sysrq.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 3ffc1ce29023..bc6a24c9dfa8 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -49,6 +49,7 @@
#include <linux/syscalls.h>
#include <linux/of.h>
#include <linux/rcupdate.h>
+#include <linux/bootsplash.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
@@ -104,6 +105,8 @@ static void sysrq_handle_SAK(int key)
{
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
schedule_work(SAK_work);
+
+ bootsplash_disable();
}
static struct sysrq_key_op sysrq_SAK_op = {
.handler = sysrq_handle_SAK,
--
2.12.3
Let's disable the splash if the user presses ESC or F1-F12 on a VT.
The F1-F12 check is to disable the splash on VT switches.
Signed-off-by: Max Staudt <[email protected]>
---
drivers/tty/vt/keyboard.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
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
--
2.12.3
Load logo(s) from a file and render them in the center of the screen.
This removes the "black screen" functionality, which can now be emulated
by providing a splash file with no pictures and a black background.
Signed-off-by: Max Staudt <[email protected]>
---
MAINTAINERS | 1 +
drivers/video/fbdev/core/Makefile | 2 +-
drivers/video/fbdev/core/bootsplash.c | 36 +++-
drivers/video/fbdev/core/bootsplash_internal.h | 45 ++++-
drivers/video/fbdev/core/bootsplash_load.c | 225 +++++++++++++++++++++++++
drivers/video/fbdev/core/bootsplash_render.c | 103 ++++++++++-
include/uapi/linux/bootsplash_file.h | 118 +++++++++++++
7 files changed, 522 insertions(+), 8 deletions(-)
create mode 100644 drivers/video/fbdev/core/bootsplash_load.c
create mode 100644 include/uapi/linux/bootsplash_file.h
diff --git a/MAINTAINERS b/MAINTAINERS
index b5633b56391e..5c237445761e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2712,6 +2712,7 @@ S: Maintained
F: drivers/video/fbdev/core/bootsplash*.*
F: drivers/video/fbdev/core/dummycon.c
F: include/linux/bootsplash.h
+F: include/uapi/linux/bootsplash_file.h
BPF (Safe dynamic programs and tools)
M: Alexei Starovoitov <[email protected]>
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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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
--
2.12.3
Framebuffers with deferred I/O need to be flushed to the screen
explicitly, since we use neither the mmap nor the file I/O abstractions
that handle this for userspace FB clients.
Example: xenfb
Some framebuffer drivers implement lazy access to the screen without
actually exposing a fbdefio interface - we also match some known ones,
currently:
- ast
- cirrus
- mgag200
Signed-off-by: Max Staudt <[email protected]>
Reviewed-by: Oliver Neukum <[email protected]>
---
drivers/video/fbdev/core/bootsplash.c | 2 ++
drivers/video/fbdev/core/bootsplash_internal.h | 1 +
drivers/video/fbdev/core/bootsplash_render.c | 33 ++++++++++++++++++++++++++
3 files changed, 36 insertions(+)
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);
+ }
+}
--
2.12.3
This is the initial prototype for a lean Linux kernel bootsplash.
It works by replacing fbcon's FB manipulation routines (such as
bitblit, tileblit) with dummy functions, effectively disabling text
output, and drawing the splash directly onto the FB device.
As it is now, it will show a black screen rather than a logo, and
only if manually enabled via the kernel cmdline:
bootsplash.enable=1
There is a userland API via sysfs, to show/hide the splash on request
by dracut, systemd, or other init systems.
The reasons for implementing a bootsplash in kernel space are:
- Quieting things more and nicer than with the quiet boot option:
Currently the 'quiet' boot option does not remove the blinking
cursor and errors are still printed. There are use cases where this
is not desirable (such as embedded and desktop systems, digital
signage, etc.) and a vendor logo is preferable.
- Showing graphics, and never text, when the GUI crashes:
This is an extension of the above use case, where recovery is meant
to happen as invisibly to the user as possible. A system integrator
needs the flexibility to hide "scary text" from users in all cases
other than a panic.
This is especially desirable in embedded systems such as digital
signage.
- Racy VT API:
Userspace bootsplashes and GUIs (e.g. plymouth and X) tend to kick
each other out via the non-exclusive KDSETMODE ioctl. This can
result in situations such as the user being stuck in X with chvt
and Ctrl-Alt-Fx no longer working.
- Mode switching from FB to KMS:
We cannot switch from a generic framebuffer (vesafb, efifb) to a
KMS driver while a userspace splash keeps /dev/fb0 open. The device
will vanish, but the address space is still busy, so the KMS driver
cannot reserve its VRAM.
- Simplification of userspace integration:
Right now, hooking up a splash screen in userspace is quite complex.
Having it in the kernel makes this a breeze, as hooks for
switch_root, remounting r/w, etc. become obsolete.
Signed-off-by: Max Staudt <[email protected]>
---
MAINTAINERS | 8 +
drivers/video/console/Kconfig | 24 ++
drivers/video/fbdev/core/Makefile | 3 +
drivers/video/fbdev/core/bootsplash.c | 294 +++++++++++++++++++++++++
drivers/video/fbdev/core/bootsplash_internal.h | 55 +++++
drivers/video/fbdev/core/bootsplash_render.c | 93 ++++++++
drivers/video/fbdev/core/dummyblit.c | 89 ++++++++
drivers/video/fbdev/core/fbcon.c | 22 ++
drivers/video/fbdev/core/fbcon.h | 5 +
include/linux/bootsplash.h | 43 ++++
10 files changed, 636 insertions(+)
create mode 100644 drivers/video/fbdev/core/bootsplash.c
create mode 100644 drivers/video/fbdev/core/bootsplash_internal.h
create mode 100644 drivers/video/fbdev/core/bootsplash_render.c
create mode 100644 drivers/video/fbdev/core/dummyblit.c
create mode 100644 include/linux/bootsplash.h
diff --git a/MAINTAINERS b/MAINTAINERS
index a74227ad082e..b5633b56391e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2705,6 +2705,14 @@ S: Supported
F: drivers/net/bonding/
F: include/uapi/linux/if_bonding.h
+BOOTSPLASH
+M: Max Staudt <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/video/fbdev/core/bootsplash*.*
+F: drivers/video/fbdev/core/dummycon.c
+F: include/linux/bootsplash.h
+
BPF (Safe dynamic programs and tools)
M: Alexei Starovoitov <[email protected]>
M: Daniel Borkmann <[email protected]>
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 7f1f1fbcef9e..f3ff976266fe 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
such that other users of the framebuffer will remain normally
oriented.
+config BOOTSPLASH
+ bool "Bootup splash screen"
+ depends on FRAMEBUFFER_CONSOLE
+ ---help---
+ This option enables the Linux bootsplash screen.
+
+ The bootsplash is a full-screen logo or animation indicating a
+ booting system. It replaces the classic scrolling text with a
+ graphical alternative, similar to other systems.
+
+ Since this is technically implemented as a hook on top of fbcon,
+ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a
+ framebuffer driver is active. Thus, to get a text-free boot,
+ the system needs to boot with vesafb, efifb, or similar.
+
+ Once built into the kernel, the bootsplash needs to be enabled
+ with bootsplash.enabled=1 and a splash file needs to be supplied.
+
+ Further documentation can be found in:
+ Documentation/fb/bootsplash.txt
+
+ If unsure, say N.
+ This is typically used by distributors and system integrators.
+
config STI_CONSOLE
bool "STI text console"
depends on PARISC
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index 73493bbd7a15..66895321928e 100644
--- a/drivers/video/fbdev/core/Makefile
+++ b/drivers/video/fbdev/core/Makefile
@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
obj-$(CONFIG_FB_SVGALIB) += svgalib.o
obj-$(CONFIG_FB_DDC) += fb_ddc.o
+
+obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
+ dummyblit.o
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
new file mode 100644
index 000000000000..e449755af268
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash.c
@@ -0,0 +1,294 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
+ *
+ * Authors:
+ * Max Staudt <[email protected]>
+ *
+ * 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 --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
new file mode 100644
index 000000000000..b11da5cb90bf
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
@@ -0,0 +1,55 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Internal data structures used at runtime)
+ *
+ * Authors:
+ * Max Staudt <[email protected]>
+ *
+ * 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 --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
new file mode 100644
index 000000000000..4d7e0117f653
--- /dev/null
+++ b/drivers/video/fbdev/core/bootsplash_render.c
@@ -0,0 +1,93 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * (Rendering functions)
+ *
+ * Authors:
+ * Max Staudt <[email protected]>
+ *
+ * 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 --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c
new file mode 100644
index 000000000000..8c22ff92ce24
--- /dev/null
+++ b/drivers/video/fbdev/core/dummyblit.c
@@ -0,0 +1,89 @@
+/*
+ * linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
+ *
+ * Authors:
+ * Max Staudt <[email protected]>
+ *
+ * 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 <[email protected]>");
+MODULE_DESCRIPTION("Dummy Blitting Operation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 04612f938bab..9a39a6fcfe98 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -80,6 +80,7 @@
#include <asm/irq.h>
#include "fbcon.h"
+#include <linux/bootsplash.h>
#ifdef FBCONDEBUG
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)
for (i = first_fb_vc; i <= last_fb_vc; i++)
con2fb_map[i] = info_idx;
+ bootsplash_init();
+
err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
fbcon_is_default);
@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
else {
fbcon_set_rotation(info);
fbcon_set_bitops(ops);
+
+ if (bootsplash_would_render_now())
+ fbcon_set_dummyops(ops);
}
}
@@ -683,6 +689,19 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
ops->p = &fb_display[vc->vc_num];
fbcon_set_rotation(info);
fbcon_set_bitops(ops);
+
+ /*
+ * 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)
@@ -2184,6 +2203,9 @@ static int fbcon_switch(struct vc_data *vc)
info = registered_fb[con2fb_map[vc->vc_num]];
ops = info->fbcon_par;
+ if (bootsplash_would_render_now())
+ bootsplash_render_full(info);
+
if (softback_top) {
if (softback_lines)
fbcon_set_origin(vc);
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 18f3ac144237..45f94347fe5e 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005
+#ifdef CONFIG_BOOTSPLASH
+extern void fbcon_set_dummyops(struct fbcon_ops *ops);
+#else /* CONFIG_BOOTSPLASH */
+#define fbcon_set_dummyops(x)
+#endif /* CONFIG_BOOTSPLASH */
#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
new file mode 100644
index 000000000000..c6dd0b43180d
--- /dev/null
+++ b/include/linux/bootsplash.h
@@ -0,0 +1,43 @@
+/*
+ * Kernel based bootsplash.
+ *
+ * Authors:
+ * Max Staudt <[email protected]>
+ *
+ * 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
--
2.12.3
Unfortunately I've forgotten to rebase this patchset to 4.15, so it still builds on top of 4.14.
I'll rebase it for the next roll.
Max
On Wed, Dec 13, 2017 at 08:47:45PM +0100, Max Staudt wrote:
> Framebuffers with deferred I/O need to be flushed to the screen
> explicitly, since we use neither the mmap nor the file I/O abstractions
> that handle this for userspace FB clients.
>
> Example: xenfb
>
> Some framebuffer drivers implement lazy access to the screen without
> actually exposing a fbdefio interface - we also match some known ones,
> currently:
> - ast
> - cirrus
> - mgag200
>
> Signed-off-by: Max Staudt <[email protected]>
> Reviewed-by: Oliver Neukum <[email protected]>
> ---
> drivers/video/fbdev/core/bootsplash.c | 2 ++
> drivers/video/fbdev/core/bootsplash_internal.h | 1 +
> drivers/video/fbdev/core/bootsplash_render.c | 33 ++++++++++++++++++++++++++
> 3 files changed, 36 insertions(+)
>
> 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.
Using drm directly would allow you to flush the contents without the fake
(and tbh, really expensive on most drivers) copy op. If you insist on
using fbdev for this stuff, then at least add a new hook to flush cpu
rendering.
> + *
> + * 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")) {
We have a shared defio implementation now in drm_fb_helper.c, there's not
really many excuses to not fix up these drivers to just use those ...
-Daniel
> + struct fb_copyarea area;
> +
> + area.dx = 0;
> + area.dy = 0;
> + area.width = info->var.xres;
> + area.height = info->var.yres;
> + area.sx = 0;
> + area.sy = 0;
> +
> + info->fbops->fb_copyarea(info, &area);
> + }
> +}
> --
> 2.12.3
>
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On 12/13/2017 11:47 AM, Max Staudt wrote:
> This is the initial prototype for a lean Linux kernel bootsplash.
>
> As it is now, it will show a black screen rather than a logo, and
> only if manually enabled via the kernel cmdline:
>
> bootsplash.enable=1
Is it .enable or .enabled? (compare below)
> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index 7f1f1fbcef9e..f3ff976266fe 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
> such that other users of the framebuffer will remain normally
> oriented.
>
> +config BOOTSPLASH
> + bool "Bootup splash screen"
> + depends on FRAMEBUFFER_CONSOLE
> + ---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.
@@@@@@@@@@@@@@@@@@@@
--
~Randy
On 12/13/2017 10:35 PM, Daniel Vetter wrote:
> Using drm directly would allow you to flush the contents without the fake
> (and tbh, really expensive on most drivers) copy op. If you insist on
> using fbdev for this stuff, then at least add a new hook to flush cpu
> rendering.
My reasoning is as follows:
1) The splash screen is meant to appear as early as possible in the boot process, and even on devices that don't have a DRM driver. For example, an ARM box with only efifb. Thus, the choice to work on top of FB.
2) We need to go out of the way when a graphical application starts, and come back when it's done. fbcon already has the logic for this, and fbcon is also the thing we're trying to hide. So it seems natural to add the splash on top of fbcon - at least for now.
3) I can't use DRM from the kernel, for the same reason for which there is no "drmcon" to supplant fbcon: There is no interface to reserve framebuffer memory from kernel space: To get memory for a framebuffer, one needs to have a struct file that is passed through the DRM stack down into the drivers.
If this interface existed, then there could be a generic "fb2drm" translation layer, and we would no longer need FB compatibility code in each KMS driver. Actually, I tried to implement this translation layer a year ago, and hit too many walls.
I've prepared the code for a future in which fbdev no longer exists: My sysfs interface is generically called "bootsplash", in the hope that it will one day move on top of KMS. The hooks into fbcon are minimal and the code is straightforward to port to KMS operations rather than FB. But that's for another day, as far as I can see.
4) I don't fully understand what you'd like me to do. Last time I tried to add a new entry to the fbops struct (namely fb_open_adj_file()), you told me not to touch the framebuffer subsystem anymore, as it is meant to die and driver developers shall use KMS instead. Have I misunderstood?
Something like fb->flush() to finish kernel space accesses would be nice to have, but would need to be implemented for all affected drivers separately. The copy op hack is ugly, but solves the problem generically.
What shall I do?
Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
As far as I can see, it would be needed for defio drivers only, is that correct?
>> + *
>> + * 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")) {
>
> We have a shared defio implementation now in drm_fb_helper.c, there's not
> really many excuses to not fix up these drivers to just use those ...
I'll look into it.
Thanks!
Max
On 12/14/2017 12:55 AM, Randy Dunlap wrote:
> On 12/13/2017 11:47 AM, Max Staudt wrote:
>> This is the initial prototype for a lean Linux kernel bootsplash.
>>
>> As it is now, it will show a black screen rather than a logo, and
>> only if manually enabled via the kernel cmdline:
>>
>> bootsplash.enable=1
>
> Is it .enable or .enabled? (compare below)
Oops. It's neither, I've kicked out the option and updated the documentation, but forgot about the commit message.
Thanks!
Max
On Thu, Dec 14, 2017 at 04:36:49PM +0100, Max Staudt wrote:
> On 12/13/2017 10:35 PM, Daniel Vetter wrote:
> > Using drm directly would allow you to flush the contents without the fake
> > (and tbh, really expensive on most drivers) copy op. If you insist on
> > using fbdev for this stuff, then at least add a new hook to flush cpu
> > rendering.
>
> My reasoning is as follows:
>
> 1) The splash screen is meant to appear as early as possible in the boot
> process, and even on devices that don't have a DRM driver. For example,
> an ARM box with only efifb. Thus, the choice to work on top of FB.
>
> 2) We need to go out of the way when a graphical application starts, and
> come back when it's done. fbcon already has the logic for this, and
> fbcon is also the thing we're trying to hide. So it seems natural to add
> the splash on top of fbcon - at least for now.
And this "automatically disappear" semantics is horribly ill-defined
between fbdev and native kms. So you're not really solving a problem,
you're just not noticing the hacks because they're one layer removed (in
the fbdev emulation code).
> 3) I can't use DRM from the kernel, for the same reason for which there
> is no "drmcon" to supplant fbcon: There is no interface to reserve
> framebuffer memory from kernel space: To get memory for a framebuffer,
> one needs to have a struct file that is passed through the DRM stack
> down into the drivers.
On recent kernels you only need a struct drm_file, not a struct file. That
can be NULL. We've done this to make drmcon possible/easier.
> If this interface existed, then there could be a generic "fb2drm"
> translation layer, and we would no longer need FB compatibility code in
> each KMS driver. Actually, I tried to implement this translation layer a
> year ago, and hit too many walls.
We're pretty much there already I think. The reason it's not entirely gone
is that there's some nasty interactions between drm and the fbdev
emulation, and just having a pile of drivers that aren't too trivial to
convert.
> I've prepared the code for a future in which fbdev no longer exists: My
> sysfs interface is generically called "bootsplash", in the hope that it
> will one day move on top of KMS. The hooks into fbcon are minimal and
> the code is straightforward to port to KMS operations rather than FB.
> But that's for another day, as far as I can see.
>
> 4) I don't fully understand what you'd like me to do. Last time I tried
> to add a new entry to the fbops struct (namely fb_open_adj_file()), you
> told me not to touch the framebuffer subsystem anymore, as it is meant
> to die and driver developers shall use KMS instead. Have I
> misunderstood?
I still don't like anyone adding features to fbdev :-)
> Something like fb->flush() to finish kernel space accesses would be nice
> to have, but would need to be implemented for all affected drivers
> separately. The copy op hack is ugly, but solves the problem
> generically.
Well, with defio being the hack it is (and because of that, a bunch of drm
drivers not really supporting it) I'm not sure things actually work better
without all this.
> What shall I do?
>
> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
> As far as I can see, it would be needed for defio drivers only, is that correct?
Yes, which are kinda horrible anyway. I guess you could at least not do
all these hacks if it's not a defio driver.
-Daniel
>
>
> >> + *
> >> + * 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")) {
> >
> > We have a shared defio implementation now in drm_fb_helper.c, there's not
> > really many excuses to not fix up these drivers to just use those ...
>
> I'll look into it.
>
>
> Thanks!
> Max
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On 12/19/2017 01:23 PM, Daniel Vetter wrote:
> On Thu, Dec 14, 2017 at 04:36:49PM +0100, Max Staudt wrote:
>> 2) We need to go out of the way when a graphical application starts, and
>> come back when it's done. fbcon already has the logic for this, and
>> fbcon is also the thing we're trying to hide. So it seems natural to add
>> the splash on top of fbcon - at least for now.
>
> And this "automatically disappear" semantics is horribly ill-defined
> between fbdev and native kms. So you're not really solving a problem,
> you're just not noticing the hacks because they're one layer removed (in
> the fbdev emulation code).
That's a general complaint about fbcon and/or the fbdev emulation in KMS drivers, right?
I can't see how it relates to my bootsplash, as I'm just replacing fbcon's output, wherever fbcon desires to draw at the given moment, and in no other case.
So when a graphical application sets the VT mode to KD_GRAPHICS, we get a call to do_blank_screen(), and then fbcon -and thus the bootsplash- is muted. The ioctl API has always been like this, and it's not specific to the patch in question.
Similarly, when a graphical application allocates a framebuffer via the KMS ioctl()s, and selects it for scanout, the driver will display that instead of the framebuffer it has allocated internally for the fbdev emulation.
>> 3) I can't use DRM from the kernel, for the same reason for which there
>> is no "drmcon" to supplant fbcon: There is no interface to reserve
>> framebuffer memory from kernel space: To get memory for a framebuffer,
>> one needs to have a struct file that is passed through the DRM stack
>> down into the drivers.
>
> On recent kernels you only need a struct drm_file, not a struct file. That
> can be NULL. We've done this to make drmcon possible/easier.
Oh that's cool, I missed that. Thanks!
Maybe a fb2drm compat layer will become reality, after all.
The bootsplash code is fairly straightforward to port to a future drmcon, and I'm happy to make the changes once drmcon is available.
But for now, we only have fbcon. And a *lot* of FB drivers. And we want them to show a bootsplash instead of text. So that's where the bootsplash needs to hook into.
>> If this interface existed, then there could be a generic "fb2drm"
>> translation layer, and we would no longer need FB compatibility code in
>> each KMS driver. Actually, I tried to implement this translation layer a
>> year ago, and hit too many walls.
>
> We're pretty much there already I think. The reason it's not entirely gone
> is that there's some nasty interactions between drm and the fbdev
> emulation, and just having a pile of drivers that aren't too trivial to
> convert.
Sounds like the state of the art last year - drm_file in most cases, but struct file deep in the drivers :(
>> 4) I don't fully understand what you'd like me to do. Last time I tried
>> to add a new entry to the fbops struct (namely fb_open_adj_file()), you
>> told me not to touch the framebuffer subsystem anymore, as it is meant
>> to die and driver developers shall use KMS instead. Have I
>> misunderstood?
>
> I still don't like anyone adding features to fbdev :-)
So I must not touch fbops, correct?
>> Something like fb->flush() to finish kernel space accesses would be nice
>> to have, but would need to be implemented for all affected drivers
>> separately. The copy op hack is ugly, but solves the problem
>> generically.
>
> Well, with defio being the hack it is (and because of that, a bunch of drm
> drivers not really supporting it) I'm not sure things actually work better
> without all this.
I don't understand what you mean.
What I do know is that fb_defio is here, and it's here to stay because some drivers need it.
What I also know is that I need to flush the screen after drawing my bootsplash.
>> What shall I do?
>>
>> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
>> As far as I can see, it would be needed for defio drivers only, is that correct?
>
> Yes, which are kinda horrible anyway. I guess you could at least not do
> all these hacks if it's not a defio driver.
Again, I don't understand.
In my patch (see below), I explicitly check for info->fbdefio, as well as three known broken drmfb emulations. I don't do the copy hack on any other device.
So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
Would you like me to extend the FB API or not?
Max
> -Daniel
>
>>
>>
>>>> + *
>>>> + * 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")) {
On Tue, Dec 19, 2017 at 02:34:22PM +0100, Max Staudt wrote:
> On 12/19/2017 01:23 PM, Daniel Vetter wrote:
> > On Thu, Dec 14, 2017 at 04:36:49PM +0100, Max Staudt wrote:
> >> 2) We need to go out of the way when a graphical application starts, and
> >> come back when it's done. fbcon already has the logic for this, and
> >> fbcon is also the thing we're trying to hide. So it seems natural to add
> >> the splash on top of fbcon - at least for now.
> >
> > And this "automatically disappear" semantics is horribly ill-defined
> > between fbdev and native kms. So you're not really solving a problem,
> > you're just not noticing the hacks because they're one layer removed (in
> > the fbdev emulation code).
> That's a general complaint about fbcon and/or the fbdev emulation in KMS drivers, right?
>
> I can't see how it relates to my bootsplash, as I'm just replacing
> fbcon's output, wherever fbcon desires to draw at the given moment, and
> in no other case.
>
> So when a graphical application sets the VT mode to KD_GRAPHICS, we get
> a call to do_blank_screen(), and then fbcon -and thus the bootsplash- is
> muted. The ioctl API has always been like this, and it's not specific to
> the patch in question.
>
> Similarly, when a graphical application allocates a framebuffer via the
> KMS ioctl()s, and selects it for scanout, the driver will display that
> instead of the framebuffer it has allocated internally for the fbdev
> emulation.
>
>
> >> 3) I can't use DRM from the kernel, for the same reason for which there
> >> is no "drmcon" to supplant fbcon: There is no interface to reserve
> >> framebuffer memory from kernel space: To get memory for a framebuffer,
> >> one needs to have a struct file that is passed through the DRM stack
> >> down into the drivers.
> >
> > On recent kernels you only need a struct drm_file, not a struct file. That
> > can be NULL. We've done this to make drmcon possible/easier.
>
> Oh that's cool, I missed that. Thanks!
>
> Maybe a fb2drm compat layer will become reality, after all.
>
> The bootsplash code is fairly straightforward to port to a future drmcon, and I'm happy to make the changes once drmcon is available.
> But for now, we only have fbcon. And a *lot* of FB drivers. And we want them to show a bootsplash instead of text. So that's where the bootsplash needs to hook into.
>
>
> >> If this interface existed, then there could be a generic "fb2drm"
> >> translation layer, and we would no longer need FB compatibility code in
> >> each KMS driver. Actually, I tried to implement this translation layer a
> >> year ago, and hit too many walls.
> >
> > We're pretty much there already I think. The reason it's not entirely gone
> > is that there's some nasty interactions between drm and the fbdev
> > emulation, and just having a pile of drivers that aren't too trivial to
> > convert.
>
> Sounds like the state of the art last year - drm_file in most cases, but
> struct file deep in the drivers :(
Where do drivers deal with struct file deep down?
> >> 4) I don't fully understand what you'd like me to do. Last time I tried
> >> to add a new entry to the fbops struct (namely fb_open_adj_file()), you
> >> told me not to touch the framebuffer subsystem anymore, as it is meant
> >> to die and driver developers shall use KMS instead. Have I
> >> misunderstood?
> >
> > I still don't like anyone adding features to fbdev :-)
>
> So I must not touch fbops, correct?
The problem is that defio is totally not how a real driver works. So
preferrably bootsplash would use kms directly, and use the explict dirtyfb
callback. But if you insist on using fbdev, then I think the beast course
here is to wire up a new fb_ops->flush callback.
Note that you only need to type the 1 trivial implementation for the drm
fbdev emulation, as long as the callback is optional. Trying to make defio
work correctly, as fbdev assumes it should work, in all cases, on top of
drm is imo an entirely pointless endeavour.
> >> Something like fb->flush() to finish kernel space accesses would be nice
> >> to have, but would need to be implemented for all affected drivers
> >> separately. The copy op hack is ugly, but solves the problem
> >> generically.
> >
> > Well, with defio being the hack it is (and because of that, a bunch of drm
> > drivers not really supporting it) I'm not sure things actually work better
> > without all this.
>
> I don't understand what you mean.
>
> What I do know is that fb_defio is here, and it's here to stay because some drivers need it.
>
> What I also know is that I need to flush the screen after drawing my bootsplash.
Yes, so lets ignore defio and do the flushing correctly, at least for kms
drivers.
> >> What shall I do?
> >>
> >> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
> >> As far as I can see, it would be needed for defio drivers only, is that correct?
> >
> > Yes, which are kinda horrible anyway. I guess you could at least not do
> > all these hacks if it's not a defio driver.
>
> Again, I don't understand.
>
> In my patch (see below), I explicitly check for info->fbdefio, as well
> as three known broken drmfb emulations. I don't do the copy hack on any
> other device.
Yeah, and if we'd to the explicit flush, you wouldn't even need to check
for that. So
if (fbops->flush)
fbops->flush(); /* this covers all drm drivers */
else if (fb->defio)
copyarea hack, if you really still need to support some defio
fbdev drivers, but really I think that's questionable
else
; /* nothing */
> So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
>
> Would you like me to extend the FB API or not?
Yes. Well for real I'd like you to do kms, so maybe you need to explain
why exactly you absolutely have to use fbdev (aka which driver isn't
supported by drm that you want to enable this on).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Am Dienstag, den 19.12.2017, 14:57 +0100 schrieb Daniel Vetter:
> > Would you like me to extend the FB API or not?
>
> Yes. Well for real I'd like you to do kms, so maybe you need to explain
> why exactly you absolutely have to use fbdev (aka which driver isn't
> supported by drm that you want to enable this on).
Hi,
those would be at a minimum efifb, vesafb, xenfb
Those are obviously not sexy, but from a practical point of view
they are the minimum you need to support.
Regards
Oliver
On 12/19/2017 02:57 PM, Daniel Vetter wrote:
> Where do drivers deal with struct file deep down?
As an example, I remembered this to be the case in nouveau's code for allocating a framebuffer. So I checked, and it's much better now.
So I was mistaken about this - sorry.
Thanks a lot for cleaning up this part of DRM, I'm looking forward to a nicer future! Hopefully we can get unify the FB emulation in a single place at some point, but that's just my dreams and is going off-topic, so I'll stop here.
> The problem is that defio is totally not how a real driver works.
But they do exist and I can't ignore them.
I'm afraid I don't understand - why are those, such as xenfb, not real drivers?
> So
> preferrably bootsplash would use kms directly, and use the explict dirtyfb
> callback.
Sure, if I'd be hooking into drmcon, that would be great.
But drmcon doesn't exist yet, so it doesn't get us further to talk about a bootsplash on KMS :(
I'm hooking into the in-kernel terminal emulator, because the bootsplash is a functional extension of that. It just happens that fbcon sits on top of FB, so I work with what I get.
And the console in turn happens to work on all FB and KMS drivers, so it makes users of all kinds of drivers happy. In fact, that's why the FB emulation in KMS drivers came to be in the first place, if I remember right - to ensure fbcon continues to work.
Thus, once drmcon exists and becomes dominant over fbcon, moving the bootsplash to it makes sense. On the other hand, hooking into a raw video subsystem doesn't make sense as far as I can see, so a bootsplash on top of raw KMS is just as meaningless as a bootsplash on top of raw FB. So I have no choice but to work on top of fbcon, and thus use the FB subsystem.
> But if you insist on using fbdev, then I think the beast course
> here is to wire up a new fb_ops->flush callback.
Okay, makes sense. Thanks!
> Note that you only need to type the 1 trivial implementation for the drm
> fbdev emulation, as long as the callback is optional. Trying to make defio
> work correctly, as fbdev assumes it should work, in all cases, on top of
> drm is imo an entirely pointless endeavour.
I'll look into it.
> Yes, so lets ignore defio and do the flushing correctly, at least for kms
> drivers.
I agree.
In fact, if I define fbops->flush(), defio drivers can still add their own proper flushing function, so everybody wins. I like that, see below.
>>>> What shall I do?
>>>>
>>>> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
>>>> As far as I can see, it would be needed for defio drivers only, is that correct?
>>>
>>> Yes, which are kinda horrible anyway. I guess you could at least not do
>>> all these hacks if it's not a defio driver.
>>
>> Again, I don't understand.
>>
>> In my patch (see below), I explicitly check for info->fbdefio, as well
>> as three known broken drmfb emulations. I don't do the copy hack on any
>> other device.
>
> Yeah, and if we'd to the explicit flush, you wouldn't even need to check
> for that. So
>
> if (fbops->flush)
> fbops->flush(); /* this covers all drm drivers */
> else if (fb->defio)
> copyarea hack, if you really still need to support some defio
> fbdev drivers, but really I think that's questionable
I need to support xenfb, thus I might as well support all defio drivers.
Also, I like that your suggestion allows for affected drivers to implement their own, more efficient fbops->flush() directly, while ensuring that those that don't still have a fallback, so there is some performance to be gained.
I'll look into implementing this.
> else
> ; /* nothing */
>
>> So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
>>
>> Would you like me to extend the FB API or not?
>
> Yes. Well for real I'd like you to do kms, so maybe you need to explain
> why exactly you absolutely have to use fbdev (aka which driver isn't
> supported by drm that you want to enable this on).
See Oliver's reply - we have plenty of fb-only systems deployed in the real world. Think Xen. Think AArch64 with efifb. Think any system before the KMS driver is loaded (which is a case that the splash is supposed to handle).
Also, where would I hook into KMS, were I to implement it on top of KMS right now? I'm not working on top of FB per se, but on top of fbcon. So in a KMS world I wouldn't work on KMS itself, but on top of... drmcon, which doesn't exist.
Max
On Tue, Dec 19, 2017 at 4:41 PM, Max Staudt <[email protected]> wrote:
> On 12/19/2017 02:57 PM, Daniel Vetter wrote:
>> Where do drivers deal with struct file deep down?
>
> As an example, I remembered this to be the case in nouveau's code for allocating a framebuffer. So I checked, and it's much better now.
>
> So I was mistaken about this - sorry.
>
> Thanks a lot for cleaning up this part of DRM, I'm looking forward to a nicer future! Hopefully we can get unify the FB emulation in a single place at some point, but that's just my dreams and is going off-topic, so I'll stop here.
>
>
>> The problem is that defio is totally not how a real driver works.
>
> But they do exist and I can't ignore them.
>
> I'm afraid I don't understand - why are those, such as xenfb, not real drivers?
I mean kms drivers. The problem is that the magic mapping that fbdev
expects is real pain. Everyone else, including kms, expects an
explicit flush operation. So instead of hacking around even more with
the defio corner cases that don't work, I'm suggesting we just add
that flush operation. At least internally.
Fixing kms drivers to implement a better defio is probably not a
reasonable investement of time.
>> So
>> preferrably bootsplash would use kms directly, and use the explict dirtyfb
>> callback.
>
> Sure, if I'd be hooking into drmcon, that would be great.
>
> But drmcon doesn't exist yet, so it doesn't get us further to talk about a bootsplash on KMS :(
>
> I'm hooking into the in-kernel terminal emulator, because the bootsplash is a functional extension of that. It just happens that fbcon sits on top of FB, so I work with what I get.
Why do you need a console for a boot splash? You're not drawing
console output afaiui ... And even your current fbdev-based
implementation only interfaces with fbcon insofar as you're making
sure fbcon doesn't wreak your boot splash. Or I'm missing something
somewhere.
> And the console in turn happens to work on all FB and KMS drivers, so it makes users of all kinds of drivers happy. In fact, that's why the FB emulation in KMS drivers came to be in the first place, if I remember right - to ensure fbcon continues to work.
>
> Thus, once drmcon exists and becomes dominant over fbcon, moving the bootsplash to it makes sense. On the other hand, hooking into a raw video subsystem doesn't make sense as far as I can see, so a bootsplash on top of raw KMS is just as meaningless as a bootsplash on top of raw FB. So I have no choice but to work on top of fbcon, and thus use the FB subsystem.
>
>
>> But if you insist on using fbdev, then I think the beast course
>> here is to wire up a new fb_ops->flush callback.
>
> Okay, makes sense. Thanks!
>
>
>> Note that you only need to type the 1 trivial implementation for the drm
>> fbdev emulation, as long as the callback is optional. Trying to make defio
>> work correctly, as fbdev assumes it should work, in all cases, on top of
>> drm is imo an entirely pointless endeavour.
>
> I'll look into it.
>
>
>> Yes, so lets ignore defio and do the flushing correctly, at least for kms
>> drivers.
>
> I agree.
>
> In fact, if I define fbops->flush(), defio drivers can still add their own proper flushing function, so everybody wins. I like that, see below.
tbh I'd forget about ever touching any of the existing fbdev drivers.
Imo just not worth the time investement.
>>>>> What shall I do?
>>>>>
>>>>> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
>>>>> As far as I can see, it would be needed for defio drivers only, is that correct?
>>>>
>>>> Yes, which are kinda horrible anyway. I guess you could at least not do
>>>> all these hacks if it's not a defio driver.
>>>
>>> Again, I don't understand.
>>>
>>> In my patch (see below), I explicitly check for info->fbdefio, as well
>>> as three known broken drmfb emulations. I don't do the copy hack on any
>>> other device.
>>
>> Yeah, and if we'd to the explicit flush, you wouldn't even need to check
>> for that. So
>>
>> if (fbops->flush)
>> fbops->flush(); /* this covers all drm drivers */
>> else if (fb->defio)
>> copyarea hack, if you really still need to support some defio
>> fbdev drivers, but really I think that's questionable
>
> I need to support xenfb, thus I might as well support all defio drivers.
>
> Also, I like that your suggestion allows for affected drivers to implement their own, more efficient fbops->flush() directly, while ensuring that those that don't still have a fallback, so there is some performance to be gained.
>
> I'll look into implementing this.
>
>
>> else
>> ; /* nothing */
>>
>>> So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
>>>
>>> Would you like me to extend the FB API or not?
>>
>> Yes. Well for real I'd like you to do kms, so maybe you need to explain
>> why exactly you absolutely have to use fbdev (aka which driver isn't
>> supported by drm that you want to enable this on).
>
> See Oliver's reply - we have plenty of fb-only systems deployed in the real world. Think Xen. Think AArch64 with efifb. Think any system before the KMS driver is loaded (which is a case that the splash is supposed to handle).
And you need a real pretty boot-splash on those? That sounds all like
servers, and I haven't yet seen a request for real pretty&fast boot
splash for servers.
> Also, where would I hook into KMS, were I to implement it on top of KMS right now? I'm not working on top of FB per se, but on top of fbcon. So in a KMS world I wouldn't work on KMS itself, but on top of... drmcon, which doesn't exist.
Hm, I guess I need to double check again, but I don't get why you need
to sit on top of a console for the boot splash. I mean I understand
that you need to shut up the console when the boot splash is on, but
from a quick look you're not using fbcon to render anything or
otherwise tie into it. Where's the connection?
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
btw the reason drmcon didn't move is that David Herrmann moved on from
hacking on graphics stuff, and no one needs it. There's nothing
fundamentally wrong with his patches for a basic emergency console on
plain drm, or the simpledrm driver to get a basic drm framebuffer up
on vesafb/efifb and friends. Just wanted to bring this in since you
sound like you're expecting this to magically have happened somehow.
We don't merge code without real use-cases.
-Daniel
On Tue, Dec 19, 2017 at 4:41 PM, Max Staudt <[email protected]> wrote:
> On 12/19/2017 02:57 PM, Daniel Vetter wrote:
>> Where do drivers deal with struct file deep down?
>
> As an example, I remembered this to be the case in nouveau's code for allocating a framebuffer. So I checked, and it's much better now.
>
> So I was mistaken about this - sorry.
>
> Thanks a lot for cleaning up this part of DRM, I'm looking forward to a nicer future! Hopefully we can get unify the FB emulation in a single place at some point, but that's just my dreams and is going off-topic, so I'll stop here.
>
>
>> The problem is that defio is totally not how a real driver works.
>
> But they do exist and I can't ignore them.
>
> I'm afraid I don't understand - why are those, such as xenfb, not real drivers?
>
>
>> So
>> preferrably bootsplash would use kms directly, and use the explict dirtyfb
>> callback.
>
> Sure, if I'd be hooking into drmcon, that would be great.
>
> But drmcon doesn't exist yet, so it doesn't get us further to talk about a bootsplash on KMS :(
>
> I'm hooking into the in-kernel terminal emulator, because the bootsplash is a functional extension of that. It just happens that fbcon sits on top of FB, so I work with what I get.
>
> And the console in turn happens to work on all FB and KMS drivers, so it makes users of all kinds of drivers happy. In fact, that's why the FB emulation in KMS drivers came to be in the first place, if I remember right - to ensure fbcon continues to work.
>
> Thus, once drmcon exists and becomes dominant over fbcon, moving the bootsplash to it makes sense. On the other hand, hooking into a raw video subsystem doesn't make sense as far as I can see, so a bootsplash on top of raw KMS is just as meaningless as a bootsplash on top of raw FB. So I have no choice but to work on top of fbcon, and thus use the FB subsystem.
>
>
>> But if you insist on using fbdev, then I think the beast course
>> here is to wire up a new fb_ops->flush callback.
>
> Okay, makes sense. Thanks!
>
>
>> Note that you only need to type the 1 trivial implementation for the drm
>> fbdev emulation, as long as the callback is optional. Trying to make defio
>> work correctly, as fbdev assumes it should work, in all cases, on top of
>> drm is imo an entirely pointless endeavour.
>
> I'll look into it.
>
>
>> Yes, so lets ignore defio and do the flushing correctly, at least for kms
>> drivers.
>
> I agree.
>
> In fact, if I define fbops->flush(), defio drivers can still add their own proper flushing function, so everybody wins. I like that, see below.
>
>
>>>>> What shall I do?
>>>>>
>>>>> Shall I add a new FB op for flushing when writing to the raw memory from the kernel?
>>>>> As far as I can see, it would be needed for defio drivers only, is that correct?
>>>>
>>>> Yes, which are kinda horrible anyway. I guess you could at least not do
>>>> all these hacks if it's not a defio driver.
>>>
>>> Again, I don't understand.
>>>
>>> In my patch (see below), I explicitly check for info->fbdefio, as well
>>> as three known broken drmfb emulations. I don't do the copy hack on any
>>> other device.
>>
>> Yeah, and if we'd to the explicit flush, you wouldn't even need to check
>> for that. So
>>
>> if (fbops->flush)
>> fbops->flush(); /* this covers all drm drivers */
>> else if (fb->defio)
>> copyarea hack, if you really still need to support some defio
>> fbdev drivers, but really I think that's questionable
>
> I need to support xenfb, thus I might as well support all defio drivers.
>
> Also, I like that your suggestion allows for affected drivers to implement their own, more efficient fbops->flush() directly, while ensuring that those that don't still have a fallback, so there is some performance to be gained.
>
> I'll look into implementing this.
>
>
>> else
>> ; /* nothing */
>>
>>> So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
>>>
>>> Would you like me to extend the FB API or not?
>>
>> Yes. Well for real I'd like you to do kms, so maybe you need to explain
>> why exactly you absolutely have to use fbdev (aka which driver isn't
>> supported by drm that you want to enable this on).
>
> See Oliver's reply - we have plenty of fb-only systems deployed in the real world. Think Xen. Think AArch64 with efifb. Think any system before the KMS driver is loaded (which is a case that the splash is supposed to handle).
>
> Also, where would I hook into KMS, were I to implement it on top of KMS right now? I'm not working on top of FB per se, but on top of fbcon. So in a KMS world I wouldn't work on KMS itself, but on top of... drmcon, which doesn't exist.
>
>
>
> Max
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
On Wed, Dec 13, 2017 at 08:47:42PM +0100, Max Staudt wrote:
> Dear fbdev and fbcon developers,
>
> Thank you very much for your input for the first patch series.
>
> I've included your feedback into this second roll, and kindly ask for
> your opinion on the new patch series.
Ok I've realized that my assumptions about why you need this aren't
holding up.
So from reading these patches it sounded like you want an in-kernel boot
splash because that would be on the display faster than a userspace one
like plymouth. That's the only reasons I can see for this (if there's
another good justification, please bring it up).
I only know of very embedded setups (tv top boxes, in vehicle
entertainment) where that kind of "time to first image" really matters,
and those systems:
- have a real hw kms driver
- don't have fbcon or fbdev emulation enabled (except for some closed
source stacks that are a bit slow to adapt to the new world, and we
don't care about those in gfx).
But from discussions it sounds like you very much want to use this on
servers, which makes 0 sense to me. On a server something like plymouth
should do a perfectly reasonable job.
So, why exactly do we need this?
(let's stop the other thread meanwhile, there's no point discussing
implementation details if the why? question isn't answered yet)
Cheers, Daniel
>
>
> Changes from v1 to v2:
>
> + Added a user space tool to create splash theme files
> + Bumped the file format version:
> - Larger structs for easy future expansion
> - 2-byte corner offset
> - Offset either from corner or from center
> - Fixed padding before header->frame_ms
> + Moved bootsplash_file.h to uapi/linux
> + Merged several patches
> + Theme files are now loaded via request_firmware()
> + sysfs hook to allow loading of theme files via request_firmware()
> + Dropped the .enable cmdline option and the default file name.
> The splash will be shown as soon as a file is specified.
> + Dropped custom workqueue in favor of the kernel queue
> and cancel_delayed_work_sync()
> + Marked loaded data as const, and load/enable it atomically
> + Reduced global state by moving data into other structures
> + EXPORT_SYMBOL_GPL for fbcon_set_dummyops()
> + Atomic and barrier for splash enabled state instead of spinlock
> + Reduced warnings to infos
> + Rate limited printk
> + Changed the multi-line comment layout to kernel style
> + Simplified the file headers
> + reST-ed the documentation
>
>
>
> Max
>
>
>
>
>
> _______________________________________________
> dri-devel mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On 12/19/2017 05:02 PM, Daniel Vetter wrote:
> On Tue, Dec 19, 2017 at 4:41 PM, Max Staudt <[email protected]> wrote:
>> On 12/19/2017 02:57 PM, Daniel Vetter wrote:
>>> The problem is that defio is totally not how a real driver works.
>>
>> But they do exist and I can't ignore them.
>>
>> I'm afraid I don't understand - why are those, such as xenfb, not real drivers?
>
> I mean kms drivers. The problem is that the magic mapping that fbdev
> expects is real pain. Everyone else, including kms, expects an
> explicit flush operation. So instead of hacking around even more with
> the defio corner cases that don't work, I'm suggesting we just add
> that flush operation. At least internally.
>
> Fixing kms drivers to implement a better defio is probably not a
> reasonable investement of time.
Ah yes, I understand now, you mean that KMS drivers have explicit flush, and defio is a hack to retrofit such drivers to an API that never supported a flush operation (the fbdev API), but always used to expose the video memory directly. Right?
If yes, then I agree. Fixing the defio in the KMS drivers wouldn't even solve my problem - I'd still need to implement flush. So might as well care about the flush straight away, yep!
>>> So
>>> preferrably bootsplash would use kms directly, and use the explict dirtyfb
>>> callback.
>>
>> Sure, if I'd be hooking into drmcon, that would be great.
>>
>> But drmcon doesn't exist yet, so it doesn't get us further to talk about a bootsplash on KMS :(
>>
>> I'm hooking into the in-kernel terminal emulator, because the bootsplash is a functional extension of that. It just happens that fbcon sits on top of FB, so I work with what I get.
>
> Why do you need a console for a boot splash? You're not drawing
> console output afaiui ... And even your current fbdev-based
> implementation only interfaces with fbcon insofar as you're making
> sure fbcon doesn't wreak your boot splash. Or I'm missing something
> somewhere.
Errr... true. I'll answer it below, where you ask again.
>> In fact, if I define fbops->flush(), defio drivers can still add their own proper flushing function, so everybody wins. I like that, see below.
>
> tbh I'd forget about ever touching any of the existing fbdev drivers.
> Imo just not worth the time investement.
Fair point. It's optional anyway, and can still be done (quickly and painlessly) on demand.
Since my goal here is making a nice bootsplash, I'll touch as few drivers as I can.
>>>> So, what shall I do? As it is, the hack is already specific to devices that really, really need it.
>>>>
>>>> Would you like me to extend the FB API or not?
>>>
>>> Yes. Well for real I'd like you to do kms, so maybe you need to explain
>>> why exactly you absolutely have to use fbdev (aka which driver isn't
>>> supported by drm that you want to enable this on).
>>
>> See Oliver's reply - we have plenty of fb-only systems deployed in the real world. Think Xen. Think AArch64 with efifb. Think any system before the KMS driver is loaded (which is a case that the splash is supposed to handle).
>
> And you need a real pretty boot-splash on those? That sounds all like
> servers, and I haven't yet seen a request for real pretty&fast boot
> splash for servers.
Yeah, every little helps.
And the vesafb/efifb case is valid for all of the desktop/laptop machines as well.
>> Also, where would I hook into KMS, were I to implement it on top of KMS right now? I'm not working on top of FB per se, but on top of fbcon. So in a KMS world I wouldn't work on KMS itself, but on top of... drmcon, which doesn't exist.
>
> Hm, I guess I need to double check again, but I don't get why you need
> to sit on top of a console for the boot splash. I mean I understand
> that you need to shut up the console when the boot splash is on, but
> from a quick look you're not using fbcon to render anything or
> otherwise tie into it. Where's the connection?
Fair point.
So the case you're looking at is someone who wants to have a bootsplash, yet doesn't want to have fbcon. Correct?
I agree, this is a case that is not covered with the current code. However such a generic solution would require the definition of new semantics of both fbcon and the bootsplash fighting for the same FB device - well, as long as no graphical application uses it. Urgh... It is a lot simpler to just dual-purpose fbcon, since it knows when to shut up on its own.
And I simply assume that those who load a bootsplash file into their initramfs won't be short a few bytes to compile in fbcon as well.
So... I've hooked into fbcon for simplicity's sake, so I don't have up to three parties fighting for the same device, and so I don't have to define semantics and interfaces to solve that conflict.
Max
On 12/19/2017 05:09 PM, Daniel Vetter wrote:
> btw the reason drmcon didn't move is that David Herrmann moved on from
> hacking on graphics stuff, and no one needs it. There's nothing
> fundamentally wrong with his patches for a basic emergency console on
> plain drm, or the simpledrm driver to get a basic drm framebuffer up
> on vesafb/efifb and friends. Just wanted to bring this in since you
> sound like you're expecting this to magically have happened somehow.
> We don't merge code without real use-cases.
Don't worry, I'm not expecting this to have magically happened. It will happen when it will happen, or maybe never.
I'm just working with that I've got right now, and once a successor to fbcon takes it's throne, I'm very happy to help move the bootsplash over.
Max
On 12/19/2017 05:16 PM, Daniel Vetter wrote:
> On Wed, Dec 13, 2017 at 08:47:42PM +0100, Max Staudt wrote:
>> Dear fbdev and fbcon developers,
>>
>> Thank you very much for your input for the first patch series.
>>
>> I've included your feedback into this second roll, and kindly ask for
>> your opinion on the new patch series.
>
> Ok I've realized that my assumptions about why you need this aren't
> holding up.
>
> So from reading these patches it sounded like you want an in-kernel boot
> splash because that would be on the display faster than a userspace one
> like plymouth. That's the only reasons I can see for this (if there's
> another good justification, please bring it up).
Yep, that's one of the reasons.
You can find a lot more in the commit message for my first patch.
For example, having a userspace splash that starts as early as it can (thus on vesafb/efifb on a PC) will cause the KMS driver to fail reserving the entirety of video RAM, and thus fail loading. This cannot be fixed.
Reproducer: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
Furthermore, Plymouth is quite broken. For example, it may lock (via VT_SETMODE) the VT even though Plymouth is in "disabled" state and X has already taken control of the VT. This causes the kernel to throw away X's PID as the VT owner, and thus chvt and Ctrl-Alt-Fx no longer work because X can neither release the console (VT_RELDISP fails), nor does the kernel send it the signal to do so. This is hard to impossible to fix.
A third reason is that in practice, Plymouth's start is delayed for reasons such as the above. Yes, race conditions are being worked around with sleeps. It'd be nice to have a splash as early as possible, without having to worry about races.
So some issues are hard to fix, others are impossible to fix in userspace. I figured that rather than hacking back and forth and defining APIs in both the kernel and userspace (redoing a sizable part of Plymouth, or writing a replacement), I might as well put small and simple code in the kernel straight away.
And if it's hooked into fbcon, we get stuff for free:
- It shows *really* early, even before userland is available.
- There are no fights, no races for the device. Of any kind.
- The code is small and simple.
Further reasoning so far, from the comments to my v1 patch series:
https://lkml.org/lkml/2017/11/10/374
https://lkml.org/lkml/2017/11/9/324
> I only know of very embedded setups (tv top boxes, in vehicle
> entertainment) where that kind of "time to first image" really matters,
> and those systems:
> - have a real hw kms driver
> - don't have fbcon or fbdev emulation enabled (except for some closed
> source stacks that are a bit slow to adapt to the new world, and we
> don't care about those in gfx).
Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
> But from discussions it sounds like you very much want to use this on
> servers, which makes 0 sense to me. On a server something like plymouth
> should do a perfectly reasonable job.
As I said in the other thread, every little helps.
For example, even on a server, a nice bootsplash makes a Linux system more attractive to novice users.
On desktops, it's basically mandatory, as users seem to be scared of text scrolling by.
> So, why exactly do we need this?
For the aforementioned reasons, and to have a nice, unified bootsplash code on *all* devices.
> (let's stop the other thread meanwhile, there's no point discussing
> implementation details if the why? question isn't answered yet)
Sure, I hope this helps.
Max
On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
> On 12/19/2017 05:16 PM, Daniel Vetter wrote:
>> On Wed, Dec 13, 2017 at 08:47:42PM +0100, Max Staudt wrote:
>>> Dear fbdev and fbcon developers,
>>>
>>> Thank you very much for your input for the first patch series.
>>>
>>> I've included your feedback into this second roll, and kindly ask for
>>> your opinion on the new patch series.
>>
>> Ok I've realized that my assumptions about why you need this aren't
>> holding up.
>>
>> So from reading these patches it sounded like you want an in-kernel boot
>> splash because that would be on the display faster than a userspace one
>> like plymouth. That's the only reasons I can see for this (if there's
>> another good justification, please bring it up).
>
> Yep, that's one of the reasons.
>
> You can find a lot more in the commit message for my first patch.
>
>
> For example, having a userspace splash that starts as early as it can (thus on vesafb/efifb on a PC) will cause the KMS driver to fail reserving the entirety of video RAM, and thus fail loading. This cannot be fixed.
>
> Reproducer: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
Aka fbdev is broken and can't actually be hotunplugged.
> Furthermore, Plymouth is quite broken. For example, it may lock (via VT_SETMODE) the VT even though Plymouth is in "disabled" state and X has already taken control of the VT. This causes the kernel to throw away X's PID as the VT owner, and thus chvt and Ctrl-Alt-Fx no longer work because X can neither release the console (VT_RELDISP fails), nor does the kernel send it the signal to do so. This is hard to impossible to fix.
Aka plymouth is broken.
> A third reason is that in practice, Plymouth's start is delayed for reasons such as the above. Yes, race conditions are being worked around with sleeps. It'd be nice to have a splash as early as possible, without having to worry about races.
Aka more breakage.
> So some issues are hard to fix, others are impossible to fix in userspace. I figured that rather than hacking back and forth and defining APIs in both the kernel and userspace (redoing a sizable part of Plymouth, or writing a replacement), I might as well put small and simple code in the kernel straight away.
>
> And if it's hooked into fbcon, we get stuff for free:
> - It shows *really* early, even before userland is available.
> - There are no fights, no races for the device. Of any kind.
> - The code is small and simple.
>
>
> Further reasoning so far, from the comments to my v1 patch series:
>
> https://lkml.org/lkml/2017/11/10/374
> https://lkml.org/lkml/2017/11/9/324
>
>
>> I only know of very embedded setups (tv top boxes, in vehicle
>> entertainment) where that kind of "time to first image" really matters,
>> and those systems:
>> - have a real hw kms driver
>> - don't have fbcon or fbdev emulation enabled (except for some closed
>> source stacks that are a bit slow to adapt to the new world, and we
>> don't care about those in gfx).
>
> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
It's too big, and those folks tend to be super picky about space.
>> But from discussions it sounds like you very much want to use this on
>> servers, which makes 0 sense to me. On a server something like plymouth
>> should do a perfectly reasonable job.
>
> As I said in the other thread, every little helps.
>
> For example, even on a server, a nice bootsplash makes a Linux system more attractive to novice users.
>
> On desktops, it's basically mandatory, as users seem to be scared of text scrolling by.
>
>
>> So, why exactly do we need this?
>
> For the aforementioned reasons, and to have a nice, unified bootsplash code on *all* devices.
>
>
>> (let's stop the other thread meanwhile, there's no point discussing
>> implementation details if the why? question isn't answered yet)
>
> Sure, I hope this helps.
So essentially you're telling me that on a current general purpose
distro the gfx driver loading is a dumpster fire, and we're fixing
this by ignoring it an adding a hole new layer on top. That doesn't
sound like any kind of good idea to me.
So if just using drm for everything isn't possible (since drm drivers
can at least in theory be hotunplugged), can we at least fix the
existing fbdev kernel bugs? Not being able to unplug a drm driver when
it's still open sounds like a rather serious issues that probably
should be fixed anyway ... so we're better able to hotunplug an fbdev
driver when it's in use.
Also I'm not clear at all on the "papering over races with sleeps"
part. DRM drivers shouldn't be racy when getting loaded ...
Or we get simpledrm merged (for efifb and vesafb support) and someone
types the xendrm driver (there is floating around, it's just old) and
we could forget about any real fbdev drivers except the drm based
ones.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
On 12/19/2017 06:26 PM, Daniel Vetter wrote:
> On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
>> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
>
> It's too big, and those folks tend to be super picky about space.
I know, they really are.
However, given just how big and clunky modern systems have become, I raise my doubts about a few extra KB for fbcon code to be relevant.
My feeling is that the kernel splash probably saves even more space on the userspace side than it adds on the kernel side, thus netting a reduction in overall code size.
> So essentially you're telling me that on a current general purpose
> distro the gfx driver loading is a dumpster fire, and we're fixing
> this by ignoring it an adding a hole new layer on top. That doesn't
> sound like any kind of good idea to me.
Yes. It is a vast improvement over the status quo, and people are asking for it. And the bootsplash layer can be moved elsewhere, just change the hooks and keep the loading/rendering.
Also, gfx driver loading isn't a dumpster fire, it mostly just works. It just mustn't be done 100% carelessly.
> So if just using drm for everything isn't possible (since drm drivers
> can at least in theory be hotunplugged), can we at least fix the
> existing fbdev kernel bugs? Not being able to unplug a drm driver when
> it's still open sounds like a rather serious issues that probably
> should be fixed anyway ... so we're better able to hotunplug an fbdev
> driver when it's in use.
I don't see it as a bug. The fbdev driver gets unloaded as much as possible, but as long as a userspace application keeps the address_space mmap()ed, there's nothing we can do, short of forcibly removing it and segfaulting the process the next time it tries to render something. Am I missing something?
> Also I'm not clear at all on the "papering over races with sleeps"
> part. DRM drivers shouldn't be racy when getting loaded ...
The DRM driver loading isn't racy, but the fbdev can't be fully unloaded while Plymouth has the address_space mmap()ed. If Plymouth sleeps until drivers that are included in initramfs are (hopefully) loaded, then it will forego using its FB backend.
A solution we've experimented with is dropping the FB backend from Plymouth. It instantly fixed the busy video RAM bug. However it made the folks relying on efifb very, very unhappy.
> Or we get simpledrm merged (for efifb and vesafb support) and someone
> types the xendrm driver (there is floating around, it's just old) and
> we could forget about any real fbdev drivers except the drm based
> ones.
And drmcon, unless we come up with a better idea than hooking into the *con driver.
Sure, that'd help a lot. But what do we do until then?
Max
Hi,
> For example, having a userspace splash that starts as early as it can
> (thus on vesafb/efifb on a PC) will cause the KMS driver to fail
> reserving the entirety of video RAM, and thus fail loading. This cannot be fixed.
well the fix there is to use drm devices... like this:
https://cgit.freedesktop.org/plymouth/commit/?id=97f02ee959374afb1b8a78dc67116cd880cf2d23
> Furthermore, Plymouth is quite broken. For example, it may lock
> (via VT_SETMODE) the VT even though Plymouth is in "disabled"
> state and X has already taken control of the VT.
What do you mean by "disabled" (plymouth.enable=0?) ? if it's
disabled, it's not going to call VT_SETMODE ...
Why do you refer to VT_SETMODE as locking ? VT_SETMODE sets
whether a process handles VT changes or the kernel does. There is a
long standing kernel issue where a mode of VT_AUTO (kernel handles
vt switching) + KDGRAPHICS means VTs can't be changed. is that what
you're talking about?
Anyway plymouth is only going to step on X's toes, if the distro erroneously
asks it to. Normally, a distro would run "plymouth deactivate" before
starting X, instead of trying to run them at the same time...
> This causes the kernel to throw away X's PID as the VT owner, and thus
> chvt and Ctrl-Alt-Fx no longer work because X can neither release the
> console (VT_RELDISP fails), nor does the kernel send it the signal to do
> so. This is hard to impossible to fix.
Unless i'm missing something, this is totally just a problem with startup
scripts not doing the right thing? Plymouth shouldn't be doing anything
once X is started. If it is, that's either a plymouth bug (or more likely a
distro integration problem)
> A third reason is that in practice, Plymouth's start is delayed for reasons
> such as the above. Yes, race conditions are being worked around with
> sleeps.
??? that's not true. We don't have any sleep statements in the code to work
around race conditions with X.
We do have two configurable delays in the code, are you talking about one of
them?
1) The first is a ShowDelay option. The point of this option is,
"If boot takes 5 seconds or less, it's essentially instant and we
shouldn't show a splash at all". Nothing to do with race conditions.
You can set it to 0 if you want.
2) The second is DeviceTimeout option. The point of this option is to
decide how long to wait for udev coldplug to finish. It's mostly
relevant for systems that don't have kms drivers. The point is at
somepoint during boot we need to decide to stop waiting for a drm
device to show up and just fallback to showing graphics using
legacy interfaces (like /dev/fb). We used to wait until the udev
queue went empty, but that's error prone since it gets cleared when
the root is switched. See
https://lists.freedesktop.org/archives/systemd-devel/2015-March/029184.html
> So some issues are hard to fix, others are impossible to fix in userspace.
I'm not convinced there are any insurmountable problems here...
One thing i'd like to do is change boot to not map fbcon at first, and
only map it in on the fly when the user hits escape, or after boot
finishes. like, for instance, try booting with fbcon=vc:2 or
fbcon=map:9 to see how it improves the boot experience.
--Ray
Hi,
On Tue, Dec 19, 2017 at 10:41 AM, Max Staudt <[email protected]> wrote:
> I'm hooking into the in-kernel terminal emulator, because the bootsplash is a
> functional extension of that. It just happens that fbcon sits on top of FB, so I
> work with what I get.
>
> And the console in turn happens to work on all FB and KMS drivers, so it
> makes users of all kinds of drivers happy. In fact, that's why the FB emulation
> in KMS drivers came to be in the first place, if I remember right - to ensure
> fbcon continues to work.
But what about multi-monitor? what about hidpi screens? Ideally you want
each monitor to show the splash in a way that best fits that monitor.
You can't do that if you're drawing all over fbcon... and it's not like multiple
monitors and 4k screens are niche these days.
--Ray
On Tue, Dec 19, 2017 at 07:40:12PM +0100, Max Staudt wrote:
> On 12/19/2017 06:26 PM, Daniel Vetter wrote:
> > On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
> >> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
> >
> > It's too big, and those folks tend to be super picky about space.
>
> I know, they really are.
>
> However, given just how big and clunky modern systems have become, I
> raise my doubts about a few extra KB for fbcon code to be relevant.
>
> My feeling is that the kernel splash probably saves even more space on
> the userspace side than it adds on the kernel side, thus netting a
> reduction in overall code size.
>
>
> > So essentially you're telling me that on a current general purpose
> > distro the gfx driver loading is a dumpster fire, and we're fixing
> > this by ignoring it an adding a hole new layer on top. That doesn't
> > sound like any kind of good idea to me.
>
> Yes. It is a vast improvement over the status quo, and people are asking
> for it. And the bootsplash layer can be moved elsewhere, just change the
> hooks and keep the loading/rendering.
>
> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It
> just mustn't be done 100% carelessly.
You've talked about using sleep and stuff to paper over races. That
doesn't sound good at all.
> > So if just using drm for everything isn't possible (since drm drivers
> > can at least in theory be hotunplugged), can we at least fix the
> > existing fbdev kernel bugs? Not being able to unplug a drm driver when
> > it's still open sounds like a rather serious issues that probably
> > should be fixed anyway ... so we're better able to hotunplug an fbdev
> > driver when it's in use.
>
> I don't see it as a bug. The fbdev driver gets unloaded as much as
> possible, but as long as a userspace application keeps the address_space
> mmap()ed, there's nothing we can do, short of forcibly removing it and
> segfaulting the process the next time it tries to render something. Am I
> missing something?
I guess you could remap that too ... But yeah SIGBUS ftw. Wrap rendering
in a sighandler and abort if you hit that. In drm we try to be a bit
better and keep things around until userspace has gone.
> > Also I'm not clear at all on the "papering over races with sleeps"
> > part. DRM drivers shouldn't be racy when getting loaded ...
>
> The DRM driver loading isn't racy, but the fbdev can't be fully unloaded
> while Plymouth has the address_space mmap()ed. If Plymouth sleeps until
> drivers that are included in initramfs are (hopefully) loaded, then it
> will forego using its FB backend.
>
> A solution we've experimented with is dropping the FB backend from
> Plymouth. It instantly fixed the busy video RAM bug. However it made the
> folks relying on efifb very, very unhappy.
>
>
> > Or we get simpledrm merged (for efifb and vesafb support) and someone
> > types the xendrm driver (there is floating around, it's just old) and
> > we could forget about any real fbdev drivers except the drm based
> > ones.
>
> And drmcon, unless we come up with a better idea than hooking into the *con driver.
If we have everything as drm drivers, you can just use plymouth (with no
fbdev backend ofc) and everyone is happy. Including the efifb folks (it's
simply going to be called efidrmfb or something like that). So no idea why
you need a *con.
> Sure, that'd help a lot. But what do we do until then?
Make it happen? Twiddling thumbs is an option too ofc, but it tends to not
result in results :-)
Cheers, Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On Tue, Dec 19, 2017 at 05:23:52PM +0100, Max Staudt wrote:
> On 12/19/2017 05:02 PM, Daniel Vetter wrote:
> > On Tue, Dec 19, 2017 at 4:41 PM, Max Staudt <[email protected]> wrote:
> >> On 12/19/2017 02:57 PM, Daniel Vetter wrote:
> >>> The problem is that defio is totally not how a real driver works.
> >>
> >> But they do exist and I can't ignore them.
> >>
> >> I'm afraid I don't understand - why are those, such as xenfb, not real drivers?
> >
> > I mean kms drivers. The problem is that the magic mapping that fbdev
> > expects is real pain. Everyone else, including kms, expects an
> > explicit flush operation. So instead of hacking around even more with
> > the defio corner cases that don't work, I'm suggesting we just add
> > that flush operation. At least internally.
> >
> > Fixing kms drivers to implement a better defio is probably not a
> > reasonable investement of time.
>
> Ah yes, I understand now, you mean that KMS drivers have explicit flush,
> and defio is a hack to retrofit such drivers to an API that never
> supported a flush operation (the fbdev API), but always used to expose
> the video memory directly. Right?
>
> If yes, then I agree. Fixing the defio in the KMS drivers wouldn't even
> solve my problem - I'd still need to implement flush. So might as well
> care about the flush straight away, yep!
Yup.
I'll leave the more fundamental discussion to the other thread on the
cover letter.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On 20/12/2017 10:43, Daniel Vetter wrote:
> On Tue, Dec 19, 2017 at 07:40:12PM +0100, Max Staudt wrote:
>> On 12/19/2017 06:26 PM, Daniel Vetter wrote:
>>> On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
>>>> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
>>>
>>> It's too big, and those folks tend to be super picky about space.
>>
>> I know, they really are.
>>
>> However, given just how big and clunky modern systems have become, I
>> raise my doubts about a few extra KB for fbcon code to be relevant.
>>
>> My feeling is that the kernel splash probably saves even more space on
>> the userspace side than it adds on the kernel side, thus netting a
>> reduction in overall code size.
>>
>>
>>> So essentially you're telling me that on a current general purpose
>>> distro the gfx driver loading is a dumpster fire, and we're fixing
>>> this by ignoring it an adding a hole new layer on top. That doesn't
>>> sound like any kind of good idea to me.
>>
>> Yes. It is a vast improvement over the status quo, and people are asking
>> for it. And the bootsplash layer can be moved elsewhere, just change the
>> hooks and keep the loading/rendering.
>>
>> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It
>> just mustn't be done 100% carelessly.
>
> You've talked about using sleep and stuff to paper over races. That
> doesn't sound good at all.
>
>>> So if just using drm for everything isn't possible (since drm drivers
>>> can at least in theory be hotunplugged), can we at least fix the
>>> existing fbdev kernel bugs? Not being able to unplug a drm driver when
>>> it's still open sounds like a rather serious issues that probably
>>> should be fixed anyway ... so we're better able to hotunplug an fbdev
>>> driver when it's in use.
>>
>> I don't see it as a bug. The fbdev driver gets unloaded as much as
>> possible, but as long as a userspace application keeps the address_space
>> mmap()ed, there's nothing we can do, short of forcibly removing it and
>> segfaulting the process the next time it tries to render something. Am I
>> missing something?
>
> I guess you could remap that too ... But yeah SIGBUS ftw. Wrap rendering
> in a sighandler and abort if you hit that. In drm we try to be a bit
> better and keep things around until userspace has gone.
>
>>> Also I'm not clear at all on the "papering over races with sleeps"
>>> part. DRM drivers shouldn't be racy when getting loaded ...
>>
>> The DRM driver loading isn't racy, but the fbdev can't be fully unloaded
>> while Plymouth has the address_space mmap()ed. If Plymouth sleeps until
>> drivers that are included in initramfs are (hopefully) loaded, then it
>> will forego using its FB backend.
>>
>> A solution we've experimented with is dropping the FB backend from
>> Plymouth. It instantly fixed the busy video RAM bug. However it made the
>> folks relying on efifb very, very unhappy.
>>
>>
>>> Or we get simpledrm merged (for efifb and vesafb support) and someone
>>> types the xendrm driver (there is floating around, it's just old) and
>>> we could forget about any real fbdev drivers except the drm based
>>> ones.
>>
>> And drmcon, unless we come up with a better idea than hooking into the *con driver.
>
> If we have everything as drm drivers, you can just use plymouth (with no
> fbdev backend ofc) and everyone is happy. Including the efifb folks (it's
> simply going to be called efidrmfb or something like that). So no idea why
> you need a *con.
>
>> Sure, that'd help a lot. But what do we do until then?
>
> Make it happen? Twiddling thumbs is an option too ofc, but it tends to not
> result in results :-)
>
> Cheers, Daniel
>
My 2cents about this patchset:
You did a good job about all the animation and splash logic, but for me all this fbcon
stuff is a huge hack, please use a standard and modern display subsystem en leave fbcon
die alone....
My DRM ARM systems would love to have such bootsplash, so please, make it happen using DRM
then leave the fbcon based stuff like efifb migrate to DRM in a second time !
Neil
On Wed, Dec 20, 2017 at 11:06:34AM +0100, Neil Armstrong wrote:
> On 20/12/2017 10:43, Daniel Vetter wrote:
> > On Tue, Dec 19, 2017 at 07:40:12PM +0100, Max Staudt wrote:
> >> On 12/19/2017 06:26 PM, Daniel Vetter wrote:
> >>> On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
> >>>> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
> >>>
> >>> It's too big, and those folks tend to be super picky about space.
> >>
> >> I know, they really are.
> >>
> >> However, given just how big and clunky modern systems have become, I
> >> raise my doubts about a few extra KB for fbcon code to be relevant.
> >>
> >> My feeling is that the kernel splash probably saves even more space on
> >> the userspace side than it adds on the kernel side, thus netting a
> >> reduction in overall code size.
> >>
> >>
> >>> So essentially you're telling me that on a current general purpose
> >>> distro the gfx driver loading is a dumpster fire, and we're fixing
> >>> this by ignoring it an adding a hole new layer on top. That doesn't
> >>> sound like any kind of good idea to me.
> >>
> >> Yes. It is a vast improvement over the status quo, and people are asking
> >> for it. And the bootsplash layer can be moved elsewhere, just change the
> >> hooks and keep the loading/rendering.
> >>
> >> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It
> >> just mustn't be done 100% carelessly.
> >
> > You've talked about using sleep and stuff to paper over races. That
> > doesn't sound good at all.
> >
> >>> So if just using drm for everything isn't possible (since drm drivers
> >>> can at least in theory be hotunplugged), can we at least fix the
> >>> existing fbdev kernel bugs? Not being able to unplug a drm driver when
> >>> it's still open sounds like a rather serious issues that probably
> >>> should be fixed anyway ... so we're better able to hotunplug an fbdev
> >>> driver when it's in use.
> >>
> >> I don't see it as a bug. The fbdev driver gets unloaded as much as
> >> possible, but as long as a userspace application keeps the address_space
> >> mmap()ed, there's nothing we can do, short of forcibly removing it and
> >> segfaulting the process the next time it tries to render something. Am I
> >> missing something?
> >
> > I guess you could remap that too ... But yeah SIGBUS ftw. Wrap rendering
> > in a sighandler and abort if you hit that. In drm we try to be a bit
> > better and keep things around until userspace has gone.
> >
> >>> Also I'm not clear at all on the "papering over races with sleeps"
> >>> part. DRM drivers shouldn't be racy when getting loaded ...
> >>
> >> The DRM driver loading isn't racy, but the fbdev can't be fully unloaded
> >> while Plymouth has the address_space mmap()ed. If Plymouth sleeps until
> >> drivers that are included in initramfs are (hopefully) loaded, then it
> >> will forego using its FB backend.
> >>
> >> A solution we've experimented with is dropping the FB backend from
> >> Plymouth. It instantly fixed the busy video RAM bug. However it made the
> >> folks relying on efifb very, very unhappy.
> >>
> >>
> >>> Or we get simpledrm merged (for efifb and vesafb support) and someone
> >>> types the xendrm driver (there is floating around, it's just old) and
> >>> we could forget about any real fbdev drivers except the drm based
> >>> ones.
> >>
> >> And drmcon, unless we come up with a better idea than hooking into the *con driver.
> >
> > If we have everything as drm drivers, you can just use plymouth (with no
> > fbdev backend ofc) and everyone is happy. Including the efifb folks (it's
> > simply going to be called efidrmfb or something like that). So no idea why
> > you need a *con.
> >
> >> Sure, that'd help a lot. But what do we do until then?
> >
> > Make it happen? Twiddling thumbs is an option too ofc, but it tends to not
> > result in results :-)
> >
> > Cheers, Daniel
> >
>
> My 2cents about this patchset:
> You did a good job about all the animation and splash logic, but for me all this fbcon
> stuff is a huge hack, please use a standard and modern display subsystem en leave fbcon
> die alone....
>
> My DRM ARM systems would love to have such bootsplash, so please, make it happen using DRM
> then leave the fbcon based stuff like efifb migrate to DRM in a second time !
btw since I'm probably sounding a bit too grumpy here: I'd very much
support this. I think bootsplash in kernel has a bunch of uses, and it
shouldn't be hard to get non-suse people to cheer for it (makes merging
easier if it's not just a one-off hack).
But I'm really not sold on the current integration path being anywhere
near close to a good idea long-term.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On Tue, Dec 19, 2017 at 05:16:30PM +0100, Daniel Vetter wrote:
> Ok I've realized that my assumptions about why you need this aren't
> holding up.
>
> So from reading these patches it sounded like you want an in-kernel boot
> splash because that would be on the display faster than a userspace one
> like plymouth. That's the only reasons I can see for this (if there's
> another good justification, please bring it up).
>
> I only know of very embedded setups (tv top boxes, in vehicle
> entertainment) where that kind of "time to first image" really matters,
> and those systems:
> - have a real hw kms driver
> - don't have fbcon or fbdev emulation enabled (except for some closed
> source stacks that are a bit slow to adapt to the new world, and we
> don't care about those in gfx).
>
> But from discussions it sounds like you very much want to use this on
> servers, which makes 0 sense to me. On a server something like plymouth
> should do a perfectly reasonable job.
For _one_ reason we'd like to see this is (I was one of the requesters of this
implementation), plymouth in it's infinite wisdom also grabs the serial (IPMI)
console and escape characters in a screen log are (you can think of the rest
of this sentence yourself I think).
Also plymouth grabs the escape character of HPE iLOs, which is a serious
no-go.
But for several other reasons we can't disable $BOOTSPLASH_IMPLEMENTATION as
we're shipping a general purpose distro and don't know on what hardware it
will be installed.
This is only my peronal view on this situation.
Byte,
Johannes
--
Johannes Thumshirn Storage
[email protected] +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
Hi Johannes,
On 20 December 2017 at 11:08, Johannes Thumshirn <[email protected]> wrote:
> On Tue, Dec 19, 2017 at 05:16:30PM +0100, Daniel Vetter wrote:
>> Ok I've realized that my assumptions about why you need this aren't
>> So from reading these patches it sounded like you want an in-kernel boot
>> splash because that would be on the display faster than a userspace one
>> like plymouth. That's the only reasons I can see for this (if there's
>> another good justification, please bring it up).
>>
>> I only know of very embedded setups (tv top boxes, in vehicle
>> entertainment) where that kind of "time to first image" really matters,
>> and those systems:
>> - have a real hw kms driver
>> - don't have fbcon or fbdev emulation enabled (except for some closed
>> source stacks that are a bit slow to adapt to the new world, and we
>> don't care about those in gfx).
>>
>> But from discussions it sounds like you very much want to use this on
>> servers, which makes 0 sense to me. On a server something like plymouth
>> should do a perfectly reasonable job.
>
> For _one_ reason we'd like to see this is (I was one of the requesters of this
> implementation), plymouth in it's infinite wisdom also grabs the serial (IPMI)
> console and escape characters in a screen log are (you can think of the rest
> of this sentence yourself I think).
You can set 'plymouth.ignore-serial-consoles' on your boot line to
disable this behaviour.
> Also plymouth grabs the escape character of HPE iLOs, which is a serious
> no-go.
I'm not entirely sure what this means, but maybe it's best addressed
as a bug report to the Plymouth developers? One of them is in this
thread.
Cheers,
Daniel
On Wed, Dec 20, 2017 at 11:22:36AM +0000, Daniel Stone wrote:
> > Also plymouth grabs the escape character of HPE iLOs, which is a serious
> > no-go.
>
> I'm not entirely sure what this means, but maybe it's best addressed
> as a bug report to the Plymouth developers? One of them is in this
> thread.
Some server BMCs do have a serial port emulation which can be reached via ssh
(apart from IPMI, etc...). HPE's particular implementaion has it's escape
character bound to the Escape key. So with plymouth running, i.e. because your boot
hangs, which for me working on block, scsi and friends happens at least once a
week results in physically power cycling the machine as I can't exit the
serial emulation and go back to the BMCs shell. I don't care too much as I'm
just a developer and used to power cycle test machines, but I do care about
the customer experience in this case.
To me it looks like the plymouth folks have a slight disconnect from the
server, or non-desktop world. We've already experienced this pattern in the
world of init systems.
Byte,
Johannes
--
Johannes Thumshirn Storage
[email protected] +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
On 12/19/2017 09:30 PM, Ray Strode wrote:
> Hi,
>
>> For example, having a userspace splash that starts as early as it can
>> (thus on vesafb/efifb on a PC) will cause the KMS driver to fail
>> reserving the entirety of video RAM, and thus fail loading. This cannot be fixed.
> well the fix there is to use drm devices... like this:
>
> https://cgit.freedesktop.org/plymouth/commit/?id=97f02ee959374afb1b8a78dc67116cd880cf2d23
Sorry, you're confusing things. Please re-read the v1 cover letter, the commit message for patch 1, and the associated discussions.
There is also a bug report where I've described what happens - I think it clarifies the situation a lot:
https://bugzilla.opensuse.org/show_bug.cgi?id=980750
To summarise: What you mean is for Plymouth to ignore FB devices when they have equivalent DRM devices. And yes, Plymouth does that just fine.
The problem that I am stumbling upon is different:
- the system starts with an FB driver
- after the ShowDelay time, Plymouth opens /dev/fb0
- the system finally loads the DRM driver, which tries to kick the previous FB driver
- loading the DRM driver fails because Plymouth still has the previous /dev/fb0 open
It's a wholly different issue.
>> Furthermore, Plymouth is quite broken. For example, it may lock
>> (via VT_SETMODE) the VT even though Plymouth is in "disabled"
>> state and X has already taken control of the VT.
> What do you mean by "disabled" (plymouth.enable=0?) ? if it's
> disabled, it's not going to call VT_SETMODE ...
1. System boots
2. Plymouth starts and grabs some displays
3. gdm starts and runs /usr/bin/plymouth deactivate
4. X server grabs VT
5. udev queue is empty
6. Plymouth thinks that coldplugging has finished, and grabs remaining displays
7. <this is where Plymouth calls VT_SETMODE even though it's deactivated>
8. gdm runs /usr/bin/plymouth quit --retain-splash
> Why do you refer to VT_SETMODE as locking ?
It's not a lock in the concurrency sense, sure.
If you have a better way of calling it, I'd be glad to learn.
Maybe "grabbing the VT", "taking ownership of the VT", ...?
> VT_SETMODE sets
> whether a process handles VT changes or the kernel does. There is a
> long standing kernel issue where a mode of VT_AUTO (kernel handles
> vt switching) + KDGRAPHICS means VTs can't be changed. is that what
> you're talking about?
No, that's not what I mean. I've inserted printk()s in the kernel, and I've seen the X server's PID being thrown out when Plymouth calls VT_SETMODE. Once this happens, the kernel can no longer tell X to release the display.
The VT_SETMODE API is meant to be used by a single user at a time, not by two concurrently. It was built in a time when it was assumed that nobody other than the X server would use it.
> Anyway plymouth is only going to step on X's toes, if the distro erroneously
> asks it to. Normally, a distro would run "plymouth deactivate" before
> starting X, instead of trying to run them at the same time...
That's what gdm, sddm, etc. do.
And then, if something causes Plymouth to sense a new device (such as Plymouth thinking that udev coldplug is complete), it will open the device, and as part of that, call VT_SETMODE. This is unexpected, since "plymouth deactivate" should keep it from doing this. And Plymouth's code architecture is such that this bug is hard to fix.
This is accurate as of about one year ago. I haven't looked into it since, but have decided to write a kernel-based replacement to simplify things and to show a splash as early as possible. It just avoids all of this complexity.
>> This causes the kernel to throw away X's PID as the VT owner, and thus
>> chvt and Ctrl-Alt-Fx no longer work because X can neither release the
>> console (VT_RELDISP fails), nor does the kernel send it the signal to do
>> so. This is hard to impossible to fix.
> Unless i'm missing something, this is totally just a problem with startup
> scripts not doing the right thing? Plymouth shouldn't be doing anything
> once X is started. If it is, that's either a plymouth bug (or more likely a
> distro integration problem)
It is a Plymouth bug, see above.
>> A third reason is that in practice, Plymouth's start is delayed for reasons
>> such as the above. Yes, race conditions are being worked around with
>> sleeps.
> ??? that's not true. We don't have any sleep statements in the code to work
> around race conditions with X.
>
> We do have two configurable delays in the code, are you talking about one of
> them?
>
> 1) The first is a ShowDelay option. The point of this option is,
> "If boot takes 5 seconds or less, it's essentially instant and we
> shouldn't show a splash at all". Nothing to do with race conditions.
> You can set it to 0 if you want.
This is the sleep that I mean.
On the one hand, it is this delay that makes most users not notice the "busy VRAM bug". If the DRM driver that replaces the FB driver is included in the initramfs, then in most cases, it will be loaded before the 5 seconds are up. However, if the driver is loaded after these 5 seconds have elapsed, then Plymouth will have opened /dev/fb0 and the modprobe fails.
This sleep in Plymouth, combined with DRM drivers being included in the initramfs, just happens to work around the bug on most systems.
On the other hand, what is the motivation for this delay? If Plymouth were to display the splash instantly on a system that needs 0.5 seconds to boot, then the splash would flash for 0.5 seconds. But with the delay, a system that needs 5.5 seconds to boot will also flash it for 0.5 seconds. Either way, the splash will just flash for a moment. The delay only changes which systems are affected. However, if you set the delay to 0, you'll run into the bug I described above. This is a design problem, hidden by a needless delay.
> 2) The second is DeviceTimeout option. The point of this option is to
> decide how long to wait for udev coldplug to finish. It's mostly
> relevant for systems that don't have kms drivers. The point is at
> somepoint during boot we need to decide to stop waiting for a drm
> device to show up and just fallback to showing graphics using
> legacy interfaces (like /dev/fb). We used to wait until the udev
> queue went empty, but that's error prone since it gets cleared when
> the root is switched. See
>
> https://lists.freedesktop.org/archives/systemd-devel/2015-March/029184.html
I know this thread.
In the very email you linked, Tom explains that "the udev queue is empty" is NOT a way to sense that "udev coldplug is complete":
"Just to stress this again: the assumptions plymouth makes here are invalid."
In fact, there is no way to know this. DRM devices that replace generic FB devices can appear at any time. And the solution to this is to implement a timeout? This makes zero sense. It breaks with any fundamental reasoning of concurrency. As far as I can see, Plymouth doesn't understand concurrency.
So if you have a case where:
1. plymouth deactivate
2. Xorg starts
3. plymouth thinks "coldplug complete"
4. plymouth calls VT_SETMODE
...you're clearly doing something very, very wrong because you're ignoring the "deactivate" command.
If this has been truly fixed in the meantime, please ignore it.
>> So some issues are hard to fix, others are impossible to fix in userspace.
> I'm not convinced there are any insurmountable problems here...
>
> One thing i'd like to do is change boot to not map fbcon at first, and
> only map it in on the fly when the user hits escape, or after boot
> finishes. like, for instance, try booting with fbcon=vc:2 or
> fbcon=map:9 to see how it improves the boot experience.
This doesn't touch upon any of the problems that I've described, and only serves to introduce additional failure points.
The reason why I wrote the kernel splash is that it's foolproof.
It doesn't need these hacks that just keep piling up.
No sleeps. No remapping of consoles. No races. No fights. No nothing.
This is why I started it.
Max
On 12/19/2017 10:01 PM, Ray Strode wrote:
> Hi,
>
> On Tue, Dec 19, 2017 at 10:41 AM, Max Staudt <[email protected]> wrote:
>> I'm hooking into the in-kernel terminal emulator, because the bootsplash is a
>> functional extension of that. It just happens that fbcon sits on top of FB, so I
>> work with what I get.
>>
>> And the console in turn happens to work on all FB and KMS drivers, so it
>> makes users of all kinds of drivers happy. In fact, that's why the FB emulation
>> in KMS drivers came to be in the first place, if I remember right - to ensure
>> fbcon continues to work.
>
> But what about multi-monitor? what about hidpi screens? Ideally you want
> each monitor to show the splash in a way that best fits that monitor.
Actually, I don't want that :)
This was a design decision that I've made to keep the code small and simple to audit.
As it is, the simple bootsplash code will make 99% of people happy. It includes positioning of objects in corners and in the center, and a background color, and thus can render something that doesn't look funny in all but the most extreme cases.
I've made this decision from the point of view of someone who wants to ship a general purpose distribution. If you have a look around and compare this to e.g. the Windows or Mac OS X bootsplashes, the possibilities that my kernel code provides already surpasses them.
If you really want such sophisticated features, supplanting the initial bootsplash with Plymouth (or not using it at all) is a better solution. In my opinion, it is overengineering, at least for kernel code.
So... I'll just take what the fbdev emulation gives me. In most cases (single screen systems), this looks good. In most remaining cases, you have two identical monitors that show exactly the same thing. And whatever remains can live with whatever mode the DRM driver decides to set for the fbdev emulation.
As for HiDPI, if you're working on an embedded device with a fixed screen size - say a phone - you can easily include a huge picture the size of the screen in the bootsplash.
Again, it's feature creep now. Apple just centers a, well, an apple in the middle of the screen. Windows may even boot in 640x480 and then do a mode switch when showing the desktop (not sure whether this is still true with the latest version). Neither of them scales for HiDPI, and neither cares about multiple monitors. People are happy.
So in the end, it's a matter of taste. I agree that in user space, exploring these features is fun. But in kernel space, it's definitely important to keep the code short and simple. I'm convinced that I've found a good balance :)
Max
On 12/20/2017 10:43 AM, Daniel Vetter wrote:
> On Tue, Dec 19, 2017 at 07:40:12PM +0100, Max Staudt wrote:
>> On 12/19/2017 06:26 PM, Daniel Vetter wrote:
>>> So essentially you're telling me that on a current general purpose
>>> distro the gfx driver loading is a dumpster fire, and we're fixing
>>> this by ignoring it an adding a hole new layer on top. That doesn't
>>> sound like any kind of good idea to me.
>>
>> Yes. It is a vast improvement over the status quo, and people are asking
>> for it. And the bootsplash layer can be moved elsewhere, just change the
>> hooks and keep the loading/rendering.
>>
>> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It
>> just mustn't be done 100% carelessly.
>
> You've talked about using sleep and stuff to paper over races. That
> doesn't sound good at all.
Sorry, I was unclear.
It's Plymouth's ShowDelay that, unintentionally, papers over this bug.
The driver loading bug will happen with any user based splash - it's not limited to Plymouth.
On the other hand, if you don't start a graphical application before having loaded the final graphics driver, everything is good and there is no race.
So, module loading works as intended ;)
>>> So if just using drm for everything isn't possible (since drm drivers
>>> can at least in theory be hotunplugged), can we at least fix the
>>> existing fbdev kernel bugs? Not being able to unplug a drm driver when
>>> it's still open sounds like a rather serious issues that probably
>>> should be fixed anyway ... so we're better able to hotunplug an fbdev
>>> driver when it's in use.
>>
>> I don't see it as a bug. The fbdev driver gets unloaded as much as
>> possible, but as long as a userspace application keeps the address_space
>> mmap()ed, there's nothing we can do, short of forcibly removing it and
>> segfaulting the process the next time it tries to render something. Am I
>> missing something?
>
> I guess you could remap that too ... But yeah SIGBUS ftw. Wrap rendering
> in a sighandler and abort if you hit that. In drm we try to be a bit
> better and keep things around until userspace has gone.
Hmm. Are you sure it's okay to SIG these processes just because someone else has decided to unload a driver? That is counter to everything else that I've seen so far.
Also, is it even feasible, implementation wise?
>>> Or we get simpledrm merged (for efifb and vesafb support) and someone
>>> types the xendrm driver (there is floating around, it's just old) and
>>> we could forget about any real fbdev drivers except the drm based
>>> ones.
>>
>> And drmcon, unless we come up with a better idea than hooking into the *con driver.
>
> If we have everything as drm drivers, you can just use plymouth (with no
> fbdev backend ofc) and everyone is happy. Including the efifb folks (it's
> simply going to be called efidrmfb or something like that). So no idea why
> you need a *con.
Hmm, that still makes us wait until userspace has appeared...
And the reason I built it into *con is because the logic for appearing/disappearing is basically the same, and in this chain it makes sense for the bootsplash show/hide logic to be chained behind *con.
>> Sure, that'd help a lot. But what do we do until then?
>
> Make it happen? Twiddling thumbs is an option too ofc, but it tends to not
> result in results :-)
I'm afraid I don't have the time to write an in-kernel terminal emulator, thus the wish to build upon the existing one...
On 12/20/2017 11:06 AM, Neil Armstrong wrote:
> My 2cents about this patchset:
> You did a good job about all the animation and splash logic, but for me all this fbcon
> stuff is a huge hack, please use a standard and modern display subsystem en leave fbcon
> die alone....
Thanks for the compliment!
As for fbcon: I think you're confusing things. fbcon is not the same as fbdev.
I've hooked into the terminal emulator because it allows me to hide exactly the thing I want to hide (text), it allows me to show what I want when I want (splash or text), and it spares me from defining a third competing user of the device.
I understand that you want old code to die, and as it is now, catering for the old code will cater for everyone, including the new style drivers (via their legacy interface).
> My DRM ARM systems would love to have such bootsplash, so please, make it happen using DRM
> then leave the fbcon based stuff like efifb migrate to DRM in a second time !
The current solution will "just work" on your systems as it is. I'm not ignoring them. If you've ever used a kernel console on your DRM ARM device, then the current splash will work exactly as good.
Max
On 12/20/2017 11:14 AM, Daniel Vetter wrote:
> btw since I'm probably sounding a bit too grumpy here: I'd very much
> support this. I think bootsplash in kernel has a bunch of uses, and it
> shouldn't be hard to get non-suse people to cheer for it (makes merging
> easier if it's not just a one-off hack).
Thank you!
As it seems, other people and distros are already interested - for example Manjaro.
It's also a chance to (maybe in the near future) integrate with a splash painted by EFI and/or GRUB, before userspace has even started.
> But I'm really not sold on the current integration path being anywhere
> near close to a good idea long-term.
Sure, that's a valid concern.
So there's two questions I understand from you here:
1. Do I really need to build on top of the console driver?
2. If not (1), then can I build on top of KMS instead?
Let's look at this...
1. The starting point was that the kernel's built-in terminal emulator, fbcon, is the "fallback" thing to display when no graphical application is running. It is hidden automatically as soon as a program switches to KD_GRAPHICS, and reappears as soon as that program switches back to KD_TEXT, or dies.
It seemed desirable to me to want the same behavior for a splash screen.
Furthermore, when fbcon runs, there is already a mode set. Whatever mode that may be, it's good enough for us.
It makes sense to re-use the same mode.
(This isn't really important for FB, but would be important when talking about drmcon).
Since fbcon and the splash will never be shown at the same time, it makes sense to re-use whatever framebuffer fbcon is writing into, and silence fbcon during this time (that's what my dummyops do).
When the splash is disabled, it needs to show the text that was hidden. So what I do is to call update_screen(vc_cons[fg_console].d) and also restore the original fbcon character rendering operations, thus allowing it to re-render the screen.
It thus seemed sensible to me to work inside of fbcon.
Let's stay at the FB level for the sake of taking things step by step. How would I solve this without hooking into fbcon?
To shut up fbcon, I could play with do_console_blank() and do_console_unblank(). These are called when changing between KD_GRAPHICS and KD_TEXT. I'd then have to introduce additional logic for the KD_TEXT state, which switches between showing fbcon and showing the splash. I haven't tried this, but fair enough.
To decide when to render, I'd have to have a hook that tells me when an FB mode changes, or the device disappears, or a new device appears. With fbcon, I can simply draw my splash in the fbcon_switch() function, not needing to care about whether this is a good time and whether I have a device underneath my feet. If fbcon can draw, then so can I.
2. Let's assume we follow the ideas from the final paragraphs of (1) above, and also move to KMS. How would I deal with setting modes, etc.? I wouldn't want to change modes, and I also can't always get a new framebuffer for background buffering - think devices that only have a single framebuffer, such as a fictional efidrm, or devices with little VRAM. So if these semantics get figured out for a future drmcon, then it makes sense to just double-purpose its framebuffer. After all, the console framebuffer is the one shown as a fallback, when no other process is using the graphics mode. Otherwise, I'd have to check which one to show: The splash, or the text?
So... it seemed helpful to me to build on top of the graphical console driver and double-purpose it, because it takes away the need to think about "what mode do I use", "which framebuffer to draw on", "when is it safe to draw", and so forth.
If you disagree with that, or even think that it's easier to do outside fbcon, I'd be grateful to hear ideas on how to implement it. Maybe it wasn't the best decision - but as the old saying goes, "it seemed like a very good idea at the time".
As for the FB/KMS discussion:
Since I decided to build on top of the only graphical console driver that we have, I have no choice: fbcon builds on fbdev, and thus the bootsplash is on fbdev, too. Complaining that it's not on KMS is a red herring - after all, it does work on KMS drivers, and people are happy with fbcon on KMS as well.
If integration and future paths are to be discussed, let's first talk about whether to move the splash inside/outside the console driver (fbcon).
Max
On Wed, Dec 20, 2017 at 3:55 PM, Max Staudt <[email protected]> wrote:
> On 12/20/2017 11:14 AM, Daniel Vetter wrote:
>> btw since I'm probably sounding a bit too grumpy here: I'd very much
>> support this. I think bootsplash in kernel has a bunch of uses, and it
>> shouldn't be hard to get non-suse people to cheer for it (makes merging
>> easier if it's not just a one-off hack).
>
> Thank you!
>
> As it seems, other people and distros are already interested - for example Manjaro.
>
> It's also a chance to (maybe in the near future) integrate with a splash painted by EFI and/or GRUB, before userspace has even started.
Maybe I've sounded too optimistic now.
So fundamentally I don't think an in-kernel bootsplash is a bad idea.
But most likely you want this on a highly embedded system, which
probably is compiled for your exact hw, with pretty much everything
built in. Also, no fbcon, maybe even no vt subsystem at all.
Definitely not your general purpose distro.
Your proposal to work on top of fbcon doesn't fix that niche.
Now for your problem, which seems to be to have a working bootsplash
for a general purpose distro, specifically for the bug where plymouth
prevents the real drm driver from loading: Adding an in-kernel
bootsplash doesn't make any sense, at least not to me. Instead I think
the right action is to fix the problem, both in the kernel and in
userspace.
All the problems below have fairly simple solutions, but there's imo
no point in talking technical solutions for specific problems when
we're trying to fix the wrong problem.
-Daniel
>> But I'm really not sold on the current integration path being anywhere
>> near close to a good idea long-term.
> Sure, that's a valid concern.
>
> So there's two questions I understand from you here:
>
> 1. Do I really need to build on top of the console driver?
> 2. If not (1), then can I build on top of KMS instead?
>
>
> Let's look at this...
>
> 1. The starting point was that the kernel's built-in terminal emulator, fbcon, is the "fallback" thing to display when no graphical application is running. It is hidden automatically as soon as a program switches to KD_GRAPHICS, and reappears as soon as that program switches back to KD_TEXT, or dies.
> It seemed desirable to me to want the same behavior for a splash screen.
>
> Furthermore, when fbcon runs, there is already a mode set. Whatever mode that may be, it's good enough for us.
> It makes sense to re-use the same mode.
> (This isn't really important for FB, but would be important when talking about drmcon).
>
> Since fbcon and the splash will never be shown at the same time, it makes sense to re-use whatever framebuffer fbcon is writing into, and silence fbcon during this time (that's what my dummyops do).
>
> When the splash is disabled, it needs to show the text that was hidden. So what I do is to call update_screen(vc_cons[fg_console].d) and also restore the original fbcon character rendering operations, thus allowing it to re-render the screen.
>
>
> It thus seemed sensible to me to work inside of fbcon.
>
>
> Let's stay at the FB level for the sake of taking things step by step. How would I solve this without hooking into fbcon?
>
> To shut up fbcon, I could play with do_console_blank() and do_console_unblank(). These are called when changing between KD_GRAPHICS and KD_TEXT. I'd then have to introduce additional logic for the KD_TEXT state, which switches between showing fbcon and showing the splash. I haven't tried this, but fair enough.
>
> To decide when to render, I'd have to have a hook that tells me when an FB mode changes, or the device disappears, or a new device appears. With fbcon, I can simply draw my splash in the fbcon_switch() function, not needing to care about whether this is a good time and whether I have a device underneath my feet. If fbcon can draw, then so can I.
>
>
> 2. Let's assume we follow the ideas from the final paragraphs of (1) above, and also move to KMS. How would I deal with setting modes, etc.? I wouldn't want to change modes, and I also can't always get a new framebuffer for background buffering - think devices that only have a single framebuffer, such as a fictional efidrm, or devices with little VRAM. So if these semantics get figured out for a future drmcon, then it makes sense to just double-purpose its framebuffer. After all, the console framebuffer is the one shown as a fallback, when no other process is using the graphics mode. Otherwise, I'd have to check which one to show: The splash, or the text?
>
>
>
> So... it seemed helpful to me to build on top of the graphical console driver and double-purpose it, because it takes away the need to think about "what mode do I use", "which framebuffer to draw on", "when is it safe to draw", and so forth.
>
> If you disagree with that, or even think that it's easier to do outside fbcon, I'd be grateful to hear ideas on how to implement it. Maybe it wasn't the best decision - but as the old saying goes, "it seemed like a very good idea at the time".
>
>
> As for the FB/KMS discussion:
> Since I decided to build on top of the only graphical console driver that we have, I have no choice: fbcon builds on fbdev, and thus the bootsplash is on fbdev, too. Complaining that it's not on KMS is a red herring - after all, it does work on KMS drivers, and people are happy with fbcon on KMS as well.
>
>
> If integration and future paths are to be discussed, let's first talk about whether to move the splash inside/outside the console driver (fbcon).
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
On Wed, Dec 20, 2017 at 4:11 PM, Daniel Vetter <[email protected]> wrote:
> On Wed, Dec 20, 2017 at 3:55 PM, Max Staudt <[email protected]> wrote:
>> On 12/20/2017 11:14 AM, Daniel Vetter wrote:
>>> btw since I'm probably sounding a bit too grumpy here: I'd very much
>>> support this. I think bootsplash in kernel has a bunch of uses, and it
>>> shouldn't be hard to get non-suse people to cheer for it (makes merging
>>> easier if it's not just a one-off hack).
>>
>> Thank you!
>>
>> As it seems, other people and distros are already interested - for example Manjaro.
>>
>> It's also a chance to (maybe in the near future) integrate with a splash painted by EFI and/or GRUB, before userspace has even started.
>
> Maybe I've sounded too optimistic now.
>
> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
> But most likely you want this on a highly embedded system, which
> probably is compiled for your exact hw, with pretty much everything
> built in. Also, no fbcon, maybe even no vt subsystem at all.
> Definitely not your general purpose distro.
>
> Your proposal to work on top of fbcon doesn't fix that niche.
>
> Now for your problem, which seems to be to have a working bootsplash
> for a general purpose distro, specifically for the bug where plymouth
> prevents the real drm driver from loading: Adding an in-kernel
> bootsplash doesn't make any sense, at least not to me. Instead I think
> the right action is to fix the problem, both in the kernel and in
> userspace.
>
> All the problems below have fairly simple solutions, but there's imo
> no point in talking technical solutions for specific problems when
> we're trying to fix the wrong problem.
Aside: The problem you think you need the vt/console subsystem for is
simple to fix with plain kms: kms works without fbdev, fbcon and the
entire vt subsystem. Dislay ownership is controlled through the drm
master concept. That's the exact same trick that we're using already
to figure out whether fbdev (not just fbcon) is allowed to touch the
display hw.
So yeah, there's a solution, and a modern system definitely would not
want to get encumbered with the entire vt subsystem to be able to use
a bootsplash. David Herrman had the entire pile prototyped btw,
including userspace console on top of drm, emergency log on top of
drm, and replacement for simpledrm. Adding an in-kernel boot splash
would be fairly simple for this setup. It's just that no one else
cared enough to get it merged.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Hi,
> The problem that I am stumbling upon is different:
> - the system starts with an FB driver
> - after the ShowDelay time, Plymouth opens /dev/fb0
> - the system finally loads the DRM driver, which tries to kick the previous FB driver
> - loading the DRM driver fails because Plymouth still has the previous /dev/fb0 open
So the thing to realize is, that using /dev/fb is a last ditch effort
by plymouth to make
things work. It's basically a compat hack to keep vga=0x318 working
and also a nod
to embedded systems that just have /dev/fb and don't have a kms driver. If we
fall back to /dev/fb we lose, as mentioned before, multi-monitor
support. And it's a
legacy, deprecated api.
If we've reached the scenario you're discussing above, the real
failure is that the KMS
driver took too long to load. DRM is the platform graphics api. If
it's not loading
timely enough to show graphics then that's the problem! It sounds
like maybe in the
above bug, you're just failing to load the drm driver in the initrd ?
> If you have a better way of calling it, I'd be glad to learn.
> Maybe "grabbing the VT", "taking ownership of the VT", ...?
I don't care what we call it, I just didn't understand what you were
saying before.
I think i'd say "manages vt switching", but whatever.
> And then, if something causes Plymouth to sense a new device (such as Plymouth
> thinking that udev coldplug is complete), it will open the device, and as part of that,
> call VT_SETMODE. This is unexpected, since "plymouth deactivate" should keep it
> from doing this. And Plymouth's code architecture is such that this bug is hard to fix.
If what you're describing is happening, this does sound like a bug. I
don't think it
should be hard to fix, if it's a problem. I'll look into it.
> [I] have decided to write a kernel-based replacement to simplify things and to show a
> splash as early as possible. It just avoids all of this complexity.
So, for the record, I don't actually have a problem with you doing a
kernel based splash.
(though it should use drm subsystem apis not graphics subsystem apis,
/dev/fb is going
the way of the dodo)
> This is the sleep that I mean.
>
> On the one hand, it is this delay that makes most users not notice the
> "busy VRAM bug". If the DRM driver that replaces the FB driver is included in the
> initramfs, then in most cases, it will be loaded before the 5 seconds are up. However,
> if the driver is loaded after these 5 seconds have elapsed, then Plymouth will have
> opened /dev/fb0 and the modprobe fails.
Think of this from a user perspective. If the screen is black for 15 seconds
(or something) before a splash is shown, then we've already hit a
problem! That's like 15
seconds of time where the user is wondering if their system is broken.
But I don't think that actually happens in practice. I think (maybe?)
the situation you're
hitting is your drm driver isn't starting to get loaded until N
seconds after boot has started,
because it's not in the initrd. So the fix is to put it in the initrd.
> On the other hand, what is the motivation for this delay?
As I said earlier, the motivation for the delay is to avoid showing a
splash for systems that
boot in 4 seconds or something. At that point a splash is just getting
in the way.
> If Plymouth were to display the splash instantly on a system that needs 0.5 seconds to
> boot, then the splash would flash for 0.5 seconds.
No, flashing a splash for half a second would be a bug. (again think
of things from a user
perpective). Plymouth splashes have animations at the end to
transition the user to the
login screen. Normally those animations don't contribute to boot
time, because we know
when boot will finish from prior boot data. But if boot were 0.5
seconds long, then those
animations would contribute 2 to 3 seconds to boot time, and if boot
is 0.5 seconds long
showing a splash is pointless.
> But with the delay, a system that needs 5.5 seconds to boot will also flash it for 0.5 seconds.
> Either way, the splash will just flash for a moment.
again, we don't blink the splash on and off. we have transition animations.
> The delay only changes which systems are affected. However, if you set the delay to 0,
> you'll run into the bug I described above.
Then put the drm driver in the initramfs so you fix your bug !
> This is a design problem, hidden by a needless delay.
really don't see how it is.
--Ray
On Wed, Dec 20, 2017 at 4:19 PM, Daniel Vetter <[email protected]> wrote:
> On Wed, Dec 20, 2017 at 4:11 PM, Daniel Vetter <[email protected]> wrote:
>> On Wed, Dec 20, 2017 at 3:55 PM, Max Staudt <[email protected]> wrote:
>>> On 12/20/2017 11:14 AM, Daniel Vetter wrote:
>>>> btw since I'm probably sounding a bit too grumpy here: I'd very much
>>>> support this. I think bootsplash in kernel has a bunch of uses, and it
>>>> shouldn't be hard to get non-suse people to cheer for it (makes merging
>>>> easier if it's not just a one-off hack).
>>>
>>> Thank you!
>>>
>>> As it seems, other people and distros are already interested - for example Manjaro.
>>>
>>> It's also a chance to (maybe in the near future) integrate with a splash painted by EFI and/or GRUB, before userspace has even started.
>>
>> Maybe I've sounded too optimistic now.
>>
>> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
>> But most likely you want this on a highly embedded system, which
>> probably is compiled for your exact hw, with pretty much everything
>> built in. Also, no fbcon, maybe even no vt subsystem at all.
>> Definitely not your general purpose distro.
>>
>> Your proposal to work on top of fbcon doesn't fix that niche.
>>
>> Now for your problem, which seems to be to have a working bootsplash
>> for a general purpose distro, specifically for the bug where plymouth
>> prevents the real drm driver from loading: Adding an in-kernel
>> bootsplash doesn't make any sense, at least not to me. Instead I think
>> the right action is to fix the problem, both in the kernel and in
>> userspace.
>>
>> All the problems below have fairly simple solutions, but there's imo
>> no point in talking technical solutions for specific problems when
>> we're trying to fix the wrong problem.
>
> Aside: The problem you think you need the vt/console subsystem for is
> simple to fix with plain kms: kms works without fbdev, fbcon and the
> entire vt subsystem. Dislay ownership is controlled through the drm
> master concept. That's the exact same trick that we're using already
> to figure out whether fbdev (not just fbcon) is allowed to touch the
> display hw.
>
> So yeah, there's a solution, and a modern system definitely would not
> want to get encumbered with the entire vt subsystem to be able to use
> a bootsplash. David Herrman had the entire pile prototyped btw,
> including userspace console on top of drm, emergency log on top of
> drm, and replacement for simpledrm. Adding an in-kernel boot splash
> would be fairly simple for this setup. It's just that no one else
> cared enough to get it merged.
*replacement for efifb/vesafb in the form of simpledrm. The
in-userspace fbcon is called kmscon, so also exists already. The
emergency boot splash thing was called drmlog iirc.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Hi,
> Actually, I don't want that :)
>
> This was a design decision that I've made to keep the code small and simple to audit.
> As it is, the simple bootsplash code will make 99% of people happy.
You think only 1% of linux users have more than one monitor or a 4k screen?
> I've made this decision from the point of view of someone who wants to ship a general
> purpose distribution. If you have a look around and compare this to e.g. the Windows or
> Mac OS X bootsplashes, the possibilities that my kernel code provides already
> surpasses them.
I haven't looked specifically, but I don't believe you :-) You're
telling me the apple boot
splash isn't scaled up on machines with retina displays? I don't use
OSX (or windows),
so I don't know, but I'd be really surprised.
> If you really want such sophisticated features, supplanting the initial bootsplash with
> Plymouth (or not using it at all) is a better solution. In my opinion, it is overengineering,
> at least for kernel code.
disagree..it's support for basic, commodity hardware these days.
> As for HiDPI, if you're working on an embedded device with a fixed screen size -
> say a phone - you can easily include a huge picture the size of the screen in the
> bootsplash.
I'm talking about a situation where you have a dell xps or whatever
with an external
monitor attached. Each monitor should be able to show the splash
without deforming
it, and without making it huge or microscopic. pretty basic stuff...
--Ray
On 12/20/2017 04:11 PM, Daniel Vetter wrote:
> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
> But most likely you want this on a highly embedded system, which
> probably is compiled for your exact hw, with pretty much everything
> built in. Also, no fbcon, maybe even no vt subsystem at all.
> Definitely not your general purpose distro.
If an embedded distro can use it, then so can a general purpose distro that doesn't want to use Plymouth.
It's useful in many cases.
> Your proposal to work on top of fbcon doesn't fix that niche.
It does fix it very well - it's just that it also requires fbcon.
And I'm glad to fix this if you have a good idea for a cleaner alternative.
> Now for your problem, which seems to be to have a working bootsplash
> for a general purpose distro, specifically for the bug where plymouth
> prevents the real drm driver from loading: Adding an in-kernel
> bootsplash doesn't make any sense, at least not to me. Instead I think
> the right action is to fix the problem, both in the kernel and in
> userspace.
So we SIGBUS any process using the framebuffer just because we're loading an alternative driver, which uses a hack to kick out the old driver?
It's loading the new driver that should fail because the hardware resource is busy serving the old driver!
Not existing applications being killed. This is horribly broken semantics.
Just like unloading a driver that's still in use MUST fail. Not kill the processes using it!
And if it fails to load with -EBUSY, as it should, then the bug still stands.
> All the problems below have fairly simple solutions, but there's imo
> no point in talking technical solutions for specific problems when
> we're trying to fix the wrong problem.
The problem is that a splash in userspace brings horrible hacks and workarounds into the room. We're already discussing killing processes!
No, just no. Processes aren't ours to kill willy-nilly.
Max
On 12/20/2017 04:19 PM, Daniel Vetter wrote:
> On Wed, Dec 20, 2017 at 4:11 PM, Daniel Vetter <[email protected]> wrote:
>> On Wed, Dec 20, 2017 at 3:55 PM, Max Staudt <[email protected]> wrote:
>>> On 12/20/2017 11:14 AM, Daniel Vetter wrote:
>>>> btw since I'm probably sounding a bit too grumpy here: I'd very much
>>>> support this. I think bootsplash in kernel has a bunch of uses, and it
>>>> shouldn't be hard to get non-suse people to cheer for it (makes merging
>>>> easier if it's not just a one-off hack).
>>>
>>> Thank you!
>>>
>>> As it seems, other people and distros are already interested - for example Manjaro.
>>>
>>> It's also a chance to (maybe in the near future) integrate with a splash painted by EFI and/or GRUB, before userspace has even started.
>>
>> Maybe I've sounded too optimistic now.
>>
>> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
>> But most likely you want this on a highly embedded system, which
>> probably is compiled for your exact hw, with pretty much everything
>> built in. Also, no fbcon, maybe even no vt subsystem at all.
>> Definitely not your general purpose distro.
>>
>> Your proposal to work on top of fbcon doesn't fix that niche.
>>
>> Now for your problem, which seems to be to have a working bootsplash
>> for a general purpose distro, specifically for the bug where plymouth
>> prevents the real drm driver from loading: Adding an in-kernel
>> bootsplash doesn't make any sense, at least not to me. Instead I think
>> the right action is to fix the problem, both in the kernel and in
>> userspace.
>>
>> All the problems below have fairly simple solutions, but there's imo
>> no point in talking technical solutions for specific problems when
>> we're trying to fix the wrong problem.
>
> Aside: The problem you think you need the vt/console subsystem for is
> simple to fix with plain kms: kms works without fbdev, fbcon and the
> entire vt subsystem. Dislay ownership is controlled through the drm
> master concept. That's the exact same trick that we're using already
> to figure out whether fbdev (not just fbcon) is allowed to touch the
> display hw.
So when there is no DRM master, then the FB emulation becomes active.
Sure. But I still have to multiplex between the console and the splash.
It seemed cleanest to do this inside the console. If there's a good way outside, that's just as good for me, and I'm happy to implement it.
But please help me and point me at how to do it best. Ideally, in both FB and KMS contexts. Without using additional video RAM wherever possible.
> So yeah, there's a solution, and a modern system definitely would not
> want to get encumbered with the entire vt subsystem to be able to use
> a bootsplash. David Herrman had the entire pile prototyped btw,
> including userspace console on top of drm, emergency log on top of
> drm, and replacement for simpledrm. Adding an in-kernel boot splash
> would be fairly simple for this setup. It's just that no one else
> cared enough to get it merged.
So... the solution for being unable to implement a good splash in userspace is... to move the console into the userspace?
A ton of people will beg to differ. And I'm afraid I have to disagree as well.
To be clear, I dislike the nature of the VT subsystem as well. It's a hack. But it's such an incredibly useful hack that I'm willing to turn a blind eye to its ugliness. There's a good reason why we have a terminal emulator in the kernel itself, and I'd rather keep it around for a while longer.
Max
On 12/20/2017 04:21 PM, Ray Strode wrote:
> If we've reached the scenario you're discussing above, the real
> failure is that the KMS
> driver took too long to load. DRM is the platform graphics api. If
> it's not loading
> timely enough to show graphics then that's the problem! It sounds
> like maybe in the
> above bug, you're just failing to load the drm driver in the initrd ?
This case needs to be handled.
Again, please read my bug report.
When the user changes graphics cards, the initrd does not contain the new driver. It's in the rootfs, if at all.
If it does happen to be on the rootfs, then it is potentially loaded after Plymouth has already opened /dev/fb0. And then the bug occurs.
Please don't say that I'm to blame for changing my graphics card. This is not fair.
And I have to admit, it's not even necessarily a bug. It's just the nature of the kernel/userspace split. All I know is that the boot failing due to this is not right, and horrible to debug the next time it happens to someone.
>> And then, if something causes Plymouth to sense a new device (such as Plymouth
>> thinking that udev coldplug is complete), it will open the device, and as part of that,
>> call VT_SETMODE. This is unexpected, since "plymouth deactivate" should keep it
>> from doing this. And Plymouth's code architecture is such that this bug is hard to fix.
> If what you're describing is happening, this does sound like a bug. I
> don't think it
> should be hard to fix, if it's a problem. I'll look into it.
Thank you!
It'd be nice to see this bug fixed, as it happens only occasionally (as is the nature of a race condition), and was thus really hard to debug. I'm sure it can drive people insane, as they try to find out whether they've disabled Ctrl-Alt-Fx in their xorg.conf, but really it's Plymouth getting the system into a bad state. I probably owe a bald patch on my head to this bug.
>> [I] have decided to write a kernel-based replacement to simplify things and to show a
>> splash as early as possible. It just avoids all of this complexity.
> So, for the record, I don't actually have a problem with you doing a
> kernel based splash.
Thanks!
It's really just meant as an alternative. I've heard enough people who'd prefer it over Plymouth, but Plymouth is just as important as it is much more feature-rich.
>> This is the sleep that I mean.
>>
>> On the one hand, it is this delay that makes most users not notice the
>> "busy VRAM bug". If the DRM driver that replaces the FB driver is included in the
>> initramfs, then in most cases, it will be loaded before the 5 seconds are up. However,
>> if the driver is loaded after these 5 seconds have elapsed, then Plymouth will have
>> opened /dev/fb0 and the modprobe fails.
> Think of this from a user perspective. If the screen is black for 15 seconds
> (or something) before a splash is shown, then we've already hit a
> problem! That's like 15
> seconds of time where the user is wondering if their system is broken.
This is exactly where the kernel bootsplash is useful. Since it starts even before any userspace program is loaded, it can close this gap.
I've even tried it in combination with Plymouth: Plymouth is just another graphical application, so it simply pops up "on top", just like X would. The two splashes integrate flawlessly.
> But I don't think that actually happens in practice. I think (maybe?)
> the situation you're
> hitting is your drm driver isn't starting to get loaded until N
> seconds after boot has started,
> because it's not in the initrd. So the fix is to put it in the initrd.
No. See above.
One could argue that one could put all DRM drivers into the initrd. Ubuntu does this, and the initrd is ~40 MB in size. Not nice.
And even then, the initrd could be outdated for some reason. Maybe it's a developer machine. Nobody would expect the boot to hang/fail because of this problem.
>> On the other hand, what is the motivation for this delay?
> As I said earlier, the motivation for the delay is to avoid showing a
> splash for systems that
> boot in 4 seconds or something. At that point a splash is just getting
> in the way.
>
>> If Plymouth were to display the splash instantly on a system that needs 0.5 seconds to
>> boot, then the splash would flash for 0.5 seconds.
> No, flashing a splash for half a second would be a bug. (again think
> of things from a user
> perpective). Plymouth splashes have animations at the end to
> transition the user to the
> login screen. Normally those animations don't contribute to boot
> time, because we know
> when boot will finish from prior boot data. But if boot were 0.5
> seconds long, then those
> animations would contribute 2 to 3 seconds to boot time, and if boot
> is 0.5 seconds long
> showing a splash is pointless.
>> But with the delay, a system that needs 5.5 seconds to boot will also flash it for 0.5 seconds.
>> Either way, the splash will just flash for a moment.
> again, we don't blink the splash on and off. we have transition animations.
>
>> The delay only changes which systems are affected. However, if you set the delay to 0,
>> you'll run into the bug I described above.
> Then put the drm driver in the initramfs so you fix your bug !
>
>> This is a design problem, hidden by a needless delay.
> really don't see how it is.
Ah, I see. I admit I wasn't aware of such transitions and boot timings.
So let's take SUSE. They don't have a finishing transition, the splash simply stops and is hidden at once.
Such a splash makes sense to be shown instantly, right?
So the startup delay could be reduced to 0. Except that that would mean running into the initrd "bug".
Max
On 12/20/2017 04:35 PM, Ray Strode wrote:
> Hi,
>
>> Actually, I don't want that :)
>>
>> This was a design decision that I've made to keep the code small and simple to audit.
>> As it is, the simple bootsplash code will make 99% of people happy.
> You think only 1% of linux users have more than one monitor or a 4k screen?
No, I think 99% will be glad to see a splash at all, and it's a 99% probabililty that the splash will look alright on at least one screen, if not more.
By the simple virtue that dual-monitor setups tend to use identical screens, it's okay if these are cloned while the splash is shown. So maybe 95% of these users are fine, as well.
As for 4k screens - a logo that looks okay on 800x600 will probably look fine, even though it's physically smaller, on a 4k screen.
If there really, really, really is a need, HiDPI can be retrofitted to the format later on.
>> I've made this decision from the point of view of someone who wants to ship a general
>> purpose distribution. If you have a look around and compare this to e.g. the Windows or
>> Mac OS X bootsplashes, the possibilities that my kernel code provides already
>> surpasses them.
> I haven't looked specifically, but I don't believe you :-) You're
> telling me the apple boot
> splash isn't scaled up on machines with retina displays? I don't use
> OSX (or windows),
> so I don't know, but I'd be really surprised.
Admittedly, my knowledge is aging as well. My pre-retina MacBook certainly didn't scale anything.
And Windows XP booted in 640x480, then went black, switched modes, and drew the desktop.
>> If you really want such sophisticated features, supplanting the initial bootsplash with
>> Plymouth (or not using it at all) is a better solution. In my opinion, it is overengineering,
>> at least for kernel code.
> disagree..it's support for basic, commodity hardware these days.
Hmm. I guess it's a matter of taste, and we have to agree to disagree on this one. See above.
Also, like pointed out in the other email, it's meant as an alternative to Plymouth. Maybe I should have made this clear from the beginning - it's an option, not a replacement. We're in the FOSS ecosystem after all, where it's all about choice, and that choice exists because we admit that sometimes, not everyone can be made happy with the same solution.
>> As for HiDPI, if you're working on an embedded device with a fixed screen size -
>> say a phone - you can easily include a huge picture the size of the screen in the
>> bootsplash.
> I'm talking about a situation where you have a dell xps or whatever
> with an external
> monitor attached. Each monitor should be able to show the splash
> without deforming
> it, and without making it huge or microscopic. pretty basic stuff...
See above. I doubt any other system cares.
And we can't even care before native driver KMS comes up, which may take a while, depending on the system.
I'd like to have this as an alternative to Plymouth in such setups.
Max
On Wed, Dec 13, 2017 at 08:47:42PM +0100, Max Staudt wrote:
> Dear fbdev and fbcon developers,
>
> Thank you very much for your input for the first patch series.
>
> I've included your feedback into this second roll, and kindly ask for
> your opinion on the new patch series.
>
>
> Changes from v1 to v2:
>
> + Added a user space tool to create splash theme files
> + Bumped the file format version:
> - Larger structs for easy future expansion
> - 2-byte corner offset
> - Offset either from corner or from center
> - Fixed padding before header->frame_ms
> + Moved bootsplash_file.h to uapi/linux
> + Merged several patches
> + Theme files are now loaded via request_firmware()
> + sysfs hook to allow loading of theme files via request_firmware()
> + Dropped the .enable cmdline option and the default file name.
> The splash will be shown as soon as a file is specified.
> + Dropped custom workqueue in favor of the kernel queue
> and cancel_delayed_work_sync()
> + Marked loaded data as const, and load/enable it atomically
> + Reduced global state by moving data into other structures
> + EXPORT_SYMBOL_GPL for fbcon_set_dummyops()
> + Atomic and barrier for splash enabled state instead of spinlock
> + Reduced warnings to infos
> + Rate limited printk
> + Changed the multi-line comment layout to kernel style
> + Simplified the file headers
> + reST-ed the documentation
Ok, here's my expectation:
- fix plymouth and driver loading
If the plymouth maintainer tells me that's impossible, I'll look at this
again. And no, this does not require killing drivers with SIGBUS, at least
not with drm. Meanwhile I don't think this RFC makes sense to be merged.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Hi,
On Wed, Dec 20, 2017 at 11:44 AM Max Staudt <[email protected]> wrote:
> It'd be nice to see this bug fixed, as it happens only occasionally (as is the nature of a
> race condition), and was thus really hard to debug. I'm sure it can drive people insane,
> as they try to find out whether they've disabled Ctrl-Alt-Fx in their xorg.conf, but really
> it's Plymouth getting the system into a bad state. I probably owe a bald patch on my
> head to this bug.
Okay, reading through the code I do see how what you're describing could happen.
I sketched out a patch here:
https://cgit.freedesktop.org/plymouth/commit/?h=fix-vt-management-on-deactivate&id=0b5b790d628f4c96e3ab9fbc0daba67a29b850da
that I think should fix it. I need to do some testing with it (ideally rig up
a reproducer) before I push it.
> This is exactly where the kernel bootsplash is useful. Since it starts even before any
> userspace program is loaded, it can close this gap.
>
> I've even tried it in combination with Plymouth: Plymouth is just another graphical
> application, so it simply pops up "on top", just like X would. The two splashes
> integrate flawlessly.
I just wish it used our modern graphics platform instead of the
deprecated subsystem.
> One could argue that one could put all DRM drivers into the initrd. Ubuntu does this,
> and the initrd is ~40 MB in size. Not nice.
well, that 40mb isn't just graphics drivers...
╎❯ du -sh /lib/modules/`uname -r`/kernel/drivers/gpu
2.7M /lib/modules/4.14.6-300.fc27.x86_64/kernel/drivers/gpu
3M isn't too awful.
But really you have two choices as I see it:
1) make the initrd support new hardware
2) make the initrd be taylored to a specific configuration.
I actually think ubuntu has it right by doing 1. it's going to give
the best user experience.
(not just with graphics but other new hardware too).
But if you do 2) then it's not unreasonable if things break with new
hardware. Now
ideally, the breakage would be as isolated as possible. I mean maybe
it's okay if the
boot splash breaks (or shows a text splash), but it's not okay if the
bootsplash sort of
works using /dev/fb, but then causes Xorg to break. So we should
probably change
plymouth to avoid falling back to /dev/fb in the case where new
hardware got added.
Could probably fix this by detecting if kms is around when the initrd
is generated,
and adding a config option to skip fb renderer in that case. or
something like that.
But the easy answer is to just fix the initrd to have the graphics drivers.
> And even then, the initrd could be outdated for some reason. Maybe it's a developer
> machine. Nobody would expect the boot to hang/fail because of this problem.
Right, ideally boot splash problems should never stop boot from proceeding.
> So let's take SUSE. They don't have a finishing transition, the splash simply stops
> and is hidden at once. Such a splash makes sense to be shown instantly, right?
I don't think it makes sense for animations to lack transitions.
animations without
transitions look buggy or unfinished. they should fade out or finish
the loop, or
whatever. If it's a static image it should fade to black or the
background color.
(going to be away from the computer for a few days after this message
so probably won't reply for a while to further discussion)
--Ray
Hi Max,
from Manjaro-side we have implemented it now in our v4.14 kernel series
and started to test out some themes. Current progress and feedback may
be found in our forum:
https://forum.manjaro.org/t/bootsplash-provided-by-the-kernel/34467
Best, Philip
On 12/21/2017 03:51 PM, Ray Strode wrote:
> Hi,
>
> On Wed, Dec 20, 2017 at 11:44 AM Max Staudt <[email protected]> wrote:
>> It'd be nice to see this bug fixed, as it happens only occasionally (as is the nature of a
>> race condition), and was thus really hard to debug. I'm sure it can drive people insane,
>> as they try to find out whether they've disabled Ctrl-Alt-Fx in their xorg.conf, but really
>> it's Plymouth getting the system into a bad state. I probably owe a bald patch on my
>> head to this bug.
> Okay, reading through the code I do see how what you're describing could happen.
>
> I sketched out a patch here:
>
> https://cgit.freedesktop.org/plymouth/commit/?h=fix-vt-management-on-deactivate&id=0b5b790d628f4c96e3ab9fbc0daba67a29b850da
>
> that I think should fix it. I need to do some testing with it (ideally rig up
> a reproducer) before I push it.
Hmm, I haven't looked at what manager->renderers_activated means, but from just looking at the diff, it looks like it could solve the problem. Please do test it though! I'm afraid I can't really tell you how to rig up a reproducer, since it's a race condition. Maybe a sleep() in gdm, and then forcefully emptying the udev queue?
Are you sure that process_udev_event (manager) will do the right thing?
Will it keep a list of events not processed?
What if a card is plugged in, then unplugged? Would Plymouth then handle the plugin first, see that the card isn't there, and fail gracefully? And will it handle the unplug gracefully if the card wasn't there in the first place?
Or what if I plug in two cards - it needs to keep a list of events for this case, otherwise it will only detect one card when it resumes udev processing.
Maybe these concerns are unnecessary - I haven't looked at the full Plymouth code since. Just ideas to keep in mind when rigging up the patch.
Thanks for looking into a fix!
>> This is exactly where the kernel bootsplash is useful. Since it starts even before any
>> userspace program is loaded, it can close this gap.
>>
>> I've even tried it in combination with Plymouth: Plymouth is just another graphical
>> application, so it simply pops up "on top", just like X would. The two splashes
>> integrate flawlessly.
> I just wish it used our modern graphics platform instead of the
> deprecated subsystem.
I see, and I share your concern that legacy interfaces should die.
But with the current architecture in the kernel, building it on DRM wouldn't make sense, sorry.
Also, it would exclude the efifb case, which is decidedly a design requirement.
>> One could argue that one could put all DRM drivers into the initrd. Ubuntu does this,
>> and the initrd is ~40 MB in size. Not nice.
> well, that 40mb isn't just graphics drivers...
> ╎❯ du -sh /lib/modules/`uname -r`/kernel/drivers/gpu
> 2.7M /lib/modules/4.14.6-300.fc27.x86_64/kernel/drivers/gpu
>
> 3M isn't too awful.
Oh, true. Weird, then I must have gotten something mixed up. That means there's truly tons of stuff in that initrd.
> But really you have two choices as I see it:
>
> 1) make the initrd support new hardware
> 2) make the initrd be taylored to a specific configuration.
>
> I actually think ubuntu has it right by doing 1. it's going to give
> the best user experience.
> (not just with graphics but other new hardware too).
Yes. Except when the mechanism fails.
And it doesn't cover the time before the driver is loaded.
> But if you do 2) then it's not unreasonable if things break with new
> hardware.
Agreed.
> Now
> ideally, the breakage would be as isolated as possible. I mean maybe
> it's okay if the
> boot splash breaks (or shows a text splash),
Yup.
> but it's not okay if the
> bootsplash sort of
> works using /dev/fb, but then causes Xorg to break. So we should
> probably change
> plymouth to avoid falling back to /dev/fb in the case where new
> hardware got added.
> Could probably fix this by detecting if kms is around when the initrd
> is generated,
> and adding a config option to skip fb renderer in that case. or
> something like that.
That's not possible. When generating the initrd, you don't know where it will actually be booted next.
Practical example: Last year's installation media on next year's hardware.
> But the easy answer is to just fix the initrd to have the graphics drivers.
See above - you can't guarantee that I'm afraid.
Unless the distro decides to not care about vesafb/efifb, and just show the text mode plymouth splash in case no KMS driver has been loaded until then. That's what Fedora does when booted on non-EFI machines, since it boots in VGA text (non-graphics) mode. But ideally, we'd have a graphical splash in as many cases as possible. If you boot your Fedora machine in a framebuffer mode, or in EFI mode, you'll unleash these issues.
>> So let's take SUSE. They don't have a finishing transition, the splash simply stops
>> and is hidden at once. Such a splash makes sense to be shown instantly, right?
> I don't think it makes sense for animations to lack transitions.
> animations without
> transitions look buggy or unfinished. they should fade out or finish
> the loop, or
> whatever. If it's a static image it should fade to black or the
> background color.
Umm... yeah, that's a design decision. I'm afraid that's not my department ;)
What about the delay? Do you agree that with such a simple, no-transition splash, it makes sense to reduce the delay to 0?
> (going to be away from the computer for a few days after this message
> so probably won't reply for a while to further discussion)
Yes, me too. I'll be back in 2018.
Thank you for your feedback and for fixing Plymouth!
Max
On 12/21/2017 10:48 AM, Daniel Vetter wrote:
> Ok, here's my expectation:
>
> - fix plymouth and driver loading
>
> If the plymouth maintainer tells me that's impossible, I'll look at this
> again. And no, this does not require killing drivers with SIGBUS, at least
> not with drm. Meanwhile I don't think this RFC makes sense to be merged.
I'm afraid I don't understand. How would we best go about fixing this issue?
Thank you for your valuable feedback so far, I'll be looking into addressing the issues you've brought up.
For now, I'll be on vacation until January 2018, so it'll take a while until I get back to you.
Thanks and happy new year!
Max
On Tue, 19 Dec 2017, Daniel Vetter <[email protected]> wrote:
> On Wed, Dec 13, 2017 at 08:47:42PM +0100, Max Staudt wrote:
>> Dear fbdev and fbcon developers,
>>
>> Thank you very much for your input for the first patch series.
>>
>> I've included your feedback into this second roll, and kindly ask for
>> your opinion on the new patch series.
>
> Ok I've realized that my assumptions about why you need this aren't
> holding up.
>
> So from reading these patches it sounded like you want an in-kernel boot
> splash because that would be on the display faster than a userspace one
> like plymouth. That's the only reasons I can see for this (if there's
> another good justification, please bring it up).
>
> I only know of very embedded setups (tv top boxes, in vehicle
> entertainment) where that kind of "time to first image" really matters,
> and those systems:
> - have a real hw kms driver
> - don't have fbcon or fbdev emulation enabled (except for some closed
> source stacks that are a bit slow to adapt to the new world, and we
> don't care about those in gfx).
>
> But from discussions it sounds like you very much want to use this on
> servers, which makes 0 sense to me. On a server something like plymouth
> should do a perfectly reasonable job.
>
> So, why exactly do we need this?
Okay, I'll take another step back from the implementation and most of
the discussion here, and look at what *I* would like to see on screen
when I have my user hat on and my kernel developer hat securely stowed
away.
I think the first issue is the boot manager (e.g. grub) messing up
whatever the BIOS or GOP or whatever drew. If I don't touch any buttons,
I'd prefer the Lenovo or VAIO or NUC or whatever logo stay there. IIRC
some BIOSes let you set up your own splash if you like, though that's
not really relevant for me. So already the boot manager takeover is a
problem.
The next issue is the framebuffer driver takeover. It's not unlike the
above, just one step further. If you like your grub image to stay there,
let it stay there. (Or, if the boot manager was nice enough to not mess
up the screen, let the BIOS image stay there.) All the way to KMS and
userspace.
IMHO the user friendly experience is already gone by the time we reach
any kernel/userspace bootsplash. We want our command-line tools to STFU
if they don't have anything interesting to say. As a user, 99.99+% of
the time I don't care what grub or dmesg have to say.
Of course, with the kernel developer hat on, I want all of the clues
every time in case something goes wrong. But this shouldn't have to be
mutually exclusive.
BR,
Jani.
--
Jani Nikula, Intel Open Source Technology Center
On Tue, 19 Dec 2017 19:40:12 +0100
Max Staudt <[email protected]> wrote:
> On 12/19/2017 06:26 PM, Daniel Vetter wrote:
> > On Tue, Dec 19, 2017 at 6:04 PM, Max Staudt <[email protected]> wrote:
> >> Well, those could enable fbcon if they want the bootsplash. Shouldn't make a difference anyway if they're powerful enough to run Linux. As long as the bootsplash is shown, no fbcon drawing operations are executed, so there is no expensive scrolling or such to hog the system.
> >
> > It's too big, and those folks tend to be super picky about space.
>
> I know, they really are.
>
> However, given just how big and clunky modern systems have become, I raise my doubts about a few extra KB for fbcon code to be relevant.
For embedded every KB counts. That is likely to remain the same for some
time because at the end of the day small devices are constrained about the
amount of SRAM you can put on die and the amount of power you can afford
for DRAM.
> > this by ignoring it an adding a hole new layer on top. That doesn't
> > sound like any kind of good idea to me.
>
> Yes. It is a vast improvement over the status quo, and people are asking for it. And the bootsplash layer can be moved elsewhere, just change the hooks and keep the loading/rendering.
>
> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It just mustn't be done 100% carelessly.
It's a total mess (the fbcon layer loading and locking that is). Doing all
this extra kernel stuff is like sitting in a hole and instead of trying to
climb out digging the hole bigger so you've got more room to sit in it.
Alan
> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
> But most likely you want this on a highly embedded system, which
It wouldn't be in kernel on such a device, it'll be in the bootstrap
before (or on a dual core device quite possibly while) the kernel data is
being uncompressed. Most displays need some time to stabilize clocks and
PLLs so you have to get the mode set up really really early on embedded
devices where in some cases you've got regulatory requirements to show
something on the display really really quickly. Consumers perceive a
second from on to displaying something as sluggish on a fixed function
device.
> probably is compiled for your exact hw, with pretty much everything
> built in. Also, no fbcon, maybe even no vt subsystem at all.
> Definitely not your general purpose distro.
Probably no console or tty layer even present, no keyboard drivers, no
mouse.
Alan
On Tue, 19 Dec 2017 15:07:53 +0100
Oliver Neukum <[email protected]> wrote:
> Am Dienstag, den 19.12.2017, 14:57 +0100 schrieb Daniel Vetter:
> > > Would you like me to extend the FB API or not?
> >
> > Yes. Well for real I'd like you to do kms, so maybe you need to explain
> > why exactly you absolutely have to use fbdev (aka which driver isn't
> > supported by drm that you want to enable this on).
>
> Hi,
>
> those would be at a minimum efifb, vesafb, xenfb
> Those are obviously not sexy, but from a practical point of view
> they are the minimum you need to support.
I think it's more constructive to look at it the other way around. What
drivers do we have that actually need to be used which don't have DRM
equivalents - and how do we fix that instead ?
Alan
On 12/29/2017 06:13 PM, Jani Nikula wrote:
> I think the first issue is the boot manager (e.g. grub) messing up
> whatever the BIOS or GOP or whatever drew. If I don't touch any buttons,
> I'd prefer the Lenovo or VAIO or NUC or whatever logo stay there. IIRC
> some BIOSes let you set up your own splash if you like, though that's
> not really relevant for me. So already the boot manager takeover is a
> problem.
>
> The next issue is the framebuffer driver takeover. It's not unlike the
> above, just one step further. If you like your grub image to stay there,
> let it stay there. (Or, if the boot manager was nice enough to not mess
> up the screen, let the BIOS image stay there.) All the way to KMS and
> userspace.
>
> IMHO the user friendly experience is already gone by the time we reach
> any kernel/userspace bootsplash. We want our command-line tools to STFU
> if they don't have anything interesting to say. As a user, 99.99+% of
> the time I don't care what grub or dmesg have to say.
Agreed - the kernel should go out of the user's way if they want it to be silent. It's already possible, as long as KMS is not in use (since that automatically sets a mode and thus usually clears the screen).
What you want is really the opposite of the kernel splash, or any splash on top of Linux (kernel or userspace) at all.
Returning to cases where a splash running on Linux may be desired:
I see adding to the initial logo as an interesting use case. An animation to show that the kernel hasn't crashed while booting is quite useful. Something like adding a spinning wheel underneath the initial logo helps. Macs do (or used to do) that after showing the apple, IIRC. I think this is where something simple and kernel based is helpful, vs. something userspace based. Maybe they can even build on top of each other, just like LILO used to print each letter as a confirmation of successfully executing a part of itself.
Thinking of it: Loading a KMS driver basically always necessitates a mode change on variable resolution platforms such as PCs. And changing mode requires clearing the screen. Now, what if we could preload the new framebuffer with a splash, rather than a blank screen?
That's not generally feasible (for example, double buffering is an implicit requirement), but who knows, maybe in the future. Just an odd idea.
> Of course, with the kernel developer hat on, I want all of the clues
> every time in case something goes wrong. But this shouldn't have to be
> mutually exclusive.
I agree - that's why it's important to be able to disable the bootsplash by changing the kernel cmdline.
Max
On 12/31/2017 01:35 PM, Alan Cox wrote:
> For embedded every KB counts. That is likely to remain the same for some
> time because at the end of the day small devices are constrained about the
> amount of SRAM you can put on die and the amount of power you can afford
> for DRAM.
Fascinating, thanks for the insight!
Now I have a really good reason to separate the splash from fbcon.
>>> this by ignoring it an adding a hole new layer on top. That doesn't
>>> sound like any kind of good idea to me.
>>
>> Yes. It is a vast improvement over the status quo, and people are asking for it. And the bootsplash layer can be moved elsewhere, just change the hooks and keep the loading/rendering.
>>
>> Also, gfx driver loading isn't a dumpster fire, it mostly just works. It just mustn't be done 100% carelessly.
>
> It's a total mess (the fbcon layer loading and locking that is). Doing all
> this extra kernel stuff is like sitting in a hole and instead of trying to
> climb out digging the hole bigger so you've got more room to sit in it.
I'm not sure what exactly you're unhappy about - are you complaining about the kernel hack in KMS drivers which allows them to kick out vesafb/efifb?
Max
On 12/31/2017 01:44 PM, Alan Cox wrote:
>> So fundamentally I don't think an in-kernel bootsplash is a bad idea.
>> But most likely you want this on a highly embedded system, which
>
> It wouldn't be in kernel on such a device, it'll be in the bootstrap
> before (or on a dual core device quite possibly while) the kernel data is
> being uncompressed. Most displays need some time to stabilize clocks and
> PLLs so you have to get the mode set up really really early on embedded
> devices where in some cases you've got regulatory requirements to show
> something on the display really really quickly. Consumers perceive a
> second from on to displaying something as sluggish on a fixed function
> device.
Oh no. Thanks for the input, that changes my perspective a bit.
So unless we could show it quickly enough, the kernel splash would be useful either as an addition on top of the bootloader's splash, or really aimed at fatter distros which wish to use something simple and kernel based.
Max
On 12/31/2017 01:53 PM, Alan Cox wrote:
> On Tue, 19 Dec 2017 15:07:53 +0100
> Oliver Neukum <[email protected]> wrote:
>
>> Am Dienstag, den 19.12.2017, 14:57 +0100 schrieb Daniel Vetter:
>>>> Would you like me to extend the FB API or not?
>>>
>>> Yes. Well for real I'd like you to do kms, so maybe you need to explain
>>> why exactly you absolutely have to use fbdev (aka which driver isn't
>>> supported by drm that you want to enable this on).
>>
>> Hi,
>>
>> those would be at a minimum efifb, vesafb, xenfb
>> Those are obviously not sexy, but from a practical point of view
>> they are the minimum you need to support.
>
> I think it's more constructive to look at it the other way around. What
> drivers do we have that actually need to be used which don't have DRM
> equivalents - and how do we fix that instead ?
It's *at least* the above named drivers: efifb, vesafb, xenfb.
Max