coreboot-libre-fam15h-rdimm/3rdparty/chromeec/util/ecst.c

2520 lines
68 KiB
C
Raw Normal View History

2024-03-04 11:14:53 +01:00
/*
* Copyright 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This utility is used to generate/modify the firmware header which holds
* data used by NPCX ROM code (booter).
*/
#include "ecst.h"
/* Global Variables */
enum verbose_level g_verbose;
char input_file_name[NAME_SIZE];
char output_file_name[NAME_SIZE];
char arg_file_name[NAME_SIZE];
char g_hdr_input_name[NAME_SIZE];
char hdr_args[MAX_ARGS][ARG_SIZE];
char tmp_hdr_args[MAX_ARGS][ARG_SIZE];
FILE *input_file_pointer;
FILE *g_hfd_pointer;
FILE *arg_file_pointer;
FILE *api_file_pointer;
FILE *g_hdr_pointer;
void *gh_console;
unsigned short g_text_atrib;
unsigned short g_bg_atrib;
enum calc_type g_calc_type;
unsigned int ptr_fw_addr;
unsigned int fw_offset;
int is_ptr_merge;
unsigned int g_ram_start_address;
unsigned int g_ram_size;
int api_file_size_bytes;
int is_mrider15 = FALSE;
/* Chips information, RAM start address and RAM size. */
struct chip_info chip_info[] = {{NPCX5M5G_RAM_ADDR, NPCX5M5G_RAM_SIZE},
{NPCX5M6G_RAM_ADDR, NPCX5M6G_RAM_SIZE},
{NPCX7M5X_RAM_ADDR, NPCX7M5X_RAM_SIZE},
{NPCX7M6X_RAM_ADDR, NPCX7M6X_RAM_SIZE},
{NPCX7M7X_RAM_ADDR, NPCX7M7X_RAM_SIZE},};
/* Support chips name strings */
const char *supported_chips = "npcx5m5g, npcx5m6g, npcx7m5g, npcx7m6g, "
"npcx7m6f, npcx7m6fb, npcx7m6fc, npcx7m7wb, or npcx7m7wc";
static unsigned int calc_api_csum_bin(void);
static unsigned int initialize_crc_32(void);
static unsigned int update_crc_32(unsigned int crc, char c);
static unsigned int finalize_crc_32(unsigned int crc);
/*
* Expects a path in `path`, returning a transformation as follows in `result`
*
* The last element of `path` is prefixed with `prefix` if the resulting
* string fits in an array of `resultsz` characters (incl 0-termination).
*
* On success returns TRUE,
* on error (path too long) prints an error on the TERR channel
* and returns FALSE.
*/
static int splice_into_path(char *result, const char *path, int resultsz,
const char *prefix) {
char *last_delim, *result_last_delim;
if (strlen(path) + strlen(prefix) + 1 > resultsz) {
my_printf(TERR,
"\n\nfilename '%s' with prefix '%s' too long\n\n",
path, prefix);
my_printf(TINF,
"\n\n%zu + %zu + 1 needs to fit in %d bytes\n\n",
strlen(path), strlen(prefix), resultsz);
return FALSE;
}
last_delim = strrchr(path, '/');
if (last_delim == NULL) {
/* no delimiter: prefix and exit */
sprintf(result, "%s%s", prefix, path);
return TRUE;
}
/* delimiter: copy, then patch in the prefix */
strcpy(result, path);
result_last_delim = result + (last_delim - path);
sprintf(result_last_delim + 1, "%s%s", prefix, last_delim + 1);
return TRUE;
}
/*
*----------------------------------------------------------------------
* Function: main()
* Parameters: argc, argv
* Return: 0
* Description: Parse the arguments
* Chose manipulation routine according to arguments
*
* In case of bin, save optional parameters given by user
*----------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
int mode_choose = FALSE;
/* Do we get a bin File? */
int main_fw_hdr_flag = FALSE;
/* Do we get a API bin File? */
int main_api_flag = FALSE;
/* Do we need to create a BootLoader Header file? */
int main_hdr_flag = FALSE;
/* Following variables: common to all modes */
int main_status = TRUE;
unsigned int main_temp = 0L;
char main_str_temp[TMP_STR_SIZE];
char *end_ptr;
int arg_num;
int arg_ind;
int tmp_ind;
int tmp_arg_num;
int cur_arg_index;
FILE *tmp_file;
/* Following variables are used when bin file is provided */
struct tbinparams bin_params;
bin_params.bin_params = 0;
input_file_name[0] = '\0';
memset(input_file_name, 0, NAME_SIZE);
output_file_name[0] = '\0';
memset(output_file_name, 0, NAME_SIZE);
arg_file_name[0] = '\0';
memset(arg_file_name, 0, NAME_SIZE);
g_hdr_input_name[0] = '\0';
memset(g_hdr_input_name, 0, NAME_SIZE);
/* Initialize Global variables */
g_verbose = NO_VERBOSE;
g_ram_start_address = chip_info[DEFAULT_CHIP].ram_addr;
g_ram_size = chip_info[DEFAULT_CHIP].ram_size;
/* Set default values */
g_calc_type = CALC_TYPE_NONE;
bin_params.spi_max_clk = SPI_MAX_CLOCK_DEFAULT;
bin_params.spi_clk_ratio = 0x00;
bin_params.spi_read_mode = SPI_READ_MODE_DEFAULT;
bin_params.fw_load_addr =
chip_info[DEFAULT_CHIP].ram_addr;
bin_params.fw_ep =
chip_info[DEFAULT_CHIP].ram_addr;
bin_params.fw_err_detec_s_addr = FW_CRC_START_ADDR;
bin_params.fw_err_detec_e_addr = FW_CRC_START_ADDR;
bin_params.flash_size = FLASH_SIZE_DEFAULT;
bin_params.fw_hdr_offset = 0;
ptr_fw_addr = 0x00000000;
fw_offset = 0x00000000;
is_ptr_merge = FALSE;
/* Get Standard Output Handler */
/* Wrong Number of Arguments ? No problem */
if (argc < 3)
exit_with_usage();
/* Read all arguments to local array. */
for (arg_num = 0; arg_num < argc; arg_num++)
strncpy(hdr_args[arg_num], argv[arg_num], ARG_SIZE);
/* Loop all arguments. */
/* Parse the Arguments - supports ecrp and bin */
for (arg_ind = 1; arg_ind < arg_num; arg_ind++) {
/* -h display help screen */
if (str_cmp_no_case(hdr_args[arg_ind], "-h") == 0)
exit_with_usage();
/* -v verbose */
else if (str_cmp_no_case(hdr_args[arg_ind], "-v") == 0)
g_verbose = REGULAR_VERBOSE;
/* Super verbose. */
else if (str_cmp_no_case(hdr_args[arg_ind], "-vv") == 0)
g_verbose = SUPER_VERBOSE;
else if (str_cmp_no_case(hdr_args[arg_ind],
"-mode") == 0) {
mode_choose = TRUE;
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%s", main_str_temp) != 1)) {
my_printf(TERR, "\nCannot read operation mode");
my_printf(TERR, ", bt, bh or api. !\n");
main_status = FALSE;
} else {
/* bt, bh and api should not coexist */
if (main_fw_hdr_flag ||
main_api_flag ||
main_hdr_flag) {
my_printf(TERR, "\nOperation modes bt");
my_printf(TERR, ", bh, and api should");
my_printf(TERR, " not coexist.\n");
main_status = FALSE;
}
if (str_cmp_no_case(main_str_temp, "bt") == 0)
main_fw_hdr_flag = TRUE;
else if (str_cmp_no_case(main_str_temp,
"bh") == 0)
main_hdr_flag = TRUE;
else if (str_cmp_no_case(main_str_temp,
"api") == 0)
main_api_flag = TRUE;
else {
my_printf(TERR,
"\nInvalid operation mode ");
my_printf(TERR,
"(%s)\n", main_str_temp);
main_status = FALSE;
}
}
}
else if (str_cmp_no_case(hdr_args[arg_ind], "-chip") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%s",
main_str_temp) != 1)) {
my_printf(TERR, "\nCannot read chip name %s.\n",
supported_chips);
main_status = FALSE;
} else {
if ((str_cmp_no_case(main_str_temp,
"npcx7m7wb") == 0) ||
(str_cmp_no_case(main_str_temp,
"npcx7m7wc") == 0)) {
if ((bin_params.bin_params
& BIN_FW_LOAD_START_ADDR) ==
0x00000000)
bin_params.fw_load_addr =
chip_info[NPCX7M7].ram_addr;
if ((bin_params.bin_params
& BIN_FW_ENTRY_POINT) ==
0x00000000)
bin_params.fw_ep =
chip_info[NPCX7M7].ram_addr;
g_ram_start_address =
chip_info[NPCX7M7].ram_addr;
g_ram_size =
chip_info[NPCX7M7].ram_size;
} else if ((str_cmp_no_case(main_str_temp,
"npcx7m6f") == 0) ||
(str_cmp_no_case(main_str_temp,
"npcx7m6fb") == 0) ||
(str_cmp_no_case(main_str_temp,
"npcx7m6fc") == 0) ||
(str_cmp_no_case(main_str_temp,
"npcx7m6g") == 0)) {
if ((bin_params.bin_params
& BIN_FW_LOAD_START_ADDR) ==
0x00000000)
bin_params.fw_load_addr =
chip_info[NPCX7M6].ram_addr;
if ((bin_params.bin_params &
BIN_FW_ENTRY_POINT) ==
0x00000000)
bin_params.fw_ep =
chip_info[NPCX7M6].ram_addr;
g_ram_start_address =
chip_info[NPCX7M6].ram_addr;
g_ram_size =
chip_info[NPCX7M6].ram_size;
} else if (str_cmp_no_case(main_str_temp,
"npcx7m5g") == 0) {
if ((bin_params.bin_params
& BIN_FW_LOAD_START_ADDR) ==
0x00000000)
bin_params.fw_load_addr =
chip_info[NPCX7M5].ram_addr;
if ((bin_params.bin_params &
BIN_FW_ENTRY_POINT) ==
0x00000000)
bin_params.fw_ep =
chip_info[NPCX7M5].ram_addr;
g_ram_start_address =
chip_info[NPCX7M5].ram_addr;
g_ram_size =
chip_info[NPCX7M5].ram_size;
} else if (str_cmp_no_case(main_str_temp,
"npcx5m5g") == 0) {
if ((bin_params.bin_params
& BIN_FW_LOAD_START_ADDR) ==
0x00000000)
bin_params.fw_load_addr =
chip_info[NPCX5M5G].ram_addr;
if ((bin_params.bin_params &
BIN_FW_ENTRY_POINT) == 0x00000000)
bin_params.fw_ep =
chip_info[NPCX5M5G].ram_addr;
g_ram_start_address =
chip_info[NPCX5M5G].ram_addr;
g_ram_size =
chip_info[NPCX5M5G].ram_size;
is_mrider15 = TRUE;
} else if (str_cmp_no_case(main_str_temp,
"npcx5m6g") == 0) {
if ((bin_params.bin_params &
BIN_FW_LOAD_START_ADDR) ==
0x00000000)
bin_params.fw_load_addr =
chip_info[NPCX5M6G].ram_addr;
if ((bin_params.bin_params &
BIN_FW_ENTRY_POINT) ==
0x00000000)
bin_params.fw_ep =
chip_info[NPCX5M6G].ram_addr;
g_ram_start_address =
chip_info[NPCX5M6G].ram_addr;
g_ram_size =
chip_info[NPCX5M6G].ram_size;
is_mrider15 = TRUE;
} else {
my_printf(TERR,
"\nInvalid chip name (%s) ",
main_str_temp);
my_printf(TERR, ", it should be %s.\n",
supported_chips);
main_status = FALSE;
}
}
/* -argfile Read argument file. File name must be after it.*/
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-argfile") == 0) {
arg_ind++;
if (arg_ind < arg_num) {
strncpy(arg_file_name,
hdr_args[arg_ind],
sizeof(arg_file_name) - 1);
arg_file_pointer = fopen(arg_file_name, "rt");
if (arg_file_pointer == NULL) {
my_printf(TERR,
"\n\nCannot open %s\n\n",
arg_file_name);
main_status = FALSE;
} else {
cur_arg_index = arg_ind;
/* Copy the arguments to temp array. */
for (tmp_ind = 0;
(tmp_ind + arg_ind + 1) < arg_num;
tmp_ind++)
strncpy(tmp_hdr_args[tmp_ind],
hdr_args
[tmp_ind+arg_ind+1],
ARG_SIZE);
tmp_arg_num = tmp_ind;
/* Read arguments from file to array */
for (arg_ind++;
fscanf(arg_file_pointer,
"%s",
hdr_args[arg_ind]) == 1;
arg_ind++)
;
fclose(arg_file_pointer);
arg_file_pointer = NULL;
/* Copy back the restored arguments. */
for (tmp_ind = 0;
tmp_ind < tmp_arg_num;
tmp_ind++) {
strncpy(hdr_args[arg_ind++],
tmp_hdr_args[tmp_ind],
ARG_SIZE);
}
arg_num = arg_ind;
arg_ind = cur_arg_index;
}
} else {
my_printf(TERR,
"\nMissing Argument File Name\n");
main_status = FALSE;
}
/* -i get input file name. */
} else if (str_cmp_no_case(hdr_args[arg_ind], "-i") == 0) {
arg_ind++;
if (arg_ind < arg_num) {
strncpy(input_file_name,
hdr_args[arg_ind],
sizeof(input_file_name) - 1);
} else {
my_printf(TERR, "\nMissing Input File Name\n");
main_status = FALSE;
}
/* -o Get output file name. */
} else if (str_cmp_no_case(hdr_args[arg_ind], "-o") == 0) {
arg_ind++;
if (arg_ind < arg_num) {
strncpy(output_file_name,
hdr_args[arg_ind],
sizeof(output_file_name) - 1);
} else {
my_printf(TERR,
"\nMissing Output File Name.\n");
main_status = FALSE;
}
/* -usearmrst get FW entry point from FW image offset 4.*/
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-usearmrst") == 0) {
if ((bin_params.bin_params &
BIN_FW_ENTRY_POINT) != 0x00000000) {
my_printf(TERR, "\n-usearmrst not allowed, ");
my_printf(TERR, "FW entry point already set ");
my_printf(TERR, "using -fwep !\n");
main_status = FALSE;
} else
bin_params.bin_params |=
BIN_FW_USER_ARM_RESET;
/* -nohcrs disable header CRC*/
} else if (str_cmp_no_case(hdr_args[arg_ind], "-nohcrc") == 0)
bin_params.bin_params |=
BIN_FW_HDR_CRC_DISABLE;
/* -ph merg header in BIN file. */
else if (str_cmp_no_case(hdr_args[arg_ind], "-ph") == 0) {
bin_params.bin_params |=
BIN_FW_HDR_OFFSET;
if ((strlen(hdr_args[arg_ind+1]) == 0) ||
(sscanf(hdr_args[arg_ind+1],
"%x",
&main_temp) != 1))
bin_params.fw_hdr_offset = 0;
else {
arg_ind++;
bin_params.fw_hdr_offset = main_temp;
}
/* -spimaxclk Get SPI flash max clock. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-spimaxclk") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%d", &main_temp) != 1)) {
my_printf(TERR, "\nCannot read SPI Flash Max");
my_printf(TERR, " Clock !\n");
main_status = FALSE;
} else
bin_params.spi_max_clk =
(unsigned char) main_temp;
/* -spiclkratio Get SPI flash max clock ratio. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-spiclkratio") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%d", &main_temp) != 1)) {
my_printf(TERR,
"\nCannot read SPI Clock Ratio\n");
main_status = FALSE;
} else
bin_params.spi_clk_ratio =
(unsigned char)main_temp;
/* spireadmode get SPI read mode. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-spireadmode") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%20s",
main_str_temp) != 1)) {
my_printf(TERR, "\nCannot read SPI Flash");
my_printf(TERR, " Read Mode !\n");
main_status = FALSE;
} else {
if (str_cmp_no_case(main_str_temp,
SPI_NORMAL_MODE_VAL) == 0)
bin_params.spi_read_mode =
(unsigned char) SPI_NORMAL_MODE;
else if (str_cmp_no_case(main_str_temp,
SPI_SINGLE_MODE_VAL) == 0)
bin_params.spi_read_mode =
(unsigned char)
SPI_SINGLE_MODE;
else if (str_cmp_no_case(main_str_temp,
SPI_DUAL_MODE_VAL) == 0)
bin_params.spi_read_mode =
(unsigned char)
SPI_DUAL_MODE;
else if (str_cmp_no_case(main_str_temp,
SPI_QUAD_MODE_VAL) == 0)
bin_params.spi_read_mode =
(unsigned char)
SPI_QUAD_MODE;
else {
my_printf(TERR,
"\nInvalid SPI Flash Read ");
my_printf(TERR,
"Mode (%s), it should be ",
main_str_temp);
my_printf(TERR,
"normal, singleMode, ");
my_printf(TERR,
"dualMode or quadMode !\n");
main_status = FALSE;
}
}
}
/* -unlimburst enable unlimited burst */
else if (str_cmp_no_case(hdr_args[arg_ind], "-unlimburst") == 0)
bin_params.bin_params |= BIN_UNLIM_BURST_ENABLE;
/* -nofcrc disable FW CRC. */
else if (str_cmp_no_case(hdr_args[arg_ind], "-nofcrc") == 0)
bin_params.bin_params |= BIN_FW_CRC_DISABLE;
/* -fwloadaddr, Get the FW load address. */
else if (str_cmp_no_case(hdr_args[arg_ind],
"-fwloadaddr") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%x",
&main_temp) != 1)) {
my_printf(TERR, "\nCannot read FW Load ");
my_printf(TERR, "\nstart address !\n");
main_status = FALSE;
} else {
/* Check that the address is 16-bytes aligned */
if ((main_temp &
ADDR_16_BYTES_ALIGNED_MASK) != 0) {
my_printf(TERR,
"\nFW load address start ");
my_printf(TERR,
"address (0x%08X) is not ",
main_temp);
my_printf(TERR,
"16-bytes aligned !\n");
main_status = FALSE;
} else {
bin_params.fw_load_addr =
main_temp;
bin_params.bin_params |=
BIN_FW_LOAD_START_ADDR;
}
}
/* -fwep, Get the FW entry point. */
} else if (str_cmp_no_case(hdr_args[arg_ind], "-fwep") == 0) {
if ((bin_params.bin_params & BIN_FW_USER_ARM_RESET)
!= 0x00000000) {
my_printf(TERR,
"\n-fwep not allowed, FW entry point");
my_printf(TERR,
" already set using -usearmrst!\n");
main_status = FALSE;
} else {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%x",
&main_temp) != 1)) {
my_printf(TERR,
"\nCan't read FW E-Point\n");
main_status = FALSE;
} else {
bin_params.fw_ep =
main_temp;
bin_params.bin_params |=
BIN_FW_ENTRY_POINT;
}
}
/*
* -crcstart, Get the address from where to calculate
* the FW CRC.
*/
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-crcstart") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%x",
&main_temp) != 1)) {
my_printf(TERR,
"\nCannot read FW CRC");
my_printf(TERR,
" start address !\n");
main_status = FALSE;
} else {
bin_params.fw_err_detec_e_addr =
bin_params.fw_err_detec_e_addr -
bin_params.fw_err_detec_s_addr
+ main_temp;
bin_params.fw_err_detec_s_addr =
main_temp;
bin_params.bin_params |= BIN_FW_CKS_START;
}
/* -crcsize, Get the area size that need to be CRCed. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-crcsize") == 0) {
arg_ind++;
main_temp = 0x00;
if (hdr_args[arg_ind] == NULL)
end_ptr = NULL;
else
main_temp = strtol(hdr_args[arg_ind],
&end_ptr, 16);
if (hdr_args[arg_ind] == end_ptr) {
my_printf(TERR,
"\nCannot read FW CRC area size !\n");
main_status = FALSE;
} else {
bin_params.fw_err_detec_e_addr =
bin_params.fw_err_detec_s_addr
+ main_temp - 1;
bin_params.bin_params |= BIN_FW_CKS_SIZE;
}
}
/* -fwlen, Get the FW length. */
else if (str_cmp_no_case(hdr_args[arg_ind], "-fwlen") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%x",
&main_temp) != 1)) {
my_printf(TERR, "\nCannot read FW length !\n");
main_status = FALSE;
} else {
bin_params.fw_len = main_temp;
bin_params.bin_params |= BIN_FW_LENGTH;
}
}
/* flashsize, Get the flash size. */
else if (str_cmp_no_case(hdr_args[arg_ind],
"-flashsize") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%d",
&main_temp) != 1)) {
my_printf(TERR, "\nCannot read Flash size !\n");
main_status = FALSE;
} else
bin_params.flash_size = main_temp;
/* -apisign, Get the method for error detect calculation. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-apisign") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%s",
main_str_temp) != 1)) {
my_printf(TERR, "\nCannot read API sign, CRC,");
my_printf(TERR, " CheckSum or None. !\n");
main_status = FALSE;
} else {
if (!main_api_flag) {
my_printf(TERR, "\n-apisign is valid ");
my_printf(TERR, "-only with -api.\n");
main_status = FALSE;
}
if (str_cmp_no_case(main_str_temp, "crc") == 0)
g_calc_type = CALC_TYPE_CRC;
else if (str_cmp_no_case(main_str_temp,
"checksum") == 0)
g_calc_type = CALC_TYPE_CHECKSUM;
else {
my_printf(TERR,
"\nInvalid API sign (%s)\n",
main_str_temp);
main_status = FALSE;
}
}
/* -pointer, Get the FW image address. */
} else if (str_cmp_no_case(hdr_args[arg_ind],
"-pointer") == 0) {
arg_ind++;
if ((hdr_args[arg_ind] == NULL) ||
(sscanf(hdr_args[arg_ind],
"%x",
&main_temp) != 1)) {
my_printf(TERR,
"\nCannot read FW Image address !\n");
main_status = FALSE;
} else {
/* Check that the address is 16-bytes aligned */
if ((main_temp & ADDR_16_BYTES_ALIGNED_MASK)
!= 0) {
my_printf(TERR,
"\nFW Image address (0x%08X)"
" isn't 16-bytes aligned !\n",
main_temp);
main_status = FALSE;
}
if (main_temp > MAX_FLASH_SIZE) {
my_printf(TERR,
"\nPointer address (0x%08X) ",
main_temp);
my_printf(TERR,
"is higher from flash size");
my_printf(TERR,
" (0x%08X) !\n",
MAX_FLASH_SIZE);
main_status = FALSE;
} else {
ptr_fw_addr = main_temp;
is_ptr_merge = FALSE;
}
}
}
/* -bhoffset, BootLoader Header Offset (BH location in BT). */
else if (str_cmp_no_case(hdr_args[arg_ind], "-bhoffset") == 0) {
arg_ind++;
main_temp = 0x00;
if (hdr_args[arg_ind] == NULL)
end_ptr = NULL;
else
main_temp = strtol(hdr_args[arg_ind],
&end_ptr, 16);
if (hdr_args[arg_ind] == end_ptr) {
my_printf(TERR, "\nCannot read BootLoader");
my_printf(TERR, " Header Offset !\n");
main_status = FALSE;
} else {
/* Check that the address is 16-bytes aligned */
if ((main_temp & ADDR_16_BYTES_ALIGNED_MASK)
!= 0) {
my_printf(TERR,
"\nFW Image address (0x%08X) ",
main_temp);
my_printf(TERR,
"is not 16-bytes aligned!\n");
}
if (main_temp > MAX_FLASH_SIZE) {
my_printf(TERR,
"\nFW Image address (0x%08X)",
main_temp);
my_printf(TERR,
" is higher from flash size");
my_printf(TERR,
" (0x%08X) !\n",
MAX_FLASH_SIZE);
main_status = FALSE;
} else {
fw_offset = main_temp;
is_ptr_merge = TRUE;
}
}
} else {
my_printf(TERR,
"\nUnknown flag: %s\n",
hdr_args[arg_ind]);
main_status = FALSE;
}
}
/*
* If the input and output file have the same name then exit with error.
*/
if (strcmp(output_file_name, input_file_name) == 0) {
my_printf(TINF,
"Input file name (%s) should be differed from\n",
input_file_name);
my_printf(TINF, "Output file name (%s).\n", output_file_name);
main_status = FALSE;
}
/* No problems reading argv? So go on... */
if (main_status) {
/* if output file already exist, then delete it. */
tmp_file = fopen(output_file_name, "w");
if (tmp_file != NULL)
fclose(tmp_file);
/* If no mode choose than "bt" is the default mode.*/
if (mode_choose == FALSE)
main_fw_hdr_flag = TRUE;
/* Chose manipulation routine according to arguments */
if (main_fw_hdr_flag)
main_status = main_bin(bin_params);
else if (main_api_flag)
main_status = main_api();
else if (main_hdr_flag)
main_status = main_hdr();
else
exit_with_usage();
}
/* Be sure there's no open file before you leave */
if (input_file_pointer)
fclose(input_file_pointer);
if (g_hfd_pointer)
fclose(g_hfd_pointer);
if (api_file_pointer)
fclose(api_file_pointer);
/* Delete temprary header file. */
remove(g_hdr_input_name);
/* Say Bye Bye */
if (main_status) {
my_printf(TPAS, "\n\n******************************");
my_printf(TPAS, "\n*** SUCCESS ***");
my_printf(TPAS, "\n******************************\n");
exit(EXIT_SUCCESS);
} else {
my_printf(TERR, "\n\n******************************");
my_printf(TERR, "\n*** FAILED ***");
my_printf(TERR, "\n******************************\n");
exit(EXIT_FAILURE);
}
}
/*
*-----------------------------------------------------------------------
* Function: exit_with_usage()
* Parameters: none
* Return: none
* Description: No Words...
*-----------------------------------------------------------------------
*/
void exit_with_usage(void)
{
my_printf(TUSG,
"\nECST, Embedded Controller Sign Tool, version %d.%d.%d",
T_VER, T_REV_MAJOR, T_REV_MINOR);
my_printf(TUSG, "\n");
my_printf(TUSG, "\nUsage:");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\n ECST -mode <bt|bh|api> -i <filename> [Flags]");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\nOperation Modes: ");
my_printf(TUSG, "\n bt - BootLoader Table");
my_printf(TUSG, "\n bh - BootLoader Header");
my_printf(TUSG, "\n api - Download from Flash API");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\nCommon flags:");
my_printf(TUSG, "\n -mode <type> - Operation mode: ");
my_printf(TUSG, "bt|bh|api (default is bt)");
my_printf(TUSG, "\n -i <filename> - Input file name; ");
my_printf(TUSG, "must differ from the output file name");
my_printf(TUSG, "\n -o <filename> - Output file name ");
my_printf(TUSG, "(default is out_<input_filename>.bin)");
my_printf(TUSG, "\n -argfile <filename> - Arguments file name; ");
my_printf(TUSG, "includes multiple flags");
my_printf(TUSG, "\n -chip <name> - Supported EC Chip Name: ");
my_printf(TUSG, "%s. ", supported_chips);
my_printf(TUSG, "(default is npcx5m5g)");
my_printf(TUSG, "\n -v - Verbose; prints ");
my_printf(TUSG, "information messages");
my_printf(TUSG, "\n -vv - Super Verbose; prints ");
my_printf(TUSG, "intermediate calculations");
my_printf(TUSG, "\n -h - Show this help screen");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\nBootLoader Table mode flags:");
my_printf(TUSG, "\n -nohcrc - Disable CRC on header ");
my_printf(TUSG, "(default is ON)");
my_printf(TUSG, "\n -nofcrc - Disable CRC on firmware ");
my_printf(TUSG, "(default is ON)");
my_printf(TUSG, "\n -spimaxclk <val> - SPI Flash Maximum Clock, in");
my_printf(TUSG, " MHz: 20|25|33|40|50 (default is 20)");
my_printf(TUSG, "\n -spiclkratio <val> - Core Clock / SPI Flash ");
my_printf(TUSG, "Clocks Ratio: 1 | 2 (default is 1)");
my_printf(TUSG, "\n ");
my_printf(TUSG, "Note: Not relevant for npcx5mng chips family");
my_printf(TUSG, "\n -spireadmode <type> - SPI Flash Read Mode: ");
my_printf(TUSG, "normal|fast|dual|quad (default is normal)");
my_printf(TUSG, "\n -unlimburst - Enable FIU Unlimited ");
my_printf(TUSG, "\n ");
my_printf(TUSG, "Note: Not relevant for npcx5mng chips family");
my_printf(TUSG, "Burst for SPI Flash Accesses (default is disable).");
my_printf(TUSG, "\n -fwloadaddr <addr> - Firmware load start ");
my_printf(TUSG, "address (default is Start-of-RAM)");
my_printf(TUSG, "\n Located in code RAM, ");
my_printf(TUSG, "16-bytes aligned, hex format");
my_printf(TUSG, "\n -usearmrst - Use the ARM reset table ");
my_printf(TUSG, "entry as the Firmware Entry Point");
my_printf(TUSG, "\n Can't be used with -fwep");
my_printf(TUSG, "\n -fwep <addr> - Firmware entry ");
my_printf(TUSG, "point (default is Firmware Entry Point)");
my_printf(TUSG, "\n Located in firmware area,");
my_printf(TUSG, " hex format");
my_printf(TUSG, "\n -crcstart <offset> - Firmware CRC start offset ");
my_printf(TUSG, "(default is 00000000)");
my_printf(TUSG, "\n Offset from firmware image,");
my_printf(TUSG, " 4B-aligned, for partial CRC, hex format");
my_printf(TUSG, "\n -crcsize <val> - Firmware CRC size ");
my_printf(TUSG, "(default is entire firmware size)");
my_printf(TUSG, "\n 4B-aligned, for partial ");
my_printf(TUSG, "CRC, hex format");
my_printf(TUSG, "\n -fwlen <val> - Firmware length, ");
my_printf(TUSG, "16B-aligned, hex format (default is file size).");
my_printf(TUSG, "\n -flashsize <val> - Flash size, in MB: ");
my_printf(TUSG, "1|2|4|8|16 (default is 16)");
my_printf(TUSG, "\n -ph <offset> - Paste the Firmware ");
my_printf(TUSG, "Header in the input file copy at the selected");
my_printf(TUSG, "\n offset ");
my_printf(TUSG, "(default is 00000000), hex format.");
my_printf(TUSG, "\n The firmware itself is ");
my_printf(TUSG, "expected to start at offset + 64 bytes.");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\nBootLoader Header mode flags:");
my_printf(TUSG, "\n -pointer <offset> - BootLoader Table location");
my_printf(TUSG, " in the flash, hex format");
my_printf(TUSG, "\n -bhoffset <offset> - BootLoader Header Offset");
my_printf(TUSG, " in file, hex format (BH location in BT)");
my_printf(TUSG, "\n ");
my_printf(TUSG, "\nAPI mode flags:");
my_printf(TUSG, "\n -apisign <type> - Signature type: ");
my_printf(TUSG, "crc|checksum (default is OFF)");
my_printf(TUSG, "\n\n");
exit(EXIT_FAILURE);
}
/*
*--------------------------------------------------------------------------
* Function: copy_file_to_file()
* Parameters: dst_file_name - Destination file name.
* src_file_name - Source file name.
* offset - number of bytes from the origin.
* origin - From where to seek, START, END, or CURRENT of
* file.
* Return: Number of copied bytes
* Description: Copy the source file to the end of the destination file.
*--------------------------------------------------------------------------
*/
int copy_file_to_file(char *dst_file_name,
char *src_file_name,
int offset,
int origin)
{
int index = 0;
int result = 0;
unsigned char local_val;
int src_file_size;
FILE *dst_file;
FILE *src_file;
/* Open the destination file for append. */
dst_file = fopen(dst_file_name, "r+b");
if (dst_file == NULL) {
/* destination file not exist, create it. */
dst_file = fopen(dst_file_name, "ab");
if (dst_file == NULL)
return 0;
}
/* Open the source file for read. */
src_file = fopen(src_file_name, "rb");
if (src_file == NULL) {
fclose(dst_file);
return 0;
}
/* Get the source file length in bytes. */
src_file_size = get_file_length(src_file);
/* Point to the end of the destination file, and to the start */
/* of the source file. */
if (fseek(dst_file, offset, origin) < 0)
goto out;
if (fseek(src_file, 0, SEEK_SET) < 0)
goto out;
/* Loop over all destination file and write it to the source file.*/
for (index = 0; index < src_file_size; index++) {
/* Read byte from source file. */
result = (int)(fread(&local_val, 1, 1, src_file));
/* If byte reading pass than write it to the destination, */
/* else exit from the reading loop. */
if (result) {
/* Read pass, so write it to destination file.*/
result = fwrite(&local_val, 1, 1, dst_file);
if (!result)
/*
* Write failed,
* return with the copied bytes number.
*/
break;
} else
/* Read failed, return with the copied bytes number. */
break;
}
out:
/* Close the files. */
fclose(dst_file);
fclose(src_file);
/* Copy ended, return with the number of bytes that were copied. */
return index;
}
/*
*--------------------------------------------------------------------------
* Function: my_printf()
* Parameters: as in printf + error level
* Return: none
* Description: No Words...
*--------------------------------------------------------------------------
*/
void my_printf(int error_level, char *fmt, ...)
{
va_list argptr;
if ((g_verbose == NO_VERBOSE) && (error_level == TINF))
return;
if ((g_verbose != SUPER_VERBOSE) && (error_level == TDBG))
return;
va_start(argptr, fmt);
vprintf(fmt, argptr);
va_end(argptr);
}
/*
*--------------------------------------------------------------------------
* Function: write_to_file
* Parameters: TBD
* Return: TRUE on successful write
* Description: Writes to ELF or BIN files - whatever is open
*--------------------------------------------------------------------------
*/
int write_to_file(unsigned int write_value,
unsigned int offset,
unsigned char num_of_bytes,
char *print_string)
{
int result = 0;
int index;
unsigned int localValue4;
unsigned short localValue2;
unsigned char localValue1;
if (fseek(g_hfd_pointer, offset, SEEK_SET) < 0)
return FALSE;
switch (num_of_bytes) {
case(1):
localValue1 = (unsigned char)write_value;
result = (int)(fwrite(&localValue1, 1,
1, g_hfd_pointer));
break;
case(2):
localValue2 = (unsigned short)write_value;
result = (int)(fwrite(&localValue2,
2,
1,
g_hfd_pointer));
break;
case(4):
localValue4 = write_value;
result = (int)(fwrite(&localValue4,
4,
1,
g_hfd_pointer));
break;
default:
/* Pad the same value N times. */
localValue1 = (unsigned char)write_value;
for (index = 0; index < num_of_bytes; index++)
result = (int)(fwrite(&localValue1,
1,
1,
g_hfd_pointer));
break;
}
my_printf(TINF, "\nIn write_to_file - %s", print_string);
if (result) {
my_printf(TINF,
" - Offset %2d - value 0x%x",
offset, write_value);
} else {
my_printf(TERR,
"\n\nCouldn't write %x to file at %x\n\n",
write_value, offset);
return FALSE;
}
return TRUE;
}
/*
*--------------------------------------------------------------------------
* Function: read_from_file
* Parameters: TBD
* Return: TRUE on successful read
* Description : Reads from open BIN file
*--------------------------------------------------------------------------
*/
int read_from_file(unsigned int offset,
unsigned char size_to_read,
unsigned int *read_value,
char *print_string)
{
int result;
unsigned int localValue4;
unsigned short localValue2;
unsigned char localValue1;
if (fseek(input_file_pointer, offset, SEEK_SET) < 0)
return FALSE;
switch (size_to_read) {
case(1):
result = (int)(fread(&localValue1,
1,
1,
input_file_pointer));
*read_value = localValue1;
break;
case(2):
result = (int)(fread(&localValue2,
2,
1,
input_file_pointer));
*read_value = localValue2;
break;
case(4):
result = (int)(fread(&localValue4,
4,
1,
input_file_pointer));
*read_value = localValue4;
break;
default:
my_printf(TERR, "\nIn read_from_file - %s", print_string);
my_printf(TERR, "\n\nInvalid call to read_from_file\n\n");
return FALSE;
}
my_printf(TINF, "\nIn read_from_file - %s", print_string);
if (result) {
my_printf(TINF,
" - Offset %d - value %x",
offset, *read_value);
} else {
my_printf(TERR,
"\n\nCouldn't read from file at %x\n\n",
offset);
return FALSE;
}
return TRUE;
}
/*
*--------------------------------------------------------------------------
* Function: init_calculation
* Parameters: unsigned int check_sum_crc (I\O)
* Return:
* Description: Initialize the variable according to the selected
* calculation
*--------------------------------------------------------------------------
*/
void init_calculation(unsigned int *check_sum_crc)
{
switch (g_calc_type) {
case CALC_TYPE_NONE:
case CALC_TYPE_CHECKSUM:
*check_sum_crc = 0;
break;
case CALC_TYPE_CRC:
*check_sum_crc = initialize_crc_32();
break;
}
}
/*
*--------------------------------------------------------------------------
* Function: finalize_calculation
* Parameters: unsigned int check_sum_crc (I\O)
* Return:
* Description: Finalize the variable according to the selected calculation
*--------------------------------------------------------------------------
*/
void finalize_calculation(unsigned int *check_sum_crc)
{
switch (g_calc_type) {
case CALC_TYPE_NONE:
case CALC_TYPE_CHECKSUM:
/* Do nothing */
break;
case CALC_TYPE_CRC:
*check_sum_crc = finalize_crc_32(*check_sum_crc);
break;
}
}
/*--------------------------------------------------------------------------
* Function: update_calculation
* Parameters: unsigned int check_sum_crc (I\O)
* unsigned int byte_to_add (I)
* Return:
* Description: Calculate a new checksum\crc with the new byte_to_add
* given the previous checksum\crc
*--------------------------------------------------------------------------
*/
void update_calculation(unsigned int *check_sum_crc,
unsigned char byte_to_add)
{
switch (g_calc_type) {
case CALC_TYPE_NONE:
/* Do nothing */
break;
case CALC_TYPE_CHECKSUM:
*check_sum_crc += byte_to_add;
break;
case CALC_TYPE_CRC:
*check_sum_crc = update_crc_32(*check_sum_crc, byte_to_add);
break;
}
}
/*
*--------------------------------------------------------------------------
* Function: str_cmp_no_case
* Parameters: s1, s2: Strings to compare.
* Return: function returns an integer less than, equal to, or
* greater than zero if s1 (or the first n bytes thereof) is
* found, respectively, to be less than, to match, or be
* greater than s2.
* Description: Compare two string without case sensitive.
*--------------------------------------------------------------------------
*/
int str_cmp_no_case(const char *s1, const char *s2)
{
return strcasecmp(s1, s2);
}
/*
*--------------------------------------------------------------------------
* Function: get_file_length
* Parameters: stream - Pointer to a FILE object
* Return: File length in bytes or -1 on error
* Description: Gets the file length in bytes.
*--------------------------------------------------------------------------
*/
int get_file_length(FILE *stream)
{
int current_position;
int file_len;
/* Store current position. */
current_position = ftell(stream);
if (current_position < 0)
return -1;
/* End position of the file is its length. */
if (fseek(stream, 0, SEEK_END) < 0)
return -1;
file_len = ftell(stream);
/* Restore the original position. */
if (fseek(stream, current_position, SEEK_SET) < 0)
return -1;
/* return file length. */
return file_len;
}
/*
***************************************************************************
* "bt" mode Handler
***************************************************************************
*/
/*
***************************************************************************
* Function: main_bin
* Parameters: TBD
* Return: True for success
* Description:
* TBD
***************************************************************************
*/
int main_bin(struct tbinparams binary_params)
{
unsigned int bin_file_size_bytes;
unsigned int bin_fw_offset = 0;
unsigned int tmp_param;
FILE *output_file_pointer;
/* If input file was not declared, then print error message. */
if (strlen(input_file_name) == 0) {
my_printf(TERR, "\n\nDefine input file, using -i flag\n\n");
return FALSE;
}
/* Open input file */
input_file_pointer = fopen(input_file_name, "r+b");
if (input_file_pointer == NULL) {
my_printf(TERR, "\n\nCannot open %s\n\n", input_file_name);
return FALSE;
}
/*
* Check Binary file size, this file contain the image itself,
* without any header.
*/
bin_file_size_bytes = get_file_length(input_file_pointer);
if (bin_file_size_bytes == 0) {
my_printf(TINF,
"\nBIN Input file name %s is empty (size is %d)\n",
input_file_name, bin_file_size_bytes);
return FALSE;
}
/*
* If the binary file contains also place for the header, then the FW
* size is the length of the file minus the header length
*/
if ((binary_params.bin_params & BIN_FW_HDR_OFFSET) != 0)
bin_fw_offset = binary_params.fw_hdr_offset + HEADER_SIZE;
my_printf(TINF, "\nBIN file: %s, size: %d (0x%x) bytes\n",
input_file_name,
bin_file_size_bytes,
bin_file_size_bytes);
/* Check validity of FW header offset. */
if (((int)binary_params.fw_hdr_offset < 0) ||
(binary_params.fw_hdr_offset > bin_file_size_bytes)) {
my_printf(TERR,
"\nFW header offset 0x%08x (%d) should be in the"
" range of 0 and file size (%d).\n",
binary_params.fw_hdr_offset,
binary_params.fw_hdr_offset,
bin_file_size_bytes);
return FALSE;
}
/* Create the header file in the same directory as the input file. */
if (!splice_into_path(g_hdr_input_name, input_file_name,
sizeof(g_hdr_input_name), "hdr_"))
return FALSE;
g_hfd_pointer = fopen(g_hdr_input_name, "w+b");
if (g_hfd_pointer == NULL) {
my_printf(TERR, "\n\nCannot open %s\n\n", g_hdr_input_name);
return FALSE;
}
if (strlen(output_file_name) == 0) {
if (!splice_into_path(output_file_name, input_file_name,
sizeof(output_file_name), "out_"))
return FALSE;
}
my_printf(TINF, "Output file name: %s\n", output_file_name);
/*
*********************************************************************
* Set the ANCHOR & Extended-ANCHOR
*********************************************************************
*/
/* Write the ancore. */
if (!write_to_file(FW_HDR_ANCHOR,
HDR_ANCHOR_OFFSET,
4,
"HDR - FW Header ANCHOR "))
return FALSE;
/* Write the extended anchor. */
if (binary_params.bin_params & BIN_FW_HDR_CRC_DISABLE) {
/* Write the ancore and the extended anchor. */
if (!write_to_file(FW_HDR_EXT_ANCHOR_DISABLE,
HDR_EXTENDED_ANCHOR_OFFSET, 2,
"HDR - Header EXTENDED ANCHOR "))
return FALSE;
} else {
/* Write the anchor and the extended anchor. */
if (!write_to_file(FW_HDR_EXT_ANCHOR_ENABLE,
HDR_EXTENDED_ANCHOR_OFFSET, 2,
"HDR - Header EXTENDED ANCHOR "))
return FALSE;
}
/* Write the SPI flash MAX clock. */
switch (binary_params.spi_max_clk) {
case SPI_MAX_CLOCK_20_MHZ_VAL:
tmp_param = SPI_MAX_CLOCK_20_MHZ;
break;
case SPI_MAX_CLOCK_25_MHZ_VAL:
tmp_param = SPI_MAX_CLOCK_25_MHZ;
break;
case SPI_MAX_CLOCK_33_MHZ_VAL:
tmp_param = SPI_MAX_CLOCK_33_MHZ;
break;
case SPI_MAX_CLOCK_40_MHZ_VAL:
tmp_param = SPI_MAX_CLOCK_40_MHZ;
break;
case SPI_MAX_CLOCK_50_MHZ_VAL:
tmp_param = SPI_MAX_CLOCK_50_MHZ;
break;
default:
my_printf(TERR, "\n\nInvalid SPI Flash MAX clock (%d MHz) ",
binary_params.spi_max_clk);
my_printf(TERR, "- it should be 20, 25, 33, 40 or 50 MHz");
return FALSE;
}
/* If SPI clock ratio set for MRIDER15, then it is error. */
if ((binary_params.spi_clk_ratio != 0x00) && (is_mrider15 == TRUE)) {
my_printf(TERR, "\nspiclkratio is not relevant for");
my_printf(TERR, " npcx5mng chips family !\n");
return FALSE;
}
/*
* In case SPIU clock ratio didn't set by the user,
* set it to its default value.
*/
if (binary_params.spi_clk_ratio == 0x00)
binary_params.spi_clk_ratio = SPI_CLOCK_RATIO_1_VAL;
switch (binary_params.spi_clk_ratio) {
case SPI_CLOCK_RATIO_1_VAL:
tmp_param &= SPI_CLOCK_RATIO_1;
break;
case SPI_CLOCK_RATIO_2_VAL:
tmp_param |= SPI_CLOCK_RATIO_2;
break;
default:
my_printf(TERR, "\n\nInvalid SPI Core Clock Ratio (%d) ",
binary_params.spi_clk_ratio);
my_printf(TERR, "- it should be 1 or 2");
return FALSE;
}
if (!write_to_file(tmp_param, HDR_SPI_MAX_CLK_OFFSET, 1,
"HDR - SPI flash MAX Clock "))
return FALSE;
/* Write the SPI flash Read Mode. */
tmp_param = binary_params.spi_read_mode;
/* If needed, set the unlimited burst bit. */
if (binary_params.bin_params & BIN_UNLIM_BURST_ENABLE) {
if (is_mrider15 == TRUE) {
my_printf(TERR, "\nunlimburst is not relevant for");
my_printf(TERR, " npcx5mng chips family !\n");
return FALSE;
}
tmp_param |= SPI_UNLIMITED_BURST_ENABLE;
}
if (!write_to_file(tmp_param,
HDR_SPI_READ_MODE_OFFSET, 1,
"HDR - SPI flash Read Mode "))
return FALSE;
/* Write the error detection configuration. */
if (binary_params.bin_params & BIN_FW_CRC_DISABLE) {
if (!write_to_file(FW_CRC_DISABLE,
HDR_ERR_DETECTION_CONF_OFFSET,
1,
"HDR - FW CRC Disabled "))
return FALSE;
} else {
/* Write the ancore and the extended anchor. */
if (!write_to_file(FW_CRC_ENABLE,
HDR_ERR_DETECTION_CONF_OFFSET, 1,
"HDR - FW CRC Enabled "))
return FALSE;
}
/* FW entry point should be between the FW load address and RAM size */
if ((binary_params.fw_load_addr >
(g_ram_start_address + g_ram_size)) ||
(binary_params.fw_load_addr < g_ram_start_address)) {
my_printf(TERR,
"\nFW load address (0x%08x) should be between ",
binary_params.fw_load_addr);
my_printf(TERR,
"start (0x%08x) and end (0x%08x) of RAM ).",
g_ram_start_address,
(g_ram_start_address + g_ram_size));
return FALSE;
}
/* Write the FW load start address */
if (!write_to_file(binary_params.fw_load_addr,
HDR_FW_LOAD_START_ADDR_OFFSET, 4,
"HDR - FW load start address "))
return FALSE;
/*
* Write the FW length. (MUST BE SET BEFORE fw_err_detec_e_addr)
*/
if ((binary_params.bin_params & BIN_FW_LENGTH) == 0x00000000) {
/*
* In case the FW length was not set, then the FW length is the
* size of the binary file minus the offset of the start of the
* FW.
*/
binary_params.fw_len = bin_file_size_bytes-bin_fw_offset;
}
if ((int)binary_params.fw_len < 0) {
my_printf(TERR,
"\nFW length %d (0x%08x) should be greater than 0x0.",
binary_params.fw_len,
binary_params.fw_len);
return FALSE;
}
if (((int)binary_params.fw_len >
(bin_file_size_bytes - bin_fw_offset)) ||
((int)binary_params.fw_len > g_ram_size)) {
my_printf(TERR,
"\nFW length %d (0x%08x) should be within the",
binary_params.fw_len, binary_params.fw_len);
my_printf(TERR,
" input-file (related to the FW offset)");
my_printf(TERR,
"\n (0x%08x) and within the RAM (RAM size: 0x%08x).",
(bin_file_size_bytes - bin_fw_offset), g_ram_size);
return FALSE;
}
if ((binary_params.bin_params & BIN_FW_USER_ARM_RESET) != 0x00000000) {
read_from_file((bin_fw_offset + ARM_FW_ENTRY_POINT_OFFSET),
4,
&binary_params.fw_ep,
"read FW entry point for FW image ");
if ((binary_params.fw_ep <
binary_params.fw_load_addr) ||
(binary_params.fw_ep >
(binary_params.fw_load_addr +
binary_params.fw_len))) {
my_printf(TERR,
"\nFW entry point (0x%08x) should be between",
binary_params.fw_ep);
my_printf(TERR,
" the FW load address (0x%08x) ",
binary_params.fw_load_addr);
my_printf(TERR,
"and FW length (0x%08x).\n",
(binary_params.fw_load_addr +
binary_params.fw_len));
return FALSE;
}
}
/* FW entry point should be between the FW load address and RAM size */
if ((binary_params.fw_ep <
binary_params.fw_load_addr) ||
(binary_params.fw_ep >
(binary_params.fw_load_addr +
binary_params.fw_len))) {
if (((binary_params.bin_params & BIN_FW_ENTRY_POINT) ==
0x00000000) &&
((binary_params.bin_params &
BIN_FW_LOAD_START_ADDR) != 0x00000000)) {
binary_params.fw_ep =
binary_params.fw_load_addr;
} else {
my_printf(TERR,
"\nFW entry point (0x%08x) should be ",
binary_params.fw_ep);
my_printf(TERR,
"\between the FW load address (0x%08x)",
binary_params.fw_load_addr);
my_printf(TERR,
" and FW length (0x%08x).\n",
(binary_params.fw_load_addr +
binary_params.fw_len));
return FALSE;
}
}
/* Write the FW entry point */
if (!write_to_file(binary_params.fw_ep,
HDR_FW_ENTRY_POINT_OFFSET,
4,
"HDR - FW Entry point "))
return FALSE;
/* Calculate the CRC end address. */
if ((binary_params.bin_params & BIN_FW_CKS_SIZE) == 0x00000000) {
/*
* In case the size was not set, then CRC end address is
* the size of the binary file.
*/
binary_params.fw_err_detec_e_addr =
binary_params.fw_len - 1;
} else {
/* CRC end address should be less than FW length. */
if (binary_params.fw_err_detec_e_addr >
(binary_params.fw_len - 1)) {
my_printf(TERR,
"\nCRC end address (0x%08x) should be less ",
binary_params.fw_err_detec_e_addr);
my_printf(TERR,
"than the FW length %d (0x%08x)",
(binary_params.fw_len),
(binary_params.fw_len));
return FALSE;
}
}
/* Check CRC start and end addresses. */
if (binary_params.fw_err_detec_s_addr >
binary_params.fw_err_detec_e_addr) {
my_printf(TERR,
"\nCRC start address (0x%08x) should be less or ",
binary_params.fw_err_detec_s_addr);
my_printf(TERR,
"equal to CRC end address (0x%08x)\nPlease check ",
binary_params.fw_err_detec_e_addr);
my_printf(TERR,
"CRC start address and CRC size arguments.");
return FALSE;
}
/* CRC start addr should be between the FW load address and RAM size */
if (binary_params.fw_err_detec_s_addr >
binary_params.fw_len) {
my_printf(TERR, "\nCRC start address (0x%08x) should ",
binary_params.fw_err_detec_s_addr);
my_printf(TERR, "be FW length (0x%08x).",
binary_params.fw_len);
return FALSE;
}
/* Write the CRC start address */
if (!write_to_file(binary_params.fw_err_detec_s_addr,
HDR_FW_ERR_DETECT_START_ADDR_OFFSET,
4,
"HDR - FW CRC Start "))
return FALSE;
/* CRC end addr should be between the CRC start address and RAM size */
if ((binary_params.fw_err_detec_e_addr <
binary_params.fw_err_detec_s_addr) ||
(binary_params.fw_err_detec_e_addr >
binary_params.fw_len)) {
my_printf(TERR,
"\nCRC end address (0x%08x) should be between the ",
binary_params.fw_err_detec_e_addr);
my_printf(TERR,
"CRC start address (0x%08x) and FW length (0x%08x).",
binary_params.fw_err_detec_s_addr,
binary_params.fw_len);
return FALSE;
}
/* Write the CRC end address */
if (!write_to_file(binary_params.fw_err_detec_e_addr,
HDR_FW_ERR_DETECT_END_ADDR_OFFSET,
4,
"HDR - FW CRC End "))
return FALSE;
/* Let the FW length to be aligned to 16 */
tmp_param = binary_params.fw_len % 16;
if (tmp_param)
binary_params.fw_len += (16 - tmp_param);
/* FW load address + FW length should be less than the RAM size. */
if ((binary_params.fw_load_addr +
binary_params.fw_len) >
(g_ram_start_address + g_ram_size)) {
my_printf(TERR,
"\nFW load address + FW length should (0x%08x) be ",
(binary_params.fw_load_addr + binary_params.fw_len));
my_printf(TERR,
"less than the RAM size (0x%08x).",
(g_ram_start_address + g_ram_size));
return FALSE;
}
/* Write the FW length */
if (!write_to_file(binary_params.fw_len,
HDR_FW_LENGTH_OFFSET,
4,
"HDR - FW Length "))
return FALSE;
/* Write the SPI flash MAX clock. */
switch (binary_params.flash_size) {
case FLASH_SIZE_1_MBYTES_VAL:
tmp_param = FLASH_SIZE_1_MBYTES;
break;
case FLASH_SIZE_2_MBYTES_VAL:
tmp_param = FLASH_SIZE_2_MBYTES;
break;
case FLASH_SIZE_4_MBYTES_VAL:
tmp_param = FLASH_SIZE_4_MBYTES;
break;
case FLASH_SIZE_8_MBYTES_VAL:
tmp_param = FLASH_SIZE_8_MBYTES;
break;
case FLASH_SIZE_16_MBYTES_VAL:
tmp_param = FLASH_SIZE_16_MBYTES;
break;
default:
my_printf(TERR, "\n\nInvalid Flash size (%d MBytes) -",
binary_params.flash_size);
my_printf(TERR, " it should be 1, 2, 4, 8 or 16 MBytes\n");
return FALSE;
}
if (!write_to_file(tmp_param,
HDR_FLASH_SIZE_OFFSET,
1,
"HDR - Flash size "))
return FALSE;
/* Write the reserved bytes. */
if (!write_to_file(PAD_VALUE, HDR_RESERVED, 26,
"HDR - Reserved (26 bytes) "))
return FALSE;
/* Refresh the FW header bin file in order to calculate CRC */
if (g_hfd_pointer) {
fclose(g_hfd_pointer);
g_hfd_pointer = fopen(g_hdr_input_name, "r+b");
if (g_hfd_pointer == NULL) {
my_printf(TERR,
"\n\nCannot open %s\n\n",
input_file_name);
return FALSE;
}
}
/* Calculate the FW header CRC */
if ((binary_params.bin_params & BIN_FW_HDR_CRC_DISABLE) == 0) {
/* Calculate ... */
g_calc_type = CALC_TYPE_CRC;
if (!calc_header_crc_bin(&binary_params.hdr_crc))
return FALSE;
g_calc_type = CALC_TYPE_NONE;
} else
binary_params.hdr_crc = 0;
/* Write FW header CRC to header file */
if (!write_to_file(binary_params.hdr_crc,
HDR_FW_HEADER_SIG_OFFSET,
4,
"HDR - Header CRC "))
return FALSE;
/* Calculate the FW CRC */
if ((binary_params.bin_params & BIN_FW_CRC_DISABLE) == 0) {
/* Calculate ... */
g_calc_type = CALC_TYPE_CRC;
if (!calc_firmware_csum_bin(&binary_params.fw_crc,
(bin_fw_offset +
binary_params.fw_err_detec_s_addr),
(binary_params.fw_err_detec_e_addr -
binary_params.fw_err_detec_s_addr+1)))
return FALSE;
g_calc_type = CALC_TYPE_NONE;
} else
binary_params.fw_crc = 0;
/* Write the FW CRC into file header file */
if (!write_to_file(binary_params.fw_crc,
HDR_FW_IMAGE_SIG_OFFSET,
4,
"HDR - FW CRC "))
return FALSE;
/* Close if needed... */
if (input_file_pointer) {
fclose(input_file_pointer);
input_file_pointer = NULL;
}
if (g_hfd_pointer) {
fclose(g_hfd_pointer);
g_hfd_pointer = NULL;
}
/* Create empty output file. */
output_file_pointer = fopen(output_file_name, "wb");
if (output_file_pointer)
fclose(output_file_pointer);
if ((binary_params.bin_params & BIN_FW_HDR_OFFSET) != 0) {
copy_file_to_file(output_file_name,
input_file_name,
0,
SEEK_SET);
copy_file_to_file(output_file_name,
g_hdr_input_name,
binary_params.fw_hdr_offset,
SEEK_SET);
} else {
copy_file_to_file(output_file_name,
g_hdr_input_name,
0,
SEEK_END);
copy_file_to_file(output_file_name,
input_file_name,
0,
SEEK_END);
}
my_printf(TINF, "\n\n");
return TRUE;
}
/*******************************************************************
* Function: calc_header_crc_bin
* Parameters: unsigned short header checksum (O)
* unsigned int header offset from first byte in
* the binary (I)
* Return: TRUE if successful
* Description: Go thru bin file and calculate checksum
*******************************************************************
*/
int calc_header_crc_bin(unsigned int *p_cksum)
{
int i;
unsigned int calc_header_checksum_crc = 0;
unsigned char g_header_array[HEADER_SIZE];
int line_print_size = 32;
init_calculation(&calc_header_checksum_crc);
/* Go thru the BIN File and calculate the Checksum */
if (fseek(g_hfd_pointer, 0x00000000, SEEK_SET) < 0)
return FALSE;
if (fread(g_header_array,
HEADER_SIZE,
1,
g_hfd_pointer) != 1)
return FALSE;
for (i = 0; i < (HEADER_SIZE - HEADER_CRC_FIELDS_SIZE); i++) {
/*
* I had once the Verbose check inside the my_printf, but
* it made ECST run sloooowwwwwly....
*/
if (g_verbose == SUPER_VERBOSE) {
if (i%line_print_size == 0)
my_printf(TDBG, "\n[%.4x]: ", i);
my_printf(TDBG, "%.2x ", g_header_array[i]);
}
update_calculation(&calc_header_checksum_crc,
g_header_array[i]);
if (g_verbose == SUPER_VERBOSE) {
if ((i + 1) % line_print_size == 0)
my_printf(TDBG,
"FW Header ChecksumCRC = %.8x",
calc_header_checksum_crc);
}
}
finalize_calculation(&calc_header_checksum_crc);
*p_cksum = calc_header_checksum_crc;
return TRUE;
}
/*
*******************************************************************
* Function: calc_firmware_csum_bin
* Parameters: unsigned int fwStart (I)
* unsigned int firmware size in words (I)
* unsigned int - firmware checksum (O)
* Return:
* Description: TBD
*******************************************************************
*/
int calc_firmware_csum_bin(unsigned int *p_cksum,
unsigned int fw_offset,
unsigned int fw_length)
{
unsigned int i;
unsigned int calc_read_bytes;
unsigned int calc_num_of_bytes_to_read;
unsigned int calc_curr_position;
unsigned int calc_fw_checksum_crc = 0;
unsigned char g_fw_array[BUFF_SIZE];
int line_print_size = 32;
calc_num_of_bytes_to_read = fw_length;
calc_curr_position = fw_offset;
if (g_verbose == REGULAR_VERBOSE) {
my_printf(TINF,
"\nFW Error Detect Start Dddress: 0x%08x",
calc_curr_position);
my_printf(TINF,
"\nFW Error Detect End Dddress: 0x%08x",
calc_curr_position + calc_num_of_bytes_to_read - 1);
my_printf(TINF,
"\nFW Error Detect Size: %d (0x%X)",
calc_num_of_bytes_to_read,
calc_num_of_bytes_to_read);
}
init_calculation(&calc_fw_checksum_crc);
while (calc_num_of_bytes_to_read > 0) {
if (calc_num_of_bytes_to_read > BUFF_SIZE)
calc_read_bytes = BUFF_SIZE;
else
calc_read_bytes = calc_num_of_bytes_to_read;
if (fseek(input_file_pointer,
calc_curr_position, SEEK_SET) < 0)
return 0;
if (fread(g_fw_array,
calc_read_bytes,
1,
input_file_pointer) != 1)
return 0;
for (i = 0; i < calc_read_bytes; i++) {
/*
* I had once the Verbose check inside the my_printf,
* but it made ECST run sloooowwwwwly....
*/
if (g_verbose == SUPER_VERBOSE) {
if (i%line_print_size == 0)
my_printf(TDBG,
"\n[%.4x]: ",
calc_curr_position + i);
my_printf(TDBG, "%.2x ", g_fw_array[i]);
}
update_calculation(&calc_fw_checksum_crc,
g_fw_array[i]);
if (g_verbose == SUPER_VERBOSE) {
if ((i + 1) % line_print_size == 0)
my_printf(TDBG,
"FW Checksum= %.8x",
calc_fw_checksum_crc);
}
}
calc_num_of_bytes_to_read -= calc_read_bytes;
calc_curr_position += calc_read_bytes;
} /* end of while(calc_num_of_bytes_to_read > 0) */
finalize_calculation(&calc_fw_checksum_crc);
*p_cksum = calc_fw_checksum_crc;
return TRUE;
}
/*
***************************************************************************
* "bh" mode Handler
***************************************************************************
*/
/*
*******************************************************************
* Function: main_hdr
* Parameters: TBD
* Return: True for success
* Description:
*******************************************************************
*/
int main_hdr(void)
{
int result = 0;
char tmp_file_name[NAME_SIZE + 1];
unsigned int tmp_long_val;
unsigned int bin_file_size_bytes;
tmp_file_name[NAME_SIZE] = '\0';
if (is_ptr_merge) {
if (strlen(input_file_name) == 0) {
my_printf(TERR, "\n\nNo input BIN file selected for");
my_printf(TERR, " BootLoader header file.\n\n");
return FALSE;
}
if (strlen(output_file_name) == 0)
strncpy(tmp_file_name,
input_file_name,
sizeof(tmp_file_name) - 1);
else {
copy_file_to_file(output_file_name,
input_file_name,
0,
SEEK_END);
strncpy(tmp_file_name,
output_file_name,
sizeof(tmp_file_name) - 1);
}
/* Open Header file */
g_hdr_pointer = fopen(tmp_file_name, "r+b");
if (g_hdr_pointer == NULL) {
my_printf(TERR,
"\n\nCannot open %s file.\n\n",
tmp_file_name);
return FALSE;
}
bin_file_size_bytes = get_file_length(g_hdr_pointer);
/* Offset should be less than file size. */
if (fw_offset > bin_file_size_bytes) {
my_printf(TERR,
"\n\nFW offset 0x%08x should be less than ",
fw_offset);
my_printf(TERR,
"file size 0x%x (%d).\n\n",
bin_file_size_bytes, bin_file_size_bytes);
return FALSE;
}
/* FW table should be less than file size. */
if (ptr_fw_addr > bin_file_size_bytes) {
my_printf(TERR, "\n\nFW table 0x%08x should be less ",
ptr_fw_addr);
my_printf(TERR, "than file size 0x%x (%d).\n\n",
bin_file_size_bytes, bin_file_size_bytes);
return FALSE;
}
if (fseek(g_hdr_pointer, fw_offset, SEEK_SET) < 0)
return FALSE;
tmp_long_val = HDR_PTR_SIGNATURE;
result = (int)(fwrite(&tmp_long_val,
4,
1,
g_hdr_pointer));
result |= (int)(fwrite(&ptr_fw_addr,
4,
1,
g_hdr_pointer));
if (result) {
my_printf(TINF,
"\nBootLoader Header file: %s\n",
tmp_file_name);
my_printf(TINF,
" Offset: 0x%08X, Signature: 0x%08X,",
fw_offset, HDR_PTR_SIGNATURE);
my_printf(TINF,
" Pointer: 0x%08X\n",
ptr_fw_addr);
} else {
my_printf(TERR,
"\n\nCouldn't write signature (%x) and "
"pointer to BootLoader header file (%s)\n\n",
tmp_long_val, tmp_file_name);
return FALSE;
}
} else {
if (strlen(output_file_name) == 0) {
my_printf(TERR, "\n\nNo output file selected ");
my_printf(TERR, "for BootLoader header file.\n\n");
return FALSE;
}
/* Open Output file */
g_hdr_pointer = fopen(output_file_name, "w+b");
if (g_hdr_pointer == NULL) {
my_printf(TERR,
"\n\nCannot open %s file.\n\n",
output_file_name);
return FALSE;
}
if (fseek(g_hdr_pointer, 0L, SEEK_SET) < 0)
return FALSE;
tmp_long_val = HDR_PTR_SIGNATURE;
result = (int)(fwrite(&tmp_long_val,
4,
1,
g_hdr_pointer));
result |= (int)(fwrite(&ptr_fw_addr,
4,
1,
g_hdr_pointer));
if (result) {
my_printf(TINF,
"\nBootLoader Header file: %s\n",
output_file_name);
my_printf(TINF,
" Signature: 0x%08X, Pointer: 0x%08X\n",
HDR_PTR_SIGNATURE,
ptr_fw_addr);
} else {
my_printf(TERR,
"\n\nCouldn't write signature (%x) and ",
tmp_long_val);
my_printf(TERR,
"pointer to BootLoader header file (%s)\n\n",
output_file_name);
return FALSE;
}
}
/* Close if needed... */
if (g_hdr_pointer) {
fclose(g_hdr_pointer);
g_hdr_pointer = NULL;
}
return TRUE;
}
/*
***************************************************************************
* "api" mode Handler
***************************************************************************
*/
/*
*******************************************************************
* Function: main_api
* Parameters: TBD
* Return: True for success
* Description:
* TBD
*******************************************************************
*/
int main_api(void)
{
char tmp_file_name[NAME_SIZE + 1];
int result = 0;
unsigned int crc_checksum;
tmp_file_name[NAME_SIZE] = '\0';
api_file_size_bytes = 0;
/* If API input file was not declared, then print error message. */
if (strlen(input_file_name) == 0) {
my_printf(TERR,
"\n\nNeed to define API input file, using -i flag\n\n");
return FALSE;
}
if (strlen(output_file_name) == 0) {
if (!splice_into_path(tmp_file_name, input_file_name,
sizeof(tmp_file_name), "api_"))
return FALSE;
} else
strncpy(tmp_file_name, output_file_name,
sizeof(tmp_file_name) - 1);
/* Make sure that new empty file is created. */
api_file_pointer = fopen(tmp_file_name, "w");
if (api_file_pointer == NULL) {
my_printf(TERR, "\n\nCannot open %s\n\n", tmp_file_name);
return FALSE;
}
fclose(api_file_pointer);
copy_file_to_file(tmp_file_name, input_file_name, 0, SEEK_END);
/* Open API input file */
api_file_pointer = fopen(tmp_file_name, "r+b");
if (api_file_pointer == NULL) {
my_printf(TERR, "\n\nCannot open %s\n\n", tmp_file_name);
return FALSE;
}
/*
* Check Binary file size, this file contain the image itself,
* without any header.
*/
api_file_size_bytes = get_file_length(api_file_pointer);
if (api_file_size_bytes < 0)
return FALSE;
my_printf(TINF,
"\nAPI file: %s, size: %d bytes (0x%x)\n",
tmp_file_name,
api_file_size_bytes,
api_file_size_bytes);
crc_checksum = calc_api_csum_bin();
if (fseek(api_file_pointer, api_file_size_bytes, SEEK_SET) < 0)
return FALSE;
result = (int)(fwrite(&crc_checksum,
4,
1,
api_file_pointer));
if (result)
my_printf(TINF,
"\nIn API BIN file - Offset 0x%08X - value 0x%08X",
api_file_size_bytes,
crc_checksum);
else {
my_printf(TERR,
"\n\nCouldn't write %x to API BIN file at %08x\n\n",
crc_checksum, api_file_size_bytes);
return FALSE;
}
/* Close if needed... */
if (api_file_pointer) {
fclose(api_file_pointer);
api_file_pointer = NULL;
}
return TRUE;
}
/*
*******************************************************************
* Function: calc_api_csum_bin
* Parameters:
*
* Return: Return the CRC \ checksum, or "0" in case of fail.
* Description: TBD
*******************************************************************
*/
unsigned int calc_api_csum_bin(void)
{
unsigned int i;
unsigned int calc_read_bytes;
int calc_num_of_bytes_to_read;
unsigned int calc_curr_position;
unsigned int calc_fw_checksum_crc = 0;
unsigned char g_fw_array[BUFF_SIZE];
int line_print_size = 32;
calc_num_of_bytes_to_read = api_file_size_bytes;
calc_curr_position = 0;
if (g_verbose == SUPER_VERBOSE) {
my_printf(TDBG,
"\nAPI CRC \\ Checksum First Byte Address: 0x%08x",
calc_curr_position);
my_printf(TDBG,
"\nAPI CRC \\ Checksum Size: %d (0x%X)",
calc_num_of_bytes_to_read,
calc_num_of_bytes_to_read);
}
init_calculation(&calc_fw_checksum_crc);
while (calc_num_of_bytes_to_read > 0) {
if (calc_num_of_bytes_to_read > BUFF_SIZE)
calc_read_bytes = BUFF_SIZE;
else
calc_read_bytes = calc_num_of_bytes_to_read;
if (fseek(api_file_pointer,
calc_curr_position, SEEK_SET) < 0)
return 0;
if (fread(g_fw_array,
calc_read_bytes,
1,
api_file_pointer) != 1)
return 0;
for (i = 0; i < calc_read_bytes; i++) {
/*
* I had once the Verbose check inside the my_printf,
* but it made ecst run sloooowwwwwly....
*/
if (g_verbose == SUPER_VERBOSE) {
if (i%line_print_size == 0)
my_printf(TDBG,
"\n[%.4x]: ",
calc_curr_position + i);
my_printf(TDBG, "%.2x ", g_fw_array[i]);
}
update_calculation(&calc_fw_checksum_crc,
g_fw_array[i]);
if (g_verbose == SUPER_VERBOSE) {
if ((i + 1) % line_print_size == 0)
my_printf(TDBG,
"FW Checksum= %.8x",
calc_fw_checksum_crc);
}
}
calc_num_of_bytes_to_read -= calc_read_bytes;
calc_curr_position += calc_read_bytes;
} /* end of while(calc_num_of_bytes_to_read > 0) */
finalize_calculation(&calc_fw_checksum_crc);
return calc_fw_checksum_crc;
}
/*
**************************************************************************
* CRC Handler
**************************************************************************
*/
/*
*******************************************************************
*
* #define P_xxxx
*
* The CRC's are computed using polynomials. The coefficients
* for the algorithms are defined by the following constants.
*
*******************************************************************
*/
#define P_32 0xEDB88320L
/*
*******************************************************************
*
* static int crc_tab...init
* static unsigned ... crc_tab...[]
*
* The algorithms use tables with pre-calculated values. This
* speeds up the calculation dramatically. The first time the
* CRC function is called, the table for that specific calcu-
* lation is set up. The ...init variables are used to deter-
* mine if the initialization has taken place. The calculated
* values are stored in the crc_tab... arrays.
*
* The variables are declared static. This makes them invisible
* for other modules of the program.
*
*******************************************************************
*/
static int crc_tab32_init = FALSE;
static unsigned int crc_tab32[256];
/*
********************************************************************
*
* static void init_crc...tab();
*
* Three local functions are used to initialize the tables
* with values for the algorithm.
*
*******************************************************************
*/
static void init_crc32_tab(void);
/*
*******************************************************************
*
* unsigned int initialize_crc_32( void );
*
* The function update_crc_32 calculates a new CRC-32 value
* based on the previous value of the CRC and the next byte
* of the data to be checked.
*
*******************************************************************
*/
unsigned int initialize_crc_32(void)
{
return 0xffffffffL;
} /* initialize_crc_32 */
/*
*******************************************************************
*
* unsigned int update_crc_32( unsigned int crc, char c );
*
* The function update_crc_32 calculates a new CRC-32 value
* based on the previous value of the CRC and the next byte
* of the data to be checked.
*
*******************************************************************
*/
unsigned int update_crc_32(unsigned int crc, char c)
{
unsigned int tmp, long_c;
long_c = 0x000000ffL & (unsigned int)c;
if (!crc_tab32_init)
init_crc32_tab();
tmp = crc ^ long_c;
crc = (crc >> 8) ^ crc_tab32[tmp & 0xff];
return crc;
} /* update_crc_32 */
/*
*******************************************************************
*
* static void init_crc32_tab( void );
*
* The function init_crc32_tab() is used to fill the array
* for calculation of the CRC-32 with values.
*
*******************************************************************
*/
static void init_crc32_tab(void)
{
int i, j;
unsigned int crc;
for (i = 0; i < 256; i++) {
crc = (unsigned int)i;
for (j = 0; j < 8; j++) {
if (crc & 0x00000001L)
crc = (crc >> 1) ^ P_32;
else
crc = crc >> 1;
}
crc_tab32[i] = crc;
}
crc_tab32_init = TRUE;
} /* init_crc32_tab */
/*
*******************************************************************
*
* unsigned int finalize_crc_32( unsigned int crc );
*
* The function finalize_crc_32 finalizes a CRC-32 calculation
* by performing a bit convolution (bit 0 is bit 31, etc').
*
*******************************************************************
*/
unsigned int finalize_crc_32(unsigned int crc)
{
int i;
unsigned int result = 0;
for (i = 0; i < NUM_OF_BYTES; i++)
SET_VAR_BIT(result, NUM_OF_BYTES - (i+1), READ_VAR_BIT(crc, i));
return result;
} /* finalize_crc_32 */