1/*
2 * linux/arch/unicore32/boot/compressed/head.S
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/linkage.h>
13#include <mach/memory.h>
14
15#define csub	cmpsub
16#define cand	cmpand
17#define nop8	nop; nop; nop; nop; nop; nop; nop; nop
18
19		.section ".start", #alloc, #execinstr
20		.text
21start:
22		.type	start,#function
23
24		/* Initialize ASR, PRIV mode and INTR off */
25		mov	r0, #0xD3
26		mov.a	asr, r0
27
28		adr	r0, LC0
29		ldm	(r1, r2, r3, r5, r6, r7, r8), [r0]+
30		ldw	sp, [r0+], #28
31		sub.a	r0, r0, r1		@ calculate the delta offset
32
33		/*
34		 * if delta is zero, we are running at the address
35		 * we were linked at.
36		 */
37		beq	not_relocated
38
39		/*
40		 * We're running at a different address.  We need to fix
41		 * up various pointers:
42		 *   r5 - zImage base address (_start)
43		 *   r7 - GOT start
44		 *   r8 - GOT end
45		 */
46		add	r5, r5, r0
47		add	r7, r7, r0
48		add	r8, r8, r0
49
50		/*
51		 * we need to fix up pointers into the BSS region.
52		 *   r2 - BSS start
53		 *   r3 - BSS end
54		 *   sp - stack pointer
55		 */
56		add	r2, r2, r0
57		add	r3, r3, r0
58		add	sp, sp, r0
59
60		/*
61		 * Relocate all entries in the GOT table.
62		 * This fixes up the C references.
63		 *   r7 - GOT start
64		 *   r8 - GOT end
65		 */
661001:		ldw	r1, [r7+], #0
67		add	r1, r1, r0
68		stw.w	r1, [r7]+, #4
69		csub.a	r7, r8
70		bub	1001b
71
72not_relocated:
73		/*
74		 * Clear BSS region.
75		 *   r2 - BSS start
76		 *   r3 - BSS end
77		 */
78		mov	r0, #0
791002:		stw.w	r0, [r2]+, #4
80		csub.a	r2, r3
81		bub	1002b
82
83		/*
84		 * Turn on the cache.
85		 */
86                mov     r0, #0
87                movc    p0.c5, r0, #28		@ cache invalidate all
88                nop8
89                movc    p0.c6, r0, #6		@ tlb invalidate all
90                nop8
91
92                mov     r0, #0x1c		@ en icache and wb dcache
93                movc    p0.c1, r0, #0
94                nop8
95
96		/*
97		 * Set up some pointers, for starting decompressing.
98		 */
99
100		mov	r1, sp			@ malloc space above stack
101		add	r2, sp, #0x10000	@ 64k max
102
103		/*
104		 * Check to see if we will overwrite ourselves.
105		 *   r4 = final kernel address
106		 *   r5 = start of this image
107		 *   r6 = size of decompressed image
108		 *   r2 = end of malloc space (and therefore this image)
109		 * We basically want:
110		 *   r4 >= r2 -> OK
111		 *   r4 + image length <= r5 -> OK
112		 */
113		ldw	r4, =KERNEL_IMAGE_START
114		csub.a	r4, r2
115		bea	wont_overwrite
116		add	r0, r4, r6
117		csub.a	r0, r5
118		beb	wont_overwrite
119
120		/*
121		 * If overwrite, just print error message
122		 */
123		b	__error_overwrite
124
125		/*
126		 * We're not in danger of overwriting ourselves.
127		 * Do this the simple way.
128		 */
129wont_overwrite:
130		/*
131		 * decompress_kernel:
132		 *   r0: output_start
133		 *   r1: free_mem_ptr_p
134		 *   r2: free_mem_ptr_end_p
135		 */
136		mov	r0, r4
137		b.l	decompress_kernel	@ C functions
138
139		/*
140		 * Clean and flush the cache to maintain consistency.
141		 */
142		mov	r0, #0
143                movc    p0.c5, r0, #14		@ flush dcache
144		nop8
145                movc    p0.c5, r0, #20		@ icache invalidate all
146                nop8
147
148		/*
149		 * Turn off the Cache and MMU.
150		 */
151		mov	r0, #0			@ disable i/d cache and MMU
152		movc	p0.c1, r0, #0
153                nop8
154
155		mov	r0, #0			@ must be zero
156		ldw	r4, =KERNEL_IMAGE_START
157		mov	pc, r4			@ call kernel
158
159
160		.align	2
161		.type	LC0, #object
162LC0:		.word	LC0			@ r1
163		.word	__bss_start		@ r2
164		.word	_end			@ r3
165		.word	_start			@ r5
166		.word	_image_size		@ r6
167		.word	_got_start		@ r7
168		.word	_got_end		@ r8
169		.word	decompress_stack_end	@ sp
170		.size	LC0, . - LC0
171
172print_string:
173#ifdef CONFIG_DEBUG_OCD
1742001:		ldb.w	r1, [r0]+, #1
175		csub.a	r1, #0
176		bne	2002f
177		mov	pc, lr
1782002:
179		movc	r2, p1.c0, #0
180		cand.a	r2, #2
181		bne	2002b
182		movc	p1.c1, r1, #1
183		csub.a	r1, #'\n'
184		cmoveq	r1, #'\r'
185		beq	2002b
186		b	2001b
187#else
188		mov	pc, lr
189#endif
190
191__error_overwrite:
192		adr	r0, str_error
193		b.l	print_string
1942001:		nop8
195		b	2001b
196str_error:	.asciz	"\nError: Kernel address OVERWRITE\n"
197		.align
198
199		.ltorg
200
201		.align	4
202		.section ".stack", "aw", %nobits
203decompress_stack:	.space	4096
204decompress_stack_end:
205