[ar71xx] create firmware image for the Ubiquiti LS-SR71 board
[10.03/openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1070-kexec-atags.patch.patch
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
7
8 ---
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
20
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
27           support.
28  
29 +config ATAGS_PROC
30 +       bool "Export atags in procfs"
31 +       default n
32 +       help
33 +         Should the atags used to boot the kernel be exported in an "atags"
34 +         file in procfs. Useful with kexec.
35 +
36  endmenu
37  
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
49  
50  obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
51 diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
52 new file mode 100644
53 index 0000000..e2e934c
54 --- /dev/null
55 +++ b/arch/arm/kernel/atags.c
56 @@ -0,0 +1,86 @@
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>
63 +
64 +struct buffer {
65 +       size_t size;
66 +       char *data;
67 +};
68 +static struct buffer tags_buffer;
69 +
70 +static int
71 +read_buffer(char* page, char** start, off_t off, int count,
72 +       int* eof, void* data)
73 +{
74 +       struct buffer *buffer = (struct buffer *)data;
75 +
76 +       if (off >= buffer->size) {
77 +               *eof = 1;
78 +               return 0;
79 +       }
80 +
81 +       count = min((int) (buffer->size - off), count);
82 +
83 +       memcpy(page, &buffer->data[off], count);
84 +
85 +       return count;
86 +}
87 +
88 +
89 +static int
90 +create_proc_entries(void)
91 +{
92 +       struct proc_dir_entry* tags_entry;
93 +
94 +       tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
95 +       if (!tags_entry)
96 +               return -ENOMEM;
97 +
98 +       return 0;
99 +}
100 +
101 +
102 +static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
103 +static char __initdata *atags_copy;
104 +
105 +void __init save_atags(const struct tag *tags)
106 +{
107 +       atags_copy = atags_copy_buf;
108 +       memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
109 +}
110 +
111 +
112 +static int __init init_atags_procfs(void)
113 +{
114 +       struct tag *tag;
115 +       int error;
116 +
117 +       if (!atags_copy) {
118 +               printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
119 +               return -EIO;
120 +       }
121 +
122 +       for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
123 +               ;
124 +
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)
128 +               return -ENOMEM;
129 +       memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
130 +
131 +       error = create_proc_entries();
132 +       if (error) {
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;
137 +       }
138 +
139 +       return error;
140 +}
141 +
142 +arch_initcall(init_atags_procfs);
143 diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
144 new file mode 100644
145 index 0000000..e5f028d
146 --- /dev/null
147 +++ b/arch/arm/kernel/atags.h
148 @@ -0,0 +1,5 @@
149 +#ifdef CONFIG_ATAGS_PROC
150 +extern void save_atags(struct tag *tags);
151 +#else
152 +static inline void save_atags(struct tag *tags) { }
153 +#endif
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;
163  
164  /*
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;
171  
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
178 @@ -7,23 +7,6 @@
179         .globl relocate_new_kernel
180  relocate_new_kernel:
181  
182 -       /* Move boot params back to where the kernel expects them */
183 -
184 -       ldr     r0,kexec_boot_params_address
185 -       teq     r0,#0
186 -       beq     8f
187 -
188 -       ldr     r1,kexec_boot_params_copy
189 -       mov     r6,#KEXEC_BOOT_PARAMS_SIZE/4
190 -7:
191 -       ldr     r5,[r1],#4
192 -       str     r5,[r0],#4
193 -       subs    r6,r6,#1
194 -       bne     7b
195 -
196 -8:
197 -       /* Boot params moved, now go on with the kernel */
198 -
199         ldr     r0,kexec_indirection_page
200         ldr     r1,kexec_start_address
201  
202 @@ -67,7 +50,7 @@ relocate_new_kernel:
203         mov lr,r1
204         mov r0,#0
205         ldr r1,kexec_mach_type
206 -       ldr r2,kexec_boot_params_address
207 +       ldr r2,kexec_boot_atags
208         mov pc,lr
209  
210         .globl kexec_start_address
211 @@ -82,14 +65,9 @@ kexec_indirection_page:
212  kexec_mach_type:
213         .long   0x0
214  
215 -       /* phy addr where new kernel will expect to find boot params */
216 -       .globl kexec_boot_params_address
217 -kexec_boot_params_address:
218 -       .long   0x0
219 -
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
225 +kexec_boot_atags:
226         .long   0x0
227  
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
233 @@ -24,7 +24,6 @@
234  #include <linux/interrupt.h>
235  #include <linux/smp.h>
236  #include <linux/fs.h>
237 -#include <linux/kexec.h>
238  
239  #include <asm/cpu.h>
240  #include <asm/elf.h>
241 @@ -39,6 +38,7 @@
242  #include <asm/mach/time.h>
243  
244  #include "compat.h"
245 +#include "atags.h"
246  
247  #ifndef MEM_SIZE
248  #define MEM_SIZE       (16*1024*1024)
249 @@ -784,23 +784,6 @@ static int __init customize_machine(void)
250  }
251  arch_initcall(customize_machine);
252  
253 -#ifdef CONFIG_KEXEC
254 -
255 -/* Physical addr of where the boot params should be for this machine */
256 -extern unsigned long kexec_boot_params_address;
257 -
258 -/* Physical addr of the buffer into which the boot params are copied */
259 -extern unsigned long kexec_boot_params_copy;
260 -
261 -/* Pointer to the boot params buffer, for manipulation and display */
262 -unsigned long kexec_boot_params;
263 -EXPORT_SYMBOL(kexec_boot_params);
264 -
265 -/* The buffer itself - make sure it is sized correctly */
266 -static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
267 -
268 -#endif
269 -
270  void __init setup_arch(char **cmdline_p)
271  {
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);
276  
277 -#ifdef CONFIG_KEXEC
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);
286 -       }
287 -#endif
288 -
289         /*
290          * If we have the old style parameters, convert them to
291          * a tag list.
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);
296 +               save_atags(tags);
297                 parse_tags(tags);
298         }
299  
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
304 @@ -16,6 +16,9 @@
305  
306  #define KEXEC_BOOT_PARAMS_SIZE 1536
307  
308 +#define KEXEC_ARM_ATAGS_OFFSET  0x1000
309 +#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
310 +
311  #ifndef __ASSEMBLY__
312  
313  struct kimage;
314 -- 
315 1.5.6.5
316