1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - FS - libraries
3   File:     fs_proc_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:: 2008-12-08#$
14   $Rev: 9544 $
15   $Author: yosizaki $
16 
17  *---------------------------------------------------------------------------*/
18 
19 
20 #include <nitro/fs/romfat.h>
21 #include <nitro/fs/api.h>
22 #include <nitro/card.h>
23 
24 #ifdef SDK_TWL
25 #include <twl/fatfs.h>
26 #endif
27 
28 #include "../include/command.h"
29 #include "../include/util.h"
30 #include "../include/rom.h"
31 
32 
33 #if defined(FS_IMPLEMENT)
34 
35 
36 /*---------------------------------------------------------------------------*/
37 /* Variables */
38 
39 static s32          fsi_card_lock_id;
40 static u32          fsi_default_dma_no;
41 static FSArchive    fsi_arc_rom;
42 
43 /*---------------------------------------------------------------------------*/
44 /* Functions */
45 
46 /*---------------------------------------------------------------------------*
47   Name:         FSi_IsUnreadableRomOffset
48 
49   Description:  Determines whether the specified ROM offset is in a range that cannot be read in the current environment
50 
51   Arguments:    arc			The calling archive.
52                 offset              ROM offset to be determined.
53 
54   Returns:      TRUE if the specified ROM offset cannot be read in the current environment.
55  *---------------------------------------------------------------------------*/
FSi_IsUnreadableRomOffset(FSArchive * arc,u32 offset)56 BOOL FSi_IsUnreadableRomOffset(FSArchive *arc, u32 offset)
57 {
58     BOOL    result = FALSE;
59 #if !defined(SDK_TWL)
60     (void)arc;
61     (void)offset;
62 #else // defined(SDK_TWL)
63     if (STD_CompareString(FS_GetArchiveName(arc), "rom") == 0)
64     {
65         if (!OS_IsRunOnTwl())
66         {
67             const CARDRomHeader    *header = CARD_GetOwnRomHeader();
68             if (offset >= header->twl_ltd_area_rom_offset * 0x80000)
69             {
70                 result = TRUE;
71             }
72         }
73     }
74 #endif // defined(SDK_TWL)
75     return result;
76 }
77 
78 /*---------------------------------------------------------------------------*
79   Name:         FSi_OnRomReadDone
80 
81   Description:  ROM asynchronous read completion callback
82 
83   Arguments:    arg              User specified callback argument
84 
85   Returns:      None.
86  *---------------------------------------------------------------------------*/
FSi_OnRomReadDone(void * arg)87 static void FSi_OnRomReadDone(void *arg)
88 {
89     FS_NotifyArchiveAsyncEnd((FSArchive *)arg,
90                              CARD_IsPulledOut() ? FS_RESULT_ERROR : FS_RESULT_SUCCESS);
91 }
92 
93 /*---------------------------------------------------------------------------*
94   Name:         FSi_ReadRomCallback
95 
96   Description:  ROM read callback
97 
98   Arguments:    p_arc            FSArchive structure
99                 dst        Transfer destination
100                 src        Transfer source
101                 len        Transfer size
102 
103   Returns:      Read process results
104  *---------------------------------------------------------------------------*/
FSi_ReadRomCallback(FSArchive * p_arc,void * dst,u32 src,u32 len)105 static FSResult FSi_ReadRomCallback(FSArchive *p_arc, void *dst, u32 src, u32 len)
106 {
107     CARD_ReadRomAsync(fsi_default_dma_no, (const void *)src, dst, len, FSi_OnRomReadDone, p_arc);
108     return FS_RESULT_PROC_ASYNC;
109 }
110 
111 /*---------------------------------------------------------------------------*
112   Name:         FSi_RomArchiveProc
113 
114   Description:  ROM archive procedure
115 
116   Arguments:    p_file:           FSFile structure that stores command information.
117                 cmd:              Command type.
118 
119   Returns:      Command processing result.
120  *---------------------------------------------------------------------------*/
FSi_RomArchiveProc(FSFile * p_file,FSCommandType cmd)121 static FSResult FSi_RomArchiveProc(FSFile *p_file, FSCommandType cmd)
122 {
123     (void)p_file;
124     switch (cmd)
125     {
126     case FS_COMMAND_ACTIVATE:
127         CARD_LockRom((u16)fsi_card_lock_id);
128         return FS_RESULT_SUCCESS;
129     case FS_COMMAND_IDLE:
130         CARD_UnlockRom((u16)fsi_card_lock_id);
131         return FS_RESULT_SUCCESS;
132 #if defined(SDK_TWL)
133     case FS_COMMAND_OPENFILEDIRECT:
134         // If running in NTR mode and the TWL dedicated region cannot be read, an error will occur
135         if (FSi_IsUnreadableRomOffset(FS_GetAttachedArchive(p_file), p_file->arg.openfiledirect.top))
136         {
137             OS_TWarning("specified file can be read on TWL only!(fileID=%d)\n", p_file->arg.openfiledirect.index);
138             return FS_RESULT_PERMISSION_DENIED;
139         }
140         return FS_RESULT_PROC_DEFAULT;
141 #endif
142     case FS_COMMAND_WRITEFILE:
143         return FS_RESULT_UNSUPPORTED;
144     default:
145         return FS_RESULT_PROC_UNKNOWN;
146     }
147 }
148 
149 /*---------------------------------------------------------------------------*
150   Name:         FSi_EmptyArchiveProc
151 
152   Description:  Empty archive procedure that does nothing
153 
154   Arguments:    p_file:           FSFile structure that stores command information.
155                 cmd:              Command type.
156 
157   Returns:      Command processing result.
158  *---------------------------------------------------------------------------*/
FSi_EmptyArchiveProc(FSFile * p_file,FSCommandType cmd)159 static FSResult FSi_EmptyArchiveProc(FSFile *p_file, FSCommandType cmd)
160 {
161     (void)p_file;
162     switch (cmd)
163     {
164     case FS_COMMAND_WRITEFILE:
165         return FS_RESULT_UNSUPPORTED;
166     default:
167         return FS_RESULT_PROC_UNKNOWN;
168     }
169 }
FSi_ReadDummyCallback(FSArchive * p_arc,void * dst,u32 src,u32 len)170 static FSResult FSi_ReadDummyCallback(FSArchive *p_arc, void *dst, u32 src, u32 len)
171 {
172     (void)p_arc;
173     (void)dst;
174     (void)src;
175     (void)len;
176     return FS_RESULT_UNSUPPORTED;
177 }
FSi_WriteDummyCallback(FSArchive * p_arc,const void * src,u32 dst,u32 len)178 static FSResult FSi_WriteDummyCallback(FSArchive *p_arc, const void *src, u32 dst, u32 len)
179 {
180     (void)p_arc;
181     (void)src;
182     (void)dst;
183     (void)len;
184     return FS_RESULT_UNSUPPORTED;
185 }
186 
187 /*---------------------------------------------------------------------------*
188   Name:         FSi_OverrideRomArchive
189 
190   Description:  Replaces the ROM archive content as necessary.
191 
192   Arguments:    arc              ROM archive structure that should be mounted.
193 
194   Returns:      It is necessary to return TRUE if replacing with a different implementation without using the standard ROM archive on the card.
195 
196  *---------------------------------------------------------------------------*/
FSi_OverrideRomArchive(FSArchive * arc)197 SDK_WEAK_SYMBOL BOOL FSi_OverrideRomArchive(FSArchive *arc) __attribute__((never_inline))
198 {
199     (void)arc;
200     return FALSE;
201 }
202 
203 /*---------------------------------------------------------------------------*
204   Name:         FSi_InitRomArchive
205 
206   Description:  Initialize "rom" archive.
207 
208   Arguments:    default_dma_no:   Default DMA channel for ROM.
209                                  if out of range(0-3),
210                                  use CpuCopy instead of DMA.
211 
212   Returns:      None.
213  *---------------------------------------------------------------------------*/
FSi_InitRomArchive(u32 default_dma_no)214 void FSi_InitRomArchive(u32 default_dma_no)
215 {
216     CARD_Init();
217 
218     fsi_default_dma_no = default_dma_no;
219     fsi_card_lock_id = OS_GetLockID();
220 
221     FS_InitArchive(&fsi_arc_rom);
222     (void)FS_RegisterArchiveName(&fsi_arc_rom, "rom", 3);
223 
224     // If it is a card-boot type, mount the ROM file system existing on the card.
225     if (OS_GetBootType() == OS_BOOTTYPE_ROM)
226     {
227         const CARDRomRegion *const fnt = CARD_GetRomRegionFNT();
228         const CARDRomRegion *const fat = CARD_GetRomRegionFAT();
229         FS_SetArchiveProc(&fsi_arc_rom, FSi_RomArchiveProc,
230                           FS_ARCHIVE_PROC_WRITEFILE |
231                           FS_ARCHIVE_PROC_OPENFILEDIRECT |
232                           FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE);
233         if ((fnt->offset == 0xFFFFFFFF) || (fnt->offset == 0x00000000) ||
234             (fat->offset == 0xFFFFFFFF) || (fat->offset == 0x00000000))
235         {
236         }
237         else
238         {
239             (void)FS_LoadArchive(&fsi_arc_rom, 0x00000000,
240                                  fat->offset, fat->length,
241                                  fnt->offset, fnt->length,
242                                  FSi_ReadRomCallback, NULL);
243         }
244     }
245     // Additionally, if it is an ordinary program without an existing ROM to replace, mount the empty archive.
246     else if (!FSi_OverrideRomArchive(&fsi_arc_rom))
247     {
248     }
249     if (!FS_IsArchiveLoaded(&fsi_arc_rom))
250     {
251         FS_SetArchiveProc(&fsi_arc_rom, FSi_EmptyArchiveProc, (u32)FS_ARCHIVE_PROC_ALL);
252         (void)FS_LoadArchive(&fsi_arc_rom, 0x00000000,
253                              0, 0, 0, 0, FSi_ReadDummyCallback, FSi_WriteDummyCallback);
254     }
255 
256     (void)FS_SetCurrentDirectory("rom:");
257 }
258 
259 /*---------------------------------------------------------------------------*
260   Name:         FSi_EndRomArchive
261 
262   Description:  Deallocates the "rom" archive.
263 
264   Arguments:    None.
265 
266   Returns:      None.
267  *---------------------------------------------------------------------------*/
FSi_EndRomArchive(void)268 void    FSi_EndRomArchive(void)
269 {
270     if (FS_IsArchiveLoaded(&fsi_arc_rom))
271     {
272         (void)FS_UnloadArchive(&fsi_arc_rom);
273         FS_ReleaseArchiveName(&fsi_arc_rom);
274     }
275     OS_ReleaseLockID((u16)fsi_card_lock_id);
276 }
277 
278 /*---------------------------------------------------------------------------*
279   Name:         FS_GetDefaultDMA
280 
281   Description:  get default DMA channel
282 
283   Arguments:    None.
284 
285   Returns:      current DMA channel.
286  *---------------------------------------------------------------------------*/
FS_GetDefaultDMA(void)287 u32 FS_GetDefaultDMA(void)
288 {
289     return fsi_default_dma_no;
290 }
291 
292 /*---------------------------------------------------------------------------*
293   Name:         FS_SetDefaultDMA
294 
295   Description:  set default DMA channel
296 
297   Arguments:    dma_no:      default dma channel for FS
298                                  if out of range(0-3),
299                                  use CpuCopy instead of DMA.
300 
301   Returns:      previous DMA channel.
302  *---------------------------------------------------------------------------*/
FS_SetDefaultDMA(u32 dma_no)303 u32 FS_SetDefaultDMA(u32 dma_no)
304 {
305     SDK_ASSERTMSG(dma_no != 0, "cannot use DMA channel 0 for ROM access");
306     {
307         OSIntrMode bak_psr = OS_DisableInterrupts();
308         u32     bak_dma_no = fsi_default_dma_no;
309         BOOL    bak_stat = FS_SuspendArchive(&fsi_arc_rom);
310         fsi_default_dma_no = dma_no;
311         if (bak_stat)
312         {
313             (void)FS_ResumeArchive(&fsi_arc_rom);
314         }
315         (void)OS_RestoreInterrupts(bak_psr);
316         return bak_dma_no;
317     }
318 }
319 
320 /*---------------------------------------------------------------------------*
321   Name:         FS_TryLoadTable
322 
323   Description:  preload FAT and FNT tables of file-system.
324                 if specified size is enough to load tables, load it to p_mem.
325                 then, all the operation using FAT and FNT is with p_mem.
326 
327   Arguments:    p_mem:       buffer to preload
328                 size        byte length of p_mem
329 
330   Returns:      true size of memory for FAT and FNT.
331  *---------------------------------------------------------------------------*/
FS_TryLoadTable(void * p_mem,u32 size)332 u32 FS_TryLoadTable(void *p_mem, u32 size)
333 {
334     return FS_LoadArchiveTables(&fsi_arc_rom, p_mem, size);
335 }
336 
337 /*---------------------------------------------------------------------------*
338   Name:         FS_CreateFileFromRom
339 
340   Description:  Temporarily generates a file that maps the specified CARD-ROM area.
341 
342   Arguments:    p_file:           FSFile structure that stores file handle
343                 offset:     Offset from start of the CARD-ROM region that is READ's target
344                 size:       Size in bytes from the offset in the target region
345 
346   Returns:      None.
347  *---------------------------------------------------------------------------*/
FS_CreateFileFromRom(FSFile * p_file,u32 offset,u32 size)348 BOOL FS_CreateFileFromRom(FSFile *p_file, u32 offset, u32 size)
349 {
350     return FS_OpenFileDirect(p_file, &fsi_arc_rom, offset, offset + size, 0xFFFF);
351 }
352 
353 #else /* FS_IMPLEMENT */
354 
355 /*---------------------------------------------------------------------------*
356   Name:         FSi_ReadRomDirect
357 
358   Description:  Directly read the specified ROM address.
359 
360   Arguments:    src        Transfer source offset
361                 dst              Transfer destination address
362                 len        Transfer size
363 
364   Returns:      None.
365  *---------------------------------------------------------------------------*/
FSi_ReadRomDirect(const void * src,void * dst,u32 len)366 void FSi_ReadRomDirect(const void *src, void *dst, u32 len)
367 {
368     u16     id = (u16)OS_GetLockID();
369     (void)CARD_LockRom(id);
370     CARD_ReadRom(4, src, dst, len);
371     (void)CARD_UnlockRom(id);
372     OS_ReleaseLockID(id);
373 }
374 
375 
376 #endif /* FS_IMPLEMENT */
377