1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Convert a file image to a C define
4 *
5 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
7 * For testing EFI disk management we need an in memory image of
8 * a disk.
9 *
10 * The tool file2include converts a file to a C include. The file
11 * is separated into strings of 8 bytes. Only the non-zero strings
12 * are written to the include. The output format has been designed
13 * to maintain readability.
14 *
15 * As the disk image needed for testing contains mostly zeroes a high
16 * compression ratio can be attained.
17 */
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21
22/* Size of the blocks written to the compressed file */
23#define BLOCK_SIZE 8
24
25int main(int argc, char *argv[])
26{
27	FILE *file;
28	int ret;
29	unsigned char *buf;
30	size_t count, i, j;
31
32	/* Provide usage help */
33	if (argc != 2) {
34		printf("Usage:\n%s FILENAME\n", argv[0]);
35		return EXIT_FAILURE;
36	}
37	/* Open file */
38	file = fopen(argv[1], "r");
39	if (!file) {
40		perror("fopen");
41		return EXIT_FAILURE;
42	}
43	/* Get file length */
44	ret = fseek(file, 0, SEEK_END);
45	if (ret < 0) {
46		perror("fseek");
47		return EXIT_FAILURE;
48	}
49	count = ftell(file);
50	if (!count) {
51		fprintf(stderr, "File %s has length 0\n", argv[1]);
52		return EXIT_FAILURE;
53	}
54	rewind(file);
55	/* Read file */
56	buf = malloc(count);
57	if (!buf) {
58		perror("calloc");
59		return EXIT_FAILURE;
60	}
61	count = fread(buf, 1, count, file);
62
63	/* Generate output */
64	printf("/* SPDX-License-Identifier: GPL-2.0+ */\n");
65	printf("/*\n");
66	printf(" *  Non-zero %u byte strings of a disk image\n", BLOCK_SIZE);
67	printf(" *\n");
68	printf(" *  Generated with tools/file2include\n");
69	printf(" */\n\n");
70	printf("#define EFI_ST_DISK_IMG { 0x%08zx, { \\\n", count);
71
72	for (i = 0; i < count; i += BLOCK_SIZE) {
73		int c = 0;
74
75		for (j = i; j < i + BLOCK_SIZE && j < count; ++j) {
76			if (buf[j])
77				c = 1;
78		}
79		if (!c)
80			continue;
81		printf("\t{0x%08zx, \"", i);
82		for (j = i; j < i + BLOCK_SIZE && j < count; ++j)
83			printf("\\x%02x", buf[j]);
84		printf("\"}, /* ");
85		for (j = i; j < i + BLOCK_SIZE && j < count; ++j) {
86			if (buf[j] != '*' && buf[j] >= 0x20 && buf[j] <= 0x7e)
87				printf("%c", buf[j]);
88			else
89				printf(".");
90		}
91		printf(" */ \\\n");
92	}
93	printf("\t{0, NULL} } }\n");
94
95	/* Release resources */
96	free(buf);
97	ret = fclose(file);
98	if (ret) {
99		perror("fclose");
100		return EXIT_FAILURE;
101	}
102	return EXIT_SUCCESS;
103}
104