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