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