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