diff options
-rwxr-xr-x | util/flash_ec | 57 | ||||
-rw-r--r-- | util/uut/main.c | 221 | ||||
-rw-r--r-- | util/uut/opr.c | 113 | ||||
-rw-r--r-- | util/uut/opr.h | 5 |
4 files changed, 261 insertions, 135 deletions
diff --git a/util/flash_ec b/util/flash_ec index 593a4ede1e..2260b53674 100755 --- a/util/flash_ec +++ b/util/flash_ec @@ -447,7 +447,11 @@ fi LOCAL_BUILD= if [[ -n "${EC_DIR}" ]]; then - LOCAL_BUILD="${EC_DIR}/build/${BOARD}/${EC_FILE}" + if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then + LOCAL_BUILD="${EC_DIR}/build/${BOARD}/RO/${EC_FILE}" + else + LOCAL_BUILD="${EC_DIR}/build/${BOARD}/${EC_FILE}" + fi fi # Get baseboard from build system if present @@ -953,18 +957,9 @@ function flash_npcx_uut() { BUILD_PATH="${EC_DIR}/build/${BOARD}" MONITOR_PATH="${BUILD_PATH}/chip/npcx/spiflashfw" - IMG_RO="${BUILD_PATH}/RO/ec.RO.flat" - IMG_RW="${BUILD_PATH}/RW/ec.RW.bin" MON="${MONITOR_PATH}/npcx_monitor.bin" - MON_HDR_RO="${MONITOR_PATH}/monitor_hdr_ro.bin" - MON_HDR_RW="${MONITOR_PATH}/monitor_hdr_rw.bin" - # The start address to restore monitor header binary - MON_HDR_ADDR="0x200C3000" # The start address to restore monitor firmware binary MON_ADDR="0x200C3020" - # Read the address where the EC image should be loaded from monitor header. - # Default: It is equilvalant to the beginning of code RAM address. - EC_IMG_ADDR="0x"$(xxd -e ${MON_HDR_RO} | cut -d' ' -f4) if [ ! -x "$NPCX_UUT" ]; then die "no NPCX UART Update Tool found." @@ -987,45 +982,11 @@ function flash_npcx_uut() { # Remove the prefix "/dev/" because uartupdatetool will add it. EC_UART=${EC_UART#/dev/} - MON_PARAMS="--port ${EC_UART} --baudrate 115200" - - # Read the RO image size - EC_IMG_SIZE=$(printf "%08X" $(stat -c "%s" ${IMG_RO})) - # Covert RO image size to little endian - EC_IMG_SIZE_LE=${EC_IMG_SIZE:6:2}${EC_IMG_SIZE:4:2}${EC_IMG_SIZE:2:2}${EC_IMG_SIZE:0:2} - # Replace the filed of image size in monitor header with the actual RO image size. - T=/tmp/mon_hdr_ro.$$ - xxd -g4 ${MON_HDR_RO} | awk -v s="$EC_IMG_SIZE_LE" 'NR==1 {$3=s}1' | xxd -r > ${T} - - info "Start to flash RO image.." - # Start to program EC RO image - # Load monitor header binary to address 0x200C3000 - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${MON_HDR_ADDR} --file ${T} - # Load monitor binary to address 0x200C3020 - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${MON_ADDR} --file ${MON} - # Load RO image to Code RAM range. - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${EC_IMG_ADDR} --file ${IMG_RO} - # Execute the monitor to program RO image on SPI flash - ${NPCX_UUT} ${MON_PARAMS} --opr call --addr ${MON_ADDR} - - # Read the RW image size - EC_IMG_SIZE=$(printf "%08X" $(stat -c "%s" ${IMG_RW})) - # Covert RW image size to little endian - EC_IMG_SIZE_LE=${EC_IMG_SIZE:6:2}${EC_IMG_SIZE:4:2}${EC_IMG_SIZE:2:2}${EC_IMG_SIZE:0:2} - # Replace the filed of image size in monitor header with the actual RW image size. - T=/tmp/mon_hdr_rw.$$ - xxd -g4 ${MON_HDR_RW} | awk -v s="$EC_IMG_SIZE_LE" 'NR==1 {$3=s}1' | xxd -r > ${T} - - info "Start to flash RW image.." - # Start to program EC RW image - # Load monitor header binary to address 0x200C3000 - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${MON_HDR_ADDR} --file ${T} + UUT_PARAMS="--port ${EC_UART} --baudrate 115200" + # Load monitor binary to address 0x200C3020 - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${MON_ADDR} --file ${MON} - # Load RW image to Code RAM range. - ${NPCX_UUT} ${MON_PARAMS} --opr wr --addr ${EC_IMG_ADDR} --file ${IMG_RW} - # Execute the monitor to program RW image on SPI flash - ${NPCX_UUT} ${MON_PARAMS} --opr call --addr ${MON_ADDR} + ${NPCX_UUT} ${UUT_PARAMS} --opr wr --addr ${MON_ADDR} --file ${MON} + ${NPCX_UUT} ${UUT_PARAMS} --auto --offset ${FLAGS_offset} --file ${IMG} # Reconnect the EC-3PO interpreter to the UART. dut_control ${MCU}_ec3po_interp_connect:on || \ diff --git a/util/uut/main.c b/util/uut/main.c index 4f54c62f29..251ee1bb4a 100644 --- a/util/uut/main.c +++ b/util/uut/main.c @@ -4,6 +4,7 @@ * found in the LICENSE file. */ +#include <errno.h> #include <getopt.h> #include <stdarg.h> #include <stdint.h> @@ -30,7 +31,18 @@ #define DEFAULT_BAUD_RATE 115200 #define DEFAULT_PORT_NAME "ttyS0" #define DEFAULT_DEV_NUM 0 - +#define DEFAULT_FLASH_OFFSET 0 + +/* The magic number in monitor header */ +#define MONITOR_HDR_TAG 0xA5075001 +/* The location of monitor header */ +#define MONITOR_HDR_ADDR 0x200C3000 +/* The start address of the monitor little firmware to execute */ +#define MONITOR_ADDR 0x200C3020 +/* The start address to store the firmware segment to be programmed */ +#define FIRMWARE_START_ADDR 0x10090000 +/* Divide the ec firmware image into 4K byte */ +#define FIRMWARE_SEGMENT 0x1000 /*--------------------------------------------------------------------------- * Global variables *--------------------------------------------------------------------------- @@ -54,6 +66,8 @@ static char addr_str[MAX_PARAM_SIZE]; static char size_str[MAX_PARAM_SIZE]; static uint32_t baudrate; static uint32_t dev_num; +static uint32_t flash_offset; +static bool auto_mode; /*--------------------------------------------------------------------------- * Functions prototypes @@ -66,7 +80,7 @@ static uint32_t param_get_file_size(const char *file_name); static uint32_t param_get_str_size(char *string); static void main_print_version(void); static void tool_usage(void); -static void exit_uart_app(uint32_t exit_status); +static void exit_uart_app(int32_t exit_status); enum EXIT_CODE { EC_OK = 0x00, @@ -86,6 +100,108 @@ enum EXIT_CODE { */ /*--------------------------------------------------------------------------- + * Function: image_auto_write + * + * Parameters: offset - The start address of the flash to write the firmware + * to. + * buffer - The buffer holds data of the firmware. + * file_size - the size to be programmed. + * Returns: 1 for a successful operation, 0 otherwise. + * Side effects: + * Description: + * Divide the firmware to segments and program them one by one. + *--------------------------------------------------------------------------- + */ +static bool image_auto_write(uint32_t offset, uint8_t *buffer, + uint32_t file_size) +{ + uint32_t data_buf[4]; + uint32_t addr, chunk_remain, file_seg, flash_index, seg; + uint32_t count, percent, total; + + flash_index = offset; + /* Monitor tag */ + data_buf[0] = MONITOR_HDR_TAG; + /* Where the source(RAM) address the firmware stored. */ + data_buf[2] = FIRMWARE_START_ADDR; + + file_seg = file_size; + total = 0; + while (file_seg) { + seg = (file_seg > FIRMWARE_SEGMENT) ? + FIRMWARE_SEGMENT : file_seg; + chunk_remain = seg; + addr = FIRMWARE_START_ADDR; + /* the size to be programmed */ + data_buf[1] = seg; + /* + * The offset of the flash where the segment to be programmed. + */ + data_buf[3] = flash_index; + /* Write the monitor header to RAM */ + opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR, 16); + while (chunk_remain) { + count = (chunk_remain > MAX_RW_DATA_SIZE) ? + MAX_RW_DATA_SIZE : chunk_remain; + if (opr_write_chunk(buffer, addr, count) != true) + return false; + + addr += count; + buffer += count; + chunk_remain -= count; + total += count; + percent = total * 100 / file_size; + printf("\r[%d%%] %d/%d", percent, total, file_size); + } + fflush(stdout); + if (opr_execute_return(MONITOR_ADDR) != true) + return false; + file_seg -= seg; + flash_index += seg; + } + printf("\n"); + return true; +} + +/*--------------------------------------------------------------------------- + * Function: read_input_file + * + * Parameters: size - The size of input file. + * file_name - The name if input file. + * Returns: The address of the buffer allocated to stroe file content. + * Side effects: + * Description: + * Read the file content into an allocated buffer. + *--------------------------------------------------------------------------- + */ +static uint8_t *read_input_file(uint32_t size, const char *file_name) +{ + uint8_t *buffer; + FILE *input_fp; + + buffer = malloc(size); + if (!buffer) { + fprintf(stderr, "Cannot allocate %d bytes\n", size); + return NULL; + } + input_fp = fopen(file_name, "r"); + if (!input_fp) { + display_color_msg(FAIL, + "ERROR: cannot open file %s\n", file_name); + free(buffer); + return NULL; + } + if (fread(buffer, size, 1, input_fp) != 1) { + fprintf(stderr, "Cannot read %s\n", file_name); + fclose(input_fp); + free(buffer); + return NULL; + } + fclose(input_fp); + return buffer; +} + +/*--------------------------------------------------------------------------- * Function: main * * Parameters: argc - Argument Count. @@ -102,7 +218,9 @@ int main(int argc, char *argv[]) char aux_buf[MAX_FILE_NAME_SIZE]; uint32_t size = 0; uint32_t addr = 0; + uint32_t strip_size; enum sync_result sr; + uint8_t *buffer; if (argc <= 1) exit(EC_UNSUPPORTED_CMD_ERR); @@ -111,9 +229,11 @@ int main(int argc, char *argv[]) strncpy(port_name, DEFAULT_PORT_NAME, sizeof(port_name)); baudrate = DEFAULT_BAUD_RATE; dev_num = DEFAULT_DEV_NUM; + flash_offset = DEFAULT_FLASH_OFFSET; opr_name[0] = '\0'; verbose = true; console = false; + auto_mode = false; param_parse_cmd_line(argc, argv); @@ -145,29 +265,59 @@ int main(int argc, char *argv[]) exit_uart_app(EC_SYNC_ERR); } + if (auto_mode) { + size = param_get_file_size(file_name); + if (size == 0) + exit_uart_app(EC_FILE_ERR); + + buffer = read_input_file(size, file_name); + if (!buffer) + exit_uart_app(EC_FILE_ERR); + + /* Ignore the trailing white space to speed up writing */ + strip_size = size; + while ((strip_size > 0) && (buffer[strip_size-1] == 0xFF)) + strip_size--; + + printf("Write file %s at %d with %d bytes\n", + file_name, flash_offset, strip_size); + if (image_auto_write(flash_offset, buffer, strip_size)) { + printf("Flash Done.\n"); + free(buffer); + exit_uart_app(EC_OK); + } + free(buffer); + exit_uart_app(-1); + } + param_check_opr_num(opr_name); /* Write buffer data to chosen address */ if (strcmp(opr_name, OPR_WRITE_MEM) == 0) { addr = strtoul(addr_str, &stop_str, 0); - /* - * Copy the input string to an auxiliary buffer, since string - * is altered by param_get_str_size - */ - memcpy(aux_buf, file_name, sizeof(file_name)); - - /* Retrieve input size */ - if (console) - size = param_get_str_size(aux_buf); - else + if (console) { + /* + * Copy the input string to an auxiliary buffer, since + * string is altered by param_get_str_size + */ + memcpy(aux_buf, file_name, sizeof(file_name)); + /* Retrieve input size */ + size = param_get_str_size(file_name); + /* Ensure non-zero size */ + if (size == 0) + exit_uart_app(EC_FILE_ERR); + opr_write_mem(aux_buf, addr, size); + } else { size = param_get_file_size(file_name); - - /* Ensure non-zero size */ - if (size == 0) - exit_uart_app(EC_FILE_ERR); - - opr_write_mem(file_name, addr, size); + if (size == 0) + exit_uart_app(EC_FILE_ERR); + buffer = read_input_file(size, file_name); + if (!buffer) + exit_uart_app(EC_FILE_ERR); + opr_write_mem(buffer, addr, size); + free(buffer); + } } else if (strcmp(opr_name, OPR_READ_MEM) == 0) { /* Read data to chosen address */ @@ -213,16 +363,18 @@ static const struct option long_opts[] = { {"help", 0, 0, 'h'}, {"quiet", 0, 0, 'q'}, {"console", 0, 0, 'c'}, + {"auto", 0, 0, 'A'}, {"baudrate", 1, 0, 'b'}, {"opr", 1, 0, 'o'}, {"port", 1, 0, 'p'}, {"file", 1, 0, 'f'}, {"addr", 1, 0, 'a'}, {"size", 1, 0, 's'}, + {"offset", 1, 0, 'O'}, {NULL, 0, 0, 0} }; -static char *short_opts = "vhqcb:o:p:f:a:s:?"; +static char *short_opts = "vhqcAb:o:p:f:a:s:O:?"; static void param_parse_cmd_line(int argc, char *argv[]) { @@ -246,6 +398,9 @@ static void param_parse_cmd_line(int argc, char *argv[]) case 'c': console = true; break; + case 'A': + auto_mode = true; + break; case 'b': if (sscanf(optarg, "%du", &baudrate) == 0) exit(EC_BAUDRATE_ERR); @@ -270,6 +425,9 @@ static void param_parse_cmd_line(int argc, char *argv[]) strncpy(size_str, optarg, sizeof(size_str)); size_str[sizeof(size_str)-1] = '\0'; break; + case 'O': + flash_offset = strtol(optarg, NULL, 0); + break; } } } @@ -376,22 +534,25 @@ static void tool_usage(void) { printf("%s version %s\n\n", tool_name, tool_version); printf("General switches:\n"); - printf(" --version - Print version\n"); - printf(" --help - Help menu\n"); - printf(" --quiet - Suppress verbose mode (default is " + printf(" -v, --version - Print version\n"); + printf(" -h, --help - Help menu\n"); + printf(" -q, --quiet - Suppress verbose mode (default is " "verbose ON)\n"); - printf(" --console - Print data to console (default is " + printf(" -c, --console - Print data to console (default is " "print to file)\n"); - printf(" --port <name> - Serial port name (default is %s)\n", + printf(" -p, --port <name> - Serial port name (default is %s)\n", DEFAULT_PORT_NAME); - printf(" --baudrate <num> - COM Port baud-rate (default is %d)\n", + printf(" -b, --baudrate <num> - COM Port baud-rate (default is %d)\n", DEFAULT_BAUD_RATE); + printf(" -A, --auto - Enable auto mode. (default is off)\n"); + printf(" -O, --offset <num> - With --auto, assign the offset of"); + printf(" flash where the image to be written.\n"); printf("\n"); printf("Operation specific switches:\n"); - printf(" --opr <name> - Operation number (see list below)\n"); - printf(" --file <name> - Input/output file name\n"); - printf(" --addr <num> - Start memory address\n"); - printf(" --size <num> - Size of data to read\n"); + printf(" -o, --opr <name> - Operation number (see list below)\n"); + printf(" -f, --file <name> - Input/output file name\n"); + printf(" -a, --addr <num> - Start memory address\n"); + printf(" -s, --size <num> - Size of data to read\n"); printf("\n"); } @@ -420,7 +581,7 @@ static void main_print_version(void) * Exit "nicely" the application. *--------------------------------------------------------------------------- */ -static void exit_uart_app(uint32_t exit_status) +static void exit_uart_app(int32_t exit_status) { if (opr_close_port() != true) display_color_msg(FAIL, "ERROR: Port close failed.\n"); diff --git a/util/uut/opr.c b/util/uut/opr.c index 4c79f0ba9b..27f4c3463d 100644 --- a/util/uut/opr.c +++ b/util/uut/opr.c @@ -129,6 +129,34 @@ bool opr_open_port(const char *port_name, struct comport_fields port_cfg) } /*---------------------------------------------------------------------------- + * Function: opr_write_chunk + * + * Parameters: + * buffer - Input data buffer. + * addr - Memory address to write to. + * size - Data size to write. + * Returns: true if successful, false in the case of an error. + * Side effects: + * Description: + * Write data to RAM, starting from the given address (addr). + * Data size is limited to the max chunk size (256 bytes). + *--------------------------------------------------------------------------- + */ +bool opr_write_chunk(uint8_t *buffer, uint32_t addr, uint32_t size) +{ + struct command_node wr_cmd_buf; + + if (size > MAX_RW_DATA_SIZE) { + display_color_msg(FAIL, + "ERROR: Block cannot exceed %d\n", MAX_RW_DATA_SIZE); + } + /* Initialize response size */ + wr_cmd_buf.resp_size = 1; + cmd_create_write(addr, size, buffer, + wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); + return opr_send_cmds(&wr_cmd_buf, 1); +} +/*---------------------------------------------------------------------------- * Function: opr_write_mem * * Parameters: input - Input (file-name/console), containing data to write. @@ -145,12 +173,11 @@ bool opr_open_port(const char *port_name, struct comport_fields port_cfg) * (console mode). *--------------------------------------------------------------------------- */ -void opr_write_mem(char *input, uint32_t addr, uint32_t size) +void opr_write_mem(uint8_t *buffer, uint32_t addr, uint32_t size) { - FILE *input_file_id = NULL; uint32_t cur_addr = addr; uint8_t data_buf[256]; - uint32_t write_size; + uint32_t write_size, size_remain; uint32_t cmd_idx = 1; char seps[] = " "; char *token = NULL; @@ -158,17 +185,6 @@ void opr_write_mem(char *input, uint32_t addr, uint32_t size) uint32_t block_size = (console) ? sizeof(uint32_t) : MAX_RW_DATA_SIZE; struct command_node wr_cmd_buf; - if (!console) { - input_file_id = fopen(input, "rb"); - - if (input_file_id == NULL) { - display_color_msg(FAIL, - "ERROR: could not open input file [%s]\n", - input); - return; - } - } - /* Initialize response size */ wr_cmd_buf.resp_size = 1; @@ -177,15 +193,12 @@ void opr_write_mem(char *input, uint32_t addr, uint32_t size) /* Read first token from string */ if (console) - token = strtok(input, seps); + token = strtok(buffer, seps); + size_remain = size; /* Main write loop */ while (true) { if (console) { - /* Check if last token in string is reached */ - if (token == NULL) - break; - /* * Invert token to double-word and insert the value to * data buffer @@ -193,48 +206,32 @@ void opr_write_mem(char *input, uint32_t addr, uint32_t size) (*(uint32_t *)data_buf) = strtoul(token, &stop_str, BASE_HEXADECIMAL); - /* Block size is fixed to a double-word */ - write_size = sizeof(uint32_t); - /* Prepare the next iteration */ token = strtok(NULL, seps); + } + write_size = (size_remain > block_size) ? + block_size : size_remain; + if (console) { + cmd_create_write(cur_addr, write_size, data_buf, + wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); } else { - /* Check if end of file is reached */ - if (feof(input_file_id)) - break; - - /* Read from file into data buffer */ - write_size = (uint32_t)fread(data_buf, 1, block_size, - input_file_id); - - /* - * In case we read the exact size of the file (e.g., - * 256 bytes), feof will return 0 because, even though - * the file pointer is at the end of the file, we have - * not attempted to read beyond the end. - * Only after trying to read additional byte will feof - * return a nonzero value - */ - if (write_size == 0) - break; + cmd_create_write(cur_addr, write_size, buffer, + wr_cmd_buf.cmd, &wr_cmd_buf.cmd_size); + buffer += write_size; } - - cmd_create_write(cur_addr, write_size, data_buf, wr_cmd_buf.cmd, - &wr_cmd_buf.cmd_size); if (opr_send_cmds(&wr_cmd_buf, 1) != true) break; cmd_disp_write(resp_buf, write_size, cmd_idx, ((size + (block_size - 1)) / block_size)); - - cur_addr += block_size; + cur_addr += write_size; + size_remain -= write_size; cmd_idx++; + if (size_remain == 0) + break; } DISPLAY_MSG(("\n")); - - if (!console) - fclose(input_file_id); } /*---------------------------------------------------------------------------- @@ -331,23 +328,29 @@ void opr_execute_exit(uint32_t addr) * Function: opr_execute_return * * Parameters: addr - Start address to execute from. - * Returns: none. + * Returns: true if successful, false in the case of an error. * Side effects: * Description: - * Execute code starting from a given address. - * Memory address may be in Flash (SPI), DRAM (DDR) or SRAM. - * The executed code should return with the execution result. + * Execute code starting from the given address and then check the result. + * The executed code should return with the execution result. *--------------------------------------------------------------------------- */ -void opr_execute_return(uint32_t addr) +bool opr_execute_return(uint32_t addr) { uint32_t cmd_num; cmd_build_exec_ret(addr, cmd_buf, &cmd_num); if (opr_send_cmds(cmd_buf, cmd_num) != true) - return; + return false; - cmd_disp_exec_ret(resp_buf); + /* + * Check the response command code is UFPP_FCALL_RSLT_CMD and + * the return value from monitor is 0x03. (program finish and verify ok) + */ + if (resp_buf[1] != (uint8_t)(UFPP_FCALL_RSLT_CMD) + || resp_buf[2] != 0x03) + return false; + return true; } /*---------------------------------------------------------------------------- diff --git a/util/uut/opr.h b/util/uut/opr.h index 21e05b7daf..f3d630ceb4 100644 --- a/util/uut/opr.h +++ b/util/uut/opr.h @@ -48,10 +48,11 @@ extern struct comport_fields port_cfg; void opr_usage(void); bool opr_close_port(void); bool opr_open_port(const char *port_name, struct comport_fields port_cfg); -void opr_write_mem(char *input, uint32_t addr, uint32_t size); +bool opr_write_chunk(uint8_t *buffer, uint32_t addr, uint32_t size); +void opr_write_mem(uint8_t *buffer, uint32_t addr, uint32_t size); void opr_read_mem(char *output, uint32_t addr, uint32_t size); void opr_execute_exit(uint32_t addr); -void opr_execute_return(uint32_t addr); +bool opr_execute_return(uint32_t addr); bool opr_scan_baudrate(void); enum sync_result opr_check_sync(uint32_t baudrate); #endif /* __UTIL_UUT_OPR_H */ |