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) }