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