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:: 2009-06-19#$
14 $Rev: 10786 $
15 $Author: okajima_manabu $
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_TASSERTMSG(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