VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   1) // SPDX-License-Identifier: GPL-2.0
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   2) /*
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   3)  * Extra Boot Config
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   4)  * Masami Hiramatsu <mhiramat@kernel.org>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   5)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   6) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   7) #define pr_fmt(fmt)    "bootconfig: " fmt
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900   8) 
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900   9) #include <linux/bootconfig.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  10) #include <linux/bug.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  11) #include <linux/ctype.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  12) #include <linux/errno.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  13) #include <linux/kernel.h>
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900  14) #include <linux/memblock.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  15) #include <linux/printk.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  16) #include <linux/string.h>
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  17) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  18) /*
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  19)  * Extra Boot Config (XBC) is given as tree-structured ascii text of
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  20)  * key-value pairs on memory.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  21)  * xbc_parse() parses the text to build a simple tree. Each tree node is
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  22)  * simply a key word or a value. A key node may have a next key node or/and
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  23)  * a child node (both key and value). A value node may have a next value
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  24)  * node (for array).
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  25)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  26) 
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900  27) static struct xbc_node *xbc_nodes __initdata;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  28) static int xbc_node_num __initdata;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  29) static char *xbc_data __initdata;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  30) static size_t xbc_data_size __initdata;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  31) static struct xbc_node *last_parent __initdata;
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900  32) static const char *xbc_err_msg __initdata;
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900  33) static int xbc_err_pos __initdata;
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900  34) static int open_brace[XBC_DEPTH_MAX] __initdata;
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900  35) static int brace_index __initdata;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  36) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  37) static int __init xbc_parse_error(const char *msg, const char *p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  38) {
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900  39) 	xbc_err_msg = msg;
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900  40) 	xbc_err_pos = (int)(p - xbc_data);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  41) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  42) 	return -EINVAL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  43) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  44) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  45) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  46)  * xbc_root_node() - Get the root node of extended boot config
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  47)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  48)  * Return the address of root node of extended boot config. If the
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  49)  * extended boot config is not initiized, return NULL.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  50)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  51) struct xbc_node * __init xbc_root_node(void)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  52) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  53) 	if (unlikely(!xbc_data))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  54) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  55) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  56) 	return xbc_nodes;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  57) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  58) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  59) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  60)  * xbc_node_index() - Get the index of XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  61)  * @node: A target node of getting index.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  62)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  63)  * Return the index number of @node in XBC node list.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  64)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  65) int __init xbc_node_index(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  66) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  67) 	return node - &xbc_nodes[0];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  68) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  69) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  70) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  71)  * xbc_node_get_parent() - Get the parent XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  72)  * @node: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  73)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  74)  * Return the parent node of @node. If the node is top node of the tree,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  75)  * return NULL.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  76)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  77) struct xbc_node * __init xbc_node_get_parent(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  78) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  79) 	return node->parent == XBC_NODE_MAX ? NULL : &xbc_nodes[node->parent];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  80) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  81) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  82) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  83)  * xbc_node_get_child() - Get the child XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  84)  * @node: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  85)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  86)  * Return the first child node of @node. If the node has no child, return
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  87)  * NULL.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  88)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  89) struct xbc_node * __init xbc_node_get_child(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  90) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  91) 	return node->child ? &xbc_nodes[node->child] : NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  92) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  93) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  94) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  95)  * xbc_node_get_next() - Get the next sibling XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  96)  * @node: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  97)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  98)  * Return the NEXT sibling node of @node. If the node has no next sibling,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900  99)  * return NULL. Note that even if this returns NULL, it doesn't mean @node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 100)  * has no siblings. (You also has to check whether the parent's child node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 101)  * is @node or not.)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 102)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 103) struct xbc_node * __init xbc_node_get_next(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 104) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 105) 	return node->next ? &xbc_nodes[node->next] : NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 106) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 107) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 108) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 109)  * xbc_node_get_data() - Get the data of XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 110)  * @node: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 111)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 112)  * Return the data (which is always a null terminated string) of @node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 113)  * If the node has invalid data, warn and return NULL.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 114)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 115) const char * __init xbc_node_get_data(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 116) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 117) 	int offset = node->data & ~XBC_VALUE;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 118) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 119) 	if (WARN_ON(offset >= xbc_data_size))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 120) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 121) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 122) 	return xbc_data + offset;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 123) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 124) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 125) static bool __init
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 126) xbc_node_match_prefix(struct xbc_node *node, const char **prefix)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 127) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 128) 	const char *p = xbc_node_get_data(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 129) 	int len = strlen(p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 130) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 131) 	if (strncmp(*prefix, p, len))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 132) 		return false;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 133) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 134) 	p = *prefix + len;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 135) 	if (*p == '.')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 136) 		p++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 137) 	else if (*p != '\0')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 138) 		return false;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 139) 	*prefix = p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 140) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 141) 	return true;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 142) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 143) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 144) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 145)  * xbc_node_find_child() - Find a child node which matches given key
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 146)  * @parent: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 147)  * @key: A key string.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 148)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 149)  * Search a node under @parent which matches @key. The @key can contain
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 150)  * several words jointed with '.'. If @parent is NULL, this searches the
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 151)  * node from whole tree. Return NULL if no node is matched.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 152)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 153) struct xbc_node * __init
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 154) xbc_node_find_child(struct xbc_node *parent, const char *key)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 155) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 156) 	struct xbc_node *node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 157) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 158) 	if (parent)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 159) 		node = xbc_node_get_child(parent);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 160) 	else
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 161) 		node = xbc_root_node();
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 162) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 163) 	while (node && xbc_node_is_key(node)) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 164) 		if (!xbc_node_match_prefix(node, &key))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 165) 			node = xbc_node_get_next(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 166) 		else if (*key != '\0')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 167) 			node = xbc_node_get_child(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 168) 		else
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 169) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 170) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 171) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 172) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 173) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 174) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 175) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 176)  * xbc_node_find_value() - Find a value node which matches given key
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 177)  * @parent: An XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 178)  * @key: A key string.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 179)  * @vnode: A container pointer of found XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 180)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 181)  * Search a value node under @parent whose (parent) key node matches @key,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 182)  * store it in *@vnode, and returns the value string.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 183)  * The @key can contain several words jointed with '.'. If @parent is NULL,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 184)  * this searches the node from whole tree. Return the value string if a
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 185)  * matched key found, return NULL if no node is matched.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 186)  * Note that this returns 0-length string and stores NULL in *@vnode if the
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 187)  * key has no value. And also it will return the value of the first entry if
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 188)  * the value is an array.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 189)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 190) const char * __init
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 191) xbc_node_find_value(struct xbc_node *parent, const char *key,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 192) 		    struct xbc_node **vnode)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 193) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 194) 	struct xbc_node *node = xbc_node_find_child(parent, key);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 195) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 196) 	if (!node || !xbc_node_is_key(node))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 197) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 198) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 199) 	node = xbc_node_get_child(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 200) 	if (node && !xbc_node_is_value(node))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 201) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 202) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 203) 	if (vnode)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 204) 		*vnode = node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 205) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 206) 	return node ? xbc_node_get_data(node) : "";
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 207) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 208) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 209) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 210)  * xbc_node_compose_key_after() - Compose partial key string of the XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 211)  * @root: Root XBC node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 212)  * @node: Target XBC node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 213)  * @buf: A buffer to store the key.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 214)  * @size: The size of the @buf.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 215)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 216)  * Compose the partial key of the @node into @buf, which is starting right
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 217)  * after @root (@root is not included.) If @root is NULL, this returns full
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 218)  * key words of @node.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 219)  * Returns the total length of the key stored in @buf. Returns -EINVAL
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 220)  * if @node is NULL or @root is not the ancestor of @node or @root is @node,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 221)  * or returns -ERANGE if the key depth is deeper than max depth.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 222)  * This is expected to be used with xbc_find_node() to list up all (child)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 223)  * keys under given key.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 224)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 225) int __init xbc_node_compose_key_after(struct xbc_node *root,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 226) 				      struct xbc_node *node,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 227) 				      char *buf, size_t size)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 228) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 229) 	u16 keys[XBC_DEPTH_MAX];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 230) 	int depth = 0, ret = 0, total = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 231) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 232) 	if (!node || node == root)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 233) 		return -EINVAL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 234) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 235) 	if (xbc_node_is_value(node))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 236) 		node = xbc_node_get_parent(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 237) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 238) 	while (node && node != root) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 239) 		keys[depth++] = xbc_node_index(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 240) 		if (depth == XBC_DEPTH_MAX)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 241) 			return -ERANGE;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 242) 		node = xbc_node_get_parent(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 243) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 244) 	if (!node && root)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 245) 		return -EINVAL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 246) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 247) 	while (--depth >= 0) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 248) 		node = xbc_nodes + keys[depth];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 249) 		ret = snprintf(buf, size, "%s%s", xbc_node_get_data(node),
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 250) 			       depth ? "." : "");
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 251) 		if (ret < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 252) 			return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 253) 		if (ret > size) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 254) 			size = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 255) 		} else {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 256) 			size -= ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 257) 			buf += ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 258) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 259) 		total += ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 260) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 261) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 262) 	return total;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 263) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 264) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 265) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 266)  * xbc_node_find_next_leaf() - Find the next leaf node under given node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 267)  * @root: An XBC root node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 268)  * @node: An XBC node which starts from.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 269)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 270)  * Search the next leaf node (which means the terminal key node) of @node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 271)  * under @root node (including @root node itself).
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 272)  * Return the next node or NULL if next leaf node is not found.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 273)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 274) struct xbc_node * __init xbc_node_find_next_leaf(struct xbc_node *root,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 275) 						 struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 276) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 277) 	if (unlikely(!xbc_data))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 278) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 279) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 280) 	if (!node) {	/* First try */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 281) 		node = root;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 282) 		if (!node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 283) 			node = xbc_nodes;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 284) 	} else {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 285) 		if (node == root)	/* @root was a leaf, no child node. */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 286) 			return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 287) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 288) 		while (!node->next) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 289) 			node = xbc_node_get_parent(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 290) 			if (node == root)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 291) 				return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 292) 			/* User passed a node which is not uder parent */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 293) 			if (WARN_ON(!node))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 294) 				return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 295) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 296) 		node = xbc_node_get_next(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 297) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 298) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 299) 	while (node && !xbc_node_is_leaf(node))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 300) 		node = xbc_node_get_child(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 301) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 302) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 303) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 304) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 305) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 306)  * xbc_node_find_next_key_value() - Find the next key-value pair nodes
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 307)  * @root: An XBC root node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 308)  * @leaf: A container pointer of XBC node which starts from.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 309)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 310)  * Search the next leaf node (which means the terminal key node) of *@leaf
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 311)  * under @root node. Returns the value and update *@leaf if next leaf node
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 312)  * is found, or NULL if no next leaf node is found.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 313)  * Note that this returns 0-length string if the key has no value, or
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 314)  * the value of the first entry if the value is an array.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 315)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 316) const char * __init xbc_node_find_next_key_value(struct xbc_node *root,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 317) 						 struct xbc_node **leaf)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 318) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 319) 	/* tip must be passed */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 320) 	if (WARN_ON(!leaf))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 321) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 322) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 323) 	*leaf = xbc_node_find_next_leaf(root, *leaf);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 324) 	if (!*leaf)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 325) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 326) 	if ((*leaf)->child)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 327) 		return xbc_node_get_data(xbc_node_get_child(*leaf));
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 328) 	else
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 329) 		return "";	/* No value key */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 330) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 331) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 332) /* XBC parse and tree build */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 333) 
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 334) static int __init xbc_init_node(struct xbc_node *node, char *data, u32 flag)
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 335) {
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 336) 	unsigned long offset = data - xbc_data;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 337) 
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 338) 	if (WARN_ON(offset >= XBC_DATA_MAX))
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 339) 		return -EINVAL;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 340) 
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 341) 	node->data = (u16)offset | flag;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 342) 	node->child = 0;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 343) 	node->next = 0;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 344) 
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 345) 	return 0;
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 346) }
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 347) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 348) static struct xbc_node * __init xbc_add_node(char *data, u32 flag)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 349) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 350) 	struct xbc_node *node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 351) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 352) 	if (xbc_node_num == XBC_NODE_MAX)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 353) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 354) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 355) 	node = &xbc_nodes[xbc_node_num++];
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 356) 	if (xbc_init_node(node, data, flag) < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 357) 		return NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 358) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 359) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 360) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 361) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 362) static inline __init struct xbc_node *xbc_last_sibling(struct xbc_node *node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 363) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 364) 	while (node->next)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 365) 		node = xbc_node_get_next(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 366) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 367) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 368) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 369) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 370) static struct xbc_node * __init xbc_add_sibling(char *data, u32 flag)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 371) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 372) 	struct xbc_node *sib, *node = xbc_add_node(data, flag);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 373) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 374) 	if (node) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 375) 		if (!last_parent) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 376) 			node->parent = XBC_NODE_MAX;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 377) 			sib = xbc_last_sibling(xbc_nodes);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 378) 			sib->next = xbc_node_index(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 379) 		} else {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 380) 			node->parent = xbc_node_index(last_parent);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 381) 			if (!last_parent->child) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 382) 				last_parent->child = xbc_node_index(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 383) 			} else {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 384) 				sib = xbc_node_get_child(last_parent);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 385) 				sib = xbc_last_sibling(sib);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 386) 				sib->next = xbc_node_index(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 387) 			}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 388) 		}
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 389) 	} else
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 390) 		xbc_parse_error("Too many nodes", data);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 391) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 392) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 393) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 394) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 395) static inline __init struct xbc_node *xbc_add_child(char *data, u32 flag)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 396) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 397) 	struct xbc_node *node = xbc_add_sibling(data, flag);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 398) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 399) 	if (node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 400) 		last_parent = node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 401) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 402) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 403) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 404) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 405) static inline __init bool xbc_valid_keyword(char *key)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 406) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 407) 	if (key[0] == '\0')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 408) 		return false;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 409) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 410) 	while (isalnum(*key) || *key == '-' || *key == '_')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 411) 		key++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 412) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 413) 	return *key == '\0';
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 414) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 415) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 416) static char *skip_comment(char *p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 417) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 418) 	char *ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 419) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 420) 	ret = strchr(p, '\n');
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 421) 	if (!ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 422) 		ret = p + strlen(p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 423) 	else
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 424) 		ret++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 425) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 426) 	return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 427) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 428) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 429) static char *skip_spaces_until_newline(char *p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 430) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 431) 	while (isspace(*p) && *p != '\n')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 432) 		p++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 433) 	return p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 434) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 435) 
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 436) static int __init __xbc_open_brace(char *p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 437) {
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 438) 	/* Push the last key as open brace */
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 439) 	open_brace[brace_index++] = xbc_node_index(last_parent);
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 440) 	if (brace_index >= XBC_DEPTH_MAX)
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 441) 		return xbc_parse_error("Exceed max depth of braces", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 442) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 443) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 444) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 445) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 446) static int __init __xbc_close_brace(char *p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 447) {
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 448) 	brace_index--;
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 449) 	if (!last_parent || brace_index < 0 ||
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 450) 	    (open_brace[brace_index] != xbc_node_index(last_parent)))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 451) 		return xbc_parse_error("Unexpected closing brace", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 452) 
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 453) 	if (brace_index == 0)
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 454) 		last_parent = NULL;
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 455) 	else
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 456) 		last_parent = &xbc_nodes[open_brace[brace_index - 1]];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 457) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 458) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 459) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 460) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 461) /*
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 462)  * Return delimiter or error, no node added. As same as lib/cmdline.c,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 463)  * you can use " around spaces, but can't escape " for value.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 464)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 465) static int __init __xbc_parse_value(char **__v, char **__n)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 466) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 467) 	char *p, *v = *__v;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 468) 	int c, quotes = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 469) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 470) 	v = skip_spaces(v);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 471) 	while (*v == '#') {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 472) 		v = skip_comment(v);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 473) 		v = skip_spaces(v);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 474) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 475) 	if (*v == '"' || *v == '\'') {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 476) 		quotes = *v;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 477) 		v++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 478) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 479) 	p = v - 1;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 480) 	while ((c = *++p)) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 481) 		if (!isprint(c) && !isspace(c))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 482) 			return xbc_parse_error("Non printable value", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 483) 		if (quotes) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 484) 			if (c != quotes)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 485) 				continue;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 486) 			quotes = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 487) 			*p++ = '\0';
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 488) 			p = skip_spaces_until_newline(p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 489) 			c = *p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 490) 			if (c && !strchr(",;\n#}", c))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 491) 				return xbc_parse_error("No value delimiter", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 492) 			if (*p)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 493) 				p++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 494) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 495) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 496) 		if (strchr(",;\n#}", c)) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 497) 			*p++ = '\0';
c7af4ecdffe15 (Masami Hiramatsu 2020-09-21 18:44:51 +0900 498) 			v = strim(v);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 499) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 500) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 501) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 502) 	if (quotes)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 503) 		return xbc_parse_error("No closing quotes", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 504) 	if (c == '#') {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 505) 		p = skip_comment(p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 506) 		c = '\n';	/* A comment must be treated as a newline */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 507) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 508) 	*__n = p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 509) 	*__v = v;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 510) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 511) 	return c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 512) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 513) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 514) static int __init xbc_parse_array(char **__v)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 515) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 516) 	struct xbc_node *node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 517) 	char *next;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 518) 	int c = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 519) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 520) 	do {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 521) 		c = __xbc_parse_value(__v, &next);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 522) 		if (c < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 523) 			return c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 524) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 525) 		node = xbc_add_sibling(*__v, XBC_VALUE);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 526) 		if (!node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 527) 			return -ENOMEM;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 528) 		*__v = next;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 529) 	} while (c == ',');
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 530) 	node->next = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 531) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 532) 	return c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 533) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 534) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 535) static inline __init
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 536) struct xbc_node *find_match_node(struct xbc_node *node, char *k)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 537) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 538) 	while (node) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 539) 		if (!strcmp(xbc_node_get_data(node), k))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 540) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 541) 		node = xbc_node_get_next(node);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 542) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 543) 	return node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 544) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 545) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 546) static int __init __xbc_add_key(char *k)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 547) {
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 548) 	struct xbc_node *node, *child;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 549) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 550) 	if (!xbc_valid_keyword(k))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 551) 		return xbc_parse_error("Invalid keyword", k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 552) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 553) 	if (unlikely(xbc_node_num == 0))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 554) 		goto add_node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 555) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 556) 	if (!last_parent)	/* the first level */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 557) 		node = find_match_node(xbc_nodes, k);
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 558) 	else {
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 559) 		child = xbc_node_get_child(last_parent);
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 560) 		if (child && xbc_node_is_value(child))
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 561) 			return xbc_parse_error("Subkey is mixed with value", k);
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 562) 		node = find_match_node(child, k);
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 563) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 564) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 565) 	if (node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 566) 		last_parent = node;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 567) 	else {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 568) add_node:
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 569) 		node = xbc_add_child(k, XBC_KEY);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 570) 		if (!node)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 571) 			return -ENOMEM;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 572) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 573) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 574) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 575) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 576) static int __init __xbc_parse_keys(char *k)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 577) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 578) 	char *p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 579) 	int ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 580) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 581) 	k = strim(k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 582) 	while ((p = strchr(k, '.'))) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 583) 		*p++ = '\0';
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 584) 		ret = __xbc_add_key(k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 585) 		if (ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 586) 			return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 587) 		k = p;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 588) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 589) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 590) 	return __xbc_add_key(k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 591) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 592) 
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 593) static int __init xbc_parse_kv(char **k, char *v, int op)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 594) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 595) 	struct xbc_node *prev_parent = last_parent;
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 596) 	struct xbc_node *child;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 597) 	char *next;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 598) 	int c, ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 599) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 600) 	ret = __xbc_parse_keys(*k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 601) 	if (ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 602) 		return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 603) 
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 604) 	child = xbc_node_get_child(last_parent);
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 605) 	if (child) {
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 606) 		if (xbc_node_is_key(child))
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 607) 			return xbc_parse_error("Value is mixed with subkey", v);
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 608) 		else if (op == '=')
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 609) 			return xbc_parse_error("Value is redefined", v);
4e4694d8729f7 (Masami Hiramatsu 2020-02-21 17:13:42 +0900 610) 	}
a24d286f36104 (Masami Hiramatsu 2020-02-20 21:19:12 +0900 611) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 612) 	c = __xbc_parse_value(&v, &next);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 613) 	if (c < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 614) 		return c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 615) 
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 616) 	if (op == ':' && child) {
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 617) 		xbc_init_node(child, v, XBC_VALUE);
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 618) 	} else if (!xbc_add_sibling(v, XBC_VALUE))
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 619) 		return -ENOMEM;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 620) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 621) 	if (c == ',') {	/* Array */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 622) 		c = xbc_parse_array(&next);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 623) 		if (c < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 624) 			return c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 625) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 626) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 627) 	last_parent = prev_parent;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 628) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 629) 	if (c == '}') {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 630) 		ret = __xbc_close_brace(next - 1);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 631) 		if (ret < 0)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 632) 			return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 633) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 634) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 635) 	*k = next;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 636) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 637) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 638) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 639) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 640) static int __init xbc_parse_key(char **k, char *n)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 641) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 642) 	struct xbc_node *prev_parent = last_parent;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 643) 	int ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 644) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 645) 	*k = strim(*k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 646) 	if (**k != '\0') {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 647) 		ret = __xbc_parse_keys(*k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 648) 		if (ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 649) 			return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 650) 		last_parent = prev_parent;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 651) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 652) 	*k = n;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 653) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 654) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 655) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 656) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 657) static int __init xbc_open_brace(char **k, char *n)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 658) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 659) 	int ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 660) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 661) 	ret = __xbc_parse_keys(*k);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 662) 	if (ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 663) 		return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 664) 	*k = n;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 665) 
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 666) 	return __xbc_open_brace(n - 1);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 667) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 668) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 669) static int __init xbc_close_brace(char **k, char *n)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 670) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 671) 	int ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 672) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 673) 	ret = xbc_parse_key(k, n);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 674) 	if (ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 675) 		return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 676) 	/* k is updated in xbc_parse_key() */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 677) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 678) 	return __xbc_close_brace(n - 1);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 679) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 680) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 681) static int __init xbc_verify_tree(void)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 682) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 683) 	int i, depth, len, wlen;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 684) 	struct xbc_node *n, *m;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 685) 
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 686) 	/* Brace closing */
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 687) 	if (brace_index) {
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 688) 		n = &xbc_nodes[open_brace[brace_index]];
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 689) 		return xbc_parse_error("Brace is not closed",
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 690) 					xbc_node_get_data(n));
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 691) 	}
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 692) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 693) 	/* Empty tree */
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 694) 	if (xbc_node_num == 0) {
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 695) 		xbc_parse_error("Empty config", xbc_data);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 696) 		return -ENOENT;
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 697) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 698) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 699) 	for (i = 0; i < xbc_node_num; i++) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 700) 		if (xbc_nodes[i].next > xbc_node_num) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 701) 			return xbc_parse_error("No closing brace",
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 702) 				xbc_node_get_data(xbc_nodes + i));
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 703) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 704) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 705) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 706) 	/* Key tree limitation check */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 707) 	n = &xbc_nodes[0];
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 708) 	depth = 1;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 709) 	len = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 710) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 711) 	while (n) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 712) 		wlen = strlen(xbc_node_get_data(n)) + 1;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 713) 		len += wlen;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 714) 		if (len > XBC_KEYLEN_MAX)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 715) 			return xbc_parse_error("Too long key length",
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 716) 				xbc_node_get_data(n));
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 717) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 718) 		m = xbc_node_get_child(n);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 719) 		if (m && xbc_node_is_key(m)) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 720) 			n = m;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 721) 			depth++;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 722) 			if (depth > XBC_DEPTH_MAX)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 723) 				return xbc_parse_error("Too many key words",
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 724) 						xbc_node_get_data(n));
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 725) 			continue;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 726) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 727) 		len -= wlen;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 728) 		m = xbc_node_get_next(n);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 729) 		while (!m) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 730) 			n = xbc_node_get_parent(n);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 731) 			if (!n)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 732) 				break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 733) 			len -= strlen(xbc_node_get_data(n)) + 1;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 734) 			depth--;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 735) 			m = xbc_node_get_next(n);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 736) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 737) 		n = m;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 738) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 739) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 740) 	return 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 741) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 742) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 743) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 744)  * xbc_destroy_all() - Clean up all parsed bootconfig
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 745)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 746)  * This clears all data structures of parsed bootconfig on memory.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 747)  * If you need to reuse xbc_init() with new boot config, you can
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 748)  * use this.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 749)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 750) void __init xbc_destroy_all(void)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 751) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 752) 	xbc_data = NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 753) 	xbc_data_size = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 754) 	xbc_node_num = 0;
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 755) 	memblock_free(__pa(xbc_nodes), sizeof(struct xbc_node) * XBC_NODE_MAX);
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 756) 	xbc_nodes = NULL;
ead1e19ad905b (Masami Hiramatsu 2020-09-21 18:44:42 +0900 757) 	brace_index = 0;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 758) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 759) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 760) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 761)  * xbc_init() - Parse given XBC file and build XBC internal tree
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 762)  * @buf: boot config text
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 763)  * @emsg: A pointer of const char * to store the error message
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 764)  * @epos: A pointer of int to store the error position
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 765)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 766)  * This parses the boot config text in @buf. @buf must be a
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 767)  * null terminated string and smaller than XBC_DATA_MAX.
0f0d0a77ccbdc (Masami Hiramatsu 2020-02-05 22:50:13 +0900 768)  * Return the number of stored nodes (>0) if succeeded, or -errno
0f0d0a77ccbdc (Masami Hiramatsu 2020-02-05 22:50:13 +0900 769)  * if there is any error.
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 770)  * In error cases, @emsg will be updated with an error message and
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 771)  * @epos will be updated with the error position which is the byte offset
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 772)  * of @buf. If the error is not a parser error, @epos will be -1.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 773)  */
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 774) int __init xbc_init(char *buf, const char **emsg, int *epos)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 775) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 776) 	char *p, *q;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 777) 	int ret, c;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 778) 
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 779) 	if (epos)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 780) 		*epos = -1;
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 781) 
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 782) 	if (xbc_data) {
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 783) 		if (emsg)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 784) 			*emsg = "Bootconfig is already initialized";
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 785) 		return -EBUSY;
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 786) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 787) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 788) 	ret = strlen(buf);
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 789) 	if (ret > XBC_DATA_MAX - 1 || ret == 0) {
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 790) 		if (emsg)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 791) 			*emsg = ret ? "Config data is too big" :
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 792) 				"Config data is empty";
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 793) 		return -ERANGE;
597c0e3b45409 (Masami Hiramatsu 2020-02-05 22:50:04 +0900 794) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 795) 
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 796) 	xbc_nodes = memblock_alloc(sizeof(struct xbc_node) * XBC_NODE_MAX,
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 797) 				   SMP_CACHE_BYTES);
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 798) 	if (!xbc_nodes) {
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 799) 		if (emsg)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 800) 			*emsg = "Failed to allocate bootconfig nodes";
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 801) 		return -ENOMEM;
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 802) 	}
a91e4f12ffc42 (Masami Hiramatsu 2020-02-07 23:28:17 +0900 803) 	memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 804) 	xbc_data = buf;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 805) 	xbc_data_size = ret + 1;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 806) 	last_parent = NULL;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 807) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 808) 	p = buf;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 809) 	do {
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 810) 		q = strpbrk(p, "{}=+;:\n#");
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 811) 		if (!q) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 812) 			p = skip_spaces(p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 813) 			if (*p != '\0')
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 814) 				ret = xbc_parse_error("No delimiter", p);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 815) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 816) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 817) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 818) 		c = *q;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 819) 		*q++ = '\0';
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 820) 		switch (c) {
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 821) 		case ':':
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 822) 		case '+':
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 823) 			if (*q++ != '=') {
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 824) 				ret = xbc_parse_error(c == '+' ?
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 825) 						"Wrong '+' operator" :
a2de2f86ae383 (Masami Hiramatsu 2020-07-16 01:00:29 +0900 826) 						"Wrong ':' operator",
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 827) 							q - 2);
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 828) 				break;
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 829) 			}
4c1ca831adb10 (Nick Desaulniers 2020-11-15 20:35:31 -0800 830) 			fallthrough;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 831) 		case '=':
5f811c57c9920 (Masami Hiramatsu 2020-02-21 17:13:52 +0900 832) 			ret = xbc_parse_kv(&p, q, c);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 833) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 834) 		case '{':
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 835) 			ret = xbc_open_brace(&p, q);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 836) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 837) 		case '#':
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 838) 			q = skip_comment(q);
4c1ca831adb10 (Nick Desaulniers 2020-11-15 20:35:31 -0800 839) 			fallthrough;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 840) 		case ';':
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 841) 		case '\n':
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 842) 			ret = xbc_parse_key(&p, q);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 843) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 844) 		case '}':
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 845) 			ret = xbc_close_brace(&p, q);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 846) 			break;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 847) 		}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 848) 	} while (!ret);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 849) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 850) 	if (!ret)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 851) 		ret = xbc_verify_tree();
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 852) 
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 853) 	if (ret < 0) {
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 854) 		if (epos)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 855) 			*epos = xbc_err_pos;
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 856) 		if (emsg)
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 857) 			*emsg = xbc_err_msg;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 858) 		xbc_destroy_all();
89b74cac78347 (Masami Hiramatsu 2020-03-03 20:24:50 +0900 859) 	} else
0f0d0a77ccbdc (Masami Hiramatsu 2020-02-05 22:50:13 +0900 860) 		ret = xbc_node_num;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 861) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 862) 	return ret;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 863) }
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 864) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 865) /**
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 866)  * xbc_debug_dump() - Dump current XBC node list
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 867)  *
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 868)  * Dump the current XBC node list on printk buffer for debug.
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 869)  */
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 870) void __init xbc_debug_dump(void)
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 871) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 872) 	int i;
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 873) 
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 874) 	for (i = 0; i < xbc_node_num; i++) {
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 875) 		pr_debug("[%d] %s (%s) .next=%d, .child=%d .parent=%d\n", i,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 876) 			xbc_node_get_data(xbc_nodes + i),
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 877) 			xbc_node_is_value(xbc_nodes + i) ? "value" : "key",
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 878) 			xbc_nodes[i].next, xbc_nodes[i].child,
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 879) 			xbc_nodes[i].parent);
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 880) 	}
76db5a27a827c (Masami Hiramatsu 2020-01-11 01:03:32 +0900 881) }