202 lines
3.9 KiB
ArmAsm
202 lines
3.9 KiB
ArmAsm
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||
|
/*
|
||
|
* linux/arch/unicore32/boot/compressed/head.S
|
||
|
*
|
||
|
* Code specific to PKUnity SoC and UniCore ISA
|
||
|
*
|
||
|
* Copyright (C) 2001-2010 GUAN Xue-tao
|
||
|
*/
|
||
|
#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:
|