750 lines
20 KiB
C
750 lines
20 KiB
C
/*
|
|
* Copyright 2018 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 <errno.h>
|
|
#include <getopt.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "com_port.h"
|
|
#include "compile_time_macros.h"
|
|
#include "main.h"
|
|
#include "misc_util.h"
|
|
#include "opr.h"
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Constant definitions
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
#define MAX_FILE_NAME_SIZE 512
|
|
#define MAX_PARAM_SIZE 32
|
|
#define MAX_MSG_SIZE 128
|
|
#define MAX_SYNC_RETRIES 3
|
|
|
|
/* Default values */
|
|
#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
|
|
/* Register address for chip ID */
|
|
#define NPCX_SRID_CR 0x400C101C
|
|
/* Register address for device ID */
|
|
#define NPCX_DEVICE_ID_CR 0x400C1022
|
|
#define NPCX_FLASH_BASE_ADDR 0x64000000
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Global variables
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
bool verbose;
|
|
bool console;
|
|
struct comport_fields port_cfg;
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Local variables
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
static const char tool_name[] = {"LINUX UART Update Tool"};
|
|
static const char tool_version[] = {"2.0.1"};
|
|
|
|
static char port_name[MAX_PARAM_SIZE];
|
|
static char opr_name[MAX_PARAM_SIZE];
|
|
static char file_name[MAX_FILE_NAME_SIZE];
|
|
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;
|
|
static bool read_flash_flag;
|
|
|
|
struct npcx_chip_info {
|
|
uint8_t device_id;
|
|
uint8_t chip_id;
|
|
uint32_t flash_size;
|
|
};
|
|
|
|
const static struct npcx_chip_info chip_info[] = {
|
|
{
|
|
/* NPCX796FA */
|
|
.device_id = 0x21,
|
|
.chip_id = 0x06,
|
|
.flash_size = 1024 * 1024,
|
|
},
|
|
|
|
{
|
|
/* NPCX796FB */
|
|
.device_id = 0x21,
|
|
.chip_id = 0x07,
|
|
.flash_size = 1024 * 1024,
|
|
},
|
|
|
|
{
|
|
/* NPCX797WB */
|
|
.device_id = 0x24,
|
|
.chip_id = 0x07,
|
|
.flash_size = 1024 * 1024,
|
|
},
|
|
|
|
{
|
|
/* NPCX796FC */
|
|
.device_id = 0x29,
|
|
.chip_id = 0x07,
|
|
.flash_size = 512 * 1024,
|
|
},
|
|
|
|
{
|
|
/* NPCX797WC */
|
|
.device_id = 0x2C,
|
|
.chip_id = 0x07,
|
|
.flash_size = 512 * 1024,
|
|
},
|
|
};
|
|
/*---------------------------------------------------------------------------
|
|
* Functions prototypes
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void param_parse_cmd_line(int argc, char *argv[]);
|
|
static void param_check_opr_num(const char *opr);
|
|
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(int32_t exit_status);
|
|
|
|
enum EXIT_CODE {
|
|
EC_OK = 0x00,
|
|
EC_PORT_ERR = 0x01,
|
|
EC_BAUDRATE_ERR = 0x02,
|
|
EC_SYNC_ERR = 0x03,
|
|
EC_DEV_NUM_ERR = 0x04,
|
|
EC_OPR_MUM_ERR = 0x05,
|
|
EC_ALIGN_ERR = 0x06,
|
|
EC_FILE_ERR = 0x07,
|
|
EC_UNSUPPORTED_CMD_ERR = 0x08
|
|
};
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function implementation
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* 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;
|
|
uint32_t i;
|
|
|
|
flash_index = offset;
|
|
/* Monitor tag */
|
|
data_buf[0] = MONITOR_HDR_TAG;
|
|
|
|
file_seg = file_size;
|
|
total = 0;
|
|
while (file_seg) {
|
|
seg = (file_seg > FIRMWARE_SEGMENT) ?
|
|
FIRMWARE_SEGMENT : file_seg;
|
|
/*
|
|
* Check if the content of the segment is all 0xff.
|
|
* If yes, there is no need to write.
|
|
* Call the monitor to erase the segment only for
|
|
* time efficiency.
|
|
*/
|
|
for (i = 0; i < seg && buffer[i] == 0xFF; i++)
|
|
;
|
|
if (i == seg) {
|
|
data_buf[1] = seg;
|
|
/*
|
|
* Set src_addr = 0 as a flag. When the monitor read 0
|
|
* from this field, it will do sector erase only.
|
|
*/
|
|
data_buf[2] = 0;
|
|
data_buf[3] = flash_index;
|
|
opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR,
|
|
sizeof(data_buf));
|
|
if (opr_execute_return(MONITOR_ADDR) != true)
|
|
return false;
|
|
file_seg -= seg;
|
|
flash_index += seg;
|
|
buffer += seg;
|
|
total += seg;
|
|
percent = total * 100 / file_size;
|
|
printf("\r[%d%%] %d/%d", percent, total, file_size);
|
|
fflush(stdout);
|
|
continue;
|
|
}
|
|
chunk_remain = seg;
|
|
addr = FIRMWARE_START_ADDR;
|
|
/* the size to be programmed */
|
|
data_buf[1] = seg;
|
|
/* The source(RAM) address where the firmware is stored. */
|
|
data_buf[2] = FIRMWARE_START_ADDR;
|
|
/*
|
|
* 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,
|
|
sizeof(data_buf));
|
|
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");
|
|
/* Clear the UUT header tag */
|
|
data_buf[0] = 0;
|
|
opr_write_chunk((uint8_t *)data_buf, MONITOR_HDR_ADDR, 4);
|
|
return true;
|
|
}
|
|
|
|
static bool get_flash_size(uint32_t *flash_size)
|
|
{
|
|
uint8_t dev_id, chip_id, i;
|
|
|
|
if (opr_read_chunk(&dev_id, NPCX_DEVICE_ID_CR, 1) != true)
|
|
return false;
|
|
|
|
if (opr_read_chunk(&chip_id, NPCX_SRID_CR, 1) != true)
|
|
return false;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(chip_info); i++) {
|
|
if (chip_info[i].device_id == dev_id &&
|
|
chip_info[i].chip_id == chip_id) {
|
|
*flash_size = chip_info[i].flash_size;
|
|
return true;
|
|
}
|
|
}
|
|
printf("Unknown NPCX device ID:0x%02x chip ID:0x%02x\n",
|
|
dev_id, chip_id);
|
|
|
|
return false;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* 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.
|
|
* argv - Argument Vector.
|
|
* Returns: 1 for a successful operation, 0 otherwise.
|
|
* Side effects:
|
|
* Description:
|
|
* Console application main operation.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *stop_str;
|
|
char aux_buf[MAX_FILE_NAME_SIZE];
|
|
uint32_t size = 0;
|
|
uint32_t addr = 0;
|
|
enum sync_result sr;
|
|
uint8_t *buffer;
|
|
int sync_cnt;
|
|
|
|
if (argc <= 1)
|
|
exit(EC_UNSUPPORTED_CMD_ERR);
|
|
|
|
/* Setup defaults */
|
|
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;
|
|
read_flash_flag = false;
|
|
|
|
param_parse_cmd_line(argc, argv);
|
|
|
|
/* Configure COM Port parameters */
|
|
port_cfg.baudrate = MAX(baudrate, BR_LOW_LIMIT);
|
|
port_cfg.byte_size = CS8;
|
|
port_cfg.flow_control = 0;
|
|
port_cfg.parity = 0;
|
|
port_cfg.stop_bits = 0;
|
|
|
|
/*
|
|
* Open a ComPort device. If user haven't specified such, use ComPort 1
|
|
*/
|
|
if (opr_open_port(port_name, port_cfg) != true)
|
|
exit(EC_PORT_ERR);
|
|
|
|
if (baudrate == 0) { /* Scan baud rate range */
|
|
opr_scan_baudrate();
|
|
exit_uart_app(EC_OK);
|
|
}
|
|
|
|
/* Verify Host and Device are synchronized */
|
|
DISPLAY_MSG(("Performing a Host/Device synchronization check...\n"));
|
|
for (sync_cnt = 1; sync_cnt <= MAX_SYNC_RETRIES; sync_cnt++) {
|
|
sr = opr_check_sync(baudrate);
|
|
if (sr == SR_OK)
|
|
break;
|
|
/*
|
|
* If it fails, try it again up to three times.
|
|
* It might fail for garbage data drainage from H1, or
|
|
* for timeout due to unstable data transfer yet.
|
|
*/
|
|
display_color_msg(FAIL,
|
|
"Host/Device synchronization failed, error = %d,"
|
|
" fail count = %d\n", sr, sync_cnt);
|
|
}
|
|
if (sync_cnt > MAX_SYNC_RETRIES)
|
|
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);
|
|
|
|
printf("Write file %s at %d with %d bytes\n",
|
|
file_name, flash_offset, size);
|
|
if (image_auto_write(flash_offset, buffer, size)) {
|
|
printf("Flash Done.\n");
|
|
free(buffer);
|
|
exit_uart_app(EC_OK);
|
|
}
|
|
free(buffer);
|
|
exit_uart_app(-1);
|
|
}
|
|
|
|
if (read_flash_flag) {
|
|
uint32_t flash_size;
|
|
|
|
if (get_flash_size(&flash_size)) {
|
|
printf("Read %d bytes from flash...\n", flash_size);
|
|
opr_read_mem(file_name, NPCX_FLASH_BASE_ADDR,
|
|
flash_size);
|
|
exit_uart_app(EC_OK);
|
|
}
|
|
|
|
printf("Fail to read the flash size\n");
|
|
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);
|
|
|
|
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);
|
|
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 */
|
|
|
|
addr = strtoul(addr_str, &stop_str, 0);
|
|
size = strtoul(size_str, &stop_str, 0);
|
|
|
|
opr_read_mem(file_name, addr, size);
|
|
} else if (strcmp(opr_name, OPR_EXECUTE_EXIT) == 0) {
|
|
/* Execute From Address a non-return code */
|
|
|
|
addr = strtoul(addr_str, &stop_str, 0);
|
|
|
|
opr_execute_exit(addr);
|
|
exit_uart_app(EC_OK);
|
|
} else if (strcmp(opr_name, OPR_EXECUTE_CONT) == 0) {
|
|
/* Execute From Address a returnable code */
|
|
|
|
addr = strtoul(addr_str, &stop_str, 0);
|
|
|
|
opr_execute_return(addr);
|
|
} else {
|
|
exit_uart_app(EC_UNSUPPORTED_CMD_ERR);
|
|
}
|
|
|
|
exit_uart_app(EC_OK);
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: param_parse_cmd_line
|
|
*
|
|
* Parameters: argc - Argument Count.
|
|
* argv - Argument Vector.
|
|
* Returns: None.
|
|
* Side effects:
|
|
* Description:
|
|
* Parse command line parameters.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
|
|
static const struct option long_opts[] = {
|
|
{"version", 0, 0, 'v'},
|
|
{"help", 0, 0, 'h'},
|
|
{"quiet", 0, 0, 'q'},
|
|
{"console", 0, 0, 'c'},
|
|
{"auto", 0, 0, 'A'},
|
|
{"read-flash", 0, 0, 'r'},
|
|
{"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 = "vhqcArb:o:p:f:a:s:O:?";
|
|
|
|
static void param_parse_cmd_line(int argc, char *argv[])
|
|
{
|
|
int opt, idx;
|
|
|
|
while ((opt = getopt_long(argc, argv, short_opts,
|
|
long_opts, &idx)) != -1) {
|
|
|
|
switch (opt) {
|
|
case 'v':
|
|
main_print_version();
|
|
exit(EC_OK);
|
|
case 'h':
|
|
case '?':
|
|
tool_usage();
|
|
opr_usage();
|
|
exit(EC_OK);
|
|
case 'q':
|
|
verbose = false;
|
|
break;
|
|
case 'c':
|
|
console = true;
|
|
break;
|
|
case 'A':
|
|
auto_mode = true;
|
|
break;
|
|
case 'r':
|
|
read_flash_flag = true;
|
|
break;
|
|
case 'b':
|
|
if (sscanf(optarg, "%du", &baudrate) == 0)
|
|
exit(EC_BAUDRATE_ERR);
|
|
break;
|
|
case 'o':
|
|
strncpy(opr_name, optarg, sizeof(opr_name));
|
|
opr_name[sizeof(opr_name)-1] = '\0';
|
|
break;
|
|
case 'p':
|
|
strncpy(port_name, optarg, sizeof(port_name));
|
|
port_name[sizeof(port_name)-1] = '\0';
|
|
break;
|
|
case 'f':
|
|
strncpy(file_name, optarg, sizeof(file_name));
|
|
file_name[sizeof(file_name)-1] = '\0';
|
|
break;
|
|
case 'a':
|
|
strncpy(addr_str, optarg, sizeof(addr_str));
|
|
addr_str[sizeof(addr_str)-1] = '\0';
|
|
break;
|
|
case 's':
|
|
strncpy(size_str, optarg, sizeof(size_str));
|
|
size_str[sizeof(size_str)-1] = '\0';
|
|
break;
|
|
case 'O':
|
|
flash_offset = strtol(optarg, NULL, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: param_check_opr_num
|
|
*
|
|
* Parameters: opr - Operation Number.
|
|
* Returns: none.
|
|
* Side effects:
|
|
* Description:
|
|
* Verify the validity of operation Number.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
static void param_check_opr_num(const char *opr)
|
|
{
|
|
|
|
if ((strcasecmp(opr, OPR_WRITE_MEM) != 0) &&
|
|
(strcasecmp(opr, OPR_READ_MEM) != 0) &&
|
|
(strcasecmp(opr, OPR_EXECUTE_EXIT) != 0) &&
|
|
(strcasecmp(opr, OPR_EXECUTE_CONT) != 0)) {
|
|
display_color_msg(FAIL,
|
|
"ERROR: Operation %s not supported, Supported "
|
|
"operations are %s, %s, %s & %s\n",
|
|
opr, OPR_WRITE_MEM, OPR_READ_MEM, OPR_EXECUTE_EXIT,
|
|
OPR_EXECUTE_CONT);
|
|
exit_uart_app(EC_OPR_MUM_ERR);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: param_get_file_size
|
|
*
|
|
* Parameters: file_name - input file name.
|
|
* Returns: size of file (in bytes).
|
|
* Side effects:
|
|
* Description:
|
|
* Retrieve the size (in bytes) of a given file.
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
static uint32_t param_get_file_size(const char *file_name)
|
|
{
|
|
struct stat fst;
|
|
|
|
if (stat(file_name, &fst)) {
|
|
display_color_msg(FAIL,
|
|
"ERROR: Could not stat file [%s]\n", file_name);
|
|
return 0;
|
|
}
|
|
return fst.st_size;
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: param_get_str_size
|
|
*
|
|
* Parameters: string - input string.
|
|
* Returns: size of double-words (in bytes).
|
|
* Side effects:
|
|
* Description:
|
|
* Retrieve the size (in bytes) of double-word values in a given string.
|
|
* E.g., given the string "1234 AB5678 FF", return 12 (for three
|
|
* double-words).
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
static uint32_t param_get_str_size(char *string)
|
|
{
|
|
uint32_t str_size = 0;
|
|
char seps[] = " ";
|
|
char *token = NULL;
|
|
|
|
/* Verify string is non-NULL */
|
|
if ((string == NULL) || (strlen(string) == 0)) {
|
|
display_color_msg(FAIL,
|
|
"ERROR: Zero length input string provided\n");
|
|
return 0;
|
|
}
|
|
|
|
/* Read first token from string */
|
|
token = strtok(string, seps);
|
|
|
|
/* Loop while there are tokens in "string" */
|
|
while (token != NULL) {
|
|
str_size++;
|
|
token = strtok(NULL, seps);
|
|
}
|
|
|
|
/* Refer to each token as a double-word */
|
|
str_size *= sizeof(uint32_t);
|
|
return str_size;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* Function: tool_usage
|
|
*
|
|
* Parameters: none.
|
|
* Returns: none.
|
|
* Side effects:
|
|
* Description:
|
|
* Prints the console application help menu.
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
static void tool_usage(void)
|
|
{
|
|
printf("%s version %s\n\n", tool_name, tool_version);
|
|
printf("General switches:\n");
|
|
printf(" -v, --version - Print version\n");
|
|
printf(" -h, --help - Help menu\n");
|
|
printf(" -q, --quiet - Suppress verbose mode (default is "
|
|
"verbose ON)\n");
|
|
printf(" -c, --console - Print data to console (default is "
|
|
"print to file)\n");
|
|
printf(" -p, --port <name> - Serial port name (default is %s)\n",
|
|
DEFAULT_PORT_NAME);
|
|
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(" -r, --read-flash - With --file=<file>, Read the whole"
|
|
" flash content and write it to <file>.\n");
|
|
printf("\n");
|
|
printf("Operation specific switches:\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");
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* Function: main_print_version
|
|
*
|
|
* Parameters: none
|
|
* Returns: none
|
|
* Side effects:
|
|
* Description:
|
|
* This routine prints the tool version
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
static void main_print_version(void)
|
|
{
|
|
printf("%s version %s\n\n", tool_name, tool_version);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: exit_uart_app
|
|
*
|
|
* Parameters: none.
|
|
* Returns: none.
|
|
* Side effects:
|
|
* Description:
|
|
* Exit "nicely" the application.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
static void exit_uart_app(int32_t exit_status)
|
|
{
|
|
if (opr_close_port() != true)
|
|
display_color_msg(FAIL, "ERROR: Port close failed.\n");
|
|
|
|
exit(exit_status);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function: display_color_msg
|
|
*
|
|
* Parameters:
|
|
* success - SUCCESS for successful message, FAIL for erroneous
|
|
* massage.
|
|
* fmt - Massage to dispaly (format and arguments).
|
|
*
|
|
* Returns: none
|
|
* Side effects: Using DISPLAY_MSG macro.
|
|
* Description:
|
|
* This routine displays a message using color attributes:
|
|
* In case of a successful message, use green foreground text on
|
|
* black background.
|
|
* In case of an erroneous message, use red foreground text on
|
|
* black background.
|
|
*---------------------------------------------------------------------------
|
|
*/
|
|
void display_color_msg(bool success, char *fmt, ...)
|
|
{
|
|
va_list argptr;
|
|
|
|
va_start(argptr, fmt);
|
|
vprintf(fmt, argptr);
|
|
va_end(argptr);
|
|
}
|