e32boot.cpp revision 1.1 1 1.1 kiyohara /* $NetBSD: e32boot.cpp,v 1.1 2013/04/28 12:11:27 kiyohara Exp $ */
2 1.1 kiyohara /*
3 1.1 kiyohara * Copyright (c) 2012, 2013 KIYOHARA Takashi
4 1.1 kiyohara * All rights reserved.
5 1.1 kiyohara *
6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without
7 1.1 kiyohara * modification, are permitted provided that the following conditions
8 1.1 kiyohara * are met:
9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright
10 1.1 kiyohara * notice, this list of conditions and the following disclaimer.
11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the
13 1.1 kiyohara * documentation and/or other materials provided with the distribution.
14 1.1 kiyohara *
15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE.
26 1.1 kiyohara */
27 1.1 kiyohara
28 1.1 kiyohara #include <e32base.h>
29 1.1 kiyohara #include <e32def.h>
30 1.1 kiyohara #include <e32std.h>
31 1.1 kiyohara
32 1.1 kiyohara #include "cpu.h"
33 1.1 kiyohara #include "e32boot.h"
34 1.1 kiyohara #include "ekern.h"
35 1.1 kiyohara #include "epoc32.h"
36 1.1 kiyohara #include "netbsd.h"
37 1.1 kiyohara
38 1.1 kiyohara
39 1.1 kiyohara class E32BootLDD : public DLogicalDevice {
40 1.1 kiyohara public:
41 1.1 kiyohara E32BootLDD(void);
42 1.1 kiyohara virtual TInt Install(void);
43 1.1 kiyohara virtual void GetCaps(TDes8 &) const;
44 1.1 kiyohara virtual DLogicalChannel *CreateL(void);
45 1.1 kiyohara };
46 1.1 kiyohara
47 1.1 kiyohara class E32BootChannel : public DLogicalChannel {
48 1.1 kiyohara public:
49 1.1 kiyohara E32BootChannel(DLogicalDevice *);
50 1.1 kiyohara
51 1.1 kiyohara protected:
52 1.1 kiyohara virtual void DoCancel(TInt);
53 1.1 kiyohara virtual void DoRequest(TInt, TAny *, TAny *);
54 1.1 kiyohara virtual TInt DoControl(TInt, TAny *, TAny *);
55 1.1 kiyohara
56 1.1 kiyohara private:
57 1.1 kiyohara EPOC32 *epoc32;
58 1.1 kiyohara TAny *safeAddress;
59 1.1 kiyohara
60 1.1 kiyohara TInt BootNetBSD(NetBSD *, struct btinfo_common *);
61 1.1 kiyohara };
62 1.1 kiyohara
63 1.1 kiyohara
64 1.1 kiyohara /* E32Dll() function is required by all DLLs. */
65 1.1 kiyohara GLDEF_C TInt
66 1.1 kiyohara E32Dll(TDllReason)
67 1.1 kiyohara {
68 1.1 kiyohara
69 1.1 kiyohara return KErrNone;
70 1.1 kiyohara }
71 1.1 kiyohara
72 1.1 kiyohara EXPORT_C DLogicalDevice *
73 1.1 kiyohara CreateLogicalDevice(void)
74 1.1 kiyohara {
75 1.1 kiyohara
76 1.1 kiyohara return new E32BootLDD;
77 1.1 kiyohara }
78 1.1 kiyohara
79 1.1 kiyohara E32BootLDD::E32BootLDD(void)
80 1.1 kiyohara {
81 1.1 kiyohara /* Nothing */
82 1.1 kiyohara }
83 1.1 kiyohara
84 1.1 kiyohara TInt
85 1.1 kiyohara E32BootLDD::Install(void)
86 1.1 kiyohara {
87 1.1 kiyohara
88 1.1 kiyohara return SetName(&E32BootName);
89 1.1 kiyohara }
90 1.1 kiyohara
91 1.1 kiyohara void
92 1.1 kiyohara E32BootLDD::GetCaps(TDes8 &aDes) const
93 1.1 kiyohara {
94 1.1 kiyohara TVersion version(0, 0, 0); /* XXXXX: What is it? Don't check? */
95 1.1 kiyohara
96 1.1 kiyohara aDes.FillZ(aDes.MaxLength());
97 1.1 kiyohara aDes.Copy((TUint8 *)&version, Min(aDes.MaxLength(), sizeof(version)));
98 1.1 kiyohara }
99 1.1 kiyohara
100 1.1 kiyohara DLogicalChannel *
101 1.1 kiyohara E32BootLDD::CreateL(void)
102 1.1 kiyohara {
103 1.1 kiyohara
104 1.1 kiyohara return new (ELeave) E32BootChannel(this);
105 1.1 kiyohara }
106 1.1 kiyohara
107 1.1 kiyohara
108 1.1 kiyohara E32BootChannel::E32BootChannel(DLogicalDevice *aDevice)
109 1.1 kiyohara : DLogicalChannel(aDevice)
110 1.1 kiyohara {
111 1.1 kiyohara
112 1.1 kiyohara epoc32 = new EPOC32;
113 1.1 kiyohara safeAddress = NULL;
114 1.1 kiyohara }
115 1.1 kiyohara
116 1.1 kiyohara void
117 1.1 kiyohara E32BootChannel::DoCancel(TInt aReqNo)
118 1.1 kiyohara {
119 1.1 kiyohara /* Nothing */
120 1.1 kiyohara }
121 1.1 kiyohara
122 1.1 kiyohara void
123 1.1 kiyohara E32BootChannel::DoRequest(TInt aReqNo, TAny *a1, TAny *a2)
124 1.1 kiyohara {
125 1.1 kiyohara /* Nothing */
126 1.1 kiyohara }
127 1.1 kiyohara
128 1.1 kiyohara TInt
129 1.1 kiyohara E32BootChannel::DoControl(TInt aFunction, TAny *a1, TAny *a2)
130 1.1 kiyohara {
131 1.1 kiyohara
132 1.1 kiyohara switch (aFunction) {
133 1.1 kiyohara case KE32BootGetProcessorID:
134 1.1 kiyohara {
135 1.1 kiyohara TInt id;
136 1.1 kiyohara
137 1.1 kiyohara __asm("mrc p15, 0, %0, c0, c0" : "=r"(id));
138 1.1 kiyohara *(TUint *)a1 = id;
139 1.1 kiyohara break;
140 1.1 kiyohara }
141 1.1 kiyohara
142 1.1 kiyohara case KE32BootSetSafeAddress:
143 1.1 kiyohara {
144 1.1 kiyohara safeAddress = (TAny *)PAGE_ALIGN(a1);
145 1.1 kiyohara break;
146 1.1 kiyohara }
147 1.1 kiyohara
148 1.1 kiyohara case KE32BootBootNetBSD:
149 1.1 kiyohara {
150 1.1 kiyohara NetBSD *netbsd = (NetBSD *)a1;
151 1.1 kiyohara struct btinfo_common *bootinfo = (struct btinfo_common *)a2;
152 1.1 kiyohara
153 1.1 kiyohara BootNetBSD(netbsd, bootinfo);
154 1.1 kiyohara
155 1.1 kiyohara /* NOTREACHED */
156 1.1 kiyohara
157 1.1 kiyohara break;
158 1.1 kiyohara }
159 1.1 kiyohara
160 1.1 kiyohara default:
161 1.1 kiyohara break;
162 1.1 kiyohara }
163 1.1 kiyohara return KErrNone;
164 1.1 kiyohara }
165 1.1 kiyohara
166 1.1 kiyohara TInt
167 1.1 kiyohara E32BootChannel::BootNetBSD(NetBSD *netbsd, struct btinfo_common *bootinfo)
168 1.1 kiyohara {
169 1.1 kiyohara TAny *mmu_disabled, *ttb;
170 1.1 kiyohara
171 1.1 kiyohara __asm("adr %0, mmu_disabled" : "=r"(mmu_disabled));
172 1.1 kiyohara mmu_disabled = epoc32->GetPhysicalAddress(mmu_disabled);
173 1.1 kiyohara /*
174 1.1 kiyohara * ARMv3 can't read TTB from CP15 C1.
175 1.1 kiyohara * Also can't read Control Register.
176 1.1 kiyohara */
177 1.1 kiyohara ttb = epoc32->GetPhysicalAddress(epoc32->GetTTB());
178 1.1 kiyohara
179 1.1 kiyohara __asm __volatile(" \
180 1.1 kiyohara mrs r12, cpsr; \
181 1.1 kiyohara /* Clear PSR_MODE and Interrupts */ \
182 1.1 kiyohara bic r12, r12, #0xdf; \
183 1.1 kiyohara /* Disable Interrupts(IRQ/FIQ) */ \
184 1.1 kiyohara orr r12, r12, #(3 << 6); \
185 1.1 kiyohara /* Set SVC32 MODE */ \
186 1.1 kiyohara orr r12, r12, #0x13; \
187 1.1 kiyohara msr cpsr_c, r12; \
188 1.1 kiyohara \
189 1.1 kiyohara ldr r10, [%0, #0x0]; \
190 1.1 kiyohara ldr sp, [%0, #0x4]; \
191 1.1 kiyohara ldr lr, [%0, #0x8]; \
192 1.1 kiyohara mov r12, %1; \
193 1.1 kiyohara " :: "r"(netbsd), "r"(bootinfo));
194 1.1 kiyohara
195 1.1 kiyohara __asm __volatile(" \
196 1.1 kiyohara mov r7, %2; \
197 1.1 kiyohara mov r8, %1; \
198 1.1 kiyohara mov r9, %0; \
199 1.1 kiyohara \
200 1.1 kiyohara /* Set all domains to 15 */ \
201 1.1 kiyohara mov r0, #0xffffffff; \
202 1.1 kiyohara mcr p15, 0, r0, c3, c0; \
203 1.1 kiyohara \
204 1.1 kiyohara /* Disable MMU */ \
205 1.1 kiyohara mov r0, #0x38; /* WBUF | 32BP | 32BD */ \
206 1.1 kiyohara mcr p15, 0, r0, c1, c0, 0; \
207 1.1 kiyohara \
208 1.1 kiyohara mov pc, r7; \
209 1.1 kiyohara \
210 1.1 kiyohara mmu_disabled: \
211 1.1 kiyohara /* \
212 1.1 kiyohara * r8 safe address(maybe frame-buffer address)\
213 1.1 kiyohara * r9 ttb \
214 1.1 kiyohara * r10 buffer (netbsd) \
215 1.1 kiyohara * r11 memory descriptor \
216 1.1 kiyohara * r12 bootinfo \
217 1.1 kiyohara * sp load descriptor \
218 1.1 kiyohara * lr entry point \
219 1.1 kiyohara */ \
220 1.1 kiyohara /* save lr to r7 before call functions. */ \
221 1.1 kiyohara mov r7, lr; \
222 1.1 kiyohara \
223 1.1 kiyohara mov r0, r8; \
224 1.1 kiyohara mov r1, r9; \
225 1.1 kiyohara bl vtop; \
226 1.1 kiyohara mov r8, r0; \
227 1.1 kiyohara \
228 1.1 kiyohara /* \
229 1.1 kiyohara * Copy bootinfo to safe address. \
230 1.1 kiyohara * That addr used to framebuffer by EPOC32. \
231 1.1 kiyohara */ \
232 1.1 kiyohara mov r0, r12; \
233 1.1 kiyohara mov r1, r9; \
234 1.1 kiyohara bl vtop; \
235 1.1 kiyohara mov r1, r0; \
236 1.1 kiyohara mov r12, r8; \
237 1.1 kiyohara mov r0, r8; \
238 1.1 kiyohara mov r2, #0x400; \
239 1.1 kiyohara bl copy; \
240 1.1 kiyohara \
241 1.1 kiyohara /* save lr(r7) to r8. it is no need. */ \
242 1.1 kiyohara mov r8, r7; \
243 1.1 kiyohara \
244 1.1 kiyohara /* Copy loader to safe address + 0x400. */ \
245 1.1 kiyohara add r0, r12, #0x400; \
246 1.1 kiyohara adr r1, miniloader_start; \
247 1.1 kiyohara adr r2, miniloader_end; \
248 1.1 kiyohara sub r2, r2, r1; \
249 1.1 kiyohara bl copy; \
250 1.1 kiyohara \
251 1.1 kiyohara /* Make load-descriptor to safe addr + 0x800. */\
252 1.1 kiyohara mov r0, sp; \
253 1.1 kiyohara mov r1, r9; \
254 1.1 kiyohara bl vtop; \
255 1.1 kiyohara mov sp, r0; \
256 1.1 kiyohara add r4, r12, #0x800; \
257 1.1 kiyohara \
258 1.1 kiyohara next_section: \
259 1.1 kiyohara ldmia sp!, {r5 - r7}; \
260 1.1 kiyohara \
261 1.1 kiyohara next_page: \
262 1.1 kiyohara add r0, r10, r6; \
263 1.1 kiyohara mov r1, r9; \
264 1.1 kiyohara bl vtop; \
265 1.1 kiyohara /* vtop returns set mask to r2 */ \
266 1.1 kiyohara orr r2, r0, r2; \
267 1.1 kiyohara add r2, r2, #1; \
268 1.1 kiyohara sub r2, r2, r0; \
269 1.1 kiyohara cmp r2, r7; \
270 1.1 kiyohara movgt r2, r7; \
271 1.1 kiyohara mov r1, r0; \
272 1.1 kiyohara mov r0, r5; \
273 1.1 kiyohara stmia r4!, {r0 - r2}; \
274 1.1 kiyohara add r5, r5, r2; \
275 1.1 kiyohara add r6, r6, r2; \
276 1.1 kiyohara subs r7, r7, r2; \
277 1.1 kiyohara bgt next_page; \
278 1.1 kiyohara \
279 1.1 kiyohara ldr r0, [sp]; \
280 1.1 kiyohara cmp r0, #0xffffffff; \
281 1.1 kiyohara beq fin; \
282 1.1 kiyohara /* Pad to section align. */ \
283 1.1 kiyohara str r5, [r4], #4; \
284 1.1 kiyohara mov r6, #0xffffffff; \
285 1.1 kiyohara str r6, [r4], #4; \
286 1.1 kiyohara sub r2, r0, r5; \
287 1.1 kiyohara str r2, [r4], #4; \
288 1.1 kiyohara b next_section; \
289 1.1 kiyohara \
290 1.1 kiyohara fin: \
291 1.1 kiyohara stmia r4, {r5 - r7}; \
292 1.1 kiyohara add sp, r12, #0x800; \
293 1.1 kiyohara \
294 1.1 kiyohara /* save lr(r8) to r11. r11 is no need. */ \
295 1.1 kiyohara mov r11, r8; \
296 1.1 kiyohara \
297 1.1 kiyohara /* Fixup load-descriptor by BTINFO_MEMORY. */ \
298 1.1 kiyohara mov r10, r12; \
299 1.1 kiyohara mov r9, sp; \
300 1.1 kiyohara add r8, sp, #12; \
301 1.1 kiyohara next_bootinfo: \
302 1.1 kiyohara ldmia r10, {r0, r1}; \
303 1.1 kiyohara cmp r1, #0; /* BTINFO_NONE */ \
304 1.1 kiyohara beq btinfo_none; \
305 1.1 kiyohara \
306 1.1 kiyohara cmp r1, #2; /* BTINFO_MEMORY */ \
307 1.1 kiyohara beq btinfo_memory; \
308 1.1 kiyohara add r10, r10, r0; \
309 1.1 kiyohara b next_bootinfo; \
310 1.1 kiyohara \
311 1.1 kiyohara btinfo_none: \
312 1.1 kiyohara /* ENOMEM */ \
313 1.1 kiyohara add r2, r12, #0x800; \
314 1.1 kiyohara mov r1, #640; \
315 1.1 kiyohara mov r0, #0x00ff0000; \
316 1.1 kiyohara orr r0, r0, #0x00ff; \
317 1.1 kiyohara 98: \
318 1.1 kiyohara str r0, [r2], #4; \
319 1.1 kiyohara subs r1, r1, #4; \
320 1.1 kiyohara bgt 98b; \
321 1.1 kiyohara mov r1, #640; \
322 1.1 kiyohara mov r0, #0xff000000; \
323 1.1 kiyohara orr r0, r0, #0xff00; \
324 1.1 kiyohara 99: \
325 1.1 kiyohara str r0, [r2], #4; \
326 1.1 kiyohara subs r1, r1, #4; \
327 1.1 kiyohara bgt 99b; \
328 1.1 kiyohara 100: \
329 1.1 kiyohara b 100b; \
330 1.1 kiyohara \
331 1.1 kiyohara btinfo_memory: \
332 1.1 kiyohara ldmia r10!, {r4 - r7}; \
333 1.1 kiyohara ldr r4, [r9, #0]; \
334 1.1 kiyohara subs r4, r4, r6; \
335 1.1 kiyohara addgt r6, r6, r4; \
336 1.1 kiyohara subgt r7, r7, r4; \
337 1.1 kiyohara next_desc: \
338 1.1 kiyohara ldmia r9, {r3 - r5}; \
339 1.1 kiyohara ldmia r8!, {r0 - r2}; \
340 1.1 kiyohara add r3, r3, r5; \
341 1.1 kiyohara add r4, r4, r5; \
342 1.1 kiyohara cmp r3, r0; \
343 1.1 kiyohara cmpeq r4, r1; \
344 1.1 kiyohara beq join_desc; \
345 1.1 kiyohara \
346 1.1 kiyohara ldr r3, [r9, #0]; \
347 1.1 kiyohara cmp r3, r6; \
348 1.1 kiyohara strlt r6, [r9, #0]; /* Fixup */ \
349 1.1 kiyohara cmp r5, r7; \
350 1.1 kiyohara bgt split_desc; \
351 1.1 kiyohara add r6, r6, r5; \
352 1.1 kiyohara sub r7, r7, r5; \
353 1.1 kiyohara add r9, r9, #12; \
354 1.1 kiyohara stmia r9, {r0 - r2}; \
355 1.1 kiyohara cmp r0, #0xffffffff; \
356 1.1 kiyohara beq fixuped; \
357 1.1 kiyohara b next_desc; \
358 1.1 kiyohara \
359 1.1 kiyohara join_desc: /* Join r8 descriptor to r9. */ \
360 1.1 kiyohara add r5, r5, r2; \
361 1.1 kiyohara str r5, [r9, #8]; \
362 1.1 kiyohara b next_desc; \
363 1.1 kiyohara \
364 1.1 kiyohara split_desc: /* Split r9 descriptor. */ \
365 1.1 kiyohara ldr r3, [r9, #0]; \
366 1.1 kiyohara ldr r4, [r9, #4]; \
367 1.1 kiyohara str r7, [r9, #8]; \
368 1.1 kiyohara \
369 1.1 kiyohara sub r6, r5, r7; \
370 1.1 kiyohara add r5, r4, r7; \
371 1.1 kiyohara add r4, r3, r7; \
372 1.1 kiyohara sub r8, r8, #12; /* Back to prev desc */ \
373 1.1 kiyohara add r9, r9, #12;/* Point to splited desc */ \
374 1.1 kiyohara \
375 1.1 kiyohara cmp r8, r9; \
376 1.1 kiyohara bne 2f; \
377 1.1 kiyohara add r0, r8, #12; \
378 1.1 kiyohara mov r1, r8; \
379 1.1 kiyohara mov r2, #0; \
380 1.1 kiyohara 1: \
381 1.1 kiyohara ldr r3, [r8, r2]; \
382 1.1 kiyohara add r2, r2, #12; \
383 1.1 kiyohara cmp r3, #0xffffffff; \
384 1.1 kiyohara bne 1b; \
385 1.1 kiyohara bl copy; \
386 1.1 kiyohara add r8, r8, #12; /* Point to moved desc */ \
387 1.1 kiyohara 2: \
388 1.1 kiyohara stmia r9, {r4 - r6}; \
389 1.1 kiyohara b next_bootinfo; \
390 1.1 kiyohara \
391 1.1 kiyohara fixuped: \
392 1.1 kiyohara /* Jump to miniloader. Our LR is entry-point! */\
393 1.1 kiyohara add pc, r12, #0x400; \
394 1.1 kiyohara \
395 1.1 kiyohara vtop: \
396 1.1 kiyohara /* \
397 1.1 kiyohara * paddr vtop(vaddr, ttb) \
398 1.1 kiyohara */ \
399 1.1 kiyohara bic r2, r0, #0x000f0000; /* L1_ADDR_BITS */ \
400 1.1 kiyohara bic r2, r2, #0x0000ff00; /* L1_ADDR_BITS */ \
401 1.1 kiyohara bic r2, r2, #0x000000ff; /* L1_ADDR_BITS */ \
402 1.1 kiyohara mov r2, r2, lsr #(20 - 2); \
403 1.1 kiyohara ldr r1, [r1, r2]; \
404 1.1 kiyohara and r3, r1, #0x3; /* L1_TYPE_MASK */ \
405 1.1 kiyohara cmp r3, #0; \
406 1.1 kiyohara bne valid; \
407 1.1 kiyohara \
408 1.1 kiyohara invalid: \
409 1.1 kiyohara mov r0, #-1; \
410 1.1 kiyohara mov pc, lr; \
411 1.1 kiyohara \
412 1.1 kiyohara valid: \
413 1.1 kiyohara cmp r3, #0x2; \
414 1.1 kiyohara bgt 3f; \
415 1.1 kiyohara beq 2f; \
416 1.1 kiyohara \
417 1.1 kiyohara 1: /* Coarse L2 */ \
418 1.1 kiyohara mov r2, #10; \
419 1.1 kiyohara b l2; \
420 1.1 kiyohara \
421 1.1 kiyohara 2: /* Section */ \
422 1.1 kiyohara mov r2, #0xff000000; /* L1_S_ADDR_MASK */\
423 1.1 kiyohara add r2, r2, #0x00f00000;/* L1_S_ADDR_MASK */\
424 1.1 kiyohara mvn r2, r2; \
425 1.1 kiyohara bic r3, r1, r2; \
426 1.1 kiyohara and r0, r0, r2; \
427 1.1 kiyohara orr r0, r3, r0; \
428 1.1 kiyohara mov pc, lr; \
429 1.1 kiyohara \
430 1.1 kiyohara 3: /* Fine L2 */ \
431 1.1 kiyohara mov r2, #12; \
432 1.1 kiyohara l2: \
433 1.1 kiyohara mov r3, #1; \
434 1.1 kiyohara mov r3, r3, lsl r2; \
435 1.1 kiyohara sub r3, r3, #1; \
436 1.1 kiyohara bic r1, r1, r3; /* L2 table */ \
437 1.1 kiyohara mov r3, r0, lsl #12; \
438 1.1 kiyohara mov r3, r3, lsr #12; \
439 1.1 kiyohara sub r2, r2, #22; \
440 1.1 kiyohara rsb r2, r2, #0; \
441 1.1 kiyohara mov r3, r3, lsr r2; /* index for L2 */ \
442 1.1 kiyohara ldr r1, [r1, r3, lsl #2]; \
443 1.1 kiyohara and r3, r1, #0x3; /* L2_TYPE_MASK */ \
444 1.1 kiyohara cmp r3, #0; \
445 1.1 kiyohara beq invalid; \
446 1.1 kiyohara cmp r3, #2; \
447 1.1 kiyohara movlt r2, #16; /* L2_L_SHIFT */ \
448 1.1 kiyohara moveq r2, #12; /* L2_S_SHIFT */ \
449 1.1 kiyohara movgt r2, #10; /* L2_T_SHIFT */ \
450 1.1 kiyohara mov r3, #1; \
451 1.1 kiyohara mov r2, r3, lsl r2; \
452 1.1 kiyohara sub r2, r2, #1; \
453 1.1 kiyohara bic r3, r1, r2; \
454 1.1 kiyohara and r0, r0, r2; \
455 1.1 kiyohara orr r0, r3, r0; \
456 1.1 kiyohara mov pc, lr; \
457 1.1 kiyohara \
458 1.1 kiyohara miniloader_start: \
459 1.1 kiyohara b miniloader; \
460 1.1 kiyohara \
461 1.1 kiyohara copy: \
462 1.1 kiyohara /* \
463 1.1 kiyohara * void copy(dest, src, len) \
464 1.1 kiyohara */ \
465 1.1 kiyohara cmp r0, r1; \
466 1.1 kiyohara bgt rcopy; \
467 1.1 kiyohara lcopy: \
468 1.1 kiyohara ldr r3, [r1], #4; \
469 1.1 kiyohara str r3, [r0], #4; \
470 1.1 kiyohara subs r2, r2, #4; \
471 1.1 kiyohara bgt lcopy; \
472 1.1 kiyohara mov pc, lr; \
473 1.1 kiyohara rcopy: \
474 1.1 kiyohara subs r2, r2, #4; \
475 1.1 kiyohara ldr r3, [r1, r2]; \
476 1.1 kiyohara str r3, [r0, r2]; \
477 1.1 kiyohara bgt rcopy; \
478 1.1 kiyohara mov pc, lr; \
479 1.1 kiyohara \
480 1.1 kiyohara \
481 1.1 kiyohara miniloader: \
482 1.1 kiyohara /* \
483 1.1 kiyohara * r11 entry-point \
484 1.1 kiyohara * r12 bootinfo \
485 1.1 kiyohara * sp load-descriptor \
486 1.1 kiyohara */ \
487 1.1 kiyohara load: \
488 1.1 kiyohara ldmia sp!, {r0 - r2}; \
489 1.1 kiyohara cmp r0, #0xffffffff; \
490 1.1 kiyohara beq end; \
491 1.1 kiyohara cmp r1, #0xffffffff;/* Skip section align */\
492 1.1 kiyohara blne copy; /* or copy */ \
493 1.1 kiyohara b load; \
494 1.1 kiyohara \
495 1.1 kiyohara end: \
496 1.1 kiyohara mov r0, r12; \
497 1.1 kiyohara mov pc, r11; \
498 1.1 kiyohara nop; \
499 1.1 kiyohara nop; \
500 1.1 kiyohara miniloader_end: \
501 1.1 kiyohara \
502 1.1 kiyohara "
503 1.1 kiyohara ::"r"(ttb),
504 1.1 kiyohara "r"(safeAddress),
505 1.1 kiyohara "r"(mmu_disabled)
506 1.1 kiyohara );
507 1.1 kiyohara
508 1.1 kiyohara /* NOTREACHED */
509 1.1 kiyohara
510 1.1 kiyohara return -1;
511 1.1 kiyohara }
512