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 *)&reg_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