All of lore.kernel.org
 help / color / mirror / Atom feed
From: Max Staudt <mstaudt@suse.de>
To: b.zolnierkie@samsung.com, linux-fbdev@vger.kernel.org
Cc: mstaudt@suse.de, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, tiwai@suse.com, oneukum@suse.com,
	msrb@suse.com, sndirsch@suse.com, michal@markovi.net,
	philm@manjaro.org, bernhard.rosenkranzer@linaro.org
Subject: [RFC PATCH v2 12/13] tools/bootsplash: Add a basic splash file creation tool
Date: Wed, 13 Dec 2017 20:47:54 +0100	[thread overview]
Message-ID: <20171213194755.3409-13-mstaudt@suse.de> (raw)
In-Reply-To: <20171213194755.3409-1-mstaudt@suse.de>

Signed-off-by: Max Staudt <mstaudt@suse.de>
---
 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 <ast@kernel.org>
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 <mstaudt@suse.de>
+ *
+ * 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

WARNING: multiple messages have this Message-ID (diff)
From: Max Staudt <mstaudt@suse.de>
To: b.zolnierkie@samsung.com, linux-fbdev@vger.kernel.org
Cc: michal@markovi.net, sndirsch@suse.com, oneukum@suse.com,
	tiwai@suse.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, mstaudt@suse.de,
	bernhard.rosenkranzer@linaro.org, philm@manjaro.org
Subject: [RFC PATCH v2 12/13] tools/bootsplash: Add a basic splash file creation tool
Date: Wed, 13 Dec 2017 19:47:54 +0000	[thread overview]
Message-ID: <20171213194755.3409-13-mstaudt@suse.de> (raw)
In-Reply-To: <20171213194755.3409-1-mstaudt@suse.de>

Signed-off-by: Max Staudt <mstaudt@suse.de>
---
 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 <ast@kernel.org>
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 <mstaudt@suse.de>
+ *
+ * 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


WARNING: multiple messages have this Message-ID (diff)
From: Max Staudt <mstaudt@suse.de>
To: b.zolnierkie@samsung.com, linux-fbdev@vger.kernel.org
Cc: michal@markovi.net, sndirsch@suse.com, oneukum@suse.com,
	tiwai@suse.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, mstaudt@suse.de,
	bernhard.rosenkranzer@linaro.org, philm@manjaro.org
Subject: [RFC PATCH v2 12/13] tools/bootsplash: Add a basic splash file creation tool
Date: Wed, 13 Dec 2017 20:47:54 +0100	[thread overview]
Message-ID: <20171213194755.3409-13-mstaudt@suse.de> (raw)
In-Reply-To: <20171213194755.3409-1-mstaudt@suse.de>

Signed-off-by: Max Staudt <mstaudt@suse.de>
---
 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 <ast@kernel.org>
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 <mstaudt@suse.de>
+ *
+ * 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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2017-12-13 19:49 UTC|newest]

Thread overview: 193+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-13 19:47 [RFC PATCH v2 00/13] Kernel based bootsplash Max Staudt
2017-12-13 19:47 ` Max Staudt
2017-12-13 19:47 ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 01/13] bootsplash: Initial implementation showing black screen Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 23:55   ` Randy Dunlap
2017-12-13 23:55     ` Randy Dunlap
2017-12-14 15:37     ` Max Staudt
2017-12-14 15:37       ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 02/13] bootsplash: Add file reading and picture rendering Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 03/13] bootsplash: Flush framebuffer after drawing Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 21:35   ` Daniel Vetter
2017-12-13 21:35     ` Daniel Vetter
2017-12-13 21:35     ` Daniel Vetter
2017-12-14 15:36     ` Max Staudt
2017-12-14 15:36       ` Max Staudt
2017-12-14 15:36       ` Max Staudt
2017-12-19 12:23       ` Daniel Vetter
2017-12-19 12:23         ` Daniel Vetter
2017-12-19 12:23         ` Daniel Vetter
2017-12-19 13:34         ` Max Staudt
2017-12-19 13:34           ` Max Staudt
2017-12-19 13:34           ` Max Staudt
2017-12-19 13:57           ` Daniel Vetter
2017-12-19 13:57             ` Daniel Vetter
2017-12-19 14:07             ` Oliver Neukum
2017-12-19 14:07               ` Oliver Neukum
2017-12-31 12:53               ` Alan Cox
2017-12-31 12:53                 ` Alan Cox
2017-12-31 12:53                 ` Alan Cox
2018-01-03 18:04                 ` Max Staudt
2018-01-03 18:04                   ` Max Staudt
2018-01-03 18:04                   ` Max Staudt
2017-12-19 15:41             ` Max Staudt
2017-12-19 15:41               ` Max Staudt
2017-12-19 15:41               ` Max Staudt
2017-12-19 16:02               ` Daniel Vetter
2017-12-19 16:02                 ` Daniel Vetter
2017-12-19 16:02                 ` Daniel Vetter
2017-12-19 16:23                 ` Max Staudt
2017-12-19 16:23                   ` Max Staudt
2017-12-19 16:23                   ` Max Staudt
2017-12-20  9:45                   ` Daniel Vetter
2017-12-20  9:45                     ` Daniel Vetter
2017-12-20  9:45                     ` Daniel Vetter
2017-12-19 16:09               ` Daniel Vetter
2017-12-19 16:09                 ` Daniel Vetter
2017-12-19 16:09                 ` Daniel Vetter
2017-12-19 16:26                 ` Max Staudt
2017-12-19 16:26                   ` Max Staudt
2017-12-19 16:26                   ` Max Staudt
2017-12-19 21:01               ` Ray Strode
2017-12-19 21:01                 ` Ray Strode
2017-12-19 21:01                 ` Ray Strode
2017-12-20 13:14                 ` Max Staudt
2017-12-20 13:14                   ` Max Staudt
2017-12-20 13:14                   ` Max Staudt
2017-12-20 15:35                   ` Ray Strode
2017-12-20 15:35                     ` Ray Strode
2017-12-20 15:35                     ` Ray Strode
2017-12-20 16:52                     ` Max Staudt
2017-12-20 16:52                       ` Max Staudt
2017-12-20 16:52                       ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 04/13] bootsplash: Add corner positioning Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 05/13] bootsplash: Add animation support Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 06/13] vt: Redraw bootsplash fully on console_unblank Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 07/13] vt: Add keyboard hook to disable bootsplash Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 08/13] sysrq: Disable bootsplash on SAK Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 09/13] fbcon: Disable bootsplash on oops Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 10/13] Documentation: Add bootsplash main documentation Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 11/13] bootsplash: sysfs entries to load and unload files Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` Max Staudt [this message]
2017-12-13 19:47   ` [RFC PATCH v2 12/13] tools/bootsplash: Add a basic splash file creation tool Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47 ` [RFC PATCH v2 13/13] tools/bootsplash: Add script and data to create sample file Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:47   ` Max Staudt
2017-12-13 19:52 ` [RFC PATCH v2 00/13] Kernel based bootsplash Max Staudt
2017-12-13 19:52   ` Max Staudt
2017-12-13 19:52   ` Max Staudt
2017-12-19 16:16 ` Daniel Vetter
2017-12-19 16:16   ` Daniel Vetter
2017-12-19 16:16   ` Daniel Vetter
2017-12-19 17:04   ` Max Staudt
2017-12-19 17:04     ` Max Staudt
2017-12-19 17:04     ` Max Staudt
2017-12-19 17:26     ` Daniel Vetter
2017-12-19 17:26       ` Daniel Vetter
2017-12-19 17:26       ` Daniel Vetter
2017-12-19 18:40       ` Max Staudt
2017-12-19 18:40         ` Max Staudt
2017-12-19 18:40         ` Max Staudt
2017-12-20  9:43         ` Daniel Vetter
2017-12-20  9:43           ` Daniel Vetter
2017-12-20  9:43           ` Daniel Vetter
2017-12-20 10:06           ` Neil Armstrong
2017-12-20 10:06             ` Neil Armstrong
2017-12-20 10:06             ` Neil Armstrong
2017-12-20 10:14             ` Daniel Vetter
2017-12-20 10:14               ` Daniel Vetter
2017-12-20 10:14               ` Daniel Vetter
2017-12-20 14:55               ` Max Staudt
2017-12-20 14:55                 ` Max Staudt
2017-12-20 15:11                 ` Daniel Vetter
2017-12-20 15:11                   ` Daniel Vetter
2017-12-20 15:11                   ` Daniel Vetter
2017-12-20 15:19                   ` Daniel Vetter
2017-12-20 15:19                     ` Daniel Vetter
2017-12-20 15:19                     ` Daniel Vetter
2017-12-20 15:22                     ` Daniel Vetter
2017-12-20 15:22                       ` Daniel Vetter
2017-12-20 15:22                       ` Daniel Vetter
2017-12-20 16:23                     ` Max Staudt
2017-12-20 16:23                       ` Max Staudt
2017-12-20 16:23                       ` Max Staudt
2017-12-20 16:15                   ` Max Staudt
2017-12-20 16:15                     ` Max Staudt
2017-12-20 16:15                     ` Max Staudt
2017-12-31 12:44                   ` Alan Cox
2017-12-31 12:44                     ` Alan Cox
2017-12-31 12:44                     ` Alan Cox
2018-01-03 18:00                     ` Max Staudt
2018-01-03 18:00                       ` Max Staudt
2017-12-20 14:16             ` Max Staudt
2017-12-20 14:16               ` Max Staudt
2017-12-20 14:16               ` Max Staudt
2017-12-20 14:10           ` Max Staudt
2017-12-20 14:10             ` Max Staudt
2017-12-20 14:10             ` Max Staudt
2017-12-31 12:35         ` Alan Cox
2017-12-31 12:35           ` Alan Cox
2017-12-31 12:35           ` Alan Cox
2018-01-03 17:56           ` Max Staudt
2018-01-03 17:56             ` Max Staudt
2018-01-03 17:56             ` Max Staudt
2017-12-19 20:30     ` Ray Strode
2017-12-19 20:30       ` Ray Strode
2017-12-19 20:30       ` Ray Strode
2017-12-20 13:03       ` Max Staudt
2017-12-20 13:03         ` Max Staudt
2017-12-20 13:03         ` Max Staudt
2017-12-20 15:21         ` Ray Strode
2017-12-20 15:21           ` Ray Strode
2017-12-20 15:21           ` Ray Strode
2017-12-20 16:44           ` Max Staudt
2017-12-20 16:44             ` Max Staudt
2017-12-20 16:44             ` Max Staudt
2017-12-21 14:51             ` Ray Strode
2017-12-21 14:51               ` Ray Strode
2017-12-21 14:51               ` Ray Strode
2017-12-21 16:32               ` Max Staudt
2017-12-21 16:32                 ` Max Staudt
2017-12-20 11:08   ` Johannes Thumshirn
2017-12-20 11:08     ` Johannes Thumshirn
2017-12-20 11:22     ` Daniel Stone
2017-12-20 11:22       ` Daniel Stone
2017-12-20 11:22       ` Daniel Stone
2017-12-20 12:48       ` Johannes Thumshirn
2017-12-20 12:48         ` Johannes Thumshirn
2017-12-29 17:13   ` Jani Nikula
2017-12-29 17:13     ` Jani Nikula
2017-12-29 17:13     ` Jani Nikula
2018-01-03 17:38     ` Max Staudt
2018-01-03 17:38       ` Max Staudt
2017-12-21  9:48 ` Daniel Vetter
2017-12-21  9:48   ` Daniel Vetter
2017-12-21  9:48   ` Daniel Vetter
2017-12-21 16:52   ` Max Staudt
2017-12-21 16:52     ` Max Staudt
2017-12-21 16:52     ` Max Staudt
2017-12-21 15:00 ` Philip Müller
2017-12-21 15:00   ` Philip Müller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171213194755.3409-13-mstaudt@suse.de \
    --to=mstaudt@suse.de \
    --cc=b.zolnierkie@samsung.com \
    --cc=bernhard.rosenkranzer@linaro.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michal@markovi.net \
    --cc=msrb@suse.com \
    --cc=oneukum@suse.com \
    --cc=philm@manjaro.org \
    --cc=sndirsch@suse.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.