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-06-04#$
14 $Rev: 10698 $
15 $Author: okubata_ryoma $
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 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 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.
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 cache or page unit restrictions, but note that the function will block until the transfer is complete.
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 // Determine whether card was removed while accessed
425 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
426 // If local variables, apply to global variables
427 cache_page = cachedPage;
428 (void)userdata;
429 return retval;
430 }
431
432 #if defined(CARD_USING_ROMREADER)
433 /*---------------------------------------------------------------------------*
434 Name: CARDi_DmaReadPageCallback
435
436 Description: Callback when ROM page DMA transfer is completed.
437
438 Arguments: None.
439
440 Returns: None.
441 *---------------------------------------------------------------------------*/
CARDi_DmaReadPageCallback(void)442 static void CARDi_DmaReadPageCallback(void)
443 {
444 CARDTransferInfo *info = CARDiDmaReadRegisteredInfo;
445 if (info)
446 {
447 info->src += CARD_ROM_PAGE_SIZE;
448 info->dst += CARD_ROM_PAGE_SIZE;
449 info->len -= CARD_ROM_PAGE_SIZE;
450 // Transfer the next page if necessary
451 if (info->len > 0)
452 {
453 CARDi_StartRomPageTransfer(info->src);
454 }
455 // Transfer completed
456 else
457 {
458 cardi_common.DmaCall->Stop(cardi_common.dma);
459 (void)OS_DisableIrqMask(OS_IE_CARD_DATA);
460 (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA);
461 CARDiDmaReadRegisteredInfo = NULL;
462 // Determine whether card was removed while accessed
463 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
464 if (info->callback)
465 {
466 (*info->callback)(info->userdata);
467 }
468 }
469 }
470 }
471
472 /*---------------------------------------------------------------------------*
473 Name: CARDi_ReadRomWithDMA
474
475 Description: Transfers ROM using the DMA.
476 After transfer of the first page starts, the function returns control immediately.
477
478 Arguments: info: Transfer information
479
480 Returns: None.
481 *---------------------------------------------------------------------------*/
CARDi_ReadRomWithDMA(CARDTransferInfo * info)482 void CARDi_ReadRomWithDMA(CARDTransferInfo *info)
483 {
484 OSIntrMode bak_psr = OS_DisableInterrupts();
485 CARDiDmaReadRegisteredInfo = info;
486 // Set card transfer completion interrupt
487 (void)OS_SetIrqFunction(OS_IE_CARD_DATA, CARDi_DmaReadPageCallback);
488 (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA);
489 (void)OS_EnableIrqMask(OS_IE_CARD_DATA);
490 (void)OS_RestoreInterrupts(bak_psr);
491 // Set CARD-DMA (transfer idling)
492 cardi_common.DmaCall->Recv(cardi_common.dma, (void *)®_MI_MCD1, (void *)info->dst, CARD_ROM_PAGE_SIZE);
493 // Start first ROM transfer
494 CARDi_StartRomPageTransfer(info->src);
495 }
496
CARDi_DmaReadDone(void * userdata)497 static void CARDi_DmaReadDone(void *userdata)
498 {
499 (void)userdata;
500 #ifdef SDK_ARM9
501 // Determine whether card was removed while accessed
502 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
503 #endif
504 // Refresh at final warning stage of ROM-ECC correction
505 CARDi_RefreshRom(CARD_ROMST_RFS_WARN_L2_MASK);
506
507 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
508 CARDi_EndTask(&cardi_common);
509 }
510
511 /*---------------------------------------------------------------------------*
512 Name: CARDi_IsRomDmaAvailable
513
514 Description: Determines whether asynchronous DMA is usable in ROM transfer.
515
516 Arguments: dma: DMA channel
517 dst: Transfer destination buffer
518 src: Transfer source ROM offset
519 len: Transfer size
520
521 Returns: If DMA is usable in ROM transfer, return TRUE.
522 *---------------------------------------------------------------------------*/
CARDi_IsRomDmaAvailable(u32 dma,void * dst,u32 src,u32 len)523 static BOOL CARDi_IsRomDmaAvailable(u32 dma, void *dst, u32 src, u32 len)
524 {
525 return (dma <= MI_DMA_MAX_NUM) && (len > 0) && (((u32)dst & 31) == 0) &&
526 #ifdef SDK_ARM9
527 (((u32)dst + len <= OS_GetITCMAddress()) || ((u32)dst >= OS_GetITCMAddress() + HW_ITCM_SIZE)) &&
528 (((u32)dst + len <= OS_GetDTCMAddress()) || ((u32)dst >= OS_GetDTCMAddress() + HW_DTCM_SIZE)) &&
529 #endif
530 (((src | len) & (CARD_ROM_PAGE_SIZE - 1)) == 0);
531 }
532
533 /*---------------------------------------------------------------------------*
534 Name: CARDi_ReadRomSyncCore
535
536 Description: Common process for synchronous card reads.
537
538 Arguments: c: CARDiCommon structure
539
540 Returns: None.
541 *---------------------------------------------------------------------------*/
CARDi_ReadRomSyncCore(CARDiCommon * c)542 static void CARDi_ReadRomSyncCore(CARDiCommon *c)
543 {
544 // Run ROM access routine that corresponds to the execution environment
545 (void)(*CARDiReadRomFunction)(NULL, (void*)c->dst, c->src, c->len);
546 #ifdef SDK_ARM9
547 // Determine whether card was removed while accessed
548 CARDi_CheckPulledOutCore(CARDi_ReadRomIDCore());
549 #endif
550 // Refresh at final warning stage of ROM-ECC correction
551 CARDi_RefreshRom(CARD_ROMST_RFS_WARN_L2_MASK);
552
553 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
554 }
555 #endif // defined(CARD_USING_ROMREADER)
556
557 /*---------------------------------------------------------------------------*
558 Name: CARDi_ReadRom
559
560 Description: Basic function of ROM read.
561
562 Arguments: dma: DMA channel to use
563 src: Transfer source offset
564 dst: Transfer destination memory address
565 len: Transfer size
566 callback: Completion callback (NULL if not used)
567 arg: Argument of completion callback (ignored if not used)
568 is_async: If set to asynchronous mode, TRUE
569
570 Returns: None.
571 *---------------------------------------------------------------------------*/
CARDi_ReadRom(u32 dma,const void * src,void * dst,u32 len,MIDmaCallback callback,void * arg,BOOL is_async)572 void CARDi_ReadRom(u32 dma,
573 const void *src, void *dst, u32 len,
574 MIDmaCallback callback, void *arg, BOOL is_async)
575 {
576 #if defined(CARD_USING_ROMREADER)
577 CARDiCommon *const c = &cardi_common;
578
579 SDK_ASSERT(CARD_IsAvailable());
580 SDK_ASSERT(CARDi_GetTargetMode() == CARD_TARGET_ROM);
581 SDK_ASSERTMSG((dma != 0), "cannot specify DMA channel 0");
582
583 // Determine validity of card access
584 CARD_CheckEnabled();
585 if ((CARDi_GetAccessLevel() & CARD_ACCESS_LEVEL_ROM) == 0)
586 {
587 OS_TPanic("this program cannot access CARD-ROM!");
588 }
589
590 // Exclusive wait on ARM9 side
591 (void)CARDi_WaitForTask(c, TRUE, callback, arg);
592
593 // Get DMA interface
594 c->DmaCall = CARDi_GetDmaInterface(dma);
595 c->dma = (u32)((c->DmaCall != NULL) ? (dma & MI_DMA_CHANNEL_MASK) : MI_DMA_NOT_USE);
596 if (c->dma <= MI_DMA_MAX_NUM)
597 {
598 c->DmaCall->Stop(c->dma);
599 }
600
601 // Set this time's transfer parameters
602 c->src = (u32)((u32)src + cardi_rom_base);
603 c->dst = (u32)dst;
604 c->len = (u32)len;
605
606 // Set transfer parameter
607 {
608 CARDTransferInfo *info = CARDiDmaReadInfo;
609 info->callback = CARDi_DmaReadDone;
610 info->userdata = NULL;
611 info->src = c->src;
612 info->dst = c->dst;
613 info->len = c->len;
614 info->work = 0;
615 }
616
617 // DMA transfers can be used in some cases, if it is an environment where hash checks are invalid
618 if ((CARDiReadRomFunction == CARDi_ReadRomWithCPU) &&
619 CARDi_IsRomDmaAvailable(c->dma, (void *)c->dst, c->src, c->len))
620 {
621 #if defined(SDK_ARM9)
622 // Depending upon the size of the transfer range, switch the manner in which the cache is invalidated
623 OSIntrMode bak_psr = OS_DisableInterrupts();
624 if (CARDiEnableCacheInvalidationIC)
625 {
626 CARDi_ICInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_ic);
627 }
628 if (CARDiEnableCacheInvalidationDC)
629 {
630 CARDi_DCInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_dc);
631 }
632 (void)OS_RestoreInterrupts(bak_psr);
633 #endif
634 // Start asynchronous transfer using DMA
635 CARDi_ReadRomWithDMA(CARDiDmaReadInfo);
636 // Wait until complete here if synchronous transfer is requested
637 if (!is_async)
638 {
639 CARD_WaitRomAsync();
640 }
641 }
642 else
643 {
644 // Even with CPU transfers, it is necessary to invalidate because the instruction cache is incompatible
645 if (CARDiEnableCacheInvalidationIC)
646 {
647 CARDi_ICInvalidateSmart((void *)c->dst, c->len, c->flush_threshold_ic);
648 }
649 // Register task to thread if some form of direct processing is required by the CPU
650 (void)CARDi_ExecuteOldTypeTask(CARDi_ReadRomSyncCore, is_async);
651 }
652 #else
653 (void)dma;
654 (void)is_async;
655 (void)CARDi_ReadRomWithCPU(NULL, dst, (u32)src, len);
656 if (callback)
657 {
658 (*callback)(arg);
659 }
660 #endif // defined(CARD_USING_ROMREADER)
661 }
662
663 /*---------------------------------------------------------------------------*
664 Name: CARDi_ReadRomID
665
666 Description: Reads the card ID.
667
668 Arguments: None.
669
670 Returns: Card ID.
671 *---------------------------------------------------------------------------*/
CARDi_ReadRomID(void)672 u32 CARDi_ReadRomID(void)
673 {
674 u32 ret = 0;
675
676 SDK_ASSERT(CARD_IsAvailable());
677 SDK_ASSERTMSG(CARDi_GetTargetMode() == CARD_TARGET_ROM, "must be locked by CARD_LockRom()");
678
679 #if defined(SDK_ARM9)
680 (void)CARDi_WaitForTask(&cardi_common, TRUE, NULL, NULL);
681 #endif // defined(SDK_ARM9)
682
683 /* Direct access is possible, so execute here */
684 ret = CARDi_ReadRomIDCore();
685 #ifdef SDK_ARM9
686 // Detect card removal here
687 CARDi_CheckPulledOutCore(ret);
688 #endif
689
690 #if defined(SDK_ARM9)
691 cardi_common.cmd->result = CARD_RESULT_SUCCESS;
692 CARDi_EndTask(&cardi_common);
693 #endif // defined(SDK_ARM9)
694
695 return ret;
696 }
697
698 #if defined(CARD_USING_HASHCHECK)
699 #include <twl/ltdmain_begin.h>
700
701 // ROM hash calculation buffer
702 u8 *CARDiHashBufferAddress = NULL;
703 u32 CARDiHashBufferLength = 0;
704 static CARDRomHashContext context[1];
705
706 /*---------------------------------------------------------------------------*
707 Name: CARDi_ReadCardWithHash
708
709 Description: ROM transfer while confirming hash.
710
711 Arguments: buffer: Transfer destination buffer
712 offset: Transfer source ROM offset
713 length: Transfer size
714
715 Returns: None.
716 *---------------------------------------------------------------------------*/
CARDi_ReadCardWithHash(void * userdata,void * buffer,u32 offset,u32 length)717 static int CARDi_ReadCardWithHash(void *userdata, void *buffer, u32 offset, u32 length)
718 {
719 (void)userdata;
720 CARD_ReadRomHashImage(context, buffer, offset, length);
721 return (int)length;
722 }
723
724 /*---------------------------------------------------------------------------*
725 Name: CARDi_ReadCardWithHashInternalAsync
726
727 Description: Asynchronous DMA transfer for partial use internally with ROM transfers of the hash verified version.
728
729 Arguments: userdata: User-defined argument
730 buffer: Transfer destination buffer
731 offset: Transfer source ROM offset
732 length: Transfer size
733
734 Returns: None.
735 *---------------------------------------------------------------------------*/
CARDi_ReadCardWithHashInternalAsync(void * userdata,void * buffer,u32 offset,u32 length)736 static int CARDi_ReadCardWithHashInternalAsync(void *userdata, void *buffer, u32 offset, u32 length)
737 {
738 if (cardi_common.dma == MI_DMA_NOT_USE)
739 {
740 length = 0;
741 }
742 else
743 {
744 CARDRomHashContext *context = (CARDRomHashContext *)userdata;
745 static CARDTransferInfo card_hash_info[1];
746 DC_FlushRange(buffer, length);
747 card_hash_info->callback = (void(*)(void*))CARD_NotifyRomHashReadAsync;
748 card_hash_info->userdata = context;
749 card_hash_info->src = offset;
750 card_hash_info->dst = (u32)buffer;
751 card_hash_info->len = length;
752 card_hash_info->command = 0;
753 card_hash_info->work = 0;
754 CARDi_ReadRomWithDMA(card_hash_info);
755 }
756 return (int)length;
757 }
758
759 /*---------------------------------------------------------------------------*
760 Name: CARDi_InitRomHash
761
762 Description: If possible, switches to hash verification version ROM transfer.
763
764 Arguments: None.
765
766 Returns: None.
767 *---------------------------------------------------------------------------*/
CARDi_InitRomHash(void)768 static void CARDi_InitRomHash(void)
769 {
770 // 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
771 //
772 //
773 u8 *lo = (u8 *)MATH_ROUNDUP((u32)OS_GetMainArenaLo(), 32);
774 u8 *hi = (u8 *)MATH_ROUNDDOWN((u32)OS_GetMainArenaHi(), 32);
775 u32 len = CARD_CalcRomHashBufferLength(CARD_GetOwnRomHeaderTWL());
776 if (&lo[len] > hi)
777 {
778 OS_TPanic("cannot allocate memory for ROM-hash from ARENA");
779 }
780 else
781 {
782 OS_SetMainArenaLo(&lo[len]);
783 CARDiHashBufferAddress = lo;
784 CARDiHashBufferLength = len;
785 // Actually load if it is an environment where the ROM boot and hash table exist
786 if ((OS_GetBootType() == OS_BOOTTYPE_ROM) &&
787 ((((const u8 *)HW_TWL_ROM_HEADER_BUF)[0x1C] & 0x01) != 0))
788 {
789 cardi_common.dma = MI_DMA_NOT_USE;
790 CARDiReadRomFunction = CARDi_ReadCardWithHash;
791 {
792 u16 id = (u16)OS_GetLockID();
793 CARD_LockRom(id);
794 CARD_InitRomHashContext(context,
795 CARD_GetOwnRomHeaderTWL(),
796 CARDiHashBufferAddress,
797 CARDiHashBufferLength,
798 CARDi_ReadRomWithCPU,
799 CARDi_ReadCardWithHashInternalAsync,
800 context);
801 // Destroy the pointer so that there is no competition for use of the same buffer
802 CARDiHashBufferAddress = NULL;
803 CARDiHashBufferLength = 0;
804 CARD_UnlockRom(id);
805 OS_ReleaseLockID(id);
806 }
807 }
808 }
809 }
810 #include <twl/ltdmain_end.h>
811 #endif
812
813 /*---------------------------------------------------------------------------*
814 Name: CARDi_InitRom
815
816 Description: Initializes the ROM access management information.
817
818 Arguments: None.
819
820 Returns: None.
821 *---------------------------------------------------------------------------*/
CARDi_InitRom(void)822 void CARDi_InitRom(void)
823 {
824 #if defined(CARD_USING_ROMREADER)
825 CARDiReadRomFunction = CARDi_ReadRomWithCPU;
826 // 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().
827 //
828 //
829 //
830 if ((OS_GetBootType() == OS_BOOTTYPE_ROM) && CARD_GetOwnRomHeader()->rom_size)
831 {
832 u16 id = (u16)OS_GetLockID();
833 CARD_LockRom(id);
834 (void)CARDi_ReadRomWithCPU(NULL, CARDiOwnSignature,
835 CARD_GetOwnRomHeader()->rom_size,
836 CARD_ROM_DOWNLOAD_SIGNATURE_SIZE);
837 CARD_UnlockRom(id);
838 OS_ReleaseLockID(id);
839 }
840 #if defined(CARD_USING_HASHCHECK)
841 // Adopts a routine that also verifies hash, if usable
842 if (OS_IsRunOnTwl())
843 {
844 CARDi_InitRomHash();
845 }
846 #endif
847 #else
848 CARDiReadRomFunction = NULL;
849 #endif
850 }
851
852
853 /*---------------------------------------------------------------------------*
854 Name: CARD_WaitRomAsync
855
856 Description: Idles until the ROM access function is completed.
857
858 Arguments: None.
859
860 Returns: None.
861 *---------------------------------------------------------------------------*/
CARD_WaitRomAsync(void)862 void CARD_WaitRomAsync(void)
863 {
864 (void)CARDi_WaitAsync();
865 }
866
867 /*---------------------------------------------------------------------------*
868 Name: CARD_TryWaitRomAsync
869
870 Description: Determines whether the ROM access function is completed.
871
872 Arguments: None.
873
874 Returns: TRUE when the ROM access function is completed.
875 *---------------------------------------------------------------------------*/
CARD_TryWaitRomAsync(void)876 BOOL CARD_TryWaitRomAsync(void)
877 {
878 return CARDi_TryWaitAsync();
879 }
880
881 /*---------------------------------------------------------------------------*
882 Name: CARDi_GetOwnSignature
883
884 Description: Gets its own DS Download Play signature data.
885
886 Arguments: None.
887
888 Returns: Its own DS Download Play signature data.
889 *---------------------------------------------------------------------------*/
CARDi_GetOwnSignature(void)890 const u8* CARDi_GetOwnSignature(void)
891 {
892 return CARDiOwnSignature;
893 }
894
895 /*---------------------------------------------------------------------------*
896 Name: CARDi_SetOwnSignature
897
898 Description: Sets its own DS Download Play signature data.
899 Calls from the host library when booted without a card.
900
901 Arguments: DS Download Play signature data
902
903 Returns: None.
904 *---------------------------------------------------------------------------*/
CARDi_SetOwnSignature(const void * signature)905 void CARDi_SetOwnSignature(const void *signature)
906 {
907 MI_CpuCopy8(signature, CARDiOwnSignature, CARD_ROM_DOWNLOAD_SIGNATURE_SIZE);
908 }
909
910 #if defined(SDK_ARM9)
911 /*---------------------------------------------------------------------------*
912 Name: CARD_GetCacheFlushFlag
913
914 Description: Gets setting flags of whether to invalidate cache automatically.
915
916 Arguments: icache: Pointer to the location where the automatic invalidation flag for the instruction cache is stored
917 Ignore if NULL.
918 dcache: Pointer to the location the automatic invalidation flag for the instruction cache is stored.
919 Ignore if NULL.
920
921 Returns: None.
922 *---------------------------------------------------------------------------*/
CARD_GetCacheFlushFlag(BOOL * icache,BOOL * dcache)923 void CARD_GetCacheFlushFlag(BOOL *icache, BOOL *dcache)
924 {
925 SDK_ASSERT(CARD_IsAvailable());
926 if (icache)
927 {
928 *icache = CARDiEnableCacheInvalidationIC;
929 }
930 if (dcache)
931 {
932 *dcache = CARDiEnableCacheInvalidationDC;
933 }
934 }
935
936 /*---------------------------------------------------------------------------*
937 Name: CARD_SetCacheFlushFlag
938
939 Description: Sets whether to automatically invalidate cache.
940 By default, instruction cache is FALSE, and data cache is TRUE.
941
942 Arguments: icache: TRUE to enable automatic invalidation of the instruction cache
943 dcache: TRUE to enable automatic invalidation of data caches
944
945 Returns: None.
946 *---------------------------------------------------------------------------*/
CARD_SetCacheFlushFlag(BOOL icache,BOOL dcache)947 void CARD_SetCacheFlushFlag(BOOL icache, BOOL dcache)
948 {
949 SDK_ASSERT(CARD_IsAvailable());
950 CARDiEnableCacheInvalidationIC = icache;
951 CARDiEnableCacheInvalidationDC = dcache;
952 }
953 #endif
954