diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-07 03:34:02 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-07 03:34:02 -0400 |
commit | 7b76415375ba91f5a06f8d5179278c03d6151d16 (patch) | |
tree | 11f156309efb05174906954efc5159a15b202437 /arch/arm/boot | |
parent | c93212f387fdf5180d9d13cc207419abd5b3ec17 (diff) | |
parent | 8d7e4cc2c8ea1d180d32d902eb899f27d3ee53d7 (diff) |
Merge branch 'zImage_fixes' of git://git.linaro.org/people/nico/linux into devel-stable
Diffstat (limited to 'arch/arm/boot')
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 19 | ||||
-rw-r--r-- | arch/arm/boot/compressed/decompress.c | 4 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 57 | ||||
-rw-r--r-- | arch/arm/boot/compressed/misc.c | 24 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 1 |
5 files changed, 70 insertions, 35 deletions
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 8ebbb511c783..23aad0722303 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
@@ -74,7 +74,7 @@ ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) | |||
74 | ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) | 74 | ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) |
75 | else | 75 | else |
76 | ZTEXTADDR := 0 | 76 | ZTEXTADDR := 0 |
77 | ZBSSADDR := ALIGN(4) | 77 | ZBSSADDR := ALIGN(8) |
78 | endif | 78 | endif |
79 | 79 | ||
80 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ | 80 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ |
@@ -98,8 +98,6 @@ endif | |||
98 | ccflags-y := -fpic -fno-builtin | 98 | ccflags-y := -fpic -fno-builtin |
99 | asflags-y := -Wa,-march=all | 99 | asflags-y := -Wa,-march=all |
100 | 100 | ||
101 | # Provide size of uncompressed kernel to the decompressor via a linker symbol. | ||
102 | LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image) | ||
103 | # Supply ZRELADDR to the decompressor via a linker symbol. | 101 | # Supply ZRELADDR to the decompressor via a linker symbol. |
104 | ifneq ($(CONFIG_AUTO_ZRELADDR),y) | 102 | ifneq ($(CONFIG_AUTO_ZRELADDR),y) |
105 | LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) | 103 | LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) |
@@ -122,10 +120,23 @@ lib1funcs = $(obj)/lib1funcs.o | |||
122 | $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE | 120 | $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE |
123 | $(call cmd,shipped) | 121 | $(call cmd,shipped) |
124 | 122 | ||
123 | # We need to prevent any GOTOFF relocs being used with references | ||
124 | # to symbols in the .bss section since we cannot relocate them | ||
125 | # independently from the rest at run time. This can be achieved by | ||
126 | # ensuring that no private .bss symbols exist, as global symbols | ||
127 | # always have a GOT entry which is what we need. | ||
128 | # The .data section is already discarded by the linker script so no need | ||
129 | # to bother about it here. | ||
130 | check_for_bad_syms = \ | ||
131 | bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ | ||
132 | [ -z "$$bad_syms" ] || \ | ||
133 | ( echo "following symbols must have non local/private scope:" >&2; \ | ||
134 | echo "$$bad_syms" >&2; rm -f $@; false ) | ||
135 | |||
125 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ | 136 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ |
126 | $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE | 137 | $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE |
127 | $(call if_changed,ld) | 138 | $(call if_changed,ld) |
128 | @: | 139 | @$(check_for_bad_syms) |
129 | 140 | ||
130 | $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE | 141 | $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE |
131 | $(call if_changed,$(suffix_y)) | 142 | $(call if_changed,$(suffix_y)) |
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index 4c72a97bc3e1..07be5a2f8302 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c | |||
@@ -44,7 +44,7 @@ extern void error(char *); | |||
44 | #include "../../../../lib/decompress_unlzma.c" | 44 | #include "../../../../lib/decompress_unlzma.c" |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) | 47 | int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) |
48 | { | 48 | { |
49 | decompress(input, len, NULL, NULL, output, NULL, error); | 49 | return decompress(input, len, NULL, NULL, output, NULL, error); |
50 | } | 50 | } |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index a36f4526689b..c363458a4e63 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -179,16 +179,29 @@ not_angel: | |||
179 | bl cache_on | 179 | bl cache_on |
180 | 180 | ||
181 | restart: adr r0, LC0 | 181 | restart: adr r0, LC0 |
182 | ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12} | 182 | ldmia r0, {r1, r2, r3, r6, r10, r11, r12} |
183 | ldr sp, [r0, #32] | 183 | ldr sp, [r0, #28] |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * We might be running at a different address. We need | 186 | * We might be running at a different address. We need |
187 | * to fix up various pointers. | 187 | * to fix up various pointers. |
188 | */ | 188 | */ |
189 | sub r0, r0, r1 @ calculate the delta offset | 189 | sub r0, r0, r1 @ calculate the delta offset |
190 | add r5, r5, r0 @ _start | ||
191 | add r6, r6, r0 @ _edata | 190 | add r6, r6, r0 @ _edata |
191 | add r10, r10, r0 @ inflated kernel size location | ||
192 | |||
193 | /* | ||
194 | * The kernel build system appends the size of the | ||
195 | * decompressed kernel at the end of the compressed data | ||
196 | * in little-endian form. | ||
197 | */ | ||
198 | ldrb r9, [r10, #0] | ||
199 | ldrb lr, [r10, #1] | ||
200 | orr r9, r9, lr, lsl #8 | ||
201 | ldrb lr, [r10, #2] | ||
202 | ldrb r10, [r10, #3] | ||
203 | orr r9, r9, lr, lsl #16 | ||
204 | orr r9, r9, r10, lsl #24 | ||
192 | 205 | ||
193 | #ifndef CONFIG_ZBOOT_ROM | 206 | #ifndef CONFIG_ZBOOT_ROM |
194 | /* malloc space is above the relocated stack (64k max) */ | 207 | /* malloc space is above the relocated stack (64k max) */ |
@@ -206,31 +219,40 @@ restart: adr r0, LC0 | |||
206 | /* | 219 | /* |
207 | * Check to see if we will overwrite ourselves. | 220 | * Check to see if we will overwrite ourselves. |
208 | * r4 = final kernel address | 221 | * r4 = final kernel address |
209 | * r5 = start of this image | ||
210 | * r9 = size of decompressed image | 222 | * r9 = size of decompressed image |
211 | * r10 = end of this image, including bss/stack/malloc space if non XIP | 223 | * r10 = end of this image, including bss/stack/malloc space if non XIP |
212 | * We basically want: | 224 | * We basically want: |
213 | * r4 >= r10 -> OK | 225 | * r4 - 16k page directory >= r10 -> OK |
214 | * r4 + image length <= r5 -> OK | 226 | * r4 + image length <= current position (pc) -> OK |
215 | */ | 227 | */ |
228 | add r10, r10, #16384 | ||
216 | cmp r4, r10 | 229 | cmp r4, r10 |
217 | bhs wont_overwrite | 230 | bhs wont_overwrite |
218 | add r10, r4, r9 | 231 | add r10, r4, r9 |
219 | cmp r10, r5 | 232 | ARM( cmp r10, pc ) |
233 | THUMB( mov lr, pc ) | ||
234 | THUMB( cmp r10, lr ) | ||
220 | bls wont_overwrite | 235 | bls wont_overwrite |
221 | 236 | ||
222 | /* | 237 | /* |
223 | * Relocate ourselves past the end of the decompressed kernel. | 238 | * Relocate ourselves past the end of the decompressed kernel. |
224 | * r5 = start of this image | ||
225 | * r6 = _edata | 239 | * r6 = _edata |
226 | * r10 = end of the decompressed kernel | 240 | * r10 = end of the decompressed kernel |
227 | * Because we always copy ahead, we need to do it from the end and go | 241 | * Because we always copy ahead, we need to do it from the end and go |
228 | * backward in case the source and destination overlap. | 242 | * backward in case the source and destination overlap. |
229 | */ | 243 | */ |
230 | /* Round up to next 256-byte boundary. */ | 244 | /* |
231 | add r10, r10, #256 | 245 | * Bump to the next 256-byte boundary with the size of |
246 | * the relocation code added. This avoids overwriting | ||
247 | * ourself when the offset is small. | ||
248 | */ | ||
249 | add r10, r10, #((reloc_code_end - restart + 256) & ~255) | ||
232 | bic r10, r10, #255 | 250 | bic r10, r10, #255 |
233 | 251 | ||
252 | /* Get start of code we want to copy and align it down. */ | ||
253 | adr r5, restart | ||
254 | bic r5, r5, #31 | ||
255 | |||
234 | sub r9, r6, r5 @ size to copy | 256 | sub r9, r6, r5 @ size to copy |
235 | add r9, r9, #31 @ rounded up to a multiple | 257 | add r9, r9, #31 @ rounded up to a multiple |
236 | bic r9, r9, #31 @ ... of 32 bytes | 258 | bic r9, r9, #31 @ ... of 32 bytes |
@@ -245,6 +267,11 @@ restart: adr r0, LC0 | |||
245 | /* Preserve offset to relocated code. */ | 267 | /* Preserve offset to relocated code. */ |
246 | sub r6, r9, r6 | 268 | sub r6, r9, r6 |
247 | 269 | ||
270 | #ifndef CONFIG_ZBOOT_ROM | ||
271 | /* cache_clean_flush may use the stack, so relocate it */ | ||
272 | add sp, sp, r6 | ||
273 | #endif | ||
274 | |||
248 | bl cache_clean_flush | 275 | bl cache_clean_flush |
249 | 276 | ||
250 | adr r0, BSYM(restart) | 277 | adr r0, BSYM(restart) |
@@ -333,12 +360,11 @@ not_relocated: mov r0, #0 | |||
333 | LC0: .word LC0 @ r1 | 360 | LC0: .word LC0 @ r1 |
334 | .word __bss_start @ r2 | 361 | .word __bss_start @ r2 |
335 | .word _end @ r3 | 362 | .word _end @ r3 |
336 | .word _start @ r5 | ||
337 | .word _edata @ r6 | 363 | .word _edata @ r6 |
338 | .word _image_size @ r9 | 364 | .word input_data_end - 4 @ r10 (inflated size location) |
339 | .word _got_start @ r11 | 365 | .word _got_start @ r11 |
340 | .word _got_end @ ip | 366 | .word _got_end @ ip |
341 | .word user_stack_end @ sp | 367 | .word .L_user_stack_end @ sp |
342 | .size LC0, . - LC0 | 368 | .size LC0, . - LC0 |
343 | 369 | ||
344 | #ifdef CONFIG_ARCH_RPC | 370 | #ifdef CONFIG_ARCH_RPC |
@@ -1056,8 +1082,9 @@ memdump: mov r12, r0 | |||
1056 | #endif | 1082 | #endif |
1057 | 1083 | ||
1058 | .ltorg | 1084 | .ltorg |
1085 | reloc_code_end: | ||
1059 | 1086 | ||
1060 | .align | 1087 | .align |
1061 | .section ".stack", "aw", %nobits | 1088 | .section ".stack", "aw", %nobits |
1062 | user_stack: .space 4096 | 1089 | .L_user_stack: .space 4096 |
1063 | user_stack_end: | 1090 | .L_user_stack_end: |
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 2df38263124c..832d37236c59 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c | |||
@@ -26,8 +26,6 @@ unsigned int __machine_arch_type; | |||
26 | #include <linux/linkage.h> | 26 | #include <linux/linkage.h> |
27 | #include <asm/string.h> | 27 | #include <asm/string.h> |
28 | 28 | ||
29 | #include <asm/unaligned.h> | ||
30 | |||
31 | 29 | ||
32 | static void putstr(const char *ptr); | 30 | static void putstr(const char *ptr); |
33 | extern void error(char *x); | 31 | extern void error(char *x); |
@@ -139,13 +137,12 @@ void *memcpy(void *__dest, __const void *__src, size_t __n) | |||
139 | } | 137 | } |
140 | 138 | ||
141 | /* | 139 | /* |
142 | * gzip delarations | 140 | * gzip declarations |
143 | */ | 141 | */ |
144 | extern char input_data[]; | 142 | extern char input_data[]; |
145 | extern char input_data_end[]; | 143 | extern char input_data_end[]; |
146 | 144 | ||
147 | unsigned char *output_data; | 145 | unsigned char *output_data; |
148 | unsigned long output_ptr; | ||
149 | 146 | ||
150 | unsigned long free_mem_ptr; | 147 | unsigned long free_mem_ptr; |
151 | unsigned long free_mem_end_ptr; | 148 | unsigned long free_mem_end_ptr; |
@@ -170,15 +167,15 @@ asmlinkage void __div0(void) | |||
170 | error("Attempting division by 0!"); | 167 | error("Attempting division by 0!"); |
171 | } | 168 | } |
172 | 169 | ||
173 | extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); | 170 | extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); |
174 | 171 | ||
175 | 172 | ||
176 | unsigned long | 173 | void |
177 | decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, | 174 | decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, |
178 | unsigned long free_mem_ptr_end_p, | 175 | unsigned long free_mem_ptr_end_p, |
179 | int arch_id) | 176 | int arch_id) |
180 | { | 177 | { |
181 | unsigned char *tmp; | 178 | int ret; |
182 | 179 | ||
183 | output_data = (unsigned char *)output_start; | 180 | output_data = (unsigned char *)output_start; |
184 | free_mem_ptr = free_mem_ptr_p; | 181 | free_mem_ptr = free_mem_ptr_p; |
@@ -187,12 +184,11 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, | |||
187 | 184 | ||
188 | arch_decomp_setup(); | 185 | arch_decomp_setup(); |
189 | 186 | ||
190 | tmp = (unsigned char *) (((unsigned long)input_data_end) - 4); | ||
191 | output_ptr = get_unaligned_le32(tmp); | ||
192 | |||
193 | putstr("Uncompressing Linux..."); | 187 | putstr("Uncompressing Linux..."); |
194 | do_decompress(input_data, input_data_end - input_data, | 188 | ret = do_decompress(input_data, input_data_end - input_data, |
195 | output_data, error); | 189 | output_data, error); |
196 | putstr(" done, booting the kernel.\n"); | 190 | if (ret) |
197 | return output_ptr; | 191 | error("decompressor returned an error"); |
192 | else | ||
193 | putstr(" done, booting the kernel.\n"); | ||
198 | } | 194 | } |
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 5309909d7282..ea80abe78844 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in | |||
@@ -54,6 +54,7 @@ SECTIONS | |||
54 | .bss : { *(.bss) } | 54 | .bss : { *(.bss) } |
55 | _end = .; | 55 | _end = .; |
56 | 56 | ||
57 | . = ALIGN(8); /* the stack must be 64-bit aligned */ | ||
57 | .stack : { *(.stack) } | 58 | .stack : { *(.stack) } |
58 | 59 | ||
59 | .stab 0 : { *(.stab) } | 60 | .stab 0 : { *(.stab) } |