]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
7bc1e4d8 GU |
2 | /* |
3 | * Based on arch/arm/kernel/atags_proc.c | |
4 | */ | |
5 | ||
6 | #include <linux/fs.h> | |
7 | #include <linux/init.h> | |
8 | #include <linux/printk.h> | |
9 | #include <linux/proc_fs.h> | |
10 | #include <linux/slab.h> | |
11 | #include <linux/string.h> | |
12 | ||
13 | #include <asm/bootinfo.h> | |
14 | #include <asm/byteorder.h> | |
15 | ||
16 | ||
17 | static char bootinfo_tmp[1536] __initdata; | |
18 | ||
19 | static void *bootinfo_copy; | |
20 | static size_t bootinfo_size; | |
21 | ||
22 | static ssize_t bootinfo_read(struct file *file, char __user *buf, | |
23 | size_t count, loff_t *ppos) | |
24 | { | |
25 | return simple_read_from_buffer(buf, count, ppos, bootinfo_copy, | |
26 | bootinfo_size); | |
27 | } | |
28 | ||
29 | static const struct file_operations bootinfo_fops = { | |
30 | .read = bootinfo_read, | |
31 | .llseek = default_llseek, | |
32 | }; | |
33 | ||
34 | void __init save_bootinfo(const struct bi_record *bi) | |
35 | { | |
36 | const void *start = bi; | |
37 | size_t size = sizeof(bi->tag); | |
38 | ||
39 | while (be16_to_cpu(bi->tag) != BI_LAST) { | |
40 | uint16_t n = be16_to_cpu(bi->size); | |
41 | size += n; | |
42 | bi = (struct bi_record *)((unsigned long)bi + n); | |
43 | } | |
44 | ||
45 | if (size > sizeof(bootinfo_tmp)) { | |
46 | pr_err("Cannot save %zu bytes of bootinfo\n", size); | |
47 | return; | |
48 | } | |
49 | ||
50 | pr_info("Saving %zu bytes of bootinfo\n", size); | |
51 | memcpy(bootinfo_tmp, start, size); | |
52 | bootinfo_size = size; | |
53 | } | |
54 | ||
55 | static int __init init_bootinfo_procfs(void) | |
56 | { | |
57 | /* | |
58 | * This cannot go into save_bootinfo() because kmalloc and proc don't | |
59 | * work yet when it is called. | |
60 | */ | |
61 | struct proc_dir_entry *pde; | |
62 | ||
63 | if (!bootinfo_size) | |
64 | return -EINVAL; | |
65 | ||
1ecb4064 | 66 | bootinfo_copy = kmemdup(bootinfo_tmp, bootinfo_size, GFP_KERNEL); |
7bc1e4d8 GU |
67 | if (!bootinfo_copy) |
68 | return -ENOMEM; | |
69 | ||
7bc1e4d8 GU |
70 | pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL); |
71 | if (!pde) { | |
72 | kfree(bootinfo_copy); | |
73 | return -ENOMEM; | |
74 | } | |
75 | ||
76 | return 0; | |
77 | } | |
78 | ||
79 | arch_initcall(init_bootinfo_procfs); |