diff options
Diffstat (limited to 'arch/arm/boot/compressed')
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/boot/compressed/decompress.c | 45 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 76 | ||||
-rw-r--r-- | arch/arm/boot/compressed/misc.c | 122 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 11 |
5 files changed, 119 insertions, 141 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 @@ # HEAD = head.o -OBJS = misc.o +OBJS = misc.o decompress.o FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c # @@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE $(call cmd,shipped) -# Don't allow any static data in misc.o, which -# would otherwise mess up our GOT table -CFLAGS_misc.o := -Dstatic= - $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE $(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 @@ +#define _LINUX_STRING_H_ + +#include <linux/compiler.h> /* for inline */ +#include <linux/types.h> /* for size_t */ +#include <linux/stddef.h> /* for NULL */ +#include <linux/linkage.h> +#include <asm/string.h> + +extern unsigned long free_mem_ptr; +extern unsigned long free_mem_end_ptr; +extern void error(char *); + +#define STATIC static + +#define ARCH_HAS_DECOMP_WDOG + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +#ifdef CONFIG_KERNEL_LZO +#include "../../../../lib/decompress_unlzo.c" +#endif + +void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) +{ + 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 d356af7cef82..535a91daaa53 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -22,19 +22,27 @@ #if defined(CONFIG_DEBUG_ICEDCC) #ifdef CONFIG_CPU_V6 - .macro loadsp, rb + .macro loadsp, rb, tmp .endm .macro writeb, ch, rb mcr p14, 0, \ch, c0, c5, 0 .endm +#elif defined(CONFIG_CPU_V7) + .macro loadsp, rb, tmp + .endm + .macro writeb, ch, rb +wait: mrc p14, 0, pc, c0, c1, 0 + bcs wait + mcr p14, 0, \ch, c0, c5, 0 + .endm #elif defined(CONFIG_CPU_XSCALE) - .macro loadsp, rb + .macro loadsp, rb, tmp .endm .macro writeb, ch, rb mcr p14, 0, \ch, c8, c0, 0 .endm #else - .macro loadsp, rb + .macro loadsp, rb, tmp .endm .macro writeb, ch, rb mcr p14, 0, \ch, c1, c0, 0 @@ -50,7 +58,7 @@ .endm #if defined(CONFIG_ARCH_SA1100) - .macro loadsp, rb + .macro loadsp, rb, tmp mov \rb, #0x80000000 @ physical base address #ifdef CONFIG_DEBUG_LL_SER3 add \rb, \rb, #0x00050000 @ Ser3 @@ -59,13 +67,13 @@ #endif .endm #elif defined(CONFIG_ARCH_S3C2410) - .macro loadsp, rb + .macro loadsp, rb, tmp mov \rb, #0x50000000 add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT .endm #else - .macro loadsp, rb - addruart \rb + .macro loadsp, rb, tmp + addruart \rb, \tmp .endm #endif #endif @@ -162,8 +170,8 @@ not_angel: .text adr r0, LC0 - ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} ) - THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, ip} ) + ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp}) + THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} ) THUMB( ldr sp, [r0, #28] ) subs r0, r0, r1 @ calculate the delta offset @@ -174,12 +182,13 @@ not_angel: /* * We're running at a different address. We need to fix * up various pointers: - * r5 - zImage base address - * r6 - GOT start + * r5 - zImage base address (_start) + * r6 - size of decompressed image + * r11 - GOT start * ip - GOT end */ add r5, r5, r0 - add r6, r6, r0 + add r11, r11, r0 add ip, ip, r0 #ifndef CONFIG_ZBOOT_ROM @@ -197,10 +206,10 @@ not_angel: /* * Relocate all entries in the GOT table. */ -1: ldr r1, [r6, #0] @ relocate entries in the GOT +1: ldr r1, [r11, #0] @ relocate entries in the GOT add r1, r1, r0 @ table. This fixes up the - str r1, [r6], #4 @ C references. - cmp r6, ip + str r1, [r11], #4 @ C references. + cmp r11, ip blo 1b #else @@ -208,12 +217,12 @@ not_angel: * Relocate entries in the GOT table. We only relocate * the entries that are outside the (relocated) BSS region. */ -1: ldr r1, [r6, #0] @ relocate entries in the GOT +1: ldr r1, [r11, #0] @ relocate entries in the GOT cmp r1, r2 @ entry < bss_start || cmphs r3, r1 @ _end < entry addlo r1, r1, r0 @ table. This fixes up the - str r1, [r6], #4 @ C references. - cmp r6, ip + str r1, [r11], #4 @ C references. + cmp r11, ip blo 1b #endif @@ -239,6 +248,7 @@ not_relocated: mov r0, #0 * Check to see if we will overwrite ourselves. * r4 = final kernel address * r5 = start of this image + * r6 = size of decompressed image * r2 = end of malloc space (and therefore this image) * We basically want: * r4 >= r2 -> OK @@ -246,8 +256,7 @@ not_relocated: mov r0, #0 */ cmp r4, r2 bhs wont_overwrite - sub r3, sp, r5 @ > compressed kernel size - add r0, r4, r3, lsl #2 @ allow for 4x expansion + add r0, r4, r6 cmp r0, r5 bls wont_overwrite @@ -263,7 +272,6 @@ not_relocated: mov r0, #0 * r1-r3 = unused * r4 = kernel execution address * r5 = decompressed kernel start - * r6 = processor ID * r7 = architecture ID * r8 = atags pointer * r9-r12,r14 = corrupted @@ -304,7 +312,8 @@ LC0: .word LC0 @ r1 .word _end @ r3 .word zreladdr @ r4 .word _start @ r5 - .word _got_start @ r6 + .word _image_size @ r6 + .word _got_start @ r11 .word _got_end @ ip .word user_stack+4096 @ sp LC1: .word reloc_end - reloc_start @@ -328,7 +337,6 @@ params: ldr r0, =params_phys * * On entry, * r4 = kernel execution address - * r6 = processor ID * r7 = architecture number * r8 = atags pointer * r9 = run-time address of "start" (???) @@ -534,7 +542,6 @@ __common_mmu_cache_on: * r1-r3 = unused * r4 = kernel execution address * r5 = decompressed kernel start - * r6 = processor ID * r7 = architecture ID * r8 = atags pointer * r9-r12,r14 = corrupted @@ -573,19 +580,19 @@ call_kernel: bl cache_clean_flush * r1 = corrupted * r2 = corrupted * r3 = block offset - * r6 = corrupted + * r9 = corrupted * r12 = corrupted */ call_cache_fn: adr r12, proc_types #ifdef CONFIG_CPU_CP15 - mrc p15, 0, r6, c0, c0 @ get processor ID + mrc p15, 0, r9, c0, c0 @ get processor ID #else - ldr r6, =CONFIG_PROCESSOR_ID + ldr r9, =CONFIG_PROCESSOR_ID #endif 1: ldr r1, [r12, #0] @ get value ldr r2, [r12, #4] @ get mask - eor r1, r1, r6 @ (real ^ match) + eor r1, r1, r9 @ (real ^ match) tst r1, r2 @ & mask ARM( addeq pc, r12, r3 ) @ call cache function THUMB( addeq r12, r3 ) @@ -770,8 +777,7 @@ proc_types: * Turn off the Cache and MMU. ARMv3 does not support * reading the control register, but ARMv4 does. * - * On entry, r6 = processor ID - * On exit, r0, r1, r2, r3, r12 corrupted + * On exit, r0, r1, r2, r3, r9, r12 corrupted * This routine must preserve: r4, r6, r7 */ .align 5 @@ -844,10 +850,8 @@ __armv3_mmu_cache_off: /* * Clean and flush the cache to maintain consistency. * - * On entry, - * r6 = processor ID * On exit, - * r1, r2, r3, r11, r12 corrupted + * r1, r2, r3, r9, r11, r12 corrupted * This routine must preserve: * r0, r4, r5, r6, r7 */ @@ -959,7 +963,7 @@ __armv4_mmu_cache_flush: mov r2, #64*1024 @ default: 32K dcache size (*2) mov r11, #32 @ default: 32 byte line size mrc p15, 0, r3, c0, c0, 1 @ read cache type - teq r3, r6 @ cache ID register present? + teq r3, r9 @ cache ID register present? beq no_cache_id mov r1, r3, lsr #18 and r1, r1, #7 @@ -1017,7 +1021,7 @@ phex: adr r3, phexbuf strb r2, [r3, r1] b 1b -puts: loadsp r3 +puts: loadsp r3, r1 1: ldrb r2, [r0], #1 teq r2, #0 moveq pc, lr @@ -1034,7 +1038,7 @@ puts: loadsp r3 putc: mov r2, r0 mov r0, #0 - loadsp r3 + loadsp r3, r1 b 2b memdump: mov r12, r0 diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 7e0fe4d42c7b..d32bc71c1f78 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -23,8 +23,8 @@ unsigned int __machine_arch_type; #include <linux/compiler.h> /* for inline */ #include <linux/types.h> /* for size_t */ #include <linux/stddef.h> /* for NULL */ -#include <asm/string.h> #include <linux/linkage.h> +#include <asm/string.h> #include <asm/unaligned.h> @@ -53,6 +53,18 @@ static void icedcc_putc(int ch) asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch)); } + +#elif defined(CONFIG_CPU_V7) + +static void icedcc_putc(int ch) +{ + asm( + "wait: mrc p14, 0, pc, c0, c1, 0 \n\ + bcs wait \n\ + mcr p14, 0, %0, c0, c5, 0 " + : : "r" (ch)); +} + #elif defined(CONFIG_CPU_XSCALE) static void icedcc_putc(int ch) @@ -88,7 +100,6 @@ static void icedcc_putc(int ch) #endif #define putc(ch) icedcc_putc(ch) -#define flush() do { } while (0) #endif static void putstr(const char *ptr) @@ -106,57 +117,7 @@ static void putstr(const char *ptr) #endif -#define __ptr_t void * - -#define memzero(s,n) __memzero(s,n) - -/* - * Optimised C version of memzero for the ARM. - */ -void __memzero (__ptr_t s, size_t n) -{ - union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; - int i; - - u.vp = s; - - for (i = n >> 5; i > 0; i--) { - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - } - - if (n & 1 << 4) { - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - *u.ulp++ = 0; - } - - if (n & 1 << 3) { - *u.ulp++ = 0; - *u.ulp++ = 0; - } - - if (n & 1 << 2) - *u.ulp++ = 0; - - if (n & 1 << 1) { - *u.ucp++ = 0; - *u.ucp++ = 0; - } - - if (n & 1) - *u.ucp++ = 0; -} - -static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, - size_t __n) +void *memcpy(void *__dest, __const void *__src, size_t __n) { int i = 0; unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; @@ -193,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, /* * gzip delarations */ -#define STATIC static - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static void error(char *m); - extern char input_data[]; extern char input_data_end[]; -static unsigned char *output_data; -static unsigned long output_ptr; - -static void error(char *m); - -static void putstr(const char *); - -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; +unsigned char *output_data; +unsigned long output_ptr; -#ifdef STANDALONE_DEBUG -#define NO_INFLATE_MALLOC -#endif - -#define ARCH_HAS_DECOMP_WDOG - -#ifdef CONFIG_KERNEL_GZIP -#include "../../../../lib/decompress_inflate.c" -#endif - -#ifdef CONFIG_KERNEL_LZO -#include "../../../../lib/decompress_unlzo.c" -#endif +unsigned long free_mem_ptr; +unsigned long free_mem_end_ptr; #ifndef arch_error #define arch_error(x) #endif -static void error(char *x) +void error(char *x) { arch_error(x); @@ -261,6 +183,8 @@ asmlinkage void __div0(void) error("Attempting division by 0!"); } +extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); + #ifndef STANDALONE_DEBUG unsigned long @@ -281,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, output_ptr = get_unaligned_le32(tmp); putstr("Uncompressing Linux..."); - decompress(input_data, input_data_end - input_data, - NULL, NULL, output_data, NULL, error); + do_decompress(input_data, input_data_end - input_data, + output_data, error); putstr(" done, booting the kernel.\n"); return output_ptr; } diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index a5924b9b88bd..d08168941bd6 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -14,6 +14,13 @@ SECTIONS /DISCARD/ : { *(.ARM.exidx*) *(.ARM.extab*) + /* + * Discard any r/w data - this produces a link error if we have any, + * which is required for PIC decompression. Local data generates + * GOTOFF relocations, which prevents it being relocated independently + * of the text/got segments. + */ + *(.data) } . = TEXT_START; @@ -36,11 +43,13 @@ SECTIONS _etext = .; + /* Assume size of decompressed image is 4x the compressed image */ + _image_size = (_etext - _text) * 4; + _got_start = .; .got : { *(.got) } _got_end = .; .got.plt : { *(.got.plt) } - .data : { *(.data) } _edata = .; . = BSS_START; |