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