util/amdfwtool: Add option to build verstage binary into the PSP
[coreboot.git] / util / marvell / doimage_mv / doimage.c
blob18675aa56d067e0323263a0e4717ee23c0b6a9a1
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
4 Marvell GPL License Option
6 If you received this File from Marvell, you may opt to use, redistribute and/or
7 modify this File in accordance with the terms and conditions of the General
8 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
9 available along with the File in the license.txt file or by writing to the Free
10 Software Foundation, Inc.
12 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
13 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
14 DISCLAIMED. The GPL License provides additional details about this warranty
15 disclaimer.
17 *******************************************************************************/
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <time.h>
27 #include <limits.h>
29 #define _HOST_COMPILER
30 #include "bootstrap_def.h"
32 #include "doimage.h"
34 #undef DEBUG
36 #ifdef DEBUG
37 #define DB(x...) fprintf(stdout, x)
38 #else
39 #define DB(x...)
40 #endif
42 /* Global variables */
44 int f_in = -1;
45 int f_out = -1;
46 int f_header = -1;
47 struct stat fs_stat;
49 /*******************************************************************************
50 * pre_load_image
51 * pre-load the binary image into memory buffer taking into account
52 *paddings
53 * INPUT:
54 * opt user options
55 * buf_in mmapped input file
56 * OUTPUT:
57 * none
58 * RETURN:
59 * 0 on success
60 *******************************************************************************/
61 int pre_load_image(USER_OPTIONS *opt, char *buf_in)
63 int offset = 0;
65 opt->image_buf = malloc(opt->image_sz);
66 if (opt->image_buf == NULL)
67 return -1;
69 memset(opt->image_buf, 0, opt->image_sz);
71 if ((opt->pre_padding) && (opt->prepadding_size)) {
72 memset(opt->image_buf, 0x5, opt->prepadding_size);
73 offset = opt->prepadding_size;
76 if ((opt->post_padding) && (opt->postpadding_size))
77 memset(opt->image_buf + opt->image_sz - 4 -
78 opt->postpadding_size,
79 0xA, opt->postpadding_size);
81 memcpy(opt->image_buf + offset, buf_in, fs_stat.st_size);
83 return 0;
84 } /* end of pre_load_image() */
86 /*******************************************************************************
87 * build_twsi_header
88 * create TWSI header and write it into output stream
89 * INPUT:
90 * opt user options
91 * OUTPUT:
92 * none
93 * RETURN:
94 * 0 on success
95 *******************************************************************************/
96 int build_twsi_header(USER_OPTIONS *opt)
98 FILE *f_twsi;
99 MV_U8 *tmpTwsi = NULL;
100 MV_U32 *twsi_reg;
101 int i;
102 MV_U32 twsi_size = 0;
104 tmpTwsi = malloc(MAX_TWSI_HDR_SIZE);
105 if (tmpTwsi == NULL) {
106 fprintf(stderr, "TWSI space allocation error!\n");
107 return -1;
109 memset(tmpTwsi, 0xFF, MAX_TWSI_HDR_SIZE);
110 twsi_reg = (MV_U32 *)tmpTwsi;
112 f_twsi = fopen(opt->fname_twsi, "r");
113 if (f_twsi == NULL) {
114 fprintf(stderr, "Failed to open file '%s'\n", opt->fname_twsi);
115 perror("Error:");
116 return -1;
119 for (i = 0; i < (MAX_TWSI_HDR_SIZE / 4); i++) {
120 if (EOF == fscanf(f_twsi, "%x\n", twsi_reg))
121 break;
123 /* Swap Enianess */
124 *twsi_reg =
125 (((*twsi_reg >> 24) & 0xFF) | ((*twsi_reg >> 8) & 0xFF00) |
126 ((*twsi_reg << 8) & 0xFF0000) |
127 ((*twsi_reg << 24) & 0xFF000000));
128 twsi_reg++;
131 fclose(f_twsi);
133 /* Align to size = 512,1024,.. with at least 8 0xFF bytes @ the end */
134 twsi_size = ((((i + 2) * 4) & ~0x1FF) + 0x200);
136 if ((write(f_out, tmpTwsi, twsi_size)) != twsi_size) {
137 fprintf(stderr, "Error writing %s file\n", opt->fname.out);
138 return -1;
141 return 0;
142 } /* end of build_twsi_header() */
144 /*******************************************************************************
145 * build_reg_header
146 * create BIN header and write it into output stream
147 * INPUT:
148 * fname - source file name
149 * buffer - Start address of boot image buffer
150 * current_size - number of bytes already placed into the boot image buffer
151 * OUTPUT:
152 * none
153 * RETURN:
154 * size of a reg header or 0 on fail
155 *******************************************************************************/
156 int build_reg_header(char *fname, MV_U8 *buffer, MV_U32 current_size)
158 FILE *f_dram;
159 BHR_t *mainHdr = (BHR_t *)buffer;
160 headExtBHR_t *headExtHdr = headExtHdr =
161 (headExtBHR_t *)(buffer + current_size);
162 tailExtBHR_t *prevExtHdrTail =
163 NULL; /* tail of the previous extension header */
164 MV_U32 max_bytes_to_write;
165 MV_U32 *dram_reg =
166 (MV_U32 *)(buffer + current_size + sizeof(headExtBHR_t));
167 MV_U32 tmp_len;
168 int i;
170 if (mainHdr->ext == 255) {
171 fprintf(stderr, "Maximum number of extensions reached!\n");
172 return 0;
175 /* Indicate next header in previous extension if any */
176 if (mainHdr->ext != 0) {
177 prevExtHdrTail = (tailExtBHR_t *)(buffer + current_size -
178 sizeof(tailExtBHR_t));
179 prevExtHdrTail->nextHdr = 1;
182 /* Count extension headers in the main header */
183 mainHdr->ext++;
185 headExtHdr->type = EXT_HDR_TYP_REGISTER;
186 max_bytes_to_write = MAX_HEADER_SIZE - current_size - EXT_HDR_BASE_SIZE;
187 f_dram = fopen(fname, "r");
188 if (f_dram == NULL) {
189 fprintf(stderr, "Failed to open file '%s'\n", fname);
190 perror("Error:");
191 return 0;
194 for (i = 0; i < (max_bytes_to_write / 8); i += 2) {
195 if (fscanf(f_dram, "%x %x\n", &dram_reg[i], &dram_reg[i + 1]) ==
196 EOF)
197 break;
198 else if ((dram_reg[i] == 0x0) && (dram_reg[i + 1] == 0x0))
199 break;
202 fclose(f_dram);
204 if (i >= (max_bytes_to_write / 8)) {
205 fprintf(stderr, "Registers configure exceeds maximum size\n");
206 return 0;
209 /* Include extended header head and tail sizes */
210 tmp_len = EXT_HDR_BASE_SIZE + i * 4;
211 /* Write total length into the current header fields */
212 EXT_HDR_SET_LEN(headExtHdr, tmp_len);
214 return tmp_len;
215 } /* end of build_reg_header() */
217 /*******************************************************************************
218 * build_bin_header
219 * create BIN header and write it into putput stream
220 * INPUT:
221 * fname - source file name
222 * buffer - Start address of boot image buffer
223 * current_size - number of bytes already placed into the boot image buffer
224 * OUTPUT:
225 * none
226 * RETURN:
227 * size of reg header
228 *******************************************************************************/
229 int build_bin_header(char *fname, MV_U8 *buffer, MV_U32 current_size)
231 FILE *f_bin;
232 BHR_t *mainHdr = (BHR_t *)buffer;
233 headExtBHR_t *headExtHdr = (headExtBHR_t *)(buffer + current_size);
234 tailExtBHR_t *prevExtHdrTail =
235 NULL; /* tail of the previous extension header */
236 MV_U32 max_bytes_to_write;
237 MV_U32 *bin_reg =
238 (MV_U32 *)(buffer + current_size + sizeof(headExtBHR_t));
239 MV_U32 tmp_len;
240 int i;
242 if (mainHdr->ext == 255) {
243 fprintf(stderr, "Maximum number of extensions reached!\n");
244 return 0;
247 /* Indicate next header in previous extension if any */
248 if (mainHdr->ext != 0) {
249 prevExtHdrTail = (tailExtBHR_t *)(buffer + current_size -
250 sizeof(tailExtBHR_t));
251 prevExtHdrTail->nextHdr = 1;
254 /* Count extension headers in main header */
255 mainHdr->ext++;
257 headExtHdr->type = EXT_HDR_TYP_BINARY;
258 max_bytes_to_write = MAX_HEADER_SIZE - current_size - EXT_HDR_BASE_SIZE;
260 f_bin = fopen(fname, "r");
261 if (f_bin == NULL) {
262 fprintf(stderr, "Failed to open file '%s'\n", fname);
263 perror("Error:");
264 return 0;
267 for (i = 0; i < (max_bytes_to_write / 4); i++) {
268 if (fread(bin_reg, 1, 4, f_bin) != 4)
269 break;
271 bin_reg++;
274 fclose(f_bin);
276 if (i >= (max_bytes_to_write / 4)) {
277 fprintf(stderr, "Binary extension exeeds the maximum size\n");
278 return 0;
281 /* Include extended header head and tail sizes */
282 tmp_len = EXT_HDR_BASE_SIZE + i * 4;
283 /* Write total length into the current header fields */
284 EXT_HDR_SET_LEN(headExtHdr, tmp_len);
286 return tmp_len;
287 } /* end of build_exec_header() */
289 /*******************************************************************************
290 * build_headers
291 * build headers block based on user options and write it into output
292 *stream
293 * INPUT:
294 * opt user options
295 * buf_in mmapped input file
296 * OUTPUT:
297 * none
298 * RETURN:
299 * 0 on success
300 *******************************************************************************/
301 int build_headers(USER_OPTIONS *opt, char *buf_in)
303 BHR_t *hdr = NULL;
304 secExtBHR_t *secExtHdr = NULL;
305 headExtBHR_t *headExtHdr = NULL;
306 tailExtBHR_t *tailExtHdr = NULL;
307 MV_U8 *tmpHeader = NULL;
308 int i;
309 MV_U32 header_size = 0;
310 int size_written = 0;
311 MV_U32 max_bytes_to_write;
312 int error = 1;
314 tmpHeader = malloc(MAX_HEADER_SIZE);
315 if (tmpHeader == NULL) {
316 fprintf(stderr, "Header space allocation error!\n");
317 goto header_error;
320 memset(tmpHeader, 0, MAX_HEADER_SIZE);
321 hdr = (BHR_t *)tmpHeader;
323 switch (opt->image_type) {
324 case IMG_SATA:
325 hdr->blockID = IBR_HDR_SATA_ID;
326 break;
328 case IMG_UART:
329 hdr->blockID = IBR_HDR_UART_ID;
330 break;
332 case IMG_FLASH:
333 hdr->blockID = IBR_HDR_SPI_ID;
334 break;
336 case IMG_MMC:
337 hdr->blockID = IBR_HDR_MMC_ID;
338 break;
340 case IMG_NAND:
341 hdr->blockID = IBR_HDR_NAND_ID;
342 /*hdr->nandEccMode = (MV_U8)opt->nandEccMode; <<== reserved */
343 /*hdr->nandPageSize = (MV_U16)opt->nandPageSize; <<== reserved
345 hdr->nandBlockSize = (MV_U8)opt->nandBlkSize;
346 if ((opt->nandCellTech == 'S') || (opt->nandCellTech == 's'))
347 hdr->nandTechnology = MAIN_HDR_NAND_SLC;
348 else
349 hdr->nandTechnology = MAIN_HDR_NAND_MLC;
350 break;
352 case IMG_PEX:
353 hdr->blockID = IBR_HDR_PEX_ID;
354 break;
356 case IMG_I2C:
357 hdr->blockID = IBR_HDR_I2C_ID;
358 break;
360 default:
361 fprintf(stderr,
362 "Illegal image type %d for header construction!\n",
363 opt->image_type);
364 return 1;
367 /* Debug print options */
368 if (opt->flags & p_OPTION_MASK)
369 hdr->flags &= ~BHR_FLAG_PRINT_EN;
370 else
371 hdr->flags |=
372 BHR_FLAG_PRINT_EN; /* Enable printing by default */
374 if (opt->flags & b_OPTION_MASK) {
375 switch (opt->baudRate) {
376 case 2400:
377 hdr->options = BHR_OPT_BAUD_2400;
378 break;
380 case 4800:
381 hdr->options = BHR_OPT_BAUD_4800;
382 break;
384 case 9600:
385 hdr->options = BHR_OPT_BAUD_9600;
386 break;
388 case 19200:
389 hdr->options = BHR_OPT_BAUD_19200;
390 break;
392 case 38400:
393 hdr->options = BHR_OPT_BAUD_38400;
394 break;
396 case 57600:
397 hdr->options = BHR_OPT_BAUD_57600;
398 break;
400 case 115200:
401 hdr->options = BHR_OPT_BAUD_115200;
402 break;
404 default:
405 fprintf(stderr, "Unsupported baud rate - %d!\n",
406 opt->baudRate);
407 return 1;
409 } else
410 hdr->options = BHR_OPT_BAUD_DEFAULT;
412 /* debug port number */
413 if (opt->flags & u_OPTION_MASK)
414 hdr->options |= (opt->debugPortNum << BHR_OPT_UART_PORT_OFFS) &
415 BHR_OPT_UART_PORT_MASK;
417 /* debug port MPP setup index */
418 if (opt->flags & m_OPTION_MASK)
419 hdr->options |= (opt->debugPortMpp << BHR_OPT_UART_MPPS_OFFS) &
420 BHR_OPT_UART_MPPS_MASK;
422 hdr->destinationAddr = opt->image_dest;
423 hdr->executionAddr = (MV_U32)opt->image_exec;
424 hdr->version = MAIN_HDR_VERSION;
425 hdr->blockSize = fs_stat.st_size;
427 header_size = sizeof(BHR_t);
429 /* Update Block size address */
430 if ((opt->flags & X_OPTION_MASK) || (opt->flags & Y_OPTION_MASK)) {
431 /* Align padding to 32 bit */
432 if (opt->prepadding_size & 0x3)
433 opt->prepadding_size +=
434 (4 - (opt->prepadding_size & 0x3));
436 if (opt->postpadding_size & 0x3)
437 opt->postpadding_size +=
438 (4 - (opt->postpadding_size & 0x3));
440 hdr->blockSize += opt->prepadding_size + opt->postpadding_size;
443 /* Align the image size to 4 byte boundary */
444 if (hdr->blockSize & 0x3) {
445 opt->bytesToAlign = (4 - (hdr->blockSize & 0x3));
446 hdr->blockSize += opt->bytesToAlign;
449 /***************************** TWSI Header
450 * ********************************/
452 /* TWSI header has a special purpose and placed ahead of the main header
454 if (opt->flags & M_OPTION_MASK) {
455 if (opt->fname_twsi) {
456 if (build_twsi_header(opt) != 0)
457 goto header_error;
458 } /* opt->fname_twsi */
459 } /* (opt->flags & M_OPTION_MASK) */
461 /************************** End of TWSI Header
462 * ****************************/
464 /********************** Single Register Header
465 * ***************************/
467 if (opt->flags & R_OPTION_MASK) {
468 if (opt->fname_dram) {
469 MV_U32 rhdr_len = build_reg_header(
470 opt->fname_dram, tmpHeader, header_size);
471 if (rhdr_len <= 0)
472 goto header_error;
474 header_size += rhdr_len;
475 tailExtHdr = (tailExtBHR_t *)(tmpHeader + header_size -
476 sizeof(tailExtBHR_t));
477 } /* if (fname_dram) */
478 } /* if (opts & R_OPTION_MASK) */
480 /******************** End of Single Register Header
481 * ************************/
483 /************************* Single Binary Header
484 * ****************************/
486 if (opt->flags & G_OPTION_MASK) {
487 if (opt->fname_bin) {
488 MV_U32 bhdr_len = build_bin_header(
489 opt->fname_bin, tmpHeader, header_size);
490 if (bhdr_len <= 0)
491 goto header_error;
493 header_size += bhdr_len;
494 tailExtHdr = (tailExtBHR_t *)(tmpHeader + header_size -
495 sizeof(tailExtBHR_t));
496 } /* if (fname_bin) */
497 } /* (opt->flags & G_OPTION_MASK) */
499 /******************* End of Single Binary Header
500 * ***************************/
502 /************************* BIN/REG Headers list
503 * ****************************/
505 if (opt->flags & C_OPTION_MASK) {
506 if (opt->fname_list) {
507 FILE *f_list;
508 char buffer[PATH_MAX + 5];
509 char *fname;
510 MV_U32 hdr_len = 0, last;
511 int (*build_hdr_func)(char *, MV_U8 *, MV_U32);
513 f_list = fopen(opt->fname_list, "r");
514 if (f_list == NULL) {
515 fprintf(stderr, "File not found\n");
516 goto header_error;
518 /* read the headers list row by row */
519 while (fgets(buffer, PATH_MAX + 4, f_list) != NULL) {
520 /* Ignore strings that are not starting with
521 * BIN/REG */
522 if (strncmp(buffer, "BIN", 3) == 0)
523 build_hdr_func = build_bin_header;
524 else if (strncmp(buffer, "REG", 3) == 0)
525 build_hdr_func = build_reg_header;
526 else
527 continue;
529 fname = buffer + 3;
530 /* strip leading spaces/tabs if any */
531 while ((strncmp(fname, " ", 1) == 0) ||
532 (strncmp(fname, "\t", 1) == 0))
533 fname++;
535 /* strip trailing LF/CR symbols */
536 last = strlen(fname) - 1;
537 while ((strncmp(fname + last, "\n", 1) == 0) ||
538 (strncmp(fname + last, "\r", 1) == 0)) {
539 fname[last] = 0;
540 last--;
542 /* Insert required header into the output buffer
544 hdr_len = build_hdr_func(fname, tmpHeader,
545 header_size);
546 if (hdr_len <= 0)
547 goto header_error;
549 header_size += hdr_len;
550 tailExtHdr =
551 (tailExtBHR_t *)(tmpHeader + header_size -
552 sizeof(tailExtBHR_t));
555 fclose(f_list);
556 } /* if (fname_list) */
557 } /* (opt->flags & C_OPTION_MASK) */
559 /********************** End of BIN/REG Headers list
560 * ************************/
562 /* Align the headers block to... */
563 if (opt->image_type == IMG_NAND) {
564 /* ... NAND page size */
565 header_size +=
566 opt->nandPageSize - (header_size & (opt->nandPageSize - 1));
567 } else if ((opt->image_type == IMG_SATA) ||
568 (opt->image_type == IMG_MMC)) {
569 /* ... disk logical block size */
570 header_size += 512 - (header_size & 0x1FF);
571 } else if (opt->image_type == IMG_UART) {
572 /* ... Xmodem packet size */
573 header_size += 128 - (header_size & 0x7F);
575 /* Setup the image source address */
576 if (opt->image_type == IMG_SATA) {
577 if ((opt->image_source) && (opt->image_source > header_size))
578 hdr->sourceAddr = opt->image_source;
579 else
580 hdr->sourceAddr =
581 header_size >> 9; /* Already aligned to 512 */
582 } else {
583 if ((opt->image_source) && (opt->image_source > header_size)) {
584 hdr->sourceAddr = opt->image_source;
585 opt->img_gap = opt->image_source - header_size;
586 } else {
587 /* The source imgage address should be aligned
588 to 32 byte boundary (cache line size).
589 For NAND it should be aligned to 512 bytes boundary
590 (for ECC)
591 The image immediately follows the header block,
592 so if the source addess is undefined, it should be
593 derived from the header size.
594 The headers size is always alighed to 4 byte
595 boundary */
596 int boundary = 32;
598 if ((opt->image_type == IMG_NAND) ||
599 (opt->image_type == IMG_MMC))
600 boundary = 512;
602 if (header_size & (boundary - 1))
603 opt->img_gap =
604 boundary - (header_size & (boundary - 1));
606 hdr->sourceAddr = header_size + opt->img_gap;
610 /* source address and extension headers number can be written now */
611 fprintf(stdout,
612 "Ext. headers = %d, Header size = %d bytes Hdr-to-Img gap = %d bytes\n",
613 hdr->ext, header_size, opt->img_gap);
615 /* If not UART/TWSI image, an extra word for boot image checksum is
616 * needed */
617 if ((opt->image_type == IMG_FLASH) || (opt->image_type == IMG_NAND) ||
618 (opt->image_type == IMG_MMC) || (opt->image_type == IMG_SATA) ||
619 (opt->image_type == IMG_PEX) || (opt->image_type == IMG_I2C))
620 hdr->blockSize += 4;
622 fprintf(stdout,
623 "New image size = %#x[%d] Source image size = %#x[%d]\n",
624 hdr->blockSize, hdr->blockSize, (unsigned int)fs_stat.st_size,
625 (int)fs_stat.st_size);
627 hdr->hdrSizeMsb = (header_size & 0x00FF0000) >> 16;
628 hdr->hdrSizeLsb = header_size & 0x0000FFFF;
630 opt->image_sz = hdr->blockSize;
632 /* Load image into memory buffer */
633 if (REGULAR_IMAGE(opt)) {
634 if (0 != pre_load_image(opt, buf_in)) {
635 fprintf(stderr, "Failed image pre-load!\n");
636 goto header_error;
640 /* Now the headers block checksum should be calculated and wrote in the
641 * header */
642 /* This checksum value should be valid for both secure and unsecure boot
643 * modes */
644 /* This value will be checked first before RSA key and signature
645 * verification */
646 hdr->checkSum = checksum8((void *)hdr, MAIN_HDR_GET_LEN(hdr), 0);
648 /* Write to file(s) */
649 if (opt->header_mode == HDR_IMG_TWO_FILES) {
650 /* copy header to output image */
651 size_written = write(f_header, tmpHeader, header_size);
652 if (size_written != header_size) {
653 fprintf(stderr, "Error writing %s file\n"
654 , opt->fname.hdr_out);
655 goto header_error;
658 fprintf(stdout, "====>>>> %s was created\n",
659 opt->fname_arr[HDR_FILE_INDX]);
660 /* if (header_mode == HDR_IMG_TWO_FILES) */
661 } else {
662 /* copy header to output image */
663 size_written = write(f_out, tmpHeader, header_size);
664 if (size_written != header_size) {
665 fprintf(stderr, "Error writing %s file\n"
666 , opt->fname.out);
667 goto header_error;
670 } /* if (header_mode != HDR_IMG_TWO_FILES) */
672 error = 0;
674 header_error:
676 if (tmpHeader)
677 free(tmpHeader);
679 return error;
681 } /* end of build_headers() */
683 /*******************************************************************************
684 * build_bootrom_img
685 * create image in bootrom format and write it into output stream
686 * INPUT:
687 * opt user options
688 * buf_in mmapped input file
689 * OUTPUT:
690 * none
691 * RETURN:
692 * 0 on success
693 *******************************************************************************/
694 int build_bootrom_img(USER_OPTIONS *opt, char *buf_in)
696 unsigned int CRC_32 = 0;
697 int tmpSize = BOOTROM_SIZE - sizeof(CRC_32);
698 char *tmpImg = NULL;
699 int size_written = 0;
700 int error = 1;
702 tmpImg = malloc(tmpSize);
703 if (tmpImg == NULL)
704 return 1;
706 /* PAD image with Zeros until BOOTROM_SIZE*/
707 memcpy(tmpImg, buf_in, fs_stat.st_size);
708 memset(tmpImg + fs_stat.st_size, 0, tmpSize - fs_stat.st_size);
710 /* copy input image to output image */
711 size_written = write(f_out, tmpImg, tmpSize);
713 /* calculate checsum */
714 CRC_32 = crc32(0, (u32 *)tmpImg, tmpSize / 4);
715 tmpSize += sizeof(CRC_32);
716 printf("Image CRC32 (size = %d) = 0x%08x\n", tmpSize, CRC_32);
718 size_written += write(f_out, &CRC_32, sizeof(CRC_32));
720 if (size_written == tmpSize)
721 error = 0;
723 bootrom_img_error:
725 if (tmpImg)
726 free(tmpImg);
728 return error;
729 } /* end of build_bootrom_img() */
731 /*******************************************************************************
732 * build_hex_img
733 * create image in hex format and write it into output stream
734 * INPUT:
735 * opt user options
736 * buf_in mmapped input file
737 * OUTPUT:
738 * none
739 * RETURN:
740 * 0 on success
741 *******************************************************************************/
742 int build_hex_img(USER_OPTIONS *opt, char *buf_in)
744 FILE *f_desc[2] = {NULL};
745 char *tmpImg = NULL;
746 int hex_len;
747 int hex_unaligned_len = 0;
748 unsigned char *hex8 = NULL;
749 unsigned char tmp8;
750 unsigned short *hex16 = NULL;
751 unsigned short tmp16;
752 unsigned int *hex32 = NULL;
753 unsigned int tmp32;
754 unsigned int tmp32_low;
755 int size_written = 0;
756 int alignment = 0;
757 int files_num;
758 int i;
759 int error = 1;
761 /* Calculate aligned image size */
762 hex_len = fs_stat.st_size;
764 alignment = opt->hex_width >> 3;
765 hex_unaligned_len = fs_stat.st_size & (alignment - 1);
767 if (hex_unaligned_len) {
768 hex_len -= hex_unaligned_len;
769 hex_len += alignment;
772 /* Copy the input image to memory buffer */
773 tmpImg = malloc(hex_len);
774 if (tmpImg == NULL)
775 goto hex_image_end;
777 memset(tmpImg, 0, hex_len);
778 memcpy(tmpImg, buf_in, fs_stat.st_size);
780 if (opt->fname.hdr_out)
781 files_num = 2;
782 else
783 files_num = 1;
785 for (i = 0; i < files_num; i++) {
786 f_desc[i] = fopen(opt->fname_arr[i + 1], "w");
787 if (f_desc[i] == NULL)
788 goto hex_image_end;
791 switch (opt->hex_width) {
792 case 8:
793 hex8 = (unsigned char *)tmpImg;
795 for (i = 0; hex_len > 0; hex_len--) {
796 fprintf(f_desc[i], "%02X\n", *hex8++);
797 size_written += 1;
798 i ^= files_num - 1;
800 break;
802 case 16:
803 hex16 = (unsigned short *)tmpImg;
805 for (; hex_len > 0; hex_len -= 2) {
806 fprintf(f_desc[0], "%04X\n", *hex16++);
807 size_written += 2;
809 break;
811 case 32:
812 hex32 = (unsigned int *)tmpImg;
814 for (; hex_len > 0; hex_len -= 4) {
815 fprintf(f_desc[0], "%08X\n", *hex32++);
816 size_written += 4;
818 break;
820 case 64:
821 hex32 = (unsigned int *)tmpImg;
823 for (; hex_len > 0; hex_len -= 8) {
824 fprintf(f_desc[0], "%08X%08X\n", *hex32++, *hex32++);
825 size_written += 8;
827 break;
829 } /* switch (opt->hex_width)*/
831 error = 0;
833 hex_image_end:
835 if (tmpImg)
836 free(tmpImg);
838 for (i = 0; i < files_num; i++) {
839 if (f_desc[i] != NULL)
840 fclose(f_desc[i]);
843 return error;
844 } /* end of build_hex_img() */
846 /*******************************************************************************
847 * build_bin_img
848 * create image in binary format and write it into output stream
849 * INPUT:
850 * opt user options
851 * buf_in mmapped input file
852 * OUTPUT:
853 * none
854 * RETURN:
855 * 0 on success
856 *******************************************************************************/
857 int build_bin_img(USER_OPTIONS *opt, char *buf_in)
859 FILE *f_ds = NULL;
860 FILE *f_desc[4] = {NULL};
861 char *tmpImg = NULL;
862 int hex_len = 0;
863 int one_file_len = 0;
864 int size_written = 0;
865 int alignment = 0;
866 int hex_unaligned_len = 0;
867 unsigned char *hex8 = NULL;
868 unsigned char tmp8;
869 unsigned short *hex16 = NULL;
870 unsigned short tmp16;
871 unsigned long *hex32 = NULL;
872 unsigned long tmp32;
873 unsigned long tmp32low;
874 int i;
875 int fidx;
876 int files_num = 1;
877 int error = 1;
879 /* Calculate aligned image size */
880 hex_len = fs_stat.st_size;
882 alignment = opt->hex_width >> 3;
883 hex_unaligned_len = fs_stat.st_size & (alignment - 1);
885 if (hex_unaligned_len) {
886 hex_len -= hex_unaligned_len;
887 hex_len += alignment;
890 /* prepare output files */
891 if (opt->fname.romd) /*16KB*/
892 files_num = 4;
893 else if (opt->fname.romc) /*12KB*/
894 files_num = 3;
895 else if (opt->fname.hdr_out)
896 files_num = 2;
898 one_file_len = hex_len / files_num;
900 for (i = 0; i < files_num; i++) {
901 f_desc[i] = fopen(opt->fname_arr[i + 1], "w");
902 if (f_desc[i] == NULL)
903 goto bin_image_end;
906 /* Copy the input image to memory buffer */
907 tmpImg = malloc(hex_len);
908 if (tmpImg == NULL)
909 goto bin_image_end;
911 memset(tmpImg, 0, (hex_len));
912 memcpy(tmpImg, buf_in, fs_stat.st_size);
914 /* Split output image buffer according to width and number of files */
915 switch (opt->hex_width) {
916 case 8:
917 hex8 = (unsigned char *)tmpImg;
918 if (files_num != 2) {
919 fprintf(stderr,
920 "Must supply two output file names for this width!\n");
921 goto bin_image_end;
924 for (fidx = 1; (fidx >= 0) && (hex_len > 0); fidx--) {
925 f_ds = f_desc[1 - fidx];
927 for (; hex_len > (fidx * one_file_len); hex_len--) {
928 tmp8 = *hex8;
930 for (i = 0; i < opt->hex_width; i++) {
931 fprintf(f_ds, "%d",
932 ((tmp8 & 0x80) >> 7));
933 tmp8 <<= 1;
935 fprintf(f_ds, "\n");
937 hex8++;
938 size_written += 1;
941 break;
943 case 16:
944 hex16 = (unsigned short *)tmpImg;
946 for (; hex_len > 0; hex_len -= 2) {
947 tmp16 = *hex16;
949 for (i = 0; i < opt->hex_width; i++) {
950 fprintf(f_desc[0], "%d",
951 ((tmp16 & 0x8000) >> 15));
952 tmp16 <<= 1;
954 fprintf(f_desc[0], "\n");
956 hex16++;
957 size_written += 2;
959 break;
961 case 32:
962 hex32 = (long *)tmpImg;
964 for (fidx = files_num - 1; (fidx >= 0) && (hex_len > 0);
965 fidx--) {
966 f_ds = f_desc[files_num - 1 - fidx];
968 for (; hex_len > (fidx * one_file_len); hex_len -= 4) {
969 tmp32 = *hex32;
971 for (i = 0; i < opt->hex_width; i++) {
972 fprintf(f_ds, "%ld",
973 ((tmp32 & 0x80000000) >> 31));
974 tmp32 <<= 1;
976 fprintf(f_ds, "\n");
977 hex32++;
978 size_written += 4;
981 break;
983 case 64:
984 hex32 = (long *)tmpImg;
986 for (; hex_len > 0; hex_len -= 8) {
987 tmp32low = *hex32++;
988 tmp32 = *hex32++;
990 for (i = 0; i < 32; i++) {
991 fprintf(f_desc[0], "%ld",
992 ((tmp32 & 0x80000000) >> 31));
993 tmp32 <<= 1;
995 for (i = 0; i < 32; i++) {
996 fprintf(f_desc[0], "%ld",
997 ((tmp32low & 0x80000000) >> 31));
998 tmp32low <<= 1;
1000 fprintf(f_desc[0], "\n");
1001 size_written += 8;
1003 break;
1004 } /* switch (opt->hex_width) */
1006 error = 0;
1008 bin_image_end:
1010 if (tmpImg)
1011 free(tmpImg);
1013 for (i = 0; i < files_num; i++) {
1014 if (f_desc[i] != NULL)
1015 fclose(f_desc[i]);
1018 return error;
1020 } /* end of build_bin_img() */
1022 /*******************************************************************************
1023 * build_regular_img
1024 * create regular boot image and write it into output stream
1025 * INPUT:
1026 * opt user options
1027 * buf_in mmapped input file
1028 * OUTPUT:
1029 * none
1030 * RETURN:
1031 * 0 on success
1032 *******************************************************************************/
1033 int build_regular_img(USER_OPTIONS *opt, char *buf_in)
1035 int size_written = 0;
1036 int new_file_size = 0;
1037 MV_U32 chsum32 = 0;
1039 new_file_size = opt->image_sz;
1041 if (0 != opt->img_gap) { /* cache line/NAND page/requested offset image
1042 alignment */
1043 MV_U8 *gap_buf;
1045 gap_buf = calloc(opt->img_gap, sizeof(MV_U8));
1046 if (gap_buf == NULL) {
1047 fprintf(stderr,
1048 "Failed to allocate memory for header to image gap!\n");
1049 return 1;
1051 size_written += write(f_out, gap_buf, opt->img_gap);
1052 new_file_size += opt->img_gap;
1053 free(gap_buf);
1056 /* Calculate checksum and copy it to the image tail */
1057 chsum32 = checksum32((void *)opt->image_buf, opt->image_sz - 4, 0);
1058 memcpy(opt->image_buf + opt->image_sz - 4, &chsum32, 4);
1060 /* copy input image to output image */
1061 size_written += write(f_out, opt->image_buf, opt->image_sz);
1062 free(opt->image_buf);
1064 if (new_file_size != size_written) {
1065 fprintf(stderr, "Size mismatch between calculated/written\n");
1066 return 1;
1069 return 0;
1070 } /* end of build_other_img() */
1072 /*******************************************************************************
1073 * process_image
1074 * handle input and output file options, read and verify RSA and AES
1075 *keys.
1076 * INPUT:
1077 * opt user options
1078 * OUTPUT:
1079 * none
1080 * RETURN:
1081 * 0 on success
1082 ******************************************************************************/
1083 int process_image(USER_OPTIONS *opt)
1085 int i;
1086 int override[2];
1087 char *buf_in = NULL;
1088 int err = 1;
1090 /* check if the output image exist */
1091 printf(" ");
1092 for (i = IMG_FILE_INDX; i <= HDR_FILE_INDX; i++) {
1093 if (opt->fname_arr[i]) {
1094 override[i] = 0;
1096 if (0 == stat(opt->fname_arr[i], &fs_stat)) {
1097 char c;
1098 /* ask for overwrite permissions */
1099 fprintf(stderr,
1100 "File '%s' already exist! Overwrite it (Y/n)?",
1101 opt->fname_arr[i]);
1102 c = getc(stdin);
1103 if ((c == 'N') || (c == 'n')) {
1104 printf("exit.. nothing done.\n");
1105 exit(0);
1106 } else if ((c == 'Y') || (c == 'y')) {
1107 /* additional read is needed for Enter
1108 * key */
1109 c = getc(stdin);
1111 override[i] = 1;
1116 /* open input image file and check if it's size is OK */
1117 if (opt->header_mode != HDR_ONLY) {
1118 f_in = open(opt->fname.in, O_RDONLY | O_BINARY);
1119 if (f_in == -1) {
1120 fprintf(stderr, "File '%s' not found\n", opt->fname.in);
1121 goto end;
1123 /* get the size of the input image */
1124 if (0 != fstat(f_in, &fs_stat)) {
1125 fprintf(stderr, "fstat failed for file: '%s' err=%d\n",
1126 opt->fname.in, err);
1127 goto end;
1129 /*Check the source image size for limited output storage
1130 * (bootrom) */
1131 if (opt->image_type == IMG_BOOTROM) {
1132 int max_img_size = BOOTROM_SIZE - sizeof(u32);
1134 if (fs_stat.st_size > max_img_size) {
1135 fprintf(stderr,
1136 "ERROR : source image is bigger than %d bytes\n",
1137 max_img_size);
1138 goto end;
1141 /* map the input image */
1142 buf_in =
1143 mmap(0, fs_stat.st_size, PROT_READ, MAP_SHARED, f_in, 0);
1144 if (!buf_in) {
1145 fprintf(stderr, "Error mapping %s file\n",
1146 opt->fname.in);
1147 goto end;
1151 /* open the output image file */
1152 if (override[IMG_FILE_INDX] == 0)
1153 f_out = open(opt->fname.out,
1154 O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0666);
1155 else
1156 f_out = open(opt->fname.out, O_RDWR | O_BINARY);
1158 if (f_out == -1) {
1159 fprintf(stderr, "Error opening %s file\n", opt->fname.out);
1160 goto end;
1163 /* open the output header file */
1164 if (opt->header_mode == HDR_IMG_TWO_FILES) {
1165 if (override[HDR_FILE_INDX] == 0)
1166 f_header =
1167 open(opt->fname.hdr_out,
1168 O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0666);
1169 else
1170 f_header = open(opt->fname.hdr_out, O_RDWR | O_BINARY);
1172 if (f_header == -1) {
1173 fprintf(stderr, "Error opening %s file\n",
1174 opt->fname.hdr_out);
1175 goto end;
1179 /* Image Header(s) */
1180 if (opt->header_mode != IMG_ONLY) {
1181 if (0 != build_headers(opt, buf_in))
1182 goto end;
1185 /* Output Image */
1186 if (opt->header_mode != HDR_ONLY) {
1187 if (opt->image_type == IMG_BOOTROM)
1188 err = build_bootrom_img(opt, buf_in);
1189 else if (opt->image_type == IMG_HEX)
1190 err = build_hex_img(opt, buf_in);
1191 else if (opt->image_type == IMG_BIN)
1192 err = build_bin_img(opt, buf_in);
1193 else
1194 err = build_regular_img(opt, buf_in);
1196 if (err != 0) {
1197 fprintf(stderr, "Error writing %s file\n"
1198 , opt->fname.out);
1199 goto end;
1202 fprintf(stdout, "====>>>> %s was created\n",
1203 opt->fname_arr[IMG_FILE_INDX]);
1205 } /* if (opt->header_mode != HDR_ONLY) */
1207 end:
1208 /* close handles */
1209 if (f_out != -1)
1210 close(f_out);
1212 if (f_header != -1)
1213 close(f_header);
1215 if (buf_in)
1216 munmap((void *)buf_in, fs_stat.st_size);
1218 if (f_in != -1)
1219 close(f_in);
1221 return err;
1223 } /* end of process_image() */
1225 /*******************************************************************************
1226 * print_usage
1227 * print command switches and their description
1228 * INPUT:
1229 * none
1230 * OUTPUT:
1231 * none
1232 * RETURN:
1233 * none
1234 *******************************************************************************/
1235 void print_usage(void)
1237 printf(
1238 "==============================================================================================\n\n");
1239 printf("Marvell doimage Tool version %s\n", VERSION_NUMBER);
1240 printf("Supported SoC devices:\n\t%s\n", PRODUCT_SUPPORT);
1241 printf(
1242 "==============================================================================================\n\n");
1243 printf("Usage:\n");
1244 printf(
1245 "doimage <mandatory_opt> [other_options] [bootrom_output] <image_in> <image_out> [header_out]\n\n");
1247 printf("<mandatory_opt> - can be one or more of the following:\n");
1248 printf(
1249 "==============================================================================================\n\n");
1251 printf(
1252 "-T image_type: sata\\uart\\flash\\bootrom\\nand\\hex\\bin\\pex\\mmc\n");
1253 printf("-D image_dest: image destination in dram (in hex)\n");
1254 printf("-E image_exec: execution address in dram (in hex)\n");
1255 printf(
1256 " if image_type is 'flash' and image_dest is 0xffffffff\n");
1257 printf(" then execution address on the flash\n");
1258 printf(
1259 "-S image_source: if image_type is sata then the starting sector of\n");
1260 printf(" the source image on the disk\n");
1261 printf(
1262 " if image_type is flash\\nand then the starting offset of\n");
1263 printf(
1264 " the source image at the flash - optional for flash\\nand\n");
1265 printf("-W hex_width : HEX file width, can be 8,16,32,64\n");
1266 printf(
1267 "-M twsi_file: ascii file name that contains the I2C init regs set by h/w.\n");
1268 printf(" this is used in i2c boot only\n");
1270 printf("\nThe following options are mandatory for NAND image type:\n");
1271 printf(
1272 "-----------------------------------------------------------------------------------------------\n\n");
1274 printf(
1275 "-L nand_blk_size:NAND block size in KBytes (decimal int in range 64-16320)\n");
1276 printf(
1277 " This parameter is ignored for flashes with 512B pages\n");
1278 printf(
1279 " Such small page flashes always use 16K block sizes\n");
1280 printf(
1281 "-N nand_cell_typ:NAND cell technology type (char: M for MLC, S for SLC)\n");
1282 printf(
1283 "-P nand_pg_size: NAND page size: (decimal 512, 2048, 4096 or 8192)\n");
1285 printf(
1286 "-G exec_file: ascii file name that contains binary routine (ARM 5TE THUMB)\n");
1287 printf(
1288 " to run before the bootloader image execution.\n");
1289 printf(
1290 " The routine must contain an appropriate code for saving\n");
1291 printf(
1292 " all registers at the routine start and restore them\n");
1293 printf(" before return from the routine\n");
1294 printf(
1295 "-R dram_file: ascii file name that contains the list of dram regs\n");
1296 printf(
1297 "-C hdrs_file: ascii file name that defines BIN/REG headers order and their sources\n");
1298 printf("-X pre_padding_size (hex)\n");
1299 printf("-Y post_padding_size (hex)\n");
1300 printf("-H header_mode: Header mode, can be:\n");
1301 printf(
1302 " -H 1 : will create one file (image_out) for header and image\n");
1303 printf(
1304 " -H 2 : will create two files, (image_out) for image , (header_out) for header\n");
1305 printf(
1306 " -H 3 : will create one file (image_out) for header only\n");
1307 printf(
1308 " -H 4 : will create one file (image_out) for image only\n");
1310 printf(
1311 "\n[bootrom_output] - optional and can be one or more of the following:\n");
1312 printf(
1313 "==============================================================================================\n\n");
1315 printf(
1316 "-p Disable BootROM messages output to UART port (enabled by default)\n");
1317 printf("-b baudrate Set BootROM debug port UART baudrate\n");
1318 printf(
1319 " value = 2400,4800,9600,19200,38400,57600,115200 (use default baudrate is omitted)\n");
1320 printf(
1321 "-u port_num Set BootROM debug port UART number value = 0-3 (use default port if omitted)\n");
1322 printf(
1323 "-m mpp_config Select BootROM debug port MPPs configuration value = 0-7 (BootROM-specific)\n");
1325 printf("\nCommand examples:\n\n");
1327 printf("doimage -T hex -W width image_in image_out\n");
1328 printf("doimage -T bootrom image_in image_out\n");
1329 printf("doimage -T resume image_in image_out\n");
1330 printf("doimage -T sata -S sector -D image_dest -E image_exec\n");
1331 printf(" [other_options] image_in image_out header_out\n\n");
1332 printf("doimage -T flash -D image_dest -E image_exec [-S address]\n");
1333 printf(" [other_options] image_in image_out\n\n");
1334 printf("doimage -T pex -D image_dest -E image_exec\n");
1335 printf(" [other_options] image_in image_out\n\n");
1336 printf(
1337 "doimage -T nand -D image_dest -E image_exec [-S address] -P page_size\n");
1338 printf(" -L 2 -N S [other_options] image_in image_out\n\n");
1339 printf("doimage -T uart -D image_dest -E image_exec\n");
1340 printf(" [other_options] image_in image_out\n\n");
1341 printf("doimage -T pex -D image_dest -E image_exec\n");
1342 printf(" [other_options] image_in image_out\n\n");
1343 printf("\n\n");
1345 } /* end of print_usage() */
1347 /*******************************************************************************
1348 * checksum8
1349 * calculate 8-bit checksum of memory buffer
1350 * INPUT:
1351 * start buffer start
1352 * len buffer length
1353 * csum initial checksum value
1354 * OUTPUT:
1355 * none
1356 * RETURN:
1357 * 8-bit buffer checksum
1358 *******************************************************************************/
1359 MV_U8 checksum8(void *start, MV_U32 len, MV_U8 csum)
1361 register MV_U8 sum = csum;
1363 volatile MV_U8 *startp = (volatile MV_U8 *)start;
1365 do {
1366 sum += *(MV_U8 *)startp;
1367 startp++;
1369 } while (--len);
1371 return sum;
1373 } /* end of checksum8 */
1375 /*******************************************************************************
1376 * checksum32
1377 * calculate 32-bit checksum of memory buffer
1378 * INPUT:
1379 * start buffer start
1380 * len buffer length
1381 * csum initial checksum value
1382 * OUTPUT:
1383 * none
1384 * RETURN:
1385 * 32-bit buffer checksum
1386 *******************************************************************************/
1387 MV_U32 checksum32(void *start, MV_U32 len, MV_U32 csum)
1389 register MV_U32 sum = csum;
1390 volatile MV_U32 *startp = (volatile MV_U32 *)start;
1392 do {
1393 sum += *(MV_U32 *)startp;
1394 startp++;
1395 len -= 4;
1397 } while (len);
1399 return sum;
1401 } /* *end of checksum32() */
1403 /*******************************************************************************
1404 * make_crc_table
1405 * init CRC table
1406 * INPUT:
1407 * crc_table CRC table location
1408 * OUTPUT:
1409 * crc_table CRC table location
1410 * RETURN:
1411 * none
1412 *******************************************************************************/
1413 void make_crc_table(MV_U32 *crc_table)
1415 MV_U32 c;
1416 MV_32 n, k;
1417 MV_U32 poly;
1419 /* terms of polynomial defining this crc (except x^32): */
1420 static const MV_U8 p[] = {0, 1, 2, 4, 5, 7, 8,
1421 10, 11, 12, 16, 22, 23, 26};
1423 /* make exclusive-or pattern from polynomial (0xedb88320L) */
1424 poly = 0L;
1425 for (n = 0; n < sizeof(p) / sizeof(MV_U8); n++)
1426 poly |= 1L << (31 - p[n]);
1428 for (n = 0; n < 256; n++) {
1429 c = (MV_U32)n;
1430 for (k = 0; k < 8; k++)
1431 c = c & 1 ? poly ^ (c >> 1) : c >> 1;
1432 crc_table[n] = c;
1435 } /* end of make_crc_table */
1437 #define DO1(buf) (crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8))
1438 #define DO2(buf) do { \
1439 DO1(buf); \
1440 DO1(buf); \
1441 } while (0)
1442 #define DO4(buf) do { \
1443 DO2(buf); \
1444 DO2(buf); \
1445 } while (0)
1446 #define DO8(buf) do { \
1447 DO4(buf); \
1448 DO4(buf); \
1449 } while (0)
1451 /*******************************************************************************
1452 * crc32
1453 * calculate CRC32 on memory buffer
1454 * INPUT:
1455 * crc initial CRC value
1456 * buf memory buffer
1457 * len buffer length
1458 * OUTPUT:
1459 * none
1460 * RETURN:
1461 * CRC32 of the memory buffer
1462 *******************************************************************************/
1463 MV_U32 crc32(MV_U32 crc, volatile MV_U32 *buf, MV_U32 len)
1465 MV_U32 crc_table[256];
1467 /* Create the CRC table */
1468 make_crc_table(crc_table);
1470 crc = crc ^ 0xffffffffL;
1471 while (len >= 8) {
1472 DO8(buf);
1473 len -= 8;
1476 if (len) {
1477 do {
1478 DO1(buf);
1479 } while (--len);
1482 return crc ^ 0xffffffffL;
1484 } /* end of crc32() */
1486 /*******************************************************************************
1487 * select_image
1488 * select image options by the image name
1489 * INPUT:
1490 * img_name image name
1491 * OUTPUT:
1492 * opt image options
1493 * RETURN:
1494 * 0 on success, 1 if image name is invalid
1495 *******************************************************************************/
1496 int select_image(char *img_name, USER_OPTIONS *opt)
1498 int i;
1500 static IMG_MAP img_map[] = {
1501 {IMG_SATA, "sata", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK},
1502 {IMG_UART, "uart", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK},
1503 {IMG_FLASH, "flash", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK},
1504 {IMG_MMC, "mmc", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK},
1505 {IMG_BOOTROM, "bootrom", T_OPTION_MASK},
1506 {IMG_NAND, "nand", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK |
1507 L_OPTION_MASK | N_OPTION_MASK |
1508 P_OPTION_MASK},
1509 {IMG_HEX, "hex", T_OPTION_MASK | W_OPTION_MASK},
1510 {IMG_BIN, "bin", T_OPTION_MASK | W_OPTION_MASK},
1511 {IMG_PEX, "pex", D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK},
1512 {IMG_I2C, "i2c",
1513 D_OPTION_MASK | T_OPTION_MASK | E_OPTION_MASK | M_OPTION_MASK},
1516 for (i = 0; i < ARRAY_SIZE(img_map); i++) {
1517 if (strcmp(img_name, img_map[i].img_name) == 0) {
1518 opt->image_type = img_map[i].img_type;
1519 opt->req_flags = img_map[i].img_opt;
1520 return 0;
1524 return 1;
1526 } /* *end of select_image() */
1528 /*******************************************************************************
1529 * main
1530 *******************************************************************************/
1531 int main(int argc, char **argv)
1533 USER_OPTIONS options;
1534 int optch; /* command-line option char */
1535 static char optstring[] =
1536 "T:D:E:X:Y:S:P:W:H:R:M:G:L:N:C:b:u:m:p";
1537 int i, k;
1539 if (argc < 2)
1540 goto parse_error;
1542 memset(&options, 0, sizeof(USER_OPTIONS));
1543 options.header_mode = HDR_IMG_ONE_FILE;
1545 fprintf(stdout, "\n");
1547 while ((optch = getopt(argc, argv, optstring)) != -1) {
1548 char *endptr = NULL;
1550 switch (optch) {
1551 case 'T': /* image type */
1552 if ((select_image(optarg, &options) != 0) ||
1553 (options.flags & T_OPTION_MASK))
1554 goto parse_error;
1555 options.flags |= T_OPTION_MASK;
1556 break;
1558 case 'D': /* image destination */
1559 options.image_dest = strtoul(optarg, &endptr, 16);
1560 if (*endptr || (options.flags & D_OPTION_MASK))
1561 goto parse_error;
1562 options.flags |= D_OPTION_MASK;
1563 DB("Image destination address %#x\n",
1564 options.image_dest);
1565 break;
1567 case 'E': /* image execution */
1568 options.image_exec = strtoul(optarg, &endptr, 16);
1569 if (*endptr || (options.flags & E_OPTION_MASK))
1570 goto parse_error;
1571 options.flags |= E_OPTION_MASK;
1572 DB("Image execution address %#x\n", options.image_exec);
1573 break;
1575 case 'X': /* Pre - Padding */
1576 options.prepadding_size = strtoul(optarg, &endptr, 16);
1577 if (*endptr || (options.flags & X_OPTION_MASK))
1578 goto parse_error;
1579 options.pre_padding = 1;
1580 options.flags |= X_OPTION_MASK;
1581 DB("Pre-pad image by %#x bytes\n",
1582 options.prepadding_size);
1583 break;
1585 case 'Y': /* Post - Padding */
1586 options.postpadding_size = strtoul(optarg, &endptr, 16);
1587 if (*endptr || (options.flags & Y_OPTION_MASK))
1588 goto parse_error;
1589 options.post_padding = 1;
1590 options.flags |= Y_OPTION_MASK;
1591 DB("Post-pad image by %#x bytes\n",
1592 options.postpadding_size);
1593 break;
1595 case 'S': /* starting sector */
1596 options.image_source = strtoul(optarg, &endptr, 16);
1597 if (*endptr || (options.flags & S_OPTION_MASK))
1598 goto parse_error;
1599 options.flags |= S_OPTION_MASK;
1600 DB("Image start sector (image source) %#x\n",
1601 options.image_source);
1602 break;
1604 case 'P': /* NAND Page Size */
1605 options.nandPageSize = strtoul(optarg, &endptr, 10);
1606 if (*endptr || (options.flags & P_OPTION_MASK))
1607 goto parse_error;
1608 options.flags |= P_OPTION_MASK;
1609 DB("NAND page size %d bytes\n", options.nandPageSize);
1610 break;
1612 case 'C': /* headers definition filename */
1613 options.fname_list = optarg;
1614 if (options.flags & C_OPTION_MASK)
1615 goto parse_error;
1616 options.flags |= C_OPTION_MASK;
1617 DB("Headers definition file name %s\n",
1618 options.fname_list);
1619 break;
1621 case 'W': /* HEX file width */
1622 options.hex_width = strtoul(optarg, &endptr, 10);
1623 if (*endptr || (options.flags & W_OPTION_MASK))
1624 goto parse_error;
1625 options.flags |= W_OPTION_MASK;
1626 DB("HEX file width %d bytes\n", options.hex_width);
1627 break;
1629 case 'H': /* Header file mode */
1630 options.header_mode = strtoul(optarg, &endptr, 10);
1631 if (*endptr || (options.flags & H_OPTION_MASK))
1632 goto parse_error;
1633 options.flags |= H_OPTION_MASK;
1634 DB("Header file mode is %d\n", options.header_mode);
1635 break;
1637 case 'R': /* dram file */
1638 options.fname_dram = optarg;
1639 if (options.flags & R_OPTION_MASK)
1640 goto parse_error;
1641 options.flags |= R_OPTION_MASK;
1642 DB("Registers header file name %s\n",
1643 options.fname_dram);
1644 break;
1646 case 'M': /* TWSI file */
1647 options.fname_twsi = optarg;
1648 if (options.flags & M_OPTION_MASK)
1649 goto parse_error;
1650 options.flags |= M_OPTION_MASK;
1651 DB("TWSI header file name %s\n", options.fname_twsi);
1652 break;
1654 case 'G': /* binary file */
1655 options.fname_bin = optarg;
1656 if (options.flags & G_OPTION_MASK)
1657 goto parse_error;
1658 options.flags |= G_OPTION_MASK;
1659 DB("Binary header file name %s\n", options.fname_bin);
1660 break;
1662 case 'L': /* NAND block size */
1663 options.nandBlkSize = strtoul(optarg, &endptr, 10) / 64;
1664 if (*endptr || (options.flags & L_OPTION_MASK))
1665 goto parse_error;
1666 options.flags |= L_OPTION_MASK;
1667 DB("NAND block size %d\n", options.nandBlkSize);
1668 break;
1670 case 'N': /* NAND cell technology */
1671 options.nandCellTech = optarg[0];
1672 if (options.flags & N_OPTION_MASK)
1673 goto parse_error;
1674 options.flags |= N_OPTION_MASK;
1675 DB("NAND cell technology %c\n", options.nandCellTech);
1676 break;
1678 case 'p': /* BootROM debug output */
1679 if (options.flags & p_OPTION_MASK)
1680 goto parse_error;
1681 options.flags |= p_OPTION_MASK;
1682 DB("BootROM debug output disabled\n");
1683 break;
1685 case 'b': /* BootROM debug port baudrate */
1686 options.baudRate = strtoul(optarg, &endptr, 10);
1687 if (*endptr || (options.flags & b_OPTION_MASK))
1688 goto parse_error;
1689 options.flags |= b_OPTION_MASK;
1690 DB("BootROM debug port baudrate %d\n",
1691 options.baudRate);
1692 break;
1694 case 'u': /* BootROM debug port number */
1695 options.debugPortNum = strtoul(optarg, &endptr, 10);
1696 if (*endptr || (options.flags & u_OPTION_MASK))
1697 goto parse_error;
1698 options.flags |= u_OPTION_MASK;
1699 DB("BootROM debug port number %d\n",
1700 options.debugPortNum);
1701 break;
1703 case 'm': /* BootROM debug port MPP settings */
1704 options.debugPortMpp = strtoul(optarg, &endptr, 10);
1705 if (*endptr || (options.flags & m_OPTION_MASK))
1706 goto parse_error;
1707 options.flags |= m_OPTION_MASK;
1708 DB("BootROM debug port MPP setup # %d\n",
1709 options.debugPortMpp);
1710 break;
1712 default:
1713 goto parse_error;
1715 } /* parse command-line options */
1717 /* assign file names */
1718 for (i = 0; (optind < argc) && (i < ARRAY_SIZE(options.fname_arr));
1719 ++optind, i++) {
1720 options.fname_arr[i] = argv[optind];
1721 DB("File @ array index %d is %s (option index is %d)\n", i,
1722 argv[optind], optind);
1723 /* verify that all file names are different */
1724 for (k = 0; k < i; k++) {
1725 if (0 == strcmp(options.fname_arr[i],
1726 options.fname_arr[k])) {
1727 fprintf(stderr,
1728 "\nError: Input and output images can't be the same\n");
1729 exit(1);
1734 if (!(options.flags & T_OPTION_MASK))
1735 goto parse_error;
1737 /* verify HEX/BIN file width selection to be valid */
1738 if ((options.flags & W_OPTION_MASK) && (options.hex_width != 8) &&
1739 (options.hex_width != 16) && (options.hex_width != 32) &&
1740 (options.hex_width != 64))
1741 goto parse_error;
1742 /* BootROM test images, no header is needed */
1743 if ((options.image_type == IMG_BOOTROM) ||
1744 (options.image_type == IMG_HEX) || (options.image_type == IMG_BIN))
1745 options.header_mode = IMG_ONLY;
1747 if (options.header_mode == IMG_ONLY) {
1748 /* remove unneeded options */
1749 options.req_flags &=
1750 ~(D_OPTION_MASK | E_OPTION_MASK | S_OPTION_MASK |
1751 R_OPTION_MASK | P_OPTION_MASK | L_OPTION_MASK |
1752 N_OPTION_MASK);
1755 if (options.req_flags != (options.flags & options.req_flags))
1756 goto parse_error;
1758 if ((options.flags & L_OPTION_MASK) &&
1759 ((options.nandBlkSize > 255) ||
1760 ((options.nandBlkSize == 0) && (options.nandPageSize != 512)))) {
1761 fprintf(stderr, "Error: wrong NAND block size %d!\n\n\n\n\n",
1762 64 * options.nandBlkSize);
1763 goto parse_error;
1766 if ((options.flags & N_OPTION_MASK) && (options.nandCellTech != 'S') &&
1767 (options.nandCellTech != 'M') && (options.nandCellTech != 's') &&
1768 (options.nandCellTech != 'm')) {
1769 fprintf(stderr,
1770 "Error: Wrong NAND cell technology type!\n\n\n\n\n");
1771 goto parse_error;
1774 return process_image(&options);
1776 parse_error:
1778 print_usage();
1779 exit(1);
1781 } /* end of main() */