diff options
Diffstat (limited to 'arch/arm/boot')
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 17 | ||||
-rw-r--r-- | arch/arm/boot/compressed/decompress.c | 4 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 30 | ||||
-rw-r--r-- | arch/arm/boot/compressed/misc.c | 24 |
4 files changed, 45 insertions, 30 deletions
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0c6852d..23aad07 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -98,8 +98,6 @@ endif ccflags-y := -fpic -fno-builtin asflags-y := -Wa,-march=all -# Provide size of uncompressed kernel to the decompressor via a linker symbol. -LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) @@ -122,10 +120,23 @@ lib1funcs = $(obj)/lib1funcs.o $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE $(call cmd,shipped) +# We need to prevent any GOTOFF relocs being used with references +# to symbols in the .bss section since we cannot relocate them +# independently from the rest at run time. This can be achieved by +# ensuring that no private .bss symbols exist, as global symbols +# always have a GOT entry which is what we need. +# The .data section is already discarded by the linker script so no need +# to bother about it here. +check_for_bad_syms = \ +bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ +[ -z "$$bad_syms" ] || \ + ( echo "following symbols must have non local/private scope:" >&2; \ + echo "$$bad_syms" >&2; rm -f $@; false ) + $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE $(call if_changed,ld) - @: + @$(check_for_bad_syms) $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE $(call if_changed,$(suffix_y)) diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index 4c72a97..07be5a2 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c @@ -44,7 +44,7 @@ extern void error(char *); #include "../../../../lib/decompress_unlzma.c" #endif -void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) +int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) { - decompress(input, len, NULL, NULL, output, NULL, error); + return decompress(input, len, NULL, NULL, output, NULL, error); } diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 6fdf4ab..f9da419 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -179,7 +179,7 @@ not_angel: bl cache_on restart: adr r0, LC0 - ldmia r0, {r1, r2, r3, r6, r9, r11, r12} + ldmia r0, {r1, r2, r3, r6, r10, r11, r12} ldr sp, [r0, #28] /* @@ -188,6 +188,20 @@ restart: adr r0, LC0 */ sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata + add r10, r10, r0 @ inflated kernel size location + + /* + * The kernel build system appends the size of the + * decompressed kernel at the end of the compressed data + * in little-endian form. + */ + ldrb r9, [r10, #0] + ldrb lr, [r10, #1] + orr r9, r9, lr, lsl #8 + ldrb lr, [r10, #2] + ldrb r10, [r10, #3] + orr r9, r9, lr, lsl #16 + orr r9, r9, r10, lsl #24 #ifndef CONFIG_ZBOOT_ROM /* malloc space is above the relocated stack (64k max) */ @@ -347,10 +361,10 @@ LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word _edata @ r6 - .word _image_size @ r9 + .word input_data_end - 4 @ r10 (inflated size location) .word _got_start @ r11 .word _got_end @ ip - .word user_stack_end @ sp + .word .L_user_stack_end @ sp .size LC0, . - LC0 #ifdef CONFIG_ARCH_RPC @@ -763,12 +777,6 @@ proc_types: W(b) __armv4_mmu_cache_off W(b) __armv6_mmu_cache_flush - .word 0x560f5810 @ Marvell PJ4 ARMv6 - .word 0xff0ffff0 - W(b) __armv4_mmu_cache_on - W(b) __armv4_mmu_cache_off - W(b) __armv6_mmu_cache_flush - .word 0x000f0000 @ new CPU Id .word 0x000f0000 W(b) __armv7_mmu_cache_on @@ -1094,5 +1102,5 @@ reloc_code_end: .align .section ".stack", "aw", %nobits -user_stack: .space 4096 -user_stack_end: +.L_user_stack: .space 4096 +.L_user_stack_end: diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 2df3826..832d372 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -26,8 +26,6 @@ unsigned int __machine_arch_type; #include <linux/linkage.h> #include <asm/string.h> -#include <asm/unaligned.h> - static void putstr(const char *ptr); extern void error(char *x); @@ -139,13 +137,12 @@ void *memcpy(void *__dest, __const void *__src, size_t __n) } /* - * gzip delarations + * gzip declarations */ extern char input_data[]; extern char input_data_end[]; unsigned char *output_data; -unsigned long output_ptr; unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; @@ -170,15 +167,15 @@ asmlinkage void __div0(void) error("Attempting division by 0!"); } -extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); +extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); -unsigned long +void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, int arch_id) { - unsigned char *tmp; + int ret; output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; @@ -187,12 +184,11 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, arch_decomp_setup(); - tmp = (unsigned char *) (((unsigned long)input_data_end) - 4); - output_ptr = get_unaligned_le32(tmp); - putstr("Uncompressing Linux..."); - do_decompress(input_data, input_data_end - input_data, - output_data, error); - putstr(" done, booting the kernel.\n"); - return output_ptr; + ret = do_decompress(input_data, input_data_end - input_data, + output_data, error); + if (ret) + error("decompressor returned an error"); + else + putstr(" done, booting the kernel.\n"); } |