arm64: use __vmalloc_node in arch_alloc_vmap_stack
[linux-2.6-microblaze.git] / lib / bootconfig.c
index ec3ce7f..912ef49 100644 (file)
@@ -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;