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