1
0
uboot-1.1.4-kirkwood/tools/doimage.c

1264 lines
33 KiB
C
Raw Permalink Normal View History

2024-01-09 13:43:28 +01:00
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
*******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#define _HOST_COMPILER
#include "bootstrap_def.h"
#ifndef O_BINARY /* should be define'd on __WIN32__ */
#define O_BINARY 0
#endif
#define DOIMAGE_VERSION "1.00"
void print_usage(void);
int f_in = -1;
int f_out = -1;
int f_header = -1;
typedef enum
{
IMG_SATA,
IMG_UART,
IMG_FLASH,
IMG_BOOTROM,
IMG_NAND,
IMG_HEX,
IMG_BIN,
IMG_PEX,
IMG_I2C
}IMG_TYPE;
typedef enum
{
HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */
HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */
HDR_ONLY = 3, /* Create only header */
IMG_ONLY = 4, /* Create only image */
}HEADER_MODE;
#define T_OPTION_MASK 0x1 /* image type */
#define D_OPTION_MASK 0x2 /* image destination */
#define E_OPTION_MASK 0x4 /* image execution address */
#define S_OPTION_MASK 0x8 /* image source */
#define R_OPTION_MASK 0x10 /* DRAM file */
#define C_OPTION_MASK 0x20 /* NAND ECC mode */
#define P_OPTION_MASK 0x40 /* NAND Page size */
#define M_OPTION_MASK 0x80 /* TWSI serial init file */
#define W_OPTION_MASK 0x100 /* HEX file width */
#define H_OPTION_MASK 0x200 /* Header mode*/
#define X_OPTION_MASK 0x400 /* Pre padding */
#define Y_OPTION_MASK 0x800 /* Post padding*/
#define I_OPTION_MASK 0x1000 /* SATA PIO mode*/
#define L_OPTION_MASK 0x2000 /* delay time in mseconds*/
#define SATA_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|S_OPTION_MASK)
#define UART_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK)
#define FLASH_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK)
#define PEX_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK)
#define I2C_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|M_OPTION_MASK)
#define MAX_TWSI_HDR_SIZE (60*1024) /* MAX eeprom is 64K & leave 4K for image and header */
#define BOOTROM_MUST_OPT (T_OPTION_MASK)
#define NAND_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|P_OPTION_MASK)
#define HEX_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK)
#define BIN_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK)
/* 32 bit checksum */
u32 checksum32(/*u32*/void* start, u32 len, u32 csum);
u8 checksum8(/*u32*/void* start, u32 len,u8 csum);
u32 crc32(u32 crc, volatile u32 *buf, u32 len);
int main(int argc,char** argv)
{
char *image_type = NULL;
IMG_TYPE img;
unsigned int image_dest=0,image_exec=0,header_size=0, image_source = 0, twsi_size=0;
char *fname_in,*fname_out=NULL,*fname_hdr_out=NULL,*fname_romc=NULL,
*fname_dram=NULL,*fname_twsi=NULL;
char *inst_set;
unsigned char *ptr;
BHR_t hdr;
ExtBHR_t extHdr;
struct stat fs_stat,fs_stat_code;
char *buf_in = NULL ,*buf_code = NULL;
int override[2];
int err,size_written=0;
char *tmpHeader = NULL;
char *tmpTwsi = NULL;
unsigned int opts=0,required_opts = 0;
unsigned int chsum32 = 0;
unsigned int nandPageSize=0, nandEccMode=0, hex_width=0,header_mode = HDR_IMG_ONE_FILE,ms_delay=0;
FILE* f_dram, *f_hex,*f_hex2, *f_hex3, *f_twsi;
int f_code;
unsigned char *hex8=NULL, tmp8;
unsigned short *hex16=NULL, tmp16;
unsigned long *hex32=NULL, tmp32;
unsigned long lastDword = 0;
int i=0;
unsigned int bytesToAlign=0;
char** f_out_names[2];
int pre_padding=0, post_padding=0, padding_size=0;
#define IMG_FILE_INDX 0
#define HDR_FILE_INDX 1
f_out_names[IMG_FILE_INDX] = &fname_out;
f_out_names[HDR_FILE_INDX] = &fname_hdr_out;
memset((void*)&hdr,0,sizeof(BHR_t));
memset((void*)&extHdr,0,sizeof(ExtBHR_t));
if (argc ==1)
{
print_usage();
exit(1);
}
while (--argc > 0 && **++argv == '-')
{
while (*++*argv)
{
switch (**argv)
{
case 'T': /* image type */
if (--argc <= 0) {print_usage();exit(1);}
image_type = *++argv;
if (opts & T_OPTION_MASK) {print_usage();exit(1);}
opts |= T_OPTION_MASK;
break;
case 'D': /* image destination */
if (--argc <= 0) {print_usage();exit(1);}
image_dest = strtoul (*++argv, (char **)&ptr, 16);
if (*ptr) {print_usage();exit(1);}
if (opts & D_OPTION_MASK) {print_usage();exit(1);}
opts |= D_OPTION_MASK;
break;
case 'E': /* image execution */
if (--argc <= 0) {print_usage();exit(1);}
image_exec = strtoul (*++argv, (char **)&ptr, 16);
if (*ptr) {print_usage();exit(1);}
if (opts & E_OPTION_MASK) {print_usage();exit(1);}
opts |= E_OPTION_MASK;
break;
case 'X': /* Pre - Padding */
if (--argc <= 0) {print_usage();exit(1);}
padding_size = strtoul (*++argv, (char **)&ptr, 16);
pre_padding=1;
if (*ptr) {print_usage();exit(1);}
if (opts & X_OPTION_MASK) {print_usage();exit(1);}
opts |= X_OPTION_MASK;
break;
case 'Y': /* Post - Padding */
if (--argc <= 0) {print_usage();exit(1);}
padding_size = strtoul (*++argv, (char **)&ptr, 16);
post_padding=1;
if (*ptr) {print_usage();exit(1);}
if (opts & Y_OPTION_MASK) {print_usage();exit(1);}
opts |= Y_OPTION_MASK;
break;
case 'I': /* PIO */
if (argc <= 0) {print_usage();exit(1);}
if (opts & I_OPTION_MASK) {print_usage();exit(1);}
opts |= I_OPTION_MASK;
break;
case 'S': /* starting sector */
if (--argc <= 0) {print_usage();exit(1);}
image_source = strtoul (*++argv, (char **)&ptr, 16);
if (*ptr) {print_usage();exit(1);}
if (opts & S_OPTION_MASK) {print_usage();exit(1);}
opts |= S_OPTION_MASK;
break;
case 'P': /* NAND Page Size */
if (--argc <= 0) {print_usage();exit(1);}
nandPageSize = strtoul (*++argv, (char **)&ptr, 10);
if (*ptr) {print_usage();exit(1);}
if (opts & P_OPTION_MASK) {print_usage();exit(1);}
opts |= P_OPTION_MASK;
break;
case 'C': /* NAND ECC mode */
if (--argc <= 0) {print_usage();exit(1);}
nandEccMode = strtoul (*++argv, (char **)&ptr, 10);
if (*ptr) {print_usage();exit(1);}
if (opts & C_OPTION_MASK) {print_usage();exit(1);}
opts |= C_OPTION_MASK;
break;
case 'L': /* Delay time */
if (--argc <= 0) {print_usage();exit(1);}
ms_delay = strtoul (*++argv, (char **)&ptr, 10);
if (*ptr) {print_usage();exit(1);}
if (opts & L_OPTION_MASK) {print_usage();exit(1);}
opts |= L_OPTION_MASK;
break;
case 'W': /* HEX file width */
if (--argc <= 0) {print_usage();exit(1);}
hex_width = strtoul (*++argv, (char **)&ptr, 10);
if (*ptr) {print_usage();exit(1);}
if (opts & W_OPTION_MASK) {print_usage();exit(1);}
opts |= W_OPTION_MASK;
break;
case 'H': /* Header file mode */
if (--argc <= 0) {print_usage();exit(1);}
header_mode = strtoul (*++argv, (char **)&ptr, 10);
if (*ptr) {print_usage();exit(1);}
if (opts & H_OPTION_MASK) {print_usage();exit(1);}
opts |= H_OPTION_MASK;
break;
case 'R': /* dram file*/
if (--argc <= 0) {print_usage();exit(1);}
fname_dram = *++argv;
if (opts & R_OPTION_MASK) {print_usage();exit(1);}
opts |= R_OPTION_MASK;
break;
case 'M': /* TWSI serial init file*/
if (--argc <= 0) {print_usage();exit(1);}
fname_twsi = *++argv;
if (opts & M_OPTION_MASK) {print_usage();exit(1);}
opts |= M_OPTION_MASK;
break;
}
}
}
/* 2 sperate images is used with SATA only */
if (header_mode == HDR_IMG_TWO_FILES)
{
if (!(opts & S_OPTION_MASK))
{
fprintf(stderr,"Error: -S option is missing\n\n\n\n\n");
print_usage();exit(1);
}
}
/* verify HEX file width selection to be valid */
if (opts & W_OPTION_MASK)
{
if ((hex_width != 8)&&(hex_width != 16)&&(hex_width != 32)&&(hex_width != 64))
{print_usage();exit(1);}
}
/* get the minimum option set based on boot mode */
if (opts & T_OPTION_MASK)
{
if (strcmp(image_type, "sata") == 0)
{
img=IMG_SATA;
required_opts = SATA_MUST_OPT;
}
else if (strcmp(image_type, "nand") == 0)
{
img=IMG_NAND;
required_opts = NAND_MUST_OPT;
}
else if (strcmp(image_type, "hex") == 0)
{
img=IMG_HEX;
required_opts = HEX_MUST_OPT;
}
else if (strcmp(image_type, "bin") == 0)
{
img=IMG_BIN;
required_opts = BIN_MUST_OPT;
}
else if (strcmp(image_type, "uart") == 0)
{
img=IMG_UART;
required_opts = UART_MUST_OPT;
}
else if (strcmp(image_type, "flash") == 0)
{
img=IMG_FLASH;
required_opts = FLASH_MUST_OPT;
}
else if (strcmp(image_type, "bootrom") == 0)
{
img=IMG_BOOTROM;
required_opts = BOOTROM_MUST_OPT;
}
else if (strcmp(image_type, "pex") == 0)
{
img=IMG_PEX;
required_opts = PEX_MUST_OPT;
}
else if (strcmp(image_type, "i2c") == 0)
{
img=IMG_I2C;
required_opts = I2C_MUST_OPT;
}
else {print_usage();exit(1);}
}
else
{
print_usage();
exit(1);
}
if (header_mode == IMG_ONLY)
{
required_opts &= ~(D_OPTION_MASK|E_OPTION_MASK|S_OPTION_MASK|R_OPTION_MASK|P_OPTION_MASK);
}
if (required_opts != (opts & required_opts)) {print_usage();exit(1);}
hdr.ddrInitDelay = ms_delay;
hdr.destinationAddr = image_dest;
hdr.executionAddr = image_exec;
switch (img)
{
case IMG_BOOTROM:
header_mode = IMG_ONLY;
break;
case IMG_HEX:
header_mode = IMG_ONLY;
break;
case IMG_BIN:
header_mode = IMG_ONLY;
break;
case IMG_SATA:
hdr.blockID = IBR_HDR_SATA_ID;
header_size = 512;
if (image_source) hdr.sourceAddr = image_source;
else hdr.sourceAddr = 2; /* default */
if (!(opts & H_OPTION_MASK))
{
header_mode = HDR_IMG_TWO_FILES/*HDR_ONLY*/;
}
if (opts & I_OPTION_MASK)
{
hdr.sataPioMode = 1;
}
break;
case IMG_UART:
hdr.blockID = IBR_HDR_UART_ID;
if (opts & R_OPTION_MASK)
{
header_size = 512;
} else header_size = 128;
hdr.sourceAddr = header_size;
break;
case IMG_FLASH:
hdr.blockID = IBR_HDR_SPI_ID;
if (opts & R_OPTION_MASK)
{
header_size = 512;
} else header_size = sizeof(BHR_t);
if ((image_source)&&(image_source >= header_size))
{
hdr.sourceAddr = image_source;
}else
{
hdr.sourceAddr = header_size; /* default */
}
break;
case IMG_NAND:
hdr.blockID = IBR_HDR_NAND_ID;
if (opts & R_OPTION_MASK)
{
header_size = 512;
} else header_size = sizeof(BHR_t);
if ((image_source)&&(image_source >= header_size))
{
hdr.sourceAddr = image_source;
}else
{
hdr.sourceAddr = header_size; /* default */
}
hdr.nandPageSize = (MV_U16)nandPageSize;
hdr.nandEccMode = (MV_U8)nandEccMode;
break;
case IMG_PEX:
hdr.blockID = IBR_HDR_PEX_ID;
if (opts & R_OPTION_MASK)
{
header_size = 512;
} else header_size = sizeof(BHR_t);
if ((image_source)&&(image_source >= header_size))
{
hdr.sourceAddr = image_source;
}else
{
hdr.sourceAddr = header_size; /* default */
}
case IMG_I2C:
hdr.blockID = IBR_HDR_I2C_ID;
if (opts & R_OPTION_MASK)
{
header_size = 512;
} else header_size = sizeof(BHR_t);
if ((image_source)&&(image_source >= header_size))
{
hdr.sourceAddr = image_source;
}else
{
hdr.sourceAddr = header_size; /* default */
}
}
if ((header_mode == HDR_IMG_TWO_FILES) || ((header_mode == IMG_ONLY) && (img == IMG_BIN)))
{
if (argc == 4) /* In case ROMC is needed */
{
fname_in = *argv++;
fname_out = *argv++;
fname_hdr_out = *argv++;
fname_romc = *argv++;
if ((0 == strcmp(fname_in, fname_out)) ||
(0 == strcmp(fname_in, fname_hdr_out)) ||
(0 == strcmp(fname_in, fname_romc)) ||
(0 == strcmp(fname_out, fname_hdr_out)) ||
(0 == strcmp(fname_out, fname_romc)) ||
(0 == strcmp(fname_hdr_out, fname_romc)))
{
fprintf(stderr,"Error: Input and output images can't be the same\n");
exit(1);
}
}
else if (argc == 3)
{
fname_in = *argv++;
fname_out = *argv++;
fname_hdr_out = *argv++;
if ((0 == strcmp(fname_in, fname_out))||
(0 == strcmp(fname_in, fname_hdr_out))||
(0 == strcmp(fname_out, fname_hdr_out)))
{
fprintf(stderr,"Error: Input and output images can't be the same\n");
exit(1);
}
}
else
{
print_usage();
exit(1);
}
}
else
{
if (argc == 2)
{
fname_in = *argv++;
fname_out = *argv++;
if (0 == strcmp(fname_in, fname_out))
{
fprintf(stderr,"Error: Input and output images can't be the same\n");
exit(1);
}
}
else
{
print_usage();
exit(1);
}
}
/* check if the output image exist */
i = 0;
do
{
if (*f_out_names[i])
{
f_out = open(*f_out_names[i],O_RDONLY|O_BINARY);
if (f_out != -1)
{
char c;
close(f_out);
f_out = -1;
fprintf(stderr,"File '%s' already exist! override (y/n)?",*f_out_names[i]);
c = getc(stdin);
if ((c == 'N')||(c == 'n'))
{
printf("exit.. nothing done. \n");
exit(0);
}
/* for the Enter */
c = getc(stdin);
override[i] = 1;
}
else
{
override[i] = 0;
}
}
i++;
if (i == 2) break;
}while(1);
if (header_mode != HDR_ONLY)
{
/* open input image */
f_in = open(fname_in,O_RDONLY|O_BINARY);
if (f_in == -1)
{
fprintf(stderr,"File '%s' not found \n",fname_in);
exit(0);
}
/* get the size of the input image */
err = fstat(f_in, &fs_stat);
if (0 != err)
{
close(f_in);
fprintf(stderr,"fstat failed for file: '%s' err=%d\n",fname_in,err);
exit(1);
}
if ((fs_stat.st_size > BOOTROM_SIZE)&&(img == IMG_BOOTROM))
{
printf("ERROR : bootstrap.bin size is bigger than %d bytes \n",BOOTROM_SIZE);
close(f_in);
exit(1);
}
/* map the input image */
buf_in = mmap(0, fs_stat.st_size, PROT_READ, MAP_SHARED, f_in, 0);
if (!buf_in)
{
fprintf(stderr,"Error mapping %s file \n",fname_in);
goto end;
}
}
/* open the output image */
if (override[IMG_FILE_INDX] == 0)
{
f_out = open(fname_out,O_RDWR|O_TRUNC|O_CREAT|O_BINARY,0666);
}
else f_out = open(fname_out,O_RDWR|O_BINARY);
if (f_out == -1)
{
fprintf(stderr,"Error openning %s file \n",fname_out);
}
if (header_mode == HDR_IMG_TWO_FILES)
{
/* open the output header file */
if (override[HDR_FILE_INDX] == 0)
{
f_header = open(fname_hdr_out,O_RDWR|O_TRUNC|O_CREAT|O_BINARY,0666);
}
else f_header = open(fname_hdr_out,O_RDWR|O_BINARY);
if (f_header == -1)
{
fprintf(stderr,"Error openning %s file \n",fname_hdr_out);
}
}
/* Image Header */
if (header_mode != IMG_ONLY)
{
hdr.blockSize = fs_stat.st_size;
if (opts & R_OPTION_MASK)
{
hdr.ext = 1;
}
/* for FLASH\NAND , we have extra word for checksum */
if ((img == IMG_FLASH)||(img == IMG_NAND)||(img == IMG_SATA)||(img == IMG_PEX)||(img == IMG_I2C))
{
/*hdr.blockSize++;*/
hdr.blockSize +=4;
}
/* in sata headers, blocksize is in sectors (512 byte)*/
if (img == IMG_SATA)
{
/*hdr.blockSize = (hdr.blockSize + 511) >> 9;*/
}
/* Update Block size address */
if (padding_size)
{
/* Align padding to 32 bit */
if (padding_size & 0x3)
{
padding_size += (4 - (padding_size & 0x3));
}
hdr.blockSize += padding_size;
}
/* Align size to 4 byte*/
if (hdr.blockSize & 0x3)
{
printf("hdr.blockSize = 0x%x fs_stat.st_size = 0x%x\n", hdr.blockSize, fs_stat.st_size);
bytesToAlign = (4 - (hdr.blockSize & 0x3));
hdr.blockSize += bytesToAlign;
}
tmpTwsi = malloc(MAX_TWSI_HDR_SIZE);
memset(tmpTwsi, 0xFF, MAX_TWSI_HDR_SIZE);
if (opts & M_OPTION_MASK)
{
if (fname_twsi)
{
int i;
unsigned int * twsi_reg = (unsigned int *)tmpTwsi;;
f_twsi = fopen(fname_twsi, "r");
if (f_twsi == NULL)
{
fprintf(stderr,"File '%s' not found \n",fname_twsi);
exit(1);
}
for (i=0; i<(MAX_TWSI_HDR_SIZE/4); i++)
{
if (EOF == fscanf(f_twsi,"%x\n",twsi_reg))
break;
/* Swap Enianess */
*twsi_reg = ( ((*twsi_reg >> 24) & 0xFF) |
((*twsi_reg >> 8) & 0xFF00) |
((*twsi_reg << 8) & 0xFF0000) |
((*twsi_reg << 24) & 0xFF000000) );
twsi_reg++;
}
fclose(f_twsi);
twsi_size = ((((i+2)*4) & ~0x1FF) + 0x200); /*size=512,1024,.. with at least 8 0xFF bytes */
if ((write(f_out, tmpTwsi, twsi_size)) != twsi_size)
{
fprintf(stderr,"Error writing %s file \n",fname_out);
goto end;
}
}
}
tmpHeader = malloc(header_size);
memset(tmpHeader, 0 ,header_size);
hdr.checkSum = checksum8((void*)&hdr, sizeof(BHR_t) ,0);
memcpy(tmpHeader, &hdr, sizeof(BHR_t));
/* Header extension */
if (opts & R_OPTION_MASK)
{
int dram_buf_size=0,code_buf_size=0;
/* First we will take of DRAM */
if (fname_dram)
{
int i;
/*unsigned int dram_reg[DRAM_REGS_NUM];*/
unsigned int dram_reg[(512>>2)];
f_dram = fopen(fname_dram, "r");
if (f_dram == NULL)
{
fprintf(stderr,"File '%s' not found \n",fname_dram);
exit(1);
}
/*for (i=0; i< DRAM_REGS_NUM ; i++)*/
i=0;
while (EOF != fscanf(f_dram,"%x\n",&dram_reg[i++]));
fclose(f_dram);
/*dram_buf_size = DRAM_REGS_NUM * 4;*/
dram_buf_size = (i-1)*4;
memcpy(tmpHeader + sizeof(BHR_t) + sizeof(ExtBHR_t),
dram_reg, dram_buf_size);
extHdr.dramRegsOffs = sizeof(BHR_t) + sizeof(ExtBHR_t);
}
memcpy(tmpHeader + sizeof(BHR_t), &extHdr, sizeof(ExtBHR_t));
*(MV_U8*)(tmpHeader + header_size - 1) = checksum8((u32)(tmpHeader + sizeof(BHR_t)), header_size - sizeof(BHR_t),0);
}
if (header_mode == HDR_IMG_TWO_FILES)
{
/* copy header to output image */
size_written = write(f_header, tmpHeader, header_size);
if (size_written != header_size)
{
fprintf(stderr,"Error writing %s file \n",fname_hdr_out);
goto end;
}
fprintf(stdout, "%s was created \n", *f_out_names[HDR_FILE_INDX]);
}
else
{
/* copy header to output image */
size_written = write(f_out, tmpHeader, header_size);
if (size_written != header_size)
{
fprintf(stderr,"Error writing %s file \n",fname_out);
goto end;
}
}
}
if (header_mode != HDR_ONLY)
{
char *padding = NULL;
int new_file_size = 0;
if (img == IMG_BOOTROM)
{
char *tmp1;
int tmpSize = BOOTROM_SIZE - sizeof(chsum32);
/* PAD image with Zeros until BOOTROM_SIZE*/
tmp1 = malloc(tmpSize);
if (tmp1 == NULL)
goto end;
memcpy(tmp1, buf_in, fs_stat.st_size);
memset(tmp1 + fs_stat.st_size, 0, tmpSize - fs_stat.st_size);
fs_stat.st_size = tmpSize;
/* copy input image to output image */
size_written = write(f_out, tmp1, fs_stat.st_size);
/* calculate checsum */
chsum32 = crc32(0, (u32*)tmp1, (fs_stat.st_size/4));
printf("Image Chacksum (size = %d) = 0x%08x\n", fs_stat.st_size, chsum32);
fs_stat.st_size += sizeof(chsum32) ;
size_written += write(f_out, &chsum32, sizeof(chsum32));
if (tmp1)
free(tmp1);
new_file_size = fs_stat.st_size;
}
else if (img == IMG_HEX)
{
char *tmp1 = NULL;
f_hex = fopen(fname_out, "w");
if (f_hex == NULL) goto end;
int hex_len = fs_stat.st_size;
int hex_unaligned_len = 0;
switch (hex_width)
{
case 8:
hex8 = (unsigned char*)buf_in;
do
{
fprintf(f_hex,"%02X\n",*hex8);
hex8++;
size_written += 1;
hex_len--;
}while(hex_len);
break;
case 16:
hex16 = (unsigned short*)buf_in;
hex_unaligned_len = (fs_stat.st_size & 0x1);
if (hex_unaligned_len)
{
hex_len -= hex_unaligned_len;
hex_len += 2;
tmp1 = malloc(hex_len);
hex16 = (unsigned short*)tmp1;
memset(tmp1, 0, (hex_len));
memcpy(tmp1, buf_in, fs_stat.st_size);
}
do
{
fprintf(f_hex,"%04X\n",*hex16++);
size_written += 2;
hex_len -= 2;
}while(hex_len);
break;
case 32:
hex32 = (long*)buf_in;
hex_unaligned_len = (fs_stat.st_size & 0x3);
if (hex_unaligned_len)
{
hex_len -= hex_unaligned_len;
hex_len += 4;
tmp1 = malloc(hex_len);
hex16 = (unsigned short*)tmp1;
memset(tmp1, 0, (hex_len));
memcpy(tmp1, buf_in, fs_stat.st_size);
}
do
{
fprintf(f_hex,"%08X\n",*hex32++);
size_written += 4;
hex_len -= 4;
}while(hex_len);
break;
case 64:
hex32 = (long*)buf_in;
hex_unaligned_len = (fs_stat.st_size & 0x7);
if (hex_unaligned_len)
{
hex_len -= hex_unaligned_len;
hex_len += 8;
tmp1 = malloc(hex_len);
hex16 = (unsigned short*)tmp1;
memset(tmp1, 0, (hex_len));
memcpy(tmp1, buf_in, fs_stat.st_size);
}
do
{
fprintf(f_hex,"%08X%08X\n",*hex32++, *hex32++);
size_written += 8;
hex_len -= 8;
}while(hex_len);
break;
}
size_written = fs_stat.st_size;
if (tmp1) free(tmp1);
fclose(f_hex);
new_file_size = fs_stat.st_size;
}
else if (img == IMG_BIN)
{
char *tmp1 = NULL;
int one_file_len;
int hex_len = fs_stat.st_size;
f_hex = fopen(fname_out, "w");
if (f_hex == NULL) goto end;
f_hex2 = fopen(fname_hdr_out, "w");
if (f_hex2 == NULL) goto end;
if (fname_romc)
{
f_hex3 = fopen(fname_romc, "w");
if (f_hex3 == NULL) goto end;
one_file_len = (hex_len / 3);
}
else
{
one_file_len = hex_len * 0.5;
}
int hex_unaligned_len = 0;
switch (hex_width)
{
case 8:
hex8 = (unsigned char*)buf_in;
do
{
tmp8 = *hex8;
if (hex_len > one_file_len)
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex,"%d",((tmp8 & 0x80) >> 7));
tmp8 <<= 1;
}
fprintf(f_hex,"\n");
}
else
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex2,"%d",((tmp8 & 0x80) >> 7));
tmp8 <<= 1;
}
fprintf(f_hex2,"\n");
}
hex8++;
size_written += 1;
hex_len--;
}while(hex_len);
break;
case 16:
hex16 = (unsigned short*)buf_in;
hex_unaligned_len = (fs_stat.st_size & 0x1);
if (hex_unaligned_len)
{
hex_len -= hex_unaligned_len;
hex_len += 2;
tmp1 = malloc(hex_len);
hex16 = (unsigned short*)tmp1;
memset(tmp1, 0, (hex_len));
memcpy(tmp1, buf_in, fs_stat.st_size);
}
do
{
tmp16 = *hex16;
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex,"%d",((tmp16 & 0x8000) >> 15));
tmp16 <<= 1;
}
fprintf(f_hex,"\n");
hex16++;
size_written += 2;
hex_len -= 2;
}while(hex_len);
break;
case 32:
hex32 = (long*)buf_in;
hex_unaligned_len = (fs_stat.st_size & 0x3);
if (hex_unaligned_len)
{
hex_len -= hex_unaligned_len;
hex_len += 4;
tmp1 = malloc(hex_len);
hex16 = (unsigned short*)tmp1;
memset(tmp1, 0, (hex_len));
memcpy(tmp1, buf_in, fs_stat.st_size);
}
do
{
tmp32 = *hex32;
if (fname_romc)
{
if (hex_len > (2 * one_file_len))
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex,"%d",((tmp32 & 0x80000000) >> 31));
tmp32 <<= 1;
}
fprintf(f_hex,"\n");
}
else if (hex_len > one_file_len)
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex2,"%d",((tmp32 & 0x80000000) >> 31));
tmp32 <<= 1;
}
fprintf(f_hex2,"\n");
}
else
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex3,"%d",((tmp32 & 0x80000000) >> 31));
tmp32 <<= 1;
}
fprintf(f_hex3,"\n");
}
}
else
{
if (hex_len > one_file_len)
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex,"%d",((tmp32 & 0x80000000) >> 31));
tmp32 <<= 1;
}
fprintf(f_hex,"\n");
}
else
{
for (i=0; i<hex_width ; i++)
{
fprintf(f_hex2,"%d",((tmp32 & 0x80000000) >> 31));
tmp32 <<= 1;
}
fprintf(f_hex2,"\n");
}
}
hex32++;
size_written += 4;
hex_len -= 4;
}while(hex_len);
break;
case 64:
fprintf(stderr,"Error: 64 Bit is not supported for binary files\n\n\n\n\n");
break;
}
size_written = fs_stat.st_size;
if (tmp1) free(tmp1);
fclose(f_hex);
fclose(f_hex2);
new_file_size = fs_stat.st_size;
}
else
{
size_written = 0;
if ((pre_padding)&&(padding_size))
{
padding = malloc(padding_size);
if (padding)
{
new_file_size += padding_size;
memset((void*)padding, 0x5, padding_size);
size_written += write(f_out, padding, padding_size);
chsum32 = checksum32(/*(u32)*/ (void*)padding, padding_size, chsum32);
}
}
new_file_size += fs_stat.st_size;
/* Calculate checksum */
chsum32 = checksum32(/*(u32)*/ (void*)buf_in, (u32)((u32)fs_stat.st_size - bytesToAlign), chsum32);
if (bytesToAlign)
{
memcpy(&lastDword, (buf_in + (fs_stat.st_size - bytesToAlign)) , bytesToAlign);
}
chsum32 = checksum32(/*(u32)*/ (void*)&lastDword, 4,chsum32);
/* copy input image to output image */
size_written += write(f_out, buf_in, fs_stat.st_size);
if (bytesToAlign)
{
size_written += write(f_out, &lastDword, bytesToAlign);
}
if ((post_padding)&&(padding_size))
{
padding = malloc(padding_size);
if (padding)
{
new_file_size += padding_size;
memset((void*)padding, 0xa, padding_size);
size_written += write(f_out, padding, padding_size);
chsum32 = checksum32(/*(u32)*/ (void*)padding, padding_size, chsum32);
}
}
/* write checksum */
size_written += write(f_out, &chsum32, sizeof(chsum32));
new_file_size +=4 ;
}
if (size_written != new_file_size)
{
fprintf(stderr,"Error writing %s file \n",fname_out);
goto end;
}
fprintf(stdout, "%s was created \n", *f_out_names[IMG_FILE_INDX]);
}
end:
if (tmpHeader)
free(tmpHeader);
/* close handles */
if (f_out != -1)
close(f_out);
if (f_header != -1)
close(f_header);
if (buf_in)
munmap((void*)buf_in, fs_stat.st_size);
if (f_in != -1)
close(f_in);
return 0;
}
void print_usage(void)
{
printf("\n");
printf("Marvell doimage Tool version %s\n", DOIMAGE_VERSION);
printf("Supported SoC devices: \n");
printf(" Marvell 88F6082 - A1\n");
printf(" Marvell 88F6180 - A1\n");
printf(" Marvell 88F6280 - A1\n");
printf(" Marvell 88F6192 - A1\n");
printf(" Marvell 88F6190 - A1\n");
printf(" Marvell 88F6281 - A1\n");
printf(" Marvell 88F6282 - A1\n");
printf("\n");
printf("usage: \n");
printf("doimage <must_options> [other_options] image_in image_out [header_out]\n");
printf("\n<must_options> - can be one or more of the following:\n\n");
printf("-T image_type: sata\\uart\\flash\\bootrom\\nand\\hex\\pex\n");
printf(" if image_type is sata, the image_out will\n");
printf(" include header only.\n");
printf("-D image_dest: image destination in dram (in hex)\n");
printf("-E image_exec: execution address in dram (in hex)\n");
printf(" if image_type is 'flash' and image_dest is 0xffffffff\n");
printf(" then execution address on the flash\n");
printf("-S image_source: if image_type is sata then the starting sector of\n");
printf(" the source image on the disk - mandatory for sata\n");
printf(" if image_type is flash\\nand then the starting offset of\n");
printf(" the source image at the flash - optional for flash\\nand\n");
printf("-W hex_width : HEX file width, can be 8,16,32,64 \n");
printf("-M twsi_file: ascii file name that contains the I2C init regs set by h/w.\n");
printf(" this is used in i2c boot only\n");
printf("\n<other_options> - optional and can be one or more of the following:\n\n");
printf("-R dram_file: ascii file name that contains the list of dram regs\n");
printf("-P nand_page_size (decimal 512, 2048, ..): NAND Page size\n");
printf("-C nand_ecc_mode (1=Hamming, 2=RS, 3=None)\n");
printf("-L delay in mili seconds before DRAM init\n");
printf("-I copy image in PIO mode (valid for SATA only)\n");
printf("-X pre_padding_size (hex)\n");
printf("-Y post_padding_size (hex)\n");
printf("-H header_mode: Header mode, can be:\n");
printf(" -H 1 :will create one file (image_out) for header and image\n");
printf(" -H 2 :will create two files, (image_out) for image , (header_out) for header\n");
printf(" -H 3 :will create one file (image_out) for header only \n");
printf(" -H 4 :will create one file (image_out) for image only \n");
printf("\ncommand possibilities: \n\n");
printf("doimage -T hex -W width image_in image_out\n");
printf("doimage -T bootrom image_in image_out\n");
printf("doimage -T sata -S sector -D image_dest -E image_exec\n");
printf(" [other_options] image_in image_out header_out\n\n");
printf("doimage -T flash -D image_dest -E image_exec [-S address]\n");
printf(" [other_options] image_in image_out\n\n");
printf("doimage -T pex -D image_dest -E image_exec \n");
printf(" [other_options] image_in image_out\n\n");
printf("doimage -T nand -D image_dest -E image_exec [-S address] -P page_size\n");
printf(" [other_options] image_in image_out\n\n");
printf("doimage -T uart -D image_dest -E image_exec\n");
printf(" [other_options] image_in image_out\n\n");
printf("doimage -T pex -D image_dest -E image_exec \n");
printf(" [other_options] image_in image_out\n\n");
printf("doimage -T i2c -D image_dest -E image_exec -M twsi_init_file\n");
printf(" [other_options] image_in image_out\n\n");
printf("\n\n\n");
}
/* 8 bit checksum */
u8 checksum8(void* /*u32*/ start, u32 len,u8 csum)
{
register u8 sum = csum;
volatile u8* startp = (volatile u8*)start;
do{
sum += *startp;
startp++;
}while(--len);
return (sum);
}
/* 32 bit checksum */
u32 checksum32(/*u32*/void* start, u32 len, u32 csum)
{
register u32 sum = csum;
volatile u32* startp = (volatile u32*)start;
int currLen = len;
do{
sum += *(u32*)startp;
startp++;
currLen -= 4;
}while(currLen > 0);
return (sum);
}
void make_crc_table(MV_U32 *crc_table)
{
MV_U32 c;
MV_32 n, k;
MV_U32 poly;
/* terms of polynomial defining this crc (except x^32): */
static const MV_U8 p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* make exclusive-or pattern from polynomial (0xedb88320L) */
poly = 0L;
for (n = 0; n < sizeof(p)/sizeof(MV_U8); n++)
poly |= 1L << (31 - p[n]);
for (n = 0; n < 256; n++)
{
c = (MV_U32)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[n] = c;
}
}
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf) DO1(buf); DO1(buf);
#define DO4(buf) DO2(buf); DO2(buf);
#define DO8(buf) DO4(buf); DO4(buf);
MV_U32 crc32(MV_U32 crc, volatile MV_U32 *buf, MV_U32 len)
{
MV_U32 crc_table[256];
/* Create the CRC table */
make_crc_table(crc_table);
crc = crc ^ 0xffffffffL;
while (len >= 8)
{
DO8(buf);
len -= 8;
}
if (len) do
{
DO1(buf);
} while (--len);
return crc ^ 0xffffffffL;
}