1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS
3   File:     os_reset.c
4 
5   Copyright 2007-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-06-08#$
14   $Rev: 10706 $
15   $Author: yosizaki $
16  *---------------------------------------------------------------------------*/
17 #include        <nitro.h>
18 #include        <nitro/mb.h>
19 #include        <nitro/snd/common/global.h>
20 #include        <nitro/card.h>
21 
22 #include        <nitro/code32.h>
23 
24 //---- autoload start
25 #ifdef SDK_ARM9
26 #define OSi_HW_DTCM               SDK_AUTOLOAD_DTCM_START
27 #endif
28 
29 //---------------- local functions
30 #ifdef SDK_ARM9
31 static void OSi_CpuClear32(register u32 data, register void *destp, register u32 size);
32 static void OSi_ReloadRomData(void);
33 static void OSi_ReadCardRom32(u32 src, void *dst, int len);
34 #endif // ifdef SDK_ARM9
35 
36 void OSi_DoResetSystem(void);
37 static void OSi_DoBoot(void);
38 
39 #ifdef  SDK_TWL
40 static void OSi_ReloadTwlRomData(void);
41 #ifdef  SDK_ARM7
42 extern void SDK_LTDAUTOLOAD_LTDMAIN_START(void);
43 void* const OSi_LtdMainParams[] =
44 {
45     (void*)SDK_LTDAUTOLOAD_LTDMAIN_START,
46 };
47 #endif
48 #endif
49 
50 //---------------- local variables
51 static u16 OSi_IsInitReset = FALSE;
52 
53 //================================================================================
54 /*---------------------------------------------------------------------------*
55   Name:         OS_InitReset
56 
57   Description:  init reset system
58 
59   Arguments:    None.
60 
61   Returns:      None.
62  *---------------------------------------------------------------------------*/
OS_InitReset(void)63 void OS_InitReset(void)
64 {
65     if (OSi_IsInitReset)
66     {
67         return;
68     }
69     OSi_IsInitReset = TRUE;
70 
71     //---------------- ARM9
72 #ifdef SDK_ARM9
73     //---- wait ARM7 PXI library start
74     PXI_Init();
75     while (!PXI_IsCallbackReady(PXI_FIFO_TAG_OS, PXI_PROC_ARM7))
76     {
77     }
78 #endif
79 
80     //---- set PXI receive callback
81     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_OS, OSi_CommonCallback);
82 }
83 
84 /*---------------------------------------------------------------------------*
85   Name:         OS_ResetSystem
86 
87   Description:  Start reset sequence.
88                 To decrease code in itcm or wram,
89                 separate this function from OSi_DoResetSystem()
90 
91   Arguments:    (ARM9) parameter : reset parameter
92                 (ARM7) None
93 
94   Returns:      None.
95  *---------------------------------------------------------------------------*/
96 //---------------- ARM9
97 #ifdef SDK_ARM9
OS_ResetSystem(u32 parameter)98 void OS_ResetSystem(u32 parameter)
99 {
100 #ifdef  SDK_TWL
101     //---- stop if reset from non-card application
102     if ((MB_IsMultiBootChild() == TRUE) ||
103         ((OS_IsRunOnTwl() == TRUE) && ((*((u32*)(HW_TWL_ROM_HEADER_BUF + 0x234)) & 0x00000004) != 0)))
104     {
105 #ifndef SDK_FINALROM
106         OS_Panic("Only card booted application can execute software reset.\nSee OS_ResetSystem() reference manual.");
107 #else
108         OS_Panic("");
109 #endif
110     }
111 #else
112     //---- stop if reset from multiboot child
113     if (MB_IsMultiBootChild())
114     {
115 #ifndef SDK_FINALROM
116         OS_Panic("Cannot reset from MB child.\nSee OS_ResetSystem() reference manual.");
117 #else
118         OS_Panic("");
119 #endif
120     }
121 #endif
122     //---- stop if reset on TWL-mode
123 #ifdef  SDK_TWL
124     if (OS_IsRunOnTwl())
125     {
126 #ifndef SDK_FINALROM
127         OS_Panic("Cannot reset on TWL-mode.\nSee OS_ResetSystem() reference manual.");
128 #else
129         OS_Panic("");
130 #endif
131     }
132 #endif
133 
134 #ifdef  SDK_TWL
135     if ( OS_IsRunOnTwl() )
136     {
137         // End processing
138         // If making an ARM7 processor request, wait for the callback function to complete
139         PMi_ExecutePostExitCallbackList();
140     }
141 #endif
142 
143     //---- wait while card is locked
144     {
145         u16     id = (u16)OS_GetLockID();
146         CARD_LockRom(id);
147     }
148 
149     //---- set only pxi interrupt available
150     (void)OS_SetIrqMask(OS_IE_FIFO_RECV);
151     (void)OS_ResetRequestIrqMask(0xffffffff /*all request */ );
152 
153     //---- stop all dma
154 	MI_StopAllDma();
155 #ifdef SDK_TWL
156 	if (OS_IsRunOnTwl())
157 	{
158 		MI_StopAllNDma();
159 	}
160 #endif
161 
162     //---- save parameter
163     *(u32 *)HW_RESET_PARAMETER_BUF = parameter;
164 
165     //---- send reset command to ARM7
166     OSi_SendToPxi(OS_PXI_COMMAND_RESET);
167 
168     //---- reset
169     OSi_DoResetSystem();
170 
171     // Doesn't reach here
172 }
173 
174 //---------------- ARM7
175 #else  // ifdef SDK_ARM9
176 #pragma dont_inline on
OS_ResetSystem(void)177 void OS_ResetSystem(void)
178 {
179     //---- set only pxi interrupt available
180     (void)OS_SetIrqMask(OS_IE_FIFO_RECV);
181     (void)OS_ResetRequestIrqMask(0xffffffff /*all request */ );
182 
183     //---- stop all dma
184 	{
185 		u32 n;
186 		for( n=0; n<4; n++ )
187 		{
188 			MI_StopDma(n);
189 #ifdef SDK_TWL
190 			if (OS_IsRunOnTwl())
191 			{
192 				MI_StopNDma(n);
193 			}
194 #endif
195 		}
196 	}
197 
198     //---- sound stop
199     SND_Shutdown();
200 
201     //---- send reset command to ARM9
202     OSi_SendToPxi(OS_PXI_COMMAND_RESET);
203 
204     //---- reset
205     OSi_DoResetSystem();
206 }
207 #pragma dont_inline reset
208 #endif // ifdef SDK_ARM9
209 
210 #if defined(SDK_TWL) && defined(SDK_ARM9)
211 #include <twl/itcm_begin.h>
212 #define OSi_TCM_REGION_BASE_MASK  HW_C9_TCMR_BASE_MASK  // 0xfffff000
OSi_GetDTCMAddress(void)213 static asm u32 OSi_GetDTCMAddress(void)
214 {
215     mrc      p15, 0, r0, c9, c1, 0
216     ldr      r1, =OSi_TCM_REGION_BASE_MASK
217     and      r0, r0, r1
218     bx       lr
219 }
220 /*---------------------------------------------------------------------------*
221   Name:         OSi_VerifyStaticSegments
222 
223   Description:  Verifies 4 static segments before rebooting.
224 
225   Arguments:    None.
226 
227   Returns:      None.
228  *---------------------------------------------------------------------------*/
OSi_VerifyStaticSegments(void)229 static void OSi_VerifyStaticSegments(void)
230 {
231     BOOL                    result = TRUE;
232     const CARDRomHeaderTWL *header = (const CARDRomHeaderTWL *)HW_TWL_ROM_HEADER_BUF;
233     if ((((const u8 *)header)[0x1C] & 0x01) != 0)
234     {
235         int                     i;
236         // use DTCM as workarea
237         u8                     *work = (u8 *)OSi_GetDTCMAddress();
238         SVCHMACSHA1Context     *context = (SVCHMACSHA1Context *)&work[0];
239         u8                     *digest = &work[sizeof(SVCHMACSHA1Context)];
240         // calculate and verify HMAC-SHA1 of the static segments
241         enum { SEGMENT_TOTAL = 4 };
242         struct Segment { u8 *address; u32 size; } *(table[SEGMENT_TOTAL]);
243         const void             *(compareDigests[SEGMENT_TOTAL]);
244         table[0] = (struct Segment *)&header->ntr.main_ram_address;
245         table[1] = (struct Segment *)&header->ntr.sub_ram_address;
246         table[2] = (struct Segment *)&header->main_ltd_ram_address;
247         table[3] = (struct Segment *)&header->sub_ltd_ram_address;
248         compareDigests[0] = &((const u8 *)header)[0x3A0];
249         compareDigests[1] = header->sub_static_digest;
250         compareDigests[2] = header->main_ltd_static_digest;
251         compareDigests[3] = header->sub_ltd_static_digest;
252         for (i = 0; i < SEGMENT_TOTAL; ++i)
253         {
254             static const u8 hmacKey[] =
255             {
256                 0x21, 0x06, 0xc0, 0xde, 0xba, 0x98, 0xce, 0x3f,
257                 0xa6, 0x92, 0xe3, 0x9d, 0x46, 0xf2, 0xed, 0x01,
258                 0x76, 0xe3, 0xcc, 0x08, 0x56, 0x23, 0x63, 0xfa,
259                 0xca, 0xd4, 0xec, 0xdf, 0x9a, 0x62, 0x78, 0x34,
260                 0x8f, 0x6d, 0x63, 0x3c, 0xfe, 0x22, 0xca, 0x92,
261                 0x20, 0x88, 0x97, 0x23, 0xd2, 0xcf, 0xae, 0xc2,
262                 0x32, 0x67, 0x8d, 0xfe, 0xca, 0x83, 0x64, 0x98,
263                 0xac, 0xfd, 0x3e, 0x37, 0x87, 0x46, 0x58, 0x24,
264             };
265             const u8   *address = table[i]->address;
266             u32         size = table[i]->size;
267             if (i == 0)
268             {
269                 address += 0x4000;
270                 size -= 0x4000;
271             }
272             SVC_HMACSHA1Init(context, hmacKey, sizeof(hmacKey));
273             SVC_HMACSHA1Update(context, address, size);
274             SVC_HMACSHA1GetHash(context, digest);
275             result &= (SVC_CompareSHA1(digest, compareDigests[i]) != FALSE);
276         }
277     }
278     // if any segment is invalid, enter the endless-loop
279     while (result == FALSE)
280     {
281     }
282 }
283 #include <twl/itcm_end.h>
284 #endif // defined(SDK_TWL) && defined(SDK_ARM9)
285 
286 /*---------------------------------------------------------------------------*
287   Name:         OSi_DoResetSystem
288 
289   Description:  Start reset sequence.
290                 Subroutine of OS_ResetSystem().
291                 This part is put in itcm/wram because rom data will be
292                 Loaded anew.
293 
294   Arguments:    None.
295 
296   Returns:      None.
297  *---------------------------------------------------------------------------*/
298 //---------------- ARM9
299 #ifdef SDK_ARM9
300 #ifdef  SDK_TWL
301 #include    <twl/itcm_begin.h>
302 #else
303 #include    <nitro/itcm_begin.h>
304 #endif
305 SDK_WEAK_SYMBOL
OSi_DoResetSystem(void)306 void OSi_DoResetSystem(void)
307 __attribute__((never_inline))
308 {
309     //---- wait to receive reset command from ARM7
310     while (!OS_IsResetOccurred())
311     {
312     }
313 
314     //---- set IME = 0
315     reg_OS_IME = 0;
316 
317     //---- reload ROM data
318 #ifdef  SDK_TWL
319     if (OS_IsRunOnTwl() == TRUE)
320     {
321         OSi_ReloadTwlRomData();
322         OSi_VerifyStaticSegments();
323     }
324     else
325 #endif
326     {
327         OSi_ReloadRomData();
328     }
329 
330     //---- do boot
331     OSi_DoBoot();
332 }
333 
334 #ifdef  SDK_TWL
335 #include    <twl/itcm_end.h>
336 #else
337 #include    <nitro/itcm_end.h>
338 #endif
339 
340 //---------------- ARM7
341 #else  // ifdef SDK_ARM9
342 #ifdef  SDK_TWL
343 #include    <twl/wram_begin.h>
344 #else
345 #include    <nitro/wram_begin.h>
346 #endif
347 SDK_WEAK_SYMBOL
OSi_DoResetSystem(void)348 void OSi_DoResetSystem(void)
349 __attribute__((never_inline))
350 {
351     //---- set IME = 0
352     reg_OS_IME = 0;
353 
354 #ifdef  SDK_TWL
355     if (OS_IsRunOnTwl() == TRUE)
356     {
357         OSi_ReloadTwlRomData();
358     }
359 #endif
360 
361     //---- do boot
362     OSi_DoBoot();
363 }
364 
365 #ifdef  SDK_TWL
366 #include    <twl/wram_end.h>
367 #else
368 #include    <nitro/wram_end.h>
369 #endif
370 #endif // ifdef SDK_ARM9
371 
372 /*---------------------------------------------------------------------------*
373   Name:         OSi_DoBoot
374 
375   Description:  do boot
376 
377   Arguments:    None.
378 
379   Returns:      None.
380  *---------------------------------------------------------------------------*/
381 //---------------- ARM9
382 #ifdef SDK_ARM9
383 #ifdef  SDK_TWL
384 #include    <twl/itcm_begin.h>
385 #else
386 #include    <nitro/itcm_begin.h>
387 #endif
OSi_DoBoot(void)388 asm void OSi_DoBoot( void )
389 {
390     //---- set IME = 0
391     mov         r12, #HW_REG_BASE
392     str         r12, [r12, #REG_IME_OFFSET]
393 
394     //---- clear interrupt vector just to make sure
395     ldr         r1, =OSi_HW_DTCM
396     add         r1, r1, #0x3fc0
397     add         r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR
398     mov         r0, #0
399     str         r0, [r1, #0]
400 
401     //---- Synchronicity with ARM7
402     ldr         r1, =REG_SUBPINTF_ADDR
403 @1:
404     ldrh        r0, [r1]
405     and         r0, r0, #0x000f
406     cmp         r0, #0x0001
407     bne         @1                              // wait till subp status == 1
408     mov         r0, #0x0100
409     strh        r0, [r1]                        // mainp status == 1
410 
411     //---- clear some memory
412     mov         r0, #0
413     ldr         r3, =HW_EXCP_VECTOR_MAIN        // save exception vector
414     ldr         r4, [r3]
415 
416     ldr         r1, =HW_BIOS_EXCP_STACK_MAIN    // clear system area. (exception, arena, DMA clear buf...)
417     mov         r2, #0x80
418     bl          OSi_CpuClear32
419 
420     str         r4, [r3]                        // restore exception vector
421 
422     ldr         r1, =HW_PXI_SIGNAL_PARAM_ARM9   // clear system area. (wm, thread, lock, intr...)
423     mov         r2, #0x18
424     bl          OSi_CpuClear32
425 
426     ldr         r1, =HW_WM_RSSI_POOL
427     strh        r0, [r1]
428 
429     ldr         r1, =HW_COMPONENT_PARAM         // clear system area. (wm, thread, lock, intr...)
430     mov         r2, #0x64
431     bl          OSi_CpuClear32
432 
433     //---- Synchronicity with ARM7
434     ldr         r1, =REG_SUBPINTF_ADDR
435 @2:
436     ldrh        r0, [r1]
437     and         r0, r0, #0x000f
438     cmp         r0, #0x0001                     // wait till subp status == 0
439     beq         @2
440     mov         r0, #0
441     strh        r0, [r1]                        // mainp status == 0
442 
443     //---- get boot address
444     ldr         r3, =HW_ROM_HEADER_BUF          // r3 = ROM header
445     ldr         r12, [r3, #0x24]                // lr = r12 = ARM9 entry address
446     mov         lr, r12
447 
448     //---- clear registers r0-r11
449     ldr         r11, =HW_PXI_SIGNAL_PARAM_ARM9  // clear r0-r11
450     ldmia       r11, {r0-r10}
451     mov         r11, #0
452 
453     //---- boot game
454     bx          r12                             // jump to r12
455 }
456 #ifdef  SDK_TWL
457 #include <twl/itcm_end.h>
458 #else
459 #include <nitro/itcm_end.h>
460 #endif
461 
462 //---------------- ARM7
463 #else  //ifdef SDK_ARM9
464 #ifdef  SDK_TWL
465 #include <twl/wram_begin.h>
466 #else
467 #include <nitro/wram_begin.h>
468 #endif
OSi_DoBoot(void)469 asm void OSi_DoBoot( void )
470 {
471     //---- set IME = 0
472     mov         r12, #HW_REG_BASE
473     str         r12, [r12, #REG_IME_OFFSET]
474 
475     //---- clear interrupt vector just to make sure
476     ldr         r1, =HW_INTR_VECTOR_BUF
477     mov         r0, #0
478     str         r0, [r1, #0]
479 
480     //---- Synchronicity with ARM9
481     ldr         r1, =REG_MAINPINTF_ADDR
482     mov         r0, #0x0100
483     strh        r0, [r1]                        // subp status = 1
484 @1:
485     ldrh        r0, [r1]
486     and         r0, r0, #0x000f
487     cmp         r0, #0x0001                     // wait till mainp status == 1
488     bne         @1
489 
490     //---- Synchronicity with ARM9
491     ldr         r1, =REG_MAINPINTF_ADDR
492     mov         r0, #0                          // subp status = 0
493     strh        r0, [r1]
494 @2:
495     ldrh        r0, [r1]
496     cmp         r0, #0x0001                     // wait till mainp status == 0
497     beq         @2
498 
499     //---- get boot address
500     ldr         r3, =HW_ROM_HEADER_BUF          // r3 = ROM header
501     ldr         r12, [r3, #0x34]                // lr = r12 = ARM7 entry address
502     mov         lr, r12
503 
504     //---- clear registers r0-r3
505     mov         r0, #0
506     mov         r1, #0
507     mov         r2, #0
508     mov         r3, #0
509 
510     //---- boot game
511     bx          r12
512 }
513 #ifdef  SDK_TWL
514 #include <twl/wram_end.h>
515 #else
516 #include <nitro/wram_end.h>
517 #endif
518 #endif //ifdef SDK_ARM9
519 
520 
521 #ifdef SDK_ARM9
522 #ifdef  SDK_TWL
523 #include    <twl/itcm_begin.h>
524 #else
525 #include    <nitro/itcm_begin.h>
526 #endif
527 /*---------------------------------------------------------------------------*
528   Name:         OSi_CpuClear32
529 
530   Description:  Fills memory with specified data.
531                 32-bit version.
532 
533   Arguments:    data: Fill data
534                 destp : destination address
535                 size: Size (bytes)
536 
537   Returns:      None.
538  *---------------------------------------------------------------------------*/
OSi_CpuClear32(register u32 data,register void * destp,register u32 size)539 static asm void  OSi_CpuClear32( register u32 data, register void *destp, register u32 size )
540 {
541     add     r12, r1, r2             // r12: destEndp = destp + size
542 @1:
543     cmp     r1, r12                 // while (destp < destEndp)
544     stmltia r1!, {r0}               // *((vu32 *)(destp++)) = data
545     blt     @1
546     bx      lr
547 }
548 
549 /*---------------------------------------------------------------------------*
550   Name:         OSi_ReloadRomData
551 
552   Description:  reload ROM data from card
553 
554   Arguments:    None.
555 
556   Returns:      None.
557  *---------------------------------------------------------------------------*/
OSi_ReloadRomData(void)558 static void OSi_ReloadRomData(void)
559 {
560     u32     p = (u32)HW_ROM_HEADER_BUF;
561     const u32 rom_base = *(u32 *)HW_ROM_BASE_OFFSET_BUF;
562 
563     /* if necessary, reload ROM header. */
564     if (rom_base >= 0x8000)
565         OSi_ReadCardRom32(rom_base, (void *)p, 0x160);
566 
567     {
568         u32     src_arm9 = *(u32 *)(p + 0x20);
569         u32     dst_arm9 = *(u32 *)(p + 0x28);
570         u32     len_arm9 = *(u32 *)(p + 0x2c);
571         u32     src_arm7 = *(u32 *)(p + 0x30);
572         u32     dst_arm7 = *(u32 *)(p + 0x38);
573         u32     len_arm7 = *(u32 *)(p + 0x3c);
574 
575         {
576             OSIntrMode bak_cpsr = OS_DisableInterrupts();
577             DC_StoreAll();
578             DC_InvalidateAll();
579             (void)OS_RestoreInterrupts(bak_cpsr);
580         }
581         IC_InvalidateAll();
582         DC_WaitWriteBufferEmpty();
583 
584         //OS_Printf("A9 %x %x %x %x\n", *(u32*)(p+0x20), *(u32*)(p+0x24), *(u32*)(p+0x28), *(u32*)(p+0x2c) );
585         //OS_Printf("A7 %x %x %x %x\n", *(u32*)(p+0x30), *(u32*)(p+0x34), *(u32*)(p+0x38), *(u32*)(p+0x3c) );
586 
587         /* add base-offset. */
588         src_arm9 += rom_base;
589         src_arm7 += rom_base;
590 
591         //---- ARM9 code
592         if (src_arm9 < 0x8000)         // top 32KByte of the rom cannot be read.
593         {
594             u32     diff = 0x8000 - src_arm9;
595             src_arm9 = 0x8000;
596             dst_arm9 += diff;
597             len_arm9 -= diff;
598         }
599         OSi_ReadCardRom32(src_arm9, (void *)dst_arm9, (int)len_arm9);
600 
601         //---- ARM7 code
602         OSi_ReadCardRom32(src_arm7, (void *)dst_arm7, (int)len_arm7);
603     }
604 }
605 
606 /*---------------------------------------------------------------------------*
607   Name:         OSi_ReadCardRom32
608 
609   Description:  read card data by CPU
610                 (subroutine of OSi_ReloadRomData)
611 
612   Arguments:    src: Source address, need to be 4-byte aligned
613                 dest: Destination address, need to be 4-byte aligned
614                 len: Size of forwarding
615 
616   Returns:      None.
617  *---------------------------------------------------------------------------*/
OSi_ReadCardRom32(u32 src,void * dst,int len)618 static void OSi_ReadCardRom32(u32 src, void *dst, int len)
619 {
620     //---- I/O registers for CARD
621     vu8    *const reg_CARD_MASTERCNT = (vu8 *)(HW_REG_BASE + 0x1a1);
622     vu8    *const reg_CARD_CMD = (vu8 *)(HW_REG_BASE + 0x1a8);
623     vu32   *const reg_CARD_CNT = (vu32 *)(HW_REG_BASE + 0x1a4);
624     vu32   *const reg_CARD_DATA = (vu32 *)(HW_REG_BASE + 0x100010);
625     vu32   *const hdr_GAME_BUF = (vu32 *)(HW_ROM_HEADER_BUF + 0x60);
626 
627 
628     enum
629     {
630         CARD_MASTER_SELECT_ROM = 0x00,
631         CARD_MASTER_ENABLE = 0x80,
632         CARD_CMD_READ_PAGE = 0xb7,
633         CARD_CTRL_CMD_MASK = 0x07000000,
634         CARD_CTRL_CMD_PAGE = 0x01000000,
635         CARD_CTRL_READ = 0x00000000,
636         CARD_CTRL_RESET_HI = 0x20000000,
637         CARD_CTRL_START = 0x80000000,
638         CARD_CTRL_READY = 0x00800000,
639         CARD_ENUM_END
640     };
641 
642     const u32 ctrl_start = (u32)((*hdr_GAME_BUF & ~CARD_CTRL_CMD_MASK)
643                                  | (CARD_CTRL_CMD_PAGE | CARD_CTRL_READ
644                                     | CARD_CTRL_START | CARD_CTRL_RESET_HI));
645 
646     //---- position of page. minus value mean before range.
647     int     pos = -(int)(src & (512 - 1));
648 
649     //---- wait finishing just to make sure, and turn master enable on
650     while ((*reg_CARD_CNT & CARD_CTRL_START) != 0)
651     {
652     }
653     *reg_CARD_MASTERCNT = (u32)(CARD_MASTER_SELECT_ROM | CARD_MASTER_ENABLE);
654 
655     for (src = (u32)(src + pos); pos < len; src += 512)
656     {
657         //---- setting for command of one page reading
658         reg_CARD_CMD[0] = (u8)(CARD_CMD_READ_PAGE);
659         reg_CARD_CMD[1] = (u8)(src >> 24);
660         reg_CARD_CMD[2] = (u8)(src >> 16);
661         reg_CARD_CMD[3] = (u8)(src >> 8);
662         reg_CARD_CMD[4] = (u8)(src >> 0);
663         reg_CARD_CMD[5] = (u8)(0);
664         reg_CARD_CMD[6] = (u8)(0);
665         reg_CARD_CMD[7] = (u8)(0);
666 
667         //---- start forwarding by CPU
668         *reg_CARD_CNT = ctrl_start;
669         for (;;)
670         {
671             u32     ctrl = *reg_CARD_CNT;
672 
673             //---- check if ok to read word data
674             if ((ctrl & CARD_CTRL_READY) != 0)
675             {
676                 //---- read data
677                 const u32 data = *reg_CARD_DATA;
678 
679                 //---- store data
680                 if ((pos >= 0) && (pos < len))
681                 {
682                     *(u32 *)((u32)dst + pos) = data;
683                 }
684 
685                 pos += sizeof(u32);
686             }
687 
688             //---- notice: need to read whole one page data
689             if (!(ctrl & CARD_CTRL_START))
690             {
691                 break;
692             }
693         }
694     }
695 }
696 
697 #ifdef  SDK_TWL
698 #include <twl/itcm_end.h>
699 #else
700 #include <nitro/itcm_end.h>
701 #endif
702 #endif //ifdef SDK_ARM9
703 
704 #ifdef  SDK_TWL
705 /*---------------------------------------------------------------------------*
706   Name:         OSi_ReloadTwlRomData
707 
708   Description:
709 
710   Arguments:    None.
711 
712   Returns:      None.
713  *---------------------------------------------------------------------------*/
714 #ifdef  SDK_ARM9
715 //---------------- ARM9
716 #include <twl/itcm_begin.h>
717 static asm void
OSi_ReloadTwlRomData(void)718 OSi_ReloadTwlRomData(void)
719 {
720     stmfd   sp!, {lr}
721 @shakeHand01:
722     /* Synch with ARM7*/
723     ldr     r0, =HW_BOOT_SYNC_PHASE
724     mov     r1, #1
725     strh    r1, [r0]
726     ldr     r0, =HW_BOOT_SHAKEHAND_9
727     ldr     r1, =HW_BOOT_SHAKEHAND_7
728     ldrh    r2, [r1]
729     ldrh    r3, [r0]
730 @shakeHand01_loop:
731     add     r3, r3, #1
732     strh    r3, [r0]
733     ldrh    r12, [r1]
734     cmp     r2, r12
735     beq     @shakeHand01_loop
736     add     r3, r3, #1
737     strh    r3, [r0]
738 
739     /* The ROM base offset cannot be changed when running in TWL mode */
740     mov     r0, #0
741     stmfd   sp!, {r0}
742 
743 @loadStatic:
744     /* Load the binary for the ARM9 */
745     ldr     r12, =HW_ROM_HEADER_BUF
746     ldr     r0, [r12, #0x20]
747     ldr     r1, [r12, #0x28]
748     ldr     r2, [r12, #0x2c]
749     ldr     r3, [sp]
750     add     r0, r0, r3
751     subs    r3, r0, #0x8000
752     movlt   r0, #0x8000
753     sublt   r1, r1, r3
754     addlt   r2, r2, r3
755     cmp     r2, #0
756     blgt    OSi_ReadCardRom32
757     /* Load the binary for the ARM97 */
758     ldr     r12, =HW_ROM_HEADER_BUF
759     ldr     r0, [r12, #0x30]
760     ldr     r1, [r12, #0x38]
761     ldr     r2, [r12, #0x3c]
762     ldr     r3, [sp]
763     add     r0, r0, r3
764     cmp     r2, #0
765     blgt    OSi_ReadCardRom32
766 
767 @loadLtdStatic:
768     /* Load the extension binary for the ARM9 */
769     ldr     r12, =HW_TWL_ROM_HEADER_BUF
770     ldr     r0, [r12, #0x1c0]
771     ldr     r1, [r12, #0x1c8]
772     ldr     r2, [r12, #0x1cc]
773     add     r0, r0, #0x4000
774     add     r1, r1, #0x4000
775     sub     r2, r2, #0x4000
776     subs    r3, r0, #0x8000
777     movlt   r0, #0x8000
778     sublt   r1, r1, r3
779     addlt   r2, r2, r3
780     cmp     r2, #0
781     blgt    OSi_ReadCardRom32
782     /* Load the extension binary for the ARM7 */
783     ldr     r12, =HW_TWL_ROM_HEADER_BUF
784     ldr     r0, [r12, #0x1d0]
785     ldr     r1, [r12, #0x1d8]
786     ldr     r2, [r12, #0x1dc]
787     add     r0, r0, #0x4000
788     add     r1, r1, #0x4000
789     sub     r2, r2, #0x4000
790     subs    r3, r0, #0x8000
791     movlt   r0, #0x8000
792     sublt   r1, r1, r3
793     addlt   r2, r2, r3
794     cmp     r2, #0
795     blgt    OSi_ReadCardRom32
796     /* It is necessary to recover the beginning portion of the extension binary that was retracted */
797     mov     r3, #2
798 @arrangeCache:
799     ldmfd   sp!, {r0}
800     /* DC_StoreAll() */
801     mov     r1, #0
802 @arrangeCache_loop01:
803     mov     r0, #0
804 @arrangeCache_loop02:
805     orr     r2, r1, r0
806     mcr     p15, 0, r2, c7, c10, 2
807     add     r0, r0, #HW_CACHE_LINE_SIZE
808     cmp     r0, #(HW_DCACHE_SIZE / 4)
809     blt     @arrangeCache_loop02
810     adds    r1, r1, #(1 << HW_C7_CACHE_SET_NO_SHIFT)
811     bne     @arrangeCache_loop01
812     /* DC_InvalidateAll() */
813     mov     r0, #0
814     mcr     p15, 0, r0, c7, c6, 0
815     /* IC_InvalidateAll() */
816 //  mov     r0, #0
817     mcr     p15, 0, r0, c7, c5, 0
818     /* DC_WaitWriteBufferEmpty() */
819 //  mov     r0, #0
820     mcr     p15, 0, r0, c7, c10, 4
821 
822     /* Synch with ARM7 */
823     ldr     r0, =HW_BOOT_SYNC_PHASE
824     strh    r3, [r0]
825     ldr     r0, =HW_BOOT_SHAKEHAND_9
826     ldr     r1, =HW_BOOT_SHAKEHAND_7
827     ldrh    r2, [r1]
828     ldrh    r3, [r0]
829 @shakeHand02_loop:
830     add     r3, r3, #1
831     strh    r3, [r0]
832     ldrh    r12, [r1]
833     cmp     r2, r12
834     beq     @shakeHand02_loop
835     add     r3, r3, #1
836     strh    r3, [r0]
837 
838     ldmfd   sp!, {pc}
839 //  bx      lr
840 }
841 #include <twl/itcm_end.h>
842 
843 #else   // ifdef SDK_ARM9
844 //---------------- ARM7
845 #include <twl/ltdwram_begin.h>
846 static asm void
OSi_ReloadTwlRomData(void)847 OSi_ReloadTwlRomData(void)
848 {
849 @shakeHand01:
850     /* Synch with ARM9 */
851     ldr     r0, =HW_BOOT_SHAKEHAND_9
852     ldr     r1, =HW_BOOT_SHAKEHAND_7
853     ldrh    r2, [r0]
854     ldrh    r3, [r1]
855 @shakeHand01_loop:
856     add     r3, r3, #1
857     strh    r3, [r1]
858     ldrh    r12, [r0]
859     cmp     r2, r12
860     beq     @shakeHand01_loop
861     add     r3, r3, #1
862     strh    r3, [r1]
863 
864     ldr     r0, =HW_BOOT_SYNC_PHASE
865 @shakeHand01_waitLoop:
866     ldrh    r1, [r0]
867     cmp     r1, #3
868     beq     @shakeHand02
869     cmp     r1, #2
870     bne     @shakeHand01_waitLoop
871 
872 @restoreShelteredBinary:
873     ldr     r12, =HW_TWL_ROM_HEADER_BUF
874     /* Recover retracted data from the ARM7 extended binary */
875     ldr     r0, [r12, #0x1dc]
876     cmp     r0, #0
877     beq     @restoreNext
878     ldr     r2, [r12, #0x1d8]   // r2 = Resident module RAM address for ARM7
879     ldr     r0, =OSi_LtdMainParams
880     ldr     r3, [r0]            // r3 = end of src address
881     sub     r1, r3, #0x4000     // r1 = start of src address
882 @restoreLoop01:
883     ldr     r0, [r1], #4
884     str     r0, [r2], #4
885     cmp     r1, r3
886     blt     @restoreLoop01
887 
888 @restoreNext:
889     /* Recover retracted data of the extension binary for ARM9 */
890     ldr     r0, [r12, #0x1cc]
891     cmp     r0, #0
892     beq     @shakeHand02
893     ldr     r2, [r12, #0x1c8]   // r2 = Resident module RAM address for ARM9
894     ldr     r0, =OSi_LtdMainParams
895     ldr     r0, [r0]
896     sub     r3, r0, #0x4000     // r3 = end of src address
897     sub     r1, r3, #0x4000     // r1 = start of src address
898 @restoreLoop02:
899     ldr     r0, [r1], #4
900     str     r0, [r2], #4
901     cmp     r1, r3
902     blt     @restoreLoop02
903 
904 @shakeHand02:
905     /* Synch with ARM9 */
906     ldr     r0, =HW_BOOT_SHAKEHAND_9
907     ldr     r1, =HW_BOOT_SHAKEHAND_7
908     ldrh    r2, [r0]
909     ldrh    r3, [r1]
910 @shakeHand02_loop:
911     add     r3, r3, #1
912     strh    r3, [r1]
913     ldrh    r12, [r0]
914     cmp     r2, r12
915     beq     @shakeHand02_loop
916     add     r3, r3, #1
917     strh    r3, [r1]
918 
919     bx      lr
920 }
921 #include <twl/ltdwram_end.h>
922 
923 #endif  // ifdef SDK_ARM9
924 #endif  // ifdef SDK_TWL
925