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