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},
66 .description
= "Meraki MR24 Access Point",
68 .imagelen
= 0x00800000,
69 .statichash
= {0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff},
75 /* terminating entry */
82 #define ERR(fmt, ...) do { \
84 fprintf(stderr, "[%s] *** error: " fmt "\n", \
85 progname, ## __VA_ARGS__); \
88 #define ERRS(fmt, ...) do { \
91 fprintf(stderr, "[%s] *** error: " fmt "\n", \
92 progname, ## __VA_ARGS__, strerror(save)); \
95 static const struct board_info
*find_board(const char *id
)
97 const struct board_info
*ret
;
98 const struct board_info
*board
;
101 for (board
= boards
; board
->id
!= NULL
; board
++) {
102 if (strcasecmp(id
, board
->id
) == 0) {
111 static void usage(int status
)
113 FILE *stream
= (status
!= EXIT_SUCCESS
) ? stderr
: stdout
;
114 const struct board_info
*board
;
116 fprintf(stream
, "Usage: %s [OPTIONS...]\n", progname
);
120 " -B <board> create image for the board specified with <board>\n"
121 " -i <file> read kernel image from the file <file>\n"
122 " -o <file> write output to the file <file>\n"
123 " -s strip padding from the end of the image\n"
124 " -h show this screen\n"
127 fprintf(stream
, "\nBoards:\n");
128 for (board
= boards
; board
->id
!= NULL
; board
++)
129 fprintf(stream
, " %-16s%s\n", board
->id
, board
->description
);
134 void writel(unsigned char *buf
, size_t offset
, uint32_t value
)
136 value
= htonl(value
);
137 memcpy(buf
+ offset
, &value
, sizeof(uint32_t));
140 int main(int argc
, char *argv
[])
142 int ret
= EXIT_FAILURE
;
145 unsigned char *kernel
;
148 bool strip_padding
= false;
149 char *ofname
= NULL
, *ifname
= NULL
;
152 progname
= basename(argv
[0]);
157 c
= getopt(argc
, argv
, "B:i:o:sh");
172 strip_padding
= true;
183 if (board_id
== NULL
) {
184 ERR("no board specified");
188 board
= find_board(board_id
);
190 ERR("unknown board \"%s\"", board_id
);
194 if (ifname
== NULL
) {
195 ERR("no input file specified");
199 if (ofname
== NULL
) {
200 ERR("no output file specified");
204 in
= fopen(ifname
, "r");
206 ERRS("could not open \"%s\" for reading: %s", ifname
);
210 buflen
= board
->imagelen
;
211 kspace
= buflen
- HDR_LENGTH
;
213 /* Get kernel length */
214 fseek(in
, 0, SEEK_END
);
219 ERR("file \"%s\" is too big - max size: 0x%08lX\n",
224 /* If requested, resize buffer to remove padding */
226 buflen
= klen
+ HDR_LENGTH
;
228 /* Allocate and initialize buffer for final image */
229 buf
= malloc(buflen
);
231 ERRS("no memory for buffer: %s\n");
234 memset(buf
, PADDING_BYTE
, buflen
);
237 kernel
= buf
+ HDR_LENGTH
;
238 fread(kernel
, klen
, 1, in
);
240 /* Write magic values and filler */
241 writel(buf
, HDR_OFF_MAGIC1
, board
->magic
);
242 writel(buf
, HDR_OFF_MAGIC2
, board
->magic
);
243 writel(buf
, HDR_OFF_FILLER
, 0);
245 /* Write header and image length */
246 writel(buf
, HDR_OFF_HDRLEN
, HDR_LENGTH
);
247 writel(buf
, HDR_OFF_IMAGELEN
, klen
);
249 /* Write checksum and static hash */
250 sha1_csum(kernel
, klen
, buf
+ HDR_OFF_CHECKSUM
);
251 memcpy(buf
+ HDR_OFF_STATICHASH
, board
->statichash
, 20);
253 /* Save finished image */
254 out
= fopen(ofname
, "w");
256 ERRS("could not open \"%s\" for writing: %s", ofname
);
259 fwrite(buf
, buflen
, 1, out
);