Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tools/bootconfig: Show line and column in parse error

Show line and column when we got a parse error in bootconfig tool.
Current lib/bootconfig shows the parse error with byte offset, but
that is not human readable.
This makes xbc_init() not showing error message itself but able to
pass the error message and position to caller, so that the caller
can decode it and show the error message with line number and columns.

With this patch, bootconfig tool shows an error with line:column as
below.

$ cat samples/bad-dotword.bconf
# do not start keyword with .
key {
.word = 1
}
$ ./bootconfig -a samples/bad-dotword.bconf initrd
Parse Error: Invalid keyword at 3:3

Link: http://lkml.kernel.org/r/158323469002.10560.4023923847704522760.stgit@devnote2

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Masami Hiramatsu and committed by
Steven Rostedt (VMware)
89b74cac 306b69dc

+69 -18
+2 -1
include/linux/bootconfig.h
··· 216 216 } 217 217 218 218 /* XBC node initializer */ 219 - int __init xbc_init(char *buf); 219 + int __init xbc_init(char *buf, const char **emsg, int *epos); 220 + 220 221 221 222 /* XBC cleanup data structures */ 222 223 void __init xbc_destroy_all(void);
+10 -4
init/main.c
··· 353 353 static void __init setup_boot_config(const char *cmdline) 354 354 { 355 355 static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; 356 + const char *msg; 357 + int pos; 356 358 u32 size, csum; 357 359 char *data, *copy; 358 360 u32 *hdr; ··· 402 400 memcpy(copy, data, size); 403 401 copy[size] = '\0'; 404 402 405 - ret = xbc_init(copy); 406 - if (ret < 0) 407 - pr_err("Failed to parse bootconfig\n"); 408 - else { 403 + ret = xbc_init(copy, &msg, &pos); 404 + if (ret < 0) { 405 + if (pos < 0) 406 + pr_err("Failed to init bootconfig: %s.\n", msg); 407 + else 408 + pr_err("Failed to parse bootconfig: %s at %d.\n", 409 + msg, pos); 410 + } else { 409 411 pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret); 410 412 /* keys starting with "kernel." are passed via cmdline */ 411 413 extra_command_line = xbc_make_cmdline("kernel");
+26 -9
lib/bootconfig.c
··· 29 29 static char *xbc_data __initdata; 30 30 static size_t xbc_data_size __initdata; 31 31 static struct xbc_node *last_parent __initdata; 32 + static const char *xbc_err_msg __initdata; 33 + static int xbc_err_pos __initdata; 32 34 33 35 static int __init xbc_parse_error(const char *msg, const char *p) 34 36 { 35 - int pos = p - xbc_data; 37 + xbc_err_msg = msg; 38 + xbc_err_pos = (int)(p - xbc_data); 36 39 37 - pr_err("Parse error at pos %d: %s\n", pos, msg); 38 40 return -EINVAL; 39 41 } 40 42 ··· 740 738 /** 741 739 * xbc_init() - Parse given XBC file and build XBC internal tree 742 740 * @buf: boot config text 741 + * @emsg: A pointer of const char * to store the error message 742 + * @epos: A pointer of int to store the error position 743 743 * 744 744 * This parses the boot config text in @buf. @buf must be a 745 745 * null terminated string and smaller than XBC_DATA_MAX. 746 746 * Return the number of stored nodes (>0) if succeeded, or -errno 747 747 * if there is any error. 748 + * In error cases, @emsg will be updated with an error message and 749 + * @epos will be updated with the error position which is the byte offset 750 + * of @buf. If the error is not a parser error, @epos will be -1. 748 751 */ 749 - int __init xbc_init(char *buf) 752 + int __init xbc_init(char *buf, const char **emsg, int *epos) 750 753 { 751 754 char *p, *q; 752 755 int ret, c; 753 756 757 + if (epos) 758 + *epos = -1; 759 + 754 760 if (xbc_data) { 755 - pr_err("Error: bootconfig is already initialized.\n"); 761 + if (emsg) 762 + *emsg = "Bootconfig is already initialized"; 756 763 return -EBUSY; 757 764 } 758 765 759 766 ret = strlen(buf); 760 767 if (ret > XBC_DATA_MAX - 1 || ret == 0) { 761 - pr_err("Error: Config data is %s.\n", 762 - ret ? "too big" : "empty"); 768 + if (emsg) 769 + *emsg = ret ? "Config data is too big" : 770 + "Config data is empty"; 763 771 return -ERANGE; 764 772 } 765 773 766 774 xbc_nodes = memblock_alloc(sizeof(struct xbc_node) * XBC_NODE_MAX, 767 775 SMP_CACHE_BYTES); 768 776 if (!xbc_nodes) { 769 - pr_err("Failed to allocate memory for bootconfig nodes.\n"); 777 + if (emsg) 778 + *emsg = "Failed to allocate bootconfig nodes"; 770 779 return -ENOMEM; 771 780 } 772 781 memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX); ··· 827 814 if (!ret) 828 815 ret = xbc_verify_tree(); 829 816 830 - if (ret < 0) 817 + if (ret < 0) { 818 + if (epos) 819 + *epos = xbc_err_pos; 820 + if (emsg) 821 + *emsg = xbc_err_msg; 831 822 xbc_destroy_all(); 832 - else 823 + } else 833 824 ret = xbc_node_num; 834 825 835 826 return ret;
+31 -4
tools/bootconfig/main.c
··· 130 130 int ret; 131 131 u32 size = 0, csum = 0, rcsum; 132 132 char magic[BOOTCONFIG_MAGIC_LEN]; 133 + const char *msg; 133 134 134 135 ret = fstat(fd, &stat); 135 136 if (ret < 0) ··· 183 182 return -EINVAL; 184 183 } 185 184 186 - ret = xbc_init(*buf); 185 + ret = xbc_init(*buf, &msg, NULL); 187 186 /* Wrong data */ 188 - if (ret < 0) 187 + if (ret < 0) { 188 + pr_err("parse error: %s.\n", msg); 189 189 return ret; 190 + } 190 191 191 192 return size; 192 193 } ··· 247 244 return ret; 248 245 } 249 246 247 + static void show_xbc_error(const char *data, const char *msg, int pos) 248 + { 249 + int lin = 1, col, i; 250 + 251 + if (pos < 0) { 252 + pr_err("Error: %s.\n", msg); 253 + return; 254 + } 255 + 256 + /* Note that pos starts from 0 but lin and col should start from 1. */ 257 + col = pos + 1; 258 + for (i = 0; i < pos; i++) { 259 + if (data[i] == '\n') { 260 + lin++; 261 + col = pos - i; 262 + } 263 + } 264 + pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); 265 + 266 + } 267 + 250 268 int apply_xbc(const char *path, const char *xbc_path) 251 269 { 252 270 u32 size, csum; 253 271 char *buf, *data; 254 272 int ret, fd; 273 + const char *msg; 274 + int pos; 255 275 256 276 ret = load_xbc_file(xbc_path, &buf); 257 277 if (ret < 0) { ··· 293 267 *(u32 *)(data + size + 4) = csum; 294 268 295 269 /* Check the data format */ 296 - ret = xbc_init(buf); 270 + ret = xbc_init(buf, &msg, &pos); 297 271 if (ret < 0) { 298 - pr_err("Failed to parse %s: %d\n", xbc_path, ret); 272 + show_xbc_error(data, msg, pos); 299 273 free(data); 300 274 free(buf); 275 + 301 276 return ret; 302 277 } 303 278 printf("Apply %s to %s\n", xbc_path, path);