Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Extra Boot Config
0004  * Masami Hiramatsu <mhiramat@kernel.org>
0005  */
0006 
0007 #ifdef __KERNEL__
0008 #include <linux/bootconfig.h>
0009 #include <linux/bug.h>
0010 #include <linux/ctype.h>
0011 #include <linux/errno.h>
0012 #include <linux/kernel.h>
0013 #include <linux/memblock.h>
0014 #include <linux/string.h>
0015 
0016 #ifdef CONFIG_BOOT_CONFIG_EMBED
0017 /* embedded_bootconfig_data is defined in bootconfig-data.S */
0018 extern __visible const char embedded_bootconfig_data[];
0019 extern __visible const char embedded_bootconfig_data_end[];
0020 
0021 const char * __init xbc_get_embedded_bootconfig(size_t *size)
0022 {
0023     *size = embedded_bootconfig_data_end - embedded_bootconfig_data;
0024     return (*size) ? embedded_bootconfig_data : NULL;
0025 }
0026 #endif
0027 
0028 #else /* !__KERNEL__ */
0029 /*
0030  * NOTE: This is only for tools/bootconfig, because tools/bootconfig will
0031  * run the parser sanity test.
0032  * This does NOT mean lib/bootconfig.c is available in the user space.
0033  * However, if you change this file, please make sure the tools/bootconfig
0034  * has no issue on building and running.
0035  */
0036 #include <linux/bootconfig.h>
0037 #endif
0038 
0039 /*
0040  * Extra Boot Config (XBC) is given as tree-structured ascii text of
0041  * key-value pairs on memory.
0042  * xbc_parse() parses the text to build a simple tree. Each tree node is
0043  * simply a key word or a value. A key node may have a next key node or/and
0044  * a child node (both key and value). A value node may have a next value
0045  * node (for array).
0046  */
0047 
0048 static struct xbc_node *xbc_nodes __initdata;
0049 static int xbc_node_num __initdata;
0050 static char *xbc_data __initdata;
0051 static size_t xbc_data_size __initdata;
0052 static struct xbc_node *last_parent __initdata;
0053 static const char *xbc_err_msg __initdata;
0054 static int xbc_err_pos __initdata;
0055 static int open_brace[XBC_DEPTH_MAX] __initdata;
0056 static int brace_index __initdata;
0057 
0058 #ifdef __KERNEL__
0059 static inline void * __init xbc_alloc_mem(size_t size)
0060 {
0061     return memblock_alloc(size, SMP_CACHE_BYTES);
0062 }
0063 
0064 static inline void __init xbc_free_mem(void *addr, size_t size)
0065 {
0066     memblock_free(addr, size);
0067 }
0068 
0069 #else /* !__KERNEL__ */
0070 
0071 static inline void *xbc_alloc_mem(size_t size)
0072 {
0073     return malloc(size);
0074 }
0075 
0076 static inline void xbc_free_mem(void *addr, size_t size)
0077 {
0078     free(addr);
0079 }
0080 #endif
0081 /**
0082  * xbc_get_info() - Get the information of loaded boot config
0083  * @node_size: A pointer to store the number of nodes.
0084  * @data_size: A pointer to store the size of bootconfig data.
0085  *
0086  * Get the number of used nodes in @node_size if it is not NULL,
0087  * and the size of bootconfig data in @data_size if it is not NULL.
0088  * Return 0 if the boot config is initialized, or return -ENODEV.
0089  */
0090 int __init xbc_get_info(int *node_size, size_t *data_size)
0091 {
0092     if (!xbc_data)
0093         return -ENODEV;
0094 
0095     if (node_size)
0096         *node_size = xbc_node_num;
0097     if (data_size)
0098         *data_size = xbc_data_size;
0099     return 0;
0100 }
0101 
0102 static int __init xbc_parse_error(const char *msg, const char *p)
0103 {
0104     xbc_err_msg = msg;
0105     xbc_err_pos = (int)(p - xbc_data);
0106 
0107     return -EINVAL;
0108 }
0109 
0110 /**
0111  * xbc_root_node() - Get the root node of extended boot config
0112  *
0113  * Return the address of root node of extended boot config. If the
0114  * extended boot config is not initiized, return NULL.
0115  */
0116 struct xbc_node * __init xbc_root_node(void)
0117 {
0118     if (unlikely(!xbc_data))
0119         return NULL;
0120 
0121     return xbc_nodes;
0122 }
0123 
0124 /**
0125  * xbc_node_index() - Get the index of XBC node
0126  * @node: A target node of getting index.
0127  *
0128  * Return the index number of @node in XBC node list.
0129  */
0130 int __init xbc_node_index(struct xbc_node *node)
0131 {
0132     return node - &xbc_nodes[0];
0133 }
0134 
0135 /**
0136  * xbc_node_get_parent() - Get the parent XBC node
0137  * @node: An XBC node.
0138  *
0139  * Return the parent node of @node. If the node is top node of the tree,
0140  * return NULL.
0141  */
0142 struct xbc_node * __init xbc_node_get_parent(struct xbc_node *node)
0143 {
0144     return node->parent == XBC_NODE_MAX ? NULL : &xbc_nodes[node->parent];
0145 }
0146 
0147 /**
0148  * xbc_node_get_child() - Get the child XBC node
0149  * @node: An XBC node.
0150  *
0151  * Return the first child node of @node. If the node has no child, return
0152  * NULL.
0153  */
0154 struct xbc_node * __init xbc_node_get_child(struct xbc_node *node)
0155 {
0156     return node->child ? &xbc_nodes[node->child] : NULL;
0157 }
0158 
0159 /**
0160  * xbc_node_get_next() - Get the next sibling XBC node
0161  * @node: An XBC node.
0162  *
0163  * Return the NEXT sibling node of @node. If the node has no next sibling,
0164  * return NULL. Note that even if this returns NULL, it doesn't mean @node
0165  * has no siblings. (You also has to check whether the parent's child node
0166  * is @node or not.)
0167  */
0168 struct xbc_node * __init xbc_node_get_next(struct xbc_node *node)
0169 {
0170     return node->next ? &xbc_nodes[node->next] : NULL;
0171 }
0172 
0173 /**
0174  * xbc_node_get_data() - Get the data of XBC node
0175  * @node: An XBC node.
0176  *
0177  * Return the data (which is always a null terminated string) of @node.
0178  * If the node has invalid data, warn and return NULL.
0179  */
0180 const char * __init xbc_node_get_data(struct xbc_node *node)
0181 {
0182     int offset = node->data & ~XBC_VALUE;
0183 
0184     if (WARN_ON(offset >= xbc_data_size))
0185         return NULL;
0186 
0187     return xbc_data + offset;
0188 }
0189 
0190 static bool __init
0191 xbc_node_match_prefix(struct xbc_node *node, const char **prefix)
0192 {
0193     const char *p = xbc_node_get_data(node);
0194     int len = strlen(p);
0195 
0196     if (strncmp(*prefix, p, len))
0197         return false;
0198 
0199     p = *prefix + len;
0200     if (*p == '.')
0201         p++;
0202     else if (*p != '\0')
0203         return false;
0204     *prefix = p;
0205 
0206     return true;
0207 }
0208 
0209 /**
0210  * xbc_node_find_subkey() - Find a subkey node which matches given key
0211  * @parent: An XBC node.
0212  * @key: A key string.
0213  *
0214  * Search a key node under @parent which matches @key. The @key can contain
0215  * several words jointed with '.'. If @parent is NULL, this searches the
0216  * node from whole tree. Return NULL if no node is matched.
0217  */
0218 struct xbc_node * __init
0219 xbc_node_find_subkey(struct xbc_node *parent, const char *key)
0220 {
0221     struct xbc_node *node;
0222 
0223     if (parent)
0224         node = xbc_node_get_subkey(parent);
0225     else
0226         node = xbc_root_node();
0227 
0228     while (node && xbc_node_is_key(node)) {
0229         if (!xbc_node_match_prefix(node, &key))
0230             node = xbc_node_get_next(node);
0231         else if (*key != '\0')
0232             node = xbc_node_get_subkey(node);
0233         else
0234             break;
0235     }
0236 
0237     return node;
0238 }
0239 
0240 /**
0241  * xbc_node_find_value() - Find a value node which matches given key
0242  * @parent: An XBC node.
0243  * @key: A key string.
0244  * @vnode: A container pointer of found XBC node.
0245  *
0246  * Search a value node under @parent whose (parent) key node matches @key,
0247  * store it in *@vnode, and returns the value string.
0248  * The @key can contain several words jointed with '.'. If @parent is NULL,
0249  * this searches the node from whole tree. Return the value string if a
0250  * matched key found, return NULL if no node is matched.
0251  * Note that this returns 0-length string and stores NULL in *@vnode if the
0252  * key has no value. And also it will return the value of the first entry if
0253  * the value is an array.
0254  */
0255 const char * __init
0256 xbc_node_find_value(struct xbc_node *parent, const char *key,
0257             struct xbc_node **vnode)
0258 {
0259     struct xbc_node *node = xbc_node_find_subkey(parent, key);
0260 
0261     if (!node || !xbc_node_is_key(node))
0262         return NULL;
0263 
0264     node = xbc_node_get_child(node);
0265     if (node && !xbc_node_is_value(node))
0266         return NULL;
0267 
0268     if (vnode)
0269         *vnode = node;
0270 
0271     return node ? xbc_node_get_data(node) : "";
0272 }
0273 
0274 /**
0275  * xbc_node_compose_key_after() - Compose partial key string of the XBC node
0276  * @root: Root XBC node
0277  * @node: Target XBC node.
0278  * @buf: A buffer to store the key.
0279  * @size: The size of the @buf.
0280  *
0281  * Compose the partial key of the @node into @buf, which is starting right
0282  * after @root (@root is not included.) If @root is NULL, this returns full
0283  * key words of @node.
0284  * Returns the total length of the key stored in @buf. Returns -EINVAL
0285  * if @node is NULL or @root is not the ancestor of @node or @root is @node,
0286  * or returns -ERANGE if the key depth is deeper than max depth.
0287  * This is expected to be used with xbc_find_node() to list up all (child)
0288  * keys under given key.
0289  */
0290 int __init xbc_node_compose_key_after(struct xbc_node *root,
0291                       struct xbc_node *node,
0292                       char *buf, size_t size)
0293 {
0294     uint16_t keys[XBC_DEPTH_MAX];
0295     int depth = 0, ret = 0, total = 0;
0296 
0297     if (!node || node == root)
0298         return -EINVAL;
0299 
0300     if (xbc_node_is_value(node))
0301         node = xbc_node_get_parent(node);
0302 
0303     while (node && node != root) {
0304         keys[depth++] = xbc_node_index(node);
0305         if (depth == XBC_DEPTH_MAX)
0306             return -ERANGE;
0307         node = xbc_node_get_parent(node);
0308     }
0309     if (!node && root)
0310         return -EINVAL;
0311 
0312     while (--depth >= 0) {
0313         node = xbc_nodes + keys[depth];
0314         ret = snprintf(buf, size, "%s%s", xbc_node_get_data(node),
0315                    depth ? "." : "");
0316         if (ret < 0)
0317             return ret;
0318         if (ret > size) {
0319             size = 0;
0320         } else {
0321             size -= ret;
0322             buf += ret;
0323         }
0324         total += ret;
0325     }
0326 
0327     return total;
0328 }
0329 
0330 /**
0331  * xbc_node_find_next_leaf() - Find the next leaf node under given node
0332  * @root: An XBC root node
0333  * @node: An XBC node which starts from.
0334  *
0335  * Search the next leaf node (which means the terminal key node) of @node
0336  * under @root node (including @root node itself).
0337  * Return the next node or NULL if next leaf node is not found.
0338  */
0339 struct xbc_node * __init xbc_node_find_next_leaf(struct xbc_node *root,
0340                          struct xbc_node *node)
0341 {
0342     struct xbc_node *next;
0343 
0344     if (unlikely(!xbc_data))
0345         return NULL;
0346 
0347     if (!node) {    /* First try */
0348         node = root;
0349         if (!node)
0350             node = xbc_nodes;
0351     } else {
0352         /* Leaf node may have a subkey */
0353         next = xbc_node_get_subkey(node);
0354         if (next) {
0355             node = next;
0356             goto found;
0357         }
0358 
0359         if (node == root)   /* @root was a leaf, no child node. */
0360             return NULL;
0361 
0362         while (!node->next) {
0363             node = xbc_node_get_parent(node);
0364             if (node == root)
0365                 return NULL;
0366             /* User passed a node which is not uder parent */
0367             if (WARN_ON(!node))
0368                 return NULL;
0369         }
0370         node = xbc_node_get_next(node);
0371     }
0372 
0373 found:
0374     while (node && !xbc_node_is_leaf(node))
0375         node = xbc_node_get_child(node);
0376 
0377     return node;
0378 }
0379 
0380 /**
0381  * xbc_node_find_next_key_value() - Find the next key-value pair nodes
0382  * @root: An XBC root node
0383  * @leaf: A container pointer of XBC node which starts from.
0384  *
0385  * Search the next leaf node (which means the terminal key node) of *@leaf
0386  * under @root node. Returns the value and update *@leaf if next leaf node
0387  * is found, or NULL if no next leaf node is found.
0388  * Note that this returns 0-length string if the key has no value, or
0389  * the value of the first entry if the value is an array.
0390  */
0391 const char * __init xbc_node_find_next_key_value(struct xbc_node *root,
0392                          struct xbc_node **leaf)
0393 {
0394     /* tip must be passed */
0395     if (WARN_ON(!leaf))
0396         return NULL;
0397 
0398     *leaf = xbc_node_find_next_leaf(root, *leaf);
0399     if (!*leaf)
0400         return NULL;
0401     if ((*leaf)->child)
0402         return xbc_node_get_data(xbc_node_get_child(*leaf));
0403     else
0404         return "";  /* No value key */
0405 }
0406 
0407 /* XBC parse and tree build */
0408 
0409 static int __init xbc_init_node(struct xbc_node *node, char *data, uint32_t flag)
0410 {
0411     unsigned long offset = data - xbc_data;
0412 
0413     if (WARN_ON(offset >= XBC_DATA_MAX))
0414         return -EINVAL;
0415 
0416     node->data = (uint16_t)offset | flag;
0417     node->child = 0;
0418     node->next = 0;
0419 
0420     return 0;
0421 }
0422 
0423 static struct xbc_node * __init xbc_add_node(char *data, uint32_t flag)
0424 {
0425     struct xbc_node *node;
0426 
0427     if (xbc_node_num == XBC_NODE_MAX)
0428         return NULL;
0429 
0430     node = &xbc_nodes[xbc_node_num++];
0431     if (xbc_init_node(node, data, flag) < 0)
0432         return NULL;
0433 
0434     return node;
0435 }
0436 
0437 static inline __init struct xbc_node *xbc_last_sibling(struct xbc_node *node)
0438 {
0439     while (node->next)
0440         node = xbc_node_get_next(node);
0441 
0442     return node;
0443 }
0444 
0445 static inline __init struct xbc_node *xbc_last_child(struct xbc_node *node)
0446 {
0447     while (node->child)
0448         node = xbc_node_get_child(node);
0449 
0450     return node;
0451 }
0452 
0453 static struct xbc_node * __init __xbc_add_sibling(char *data, uint32_t flag, bool head)
0454 {
0455     struct xbc_node *sib, *node = xbc_add_node(data, flag);
0456 
0457     if (node) {
0458         if (!last_parent) {
0459             /* Ignore @head in this case */
0460             node->parent = XBC_NODE_MAX;
0461             sib = xbc_last_sibling(xbc_nodes);
0462             sib->next = xbc_node_index(node);
0463         } else {
0464             node->parent = xbc_node_index(last_parent);
0465             if (!last_parent->child || head) {
0466                 node->next = last_parent->child;
0467                 last_parent->child = xbc_node_index(node);
0468             } else {
0469                 sib = xbc_node_get_child(last_parent);
0470                 sib = xbc_last_sibling(sib);
0471                 sib->next = xbc_node_index(node);
0472             }
0473         }
0474     } else
0475         xbc_parse_error("Too many nodes", data);
0476 
0477     return node;
0478 }
0479 
0480 static inline struct xbc_node * __init xbc_add_sibling(char *data, uint32_t flag)
0481 {
0482     return __xbc_add_sibling(data, flag, false);
0483 }
0484 
0485 static inline struct xbc_node * __init xbc_add_head_sibling(char *data, uint32_t flag)
0486 {
0487     return __xbc_add_sibling(data, flag, true);
0488 }
0489 
0490 static inline __init struct xbc_node *xbc_add_child(char *data, uint32_t flag)
0491 {
0492     struct xbc_node *node = xbc_add_sibling(data, flag);
0493 
0494     if (node)
0495         last_parent = node;
0496 
0497     return node;
0498 }
0499 
0500 static inline __init bool xbc_valid_keyword(char *key)
0501 {
0502     if (key[0] == '\0')
0503         return false;
0504 
0505     while (isalnum(*key) || *key == '-' || *key == '_')
0506         key++;
0507 
0508     return *key == '\0';
0509 }
0510 
0511 static char *skip_comment(char *p)
0512 {
0513     char *ret;
0514 
0515     ret = strchr(p, '\n');
0516     if (!ret)
0517         ret = p + strlen(p);
0518     else
0519         ret++;
0520 
0521     return ret;
0522 }
0523 
0524 static char *skip_spaces_until_newline(char *p)
0525 {
0526     while (isspace(*p) && *p != '\n')
0527         p++;
0528     return p;
0529 }
0530 
0531 static int __init __xbc_open_brace(char *p)
0532 {
0533     /* Push the last key as open brace */
0534     open_brace[brace_index++] = xbc_node_index(last_parent);
0535     if (brace_index >= XBC_DEPTH_MAX)
0536         return xbc_parse_error("Exceed max depth of braces", p);
0537 
0538     return 0;
0539 }
0540 
0541 static int __init __xbc_close_brace(char *p)
0542 {
0543     brace_index--;
0544     if (!last_parent || brace_index < 0 ||
0545         (open_brace[brace_index] != xbc_node_index(last_parent)))
0546         return xbc_parse_error("Unexpected closing brace", p);
0547 
0548     if (brace_index == 0)
0549         last_parent = NULL;
0550     else
0551         last_parent = &xbc_nodes[open_brace[brace_index - 1]];
0552 
0553     return 0;
0554 }
0555 
0556 /*
0557  * Return delimiter or error, no node added. As same as lib/cmdline.c,
0558  * you can use " around spaces, but can't escape " for value.
0559  */
0560 static int __init __xbc_parse_value(char **__v, char **__n)
0561 {
0562     char *p, *v = *__v;
0563     int c, quotes = 0;
0564 
0565     v = skip_spaces(v);
0566     while (*v == '#') {
0567         v = skip_comment(v);
0568         v = skip_spaces(v);
0569     }
0570     if (*v == '"' || *v == '\'') {
0571         quotes = *v;
0572         v++;
0573     }
0574     p = v - 1;
0575     while ((c = *++p)) {
0576         if (!isprint(c) && !isspace(c))
0577             return xbc_parse_error("Non printable value", p);
0578         if (quotes) {
0579             if (c != quotes)
0580                 continue;
0581             quotes = 0;
0582             *p++ = '\0';
0583             p = skip_spaces_until_newline(p);
0584             c = *p;
0585             if (c && !strchr(",;\n#}", c))
0586                 return xbc_parse_error("No value delimiter", p);
0587             if (*p)
0588                 p++;
0589             break;
0590         }
0591         if (strchr(",;\n#}", c)) {
0592             *p++ = '\0';
0593             v = strim(v);
0594             break;
0595         }
0596     }
0597     if (quotes)
0598         return xbc_parse_error("No closing quotes", p);
0599     if (c == '#') {
0600         p = skip_comment(p);
0601         c = '\n';   /* A comment must be treated as a newline */
0602     }
0603     *__n = p;
0604     *__v = v;
0605 
0606     return c;
0607 }
0608 
0609 static int __init xbc_parse_array(char **__v)
0610 {
0611     struct xbc_node *node;
0612     char *next;
0613     int c = 0;
0614 
0615     if (last_parent->child)
0616         last_parent = xbc_node_get_child(last_parent);
0617 
0618     do {
0619         c = __xbc_parse_value(__v, &next);
0620         if (c < 0)
0621             return c;
0622 
0623         node = xbc_add_child(*__v, XBC_VALUE);
0624         if (!node)
0625             return -ENOMEM;
0626         *__v = next;
0627     } while (c == ',');
0628     node->child = 0;
0629 
0630     return c;
0631 }
0632 
0633 static inline __init
0634 struct xbc_node *find_match_node(struct xbc_node *node, char *k)
0635 {
0636     while (node) {
0637         if (!strcmp(xbc_node_get_data(node), k))
0638             break;
0639         node = xbc_node_get_next(node);
0640     }
0641     return node;
0642 }
0643 
0644 static int __init __xbc_add_key(char *k)
0645 {
0646     struct xbc_node *node, *child;
0647 
0648     if (!xbc_valid_keyword(k))
0649         return xbc_parse_error("Invalid keyword", k);
0650 
0651     if (unlikely(xbc_node_num == 0))
0652         goto add_node;
0653 
0654     if (!last_parent)   /* the first level */
0655         node = find_match_node(xbc_nodes, k);
0656     else {
0657         child = xbc_node_get_child(last_parent);
0658         /* Since the value node is the first child, skip it. */
0659         if (child && xbc_node_is_value(child))
0660             child = xbc_node_get_next(child);
0661         node = find_match_node(child, k);
0662     }
0663 
0664     if (node)
0665         last_parent = node;
0666     else {
0667 add_node:
0668         node = xbc_add_child(k, XBC_KEY);
0669         if (!node)
0670             return -ENOMEM;
0671     }
0672     return 0;
0673 }
0674 
0675 static int __init __xbc_parse_keys(char *k)
0676 {
0677     char *p;
0678     int ret;
0679 
0680     k = strim(k);
0681     while ((p = strchr(k, '.'))) {
0682         *p++ = '\0';
0683         ret = __xbc_add_key(k);
0684         if (ret)
0685             return ret;
0686         k = p;
0687     }
0688 
0689     return __xbc_add_key(k);
0690 }
0691 
0692 static int __init xbc_parse_kv(char **k, char *v, int op)
0693 {
0694     struct xbc_node *prev_parent = last_parent;
0695     struct xbc_node *child;
0696     char *next;
0697     int c, ret;
0698 
0699     ret = __xbc_parse_keys(*k);
0700     if (ret)
0701         return ret;
0702 
0703     c = __xbc_parse_value(&v, &next);
0704     if (c < 0)
0705         return c;
0706 
0707     child = xbc_node_get_child(last_parent);
0708     if (child && xbc_node_is_value(child)) {
0709         if (op == '=')
0710             return xbc_parse_error("Value is redefined", v);
0711         if (op == ':') {
0712             unsigned short nidx = child->next;
0713 
0714             xbc_init_node(child, v, XBC_VALUE);
0715             child->next = nidx; /* keep subkeys */
0716             goto array;
0717         }
0718         /* op must be '+' */
0719         last_parent = xbc_last_child(child);
0720     }
0721     /* The value node should always be the first child */
0722     if (!xbc_add_head_sibling(v, XBC_VALUE))
0723         return -ENOMEM;
0724 
0725 array:
0726     if (c == ',') { /* Array */
0727         c = xbc_parse_array(&next);
0728         if (c < 0)
0729             return c;
0730     }
0731 
0732     last_parent = prev_parent;
0733 
0734     if (c == '}') {
0735         ret = __xbc_close_brace(next - 1);
0736         if (ret < 0)
0737             return ret;
0738     }
0739 
0740     *k = next;
0741 
0742     return 0;
0743 }
0744 
0745 static int __init xbc_parse_key(char **k, char *n)
0746 {
0747     struct xbc_node *prev_parent = last_parent;
0748     int ret;
0749 
0750     *k = strim(*k);
0751     if (**k != '\0') {
0752         ret = __xbc_parse_keys(*k);
0753         if (ret)
0754             return ret;
0755         last_parent = prev_parent;
0756     }
0757     *k = n;
0758 
0759     return 0;
0760 }
0761 
0762 static int __init xbc_open_brace(char **k, char *n)
0763 {
0764     int ret;
0765 
0766     ret = __xbc_parse_keys(*k);
0767     if (ret)
0768         return ret;
0769     *k = n;
0770 
0771     return __xbc_open_brace(n - 1);
0772 }
0773 
0774 static int __init xbc_close_brace(char **k, char *n)
0775 {
0776     int ret;
0777 
0778     ret = xbc_parse_key(k, n);
0779     if (ret)
0780         return ret;
0781     /* k is updated in xbc_parse_key() */
0782 
0783     return __xbc_close_brace(n - 1);
0784 }
0785 
0786 static int __init xbc_verify_tree(void)
0787 {
0788     int i, depth, len, wlen;
0789     struct xbc_node *n, *m;
0790 
0791     /* Brace closing */
0792     if (brace_index) {
0793         n = &xbc_nodes[open_brace[brace_index]];
0794         return xbc_parse_error("Brace is not closed",
0795                     xbc_node_get_data(n));
0796     }
0797 
0798     /* Empty tree */
0799     if (xbc_node_num == 0) {
0800         xbc_parse_error("Empty config", xbc_data);
0801         return -ENOENT;
0802     }
0803 
0804     for (i = 0; i < xbc_node_num; i++) {
0805         if (xbc_nodes[i].next > xbc_node_num) {
0806             return xbc_parse_error("No closing brace",
0807                 xbc_node_get_data(xbc_nodes + i));
0808         }
0809     }
0810 
0811     /* Key tree limitation check */
0812     n = &xbc_nodes[0];
0813     depth = 1;
0814     len = 0;
0815 
0816     while (n) {
0817         wlen = strlen(xbc_node_get_data(n)) + 1;
0818         len += wlen;
0819         if (len > XBC_KEYLEN_MAX)
0820             return xbc_parse_error("Too long key length",
0821                 xbc_node_get_data(n));
0822 
0823         m = xbc_node_get_child(n);
0824         if (m && xbc_node_is_key(m)) {
0825             n = m;
0826             depth++;
0827             if (depth > XBC_DEPTH_MAX)
0828                 return xbc_parse_error("Too many key words",
0829                         xbc_node_get_data(n));
0830             continue;
0831         }
0832         len -= wlen;
0833         m = xbc_node_get_next(n);
0834         while (!m) {
0835             n = xbc_node_get_parent(n);
0836             if (!n)
0837                 break;
0838             len -= strlen(xbc_node_get_data(n)) + 1;
0839             depth--;
0840             m = xbc_node_get_next(n);
0841         }
0842         n = m;
0843     }
0844 
0845     return 0;
0846 }
0847 
0848 /* Need to setup xbc_data and xbc_nodes before call this. */
0849 static int __init xbc_parse_tree(void)
0850 {
0851     char *p, *q;
0852     int ret = 0, c;
0853 
0854     last_parent = NULL;
0855     p = xbc_data;
0856     do {
0857         q = strpbrk(p, "{}=+;:\n#");
0858         if (!q) {
0859             p = skip_spaces(p);
0860             if (*p != '\0')
0861                 ret = xbc_parse_error("No delimiter", p);
0862             break;
0863         }
0864 
0865         c = *q;
0866         *q++ = '\0';
0867         switch (c) {
0868         case ':':
0869         case '+':
0870             if (*q++ != '=') {
0871                 ret = xbc_parse_error(c == '+' ?
0872                         "Wrong '+' operator" :
0873                         "Wrong ':' operator",
0874                             q - 2);
0875                 break;
0876             }
0877             fallthrough;
0878         case '=':
0879             ret = xbc_parse_kv(&p, q, c);
0880             break;
0881         case '{':
0882             ret = xbc_open_brace(&p, q);
0883             break;
0884         case '#':
0885             q = skip_comment(q);
0886             fallthrough;
0887         case ';':
0888         case '\n':
0889             ret = xbc_parse_key(&p, q);
0890             break;
0891         case '}':
0892             ret = xbc_close_brace(&p, q);
0893             break;
0894         }
0895     } while (!ret);
0896 
0897     return ret;
0898 }
0899 
0900 /**
0901  * xbc_exit() - Clean up all parsed bootconfig
0902  *
0903  * This clears all data structures of parsed bootconfig on memory.
0904  * If you need to reuse xbc_init() with new boot config, you can
0905  * use this.
0906  */
0907 void __init xbc_exit(void)
0908 {
0909     xbc_free_mem(xbc_data, xbc_data_size);
0910     xbc_data = NULL;
0911     xbc_data_size = 0;
0912     xbc_node_num = 0;
0913     xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
0914     xbc_nodes = NULL;
0915     brace_index = 0;
0916 }
0917 
0918 /**
0919  * xbc_init() - Parse given XBC file and build XBC internal tree
0920  * @data: The boot config text original data
0921  * @size: The size of @data
0922  * @emsg: A pointer of const char * to store the error message
0923  * @epos: A pointer of int to store the error position
0924  *
0925  * This parses the boot config text in @data. @size must be smaller
0926  * than XBC_DATA_MAX.
0927  * Return the number of stored nodes (>0) if succeeded, or -errno
0928  * if there is any error.
0929  * In error cases, @emsg will be updated with an error message and
0930  * @epos will be updated with the error position which is the byte offset
0931  * of @buf. If the error is not a parser error, @epos will be -1.
0932  */
0933 int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
0934 {
0935     int ret;
0936 
0937     if (epos)
0938         *epos = -1;
0939 
0940     if (xbc_data) {
0941         if (emsg)
0942             *emsg = "Bootconfig is already initialized";
0943         return -EBUSY;
0944     }
0945     if (size > XBC_DATA_MAX || size == 0) {
0946         if (emsg)
0947             *emsg = size ? "Config data is too big" :
0948                 "Config data is empty";
0949         return -ERANGE;
0950     }
0951 
0952     xbc_data = xbc_alloc_mem(size + 1);
0953     if (!xbc_data) {
0954         if (emsg)
0955             *emsg = "Failed to allocate bootconfig data";
0956         return -ENOMEM;
0957     }
0958     memcpy(xbc_data, data, size);
0959     xbc_data[size] = '\0';
0960     xbc_data_size = size + 1;
0961 
0962     xbc_nodes = xbc_alloc_mem(sizeof(struct xbc_node) * XBC_NODE_MAX);
0963     if (!xbc_nodes) {
0964         if (emsg)
0965             *emsg = "Failed to allocate bootconfig nodes";
0966         xbc_exit();
0967         return -ENOMEM;
0968     }
0969     memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX);
0970 
0971     ret = xbc_parse_tree();
0972     if (!ret)
0973         ret = xbc_verify_tree();
0974 
0975     if (ret < 0) {
0976         if (epos)
0977             *epos = xbc_err_pos;
0978         if (emsg)
0979             *emsg = xbc_err_msg;
0980         xbc_exit();
0981     } else
0982         ret = xbc_node_num;
0983 
0984     return ret;
0985 }