[U-Boot] [PATCH 14/17] tools: kwbimage: Refactor line parsing and fix error
Mario Six
mario.six at gdsys.cc
Wed Nov 23 16:12:32 CET 2016
The function image_create_config_parse_oneline is pretty complex, and
since more parameters will be added to support secure booting, we
refactor the function to make it more readable.
Also, when a line contained just a keyword without any parameters,
strtok_r returned NULL, which was then indiscriminately fed into atoi,
causing a segfault. To correct this, we add a NULL check before feeding
the extracted token to atoi, and print an error message in case the
token is NULL.
Signed-off-by: Mario Six <mario.six at gdsys.cc>
---
tools/kwbimage.c | 157 ++++++++++++++++++++++++++++++++++---------------------
1 file changed, 96 insertions(+), 61 deletions(-)
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 7ed5453..1bc0102 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -55,20 +55,39 @@ struct nand_ecc_mode nand_ecc_modes[] = {
#define BINARY_MAX_ARGS 8
/* In-memory representation of a line of the configuration file */
+
+enum image_cfg_type {
+ IMAGE_CFG_VERSION = 0x1,
+ IMAGE_CFG_BOOT_FROM,
+ IMAGE_CFG_DEST_ADDR,
+ IMAGE_CFG_EXEC_ADDR,
+ IMAGE_CFG_NAND_BLKSZ,
+ IMAGE_CFG_NAND_BADBLK_LOCATION,
+ IMAGE_CFG_NAND_ECC_MODE,
+ IMAGE_CFG_NAND_PAGESZ,
+ IMAGE_CFG_BINARY,
+ IMAGE_CFG_PAYLOAD,
+ IMAGE_CFG_DATA,
+
+ IMAGE_CFG_COUNT
+} type;
+
+static const char * const id_strs[] = {
+ [IMAGE_CFG_VERSION] = "VERSION",
+ [IMAGE_CFG_BOOT_FROM] = "BOOT_FROM",
+ [IMAGE_CFG_DEST_ADDR] = "DEST_ADDR",
+ [IMAGE_CFG_EXEC_ADDR] = "EXEC_ADDR",
+ [IMAGE_CFG_NAND_BLKSZ] = "NAND_BLKSZ",
+ [IMAGE_CFG_NAND_BADBLK_LOCATION] = "NAND_BADBLK_LOCATION",
+ [IMAGE_CFG_NAND_ECC_MODE] = "NAND_ECC_MODE",
+ [IMAGE_CFG_NAND_PAGESZ] = "NAND_PAGE_SIZE",
+ [IMAGE_CFG_BINARY] = "BINARY",
+ [IMAGE_CFG_PAYLOAD] = "PAYLOAD",
+ [IMAGE_CFG_DATA] = "DATA",
+};
+
struct image_cfg_element {
- enum {
- IMAGE_CFG_VERSION = 0x1,
- IMAGE_CFG_BOOT_FROM,
- IMAGE_CFG_DEST_ADDR,
- IMAGE_CFG_EXEC_ADDR,
- IMAGE_CFG_NAND_BLKSZ,
- IMAGE_CFG_NAND_BADBLK_LOCATION,
- IMAGE_CFG_NAND_ECC_MODE,
- IMAGE_CFG_NAND_PAGESZ,
- IMAGE_CFG_BINARY,
- IMAGE_CFG_PAYLOAD,
- IMAGE_CFG_DATA,
- } type;
+ enum image_cfg_type type;
union {
unsigned int version;
unsigned int bootfrom;
@@ -488,78 +507,94 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
return image;
}
+int recognize_keyword(char *keyword)
+{
+ int kw_id;
+
+ for (kw_id = 1; kw_id < IMAGE_CFG_COUNT; ++kw_id)
+ if (!strcmp(keyword, id_strs[kw_id]))
+ return kw_id;
+
+ return 0;
+}
+
static int image_create_config_parse_oneline(char *line,
struct image_cfg_element *el)
{
- char *keyword, *saveptr;
- char deliminiters[] = " \t";
+ char *keyword, *saveptr, *value1, *value2;
+ char delimiters[] = " \t";
+ int keyword_id, ret, argi;
+ char *unknown_msg = "Ignoring unknown line '%s'\n";
- keyword = strtok_r(line, deliminiters, &saveptr);
- if (!strcmp(keyword, "VERSION")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
+ keyword = strtok_r(line, delimiters, &saveptr);
+ keyword_id = recognize_keyword(keyword);
- el->type = IMAGE_CFG_VERSION;
- el->version = atoi(value);
- } else if (!strcmp(keyword, "BOOT_FROM")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
- int ret = image_boot_mode_id(value);
+ if (!keyword_id) {
+ fprintf(stderr, unknown_msg, line);
+ return 0;
+ }
+
+ el->type = keyword_id;
+
+ value1 = strtok_r(NULL, delimiters, &saveptr);
+
+ if (!value1) {
+ fprintf(stderr, "Parameter missing in line '%s'\n", line);
+ return -1;
+ }
+
+ switch (keyword_id) {
+ case IMAGE_CFG_VERSION:
+ el->version = atoi(value1);
+ break;
+ case IMAGE_CFG_BOOT_FROM:
+ ret = image_boot_mode_id(value1);
if (ret < 0) {
- fprintf(stderr,
- "Invalid boot media '%s'\n", value);
+ fprintf(stderr, "Invalid boot media '%s'\n", value1);
return -1;
}
- el->type = IMAGE_CFG_BOOT_FROM;
el->bootfrom = ret;
- } else if (!strcmp(keyword, "NAND_BLKSZ")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
-
- el->type = IMAGE_CFG_NAND_BLKSZ;
- el->nandblksz = strtoul(value, NULL, 16);
- } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
-
- el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
- el->nandbadblklocation =
- strtoul(value, NULL, 16);
- } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
- int ret = image_nand_ecc_mode_id(value);
+ break;
+ case IMAGE_CFG_NAND_BLKSZ:
+ el->nandblksz = strtoul(value1, NULL, 16);
+ break;
+ case IMAGE_CFG_NAND_BADBLK_LOCATION:
+ el->nandbadblklocation = strtoul(value1, NULL, 16);
+ break;
+ case IMAGE_CFG_NAND_ECC_MODE:
+ ret = image_nand_ecc_mode_id(value1);
if (ret < 0) {
- fprintf(stderr,
- "Invalid NAND ECC mode '%s'\n", value);
+ fprintf(stderr, "Invalid NAND ECC mode '%s'\n", value1);
return -1;
}
- el->type = IMAGE_CFG_NAND_ECC_MODE;
el->nandeccmode = ret;
- } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
-
- el->type = IMAGE_CFG_NAND_PAGESZ;
- el->nandpagesz = strtoul(value, NULL, 16);
- } else if (!strcmp(keyword, "BINARY")) {
- char *value = strtok_r(NULL, deliminiters, &saveptr);
- int argi = 0;
+ break;
+ case IMAGE_CFG_NAND_PAGESZ:
+ el->nandpagesz = strtoul(value1, NULL, 16);
+ break;
+ case IMAGE_CFG_BINARY:
+ argi = 0;
- el->type = IMAGE_CFG_BINARY;
- el->binary.file = strdup(value);
+ el->binary.file = strdup(value1);
while (1) {
- value = strtok_r(NULL, deliminiters, &saveptr);
+ char *value = strtok_r(NULL, delimiters, &saveptr);
+
if (!value)
break;
el->binary.args[argi] = strtoul(value, NULL, 16);
argi++;
if (argi >= BINARY_MAX_ARGS) {
fprintf(stderr,
- "Too many argument for binary\n");
+ "Too many arguments for BINARY\n");
return -1;
}
}
el->binary.nargs = argi;
- } else if (!strcmp(keyword, "DATA")) {
- char *value1 = strtok_r(NULL, deliminiters, &saveptr);
- char *value2 = strtok_r(NULL, deliminiters, &saveptr);
+ break;
+ case IMAGE_CFG_DATA:
+ value2 = strtok_r(NULL, delimiters, &saveptr);
if (!value1 || !value2) {
fprintf(stderr,
@@ -567,11 +602,11 @@ static int image_create_config_parse_oneline(char *line,
return -1;
}
- el->type = IMAGE_CFG_DATA;
el->regdata.raddr = strtoul(value1, NULL, 16);
el->regdata.rdata = strtoul(value2, NULL, 16);
- } else {
- fprintf(stderr, "Ignoring unknown line '%s'\n", line);
+ break;
+ default:
+ fprintf(stderr, unknown_msg, line);
}
return 0;
--
2.9.0
More information about the U-Boot
mailing list