2 * Copyright (C) 2015 Thomas Hebb <tommyhebb@gmail.com>
4 * The format of the header this tool generates was first documented by
5 * Chris Blake <chrisrblake93 (at) gmail.com> in a shell script of the
6 * same purpose. I have created this reimplementation at his request. The
7 * original script can be found at:
8 * <https://github.com/riptidewave93/meraki-partbuilder>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
23 #include <arpa/inet.h>
27 #define PADDING_BYTE 0xff
29 #define HDR_LENGTH 0x00000400
30 #define HDR_OFF_MAGIC1 0
31 #define HDR_OFF_HDRLEN 4
32 #define HDR_OFF_IMAGELEN 8
33 #define HDR_OFF_CHECKSUM 12
34 #define HDR_OFF_MAGIC2 32
35 #define HDR_OFF_FILLER 36
36 #define HDR_OFF_STATICHASH 40
41 unsigned char statichash[20];
49 static char *progname;
51 static char *board_id;
52 static const struct board_info *board;
54 static const struct board_info boards[] = {
57 .description = "Meraki MR18 Access Point",
59 .imagelen = 0x00800000,
60 .statichash = {0xda, 0x39, 0xa3, 0xee, 0x5e,
61 0x6b, 0x4b, 0x0d, 0x32, 0x55,
62 0xbf, 0xef, 0x95, 0x60, 0x18,
63 0x90, 0xaf, 0xd8, 0x07, 0x09},
65 /* terminating entry */
72 #define ERR(fmt, ...) do { \
74 fprintf(stderr, "[%s] *** error: " fmt "\n", \
75 progname, ## __VA_ARGS__); \
78 #define ERRS(fmt, ...) do { \
81 fprintf(stderr, "[%s] *** error: " fmt "\n", \
82 progname, ## __VA_ARGS__, strerror(save)); \
85 static const struct board_info *find_board(const char *id)
87 const struct board_info *ret;
88 const struct board_info *board;
91 for (board = boards; board->id != NULL; board++) {
92 if (strcasecmp(id, board->id) == 0) {
101 static void usage(int status)
103 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
104 const struct board_info *board;
106 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
110 " -B <board> create image for the board specified with <board>\n"
111 " -i <file> read kernel image from the file <file>\n"
112 " -o <file> write output to the file <file>\n"
113 " -s strip padding from the end of the image\n"
114 " -h show this screen\n"
117 fprintf(stream, "\nBoards:\n");
118 for (board = boards; board->id != NULL; board++)
119 fprintf(stream, " %-16s%s\n", board->id, board->description);
124 void writel(unsigned char *buf, size_t offset, uint32_t value)
126 value = htonl(value);
127 memcpy(buf + offset, &value, sizeof(uint32_t));
130 int main(int argc, char *argv[])
132 int ret = EXIT_FAILURE;
135 unsigned char *kernel;
138 bool strip_padding = false;
139 char *ofname = NULL, *ifname = NULL;
142 progname = basename(argv[0]);
147 c = getopt(argc, argv, "B:i:o:sh");
162 strip_padding = true;
173 if (board_id == NULL) {
174 ERR("no board specified");
178 board = find_board(board_id);
180 ERR("unknown board \"%s\"", board_id);
184 if (ifname == NULL) {
185 ERR("no input file specified");
189 if (ofname == NULL) {
190 ERR("no output file specified");
194 in = fopen(ifname, "r");
196 ERRS("could not open \"%s\" for reading: %s", ifname);
200 buflen = board->imagelen;
201 kspace = buflen - HDR_LENGTH;
203 /* Get kernel length */
204 fseek(in, 0, SEEK_END);
209 ERR("file \"%s\" is too big - max size: 0x%08lX\n",
214 /* If requested, resize buffer to remove padding */
216 buflen = klen + HDR_LENGTH;
218 /* Allocate and initialize buffer for final image */
219 buf = malloc(buflen);
221 ERRS("no memory for buffer: %s\n");
224 memset(buf, PADDING_BYTE, buflen);
227 kernel = buf + HDR_LENGTH;
228 fread(kernel, klen, 1, in);
230 /* Write magic values and filler */
231 writel(buf, HDR_OFF_MAGIC1, board->magic);
232 writel(buf, HDR_OFF_MAGIC2, board->magic);
233 writel(buf, HDR_OFF_FILLER, 0);
235 /* Write header and image length */
236 writel(buf, HDR_OFF_HDRLEN, HDR_LENGTH);
237 writel(buf, HDR_OFF_IMAGELEN, klen);
239 /* Write checksum and static hash */
240 sha1_csum(kernel, klen, buf + HDR_OFF_CHECKSUM);
241 memcpy(buf + HDR_OFF_STATICHASH, board->statichash, 20);
243 /* Save finished image */
244 out = fopen(ofname, "w");
246 ERRS("could not open \"%s\" for writing: %s", ofname);
249 fwrite(buf, buflen, 1, out);