summaryrefslogtreecommitdiffstats
path: root/arch/arm/boot/compressed/head.S
blob: 796f812abd942bcb21b16155760de377911b8822 (plain)
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
 * linux/arch/arm/boot/compressed/head.S
 *
 * Copyright (C) 1996-1999 Russell King
 */
#include <linux/linkage.h>

		.section ".start", #alloc, #execinstr
/*
 * sort out different calling conventions
 */
		.align
start:
		.type	start,#function
		.rept	8
		mov	r0, r0
		.endr

		b	1f
		.word	0x016f2818		@ Magic numbers to help the loader
		.word	start	
1:

		/*
		 * some architecture specific code can
		 * be inserted by the linker here
		 */

		.text
1:		teq	r0, #0
		bne	1b
		mov	r7, r1			@ save architecture ID
		mrc	p15, 0, r6, c0, c0	@ get processor ID
		adr	r2, LC0
		ldmia	r2, {r2, r3, r4, r5, sp}

		mov	r0, #0
1:		str	r0, [r2], #4		@ clear bss
		str	r0, [r2], #4
		str	r0, [r2], #4
		str	r0, [r2], #4
		cmp	r2, r3
		blt	1b

		mov	r1, sp			@ malloc space above stack
		add	r2, sp, #0x10000	@ 64k max

		teq	r4, r5			@ will we overwrite ourselves?
		moveq	r5, r2
		movne	r5, r4

		mov	r0, r5
		mov	r3, r7
		bl	SYMBOL_NAME(decompress_kernel)

		teq	r4, r5			@ do we need to relocate
		beq	call_kernel		@ the kernel?

		add	r0, r0, #127
		bic	r0, r0, #127		@ align the kernel length
/*
 * r0     = decompressed kernel length
 * r1-r3  = unused
 * r4     = kernel execution address
 * r5     = decompressed kernel start
 * r6     = processor ID
 * r7     = architecture ID
 * r8-r14 = unused
 */
		add	r1, r5, r0		@ end of decompressed kernel
		adr	r2, reloc_start
		adr	r3, reloc_end
1:		ldmia	r2!, {r8 - r13}		@ copy relocation code
		stmia	r1!, {r8 - r13}
		ldmia	r2!, {r8 - r13}
		stmia	r1!, {r8 - r13}
		cmp	r2, r3
		blt	1b

		eor	r1, r6, #0x44 << 24	@ SA-110 or SA-1100?
		eor	r1, r1, #0x01 << 16
		eor	r1, r1, #0xa1 << 8
		movs	r1, r1, lsr #5
		mcreq	p15, 0, r1, c7, c7, 0	@ flush I & D-cache
		mcreq	p15, 0, r1, c7, c10, 4	@ drain WB
		add	pc, r5, r0		@ call relocation code

/*
 * r0     = decompressed kernel length
 * r1-r3  = unused
 * r4     = kernel execution address
 * r5     = decompressed kernel start
 * r6     = processor ID
 * r7     = architecture ID
 * r8-r14 = unused
 */
reloc_start:	add	r8, r5, r0
#if 0
	mov r0, #'\n'
	bl putc
	mov r0, r6
	mov r1, #8
	bl phex
	mov r0, #':'
	bl putc
	mov r0, r5
	mov r1, #8
	bl phex
	mov r0, #'-'
	bl putc
	mov r0, r8
	mov r1, #8
	bl phex
	mov r0, #'>'
	bl putc
	mov r0, r4
	mov r1, #8
	bl phex
	mov r0, #'\n'
	bl putc
#endif
		mov	r0, r8
		mov	r1, r4
1:
		.rept	4
		ldmia	r5!, {r2, r3, r8 - r13}	@ relocate kernel
		stmia	r1!, {r2, r3, r8 - r13}
		.endr

		cmp	r5, r0
		blt	1b
#if 0
	mov r8, r0
	mov r0, r5
	mov r1, #8
	bl phex
	mov r0, #'-'
	bl putc
	mov r0, r8
	mov r1, #8
	bl phex
	mov r0, #'\n'
	bl putc
	mov r0, r4
	bl  memdump
#endif
		eor	r0, r6, #0x44 << 24	@ SA-110 or SA-1100?
		eor	r0, r0, #0x01 << 16
		eor	r0, r0, #0xa1 << 8
		movs	r0, r0, lsr #5
		mcreq	p15, 0, r0, c7, c7, 0	@ flush I cache
		mcreq	p15, 0, r1, c7, c10, 4	@ drain WB

call_kernel:	mov	r0, #0
		mov	r1, r7			@ restore architecture number
		mov	pc, r4			@ call kernel

phexbuf:	.space	12

#if 0
		.macro	loadsp,	rb
		mov	\rb, #0x7c000000
		.endm

		.macro	writeb,	rb
		strb	\rb, [r3, #0x3f8]
		.endm
#else
		.macro	loadsp,	rb
		mov	\rb, #0x03000000
		orr	\rb, \rb, #0x00010000
		.endm

		.macro	writeb,	rb
		strb	\rb, [r3, #0x3f8 << 2]
		.endm
#endif

phex:		adr	r3, phexbuf
		mov	r2, #0
		strb	r2, [r3, r1]
1:		subs	r1, r1, #1
		movmi	r0, r3
		bmi	puts
		and	r2, r0, #15
		mov	r0, r0, lsr #4
		cmp	r2, #10
		addge	r2, r2, #7
		add	r2, r2, #'0'
		strb	r2, [r3, r1]
		b	1b

puts:		loadsp	r3
1:		ldrb	r2, [r0], #1
		teq	r2, #0
		moveq	pc, lr
2:		writeb	r2
		mov	r1, #0x00020000
3:		subs	r1, r1, #1
		bne	3b
		teq	r2, #'\n'
		moveq	r2, #'\r'
		beq	2b
		teq	r0, #0
		bne	1b
		mov	pc, lr
putc:
		mov	r2, r0
		mov	r0, #0
		loadsp	r3
		b	2b

memdump:	mov	r12, r0
		mov	r10, lr
		mov	r1, #8
		bl	phex
		mov	r0, #'\n'
		bl	putc
		mov	r11, #0
2:		mov	r0, r11, lsl #2
		mov	r1, #4
		bl	phex
		mov	r0, #':'
		bl	putc
1:		mov	r0, #' '
		bl	putc
		ldr	r0, [r12, r11, lsl #2]
		mov	r1, #8
		bl	phex
		and	r0, r11, #7
		teq	r0, #3
		moveq	r0, #' '
		bleq	putc
		and	r0, r11, #7
		add	r11, r11, #1
		teq	r0, #7
		bne	1b
		mov	r0, #'\n'
		bl	putc
		cmp	r11, #64
		blt	2b
		mov	pc, r10
reloc_end:

LC0:		.word	__bss_start
		.word	_end
		.word	_load_addr
		.word	_start
		.word	user_stack+4096
		.align

		.section	".stack"
user_stack:	.space	4096