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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
* Copyright (C) 2010 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
/* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux
* loader
*
* Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
* Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
*
*/
.equ PROC_ID, 0x60000000
.equ CPU_IDIS, 0x60004028
.equ CPU_CTRL, 0x60007000
.equ CPU_STATUS, 0x60007000
.equ COP_IDIS, 0x60004038
.equ COP_CTRL, 0x60007004
.equ COP_STATUS, 0x60007004
.equ CPU_SLEEPING,0x80000000
.equ COP_SLEEPING,0x80000000
.equ SLEEP, 0x80000000
.equ WAKE, 0x00000000
.equ MMAP_LOG, 0xf000f000 /* MMAP0 */
.equ MMAP_PHYS, 0xf000f004
.equ INT_VECT_TBL,0x6000f100
.equ CACHE_CTRL, 0x6000c000
.equ CACHE_ENAB, 0x1
.equ CACHE_OP_COMMIT_DISCARD, 0x1
.equ CACHE_OP_COMMIT , 0x0
#if MEMORYSIZE > 32
.equ MMAP_MASK, 0x00003c00
#else
.equ MMAP_MASK, 0x00003e00
#endif
.equ MMAP_FLAGS, 0x00000f84
/*
* Entry point
*/
.section .init.text,"ax",%progbits
.global start
start:
b newstart
#ifdef IPOD_ARCH
.align 8 /* starts at 0x100 */
.global boot_table
boot_table:
/* here comes the boot table, don't move its offset - preceding
code+data must stay <= 256 bytes */
.space 400
#else /* !IPOD_ARCH */
/* (more than enough) space for exception vectors and mi4 magic */
.space 68*4
#endif /* IPOD_ARCH */
newstart:
msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
adr r4, start /* cache initial load address */
/* Copy startup stub to IRAM since we need to both move the bootloader's
* location, which could overlap itself, and setup the memory mapper. */
adr r0, start_stub_begin
mov r1, #0x40000000
adr r2, start_stub_end
1:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r0, r2
blo 1b
mov pc, #0x40000000
start_stub_begin:
ldr r0, =PROC_ID
ldrb r0, [r0]
cmp r0, #0x55
beq cpu
cop:
mov r0, #CACHE_OP_COMMIT_DISCARD
bl cache_operation
ldr r1, =COP_CTRL
mov r0, #SLEEP
/* sleep us (co-processor) while bootloader is copied */
str r0, [r1]
nop
nop
nop
/* branch to final physical load address */
ldr r2, =1f
and r4, r4, #0xfc000000
add pc, r2, r4
1:
/* wait for bootloader to finish */
str r0, [r1]
nop
nop
nop
/* branch to the address returned by main() */
adr r0, startup_loc
ldr pc, [r0]
cpu:
/* wait for COP to sleep */
ldr r1, =COP_STATUS
1:
ldr r0, [r1]
tst r0, #COP_SLEEPING
beq 1b
mov r0, #CACHE_OP_COMMIT_DISCARD
bl cache_operation
/* move bootloader to the correct load address if needed */
ldr r1, =_loadaddress
cmp r4, r1
ldrne r2, =_loadaddressend
movne r0, r4
sublo r3, r2, r1 /* size */
addlo r0, r0, r3 /* initial load end addr */
1: /* lower to higher move - copy up */
cmphi r2, r1
ldrhi r3, [r0], #4
strhi r3, [r1], #4
bhi 1b
1: /* higher to lower move - copy down */
cmplo r1, r2
ldrlo r3, [r0, #-4]!
strlo r3, [r2, #-4]!
blo 1b
mov r0, #CACHE_OP_COMMIT
bl cache_operation
and r4, r4, #0xfc000000
ldr r0, =MMAP_FLAGS
orr r0, r0, r4 /* adjust for execute address */
ldr r1, =MMAP_MASK
ldr r2, =MMAP_LOG
ldr r3, =MMAP_PHYS
str r1, [r2] /* MMAP_LOG = MMAP_MASK */
str r0, [r3] /* MMAP_PHYS = MMAP_FLAGS | SDRAM base addr */
/* wake the COP to jump it to the correct place */
ldr r1, =COP_CTRL
mov r0, #WAKE
str r0, [r1]
/* wait for COP to halt then loading may proceed */
ldr r1, =COP_STATUS
1:
ldr r0, [r1]
tst r0, #COP_SLEEPING
beq 1b
ldr r0, =start_stub_end
add pc, r0, r4
cache_operation: /* (bool commit_discard) */
ldr r2, =CACHE_CTRL
ldr r1, [r2]
tst r1, #CACHE_ENAB
bxeq lr
cmp r0, #CACHE_OP_COMMIT
ldr r0, =0xf000f044
ldr r1, [r0]
orrne r1, r1, #0x6
orreq r1, r1, #0x2
str r1, [r0]
1:
ldr r1, [r2]
tst r1, #0x8000
bne 1b
bx lr
.ltorg /* constants used in stub come with us to IRAM */
start_stub_end:
/* now executing from final physical address */
/* copy the vector addresses to the table */
ldr r0, =INT_VECT_TBL
adr r1, vectorsstart
adr r2, vectorsend
1:
cmp r2, r1
ldrhi r3, [r1], #4
strhi r3, [r0], #4
bhi 1b
/* Copy the IRAM */
ldr r0, =_iramcopy
ldr r1, =_iramstart
ldr r2, =_iramend
1:
cmp r2, r1
ldrhi r3, [r0], #4
strhi r3, [r1], #4
bhi 1b
mov r0, #0
/* Zero out IBSS */
ldr r1, =_iedata
ldr r2, =_iend
1:
cmp r2, r1
strhi r0, [r1], #4
bhi 1b
/* Initialise bss/ncbss sections to zero */
ldr r1, =_edata
ldr r2, =_end
1:
cmp r2, r1
strhi r0, [r1], #4
bhi 1b
/* Set up some stack and munge it with 0xdeadbeef */
ldr r0, =0xdeadbeef
ldr r1, =stackbegin
ldr sp, =stackend
1:
cmp sp, r1
strhi r0, [r1], #4
bhi 1b
/* Set up stack for IRQ mode */
msr cpsr_c, #0xd2 /* IRQ/FIQ disabled */
ldr sp, =irq_stack
/* Let abort and undefined modes use IRQ stack */
msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */
ldr sp, =irq_stack
msr cpsr_c, #0xdb /* IRQ/FIQ disabled */
ldr sp, =irq_stack
/* Switch back to supervisor mode */
msr cpsr_c, #0xd3
/* execute the loader - this will load an image to 0x10000000 */
ldr r0, =main
mov lr, pc
bx r0
/* store actual startup location returned by main() */
ldr r1, =startup_loc
str r0, [r1]
/* write back anything loaded + startup_loc */
mov r0, #CACHE_OP_COMMIT
bl cache_operation
mov r0, #0
/* disable memory mapper */
ldr r1, =MMAP_LOG
ldr r2, =MMAP_PHYS
str r0, [r1]
str r0, [r2]
/* bring COP back to life */
ldr r1, =COP_CTRL
mov r0, #WAKE
str r0, [r1]
/* after this point, r0-r3 are reserved for OF magic */
#if defined(SANSA_C200) || defined(PHILIPS_HDD1630)
/* Magic for loading the c200 OF */
ldr r0, =0xb00d10ad
mov r1, #0x700
ldr r2, =0xfff0
mov r3, #0x7
#endif
#if defined(PHILIPS_HDD6330)
/* Magic for loading the HDD6XX0 OF */
ldr r0, =0xb00d10ad
mov r1, #0x800
ldr r2, =0xfff0
mov r3, #0x7
#endif
/* branch to the address returned by main() */
adr r4, startup_loc
ldr pc, [r4]
startup_loc:
.word 0x00000000
/* exception handlers: will be copied to local vector table */
vectorsstart:
.word newstart
.word undef_instr_handler
.word software_int_handler
.word prefetch_abort_handler
.word data_abort_handler
.word reserved_handler
.word irq_handler
.word fiq_handler
vectorsend:
.text
/* All illegal exceptions call into UIE with exception address as first
parameter. This is calculated differently depending on which exception
we're in. Second parameter is exception number, used for a string lookup
in UIE.
*/
undef_instr_handler:
sub r0, lr, #4
mov r1, #0
b UIE
/* We run supervisor mode most of the time, and should never see a software
exception being thrown. Perhaps make it illegal and call UIE?
*/
software_int_handler:
reserved_handler:
movs pc, lr
prefetch_abort_handler:
sub r0, lr, #4
mov r1, #1
b UIE
data_abort_handler:
sub r0, lr, #8
mov r1, #2
b UIE
/* should never happen in the bootloader */
fiq_handler:
subs pc, lr, #4
/* 256 words of IRQ stack */
.section .bss
.balign 16
.space 256*4
irq_stack:
|