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