aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-02-25 07:14:40 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-25 14:34:31 -0500
commit5de813b6cd06460b337f9da9afe316823cf3ef45 (patch)
tree804eb5a2d986569353ac5c8728af419ce1907124 /arch/arm
parentd6d502fa4be1acd01971476fc732c95a4da16d90 (diff)
ARM: Eliminate decompressor -Dstatic= PIC hack
We used to build decompressors with -Dstatic= to avoid any local data being generated. The problem is that local data generates GOTOFF relocations, which means we can't relocate the data relative to the text segment. Global data, on the other hand, goes through the GOT, and can be relocated anywhere. Unfortunately, with the new decompressors, this presents a problem since they declare static data within functions, and this leads to stack overflow. Fix this by separating out the decompressor code into a separate file, and removing 'static' from BSS data in misc.c. Also, discard the .data section - this means that should we end up with read/write initialized data, the decompressor will fail to link and the problem will be obvious. Acked-by: Nicolas Pitre <nico@fluxnic.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boot/compressed/Makefile6
-rw-r--r--arch/arm/boot/compressed/decompress.c45
-rw-r--r--arch/arm/boot/compressed/misc.c109
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in8
4 files changed, 64 insertions, 104 deletions
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 2d4d88ba73bf..97c89e7de7d3 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -5,7 +5,7 @@
5# 5#
6 6
7HEAD = head.o 7HEAD = head.o
8OBJS = misc.o 8OBJS = misc.o decompress.o
9FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c 9FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
10 10
11# 11#
@@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o
106$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE 106$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
107 $(call cmd,shipped) 107 $(call cmd,shipped)
108 108
109# Don't allow any static data in misc.o, which
110# would otherwise mess up our GOT table
111CFLAGS_misc.o := -Dstatic=
112
113$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ 109$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
114 $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE 110 $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
115 $(call if_changed,ld) 111 $(call if_changed,ld)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
new file mode 100644
index 000000000000..0da382f33157
--- /dev/null
+++ b/arch/arm/boot/compressed/decompress.c
@@ -0,0 +1,45 @@
1#define _LINUX_STRING_H_
2
3#include <linux/compiler.h> /* for inline */
4#include <linux/types.h> /* for size_t */
5#include <linux/stddef.h> /* for NULL */
6#include <linux/linkage.h>
7#include <asm/string.h>
8
9extern unsigned long free_mem_ptr;
10extern unsigned long free_mem_end_ptr;
11extern void error(char *);
12
13#define STATIC static
14
15#define ARCH_HAS_DECOMP_WDOG
16
17/* Diagnostic functions */
18#ifdef DEBUG
19# define Assert(cond,msg) {if(!(cond)) error(msg);}
20# define Trace(x) fprintf x
21# define Tracev(x) {if (verbose) fprintf x ;}
22# define Tracevv(x) {if (verbose>1) fprintf x ;}
23# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
24# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
25#else
26# define Assert(cond,msg)
27# define Trace(x)
28# define Tracev(x)
29# define Tracevv(x)
30# define Tracec(c,x)
31# define Tracecv(c,x)
32#endif
33
34#ifdef CONFIG_KERNEL_GZIP
35#include "../../../../lib/decompress_inflate.c"
36#endif
37
38#ifdef CONFIG_KERNEL_LZO
39#include "../../../../lib/decompress_unlzo.c"
40#endif
41
42void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
43{
44 decompress(input, len, NULL, NULL, output, NULL, error);
45}
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 7e0fe4d42c7b..4c663fbe0a05 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -23,8 +23,8 @@ unsigned int __machine_arch_type;
23#include <linux/compiler.h> /* for inline */ 23#include <linux/compiler.h> /* for inline */
24#include <linux/types.h> /* for size_t */ 24#include <linux/types.h> /* for size_t */
25#include <linux/stddef.h> /* for NULL */ 25#include <linux/stddef.h> /* for NULL */
26#include <asm/string.h>
27#include <linux/linkage.h> 26#include <linux/linkage.h>
27#include <asm/string.h>
28 28
29#include <asm/unaligned.h> 29#include <asm/unaligned.h>
30 30
@@ -106,57 +106,7 @@ static void putstr(const char *ptr)
106 106
107#endif 107#endif
108 108
109#define __ptr_t void * 109void *memcpy(void *__dest, __const void *__src, size_t __n)
110
111#define memzero(s,n) __memzero(s,n)
112
113/*
114 * Optimised C version of memzero for the ARM.
115 */
116void __memzero (__ptr_t s, size_t n)
117{
118 union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
119 int i;
120
121 u.vp = s;
122
123 for (i = n >> 5; i > 0; i--) {
124 *u.ulp++ = 0;
125 *u.ulp++ = 0;
126 *u.ulp++ = 0;
127 *u.ulp++ = 0;
128 *u.ulp++ = 0;
129 *u.ulp++ = 0;
130 *u.ulp++ = 0;
131 *u.ulp++ = 0;
132 }
133
134 if (n & 1 << 4) {
135 *u.ulp++ = 0;
136 *u.ulp++ = 0;
137 *u.ulp++ = 0;
138 *u.ulp++ = 0;
139 }
140
141 if (n & 1 << 3) {
142 *u.ulp++ = 0;
143 *u.ulp++ = 0;
144 }
145
146 if (n & 1 << 2)
147 *u.ulp++ = 0;
148
149 if (n & 1 << 1) {
150 *u.ucp++ = 0;
151 *u.ucp++ = 0;
152 }
153
154 if (n & 1)
155 *u.ucp++ = 0;
156}
157
158static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
159 size_t __n)
160{ 110{
161 int i = 0; 111 int i = 0;
162 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; 112 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
@@ -193,59 +143,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
193/* 143/*
194 * gzip delarations 144 * gzip delarations
195 */ 145 */
196#define STATIC static
197
198/* Diagnostic functions */
199#ifdef DEBUG
200# define Assert(cond,msg) {if(!(cond)) error(msg);}
201# define Trace(x) fprintf x
202# define Tracev(x) {if (verbose) fprintf x ;}
203# define Tracevv(x) {if (verbose>1) fprintf x ;}
204# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
205# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
206#else
207# define Assert(cond,msg)
208# define Trace(x)
209# define Tracev(x)
210# define Tracevv(x)
211# define Tracec(c,x)
212# define Tracecv(c,x)
213#endif
214
215static void error(char *m);
216
217extern char input_data[]; 146extern char input_data[];
218extern char input_data_end[]; 147extern char input_data_end[];
219 148
220static unsigned char *output_data; 149unsigned char *output_data;
221static unsigned long output_ptr; 150unsigned long output_ptr;
222
223static void error(char *m);
224 151
225static void putstr(const char *); 152unsigned long free_mem_ptr;
226 153unsigned long free_mem_end_ptr;
227static unsigned long free_mem_ptr;
228static unsigned long free_mem_end_ptr;
229
230#ifdef STANDALONE_DEBUG
231#define NO_INFLATE_MALLOC
232#endif
233
234#define ARCH_HAS_DECOMP_WDOG
235
236#ifdef CONFIG_KERNEL_GZIP
237#include "../../../../lib/decompress_inflate.c"
238#endif
239
240#ifdef CONFIG_KERNEL_LZO
241#include "../../../../lib/decompress_unlzo.c"
242#endif
243 154
244#ifndef arch_error 155#ifndef arch_error
245#define arch_error(x) 156#define arch_error(x)
246#endif 157#endif
247 158
248static void error(char *x) 159void error(char *x)
249{ 160{
250 arch_error(x); 161 arch_error(x);
251 162
@@ -261,6 +172,8 @@ asmlinkage void __div0(void)
261 error("Attempting division by 0!"); 172 error("Attempting division by 0!");
262} 173}
263 174
175extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
176
264#ifndef STANDALONE_DEBUG 177#ifndef STANDALONE_DEBUG
265 178
266unsigned long 179unsigned long
@@ -281,8 +194,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
281 output_ptr = get_unaligned_le32(tmp); 194 output_ptr = get_unaligned_le32(tmp);
282 195
283 putstr("Uncompressing Linux..."); 196 putstr("Uncompressing Linux...");
284 decompress(input_data, input_data_end - input_data, 197 do_decompress(input_data, input_data_end - input_data,
285 NULL, NULL, output_data, NULL, error); 198 output_data, error);
286 putstr(" done, booting the kernel.\n"); 199 putstr(" done, booting the kernel.\n");
287 return output_ptr; 200 return output_ptr;
288} 201}
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index a5924b9b88bd..7ca9ecff652f 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -14,6 +14,13 @@ SECTIONS
14 /DISCARD/ : { 14 /DISCARD/ : {
15 *(.ARM.exidx*) 15 *(.ARM.exidx*)
16 *(.ARM.extab*) 16 *(.ARM.extab*)
17 /*
18 * Discard any r/w data - this produces a link error if we have any,
19 * which is required for PIC decompression. Local data generates
20 * GOTOFF relocations, which prevents it being relocated independently
21 * of the text/got segments.
22 */
23 *(.data)
17 } 24 }
18 25
19 . = TEXT_START; 26 . = TEXT_START;
@@ -40,7 +47,6 @@ SECTIONS
40 .got : { *(.got) } 47 .got : { *(.got) }
41 _got_end = .; 48 _got_end = .;
42 .got.plt : { *(.got.plt) } 49 .got.plt : { *(.got.plt) }
43 .data : { *(.data) }
44 _edata = .; 50 _edata = .;
45 51
46 . = BSS_START; 52 . = BSS_START;