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:: 2010-04-09#$
14   $Rev: 11318 $
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(BOOL ontwl);
33 static void OSi_ReadCardRom32(u32 src, void *dst, int len);
34 
35 extern u32  OSi_GetOriginalExceptionHandler(void);
36 #endif // ifdef SDK_ARM9
37 
38 void OSi_DoResetSystem(void);
39 static void OSi_DoBoot(void);
40 
41 #ifdef  SDK_TWL
42 static void OSi_ReloadTwlRomData(void);
43 #ifdef  SDK_ARM7
44 extern void SDK_LTDAUTOLOAD_LTDMAIN_START(void);
45 void* const OSi_LtdMainParams[] =
46 {
47     (void*)SDK_LTDAUTOLOAD_LTDMAIN_START,
48 };
49 #endif
50 #endif
51 
52 //---------------- Local variables
53 static u16 OSi_IsInitReset = FALSE;
54 
55 //================================================================================
56 /*---------------------------------------------------------------------------*
57   Name:         OS_InitReset
58 
59   Description:  Initializes reset system.
60 
61   Arguments:    None.
62 
63   Returns:      None.
64  *---------------------------------------------------------------------------*/
OS_InitReset(void)65 void OS_InitReset(void)
66 {
67     if (OSi_IsInitReset)
68     {
69         return;
70     }
71     OSi_IsInitReset = TRUE;
72 
73     //---------------- ARM9
74 #ifdef SDK_ARM9
75     //---- Wait ARM7 PXI library start
76     PXI_Init();
77     while (!PXI_IsCallbackReady(PXI_FIFO_TAG_OS, PXI_PROC_ARM7))
78     {
79     }
80 #endif
81 
82     //---- Set PXI receive callback
83     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_OS, OSi_CommonCallback);
84 }
85 
86 /*---------------------------------------------------------------------------*
87   Name:         OS_ResetSystem
88 
89   Description:  Starts reset sequence.
90                 To decrease code in ITCM or WRAM,
91                 separate this function from OSi_DoResetSystem()
92 
93   Arguments:    (ARM9) parameter: Reset parameter
94                 (ARM7) None
95 
96   Returns:      None.
97  *---------------------------------------------------------------------------*/
98 //---------------- ARM9
99 #ifdef SDK_ARM9
OS_ResetSystem(u32 parameter)100 void OS_ResetSystem(u32 parameter)
101 {
102 #ifdef  SDK_TWL
103     //---- Stop if reset from non-card application
104     if ((MB_IsMultiBootChild() == TRUE) ||
105         ((OS_IsRunOnTwl() == TRUE) && ((*((u32*)(HW_TWL_ROM_HEADER_BUF + 0x234)) & 0x00000004) != 0)))
106     {
107 #ifndef SDK_FINALROM
108         OS_TPanic("Only card booted application can execute software reset.\nSee OS_ResetSystem() reference manual.");
109 #else
110         OS_TPanic("");
111 #endif
112     }
113 #else
114     //---- Stop if reset from multiboot child
115     if (MB_IsMultiBootChild())
116     {
117 #ifndef SDK_FINALROM
118         OS_TPanic("Cannot reset from MB child.\nSee OS_ResetSystem() reference manual.");
119 #else
120         OS_TPanic("");
121 #endif
122     }
123 #endif
124 
125 #ifdef  SDK_TWL
126     if ( OS_IsRunOnTwl() )
127     {
128         // End processing
129         // If making an ARM7 processor request, wait for the callback function to complete
130         PMi_ExecutePostExitCallbackList();
131     }
132 #endif
133 
134     //---- Wait while card is locked
135     {
136         u16     id = (u16)OS_GetLockID();
137         CARD_LockRom(id);
138     }
139 
140     //---- Set only PXI interrupt available
141     (void)OS_SetIrqMask(OS_IE_FIFO_RECV);
142     (void)OS_ResetRequestIrqMask(~OS_IE_FIFO_RECV);
143 
144     //---- Stop all DMA
145 	MI_StopAllDma();
146 #ifdef SDK_TWL
147 	if (OS_IsRunOnTwl())
148 	{
149 		MI_StopAllNDma();
150 	}
151 #endif
152 
153     //---- Save parameter
154     *(u32 *)HW_RESET_PARAMETER_BUF = parameter;
155 
156     //---- Send reset command to ARM7
157     OSi_SendToPxi(OS_PXI_COMMAND_RESET);
158 
159     //---- Get original exception handler and put into temp area to set back later
160     *(u32*)HW_COMPONENT_PARAM = OSi_GetOriginalExceptionHandler();
161 
162     //---- Reset
163     OSi_DoResetSystem();
164 
165     // Doesn't reach here
166 }
167 
168 //---------------- ARM7
169 #else  // ifdef SDK_ARM9
170 #pragma dont_inline on
OS_ResetSystem(void)171 void OS_ResetSystem(void)
172 {
173     //---- Set only PXI interrupt available
174     (void)OS_SetIrqMask(OS_IE_FIFO_RECV);
175     (void)OS_ResetRequestIrqMask(0xffffffff /*All request */ );
176 
177     //---- Stop all DMA
178 	{
179 		u32 n;
180 		for( n=0; n<4; n++ )
181 		{
182 			MI_StopDma(n);
183 #ifdef SDK_TWL
184 			if (OS_IsRunOnTwl())
185 			{
186 				MI_StopNDma(n);
187 			}
188 #endif
189 		}
190 	}
191 
192     //---- Sound stop
193     SND_Shutdown();
194 
195     //---- Send reset command to ARM9
196     OSi_SendToPxi(OS_PXI_COMMAND_RESET);
197 
198     //---- Reset
199     OSi_DoResetSystem();
200 }
201 #pragma dont_inline reset
202 #endif // ifdef SDK_ARM9
203 
204 #define SDK_OS_RESET_COMPACT
205 
206 #if defined(SDK_TWL) && defined(SDK_ARM9)
207 #include <twl/itcm_begin.h>
208 
209 #if defined(SDK_OS_RESET_COMPACT)
210 // Bundle all of the SVC processing used at the final stage of a software reset, and back it up to ITCM
211 #include <nitro/code16.h>
212 #define SVC_ID_SHA1_INIT   36
213 #define SVC_ID_SHA1_UPDATE 37
214 #define SVC_ID_SHA1_FINAL  38
215 #define SVC_ID_CALC_SHA1   39
216 #define SVC_ID_CMP_SHA1    40
OSi_VerifyStaticSegmentHash(const u8 * src,u32 len,const void * digest)217 asm static BOOL OSi_VerifyStaticSegmentHash(const u8 *src, u32 len, const void *digest)
218 {
219 #define VAR_STACK_DIGEST  (0)
220 #define VAR_STACK_PADBUF  (VAR_STACK_DIGEST  + SVC_SHA1_DIGEST_SIZE)
221 #define VAR_STACK_CONTEXT (VAR_STACK_PADBUF  + SVC_SHA1_BLOCK_SIZE)
222 #define VAR_STACK_TOTAL   (VAR_STACK_CONTEXT + sizeof(SVCSHA1Context))
223     PUSH    {R3, R4, R5, R6, R7, LR}
224     SUB     SP, #VAR_STACK_TOTAL // 0xB8
225     MOV     R4, R1 // len
226     MOV     R5, R0 // src
227     MOV     R7, R2 // digest
228     // Initialize SHA-1 structure
229     ADD     R0, SP, #VAR_STACK_CONTEXT
230     MOV     R3, #SVCSHA1Context.sha_block
231     ADD     R3, R0
232     MOV     R2, #0
233     STR     R2, [R3]
234     SWI     SVC_ID_SHA1_INIT
235     // Input ipad
236     LDR     R0, =@key
237     ADD     R1, SP, #VAR_STACK_PADBUF
238     MOV     R2, #0x0
239     MOV     R3, #0x36
240 @0:
241     LDRB    R6, [R0, R2]
242     EOR     R6, R3
243     STRB    R6, [R1, R2]
244     ADD     R2, R2, #0x1
245     CMP     R2, #SVC_SHA1_BLOCK_SIZE
246     BLT     @0
247     ADD     R0, SP, #VAR_STACK_CONTEXT
248     SWI     SVC_ID_SHA1_UPDATE
249     // Input message
250     ADD     R0, SP, #VAR_STACK_CONTEXT
251     MOV     R1, R5
252     MOV     R2, R4
253     SWI     SVC_ID_SHA1_UPDATE
254     // Calculate ihash
255     ADD     R0, SP, #VAR_STACK_DIGEST
256     ADD     R1, SP, #VAR_STACK_CONTEXT
257     SWI     SVC_ID_SHA1_FINAL
258     // Initialize SHA-1 structure
259     ADD     R0, SP, #VAR_STACK_CONTEXT
260     MOV     R3, #SVCSHA1Context.sha_block
261     ADD     R3, R0
262     MOV     R2, #0
263     STR     R2, [R3]
264     SWI     SVC_ID_SHA1_INIT
265     // Input opad
266     LDR     R0, =@key
267     ADD     R1, SP, #VAR_STACK_PADBUF
268     MOV     R2, #0x0
269     MOV     R3, #0x5C
270 @1:
271     LDRB    R6, [R0, R2]
272     EOR     R6, R3
273     STRB    R6, [R1, R2]
274     ADD     R2, R2, #0x1
275     CMP     R2, #SVC_SHA1_BLOCK_SIZE
276     BLT     @1
277     ADD     R0, SP, #VAR_STACK_CONTEXT
278     SWI     SVC_ID_SHA1_UPDATE
279     // Input ihash
280     ADD     R0, SP, #VAR_STACK_CONTEXT
281     ADD     R1, SP, #VAR_STACK_DIGEST
282     MOV     R2, #SVC_SHA1_DIGEST_SIZE
283     SWI     SVC_ID_SHA1_UPDATE
284     // Calculate ohash
285     ADD     R0, SP, #VAR_STACK_DIGEST
286     ADD     R1, SP, #VAR_STACK_CONTEXT
287     SWI     SVC_ID_SHA1_FINAL
288     // Compare ohash
289     ADD     R0, SP, #VAR_STACK_DIGEST
290     MOV     R1, R7
291     SWI     SVC_ID_CMP_SHA1
292     CMP     R0, #0x0
293     BEQ     @2
294     MOV     R0, #0x1
295 @2:
296     ADD     SP, #0xB8
297     POP     {R3, R4, R5, R6, R7, PC}
298     NOP
299 #undef VAR_STACK_DIGEST
300 #undef VAR_STACK_PADBUF
301 #undef VAR_STACK_CONTEXT
302 #undef VAR_STACK_TOTAL
303 @key:
304     dcd 0xDEC00621
305     dcd 0x3FCE98BA
306     dcd 0x9DE392A6
307     dcd 0x01EDF246
308     dcd 0x08CCE376
309     dcd 0xFA632356
310     dcd 0xDFECD4CA
311     dcd 0x3478629A
312     dcd 0x3C636D8F
313     dcd 0x92CA22FE
314     dcd 0x23978820
315     dcd 0xC2AECFD2
316     dcd 0xFE8D6732
317     dcd 0x986483CA
318     dcd 0x373EFDAC
319     dcd 0x24584687
320 }
321 #include <nitro/codereset.h>
322 #include <nitro/code32.h>
323 #endif
324 
325 #if !defined(SDK_OS_RESET_COMPACT)
326 #define OSi_TCM_REGION_BASE_MASK  HW_C9_TCMR_BASE_MASK  // 0xfffff000
OSi_GetDTCMAddress(void)327 static asm u32 OSi_GetDTCMAddress(void)
328 {
329     mrc      p15, 0, r0, c9, c1, 0
330     ldr      r1, =OSi_TCM_REGION_BASE_MASK
331     and      r0, r0, r1
332     bx       lr
333 }
334 #endif
335 /*---------------------------------------------------------------------------*
336   Name:         OSi_VerifyStaticSegments
337 
338   Description:  Verifies 4 static segments before rebooting.
339 
340   Arguments:    None.
341 
342   Returns:      None.
343  *---------------------------------------------------------------------------*/
OSi_VerifyStaticSegments(void)344 static void OSi_VerifyStaticSegments(void)
345 {
346     BOOL                    result = TRUE;
347     const CARDRomHeaderTWL *header = (const CARDRomHeaderTWL *)HW_TWL_ROM_HEADER_BUF;
348     if ((((const u8 *)header)[0x1C] & 0x01) != 0)
349     {
350         int                     i;
351 #if !defined(SDK_OS_RESET_COMPACT)
352         // Use DTCM as work area
353         u8                     *work = (u8 *)OSi_GetDTCMAddress();
354         SVCHMACSHA1Context     *context = (SVCHMACSHA1Context *)&work[0];
355         u8                     *digest = &work[sizeof(SVCHMACSHA1Context)];
356 #else
357         BOOL OSi_VerifyStaticSegmentHash(const u8 *src, u32 len, const void *digest);
358 #endif
359         // Calculate and verify HMAC-SHA1 of the static segments
360         enum { SEGMENT_TOTAL = 4 };
361         struct Segment { u8 *address; u32 size; } *(table[SEGMENT_TOTAL]);
362         const void             *(compareDigests[SEGMENT_TOTAL]);
363         table[0] = (struct Segment *)&header->ntr.main_ram_address;
364         table[1] = (struct Segment *)&header->ntr.sub_ram_address;
365         table[2] = (struct Segment *)&header->main_ltd_ram_address;
366         table[3] = (struct Segment *)&header->sub_ltd_ram_address;
367         compareDigests[0] = &((const u8 *)header)[0x3A0];
368         compareDigests[1] = header->sub_static_digest;
369         compareDigests[2] = header->main_ltd_static_digest;
370         compareDigests[3] = header->sub_ltd_static_digest;
371         for (i = 0; i < SEGMENT_TOTAL; ++i)
372         {
373 #if !defined(SDK_OS_RESET_COMPACT)
374             static const u8 hmacKey[] =
375             {
376                 0x21, 0x06, 0xc0, 0xde, 0xba, 0x98, 0xce, 0x3f,
377                 0xa6, 0x92, 0xe3, 0x9d, 0x46, 0xf2, 0xed, 0x01,
378                 0x76, 0xe3, 0xcc, 0x08, 0x56, 0x23, 0x63, 0xfa,
379                 0xca, 0xd4, 0xec, 0xdf, 0x9a, 0x62, 0x78, 0x34,
380                 0x8f, 0x6d, 0x63, 0x3c, 0xfe, 0x22, 0xca, 0x92,
381                 0x20, 0x88, 0x97, 0x23, 0xd2, 0xcf, 0xae, 0xc2,
382                 0x32, 0x67, 0x8d, 0xfe, 0xca, 0x83, 0x64, 0x98,
383                 0xac, 0xfd, 0x3e, 0x37, 0x87, 0x46, 0x58, 0x24,
384             };
385 #endif
386             const u8   *address = table[i]->address;
387             u32         size = table[i]->size;
388             if (i == 0)
389             {
390                 address += 0x4000;
391                 size -= 0x4000;
392             }
393 #if !defined(SDK_OS_RESET_COMPACT)
394             SVC_HMACSHA1Init(context, hmacKey, sizeof(hmacKey));
395             SVC_HMACSHA1Update(context, address, size);
396             SVC_HMACSHA1GetHash(context, digest);
397             result &= (SVC_CompareSHA1(digest, compareDigests[i]) != FALSE);
398 #else
399             result &= OSi_VerifyStaticSegmentHash(address, size, compareDigests[i]);
400 #endif
401         }
402     }
403     // If any segment is invalid, enter the infinite loop
404     while (result == FALSE)
405     {
406     }
407 }
408 #include <twl/itcm_end.h>
409 #endif // defined(SDK_TWL) && defined(SDK_ARM9)
410 
411 /*---------------------------------------------------------------------------*
412   Name:         OSi_DoResetSystem
413 
414   Description:  Starts reset sequence.
415                 Subroutine of OS_ResetSystem().
416                 This part is put in ITCM/WRAM because ROM data will be
417                 loaded anew.
418 
419   Arguments:    None.
420 
421   Returns:      None.
422  *---------------------------------------------------------------------------*/
423 //---------------- ARM9
424 #ifdef SDK_ARM9
425 #ifdef  SDK_TWL
426 #include    <twl/itcm_begin.h>
427 #else
428 #include    <nitro/itcm_begin.h>
429 #endif
430 SDK_WEAK_SYMBOL
OSi_DoResetSystem(void)431 void OSi_DoResetSystem(void)
432 __attribute__((never_inline))
433 {
434     //---- Wait to receive reset command from ARM7
435     while (!OS_IsResetOccurred())
436     {
437     }
438 
439     //---- Set IME = 0
440     reg_OS_IME = 0;
441 
442     //---- Reload ROM data
443 #ifdef  SDK_TWL
444     if (OS_IsRunOnTwl() == TRUE)
445     {
446         OSi_ReloadRomData(TRUE);
447         OSi_VerifyStaticSegments();
448 
449         //---- init WRAM-A/B/C setting
450         {
451             int i;
452             u32 *p1 = (u32*)(HW_TWL_ROM_HEADER_BUF + 0x0180);
453             u32 *p2 = (u32*)(REG_MBK1_ADDR);
454             for(i=0; i<8; i++)
455             {
456                 *p2++ = *p1++;
457             }
458         }
459     }
460     else
461 #endif
462     {
463         OSi_ReloadRomData(FALSE);
464     }
465 
466     //---- Do boot
467     OSi_DoBoot();
468 }
469 
470 #ifdef  SDK_TWL
471 #include    <twl/itcm_end.h>
472 #else
473 #include    <nitro/itcm_end.h>
474 #endif
475 
476 //---------------- ARM7
477 #else  // ifdef SDK_ARM9
478 #ifdef  SDK_TWL
479 #include    <twl/wram_begin.h>
480 #else
481 #include    <nitro/wram_begin.h>
482 #endif
483 SDK_WEAK_SYMBOL
OSi_DoResetSystem(void)484 void OSi_DoResetSystem(void)
485 __attribute__((never_inline))
486 {
487     //---- Set IME = 0
488     reg_OS_IME = 0;
489 
490 #ifdef  SDK_TWL
491     if (OS_IsRunOnTwl() == TRUE)
492     {
493         OSi_ReloadTwlRomData();
494     }
495 #endif
496 
497     //---- Do boot
498     OSi_DoBoot();
499 }
500 
501 #ifdef  SDK_TWL
502 #include    <twl/wram_end.h>
503 #else
504 #include    <nitro/wram_end.h>
505 #endif
506 #endif // ifdef SDK_ARM9
507 
508 /*---------------------------------------------------------------------------*
509   Name:         OSi_DoBoot
510 
511   Description:  Does boot.
512 
513   Arguments:    None.
514 
515   Returns:      None.
516  *---------------------------------------------------------------------------*/
517 //---------------- ARM9
518 #ifdef SDK_ARM9
519 #ifdef  SDK_TWL
520 #include    <twl/itcm_begin.h>
521 #else
522 #include    <nitro/itcm_begin.h>
523 #endif
OSi_DoBoot(void)524 asm void OSi_DoBoot( void )
525 {
526     //---- Set IME = 0
527     mov         r12, #HW_REG_BASE
528     str         r12, [r12, #REG_IME_OFFSET]
529 
530     //---- Clear interrupt vector just to make sure
531     ldr         r1, =OSi_HW_DTCM
532     add         r1, r1, #0x3fc0
533     add         r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR
534     mov         r0, #0
535     str         r0, [r1, #0]
536 
537     //---- Synchronicity with ARM7
538     ldr         r1, =REG_SUBPINTF_ADDR
539 @1:
540     ldrh        r0, [r1]
541     and         r0, r0, #0x000f
542     cmp         r0, #0x0001
543     bne         @1                              // Wait till subp status == 1
544     mov         r0, #0x0100
545     strh        r0, [r1]                        // mainp status == 1
546 
547     //---- Clear some memory
548     mov         r0, #0
549     ldr         r3, =HW_COMPONENT_PARAM         // save exception vector
550     ldr         r4, [r3]
551 
552     ldr         r1, =HW_BIOS_EXCP_STACK_MAIN    // Clear system area (exception, arena, DMA clear buf...)
553     mov         r2, #0x80
554     bl          OSi_CpuClear32
555 
556     ldr         r3, =HW_EXCP_VECTOR_MAIN        // Restore exception vector
557     str         r4, [r3]
558 
559     ldr         r1, =HW_PXI_SIGNAL_PARAM_ARM9   // Clear system area (wm, thread, lock, intr...)
560     mov         r2, #0x18
561     bl          OSi_CpuClear32
562 
563     ldr         r1, =HW_WM_RSSI_POOL
564     strh        r0, [r1]
565 
566     ldr         r1, =HW_COMPONENT_PARAM         // Clear system area (wm, thread, lock, intr...)
567     mov         r2, #0x64
568     bl          OSi_CpuClear32
569 
570     //---- Synchronicity with ARM7
571     ldr         r1, =REG_SUBPINTF_ADDR
572 @2:
573     ldrh        r0, [r1]
574     and         r0, r0, #0x000f
575     cmp         r0, #0x0001                     // Wait till subp status == 0
576     beq         @2
577     mov         r0, #0
578     strh        r0, [r1]                        // mainp status == 0
579 
580     //---- Get boot address
581     ldr         r3, =HW_ROM_HEADER_BUF          // r3 = ROM header
582     ldr         r12, [r3, #0x24]                // lr = r12 = ARM9 entry address
583     mov         lr, r12
584 
585     //---- Clear registers r0-r11
586     ldr         r11, =HW_PXI_SIGNAL_PARAM_ARM9  // Clear r0-r11
587     ldmia       r11, {r0-r10}
588     mov         r11, #0
589 
590     //---- Boot game
591     bx          r12                             // Jump to r12
592 }
593 #ifdef  SDK_TWL
594 #include <twl/itcm_end.h>
595 #else
596 #include <nitro/itcm_end.h>
597 #endif
598 
599 //---------------- ARM7
600 #else  //ifdef SDK_ARM9
601 #ifdef  SDK_TWL
602 #include <twl/wram_begin.h>
603 #else
604 #include <nitro/wram_begin.h>
605 #endif
OSi_DoBoot(void)606 asm void OSi_DoBoot( void )
607 {
608     //---- Set IME = 0
609     mov         r12, #HW_REG_BASE
610     str         r12, [r12, #REG_IME_OFFSET]
611 
612     //---- Clear interrupt vector just to make sure
613     ldr         r1, =HW_INTR_VECTOR_BUF
614     mov         r0, #0
615     str         r0, [r1, #0]
616 
617     //---- Synchronicity with ARM9
618     ldr         r1, =REG_MAINPINTF_ADDR
619     mov         r0, #0x0100
620     strh        r0, [r1]                        // subp status = 1
621 @1:
622     ldrh        r0, [r1]
623     and         r0, r0, #0x000f
624     cmp         r0, #0x0001                     // Wait till mainp status == 1
625     bne         @1
626 
627     //---- Synchronicity with ARM9
628     ldr         r1, =REG_MAINPINTF_ADDR
629     mov         r0, #0                          // subp status = 0
630     strh        r0, [r1]
631 @2:
632     ldrh        r0, [r1]
633     cmp         r0, #0x0001                     // Wait till mainp status == 0
634     beq         @2
635 
636     //---- Get boot address
637     ldr         r3, =HW_ROM_HEADER_BUF          // r3 = ROM header
638     ldr         r12, [r3, #0x34]                // lr = r12 = ARM7 entry address
639     mov         lr, r12
640 
641     //---- Clear registers r0-r3
642     mov         r0, #0
643     mov         r1, #0
644     mov         r2, #0
645     mov         r3, #0
646 
647     //---- Boot game
648     bx          r12
649 }
650 #ifdef  SDK_TWL
651 #include <twl/wram_end.h>
652 #else
653 #include <nitro/wram_end.h>
654 #endif
655 #endif //ifdef SDK_ARM9
656 
657 
658 #ifdef SDK_ARM9
659 #ifdef  SDK_TWL
660 #include    <twl/itcm_begin.h>
661 #else
662 #include    <nitro/itcm_begin.h>
663 #endif
664 /*---------------------------------------------------------------------------*
665   Name:         OSi_CpuClear32
666 
667   Description:  Fills memory with specified data.
668                 32-bit version
669 
670   Arguments:    data: Fill data
671                 destp: Destination address
672                 size: Size (bytes)
673 
674   Returns:      None.
675  *---------------------------------------------------------------------------*/
OSi_CpuClear32(register u32 data,register void * destp,register u32 size)676 static asm void  OSi_CpuClear32( register u32 data, register void *destp, register u32 size )
677 {
678     add     r12, r1, r2             // r12: destEndp = destp + size
679 @1:
680     cmp     r1, r12                 // while (destp < destEndp)
681     stmltia r1!, {r0}               // *((vu32 *)(destp++)) = data
682     blt     @1
683     bx      lr
684 }
685 
686 /*---------------------------------------------------------------------------*
687   Name:         OSi_ReloadRomData
688 
689   Description:  Reloads ROM data from card.
690 
691   Arguments:    None.
692 
693   Returns:      None.
694  *---------------------------------------------------------------------------*/
OSi_ReloadRomData(BOOL ontwl)695 static asm void OSi_ReloadRomData(BOOL ontwl)
696 {
697     stmfd   sp!, {r4, lr}
698     mov     r4, r0
699 
700 #ifdef SDK_TWL
701 @shakeHand01:
702     cmp     r4, #0
703     beq     @shakeHand01_end
704     /* Synchronize with ARM7 */
705     ldr     r0, =HW_BOOT_SYNC_PHASE
706     mov     r1, #1
707     strh    r1, [r0]
708     ldr     r0, =HW_BOOT_SHAKEHAND_9
709     ldr     r1, =HW_BOOT_SHAKEHAND_7
710     ldrh    r2, [r1]
711     ldrh    r3, [r0]
712 @shakeHand01_loop:
713     add     r3, r3, #1
714     strh    r3, [r0]
715     ldrh    r12, [r1]
716     cmp     r2, r12
717     beq     @shakeHand01_loop
718     add     r3, r3, #1
719     strh    r3, [r0]
720 @shakeHand01_end:
721 #endif // SDK_TWL
722 
723     // If necessary, reload the ROM header. (Only when running in NTR mode.)
724     cmp     r4, #0
725     movne   r0, #0
726     ldreq   r0, =HW_ROM_BASE_OFFSET_BUF
727     ldreq   r0, [r0]
728     stmfd   sp!, {r0}
729     cmp     r0, #0x8000
730     ldrcs   r1, =HW_ROM_HEADER_BUF
731     movcs   r2, #0x160
732     blcs    OSi_ReadCardRom32
733 
734 @loadStatic:
735     /* Load the binary for the ARM9 */
736     ldr     r12, =HW_ROM_HEADER_BUF
737     ldr     r0, [r12, #0x20]
738     ldr     r1, [r12, #0x28]
739     ldr     r2, [r12, #0x2c]
740     ldr     r3, [sp]
741     add     r0, r0, r3
742     subs    r3, r0, #0x8000
743     movlt   r0, #0x8000
744     sublt   r1, r1, r3
745     addlt   r2, r2, r3
746     cmp     r2, #0
747     blgt    OSi_ReadCardRom32
748     /* Load the binary for the ARM7 */
749     ldr     r12, =HW_ROM_HEADER_BUF
750     ldr     r0, [r12, #0x30]
751     ldr     r1, [r12, #0x38]
752     ldr     r2, [r12, #0x3c]
753     ldr     r3, [sp]
754     add     r0, r0, r3
755     cmp     r2, #0
756     blgt    OSi_ReadCardRom32
757     ldmfd   sp!, {r0}
758 
759 #ifdef SDK_TWL
760 @loadLtdStatic:
761     cmp     r4, #0
762     beq     @loadLtdStatic_end
763     /* Load the extension binary for the ARM9 */
764     ldr     r12, =HW_TWL_ROM_HEADER_BUF
765     ldr     r0, [r12, #0x1c0]
766     ldr     r1, [r12, #0x1c8]
767     ldr     r2, [r12, #0x1cc]
768     add     r0, r0, #0x4000
769     add     r1, r1, #0x4000
770     sub     r2, r2, #0x4000
771     subs    r3, r0, #0x8000
772     movlt   r0, #0x8000
773     sublt   r1, r1, r3
774     addlt   r2, r2, r3
775     cmp     r2, #0
776     blgt    OSi_ReadCardRom32
777     /* Load the extension binary for the ARM7 */
778     ldr     r12, =HW_TWL_ROM_HEADER_BUF
779     ldr     r0, [r12, #0x1d0]
780     ldr     r1, [r12, #0x1d8]
781     ldr     r2, [r12, #0x1dc]
782     add     r0, r0, #0x4000
783     add     r1, r1, #0x4000
784     sub     r2, r2, #0x4000
785     subs    r3, r0, #0x8000
786     movlt   r0, #0x8000
787     sublt   r1, r1, r3
788     addlt   r2, r2, r3
789     cmp     r2, #0
790     blgt    OSi_ReadCardRom32
791 @loadLtdStatic_end:
792 #endif // SDK_TWL
793 
794     // Flush all caches
795 @arrangeCache:
796     /* DC_StoreAll() */
797     mov     r1, #0
798 @arrangeCache_loop01:
799     mov     r0, #0
800 @arrangeCache_loop02:
801     orr     r2, r1, r0
802     mcr     p15, 0, r2, c7, c10, 2
803     add     r0, r0, #HW_CACHE_LINE_SIZE
804     cmp     r0, #(HW_DCACHE_SIZE / 4)
805     blt     @arrangeCache_loop02
806     adds    r1, r1, #(1 << HW_C7_CACHE_SET_NO_SHIFT)
807     bne     @arrangeCache_loop01
808     /* DC_InvalidateAll() */
809     mov     r0, #0
810     mcr     p15, 0, r0, c7, c6, 0
811     /* IC_InvalidateAll() */
812 //  mov     r0, #0
813     mcr     p15, 0, r0, c7, c5, 0
814     /* DC_WaitWriteBufferEmpty() */
815 //  mov     r0, #0
816     mcr     p15, 0, r0, c7, c10, 4
817 
818 #ifdef SDK_TWL
819     cmp     r4, #0
820     beq     @shakeHand02_end
821     /* Synchronize with ARM7 */
822     /* It is necessary to recover the beginning portion of the extension binary that was retracted */
823     mov     r3, #2
824     ldr     r0, =HW_BOOT_SYNC_PHASE
825     strh    r3, [r0]
826     ldr     r0, =HW_BOOT_SHAKEHAND_9
827     ldr     r1, =HW_BOOT_SHAKEHAND_7
828     ldrh    r2, [r1]
829     ldrh    r3, [r0]
830 @shakeHand02_loop:
831     add     r3, r3, #1
832     strh    r3, [r0]
833     ldrh    r12, [r1]
834     cmp     r2, r12
835     beq     @shakeHand02_loop
836     add     r3, r3, #1
837     strh    r3, [r0]
838 @shakeHand02_end:
839 #endif // SDK_TWL
840 
841     ldmfd   sp!, {r4, pc}
842 //  bx      lr
843 }
844 
845 /*---------------------------------------------------------------------------*
846   Name:         OSi_ReadCardRom32
847 
848   Description:  Reads card data by CPU.
849                 (subroutine of OSi_ReloadRomData)
850 
851   Arguments:    src: Source address, needs to be 4-byte aligned
852                 dest: Destination address, needs to be 4-byte aligned
853                 len: Size of forwarding
854 
855   Returns:      None.
856  *---------------------------------------------------------------------------*/
OSi_ReadCardRom32(u32 src,void * dst,int len)857 static void OSi_ReadCardRom32(u32 src, void *dst, int len)
858 {
859     //---- I/O registers for CARD
860     vu8    *const reg_CARD_MASTERCNT = (vu8 *)(HW_REG_BASE + 0x1a1);
861     vu8    *const reg_CARD_CMD = (vu8 *)(HW_REG_BASE + 0x1a8);
862     vu32   *const reg_CARD_CNT = (vu32 *)(HW_REG_BASE + 0x1a4);
863     vu32   *const reg_CARD_DATA = (vu32 *)(HW_REG_BASE + 0x100010);
864     vu32   *const hdr_GAME_BUF = (vu32 *)(HW_ROM_HEADER_BUF + 0x60);
865 
866 
867     enum
868     {
869         CARD_MASTER_SELECT_ROM = 0x00,
870         CARD_MASTER_ENABLE = 0x80,
871         CARD_CMD_READ_PAGE = 0xb7,
872         CARD_CTRL_CMD_MASK = 0x07000000,
873         CARD_CTRL_CMD_PAGE = 0x01000000,
874         CARD_CTRL_READ = 0x00000000,
875         CARD_CTRL_RESET_HI = 0x20000000,
876         CARD_CTRL_START = 0x80000000,
877         CARD_CTRL_READY = 0x00800000,
878         CARD_ENUM_END
879     };
880 
881     const u32 ctrl_start = (u32)((*hdr_GAME_BUF & ~CARD_CTRL_CMD_MASK)
882                                  | (CARD_CTRL_CMD_PAGE | CARD_CTRL_READ
883                                     | CARD_CTRL_START | CARD_CTRL_RESET_HI));
884 
885     //---- Position of page, minus value mean before range
886     int     pos = -(int)(src & (512 - 1));
887 
888     //---- Wait finishing just to make sure, and turn master enable on
889     while ((*reg_CARD_CNT & CARD_CTRL_START) != 0)
890     {
891     }
892     *reg_CARD_MASTERCNT = (u32)(CARD_MASTER_SELECT_ROM | CARD_MASTER_ENABLE);
893 
894     for (src = (u32)(src + pos); pos < len; src += 512)
895     {
896         //---- Setting for command of one page reading
897         reg_CARD_CMD[0] = (u8)(CARD_CMD_READ_PAGE);
898         reg_CARD_CMD[1] = (u8)(src >> 24);
899         reg_CARD_CMD[2] = (u8)(src >> 16);
900         reg_CARD_CMD[3] = (u8)(src >> 8);
901         reg_CARD_CMD[4] = (u8)(src >> 0);
902         reg_CARD_CMD[5] = (u8)(0);
903         reg_CARD_CMD[6] = (u8)(0);
904         reg_CARD_CMD[7] = (u8)(0);
905 
906         //---- Start forwarding by CPU
907         *reg_CARD_CNT = ctrl_start;
908         for (;;)
909         {
910             u32     ctrl = *reg_CARD_CNT;
911 
912             //---- Check if OK to read word data
913             if ((ctrl & CARD_CTRL_READY) != 0)
914             {
915                 //---- Read data
916                 const u32 data = *reg_CARD_DATA;
917 
918                 //---- Store data
919                 if ((pos >= 0) && (pos < len))
920                 {
921                     *(u32 *)((u32)dst + pos) = data;
922                 }
923 
924                 pos += sizeof(u32);
925             }
926 
927             //---- Note: Need to read whole one page data
928             if (!(ctrl & CARD_CTRL_START))
929             {
930                 break;
931             }
932         }
933     }
934 }
935 
936 #ifdef  SDK_TWL
937 #include <twl/itcm_end.h>
938 #else
939 #include <nitro/itcm_end.h>
940 #endif
941 #endif //ifdef SDK_ARM9
942 
943 #ifdef  SDK_TWL
944 /*---------------------------------------------------------------------------*
945   Name:         OSi_ReloadTwlRomData
946 
947   Description:
948 
949   Arguments:    None.
950 
951   Returns:      None.
952  *---------------------------------------------------------------------------*/
953 #ifdef  SDK_ARM9
954 //---------------- ARM9
955 #else   // ifdef SDK_ARM9
956 //---------------- ARM7
957 #include <twl/ltdwram_begin.h>
958 static asm void
OSi_ReloadTwlRomData(void)959 OSi_ReloadTwlRomData(void)
960 {
961 @shakeHand01:
962     /* Synch with ARM9 */
963     ldr     r0, =HW_BOOT_SHAKEHAND_9
964     ldr     r1, =HW_BOOT_SHAKEHAND_7
965     ldrh    r2, [r0]
966     ldrh    r3, [r1]
967 @shakeHand01_loop:
968     add     r3, r3, #1
969     strh    r3, [r1]
970     ldrh    r12, [r0]
971     cmp     r2, r12
972     beq     @shakeHand01_loop
973     add     r3, r3, #1
974     strh    r3, [r1]
975 
976     ldr     r0, =HW_BOOT_SYNC_PHASE
977 @shakeHand01_waitLoop:
978     ldrh    r1, [r0]
979     cmp     r1, #3
980     beq     @shakeHand02
981     cmp     r1, #2
982     bne     @shakeHand01_waitLoop
983 
984 @restoreShelteredBinary:
985     ldr     r12, =HW_TWL_ROM_HEADER_BUF
986     /* Recover retracted data from the ARM7 extended binary */
987     ldr     r0, [r12, #0x1dc]
988     cmp     r0, #0
989     beq     @restoreNext
990     ldr     r2, [r12, #0x1d8]   // r2 = static module RAM address for ARM7
991     ldr     r0, =OSi_LtdMainParams
992     ldr     r3, [r0]            // r3 = end of src address
993     sub     r1, r3, #0x4000     // r1 = start of src address
994 @restoreLoop01:
995     ldr     r0, [r1], #4
996     str     r0, [r2], #4
997     cmp     r1, r3
998     blt     @restoreLoop01
999 
1000 @restoreNext:
1001     /* Recover retracted data of the extension binary for ARM9 */
1002     ldr     r0, [r12, #0x1cc]
1003     cmp     r0, #0
1004     beq     @shakeHand02
1005     ldr     r2, [r12, #0x1c8]   // r2 = static module RAM address for ARM9
1006     ldr     r0, =OSi_LtdMainParams
1007     ldr     r0, [r0]
1008     sub     r3, r0, #0x4000     // r3 = end of src address
1009     sub     r1, r3, #0x4000     // r1 = start of src address
1010 @restoreLoop02:
1011     ldr     r0, [r1], #4
1012     str     r0, [r2], #4
1013     cmp     r1, r3
1014     blt     @restoreLoop02
1015 
1016 @shakeHand02:
1017     /* Synch with ARM9 */
1018     ldr     r0, =HW_BOOT_SHAKEHAND_9
1019     ldr     r1, =HW_BOOT_SHAKEHAND_7
1020     ldrh    r2, [r0]
1021     ldrh    r3, [r1]
1022 @shakeHand02_loop:
1023     add     r3, r3, #1
1024     strh    r3, [r1]
1025     ldrh    r12, [r0]
1026     cmp     r2, r12
1027     beq     @shakeHand02_loop
1028     add     r3, r3, #1
1029     strh    r3, [r1]
1030 
1031     bx      lr
1032 }
1033 #include <twl/ltdwram_end.h>
1034 
1035 #endif  // ifdef SDK_ARM9
1036 #endif  // ifdef SDK_TWL
1037