]> git.ipfire.org Git - thirdparty/u-boot.git/blob - tools/kwbimage.c
tools: kwbimage: Fix style violations
[thirdparty/u-boot.git] / tools / kwbimage.c
1 /*
2 * Image manipulator for Marvell SoCs
3 * supports Kirkwood, Dove, Armada 370, and Armada XP
4 *
5 * (C) Copyright 2013 Thomas Petazzoni
6 * <thomas.petazzoni@free-electrons.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 *
10 * Not implemented: support for the register headers and secure
11 * headers in v1 images
12 */
13
14 #include "imagetool.h"
15 #include <limits.h>
16 #include <image.h>
17 #include <stdint.h>
18 #include "kwbimage.h"
19
20 static struct image_cfg_element *image_cfg;
21 static int cfgn;
22
23 struct boot_mode {
24 unsigned int id;
25 const char *name;
26 };
27
28 struct boot_mode boot_modes[] = {
29 { 0x4D, "i2c" },
30 { 0x5A, "spi" },
31 { 0x8B, "nand" },
32 { 0x78, "sata" },
33 { 0x9C, "pex" },
34 { 0x69, "uart" },
35 { 0xAE, "sdio" },
36 {},
37 };
38
39 struct nand_ecc_mode {
40 unsigned int id;
41 const char *name;
42 };
43
44 struct nand_ecc_mode nand_ecc_modes[] = {
45 { 0x00, "default" },
46 { 0x01, "hamming" },
47 { 0x02, "rs" },
48 { 0x03, "disabled" },
49 {},
50 };
51
52 /* Used to identify an undefined execution or destination address */
53 #define ADDR_INVALID ((uint32_t)-1)
54
55 #define BINARY_MAX_ARGS 8
56
57 /* In-memory representation of a line of the configuration file */
58 struct image_cfg_element {
59 enum {
60 IMAGE_CFG_VERSION = 0x1,
61 IMAGE_CFG_BOOT_FROM,
62 IMAGE_CFG_DEST_ADDR,
63 IMAGE_CFG_EXEC_ADDR,
64 IMAGE_CFG_NAND_BLKSZ,
65 IMAGE_CFG_NAND_BADBLK_LOCATION,
66 IMAGE_CFG_NAND_ECC_MODE,
67 IMAGE_CFG_NAND_PAGESZ,
68 IMAGE_CFG_BINARY,
69 IMAGE_CFG_PAYLOAD,
70 IMAGE_CFG_DATA,
71 IMAGE_CFG_BAUDRATE,
72 IMAGE_CFG_DEBUG,
73 } type;
74 union {
75 unsigned int version;
76 unsigned int bootfrom;
77 struct {
78 const char *file;
79 unsigned int args[BINARY_MAX_ARGS];
80 unsigned int nargs;
81 } binary;
82 const char *payload;
83 unsigned int dstaddr;
84 unsigned int execaddr;
85 unsigned int nandblksz;
86 unsigned int nandbadblklocation;
87 unsigned int nandeccmode;
88 unsigned int nandpagesz;
89 struct ext_hdr_v0_reg regdata;
90 unsigned int baudrate;
91 unsigned int debug;
92 };
93 };
94
95 #define IMAGE_CFG_ELEMENT_MAX 256
96
97 /*
98 * Utility functions to manipulate boot mode and ecc modes (convert
99 * them back and forth between description strings and the
100 * corresponding numerical identifiers).
101 */
102
103 static const char *image_boot_mode_name(unsigned int id)
104 {
105 int i;
106
107 for (i = 0; boot_modes[i].name; i++)
108 if (boot_modes[i].id == id)
109 return boot_modes[i].name;
110 return NULL;
111 }
112
113 int image_boot_mode_id(const char *boot_mode_name)
114 {
115 int i;
116
117 for (i = 0; boot_modes[i].name; i++)
118 if (!strcmp(boot_modes[i].name, boot_mode_name))
119 return boot_modes[i].id;
120
121 return -1;
122 }
123
124 int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
125 {
126 int i;
127
128 for (i = 0; nand_ecc_modes[i].name; i++)
129 if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
130 return nand_ecc_modes[i].id;
131 return -1;
132 }
133
134 static struct image_cfg_element *
135 image_find_option(unsigned int optiontype)
136 {
137 int i;
138
139 for (i = 0; i < cfgn; i++) {
140 if (image_cfg[i].type == optiontype)
141 return &image_cfg[i];
142 }
143
144 return NULL;
145 }
146
147 static unsigned int
148 image_count_options(unsigned int optiontype)
149 {
150 int i;
151 unsigned int count = 0;
152
153 for (i = 0; i < cfgn; i++)
154 if (image_cfg[i].type == optiontype)
155 count++;
156
157 return count;
158 }
159
160 /*
161 * Compute a 8-bit checksum of a memory area. This algorithm follows
162 * the requirements of the Marvell SoC BootROM specifications.
163 */
164 static uint8_t image_checksum8(void *start, uint32_t len)
165 {
166 uint8_t csum = 0;
167 uint8_t *p = start;
168
169 /* check len and return zero checksum if invalid */
170 if (!len)
171 return 0;
172
173 do {
174 csum += *p;
175 p++;
176 } while (--len);
177
178 return csum;
179 }
180
181 static uint32_t image_checksum32(void *start, uint32_t len)
182 {
183 uint32_t csum = 0;
184 uint32_t *p = start;
185
186 /* check len and return zero checksum if invalid */
187 if (!len)
188 return 0;
189
190 if (len % sizeof(uint32_t)) {
191 fprintf(stderr, "Length %d is not in multiple of %zu\n",
192 len, sizeof(uint32_t));
193 return 0;
194 }
195
196 do {
197 csum += *p;
198 p++;
199 len -= sizeof(uint32_t);
200 } while (len > 0);
201
202 return csum;
203 }
204
205 static uint8_t baudrate_to_option(unsigned int baudrate)
206 {
207 switch (baudrate) {
208 case 2400:
209 return MAIN_HDR_V1_OPT_BAUD_2400;
210 case 4800:
211 return MAIN_HDR_V1_OPT_BAUD_4800;
212 case 9600:
213 return MAIN_HDR_V1_OPT_BAUD_9600;
214 case 19200:
215 return MAIN_HDR_V1_OPT_BAUD_19200;
216 case 38400:
217 return MAIN_HDR_V1_OPT_BAUD_38400;
218 case 57600:
219 return MAIN_HDR_V1_OPT_BAUD_57600;
220 case 115200:
221 return MAIN_HDR_V1_OPT_BAUD_115200;
222 default:
223 return MAIN_HDR_V1_OPT_BAUD_DEFAULT;
224 }
225 }
226
227 static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
228 int payloadsz)
229 {
230 struct image_cfg_element *e;
231 size_t headersz;
232 struct main_hdr_v0 *main_hdr;
233 struct ext_hdr_v0 *ext_hdr;
234 void *image;
235 int has_ext = 0;
236
237 /*
238 * Calculate the size of the header and the size of the
239 * payload
240 */
241 headersz = sizeof(struct main_hdr_v0);
242
243 if (image_count_options(IMAGE_CFG_DATA) > 0) {
244 has_ext = 1;
245 headersz += sizeof(struct ext_hdr_v0);
246 }
247
248 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
249 fprintf(stderr, "More than one payload, not possible\n");
250 return NULL;
251 }
252
253 image = malloc(headersz);
254 if (!image) {
255 fprintf(stderr, "Cannot allocate memory for image\n");
256 return NULL;
257 }
258
259 memset(image, 0, headersz);
260
261 main_hdr = image;
262
263 /* Fill in the main header */
264 main_hdr->blocksize =
265 cpu_to_le32(payloadsz + sizeof(uint32_t) - headersz);
266 main_hdr->srcaddr = cpu_to_le32(headersz);
267 main_hdr->ext = has_ext;
268 main_hdr->destaddr = cpu_to_le32(params->addr);
269 main_hdr->execaddr = cpu_to_le32(params->ep);
270
271 e = image_find_option(IMAGE_CFG_BOOT_FROM);
272 if (e)
273 main_hdr->blockid = e->bootfrom;
274 e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
275 if (e)
276 main_hdr->nandeccmode = e->nandeccmode;
277 e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
278 if (e)
279 main_hdr->nandpagesize = cpu_to_le16(e->nandpagesz);
280 main_hdr->checksum = image_checksum8(image,
281 sizeof(struct main_hdr_v0));
282
283 /* Generate the ext header */
284 if (has_ext) {
285 int cfgi, datai;
286
287 ext_hdr = image + sizeof(struct main_hdr_v0);
288 ext_hdr->offset = cpu_to_le32(0x40);
289
290 for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
291 e = &image_cfg[cfgi];
292 if (e->type != IMAGE_CFG_DATA)
293 continue;
294
295 ext_hdr->rcfg[datai].raddr =
296 cpu_to_le32(e->regdata.raddr);
297 ext_hdr->rcfg[datai].rdata =
298 cpu_to_le32(e->regdata.rdata);
299 datai++;
300 }
301
302 ext_hdr->checksum = image_checksum8(ext_hdr,
303 sizeof(struct ext_hdr_v0));
304 }
305
306 *imagesz = headersz;
307 return image;
308 }
309
310 static size_t image_headersz_v1(struct image_tool_params *params,
311 int *hasext)
312 {
313 struct image_cfg_element *binarye;
314 size_t headersz;
315 int ret;
316
317 /*
318 * Calculate the size of the header and the size of the
319 * payload
320 */
321 headersz = sizeof(struct main_hdr_v1);
322
323 if (image_count_options(IMAGE_CFG_BINARY) > 1) {
324 fprintf(stderr, "More than one binary blob, not supported\n");
325 return 0;
326 }
327
328 if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
329 fprintf(stderr, "More than one payload, not possible\n");
330 return 0;
331 }
332
333 binarye = image_find_option(IMAGE_CFG_BINARY);
334 if (binarye) {
335 struct stat s;
336
337 ret = stat(binarye->binary.file, &s);
338 if (ret < 0) {
339 char cwd[PATH_MAX];
340 char *dir = cwd;
341
342 memset(cwd, 0, sizeof(cwd));
343 if (!getcwd(cwd, sizeof(cwd))) {
344 dir = "current working directory";
345 perror("getcwd() failed");
346 }
347
348 fprintf(stderr,
349 "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
350 "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
351 "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
352 binarye->binary.file, dir);
353 return 0;
354 }
355
356 headersz += sizeof(struct opt_hdr_v1) +
357 s.st_size +
358 (binarye->binary.nargs + 2) * sizeof(uint32_t);
359 if (hasext)
360 *hasext = 1;
361 }
362
363 #if defined(CONFIG_SYS_U_BOOT_OFFS)
364 if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
365 fprintf(stderr,
366 "Error: Image header (incl. SPL image) too big!\n");
367 fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
368 (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
369 fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
370 return 0;
371 }
372 headersz = CONFIG_SYS_U_BOOT_OFFS;
373 #endif
374
375 /*
376 * The payload should be aligned on some reasonable
377 * boundary
378 */
379 return ALIGN_SUP(headersz, 4096);
380 }
381
382 static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
383 int payloadsz)
384 {
385 struct image_cfg_element *e, *binarye;
386 struct main_hdr_v1 *main_hdr;
387 size_t headersz;
388 void *image, *cur;
389 int hasext = 0;
390 int ret;
391
392 /*
393 * Calculate the size of the header and the size of the
394 * payload
395 */
396 headersz = image_headersz_v1(params, &hasext);
397 if (headersz == 0)
398 return NULL;
399
400 image = malloc(headersz);
401 if (!image) {
402 fprintf(stderr, "Cannot allocate memory for image\n");
403 return NULL;
404 }
405
406 memset(image, 0, headersz);
407
408 cur = main_hdr = image;
409 cur += sizeof(struct main_hdr_v1);
410
411 /* Fill the main header */
412 main_hdr->blocksize =
413 cpu_to_le32(payloadsz - headersz + sizeof(uint32_t));
414 main_hdr->headersz_lsb = cpu_to_le16(headersz & 0xFFFF);
415 main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
416 main_hdr->destaddr = cpu_to_le32(params->addr)
417 - sizeof(image_header_t);
418 main_hdr->execaddr = cpu_to_le32(params->ep);
419 main_hdr->srcaddr = cpu_to_le32(headersz);
420 main_hdr->ext = hasext;
421 main_hdr->version = 1;
422 e = image_find_option(IMAGE_CFG_BOOT_FROM);
423 if (e)
424 main_hdr->blockid = e->bootfrom;
425 e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
426 if (e)
427 main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
428 e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
429 if (e)
430 main_hdr->nandbadblklocation = e->nandbadblklocation;
431 e = image_find_option(IMAGE_CFG_BAUDRATE);
432 if (e)
433 main_hdr->options = baudrate_to_option(e->baudrate);
434 e = image_find_option(IMAGE_CFG_DEBUG);
435 if (e)
436 main_hdr->flags = e->debug ? 0x1 : 0;
437
438 binarye = image_find_option(IMAGE_CFG_BINARY);
439 if (binarye) {
440 struct opt_hdr_v1 *hdr = cur;
441 uint32_t *args;
442 size_t binhdrsz;
443 struct stat s;
444 int argi;
445 FILE *bin;
446
447 hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
448
449 bin = fopen(binarye->binary.file, "r");
450 if (!bin) {
451 fprintf(stderr, "Cannot open binary file %s\n",
452 binarye->binary.file);
453 return NULL;
454 }
455
456 fstat(fileno(bin), &s);
457
458 binhdrsz = sizeof(struct opt_hdr_v1) +
459 (binarye->binary.nargs + 2) * sizeof(uint32_t) +
460 s.st_size;
461
462 /*
463 * The size includes the binary image size, rounded
464 * up to a 4-byte boundary. Plus 4 bytes for the
465 * next-header byte and 3-byte alignment at the end.
466 */
467 binhdrsz = ALIGN_SUP(binhdrsz, 4) + 4;
468 hdr->headersz_lsb = cpu_to_le16(binhdrsz & 0xFFFF);
469 hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
470
471 cur += sizeof(struct opt_hdr_v1);
472
473 args = cur;
474 *args = cpu_to_le32(binarye->binary.nargs);
475 args++;
476 for (argi = 0; argi < binarye->binary.nargs; argi++)
477 args[argi] = cpu_to_le32(binarye->binary.args[argi]);
478
479 cur += (binarye->binary.nargs + 1) * sizeof(uint32_t);
480
481 ret = fread(cur, s.st_size, 1, bin);
482 if (ret != 1) {
483 fprintf(stderr,
484 "Could not read binary image %s\n",
485 binarye->binary.file);
486 return NULL;
487 }
488
489 fclose(bin);
490
491 cur += ALIGN_SUP(s.st_size, 4);
492
493 /*
494 * For now, we don't support more than one binary
495 * header, and no other header types are
496 * supported. So, the binary header is necessarily the
497 * last one
498 */
499 *((uint32_t *)cur) = 0x00000000;
500
501 cur += sizeof(uint32_t);
502 }
503
504 /* Calculate and set the header checksum */
505 main_hdr->checksum = image_checksum8(main_hdr, headersz);
506
507 *imagesz = headersz;
508 return image;
509 }
510
511 static int image_create_config_parse_oneline(char *line,
512 struct image_cfg_element *el)
513 {
514 char *keyword, *saveptr;
515 char deliminiters[] = " \t";
516
517 keyword = strtok_r(line, deliminiters, &saveptr);
518 if (!strcmp(keyword, "VERSION")) {
519 char *value = strtok_r(NULL, deliminiters, &saveptr);
520
521 el->type = IMAGE_CFG_VERSION;
522 el->version = atoi(value);
523 } else if (!strcmp(keyword, "BOOT_FROM")) {
524 char *value = strtok_r(NULL, deliminiters, &saveptr);
525 int ret = image_boot_mode_id(value);
526
527 if (ret < 0) {
528 fprintf(stderr,
529 "Invalid boot media '%s'\n", value);
530 return -1;
531 }
532 el->type = IMAGE_CFG_BOOT_FROM;
533 el->bootfrom = ret;
534 } else if (!strcmp(keyword, "NAND_BLKSZ")) {
535 char *value = strtok_r(NULL, deliminiters, &saveptr);
536
537 el->type = IMAGE_CFG_NAND_BLKSZ;
538 el->nandblksz = strtoul(value, NULL, 16);
539 } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
540 char *value = strtok_r(NULL, deliminiters, &saveptr);
541
542 el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
543 el->nandbadblklocation =
544 strtoul(value, NULL, 16);
545 } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
546 char *value = strtok_r(NULL, deliminiters, &saveptr);
547 int ret = image_nand_ecc_mode_id(value);
548
549 if (ret < 0) {
550 fprintf(stderr,
551 "Invalid NAND ECC mode '%s'\n", value);
552 return -1;
553 }
554 el->type = IMAGE_CFG_NAND_ECC_MODE;
555 el->nandeccmode = ret;
556 } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
557 char *value = strtok_r(NULL, deliminiters, &saveptr);
558
559 el->type = IMAGE_CFG_NAND_PAGESZ;
560 el->nandpagesz = strtoul(value, NULL, 16);
561 } else if (!strcmp(keyword, "BINARY")) {
562 char *value = strtok_r(NULL, deliminiters, &saveptr);
563 int argi = 0;
564
565 el->type = IMAGE_CFG_BINARY;
566 el->binary.file = strdup(value);
567 while (1) {
568 value = strtok_r(NULL, deliminiters, &saveptr);
569 if (!value)
570 break;
571 el->binary.args[argi] = strtoul(value, NULL, 16);
572 argi++;
573 if (argi >= BINARY_MAX_ARGS) {
574 fprintf(stderr,
575 "Too many argument for binary\n");
576 return -1;
577 }
578 }
579 el->binary.nargs = argi;
580 } else if (!strcmp(keyword, "DATA")) {
581 char *value1 = strtok_r(NULL, deliminiters, &saveptr);
582 char *value2 = strtok_r(NULL, deliminiters, &saveptr);
583
584 if (!value1 || !value2) {
585 fprintf(stderr,
586 "Invalid number of arguments for DATA\n");
587 return -1;
588 }
589
590 el->type = IMAGE_CFG_DATA;
591 el->regdata.raddr = strtoul(value1, NULL, 16);
592 el->regdata.rdata = strtoul(value2, NULL, 16);
593 } else if (!strcmp(keyword, "BAUDRATE")) {
594 char *value = strtok_r(NULL, deliminiters, &saveptr);
595 el->type = IMAGE_CFG_BAUDRATE;
596 el->baudrate = strtoul(value, NULL, 10);
597 } else if (!strcmp(keyword, "DEBUG")) {
598 char *value = strtok_r(NULL, deliminiters, &saveptr);
599 el->type = IMAGE_CFG_DEBUG;
600 el->debug = strtoul(value, NULL, 10);
601 } else {
602 fprintf(stderr, "Ignoring unknown line '%s'\n", line);
603 }
604
605 return 0;
606 }
607
608 /*
609 * Parse the configuration file 'fcfg' into the array of configuration
610 * elements 'image_cfg', and return the number of configuration
611 * elements in 'cfgn'.
612 */
613 static int image_create_config_parse(FILE *fcfg)
614 {
615 int ret;
616 int cfgi = 0;
617
618 /* Parse the configuration file */
619 while (!feof(fcfg)) {
620 char *line;
621 char buf[256];
622
623 /* Read the current line */
624 memset(buf, 0, sizeof(buf));
625 line = fgets(buf, sizeof(buf), fcfg);
626 if (!line)
627 break;
628
629 /* Ignore useless lines */
630 if (line[0] == '\n' || line[0] == '#')
631 continue;
632
633 /* Strip final newline */
634 if (line[strlen(line) - 1] == '\n')
635 line[strlen(line) - 1] = 0;
636
637 /* Parse the current line */
638 ret = image_create_config_parse_oneline(line,
639 &image_cfg[cfgi]);
640 if (ret)
641 return ret;
642
643 cfgi++;
644
645 if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
646 fprintf(stderr,
647 "Too many configuration elements in .cfg file\n");
648 return -1;
649 }
650 }
651
652 cfgn = cfgi;
653 return 0;
654 }
655
656 static int image_get_version(void)
657 {
658 struct image_cfg_element *e;
659
660 e = image_find_option(IMAGE_CFG_VERSION);
661 if (!e)
662 return -1;
663
664 return e->version;
665 }
666
667 static int image_version_file(const char *input)
668 {
669 FILE *fcfg;
670 int version;
671 int ret;
672
673 fcfg = fopen(input, "r");
674 if (!fcfg) {
675 fprintf(stderr, "Could not open input file %s\n", input);
676 return -1;
677 }
678
679 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
680 sizeof(struct image_cfg_element));
681 if (!image_cfg) {
682 fprintf(stderr, "Cannot allocate memory\n");
683 fclose(fcfg);
684 return -1;
685 }
686
687 memset(image_cfg, 0,
688 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
689 rewind(fcfg);
690
691 ret = image_create_config_parse(fcfg);
692 fclose(fcfg);
693 if (ret) {
694 free(image_cfg);
695 return -1;
696 }
697
698 version = image_get_version();
699 /* Fallback to version 0 is no version is provided in the cfg file */
700 if (version == -1)
701 version = 0;
702
703 free(image_cfg);
704
705 return version;
706 }
707
708 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
709 struct image_tool_params *params)
710 {
711 FILE *fcfg;
712 void *image = NULL;
713 int version;
714 size_t headersz = 0;
715 uint32_t checksum;
716 int ret;
717 int size;
718
719 fcfg = fopen(params->imagename, "r");
720 if (!fcfg) {
721 fprintf(stderr, "Could not open input file %s\n",
722 params->imagename);
723 exit(EXIT_FAILURE);
724 }
725
726 image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
727 sizeof(struct image_cfg_element));
728 if (!image_cfg) {
729 fprintf(stderr, "Cannot allocate memory\n");
730 fclose(fcfg);
731 exit(EXIT_FAILURE);
732 }
733
734 memset(image_cfg, 0,
735 IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
736 rewind(fcfg);
737
738 ret = image_create_config_parse(fcfg);
739 fclose(fcfg);
740 if (ret) {
741 free(image_cfg);
742 exit(EXIT_FAILURE);
743 }
744
745 /* The MVEBU BootROM does not allow non word aligned payloads */
746 sbuf->st_size = ALIGN_SUP(sbuf->st_size, 4);
747
748 version = image_get_version();
749 switch (version) {
750 /*
751 * Fallback to version 0 if no version is provided in the
752 * cfg file
753 */
754 case -1:
755 case 0:
756 image = image_create_v0(&headersz, params, sbuf->st_size);
757 break;
758
759 case 1:
760 image = image_create_v1(&headersz, params, sbuf->st_size);
761 break;
762
763 default:
764 fprintf(stderr, "Unsupported version %d\n", version);
765 free(image_cfg);
766 exit(EXIT_FAILURE);
767 }
768
769 if (!image) {
770 fprintf(stderr, "Could not create image\n");
771 free(image_cfg);
772 exit(EXIT_FAILURE);
773 }
774
775 free(image_cfg);
776
777 /* Build and add image checksum header */
778 checksum =
779 cpu_to_le32(image_checksum32((uint32_t *)ptr, sbuf->st_size));
780 size = write(ifd, &checksum, sizeof(uint32_t));
781 if (size != sizeof(uint32_t)) {
782 fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
783 params->cmdname, size, params->imagefile);
784 exit(EXIT_FAILURE);
785 }
786
787 sbuf->st_size += sizeof(uint32_t);
788
789 /* Finally copy the header into the image area */
790 memcpy(ptr, image, headersz);
791
792 free(image);
793 }
794
795 static void kwbimage_print_header(const void *ptr)
796 {
797 struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
798
799 printf("Image Type: MVEBU Boot from %s Image\n",
800 image_boot_mode_name(mhdr->blockid));
801 printf("Image version:%d\n", image_version((void *)ptr));
802 printf("Data Size: ");
803 genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
804 printf("Load Address: %08x\n", mhdr->destaddr);
805 printf("Entry Point: %08x\n", mhdr->execaddr);
806 }
807
808 static int kwbimage_check_image_types(uint8_t type)
809 {
810 if (type == IH_TYPE_KWBIMAGE)
811 return EXIT_SUCCESS;
812
813 return EXIT_FAILURE;
814 }
815
816 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
817 struct image_tool_params *params)
818 {
819 struct main_hdr_v0 *main_hdr;
820 struct ext_hdr_v0 *ext_hdr;
821 uint8_t checksum;
822
823 main_hdr = (void *)ptr;
824 checksum = image_checksum8(ptr,
825 sizeof(struct main_hdr_v0)
826 - sizeof(uint8_t));
827 if (checksum != main_hdr->checksum)
828 return -FDT_ERR_BADSTRUCTURE;
829
830 /* Only version 0 extended header has checksum */
831 if (image_version((void *)ptr) == 0) {
832 ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
833 checksum = image_checksum8(ext_hdr,
834 sizeof(struct ext_hdr_v0)
835 - sizeof(uint8_t));
836 if (checksum != ext_hdr->checksum)
837 return -FDT_ERR_BADSTRUCTURE;
838 }
839
840 return 0;
841 }
842
843 static int kwbimage_generate(struct image_tool_params *params,
844 struct image_type_params *tparams)
845 {
846 int alloc_len;
847 void *hdr;
848 int version = 0;
849
850 version = image_version_file(params->imagename);
851 if (version == 0) {
852 alloc_len = sizeof(struct main_hdr_v0) +
853 sizeof(struct ext_hdr_v0);
854 } else {
855 alloc_len = image_headersz_v1(params, NULL);
856 }
857
858 hdr = malloc(alloc_len);
859 if (!hdr) {
860 fprintf(stderr, "%s: malloc return failure: %s\n",
861 params->cmdname, strerror(errno));
862 exit(EXIT_FAILURE);
863 }
864
865 memset(hdr, 0, alloc_len);
866 tparams->header_size = alloc_len;
867 tparams->hdr = hdr;
868
869 /*
870 * The resulting image needs to be 4-byte aligned. At least
871 * the Marvell hdrparser tool complains if its unaligned.
872 * By returning 1 here in this function, called via
873 * tparams->vrec_header() in mkimage.c, mkimage will
874 * automatically pad the the resulting image to a 4-byte
875 * size if necessary.
876 */
877 return 1;
878 }
879
880 /*
881 * Report Error if xflag is set in addition to default
882 */
883 static int kwbimage_check_params(struct image_tool_params *params)
884 {
885 if (!strlen(params->imagename)) {
886 char *msg = "Configuration file for kwbimage creation omitted";
887
888 fprintf(stderr, "Error:%s - %s\n", params->cmdname, msg);
889 return CFG_INVALID;
890 }
891
892 return (params->dflag && (params->fflag || params->lflag)) ||
893 (params->fflag && (params->dflag || params->lflag)) ||
894 (params->lflag && (params->dflag || params->fflag)) ||
895 (params->xflag) || !(strlen(params->imagename));
896 }
897
898 /*
899 * kwbimage type parameters definition
900 */
901 U_BOOT_IMAGE_TYPE(
902 kwbimage,
903 "Marvell MVEBU Boot Image support",
904 0,
905 NULL,
906 kwbimage_check_params,
907 kwbimage_verify_header,
908 kwbimage_print_header,
909 kwbimage_set_header,
910 NULL,
911 kwbimage_check_image_types,
912 NULL,
913 kwbimage_generate
914 );