aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert@linux-m68k.org>2013-08-21 16:36:32 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2013-12-08 05:01:48 -0500
commit7bc1e4d8d506462c7d40118196f79a709f3fecfd (patch)
treee9d72b9a9e1e0368b9d3e3a9ccae929fd2ab947e /arch/m68k/kernel
parent7d5f5fa276efbbe45f0ed270b3f4e4a2816398c2 (diff)
m68k: Add support to export bootinfo in procfs
Add optional support to export the bootinfo used to boot the kernel in a "bootinfo" file in procfs. This is useful with kexec. This is based on the similar feature for ATAGS on ARM. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/Makefile1
-rw-r--r--arch/m68k/kernel/bootinfo_proc.c80
-rw-r--r--arch/m68k/kernel/setup_mm.c2
3 files changed, 83 insertions, 0 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 7ee5f00a9abb..2d5d9be16273 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -23,4 +23,5 @@ obj-$(CONFIG_PCI) += pcibios.o
23obj-$(CONFIG_HAS_DMA) += dma.o 23obj-$(CONFIG_HAS_DMA) += dma.o
24 24
25obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 25obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
26obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o
26 27
diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c
new file mode 100644
index 000000000000..7ee853e1432b
--- /dev/null
+++ b/arch/m68k/kernel/bootinfo_proc.c
@@ -0,0 +1,80 @@
1/*
2 * Based on arch/arm/kernel/atags_proc.c
3 */
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/slab.h>
10#include <linux/string.h>
11
12#include <asm/bootinfo.h>
13#include <asm/byteorder.h>
14
15
16static char bootinfo_tmp[1536] __initdata;
17
18static void *bootinfo_copy;
19static size_t bootinfo_size;
20
21static ssize_t bootinfo_read(struct file *file, char __user *buf,
22 size_t count, loff_t *ppos)
23{
24 return simple_read_from_buffer(buf, count, ppos, bootinfo_copy,
25 bootinfo_size);
26}
27
28static const struct file_operations bootinfo_fops = {
29 .read = bootinfo_read,
30 .llseek = default_llseek,
31};
32
33void __init save_bootinfo(const struct bi_record *bi)
34{
35 const void *start = bi;
36 size_t size = sizeof(bi->tag);
37
38 while (be16_to_cpu(bi->tag) != BI_LAST) {
39 uint16_t n = be16_to_cpu(bi->size);
40 size += n;
41 bi = (struct bi_record *)((unsigned long)bi + n);
42 }
43
44 if (size > sizeof(bootinfo_tmp)) {
45 pr_err("Cannot save %zu bytes of bootinfo\n", size);
46 return;
47 }
48
49 pr_info("Saving %zu bytes of bootinfo\n", size);
50 memcpy(bootinfo_tmp, start, size);
51 bootinfo_size = size;
52}
53
54static int __init init_bootinfo_procfs(void)
55{
56 /*
57 * This cannot go into save_bootinfo() because kmalloc and proc don't
58 * work yet when it is called.
59 */
60 struct proc_dir_entry *pde;
61
62 if (!bootinfo_size)
63 return -EINVAL;
64
65 bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
66 if (!bootinfo_copy)
67 return -ENOMEM;
68
69 memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
70
71 pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
72 if (!pde) {
73 kfree(bootinfo_copy);
74 return -ENOMEM;
75 }
76
77 return 0;
78}
79
80arch_initcall(init_bootinfo_procfs);
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 28abca421974..5b8ec4d5f8e8 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -146,6 +146,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
146{ 146{
147 uint16_t tag; 147 uint16_t tag;
148 148
149 save_bootinfo(record);
150
149 while ((tag = be16_to_cpu(record->tag)) != BI_LAST) { 151 while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
150 int unknown = 0; 152 int unknown = 0;
151 const void *data = record->data; 153 const void *data = record->data;