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