CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/patch/misc/0002-bootsplash.patch
Views: 3959
1
diff --git a/MAINTAINERS b/MAINTAINERS
2
index b5633b56391e..5c237445761e 100644
3
--- a/MAINTAINERS
4
+++ b/MAINTAINERS
5
@@ -2712,6 +2712,7 @@ S: Maintained
6
F: drivers/video/fbdev/core/bootsplash*.*
7
F: drivers/video/fbdev/core/dummycon.c
8
F: include/linux/bootsplash.h
9
+F: include/uapi/linux/bootsplash_file.h
10
11
BPF (Safe dynamic programs and tools)
12
M: Alexei Starovoitov <[email protected]>
13
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
14
index 66895321928e..6a8d1bab8a01 100644
15
--- a/drivers/video/fbdev/core/Makefile
16
+++ b/drivers/video/fbdev/core/Makefile
17
@@ -31,4 +31,4 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
18
obj-$(CONFIG_FB_DDC) += fb_ddc.o
19
20
obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
21
- dummyblit.o
22
+ bootsplash_load.o dummyblit.o
23
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
24
index e449755af268..843c5400fefc 100644
25
--- a/drivers/video/fbdev/core/bootsplash.c
26
+++ b/drivers/video/fbdev/core/bootsplash.c
27
@@ -32,6 +32,7 @@
28
#include <linux/workqueue.h>
29
30
#include "bootsplash_internal.h"
31
+#include "uapi/linux/bootsplash_file.h"
32
33
34
/*
35
@@ -102,10 +103,17 @@ static bool is_fb_compatible(const struct fb_info *info)
36
*/
37
void bootsplash_render_full(struct fb_info *info)
38
{
39
+ mutex_lock(&splash_state.data_lock);
40
+
41
if (!is_fb_compatible(info))
42
- return;
43
+ goto out;
44
+
45
+ bootsplash_do_render_background(info, splash_state.file);
46
+
47
+ bootsplash_do_render_pictures(info, splash_state.file);
48
49
- bootsplash_do_render_background(info);
50
+out:
51
+ mutex_unlock(&splash_state.data_lock);
52
}
53
54
55
@@ -116,6 +124,7 @@ bool bootsplash_would_render_now(void)
56
{
57
return !oops_in_progress
58
&& !console_blanked
59
+ && splash_state.file
60
&& bootsplash_is_enabled();
61
}
62
63
@@ -252,6 +261,7 @@ static struct platform_driver splash_driver = {
64
void bootsplash_init(void)
65
{
66
int ret;
67
+ struct splash_file_priv *fp;
68
69
/* Initialized already? */
70
if (splash_state.splash_device)
71
@@ -280,8 +290,26 @@ void bootsplash_init(void)
72
}
73
74
75
+ mutex_init(&splash_state.data_lock);
76
+ set_bit(0, &splash_state.enabled);
77
+
78
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
79
80
+
81
+ if (!splash_state.bootfile || !strlen(splash_state.bootfile))
82
+ return;
83
+
84
+ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
85
+ splash_state.bootfile);
86
+
87
+ if (!fp)
88
+ goto err;
89
+
90
+ mutex_lock(&splash_state.data_lock);
91
+ splash_state.splash_fb = NULL;
92
+ splash_state.file = fp;
93
+ mutex_unlock(&splash_state.data_lock);
94
+
95
return;
96
97
err_device:
98
@@ -292,3 +320,7 @@ void bootsplash_init(void)
99
err:
100
pr_err("Failed to initialize.\n");
101
}
102
+
103
+
104
+module_param_named(bootfile, splash_state.bootfile, charp, 0444);
105
+MODULE_PARM_DESC(bootfile, "Bootsplash file to load on boot");
106
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
107
index b11da5cb90bf..71e2a27ac0b8 100644
108
--- a/drivers/video/fbdev/core/bootsplash_internal.h
109
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
110
@@ -15,15 +15,43 @@
111
112
#include <linux/types.h>
113
#include <linux/fb.h>
114
+#include <linux/firmware.h>
115
#include <linux/kernel.h>
116
#include <linux/mutex.h>
117
#include <linux/spinlock.h>
118
119
+#include "uapi/linux/bootsplash_file.h"
120
+
121
122
/*
123
* Runtime types
124
*/
125
+struct splash_blob_priv {
126
+ struct splash_blob_header *blob_header;
127
+ const void *data;
128
+};
129
+
130
+
131
+struct splash_pic_priv {
132
+ const struct splash_pic_header *pic_header;
133
+
134
+ struct splash_blob_priv *blobs;
135
+ u16 blobs_loaded;
136
+};
137
+
138
+
139
+struct splash_file_priv {
140
+ const struct firmware *fw;
141
+ const struct splash_file_header *header;
142
+
143
+ struct splash_pic_priv *pics;
144
+};
145
+
146
+
147
struct splash_priv {
148
+ /* Bootup and runtime state */
149
+ char *bootfile;
150
+
151
/*
152
* Enabled/disabled state, to be used with atomic bit operations.
153
* Bit 0: 0 = Splash hidden
154
@@ -43,6 +71,13 @@ struct splash_priv {
155
struct platform_device *splash_device;
156
157
struct work_struct work_redraw_vc;
158
+
159
+ /* Splash data structures including lock for everything below */
160
+ struct mutex data_lock;
161
+
162
+ struct fb_info *splash_fb;
163
+
164
+ struct splash_file_priv *file;
165
};
166
167
168
@@ -50,6 +85,14 @@ struct splash_priv {
169
/*
170
* Rendering functions
171
*/
172
-void bootsplash_do_render_background(struct fb_info *info);
173
+void bootsplash_do_render_background(struct fb_info *info,
174
+ const struct splash_file_priv *fp);
175
+void bootsplash_do_render_pictures(struct fb_info *info,
176
+ const struct splash_file_priv *fp);
177
+
178
+
179
+void bootsplash_free_file(struct splash_file_priv *fp);
180
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
181
+ const char *path);
182
183
#endif
184
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
185
new file mode 100644
186
index 000000000000..fd807571ab7d
187
--- /dev/null
188
+++ b/drivers/video/fbdev/core/bootsplash_load.c
189
@@ -0,0 +1,225 @@
190
+/*
191
+ * Kernel based bootsplash.
192
+ *
193
+ * (Loading and freeing functions)
194
+ *
195
+ * Authors:
196
+ * Max Staudt <[email protected]>
197
+ *
198
+ * SPDX-License-Identifier: GPL-2.0
199
+ */
200
+
201
+#define pr_fmt(fmt) "bootsplash: " fmt
202
+
203
+
204
+#include <linux/bootsplash.h>
205
+#include <linux/fb.h>
206
+#include <linux/firmware.h>
207
+#include <linux/kernel.h>
208
+#include <linux/mutex.h>
209
+#include <linux/printk.h>
210
+#include <linux/types.h>
211
+#include <linux/vmalloc.h>
212
+
213
+#include "bootsplash_internal.h"
214
+#include "uapi/linux/bootsplash_file.h"
215
+
216
+
217
+
218
+
219
+/*
220
+ * Free all vmalloc()'d resources describing a splash file.
221
+ */
222
+void bootsplash_free_file(struct splash_file_priv *fp)
223
+{
224
+ if (!fp)
225
+ return;
226
+
227
+ if (fp->pics) {
228
+ unsigned int i;
229
+
230
+ for (i = 0; i < fp->header->num_pics; i++) {
231
+ struct splash_pic_priv *pp = &fp->pics[i];
232
+
233
+ if (pp->blobs)
234
+ vfree(pp->blobs);
235
+ }
236
+
237
+ vfree(fp->pics);
238
+ }
239
+
240
+ release_firmware(fp->fw);
241
+ vfree(fp);
242
+}
243
+
244
+
245
+
246
+
247
+/*
248
+ * Load a splash screen from a "firmware" file.
249
+ *
250
+ * Parsing, and sanity checks.
251
+ */
252
+#ifdef __BIG_ENDIAN
253
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_BE
254
+#else
255
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_LE
256
+#endif
257
+
258
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
259
+ const char *path)
260
+{
261
+ const struct firmware *fw;
262
+ struct splash_file_priv *fp;
263
+ unsigned int i;
264
+ const u8 *walker;
265
+
266
+ if (request_firmware(&fw, path, device))
267
+ return NULL;
268
+
269
+ if (fw->size < sizeof(struct splash_file_header)
270
+ || memcmp(fw->data, BOOTSPLASH_MAGIC, sizeof(fp->header->id))) {
271
+ pr_err("Not a bootsplash file.\n");
272
+
273
+ release_firmware(fw);
274
+ return NULL;
275
+ }
276
+
277
+ fp = vzalloc(sizeof(struct splash_file_priv));
278
+ if (!fp) {
279
+ release_firmware(fw);
280
+ return NULL;
281
+ }
282
+
283
+ pr_info("Loading splash file (%li bytes)\n", fw->size);
284
+
285
+ fp->fw = fw;
286
+ fp->header = (struct splash_file_header *)fw->data;
287
+
288
+ /* Sanity checks */
289
+ if (fp->header->version != BOOTSPLASH_VERSION) {
290
+ pr_err("Loaded v%d file, but we only support version %d\n",
291
+ fp->header->version,
292
+ BOOTSPLASH_VERSION);
293
+
294
+ goto err;
295
+ }
296
+
297
+ if (fw->size < sizeof(struct splash_file_header)
298
+ + fp->header->num_pics
299
+ * sizeof(struct splash_pic_header)
300
+ + fp->header->num_blobs
301
+ * sizeof(struct splash_blob_header)) {
302
+ pr_err("File incomplete.\n");
303
+
304
+ goto err;
305
+ }
306
+
307
+ /* Read picture headers */
308
+ if (fp->header->num_pics) {
309
+ fp->pics = vzalloc(fp->header->num_pics
310
+ * sizeof(struct splash_pic_priv));
311
+ if (!fp->pics)
312
+ goto err;
313
+ }
314
+
315
+ walker = fw->data + sizeof(struct splash_file_header);
316
+ for (i = 0; i < fp->header->num_pics; i++) {
317
+ struct splash_pic_priv *pp = &fp->pics[i];
318
+ struct splash_pic_header *ph = (void *)walker;
319
+
320
+ pr_debug("Picture %u: Size %ux%u\n", i, ph->width, ph->height);
321
+
322
+ if (ph->num_blobs < 1) {
323
+ pr_err("Picture %u: Zero blobs? Aborting load.\n", i);
324
+ goto err;
325
+ }
326
+
327
+ pp->pic_header = ph;
328
+ pp->blobs = vzalloc(ph->num_blobs
329
+ * sizeof(struct splash_blob_priv));
330
+ if (!pp->blobs)
331
+ goto err;
332
+
333
+ walker += sizeof(struct splash_pic_header);
334
+ }
335
+
336
+ /* Read blob headers */
337
+ for (i = 0; i < fp->header->num_blobs; i++) {
338
+ struct splash_blob_header *bh = (void *)walker;
339
+ struct splash_pic_priv *pp;
340
+
341
+ if (walker + sizeof(struct splash_blob_header)
342
+ > fw->data + fw->size)
343
+ goto err;
344
+
345
+ walker += sizeof(struct splash_blob_header);
346
+
347
+ if (walker + bh->length > fw->data + fw->size)
348
+ goto err;
349
+
350
+ if (bh->picture_id >= fp->header->num_pics)
351
+ goto nextblob;
352
+
353
+ pp = &fp->pics[bh->picture_id];
354
+
355
+ pr_debug("Blob %u, pic %u, blobs_loaded %u, num_blobs %u.\n",
356
+ i, bh->picture_id,
357
+ pp->blobs_loaded, pp->pic_header->num_blobs);
358
+
359
+ if (pp->blobs_loaded >= pp->pic_header->num_blobs)
360
+ goto nextblob;
361
+
362
+ switch (bh->type) {
363
+ case 0:
364
+ /* Raw 24-bit packed pixels */
365
+ if (bh->length != pp->pic_header->width
366
+ * pp->pic_header->height * 3) {
367
+ pr_err("Blob %u, type 1: Length doesn't match picture.\n",
368
+ i);
369
+
370
+ goto err;
371
+ }
372
+ break;
373
+ default:
374
+ pr_warn("Blob %u, unknown type %u.\n", i, bh->type);
375
+ goto nextblob;
376
+ }
377
+
378
+ pp->blobs[pp->blobs_loaded].blob_header = bh;
379
+ pp->blobs[pp->blobs_loaded].data = walker;
380
+ pp->blobs_loaded++;
381
+
382
+nextblob:
383
+ walker += bh->length;
384
+ if (bh->length % 16)
385
+ walker += 16 - (bh->length % 16);
386
+ }
387
+
388
+ if (walker != fw->data + fw->size)
389
+ pr_warn("Trailing data in splash file.\n");
390
+
391
+ /* Walk over pictures and ensure all blob slots are filled */
392
+ for (i = 0; i < fp->header->num_pics; i++) {
393
+ struct splash_pic_priv *pp = &fp->pics[i];
394
+
395
+ if (pp->blobs_loaded != pp->pic_header->num_blobs) {
396
+ pr_err("Picture %u doesn't have all blob slots filled.\n",
397
+ i);
398
+
399
+ goto err;
400
+ }
401
+ }
402
+
403
+ pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
404
+ fw->size,
405
+ fp->header->num_pics,
406
+ fp->header->num_blobs);
407
+
408
+ return fp;
409
+
410
+
411
+err:
412
+ bootsplash_free_file(fp);
413
+ return NULL;
414
+}
415
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
416
index 4d7e0117f653..2ae36949d0e3 100644
417
--- a/drivers/video/fbdev/core/bootsplash_render.c
418
+++ b/drivers/video/fbdev/core/bootsplash_render.c
419
@@ -19,6 +19,7 @@
420
#include <linux/types.h>
421
422
#include "bootsplash_internal.h"
423
+#include "uapi/linux/bootsplash_file.h"
424
425
426
427
@@ -70,16 +71,69 @@ static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
428
}
429
430
431
-void bootsplash_do_render_background(struct fb_info *info)
432
+/*
433
+ * Copy from source and blend into the destination picture.
434
+ * Currently assumes that the source picture is 24bpp.
435
+ * Currently assumes that the destination is <= 32bpp.
436
+ */
437
+static int splash_convert_to_fb(u8 *dst,
438
+ const struct fb_var_screeninfo *dst_var,
439
+ unsigned int dst_stride,
440
+ unsigned int dst_xoff,
441
+ unsigned int dst_yoff,
442
+ const u8 *src,
443
+ unsigned int src_width,
444
+ unsigned int src_height)
445
+{
446
+ unsigned int x, y;
447
+ unsigned int src_stride = 3 * src_width; /* Assume 24bpp packed */
448
+ u32 dst_octpp = dst_var->bits_per_pixel / 8;
449
+
450
+ dst_xoff += dst_var->xoffset;
451
+ dst_yoff += dst_var->yoffset;
452
+
453
+ /* Copy with stride and pixel size adjustment */
454
+ for (y = 0;
455
+ y < src_height && y + dst_yoff < dst_var->yres_virtual;
456
+ y++) {
457
+ const u8 *srcline = src + (y * src_stride);
458
+ u8 *dstline = dst + ((y + dst_yoff) * dst_stride)
459
+ + (dst_xoff * dst_octpp);
460
+
461
+ for (x = 0;
462
+ x < src_width && x + dst_xoff < dst_var->xres_virtual;
463
+ x++) {
464
+ u8 red, green, blue;
465
+ u32 dstpix;
466
+
467
+ /* Read pixel */
468
+ red = *srcline++;
469
+ green = *srcline++;
470
+ blue = *srcline++;
471
+
472
+ /* Write pixel */
473
+ dstpix = pack_pixel(dst_var, red, green, blue);
474
+ memcpy(dstline, &dstpix, dst_octpp);
475
+
476
+ dstline += dst_octpp;
477
+ }
478
+ }
479
+
480
+ return 0;
481
+}
482
+
483
+
484
+void bootsplash_do_render_background(struct fb_info *info,
485
+ const struct splash_file_priv *fp)
486
{
487
unsigned int x, y;
488
u32 dstpix;
489
u32 dst_octpp = info->var.bits_per_pixel / 8;
490
491
dstpix = pack_pixel(&info->var,
492
- 0,
493
- 0,
494
- 0);
495
+ fp->header->bg_red,
496
+ fp->header->bg_green,
497
+ fp->header->bg_blue);
498
499
for (y = 0; y < info->var.yres_virtual; y++) {
500
u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
501
@@ -91,3 +145,44 @@ void bootsplash_do_render_background(struct fb_info *info)
502
}
503
}
504
}
505
+
506
+
507
+void bootsplash_do_render_pictures(struct fb_info *info,
508
+ const struct splash_file_priv *fp)
509
+{
510
+ unsigned int i;
511
+
512
+ for (i = 0; i < fp->header->num_pics; i++) {
513
+ struct splash_blob_priv *bp;
514
+ struct splash_pic_priv *pp = &fp->pics[i];
515
+ long dst_xoff, dst_yoff;
516
+
517
+ if (pp->blobs_loaded < 1)
518
+ continue;
519
+
520
+ bp = &pp->blobs[0];
521
+
522
+ if (!bp || bp->blob_header->type != 0)
523
+ continue;
524
+
525
+ dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
526
+ dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
527
+
528
+ if (dst_xoff < 0
529
+ || dst_yoff < 0
530
+ || dst_xoff + pp->pic_header->width > info->var.xres
531
+ || dst_yoff + pp->pic_header->height > info->var.yres) {
532
+ pr_info_once("Picture %u is out of bounds at current resolution: %dx%d\n"
533
+ "(this will only be printed once every reboot)\n",
534
+ i, info->var.xres, info->var.yres);
535
+
536
+ continue;
537
+ }
538
+
539
+ /* Draw next splash frame */
540
+ splash_convert_to_fb(info->screen_buffer, &info->var,
541
+ info->fix.line_length, dst_xoff, dst_yoff,
542
+ bp->data,
543
+ pp->pic_header->width, pp->pic_header->height);
544
+ }
545
+}
546
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
547
new file mode 100644
548
index 000000000000..89dc9cca8f0c
549
--- /dev/null
550
+++ b/include/uapi/linux/bootsplash_file.h
551
@@ -0,0 +1,118 @@
552
+/*
553
+ * Kernel based bootsplash.
554
+ *
555
+ * (File format)
556
+ *
557
+ * Authors:
558
+ * Max Staudt <[email protected]>
559
+ *
560
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
561
+ */
562
+
563
+#ifndef __BOOTSPLASH_FILE_H
564
+#define __BOOTSPLASH_FILE_H
565
+
566
+
567
+#define BOOTSPLASH_VERSION 55561
568
+
569
+
570
+#include <linux/kernel.h>
571
+#include <linux/types.h>
572
+
573
+
574
+/*
575
+ * On-disk types
576
+ *
577
+ * A splash file consists of:
578
+ * - One single 'struct splash_file_header'
579
+ * - An array of 'struct splash_pic_header'
580
+ * - An array of raw data blocks, each padded to 16 bytes and
581
+ * preceded by a 'struct splash_blob_header'
582
+ *
583
+ * A single-frame splash may look like this:
584
+ *
585
+ * +--------------------+
586
+ * | |
587
+ * | splash_file_header |
588
+ * | -> num_blobs = 1 |
589
+ * | -> num_pics = 1 |
590
+ * | |
591
+ * +--------------------+
592
+ * | |
593
+ * | splash_pic_header |
594
+ * | |
595
+ * +--------------------+
596
+ * | |
597
+ * | splash_blob_header |
598
+ * | -> type = 0 |
599
+ * | -> picture_id = 0 |
600
+ * | |
601
+ * | (raw RGB data) |
602
+ * | (pad to 16 bytes) |
603
+ * | |
604
+ * +--------------------+
605
+ *
606
+ * All multi-byte values are stored on disk in the native format
607
+ * expected by the system the file will be used on.
608
+ */
609
+#define BOOTSPLASH_MAGIC_BE "Linux bootsplash"
610
+#define BOOTSPLASH_MAGIC_LE "hsalpstoob xuniL"
611
+
612
+struct splash_file_header {
613
+ uint8_t id[16]; /* "Linux bootsplash" (no trailing NUL) */
614
+
615
+ /* Splash file format version to avoid clashes */
616
+ uint16_t version;
617
+
618
+ /* The background color */
619
+ uint8_t bg_red;
620
+ uint8_t bg_green;
621
+ uint8_t bg_blue;
622
+ uint8_t bg_reserved;
623
+
624
+ /*
625
+ * Number of pic/blobs so we can allocate memory for internal
626
+ * structures ahead of time when reading the file
627
+ */
628
+ uint16_t num_blobs;
629
+ uint8_t num_pics;
630
+
631
+ uint8_t padding[103];
632
+} __attribute__((__packed__));
633
+
634
+
635
+struct splash_pic_header {
636
+ uint16_t width;
637
+ uint16_t height;
638
+
639
+ /*
640
+ * Number of data packages associated with this picture.
641
+ * Currently, the only use for more than 1 is for animations.
642
+ */
643
+ uint8_t num_blobs;
644
+
645
+ uint8_t padding[27];
646
+} __attribute__((__packed__));
647
+
648
+
649
+struct splash_blob_header {
650
+ /* Length of the data block in bytes. */
651
+ uint32_t length;
652
+
653
+ /*
654
+ * Type of the contents.
655
+ * 0 - Raw RGB data.
656
+ */
657
+ uint16_t type;
658
+
659
+ /*
660
+ * Picture this blob is associated with.
661
+ * Blobs will be added to a picture in the order they are
662
+ * found in the file.
663
+ */
664
+ uint8_t picture_id;
665
+
666
+ uint8_t padding[9];
667
+} __attribute__((__packed__));
668
+
669
+#endif
670
671