diff options
Diffstat (limited to 'lib/bootconfig.c')
| -rw-r--r-- | lib/bootconfig.c | 35 | 
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/bootconfig.c b/lib/bootconfig.c index ec3ce7fd299f..912ef4921398 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -29,12 +29,14 @@ static int xbc_node_num __initdata;  static char *xbc_data __initdata;  static size_t xbc_data_size __initdata;  static struct xbc_node *last_parent __initdata; +static const char *xbc_err_msg __initdata; +static int xbc_err_pos __initdata;  static int __init xbc_parse_error(const char *msg, const char *p)  { -	int pos = p - xbc_data; +	xbc_err_msg = msg; +	xbc_err_pos = (int)(p - xbc_data); -	pr_err("Parse error at pos %d: %s\n", pos, msg);  	return -EINVAL;  } @@ -738,33 +740,44 @@ void __init xbc_destroy_all(void)  /**   * xbc_init() - Parse given XBC file and build XBC internal tree   * @buf: boot config text + * @emsg: A pointer of const char * to store the error message + * @epos: A pointer of int to store the error position   *   * This parses the boot config text in @buf. @buf must be a   * null terminated string and smaller than XBC_DATA_MAX.   * Return the number of stored nodes (>0) if succeeded, or -errno   * if there is any error. + * In error cases, @emsg will be updated with an error message and + * @epos will be updated with the error position which is the byte offset + * of @buf. If the error is not a parser error, @epos will be -1.   */ -int __init xbc_init(char *buf) +int __init xbc_init(char *buf, const char **emsg, int *epos)  {  	char *p, *q;  	int ret, c; +	if (epos) +		*epos = -1; +  	if (xbc_data) { -		pr_err("Error: bootconfig is already initialized.\n"); +		if (emsg) +			*emsg = "Bootconfig is already initialized";  		return -EBUSY;  	}  	ret = strlen(buf);  	if (ret > XBC_DATA_MAX - 1 || ret == 0) { -		pr_err("Error: Config data is %s.\n", -			ret ? "too big" : "empty"); +		if (emsg) +			*emsg = ret ? "Config data is too big" : +				"Config data is empty";  		return -ERANGE;  	}  	xbc_nodes = memblock_alloc(sizeof(struct xbc_node) * XBC_NODE_MAX,  				   SMP_CACHE_BYTES);  	if (!xbc_nodes) { -		pr_err("Failed to allocate memory for bootconfig nodes.\n"); +		if (emsg) +			*emsg = "Failed to allocate bootconfig nodes";  		return -ENOMEM;  	}  	memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX); @@ -814,9 +827,13 @@ int __init xbc_init(char *buf)  	if (!ret)  		ret = xbc_verify_tree(); -	if (ret < 0) +	if (ret < 0) { +		if (epos) +			*epos = xbc_err_pos; +		if (emsg) +			*emsg = xbc_err_msg;  		xbc_destroy_all(); -	else +	} else  		ret = xbc_node_num;  	return ret;  |