aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/m68k/Kconfig7
-rw-r--r--arch/m68k/include/asm/bootinfo.h12
-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
5 files changed, 102 insertions, 0 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 178dffa9de80..dbdd2231c75d 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -104,6 +104,13 @@ config KEXEC
104 interface is strongly in flux, so no good recommendation can be 104 interface is strongly in flux, so no good recommendation can be
105 made. 105 made.
106 106
107config BOOTINFO_PROC
108 bool "Export bootinfo in procfs"
109 depends on KEXEC && M68KCLASSIC
110 help
111 Say Y to export the bootinfo used to boot the kernel in a
112 "bootinfo" file in procfs. This is useful with kexec.
113
107menu "Platform setup" 114menu "Platform setup"
108 115
109source arch/m68k/Kconfig.cpu 116source arch/m68k/Kconfig.cpu
diff --git a/arch/m68k/include/asm/bootinfo.h b/arch/m68k/include/asm/bootinfo.h
index 9edc31893fb8..8e213267f8e7 100644
--- a/arch/m68k/include/asm/bootinfo.h
+++ b/arch/m68k/include/asm/bootinfo.h
@@ -13,4 +13,16 @@
13 13
14#include <uapi/asm/bootinfo.h> 14#include <uapi/asm/bootinfo.h>
15 15
16
17#ifndef __ASSEMBLY__
18
19#ifdef CONFIG_BOOTINFO_PROC
20extern void save_bootinfo(const struct bi_record *bi);
21#else
22static inline void save_bootinfo(const struct bi_record *bi) {}
23#endif
24
25#endif /* __ASSEMBLY__ */
26
27
16#endif /* _M68K_BOOTINFO_H */ 28#endif /* _M68K_BOOTINFO_H */
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;