1 From 68bcfea9ab5d8947f711a97dcc291cb9da47c7da Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Sun, 13 Apr 2008 07:23:59 +0100
4 Subject: [PATCH] kexec-atags.patch
5 Leapfrogged from upstream (ARM Linux)
6 http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4736/1
9 arch/arm/Kconfig | 7 +++
10 arch/arm/kernel/Makefile | 1 +
11 arch/arm/kernel/atags.c | 86 +++++++++++++++++++++++++++++++++++++
12 arch/arm/kernel/atags.h | 5 ++
13 arch/arm/kernel/machine_kexec.c | 2 +
14 arch/arm/kernel/relocate_kernel.S | 30 ++-----------
15 arch/arm/kernel/setup.c | 32 +-------------
16 include/asm-arm/kexec.h | 3 +
17 8 files changed, 110 insertions(+), 56 deletions(-)
18 create mode 100644 arch/arm/kernel/atags.c
19 create mode 100644 arch/arm/kernel/atags.h
21 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
22 index 23e3d6b..ef7b9ff 100644
23 --- a/arch/arm/Kconfig
24 +++ b/arch/arm/Kconfig
25 @@ -865,6 +865,13 @@ config KEXEC
26 initially work for you. It may help to enable device hotplugging
30 + bool "Export atags in procfs"
33 + Should the atags used to boot the kernel be exported in an "atags"
34 + file in procfs. Useful with kexec.
38 if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
39 diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
40 index 593b565..5cf694c 100644
41 --- a/arch/arm/kernel/Makefile
42 +++ b/arch/arm/kernel/Makefile
43 @@ -19,6 +19,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
44 obj-$(CONFIG_PCI) += bios32.o isa.o
45 obj-$(CONFIG_SMP) += smp.o
46 obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
47 +obj-$(CONFIG_ATAGS_PROC) += atags.o
48 obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
50 obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
51 diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
53 index 0000000..e2e934c
55 +++ b/arch/arm/kernel/atags.c
57 +#include <linux/slab.h>
58 +#include <linux/kexec.h>
59 +#include <linux/proc_fs.h>
60 +#include <asm/setup.h>
61 +#include <asm/types.h>
62 +#include <asm/page.h>
68 +static struct buffer tags_buffer;
71 +read_buffer(char* page, char** start, off_t off, int count,
72 + int* eof, void* data)
74 + struct buffer *buffer = (struct buffer *)data;
76 + if (off >= buffer->size) {
81 + count = min((int) (buffer->size - off), count);
83 + memcpy(page, &buffer->data[off], count);
90 +create_proc_entries(void)
92 + struct proc_dir_entry* tags_entry;
94 + tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
102 +static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
103 +static char __initdata *atags_copy;
105 +void __init save_atags(const struct tag *tags)
107 + atags_copy = atags_copy_buf;
108 + memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
112 +static int __init init_atags_procfs(void)
118 + printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
122 + for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
125 + tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
126 + tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
127 + if (tags_buffer.data == NULL)
129 + memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
131 + error = create_proc_entries();
133 + printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
134 + kfree(tags_buffer.data);
135 + tags_buffer.size = 0;
136 + tags_buffer.data = NULL;
142 +arch_initcall(init_atags_procfs);
143 diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
145 index 0000000..e5f028d
147 +++ b/arch/arm/kernel/atags.h
149 +#ifdef CONFIG_ATAGS_PROC
150 +extern void save_atags(struct tag *tags);
152 +static inline void save_atags(struct tag *tags) { }
154 diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
155 index 863c664..db8f54a 100644
156 --- a/arch/arm/kernel/machine_kexec.c
157 +++ b/arch/arm/kernel/machine_kexec.c
158 @@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
159 extern unsigned long kexec_start_address;
160 extern unsigned long kexec_indirection_page;
161 extern unsigned long kexec_mach_type;
162 +extern unsigned long kexec_boot_atags;
165 * Provide a dummy crash_notes definition while crash dump arrives to arm.
166 @@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
167 kexec_start_address = image->start;
168 kexec_indirection_page = page_list;
169 kexec_mach_type = machine_arch_type;
170 + kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
172 /* copy our kernel relocation code to the control code page */
173 memcpy(reboot_code_buffer,
174 diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
175 index 062c111..61930eb 100644
176 --- a/arch/arm/kernel/relocate_kernel.S
177 +++ b/arch/arm/kernel/relocate_kernel.S
179 .globl relocate_new_kernel
182 - /* Move boot params back to where the kernel expects them */
184 - ldr r0,kexec_boot_params_address
188 - ldr r1,kexec_boot_params_copy
189 - mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
197 - /* Boot params moved, now go on with the kernel */
199 ldr r0,kexec_indirection_page
200 ldr r1,kexec_start_address
202 @@ -67,7 +50,7 @@ relocate_new_kernel:
205 ldr r1,kexec_mach_type
206 - ldr r2,kexec_boot_params_address
207 + ldr r2,kexec_boot_atags
210 .globl kexec_start_address
211 @@ -82,14 +65,9 @@ kexec_indirection_page:
215 - /* phy addr where new kernel will expect to find boot params */
216 - .globl kexec_boot_params_address
217 -kexec_boot_params_address:
220 - /* phy addr where old kernel put a copy of orig boot params */
221 - .globl kexec_boot_params_copy
222 -kexec_boot_params_copy:
223 + /* phy addr of the atags for the new kernel */
224 + .globl kexec_boot_atags
228 relocate_new_kernel_end:
229 diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
230 index bf56eb3..ae3712d 100644
231 --- a/arch/arm/kernel/setup.c
232 +++ b/arch/arm/kernel/setup.c
234 #include <linux/interrupt.h>
235 #include <linux/smp.h>
236 #include <linux/fs.h>
237 -#include <linux/kexec.h>
242 #include <asm/mach/time.h>
248 #define MEM_SIZE (16*1024*1024)
249 @@ -784,23 +784,6 @@ static int __init customize_machine(void)
251 arch_initcall(customize_machine);
255 -/* Physical addr of where the boot params should be for this machine */
256 -extern unsigned long kexec_boot_params_address;
258 -/* Physical addr of the buffer into which the boot params are copied */
259 -extern unsigned long kexec_boot_params_copy;
261 -/* Pointer to the boot params buffer, for manipulation and display */
262 -unsigned long kexec_boot_params;
263 -EXPORT_SYMBOL(kexec_boot_params);
265 -/* The buffer itself - make sure it is sized correctly */
266 -static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
270 void __init setup_arch(char **cmdline_p)
272 struct tag *tags = (struct tag *)&init_tags;
273 @@ -819,18 +802,6 @@ void __init setup_arch(char **cmdline_p)
274 else if (mdesc->boot_params)
275 tags = phys_to_virt(mdesc->boot_params);
278 - kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
279 - kexec_boot_params = (unsigned long)kexec_boot_params_buf;
280 - if (__atags_pointer) {
281 - kexec_boot_params_address = __atags_pointer;
282 - memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
283 - } else if (mdesc->boot_params) {
284 - kexec_boot_params_address = mdesc->boot_params;
285 - memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
290 * If we have the old style parameters, convert them to
292 @@ -846,6 +817,7 @@ void __init setup_arch(char **cmdline_p)
293 if (tags->hdr.tag == ATAG_CORE) {
294 if (meminfo.nr_banks != 0)
295 squash_mem_tags(tags);
300 diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
301 index 46dcc4d..1ee17b6 100644
302 --- a/include/asm-arm/kexec.h
303 +++ b/include/asm-arm/kexec.h
306 #define KEXEC_BOOT_PARAMS_SIZE 1536
308 +#define KEXEC_ARM_ATAGS_OFFSET 0x1000
309 +#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000