| /* | |
| * linux/arch/unicore32/boot/compressed/head.S | |
| * | |
| * Code specific to PKUnity SoC and UniCore ISA | |
| * | |
| * Copyright (C) 2001-2010 GUAN Xue-tao | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 2 as | |
| * published by the Free Software Foundation. | |
| */ | |
| #include <linux/linkage.h> | |
| #include <mach/memory.h> | |
| #define csub cmpsub | |
| #define cand cmpand | |
| #define nop8 nop; nop; nop; nop; nop; nop; nop; nop | |
| .section ".start", #alloc, #execinstr | |
| .text | |
| start: | |
| .type start,#function | |
| /* Initialize ASR, PRIV mode and INTR off */ | |
| mov r0, #0xD3 | |
| mov.a asr, r0 | |
| adr r0, LC0 | |
| ldm (r1, r2, r3, r5, r6, r7, r8), [r0]+ | |
| ldw sp, [r0+], #28 | |
| sub.a r0, r0, r1 @ calculate the delta offset | |
| /* | |
| * if delta is zero, we are running at the address | |
| * we were linked at. | |
| */ | |
| beq not_relocated | |
| /* | |
| * We're running at a different address. We need to fix | |
| * up various pointers: | |
| * r5 - zImage base address (_start) | |
| * r7 - GOT start | |
| * r8 - GOT end | |
| */ | |
| add r5, r5, r0 | |
| add r7, r7, r0 | |
| add r8, r8, r0 | |
| /* | |
| * we need to fix up pointers into the BSS region. | |
| * r2 - BSS start | |
| * r3 - BSS end | |
| * sp - stack pointer | |
| */ | |
| add r2, r2, r0 | |
| add r3, r3, r0 | |
| add sp, sp, r0 | |
| /* | |
| * Relocate all entries in the GOT table. | |
| * This fixes up the C references. | |
| * r7 - GOT start | |
| * r8 - GOT end | |
| */ | |
| 1001: ldw r1, [r7+], #0 | |
| add r1, r1, r0 | |
| stw.w r1, [r7]+, #4 | |
| csub.a r7, r8 | |
| bub 1001b | |
| not_relocated: | |
| /* | |
| * Clear BSS region. | |
| * r2 - BSS start | |
| * r3 - BSS end | |
| */ | |
| mov r0, #0 | |
| 1002: stw.w r0, [r2]+, #4 | |
| csub.a r2, r3 | |
| bub 1002b | |
| /* | |
| * Turn on the cache. | |
| */ | |
| mov r0, #0 | |
| movc p0.c5, r0, #28 @ cache invalidate all | |
| nop8 | |
| movc p0.c6, r0, #6 @ tlb invalidate all | |
| nop8 | |
| mov r0, #0x1c @ en icache and wb dcache | |
| movc p0.c1, r0, #0 | |
| nop8 | |
| /* | |
| * Set up some pointers, for starting decompressing. | |
| */ | |
| mov r1, sp @ malloc space above stack | |
| add r2, sp, #0x10000 @ 64k max | |
| /* | |
| * 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 | |
| * r4 + image length <= r5 -> OK | |
| */ | |
| ldw r4, =KERNEL_IMAGE_START | |
| csub.a r4, r2 | |
| bea wont_overwrite | |
| add r0, r4, r6 | |
| csub.a r0, r5 | |
| beb wont_overwrite | |
| /* | |
| * If overwrite, just print error message | |
| */ | |
| b __error_overwrite | |
| /* | |
| * We're not in danger of overwriting ourselves. | |
| * Do this the simple way. | |
| */ | |
| wont_overwrite: | |
| /* | |
| * decompress_kernel: | |
| * r0: output_start | |
| * r1: free_mem_ptr_p | |
| * r2: free_mem_ptr_end_p | |
| */ | |
| mov r0, r4 | |
| b.l decompress_kernel @ C functions | |
| /* | |
| * Clean and flush the cache to maintain consistency. | |
| */ | |
| mov r0, #0 | |
| movc p0.c5, r0, #14 @ flush dcache | |
| nop8 | |
| movc p0.c5, r0, #20 @ icache invalidate all | |
| nop8 | |
| /* | |
| * Turn off the Cache and MMU. | |
| */ | |
| mov r0, #0 @ disable i/d cache and MMU | |
| movc p0.c1, r0, #0 | |
| nop8 | |
| mov r0, #0 @ must be zero | |
| ldw r4, =KERNEL_IMAGE_START | |
| mov pc, r4 @ call kernel | |
| .align 2 | |
| .type LC0, #object | |
| LC0: .word LC0 @ r1 | |
| .word __bss_start @ r2 | |
| .word _end @ r3 | |
| .word _start @ r5 | |
| .word _image_size @ r6 | |
| .word _got_start @ r7 | |
| .word _got_end @ r8 | |
| .word decompress_stack_end @ sp | |
| .size LC0, . - LC0 | |
| print_string: | |
| #ifdef CONFIG_DEBUG_OCD | |
| 2001: ldb.w r1, [r0]+, #1 | |
| csub.a r1, #0 | |
| bne 2002f | |
| mov pc, lr | |
| 2002: | |
| movc r2, p1.c0, #0 | |
| cand.a r2, #2 | |
| bne 2002b | |
| movc p1.c1, r1, #1 | |
| csub.a r1, #'\n' | |
| cmoveq r1, #'\r' | |
| beq 2002b | |
| b 2001b | |
| #else | |
| mov pc, lr | |
| #endif | |
| __error_overwrite: | |
| adr r0, str_error | |
| b.l print_string | |
| 2001: nop8 | |
| b 2001b | |
| str_error: .asciz "\nError: Kernel address OVERWRITE\n" | |
| .align | |
| .ltorg | |
| .align 4 | |
| .section ".stack", "aw", %nobits | |
| decompress_stack: .space 4096 | |
| decompress_stack_end: |