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