1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
/* 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:
|