1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - CARD - libraries
3 File: card_rom.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-01-13#$
14 $Rev: 9813 $
15 $Author: yosizaki $
16
17 *---------------------------------------------------------------------------*/
18
19
20 #include <nitro/card/rom.h>
21 #include <nitro/card/pullOut.h>
22 #include <nitro/card/rom.h>
23
24
25 #include "../include/card_common.h"
26 #include "../include/card_rom.h"
27
28
29 #if defined(SDK_ARM9) && defined(SDK_TWL)
30 #define CARD_USING_HASHCHECK
31 #endif // defined(SDK_ARM9) && defined(SDK_TWL)
32
33 #if defined(SDK_ARM9) || (defined(SDK_ARM7) && defined(SDK_ARM7_READROM_SUPPORT))
34 #define CARD_USING_ROMREADER
35 #endif // defined(SDK_ARM9) || (defined(SDK_ARM7) && defined(SDK_ARM7_READROM_SUPPORT))
36
37
38 /*---------------------------------------------------------------------------*/
39 /* Constants */
40
41 #define CARD_COMMAND_PAGE 0x01000000
42 #define CARD_COMMAND_ID 0x07000000
43 #define CARD_COMMAND_REFRESH 0x00000000
44 #define CARD_COMMAND_STAT CARD_COMMAND_ID
45 #define CARD_COMMAND_MASK 0x07000000
46 #define CARD_RESET_HI 0x20000000
47 #define CARD_COMMAND_OP_G_READID 0xB8
48 #define CARD_COMMAND_OP_G_READPAGE 0xB7
49 #define CARD_COMMAND_OP_G_READSTAT 0xD6
50 #define CARD_COMMAND_OP_G_REFRESH 0xB5
51 #ifdef SDK_TWL
52 #define CARD_COMMAND_OP_N_READID 0x90
53 #define CARD_COMMAND_OP_N_READPAGE 0x00
54 #define CARD_COMMAND_OP_N_READSTAT CARD_COMMAND_OP_G_READSTAT
55 #define CARD_COMMAND_OP_N_REFRESH CARD_COMMAND_OP_G_REFRESH
56 #endif
57
58 // ROM ID
59
60 #define CARD_ROMID_1TROM_MASK 0x80000000UL // 1T-ROM type
61 #define CARD_ROMID_TWLROM_MASK 0x40000000UL // TWL-ROM
62 #define CARD_ROMID_REFRESH_MASK 0x20000000UL // Refresh support
63
64 // ROM STATUS
65
66 #define CARD_ROMST_RFS_WARN_L1_MASK 0x00000004UL
67 #define CARD_ROMST_RFS_WARN_L2_MASK 0x00000008UL
68 #define CARD_ROMST_RFS_READY_MASK 0x00000020UL
69
70
71 /*---------------------------------------------------------------------------*/
72 /* Variables */
73
74 // Base offset during read. (Normally 0)
75 u32 cardi_rom_base;
76
77 // Other internal information
78 static int (*CARDiReadRomFunction) (void *userdata, void *buffer, u32 offset, u32 length);
79
80 static CARDTransferInfo CARDiDmaReadInfo[1];
81 static CARDTransferInfo *CARDiDmaReadRegisteredInfo;
82
83 static u32 cache_page = 1;
84 static u8 CARDi_cache_buf[CARD_ROM_PAGE_SIZE] ATTRIBUTE_ALIGN(32);
85 static BOOL CARDiEnableCacheInvalidationIC = FALSE;
86 static BOOL CARDiEnableCacheInvalidationDC = TRUE;
87
88 extern BOOL OSi_IsThreadInitialized;
89
90 static u8 CARDiOwnSignature[CARD_ROM_DOWNLOAD_SIGNATURE_SIZE] ATTRIBUTE_ALIGN(4);
91
92
93 /*---------------------------------------------------------------------------*/
94 /* functions */
95
96 void CARD_RefreshRom(void);
97
98 /*---------------------------------------------------------------------------*
99 Name: CARDi_SetRomOp
100
101 Description: Set the card command
102
103 Arguments: command: Command
104 offset: Transfer page count
105
106 Returns: None.
107 *---------------------------------------------------------------------------*/
CARDi_SetRomOp(u32 command,u32 offset)108 static void CARDi_SetRomOp(u32 command, u32 offset)
109 {
110 u32 cmd1 = (u32)((offset >> 8) | (command << 24));
111 u32 cmd2 = (u32)((offset << 24));
112 // Just in case, waiting for completion of prior ROM command
113 while ((reg_MI_MCCNT1 & REG_MI_MCCNT1_START_MASK) != 0)
114 {
115 }
116 // Master enable
117 reg_MI_MCCNT0 = (u16)(REG_MI_MCCNT0_E_MASK | REG_MI_MCCNT0_I_MASK |
118 (reg_MI_MCCNT0 & ~REG_MI_MCCNT0_SEL_MASK));
119 // Command settings
120 reg_MI_MCCMD0 = MI_HToBE32(cmd1);
121 reg_MI_MCCMD1 = MI_HToBE32(cmd2);
122 }
123
124 /*---------------------------------------------------------------------------*
125 Name: CARDi_GetRomFlag
126
127 Description: Gets card command control parameters.
128
129 Arguments: flag: Command type to issue to the card device
130 (CARD_COMMAND_PAGE / CARD_COMMAND_ID /
131 CARD_COMMAND_STAT / CARD_COMMAND_REFRESH)
132
133 Returns: Card command control parameters
134 *---------------------------------------------------------------------------*/
CARDi_GetRomFlag(u32 flag)135 SDK_INLINE u32 CARDi_GetRomFlag(u32 flag)
136 {
137 u32 rom_ctrl = *(vu32 *)(HW_CARD_ROM_HEADER + 0x60);
138 return (u32)(flag | REG_MI_MCCNT1_START_MASK | CARD_RESET_HI | (rom_ctrl & ~CARD_COMMAND_MASK));
139 }
140
141 /*---------------------------------------------------------------------------*
142 Name: CARDi_IsTwlRom
143
144 Description: Determines whether game card is installed with ROM that supports TWL.
145 Returns TRUE when ROM is installed that supports TWL even for a NITRO Application.
146
147 Arguments: None.
148
149 Returns: If ROM supports TWL, return TRUE
150 *---------------------------------------------------------------------------*/
CARDi_IsTwlRom(void)151 BOOL CARDi_IsTwlRom(void)
152 {
153 u32 iplCardID = *(u32 *)(HW_BOOT_CHECK_INFO_BUF);
154
155 // If there is no card when starting up, always return FALSE
156 if ( ! iplCardID )
157 {
158 return FALSE;
159 }
160
161 return (CARDi_ReadRomID() & CARD_ROMID_TWLROM_MASK) ? TRUE : FALSE;
162 }
163
164 #ifdef SDK_TWL
165
166 /*---------------------------------------------------------------------------*
167 Name: CARDi_IsNormalMode
168
169 Description: Determines whether game card is in NORMAL mode.
170
171 Arguments: None.
172
173 Returns: If game card is in NORMAL mode, returns TRUE.
174 *---------------------------------------------------------------------------*/
CARDi_IsNormalMode(void)175 static BOOL CARDi_IsNormalMode(void)
176 {
177 const CARDRomHeader *ch = (void*)CARD_GetRomHeader();
178 const CARDRomHeaderTWL *oh = CARD_GetOwnRomHeaderTWL();
179
180 return OS_IsRunOnTwl() &&
181 (OS_GetBootType() != OS_BOOTTYPE_ROM) &&
182 oh->access_control.game_card_on &&
183 ! oh->access_control.game_card_nitro_mode;
184 }
185
186 #endif
187
188 /*---------------------------------------------------------------------------*
189 Name: CARDi_StartRomPageTransfer
190
191 Description: Starts ROM page transfers
192
193 Arguments: offset: ROM offset of transfer source
194
195 Returns: None.
196 *---------------------------------------------------------------------------*/
CARDi_StartRomPageTransfer(u32 offset)197 static void CARDi_StartRomPageTransfer(u32 offset)
198 {
199 u8 op = CARD_COMMAND_OP_G_READPAGE;
200 #ifdef SDK_TWL
201 if ( CARDi_IsNormalMode() )
202 {
203 op = CARD_COMMAND_OP_N_READPAGE;
204 }
205 #endif
206
207 CARDi_SetRomOp(op, offset);
208 reg_MI_MCCNT1 = CARDi_GetRomFlag(CARD_COMMAND_PAGE);
209 }
210
211 /*---------------------------------------------------------------------------*
212 Name: CARDi_ReadRomIDCore
213
214 Description: Reads the card ID.
215
216 Arguments: None.
217
218 Returns: Card ID
219 *---------------------------------------------------------------------------*/
CARDi_ReadRomIDCore(void)220 u32 CARDi_ReadRomIDCore(void)
221 {
222 u8 op = CARD_COMMAND_OP_G_READID;
223 #ifdef SDK_TWL
224 if ( CARDi_IsNormalMode() )
225 {
226 op = CARD_COMMAND_OP_N_READID;
227 }
228 #endif
229
230 CARDi_SetRomOp(op, 0);
231 reg_MI_MCCNT1 = (u32)(CARDi_GetRomFlag(CARD_COMMAND_ID) & ~REG_MI_MCCNT1_L1_MASK);
232 while ((reg_MI_MCCNT1 & REG_MI_MCCNT1_RDY_MASK) == 0)
233 {
234 }
235 return reg_MI_MCD1;
236 }
237
238 /*---------------------------------------------------------------------------*
239 Name: CARDi_ReadRomStatusCore
240
241 Description: Reads the card status.
242 Issue only when detecting ROM that supports refresh.
243 Required even for NITRO applications installed with supporting ROM.
244
245 Arguments: None.
246
247 Returns: Card status.
248 *---------------------------------------------------------------------------*/
CARDi_ReadRomStatusCore(void)249 u32 CARDi_ReadRomStatusCore(void)
250 {
251 u32 iplCardID = *(u32 *)(HW_BOOT_CHECK_INFO_BUF);
252
253 if ( ! (iplCardID & CARD_ROMID_REFRESH_MASK) )
254 {
255 return CARD_ROMST_RFS_READY_MASK;
256 }
257
258 CARDi_SetRomOp(CARD_COMMAND_OP_G_READSTAT, 0);
259 reg_MI_MCCNT1 = (u32)(CARDi_GetRomFlag(CARD_COMMAND_STAT) & ~REG_MI_MCCNT1_L1_MASK);
260 while ((reg_MI_MCCNT1 & REG_MI_MCCNT1_RDY_MASK) == 0)
261 {
262 }
263 return reg_MI_MCD1;
264 }
265
266 /*---------------------------------------------------------------------------*
267 Name: CARD_RefreshRom
268
269 Description: Refreshes bad blocks on card ROM.
270 Issue only when detecting ROM that supports refresh.
271 Required even for NITRO applications installed with this ROM.
272 In extremely rare cases even in the CARD_ReadRom function, when a state is entered that is close to when ECC correction is ineffective, a forced refresh occurs. However, because there is the possibility of the refresh process lasting up to approximately 50 ms, call this function periodically at safe timings for the application even if a delay is entered.
273
274
275
276
277 Arguments: None.
278
279 Returns: None.
280 *---------------------------------------------------------------------------*/
CARD_RefreshRom(void)281 void CARD_RefreshRom(void)
282 {
283 SDK_ASSERT(CARD_IsAvailable());
284 SDK_ASSERTMSG(CARDi_GetTargetMode() == CARD_TARGET_ROM, "must be locked by CARD_LockRom()");
285
286 #if defined(SDK_ARM9)
287 (void)CARDi_WaitForTask(&cardi_common, TRUE, NULL, NULL);
288 // Detect card removal here
289 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
290 #endif // defined(SDK_ARM9)
291
292 CARDi_RefreshRom(CARD_ROMST_RFS_WARN_L1_MASK | CARD_ROMST_RFS_WARN_L2_MASK);
293
294 #if defined(SDK_ARM9)
295 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
296 CARDi_EndTask(&cardi_common);
297 #endif // defined(SDK_ARM9)
298 }
299
300 /*---------------------------------------------------------------------------*
301 Name: CARDi_RefreshRom
302
303 Description: Refreshes bad blocks on card ROM.
304 Issue only when detecting ROM that supports refresh.
305 Required even for NITRO applications installed with this ROM.
306
307 Arguments: warn_mask: Warning level specification
308
309 Returns: None.
310 *---------------------------------------------------------------------------*/
CARDi_RefreshRom(u32 warn_mask)311 void CARDi_RefreshRom(u32 warn_mask)
312 {
313 if (CARDi_ReadRomStatusCore() & warn_mask)
314 {
315 CARDi_RefreshRomCore();
316 // There is the possibility that completion of the refresh can take more than 100 ms
317 while ( !(CARDi_ReadRomStatusCore() & CARD_ROMST_RFS_READY_MASK) )
318 {
319 // If that is possible, sleep
320 if ( OSi_IsThreadInitialized &&
321 OS_IsAlarmAvailable() )
322 {
323 OS_Sleep(1);
324 }
325 }
326 }
327 }
328
329 /*---------------------------------------------------------------------------*
330 Name: CARDi_RefreshRomCore
331
332 Description: Refreshes bad blocks on card ROM.
333 Required even for NITRO applications installed with this ROM.
334 Latency settings are invalid because the command is issued unilaterally to the card.
335
336 Arguments: None.
337
338 Returns: None.
339 *---------------------------------------------------------------------------*/
CARDi_RefreshRomCore(void)340 void CARDi_RefreshRomCore(void)
341 {
342 CARDi_SetRomOp(CARD_COMMAND_OP_G_REFRESH, 0);
343 reg_MI_MCCNT1 = (u32)(CARDi_GetRomFlag(CARD_COMMAND_REFRESH) & ~REG_MI_MCCNT1_L1_MASK);
344 while (reg_MI_MCCNT1 & REG_MI_MCCNT1_START_MASK)
345 {
346 }
347 }
348
349 /*---------------------------------------------------------------------------*
350 Name: CARDi_ReadRomWithCPU
351
352 Description: Transfers ROM using the CPU.
353 There is no need to consider restrictions of the cache or page units, but not that the function is blocked until the transfer is completed.
354
355
356 Arguments: userdata: (Dummy to use as the other callback)
357 buffer: Transfer destination buffer
358 offset: Transfer source ROM offset
359 length: Transfer size
360
361 Returns: None.
362 *---------------------------------------------------------------------------*/
CARDi_ReadRomWithCPU(void * userdata,void * buffer,u32 offset,u32 length)363 int CARDi_ReadRomWithCPU(void *userdata, void *buffer, u32 offset, u32 length)
364 {
365 int retval = (int)length;
366 // Cache the global variables frequently used to the local variables
367 u32 cachedPage = cache_page;
368 u8 * const cacheBuffer = CARDi_cache_buf;
369 while (length > 0)
370 {
371 // ROM transfer is always in page units
372 u8 *ptr = (u8 *)buffer;
373 u32 n = CARD_ROM_PAGE_SIZE;
374 u32 pos = MATH_ROUNDDOWN(offset, CARD_ROM_PAGE_SIZE);
375 // Use the cache if the same as the previous page
376 if (pos == cachedPage)
377 {
378 ptr = cacheBuffer;
379 }
380 else
381 {
382 // Transfer to cache if not possible to transfer directly to the buffer
383 if(((pos != offset) || (((u32)buffer & 3) != 0) || (length < n)))
384 {
385 cachedPage = pos;
386 ptr = cacheBuffer;
387 }
388 // Read directly to the buffer guaranteed with 4-byte alignment using the CPU
389 CARDi_StartRomPageTransfer(pos);
390 {
391 u32 word = 0;
392 for (;;)
393 {
394 // Wait for one word transfer to be completed
395 u32 ctrl = reg_MI_MCCNT1;
396 if ((ctrl & REG_MI_MCCNT1_RDY_MASK) != 0)
397 {
398 // Read data and store in buffer if necessary
399 u32 data = reg_MI_MCD1;
400 if (word < (CARD_ROM_PAGE_SIZE / sizeof(u32)))
401 {
402 ((u32 *)ptr)[word++] = data;
403 }
404 }
405 // End if 1 page transfer is completed
406 if ((ctrl & REG_MI_MCCNT1_START_MASK) == 0)
407 {
408 break;
409 }
410 }
411 }
412 }
413 // Transfer from cache if via cache
414 if (ptr == cacheBuffer)
415 {
416 u32 mod = offset - pos;
417 n = MATH_MIN(length, CARD_ROM_PAGE_SIZE - mod);
418 MI_CpuCopy8(cacheBuffer + mod, buffer, n);
419 }
420 buffer = (u8 *)buffer + n;
421 offset += n;
422 length -= n;
423 }
424 // If local variables, apply to global variables
425 cache_page = cachedPage;
426 (void)userdata;
427 return retval;
428 }
429
430 #if defined(CARD_USING_ROMREADER)
431 /*---------------------------------------------------------------------------*
432 Name: CARDi_DmaReadPageCallback
433
434 Description: Callback when ROM page DMA transfer is completed.
435
436 Arguments: None.
437
438 Returns: None.
439 *---------------------------------------------------------------------------*/
CARDi_DmaReadPageCallback(void)440 static void CARDi_DmaReadPageCallback(void)
441 {
442 CARDTransferInfo *info = CARDiDmaReadRegisteredInfo;
443 if (info)
444 {
445 info->src += CARD_ROM_PAGE_SIZE;
446 info->dst += CARD_ROM_PAGE_SIZE;
447 info->len -= CARD_ROM_PAGE_SIZE;
448 // Transfer the next page if necessary
449 if (info->len > 0)
450 {
451 CARDi_StartRomPageTransfer(info->src);
452 }
453 // Transfer completed
454 else
455 {
456 cardi_common.DmaCall->Stop(cardi_common.dma);
457 (void)OS_DisableIrqMask(OS_IE_CARD_DATA);
458 (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA);
459 CARDiDmaReadRegisteredInfo = NULL;
460 if (info->callback)
461 {
462 (*info->callback)(info->userdata);
463 }
464 }
465 }
466 }
467
468 /*---------------------------------------------------------------------------*
469 Name: CARDi_ReadRomWithDMA
470
471 Description: Transfers ROM using the DMA.
472 After transfer of the first page starts, the function returns control immediately.
473
474 Arguments: info: Transfer information
475
476 Returns: None.
477 *---------------------------------------------------------------------------*/
CARDi_ReadRomWithDMA(CARDTransferInfo * info)478 void CARDi_ReadRomWithDMA(CARDTransferInfo *info)
479 {
480 OSIntrMode bak_psr = OS_DisableInterrupts();
481 CARDiDmaReadRegisteredInfo = info;
482 // Set card transfer completion interrupt
483 (void)OS_SetIrqFunction(OS_IE_CARD_DATA, CARDi_DmaReadPageCallback);
484 (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA);
485 (void)OS_EnableIrqMask(OS_IE_CARD_DATA);
486 (void)OS_RestoreInterrupts(bak_psr);
487 // Set CARD-DMA (transfer idling)
488 cardi_common.DmaCall->Recv(cardi_common.dma, (void *)®_MI_MCD1, (void *)info->dst, CARD_ROM_PAGE_SIZE);
489 // Start first ROM transfer
490 CARDi_StartRomPageTransfer(info->src);
491 }
492
CARDi_DmaReadDone(void * userdata)493 static void CARDi_DmaReadDone(void *userdata)
494 {
495 (void)userdata;
496 #ifdef SDK_ARM9
497 // Determine whether card was removed while accessed
498 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
499 #endif
500 // Refresh at final warning stage of ROM-ECC correction
501 CARDi_RefreshRom(CARD_ROMST_RFS_WARN_L2_MASK);
502
503 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
504 CARDi_EndTask(&cardi_common);
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: CARDi_IsRomDmaAvailable
509
510 Description: Determines whether asynchronous DMA is usable in ROM transfer.
511
512 Arguments: dma: DMA channel
513 dst: Transfer destination buffer
514 src: Transfer source ROM offset
515 len: Transfer size
516
517 Returns: If DMA is usable in ROM transfer, return TRUE.
518 *---------------------------------------------------------------------------*/
CARDi_IsRomDmaAvailable(u32 dma,void * dst,u32 src,u32 len)519 static BOOL CARDi_IsRomDmaAvailable(u32 dma, void *dst, u32 src, u32 len)
520 {
521 return (dma <= MI_DMA_MAX_NUM) && (len > 0) && (((u32)dst & 31) == 0) &&
522 #ifdef SDK_ARM9
523 (((u32)dst + len <= OS_GetITCMAddress()) || ((u32)dst >= OS_GetITCMAddress() + HW_ITCM_SIZE)) &&
524 (((u32)dst + len <= OS_GetDTCMAddress()) || ((u32)dst >= OS_GetDTCMAddress() + HW_DTCM_SIZE)) &&
525 #endif
526 (((src | len) & (CARD_ROM_PAGE_SIZE - 1)) == 0);
527 }
528
529 /*---------------------------------------------------------------------------*
530 Name: CARDi_ReadRomSyncCore
531
532 Description: Common process for synchronous card reads.
533
534 Arguments: c: CARDiCommon structure
535
536 Returns: None.
537 *---------------------------------------------------------------------------*/
CARDi_ReadRomSyncCore(CARDiCommon * c)538 static void CARDi_ReadRomSyncCore(CARDiCommon *c)
539 {
540 // Run ROM access routine that corresponds to the execution environment
541 (void)(*CARDiReadRomFunction)(NULL, (void*)c->dst, c->src, c->len);
542 #ifdef SDK_ARM9
543 // Determine whether card was removed while accessed
544 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
545 #endif
546 // Refresh at final warning stage of ROM-ECC correction
547 CARDi_RefreshRom(CARD_ROMST_RFS_WARN_L2_MASK);
548
549 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
550 }
551 #endif // defined(CARD_USING_ROMREADER)
552
553 /*---------------------------------------------------------------------------*
554 Name: CARDi_ReadRom
555
556 Description: Basic function of ROM read
557
558 Arguments: dma: DMA channel to use
559 src: Transfer source offset
560 dst: Transfer destination memory address
561 len: Transfer size
562 callback: Completion callback (NULL if not used)
563 arg: Argument of completion callback (ignored if not used)
564 is_async: If set to asynchronous mode, TRUE
565
566 Returns: None.
567 *---------------------------------------------------------------------------*/
CARDi_ReadRom(u32 dma,const void * src,void * dst,u32 len,MIDmaCallback callback,void * arg,BOOL is_async)568 void CARDi_ReadRom(u32 dma,
569 const void *src, void *dst, u32 len,
570 MIDmaCallback callback, void *arg, BOOL is_async)
571 {
572 #if defined(CARD_USING_ROMREADER)
573 CARDiCommon *const c = &cardi_common;
574
575 SDK_ASSERT(CARD_IsAvailable());
576 SDK_ASSERT(CARDi_GetTargetMode() == CARD_TARGET_ROM);
577 SDK_ASSERTMSG((dma != 0), "cannot specify DMA channel 0");
578
579 // Determine validity of card access
580 CARD_CheckEnabled();
581 if ((CARDi_GetAccessLevel() & CARD_ACCESS_LEVEL_ROM) == 0)
582 {
583 OS_TPanic("this program cannot access CARD-ROM!");
584 }
585
586 // Exclusive wait on ARM9 side
587 (void)CARDi_WaitForTask(c, TRUE, callback, arg);
588
589 // Get DMA interface
590 c->DmaCall = CARDi_GetDmaInterface(dma);
591 c->dma = (u32)((c->DmaCall != NULL) ? (dma & MI_DMA_CHANNEL_MASK) : MI_DMA_NOT_USE);
592 if (c->dma <= MI_DMA_MAX_NUM)
593 {
594 c->DmaCall->Stop(c->dma);
595 }
596
597 // Set this time's transfer parameters
598 c->src = (u32)((u32)src + cardi_rom_base);
599 c->dst = (u32)dst;
600 c->len = (u32)len;
601
602 // Set transfer parameter
603 {
604 CARDTransferInfo *info = CARDiDmaReadInfo;
605 info->callback = CARDi_DmaReadDone;
606 info->userdata = NULL;
607 info->src = c->src;
608 info->dst = c->dst;
609 info->len = c->len;
610 info->work = 0;
611 }
612
613 // DMA transfers can be used in some cases, if it is an environment where hash checks are invalid
614 if ((CARDiReadRomFunction == CARDi_ReadRomWithCPU) &&
615 CARDi_IsRomDmaAvailable(c->dma, (void *)c->dst, c->src, c->len))
616 {
617 #if defined(SDK_ARM9)
618 // Depending upon the size of the transfer range, switch the manner in which the cache is invalidated
619 OSIntrMode bak_psr = OS_DisableInterrupts();
620 if (CARDiEnableCacheInvalidationIC)
621 {
622 CARDi_ICInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_ic);
623 }
624 if (CARDiEnableCacheInvalidationDC)
625 {
626 CARDi_DCInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_dc);
627 }
628 (void)OS_RestoreInterrupts(bak_psr);
629 #endif
630 // Start asynchronous transfer using DMA
631 CARDi_ReadRomWithDMA(CARDiDmaReadInfo);
632 // Wait until complete here if synchronous transfer is requested
633 if (!is_async)
634 {
635 CARD_WaitRomAsync();
636 }
637 }
638 else
639 {
640 // Even with CPU transfers, it is necessary to invalidate because the instruction cache is incompatible
641 if (CARDiEnableCacheInvalidationIC)
642 {
643 CARDi_ICInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_ic);
644 }
645 // Register task to thread if some form of direct processing is required by the CPU
646 (void)CARDi_ExecuteOldTypeTask(CARDi_ReadRomSyncCore, is_async);
647 }
648 #else
649 (void)dma;
650 (void)is_async;
651 (void)CARDi_ReadRomWithCPU(NULL, dst, (u32)src, len);
652 if (callback)
653 {
654 (*callback)(arg);
655 }
656 #endif // defined(CARD_USING_ROMREADER)
657 }
658
659 /*---------------------------------------------------------------------------*
660 Name: CARDi_ReadRomID
661
662 Description: Reads the card ID.
663
664 Arguments: None.
665
666 Returns: Card ID.
667 *---------------------------------------------------------------------------*/
CARDi_ReadRomID(void)668 u32 CARDi_ReadRomID(void)
669 {
670 u32 ret = 0;
671
672 SDK_ASSERT(CARD_IsAvailable());
673 SDK_ASSERTMSG(CARDi_GetTargetMode() == CARD_TARGET_ROM, "must be locked by CARD_LockRom()");
674
675 #if defined(SDK_ARM9)
676 (void)CARDi_WaitForTask(&cardi_common, TRUE, NULL, NULL);
677 #endif // defined(SDK_ARM9)
678
679 /* Direct access is possible, so execute here */
680 ret = CARDi_ReadRomIDCore();
681 #ifdef SDK_ARM9
682 // Detect card removal here
683 CARDi_CheckPulledOutCore(ret);
684 #endif
685
686 #if defined(SDK_ARM9)
687 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
688 CARDi_EndTask(&cardi_common);
689 #endif // defined(SDK_ARM9)
690
691 return ret;
692 }
693
694 #if defined(CARD_USING_HASHCHECK)
695 #include <twl/ltdmain_begin.h>
696
697 // ROM hash calculation buffer
698 u8 *CARDiHashBufferAddress = NULL;
699 u32 CARDiHashBufferLength = 0;
700 static CARDRomHashContext context[1];
701
702 /*---------------------------------------------------------------------------*
703 Name: CARDi_ReadCardWithHash
704
705 Description: ROM transfer while confirming hash.
706
707 Arguments: buffer: Transfer destination buffer
708 offset: Transfer source ROM offset
709 length: Transfer size
710
711 Returns: None.
712 *---------------------------------------------------------------------------*/
CARDi_ReadCardWithHash(void * userdata,void * buffer,u32 offset,u32 length)713 static int CARDi_ReadCardWithHash(void *userdata, void *buffer, u32 offset, u32 length)
714 {
715 (void)userdata;
716 CARD_ReadRomHashImage(context, buffer, offset, length);
717 return (int)length;
718 }
719
720 /*---------------------------------------------------------------------------*
721 Name: CARDi_ReadCardWithHashInternalAsync
722
723 Description: Asynchronous DMA transfer for partial use internally with ROM transfers of the hash verified version.
724
725 Arguments: userdata: User-defined argument
726 buffer: Transfer destination buffer
727 offset: Transfer source ROM offset
728 length: Transfer size
729
730 Returns: None.
731 *---------------------------------------------------------------------------*/
CARDi_ReadCardWithHashInternalAsync(void * userdata,void * buffer,u32 offset,u32 length)732 static int CARDi_ReadCardWithHashInternalAsync(void *userdata, void *buffer, u32 offset, u32 length)
733 {
734 if (cardi_common.dma == MI_DMA_NOT_USE)
735 {
736 length = 0;
737 }
738 else
739 {
740 CARDRomHashContext *context = (CARDRomHashContext *)userdata;
741 static CARDTransferInfo card_hash_info[1];
742 DC_FlushRange(buffer, length);
743 card_hash_info->callback = (void(*)(void*))CARD_NotifyRomHashReadAsync;
744 card_hash_info->userdata = context;
745 card_hash_info->src = offset;
746 card_hash_info->dst = (u32)buffer;
747 card_hash_info->len = length;
748 card_hash_info->command = 0;
749 card_hash_info->work = 0;
750 CARDi_ReadRomWithDMA(card_hash_info);
751 }
752 return (int)length;
753 }
754
755 /*---------------------------------------------------------------------------*
756 Name: CARDi_InitRomHash
757
758 Description: If possible, switches to hash verification version ROM transfer.
759
760 Arguments: None.
761
762 Returns: None.
763 *---------------------------------------------------------------------------*/
CARDi_InitRomHash(void)764 static void CARDi_InitRomHash(void)
765 {
766 // Because applications will often consume everything before it is necessary to call a function such as FS_Init, always allocate the buffer for hash context.
767 //
768 //
769 u8 *lo = (u8 *)MATH_ROUNDUP((u32)OS_GetMainArenaLo(), 32);
770 u8 *hi = (u8 *)MATH_ROUNDDOWN((u32)OS_GetMainArenaHi(), 32);
771 u32 len = CARD_CalcRomHashBufferLength(CARD_GetOwnRomHeaderTWL());
772 if (&lo[len] > hi)
773 {
774 OS_TPanic("cannot allocate memory for ROM-hash from ARENA");
775 }
776 else
777 {
778 OS_SetMainArenaLo(&lo[len]);
779 CARDiHashBufferAddress = lo;
780 CARDiHashBufferLength = len;
781 // Actually load if it is an environment where the ROM boot and hash table exist.
782 if ((OS_GetBootType() == OS_BOOTTYPE_ROM) &&
783 ((((const u8 *)HW_TWL_ROM_HEADER_BUF)[0x1C] & 0x01) != 0))
784 {
785 cardi_common.dma = MI_DMA_NOT_USE;
786 CARDiReadRomFunction = CARDi_ReadCardWithHash;
787 {
788 u16 id = (u16)OS_GetLockID();
789 CARD_LockRom(id);
790 CARD_InitRomHashContext(context,
791 CARD_GetOwnRomHeaderTWL(),
792 CARDiHashBufferAddress,
793 CARDiHashBufferLength,
794 CARDi_ReadRomWithCPU,
795 CARDi_ReadCardWithHashInternalAsync,
796 context);
797 // Destroy the pointer so that there is no competition for use of the same buffer
798 CARDiHashBufferAddress = NULL;
799 CARDiHashBufferLength = 0;
800 CARD_UnlockRom(id);
801 OS_ReleaseLockID(id);
802 }
803 }
804 }
805 }
806 #include <twl/ltdmain_end.h>
807 #endif
808
809 /*---------------------------------------------------------------------------*
810 Name: CARDi_InitRom
811
812 Description: Initializes the ROM access management information.
813
814 Arguments: None.
815
816 Returns: None.
817 *---------------------------------------------------------------------------*/
CARDi_InitRom(void)818 void CARDi_InitRom(void)
819 {
820 #if defined(CARD_USING_ROMREADER)
821 CARDiReadRomFunction = CARDi_ReadRomWithCPU;
822 // In the TWL-SDK, hash verification is implemented in ROM data access, but because signature data of the DS Download Play is embedded after hash calculations, inadvertent reading by the CARD_ReadRom function thereafter is prohibited and it is necessary to explicitly reference using the CARDi_GetOwnSignature function.
823 //
824 //
825 //
826 if ((OS_GetBootType() == OS_BOOTTYPE_ROM) && CARD_GetOwnRomHeader()->rom_size)
827 {
828 u16 id = (u16)OS_GetLockID();
829 CARD_LockRom(id);
830 (void)CARDi_ReadRomWithCPU(NULL, CARDiOwnSignature,
831 CARD_GetOwnRomHeader()->rom_size,
832 CARD_ROM_DOWNLOAD_SIGNATURE_SIZE);
833 CARD_UnlockRom(id);
834 OS_ReleaseLockID(id);
835 }
836 #if defined(CARD_USING_HASHCHECK)
837 // Adopts a routine that also verifies hash, if usable
838 if (OS_IsRunOnTwl())
839 {
840 CARDi_InitRomHash();
841 }
842 #endif
843 #else
844 CARDiReadRomFunction = NULL;
845 #endif
846 }
847
848
849 /*---------------------------------------------------------------------------*
850 Name: CARD_WaitRomAsync
851
852 Description: Idles until the ROM access function is completed.
853
854 Arguments: None.
855
856 Returns: None.
857 *---------------------------------------------------------------------------*/
CARD_WaitRomAsync(void)858 void CARD_WaitRomAsync(void)
859 {
860 (void)CARDi_WaitAsync();
861 }
862
863 /*---------------------------------------------------------------------------*
864 Name: CARD_TryWaitRomAsync
865
866 Description: Determines whether the ROM access function is completed.
867
868 Arguments: None.
869
870 Returns: TRUE when the ROM access function is completed.
871 *---------------------------------------------------------------------------*/
CARD_TryWaitRomAsync(void)872 BOOL CARD_TryWaitRomAsync(void)
873 {
874 return CARDi_TryWaitAsync();
875 }
876
877 /*---------------------------------------------------------------------------*
878 Name: CARDi_GetOwnSignature
879
880 Description: Gets its own DS Download Play signature data.
881
882 Arguments: None.
883
884 Returns: Its own DS Download Play signature data
885 *---------------------------------------------------------------------------*/
CARDi_GetOwnSignature(void)886 const u8* CARDi_GetOwnSignature(void)
887 {
888 return CARDiOwnSignature;
889 }
890
891 /*---------------------------------------------------------------------------*
892 Name: CARDi_SetOwnSignature
893
894 Description: Sets its own DS Download Play signature data.
895 Calls from the host library when booted without a card.
896
897 Arguments: DS Download Play signature data
898
899 Returns: None.
900 *---------------------------------------------------------------------------*/
CARDi_SetOwnSignature(const void * signature)901 void CARDi_SetOwnSignature(const void *signature)
902 {
903 MI_CpuCopy8(signature, CARDiOwnSignature, CARD_ROM_DOWNLOAD_SIGNATURE_SIZE);
904 }
905
906 #if defined(SDK_ARM9)
907 /*---------------------------------------------------------------------------*
908 Name: CARD_GetCacheFlushFlag
909
910 Description: Gets setting flags of whether to invalidate cache automatically.
911
912 Arguments: icache: Pointer to the location where the automatic invalidation flag for the instruction cache is stored
913 Ignore if NULL.
914 dcache: Pointer to the location the automatic invalidation flag for the instruction cache is stored.
915 Ignore if NULL.
916
917 Returns: None.
918 *---------------------------------------------------------------------------*/
CARD_GetCacheFlushFlag(BOOL * icache,BOOL * dcache)919 void CARD_GetCacheFlushFlag(BOOL *icache, BOOL *dcache)
920 {
921 SDK_ASSERT(CARD_IsAvailable());
922 if (icache)
923 {
924 *icache = CARDiEnableCacheInvalidationIC;
925 }
926 if (dcache)
927 {
928 *dcache = CARDiEnableCacheInvalidationDC;
929 }
930 }
931
932 /*---------------------------------------------------------------------------*
933 Name: CARD_SetCacheFlushFlag
934
935 Description: Sets whether to automatically invalidate cache.
936 By default, instruction cache is FALSE, and data cache is TRUE.
937
938 Arguments: icache: TRUE to enable automatic invalidation of the instruction cache
939 dcache: TRUE to enable automatic invalidation of data caches
940
941 Returns: None.
942 *---------------------------------------------------------------------------*/
CARD_SetCacheFlushFlag(BOOL icache,BOOL dcache)943 void CARD_SetCacheFlushFlag(BOOL icache, BOOL dcache)
944 {
945 SDK_ASSERT(CARD_IsAvailable());
946 CARDiEnableCacheInvalidationIC = icache;
947 CARDiEnableCacheInvalidationDC = dcache;
948 }
949 #endif
950