• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mkmerakifw-old.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2015 Thomas Hebb <tommyhebb@gmail.com>
  4  * Copyright (C) 2016 Christian Lamparter <chunkeey@googlemail.com>
  5  *
  6  * The format of the header this tool generates was first documented by
  7  * Chris Blake <chrisrblake93 (at) gmail.com> in a shell script of the
  8  * same purpose. I have created this reimplementation at his request. The
  9  * original script can be found at:
 10  * <https://github.com/riptidewave93/meraki-partbuilder>
 11  *
 12  * Support for the old header format, which is used by the Cisco Z1 AP
 13  * has been reverse engineered from the nandloader's nand_load_bk function.
 14  * The original code is part of Cisco's GPL code and can be found at:
 15  * <https://github.com/riptidewave93/meraki-linux>
 16  */
 17 
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 #include <stdbool.h>
 21 #include <string.h>
 22 #include <libgen.h>
 23 #include <endian.h>
 24 #include <getopt.h>
 25 #include <errno.h>
 26 #include <arpa/inet.h>
 27 
 28 #define PADDING_BYTE            0xff
 29 
 30 #define HDR_LENGTH              0x00000020
 31 #define HDR_OFF_MAGIC1  0
 32 #define HDR_OFF_LOAD_ADDR       4
 33 #define HDR_OFF_IMAGELEN        8
 34 #define HDR_OFF_ENTRY   12
 35 #define HDR_OFF_CHECKSUM        16
 36 #define HDR_OFF_FILLER0 20
 37 #define HDR_OFF_FILLER1 24
 38 #define HDR_OFF_FILLER2 28
 39 
 40 struct board_info {
 41         char *id;
 42         char *description;
 43         uint32_t magic;
 44         uint32_t imagelen;
 45         uint32_t load_addr;
 46         uint32_t entry;
 47         bool le32;
 48 };
 49 
 50 /*
 51  * Globals
 52  */
 53 static char *progname;
 54 static bool strip_padding;
 55 
 56 static char *board_id;
 57 static const struct board_info *board;
 58 
 59 static const struct board_info boards[] = {
 60         {
 61                 .id             = "z1",
 62                 .description    = "Meraki Z1 Access Point",
 63                 .magic          = 0x4d495053,
 64                 .imagelen       = 0x007e0000,
 65                 .load_addr      = 0x80060000,
 66                 .entry          = 0x80060000,
 67                 .le32           = 0,
 68         }, {
 69                 .id             = "mx64",
 70                 .description    = "Meraki MX64/MX65",
 71                 .magic          = 0x4d495053,
 72                 .imagelen       = 0x00000000,
 73                 .load_addr      = 0x60008000,
 74                 .entry          = 0x60008000,
 75                 .le32           = 1,
 76         }, {
 77                 /* terminating entry */
 78         }
 79 };
 80 
 81 /*
 82  * Message macros
 83  */
 84 #define ERR(fmt, ...) do { \
 85         fflush(0); \
 86         fprintf(stderr, "[%s] *** error: " fmt "\n", \
 87                         progname, ## __VA_ARGS__); \
 88 } while (0)
 89 
 90 #define ERRS(fmt, ...) do { \
 91         int save = errno; \
 92         fflush(0); \
 93         fprintf(stderr, "[%s] *** error: " fmt "\n", \
 94                         progname, ## __VA_ARGS__, strerror(save)); \
 95 } while (0)
 96 
 97 static const struct board_info *find_board(const char *id)
 98 {
 99         const struct board_info *ret;
100         const struct board_info *board;
101 
102         ret = NULL;
103         for (board = boards; board->id != NULL; board++) {
104                 if (strcasecmp(id, board->id) == 0) {
105                         ret = board;
106                         break;
107                 }
108         }
109 
110         return ret;
111 }
112 
113 static void usage(int status)
114 {
115         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
116         const struct board_info *board;
117 
118         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
119         fprintf(stream,
120 "\n"
121 "Options:\n"
122 "  -B <board>      create image for the board specified with <board>\n"
123 "  -i <file>       read kernel image from the file <file>\n"
124 "  -o <file>       write output to the file <file>\n"
125 "  -s              strip padding from the end of the image\n"
126 "  -h              show this screen\n"
127         );
128 
129         fprintf(stream, "\nBoards:\n");
130         for (board = boards; board->id != NULL; board++)
131                 fprintf(stream, "  %-16s%s\n", board->id, board->description);
132 
133         exit(status);
134 }
135 
136 static void writel(unsigned char *buf, size_t offset, uint32_t value, bool le32)
137 {
138         if (!le32)
139                 value = htonl(value);
140 
141         memcpy(buf + offset, &value, sizeof(uint32_t));
142 }
143 
144 static const uint32_t crc32_table[] = {
145         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
146         0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
147         0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
148         0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
149         0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
150         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
151         0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
152         0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
153         0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
154         0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
155         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
156         0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
157         0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
158         0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
159         0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
160         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
161         0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
162         0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
163         0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
164         0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
165         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
166         0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
167         0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
168         0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
169         0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
170         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
171         0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
172         0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
173         0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
174         0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
175         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
176         0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
177         0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
178         0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
179         0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
180         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
181         0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
182         0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
183         0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
184         0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
185         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
186         0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
187         0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
188         0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
189         0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
190         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
191         0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
192         0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
193         0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
194         0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
195         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
196         0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
197         0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
198         0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
199         0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
200         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
201         0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
202         0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
203         0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
204         0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
205         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
206         0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
207         0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
208         0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
209 };
210 
211 static inline uint32_t crc32_accumulate_8(const uint32_t crc, const uint8_t ch)
212 {
213         return crc32_table[(crc ^ ch) & 0xff] ^ (crc >> 8);
214 }
215 
216 static void crc32_csum(uint8_t *buf, const size_t len, bool le32)
217 {
218         int j, k, l, m;
219         uint32_t crc;
220         size_t i;
221 
222         crc = ~0;
223         k = le32 * 3;
224         l = le32 * -2 + 1;
225 
226         for (i = 0; i < len; i += 4) {
227                 for (j = 3; j >= 0; j -= 1) {
228                         m = (j - k) * l;
229                         crc = crc32_accumulate_8(crc, buf[i + m]);
230                 }
231         }
232         crc = ~crc;
233 
234         writel(buf, HDR_OFF_CHECKSUM, crc, le32);
235 }
236 
237 
238 static int meraki_build_hdr(const struct board_info *board, const size_t klen,
239                             FILE *out, FILE *in)
240 {
241         unsigned char *kernel;
242         unsigned char *buf;
243         size_t buflen;
244         size_t kspace;
245 
246         size_t rc;
247         buflen = board->imagelen;
248 
249         if (buflen > 0) {
250                 kspace = buflen - HDR_LENGTH;
251 
252                 if (klen > kspace) {
253                         ERR("kernel file is too big - max size: 0x%08lX\n", kspace);
254                         return EXIT_FAILURE;
255                 }
256         }
257 
258         /* If requested, resize buffer to remove padding */
259         if (strip_padding)
260                 buflen = klen + HDR_LENGTH;
261 
262         /* Allocate and initialize buffer for final image */
263         buf = malloc(buflen);
264         if (buf == NULL) {
265                 ERRS("no memory for buffer: %s\n");
266                 return EXIT_FAILURE;
267         }
268         memset(buf, PADDING_BYTE, buflen);
269 
270         /* Load kernel */
271         kernel = buf + HDR_LENGTH;
272         fread(kernel, klen, 1, in);
273 
274         /* Write magic values and filler */
275         writel(buf, HDR_OFF_MAGIC1, board->magic, board->le32);
276         writel(buf, HDR_OFF_FILLER0, 0, board->le32);
277         writel(buf, HDR_OFF_FILLER1, 0, board->le32);
278         writel(buf, HDR_OFF_FILLER2, 0, board->le32);
279 
280         /* Write load and kernel entry point address */
281         writel(buf, HDR_OFF_LOAD_ADDR, board->load_addr, board->le32);
282         writel(buf, HDR_OFF_ENTRY, board->entry, board->le32);
283 
284         /* Write header and image length */
285         writel(buf, HDR_OFF_IMAGELEN, klen, board->le32);
286 
287         /* this gets replaced later, after the checksum has been calculated */
288         writel(buf, HDR_OFF_CHECKSUM, 0, board->le32);
289 
290         /* Write checksum */
291         crc32_csum(buf, klen + HDR_LENGTH, board->le32);
292 
293         rc = fwrite(buf, buflen, 1, out);
294 
295         free(buf);
296 
297         return rc == 1 ? EXIT_SUCCESS : EXIT_FAILURE;
298 }
299 
300 int main(int argc, char *argv[])
301 {
302         int ret = EXIT_FAILURE;
303         char *ofname = NULL, *ifname = NULL;
304         FILE *out, *in;
305         size_t klen;
306 
307         progname = basename(argv[0]);
308 
309         while (1) {
310                 int c;
311 
312                 c = getopt(argc, argv, "B:i:o:sh");
313                 if (c == -1)
314                         break;
315 
316                 switch (c) {
317                 case 'B':
318                         board_id = optarg;
319                         break;
320                 case 'i':
321                         ifname = optarg;
322                         break;
323                 case 'o':
324                         ofname = optarg;
325                         break;
326                 case 's':
327                         strip_padding = true;
328                         break;
329                 case 'h':
330                         usage(EXIT_SUCCESS);
331                         break;
332                 default:
333                         usage(EXIT_FAILURE);
334                         break;
335                 }
336         }
337 
338         if (board_id == NULL) {
339                 ERR("no board specified");
340                 goto err;
341         }
342 
343         board = find_board(board_id);
344         if (board == NULL) {
345                 ERR("unknown board \"%s\"", board_id);
346                 goto err;
347         }
348 
349         if (ifname == NULL) {
350                 ERR("no input file specified");
351                 goto err;
352         }
353 
354         if (ofname == NULL) {
355                 ERR("no output file specified");
356                 goto err;
357         }
358 
359         in = fopen(ifname, "r");
360         if (in == NULL) {
361                 ERRS("could not open \"%s\" for reading: %s", ifname);
362                 goto err;
363         }
364 
365         /* Get kernel length */
366         fseek(in, 0, SEEK_END);
367         klen = ftell(in);
368         rewind(in);
369 
370         out = fopen(ofname, "w");
371         if (out == NULL) {
372                 ERRS("could not open \"%s\" for writing: %s", ofname);
373                 goto err_close_in;
374         }
375 
376         ret = meraki_build_hdr(board, klen, out, in);
377         fclose(out);
378 
379 err_close_in:
380         fclose(in);
381 
382 err:
383         return ret;
384 }
385 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt