| /* |
| * 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. |
| */ |
| |
| /* Include */ |
| #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; |
| unsigned 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},}; |
| |
| 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); |
| |
| /* |
| *---------------------------------------------------------------------- |
| * 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, "); |
| my_printf(TERR, "npcx7m7k, npcx7m6f, npcx7m5g"); |
| my_printf(TERR, ", npcx5m5g or npcx5m6g.\n"); |
| main_status = FALSE; |
| } else { |
| if (str_cmp_no_case(main_str_temp, |
| "npcx7m7k") == 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) { |
| 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, "should be npcx7m7k, "); |
| my_printf(TERR, "npcx7m6f, npcx7m5g, "); |
| my_printf(TERR, "npcx5m5g or "); |
| my_printf(TERR, "npcx5m6g."); |
| 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)); |
| 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) && |
| (arg_ind < MAX_ARGS); |
| 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)); |
| } 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)); |
| } 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)"); |
| my_printf(TERR, |
| " 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> - EC Chip Name: "); |
| my_printf(TUSG, "npcx7m7k|npcx7m6f|npcx7m5g|npcx5m5g|npcx5m6g"); |
| 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; |
| 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) |
| 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. */ |
| fseek(dst_file, offset, origin); |
| fseek(src_file, 0, SEEK_SET); |
| |
| /* 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); |
| else |
| /* Read failed, return with the copied bytes number. */ |
| break; |
| } |
| |
| /* 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: TBD |
| * Description: Writes to ELF or BIN files - whateves 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; |
| |
| fseek(g_hfd_pointer, 0L, SEEK_SET); |
| fseek(g_hfd_pointer, offset, SEEK_SET); |
| |
| 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 : TBD |
| * 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; |
| |
| fseek(input_file_pointer, 0L, SEEK_SET); |
| fseek(input_file_pointer, offset, SEEK_SET); |
| |
| 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_lengt |
| * Parameters: stream - Pointer to a FILE objec |
| * Return: File length in bytes |
| * Description: Gets the file length in bytes. |
| *-------------------------------------------------------------------------- |
| */ |
| int get_file_length(FILE *stream) |
| { |
| int curent_position; |
| int file_len; |
| |
| /* Store current position. */ |
| curent_position = ftell(stream); |
| |
| /* End position of the file is its length. */ |
| fseek(stream, 0, SEEK_END); /* seek to end of file */ |
| file_len = ftell(stream); |
| |
| /* Restore the original position. */ |
| fseek(stream, curent_position, SEEK_SET); |
| |
| /* 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) |
| { |
| char dir_name[NAME_SIZE]; |
| char *file_name_ptr = NULL; |
| char *tmp_str_ptr; |
| int dir_name_len; |
| 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", |
| binary_params.fw_hdr_offset); |
| my_printf(TERR, |
| " range of 0 and file size (%d).\n", |
| binary_params.fw_hdr_offset, |
| bin_file_size_bytes); return FALSE; |
| } |
| |
| /* Get the input directory and input file name. */ |
| file_name_ptr = input_file_name; |
| for (tmp_str_ptr = input_file_name; tmp_str_ptr != NULL;) { |
| tmp_str_ptr = strstr(tmp_str_ptr, DIR_DELIMITER_STR); |
| if (tmp_str_ptr != NULL) { |
| file_name_ptr = tmp_str_ptr + strlen(DIR_DELIMITER_STR); |
| tmp_str_ptr = file_name_ptr; |
| } |
| } |
| |
| dir_name_len = strlen(input_file_name) - strlen(file_name_ptr); |
| strncpy(dir_name, input_file_name, dir_name_len); |
| dir_name[dir_name_len] = '\0'; |
| |
| /* Create the header file in the same directory as the input file. */ |
| sprintf(g_hdr_input_name, "%shdr_%s", dir_name, file_name_ptr); |
| 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) |
| sprintf(output_file_name, "%sout_%s", dir_name, file_name_ptr); |
| |
| 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: |
| * 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 */ |
| fseek(g_hfd_pointer, 0x00000000, SEEK_SET); |
| if (fread(g_header_array, |
| 1, |
| HEADER_SIZE, |
| g_hfd_pointer) == 0) |
| return 0; |
| |
| 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]: ", |
| g_header_array + 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; |
| |
| fseek(input_file_pointer, 0L, SEEK_SET); |
| fseek(input_file_pointer, calc_curr_position, SEEK_SET); |
| if (fread(g_fw_array, |
| 1, |
| calc_read_bytes, |
| input_file_pointer) == 0) |
| 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]; |
| unsigned int tmp_long_val; |
| unsigned int bin_file_size_bytes; |
| |
| 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)); |
| 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)); |
| } |
| |
| /* 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; |
| } |
| |
| fseek(g_hdr_pointer, 0L, SEEK_SET); |
| fseek(g_hdr_pointer, fw_offset, SEEK_SET); |
| |
| 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 ", |
| tmp_long_val); |
| my_printf(TERR, |
| "pointer to BootLoader header file (%s)\n\n", |
| ptr_fw_addr, 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; |
| } |
| |
| fseek(g_hdr_pointer, 0L, SEEK_SET); |
| |
| 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 dir_name[NAME_SIZE]; |
| char *file_name_ptr = NULL; |
| char *tmp_str_ptr; |
| int dir_name_len; |
| char tmp_file_name[NAME_SIZE]; |
| int result = 0; |
| unsigned int crc_checksum; |
| |
| 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) { |
| /* Get the input directory and input file name. */ |
| file_name_ptr = input_file_name; |
| for (tmp_str_ptr = input_file_name; tmp_str_ptr != NULL;) { |
| tmp_str_ptr = strstr(tmp_str_ptr, DIR_DELIMITER_STR); |
| if (tmp_str_ptr != NULL) { |
| file_name_ptr = |
| tmp_str_ptr + strlen(DIR_DELIMITER_STR); |
| tmp_str_ptr = file_name_ptr; |
| } |
| |
| } |
| |
| dir_name_len = strlen(input_file_name) - strlen(file_name_ptr); |
| strncpy(dir_name, input_file_name, dir_name_len); |
| dir_name[dir_name_len] = '\0'; |
| |
| sprintf(tmp_file_name, "%sapi_%s", dir_name, file_name_ptr); |
| |
| } else |
| strncpy(tmp_file_name, output_file_name, sizeof(tmp_file_name)); |
| |
| /* 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); |
| 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(); |
| |
| fseek(api_file_pointer, 0L, SEEK_SET); |
| fseek(api_file_pointer, api_file_size_bytes, SEEK_SET); |
| |
| 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; |
| 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 = 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; |
| |
| fseek(api_file_pointer, 0L, SEEK_SET); |
| fseek(api_file_pointer, calc_curr_position, SEEK_SET); |
| if (fread(g_fw_array, |
| 1, |
| calc_read_bytes, |
| api_file_pointer) == 0) |
| 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 */ |
| |