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/0012-bootsplash.patch
Views: 3959
1
diff --git a/MAINTAINERS b/MAINTAINERS
2
index 7ffac272434e..ddff07cd794c 100644
3
--- a/MAINTAINERS
4
+++ b/MAINTAINERS
5
@@ -2715,6 +2715,7 @@ F: drivers/video/fbdev/core/bootsplash*.*
6
F: drivers/video/fbdev/core/dummycon.c
7
F: include/linux/bootsplash.h
8
F: include/uapi/linux/bootsplash_file.h
9
+F: tools/bootsplash/*
10
11
BPF (Safe dynamic programs and tools)
12
M: Alexei Starovoitov <[email protected]>
13
diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
14
new file mode 100644
15
index 000000000000..091b99a17567
16
--- /dev/null
17
+++ b/tools/bootsplash/.gitignore
18
@@ -0,0 +1 @@
19
+bootsplash-packer
20
diff --git a/tools/bootsplash/Makefile b/tools/bootsplash/Makefile
21
new file mode 100644
22
index 000000000000..0ad8e8a84942
23
--- /dev/null
24
+++ b/tools/bootsplash/Makefile
25
@@ -0,0 +1,9 @@
26
+CC := $(CROSS_COMPILE)gcc
27
+CFLAGS := -I../../usr/include
28
+
29
+PROGS := bootsplash-packer
30
+
31
+all: $(PROGS)
32
+
33
+clean:
34
+ rm -fr $(PROGS)
35
diff --git a/tools/bootsplash/bootsplash-packer.c b/tools/bootsplash/bootsplash-packer.c
36
new file mode 100644
37
index 000000000000..ffb6a8b69885
38
--- /dev/null
39
+++ b/tools/bootsplash/bootsplash-packer.c
40
@@ -0,0 +1,471 @@
41
+/*
42
+ * Kernel based bootsplash.
43
+ *
44
+ * (Splash file packer tool)
45
+ *
46
+ * Authors:
47
+ * Max Staudt <[email protected]>
48
+ *
49
+ * SPDX-License-Identifier: GPL-2.0
50
+ */
51
+
52
+#include <endian.h>
53
+#include <getopt.h>
54
+#include <stdint.h>
55
+#include <stdio.h>
56
+#include <stdlib.h>
57
+#include <string.h>
58
+
59
+#include <linux/bootsplash_file.h>
60
+
61
+
62
+static void print_help(char *progname)
63
+{
64
+ printf("Usage: %s [OPTIONS] outfile\n", progname);
65
+ printf("\n"
66
+ "Options, executed in order given:\n"
67
+ " -h, --help Print this help message\n"
68
+ "\n"
69
+ " --bg_red <u8> Background color (red part)\n"
70
+ " --bg_green <u8> Background color (green part)\n"
71
+ " --bg_blue <u8> Background color (blue part)\n"
72
+ " --bg_reserved <u8> (do not use)\n"
73
+ " --frame_ms <u16> Minimum milliseconds between animation steps\n"
74
+ "\n"
75
+ " --picture Start describing the next picture\n"
76
+ " --pic_width <u16> Picture width in pixels\n"
77
+ " --pic_height <u16> Picture height in pixels\n"
78
+ " --pic_position <u8> Coarse picture placement:\n"
79
+ " 0x00 - Top left\n"
80
+ " 0x01 - Top\n"
81
+ " 0x02 - Top right\n"
82
+ " 0x03 - Right\n"
83
+ " 0x04 - Bottom right\n"
84
+ " 0x05 - Bottom\n"
85
+ " 0x06 - Bottom left\n"
86
+ " 0x07 - Left\n"
87
+ "\n"
88
+ " Flags:\n"
89
+ " 0x10 - Calculate offset from corner towards center,\n"
90
+ " rather than from center towards corner\n"
91
+ " --pic_position_offset <u16> Distance from base position in pixels\n"
92
+ " --pic_anim_type <u8> Animation type:\n"
93
+ " 0 - None\n"
94
+ " 1 - Forward loop\n"
95
+ " --pic_anim_loop <u8> Loop point for animation\n"
96
+ "\n"
97
+ " --blob <filename> Include next data stream\n"
98
+ " --blob_type <u16> Type of data\n"
99
+ " --blob_picture_id <u8> Picture to associate this blob with, starting at 0\n"
100
+ " (default: number of last --picture)\n"
101
+ "\n");
102
+ printf("This tool will write %s files.\n\n",
103
+#if __BYTE_ORDER == __BIG_ENDIAN
104
+ "Big Endian (BE)");
105
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
106
+ "Little Endian (LE)");
107
+#else
108
+#error
109
+#endif
110
+}
111
+
112
+
113
+struct blob_entry {
114
+ struct blob_entry *next;
115
+
116
+ char *fn;
117
+
118
+ struct splash_blob_header header;
119
+};
120
+
121
+
122
+static void dump_file_header(struct splash_file_header *h)
123
+{
124
+ printf(" --- File header ---\n");
125
+ printf("\n");
126
+ printf(" version: %5u\n", h->version);
127
+ printf("\n");
128
+ printf(" bg_red: %5u\n", h->bg_red);
129
+ printf(" bg_green: %5u\n", h->bg_green);
130
+ printf(" bg_blue: %5u\n", h->bg_blue);
131
+ printf(" bg_reserved: %5u\n", h->bg_reserved);
132
+ printf("\n");
133
+ printf(" num_blobs: %5u\n", h->num_blobs);
134
+ printf(" num_pics: %5u\n", h->num_pics);
135
+ printf("\n");
136
+ printf(" frame_ms: %5u\n", h->frame_ms);
137
+ printf("\n");
138
+}
139
+
140
+static void dump_pic_header(struct splash_pic_header *ph)
141
+{
142
+ printf(" --- Picture header ---\n");
143
+ printf("\n");
144
+ printf(" width: %5u\n", ph->width);
145
+ printf(" height: %5u\n", ph->height);
146
+ printf("\n");
147
+ printf(" num_blobs: %5u\n", ph->num_blobs);
148
+ printf("\n");
149
+ printf(" position: %0x3x\n", ph->position);
150
+ printf(" position_offset: %5u\n", ph->position_offset);
151
+ printf("\n");
152
+ printf(" anim_type: %5u\n", ph->anim_type);
153
+ printf(" anim_loop: %5u\n", ph->anim_loop);
154
+ printf("\n");
155
+}
156
+
157
+static void dump_blob(struct blob_entry *b)
158
+{
159
+ printf(" --- Blob header ---\n");
160
+ printf("\n");
161
+ printf(" length: %7u\n", b->header.length);
162
+ printf(" type: %7u\n", b->header.type);
163
+ printf("\n");
164
+ printf(" picture_id: %7u\n", b->header.picture_id);
165
+ printf("\n");
166
+}
167
+
168
+
169
+#define OPT_MAX(var, max) \
170
+ do { \
171
+ if ((var) > max) { \
172
+ fprintf(stderr, "--%s: Invalid value\n", \
173
+ long_options[option_index].name); \
174
+ break; \
175
+ } \
176
+ } while (0)
177
+
178
+static struct option long_options[] = {
179
+ {"help", 0, 0, 'h'},
180
+ {"bg_red", 1, 0, 10001},
181
+ {"bg_green", 1, 0, 10002},
182
+ {"bg_blue", 1, 0, 10003},
183
+ {"bg_reserved", 1, 0, 10004},
184
+ {"frame_ms", 1, 0, 10005},
185
+ {"picture", 0, 0, 20000},
186
+ {"pic_width", 1, 0, 20001},
187
+ {"pic_height", 1, 0, 20002},
188
+ {"pic_position", 1, 0, 20003},
189
+ {"pic_position_offset", 1, 0, 20004},
190
+ {"pic_anim_type", 1, 0, 20005},
191
+ {"pic_anim_loop", 1, 0, 20006},
192
+ {"blob", 1, 0, 30000},
193
+ {"blob_type", 1, 0, 30001},
194
+ {"blob_picture_id", 1, 0, 30002},
195
+ {NULL, 0, NULL, 0}
196
+};
197
+
198
+
199
+int main(int argc, char **argv)
200
+{
201
+ FILE *of;
202
+ char *ofn;
203
+ int c;
204
+ int option_index = 0;
205
+
206
+ unsigned long ul;
207
+ struct splash_file_header fh = {};
208
+ struct splash_pic_header ph[255];
209
+ struct blob_entry *blob_first = NULL;
210
+ struct blob_entry *blob_last = NULL;
211
+ struct blob_entry *blob_cur = NULL;
212
+
213
+ if (argc < 2) {
214
+ print_help(argv[0]);
215
+ return EXIT_FAILURE;
216
+ }
217
+
218
+
219
+ /* Parse and and execute user commands */
220
+ while ((c = getopt_long(argc, argv, "h",
221
+ long_options, &option_index)) != -1) {
222
+ switch (c) {
223
+ case 10001: /* bg_red */
224
+ ul = strtoul(optarg, NULL, 0);
225
+ OPT_MAX(ul, 255);
226
+ fh.bg_red = ul;
227
+ break;
228
+ case 10002: /* bg_green */
229
+ ul = strtoul(optarg, NULL, 0);
230
+ OPT_MAX(ul, 255);
231
+ fh.bg_green = ul;
232
+ break;
233
+ case 10003: /* bg_blue */
234
+ ul = strtoul(optarg, NULL, 0);
235
+ OPT_MAX(ul, 255);
236
+ fh.bg_blue = ul;
237
+ break;
238
+ case 10004: /* bg_reserved */
239
+ ul = strtoul(optarg, NULL, 0);
240
+ OPT_MAX(ul, 255);
241
+ fh.bg_reserved = ul;
242
+ break;
243
+ case 10005: /* frame_ms */
244
+ ul = strtoul(optarg, NULL, 0);
245
+ OPT_MAX(ul, 65535);
246
+ fh.frame_ms = ul;
247
+ break;
248
+
249
+
250
+ case 20000: /* picture */
251
+ if (fh.num_pics >= 255) {
252
+ fprintf(stderr, "--%s: Picture array full\n",
253
+ long_options[option_index].name);
254
+ break;
255
+ }
256
+
257
+ fh.num_pics++;
258
+ break;
259
+
260
+ case 20001: /* pic_width */
261
+ ul = strtoul(optarg, NULL, 0);
262
+ OPT_MAX(ul, 65535);
263
+ ph[fh.num_pics - 1].width = ul;
264
+ break;
265
+
266
+ case 20002: /* pic_height */
267
+ ul = strtoul(optarg, NULL, 0);
268
+ OPT_MAX(ul, 65535);
269
+ ph[fh.num_pics - 1].height = ul;
270
+ break;
271
+
272
+ case 20003: /* pic_position */
273
+ ul = strtoul(optarg, NULL, 0);
274
+ OPT_MAX(ul, 255);
275
+ ph[fh.num_pics - 1].position = ul;
276
+ break;
277
+
278
+ case 20004: /* pic_position_offset */
279
+ ul = strtoul(optarg, NULL, 0);
280
+ OPT_MAX(ul, 255);
281
+ ph[fh.num_pics - 1].position_offset = ul;
282
+ break;
283
+
284
+ case 20005: /* pic_anim_type */
285
+ ul = strtoul(optarg, NULL, 0);
286
+ OPT_MAX(ul, 255);
287
+ ph[fh.num_pics - 1].anim_type = ul;
288
+ break;
289
+
290
+ case 20006: /* pic_anim_loop */
291
+ ul = strtoul(optarg, NULL, 0);
292
+ OPT_MAX(ul, 255);
293
+ ph[fh.num_pics - 1].anim_loop = ul;
294
+ break;
295
+
296
+
297
+ case 30000: /* blob */
298
+ if (fh.num_blobs >= 65535) {
299
+ fprintf(stderr, "--%s: Blob array full\n",
300
+ long_options[option_index].name);
301
+ break;
302
+ }
303
+
304
+ blob_cur = calloc(1, sizeof(struct blob_entry));
305
+ if (!blob_cur) {
306
+ fprintf(stderr, "--%s: Out of memory\n",
307
+ long_options[option_index].name);
308
+ break;
309
+ }
310
+
311
+ blob_cur->fn = optarg;
312
+ if (fh.num_pics)
313
+ blob_cur->header.picture_id = fh.num_pics - 1;
314
+
315
+ if (!blob_first)
316
+ blob_first = blob_cur;
317
+ if (blob_last)
318
+ blob_last->next = blob_cur;
319
+ blob_last = blob_cur;
320
+ fh.num_blobs++;
321
+ break;
322
+
323
+ case 30001: /* blob_type */
324
+ if (!blob_cur) {
325
+ fprintf(stderr, "--%s: No blob selected\n",
326
+ long_options[option_index].name);
327
+ break;
328
+ }
329
+
330
+ ul = strtoul(optarg, NULL, 0);
331
+ OPT_MAX(ul, 255);
332
+ blob_cur->header.type = ul;
333
+ break;
334
+
335
+ case 30002: /* blob_picture_id */
336
+ if (!blob_cur) {
337
+ fprintf(stderr, "--%s: No blob selected\n",
338
+ long_options[option_index].name);
339
+ break;
340
+ }
341
+
342
+ ul = strtoul(optarg, NULL, 0);
343
+ OPT_MAX(ul, 255);
344
+ blob_cur->header.picture_id = ul;
345
+ break;
346
+
347
+
348
+
349
+ case 'h':
350
+ case '?':
351
+ default:
352
+ print_help(argv[0]);
353
+ goto EXIT;
354
+ } /* switch (c) */
355
+ } /* while ((c = getopt_long(...)) != -1) */
356
+
357
+ /* Consume and drop lone arguments */
358
+ while (optind < argc) {
359
+ ofn = argv[optind];
360
+ optind++;
361
+ }
362
+
363
+
364
+ /* Read file lengths */
365
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
366
+ FILE *f;
367
+ long pos;
368
+ int i;
369
+
370
+ if (!blob_cur->fn)
371
+ continue;
372
+
373
+ f = fopen(blob_cur->fn, "rb");
374
+ if (!f)
375
+ goto ERR_FILE_LEN;
376
+
377
+ if (fseek(f, 0, SEEK_END))
378
+ goto ERR_FILE_LEN;
379
+
380
+ pos = ftell(f);
381
+ if (pos < 0 || pos > (1 << 30))
382
+ goto ERR_FILE_LEN;
383
+
384
+ blob_cur->header.length = pos;
385
+
386
+ fclose(f);
387
+ continue;
388
+
389
+ERR_FILE_LEN:
390
+ fprintf(stderr, "Error getting file length (or too long): %s\n",
391
+ blob_cur->fn);
392
+ if (f)
393
+ fclose(f);
394
+ continue;
395
+ }
396
+
397
+
398
+ /* Set magic headers */
399
+#if __BYTE_ORDER == __BIG_ENDIAN
400
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_BE, 16);
401
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
402
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_LE, 16);
403
+#else
404
+#error
405
+#endif
406
+ fh.version = BOOTSPLASH_VERSION;
407
+
408
+ /* Set blob counts */
409
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
410
+ if (blob_cur->header.picture_id < fh.num_pics)
411
+ ph[blob_cur->header.picture_id].num_blobs++;
412
+ }
413
+
414
+
415
+ /* Dump structs */
416
+ dump_file_header(&fh);
417
+
418
+ for (ul = 0; ul < fh.num_pics; ul++)
419
+ dump_pic_header(&ph[ul]);
420
+
421
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next)
422
+ dump_blob(blob_cur);
423
+
424
+
425
+ /* Write to file */
426
+ printf("Writing splash to file: %s\n", ofn);
427
+ of = fopen(ofn, "wb");
428
+ if (!of)
429
+ goto ERR_WRITING;
430
+
431
+ if (fwrite(&fh, sizeof(struct splash_file_header), 1, of) != 1)
432
+ goto ERR_WRITING;
433
+
434
+ for (ul = 0; ul < fh.num_pics; ul++) {
435
+ if (fwrite(&ph[ul], sizeof(struct splash_pic_header), 1, of)
436
+ != 1)
437
+ goto ERR_WRITING;
438
+ }
439
+
440
+ blob_cur = blob_first;
441
+ while (blob_cur) {
442
+ struct blob_entry *blob_old = blob_cur;
443
+ FILE *f;
444
+ char *buf[256];
445
+ uint32_t left;
446
+
447
+ if (fwrite(&blob_cur->header,
448
+ sizeof(struct splash_blob_header), 1, of) != 1)
449
+ goto ERR_WRITING;
450
+
451
+ if (!blob_cur->header.length || !blob_cur->fn)
452
+ continue;
453
+
454
+ f = fopen(blob_cur->fn, "rb");
455
+ if (!f)
456
+ goto ERR_FILE_COPY;
457
+
458
+ left = blob_cur->header.length;
459
+ while (left >= sizeof(buf)) {
460
+ if (fread(buf, sizeof(buf), 1, f) != 1)
461
+ goto ERR_FILE_COPY;
462
+ if (fwrite(buf, sizeof(buf), 1, of) != 1)
463
+ goto ERR_FILE_COPY;
464
+ left -= sizeof(buf);
465
+ }
466
+ if (left) {
467
+ if (fread(buf, left, 1, f) != 1)
468
+ goto ERR_FILE_COPY;
469
+ if (fwrite(buf, left, 1, of) != 1)
470
+ goto ERR_FILE_COPY;
471
+ }
472
+
473
+ /* Pad data stream to 16 bytes */
474
+ if (left % 16) {
475
+ if (fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
476
+ 16 - (left % 16), 1, of) != 1)
477
+ goto ERR_FILE_COPY;
478
+ }
479
+
480
+ fclose(f);
481
+ blob_cur = blob_cur->next;
482
+ free(blob_old);
483
+ continue;
484
+
485
+ERR_FILE_COPY:
486
+ if (f)
487
+ fclose(f);
488
+ goto ERR_WRITING;
489
+ }
490
+
491
+ fclose(of);
492
+
493
+EXIT:
494
+ return EXIT_SUCCESS;
495
+
496
+
497
+ERR_WRITING:
498
+ fprintf(stderr, "Error writing splash.\n");
499
+ fprintf(stderr, "The output file is probably corrupt.\n");
500
+ if (of)
501
+ fclose(of);
502
+
503
+ while (blob_cur) {
504
+ struct blob_entry *blob_old = blob_cur;
505
+
506
+ blob_cur = blob_cur->next;
507
+ free(blob_old);
508
+ }
509
+
510
+ return EXIT_FAILURE;
511
+}
512
513