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