| /* |
| * 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: |