OSDN Git Service

Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[tomoyo/tomoyo-test1.git] / fs / proc / bootconfig.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * /proc/bootconfig - Extra boot configuration
4  */
5 #include <linux/fs.h>
6 #include <linux/init.h>
7 #include <linux/printk.h>
8 #include <linux/proc_fs.h>
9 #include <linux/seq_file.h>
10 #include <linux/bootconfig.h>
11 #include <linux/slab.h>
12
13 static char *saved_boot_config;
14
15 static int boot_config_proc_show(struct seq_file *m, void *v)
16 {
17         if (saved_boot_config)
18                 seq_puts(m, saved_boot_config);
19         return 0;
20 }
21
22 /* Rest size of buffer */
23 #define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
24
25 /* Return the needed total length if @size is 0 */
26 static int __init copy_xbc_key_value_list(char *dst, size_t size)
27 {
28         struct xbc_node *leaf, *vnode;
29         const char *val;
30         char *key, *end = dst + size;
31         int ret = 0;
32
33         key = kzalloc(XBC_KEYLEN_MAX, GFP_KERNEL);
34
35         xbc_for_each_key_value(leaf, val) {
36                 ret = xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX);
37                 if (ret < 0)
38                         break;
39                 ret = snprintf(dst, rest(dst, end), "%s = ", key);
40                 if (ret < 0)
41                         break;
42                 dst += ret;
43                 vnode = xbc_node_get_child(leaf);
44                 if (vnode && xbc_node_is_array(vnode)) {
45                         xbc_array_for_each_value(vnode, val) {
46                                 ret = snprintf(dst, rest(dst, end), "\"%s\"%s",
47                                         val, vnode->next ? ", " : "\n");
48                                 if (ret < 0)
49                                         goto out;
50                                 dst += ret;
51                         }
52                 } else {
53                         ret = snprintf(dst, rest(dst, end), "\"%s\"\n", val);
54                         if (ret < 0)
55                                 break;
56                         dst += ret;
57                 }
58         }
59 out:
60         kfree(key);
61
62         return ret < 0 ? ret : dst - (end - size);
63 }
64
65 static int __init proc_boot_config_init(void)
66 {
67         int len;
68
69         len = copy_xbc_key_value_list(NULL, 0);
70         if (len < 0)
71                 return len;
72
73         if (len > 0) {
74                 saved_boot_config = kzalloc(len + 1, GFP_KERNEL);
75                 if (!saved_boot_config)
76                         return -ENOMEM;
77
78                 len = copy_xbc_key_value_list(saved_boot_config, len + 1);
79                 if (len < 0) {
80                         kfree(saved_boot_config);
81                         return len;
82                 }
83         }
84
85         proc_create_single("bootconfig", 0, NULL, boot_config_proc_show);
86
87         return 0;
88 }
89 fs_initcall(proc_boot_config_init);