1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - FS - libraries
3 File: fs_archive_fatfs.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 #ifdef SDK_TWL
20
21 #include <nitro/fs.h>
22 #include <nitro/os/ARM9/tcm.h>
23 #include <nitro/os/ARM9/cache.h>
24 #include <nitro/math/math.h>
25 #include <nitro/std/string.h>
26 #include <nitro/gx/gx_vramcnt.h>
27 #include <nitro/spi/ARM9/pm.h>
28 #include <twl/fatfs.h>
29 #include <twl/mi/common/sharedWram.h>
30
31 #include "../include/util.h"
32 #include "../include/command.h"
33 #include "../include/rom.h"
34
35
36 #if defined(FS_IMPLEMENT)
37
38
39 #include <twl/ltdmain_begin.h>
40
41
42 /*---------------------------------------------------------------------------*/
43 /* Constants */
44
45 // Characters that cannot be used in entry names of paths
46 extern const u16 *FSiPathInvalidCharactersW;
47 const u16 *FSiPathInvalidCharactersW = L":*?\"<>|";
48
49
50 /*---------------------------------------------------------------------------*/
51 /* Variables */
52
53 static int FSiSwitchableWramSlots = 0;
54
55 static FSFATFSArchiveContext FSiFATFSDriveDefault[FS_MOUNTDRIVE_MAX] ATTRIBUTE_ALIGN(32);
56 static FATFSRequestBuffer FSiFATFSAsyncRequestDefault[FS_MOUNTDRIVE_MAX] ATTRIBUTE_ALIGN(32);
57 static u8 FSiTemporaryBufferDefault[FS_TEMPORARY_BUFFER_MAX] ATTRIBUTE_ALIGN(32);
58
59
60 /*---------------------------------------------------------------------------*/
61 /* Functions */
62
63 /*---------------------------------------------------------------------------*
64 * Implementation related to customize
65 *---------------------------------------------------------------------------*/
66
67 /*---------------------------------------------------------------------------*
68 Name: FSiFATFSDrive
69
70 Description: Context array that manages the archive of a FAT base.
71 Ordinarily, an array size for the quantity of FS_MOUNTDRIVE_MAX is required, and in default, static variables in the LTDMAIN segment are used.
72
73 With applications built using a special memory arrangement, it is possible to set the proper buffer by changing this variable internally by calling the FSi_SetupFATBuffers function that was overridden.
74
75
76
77 Arguments: None.
78
79 Returns: Buffer for the amount of the FS_MOUNTDRIVE_MAX of the FSFATFSArchiveContext structure.
80 *---------------------------------------------------------------------------*/
81 FSFATFSArchiveContext *FSiFATFSDrive = NULL;
82
83 /*---------------------------------------------------------------------------*
84 Name: FSiFATFSAsyncRequest
85
86 Description: Command buffer that is used in asynchronous processing by the FAT base archive.
87 Ordinarily, an array size for the quantity of FS_MOUNTDRIVE_MAX is required, and in default, static variables in the LTDMAIN segment are used.
88
89 With applications built using a special memory arrangement, it is possible to set the proper buffer by changing this variable internally by calling the FSi_SetupFATBuffers function that was overridden.
90
91
92
93 Arguments: None.
94
95 Returns: Static command buffer of FS_TEMPORARY_BUFFER_MAX bytes.
96 *---------------------------------------------------------------------------*/
97 FATFSRequestBuffer *FSiFATFSAsyncRequest = NULL;
98
99 /*---------------------------------------------------------------------------*
100 Name: FSiTemporaryBuffer
101
102 Description: Pointer to the static temporary buffer for issuing read/write commands.
103 It must be memory that can be referenced by both ARM9/ARM7, and by default a static variable in the LTDMAIN segment is used.
104
105 For applications constructed using a special memory layout, you can change these variables to set the appropriate buffer before calling the FS_Init function.
106
107
108
109 Arguments: None.
110
111 Returns: Static command buffer of FS_TEMPORARY_BUFFER_MAX bytes.
112 *---------------------------------------------------------------------------*/
113 u8 *FSiTemporaryBuffer = NULL;
114
115 /*---------------------------------------------------------------------------*
116 Name: FSi_SetupFATBuffers
117
118 Description: Initializes various buffers needed by the FAT base archive.
119 With applications built using a special memory arrangement, it is possible to independently set the various buffers by overriding this variable and suppressing the required memory size.
120
121
122
123 Arguments: None.
124
125 Returns: None.
126 *---------------------------------------------------------------------------*/
FSi_SetupFATBuffers(void)127 SDK_WEAK_SYMBOL void FSi_SetupFATBuffers(void)
128 {
129 FSiFATFSDrive = FSiFATFSDriveDefault;
130 FSiFATFSAsyncRequest = FSiFATFSAsyncRequestDefault;
131 FSiTemporaryBuffer = FSiTemporaryBufferDefault;
132 }
133
134 /*---------------------------------------------------------------------------*
135 Name: FSi_IsValidAddressForARM7
136
137 Description: Determines whether this is a buffer accessible from ARM7.
138 With applications built using a special memory layout, it is possible to redefine the proper determination routine by overriding this function.
139
140
141
142 Arguments: buffer: Buffer to be determined
143 length: Buffer length
144
145 Returns: TRUE if it is a buffer accessible from ARM7.
146 *---------------------------------------------------------------------------*/
FSi_IsValidAddressForARM7(const void * buffer,u32 length)147 SDK_WEAK_SYMBOL BOOL FSi_IsValidAddressForARM7(const void *buffer, u32 length)
148 __attribute__((never_inline))
149 {
150 u32 addr = (u32)buffer;
151 u32 dtcm = OS_GetDTCMAddress();
152 if ((addr + length > dtcm) && (addr < dtcm + HW_DTCM_SIZE))
153 {
154 return FALSE;
155 }
156 if ((addr >= HW_TWL_MAIN_MEM) && (addr + length <= HW_TWL_MAIN_MEM_END))
157 {
158 return TRUE;
159 }
160 if ((addr >= HW_EXT_WRAM_ARM7) && (addr + length <= GX_GetSizeOfARM7()))
161 {
162 return TRUE;
163 }
164 // Allow if it is a switchable WRAM not overlapping the slot boundary
165 if ((addr >= HW_WRAM_AREA) && (addr <= HW_WRAM_AREA_END) &&
166 (MATH_ROUNDDOWN(addr, MI_WRAM_B_SLOT_SIZE) + MI_WRAM_B_SLOT_SIZE ==
167 MATH_ROUNDUP(addr + length, MI_WRAM_B_SLOT_SIZE)))
168 {
169 MIWramPos type;
170 int slot = MIi_AddressToWramSlot(buffer, &type);
171 if (slot >= 0)
172 {
173 if ((((FSiSwitchableWramSlots >> ((type == MI_WRAM_B) ? 0 : 8)) & (1 << slot)) != 0) &&
174 // If success is not always possible by switching, the application guarantees it
175 ((MI_GetWramBankMaster(type, slot) == MI_WRAM_ARM7) ||
176 (MI_SwitchWramSlot(type, slot, MI_WRAM_SIZE_32KB,
177 MI_GetWramBankMaster(type, slot), MI_WRAM_ARM7) >= 0)))
178 {
179
180 return TRUE;
181 }
182 }
183 }
184 return FALSE;
185 }
186
187 /*---------------------------------------------------------------------------*
188 Name: FSi_SetSwitchableWramSlots
189
190 Description: Specifies WRAM slot that the FS library can switch to ARM7 depending on the circumstances.
191
192 Arguments: bitsB: WRAM-B slot bit collection
193 bitsC: Bitset of WRAM-C slots
194
195 Returns: None.
196 *---------------------------------------------------------------------------*/
FSi_SetSwitchableWramSlots(int bitsB,int bitsC)197 void FSi_SetSwitchableWramSlots(int bitsB, int bitsC)
198 {
199 FSiSwitchableWramSlots = (bitsB << 0) | (bitsC << 8);
200 }
201
202 /*---------------------------------------------------------------------------*
203 Name: FSi_AllocUnicodeFullPath
204
205 Description: Gets full path linking the archive name and relative path.
206
207 Arguments: context: FSFATFSArchiveContext structure
208 relpath: Relative path under the archive
209
210 Returns: Buffer that stores the full Unicode path that begins from the archive name.
211 *---------------------------------------------------------------------------*/
FSi_AllocUnicodeFullPath(FSFATFSArchiveContext * context,const char * relpath)212 static u16* FSi_AllocUnicodeFullPath(FSFATFSArchiveContext *context, const char *relpath)
213 {
214 u16 *dst = FSi_GetUnicodeBuffer(NULL);
215 {
216 int pos = 0;
217 int dstlen;
218 // First link the archive name and the relative path
219 dstlen = FS_ARCHIVE_FULLPATH_MAX - pos - 2;
220 (void)FSi_ConvertStringSjisToUnicode(&dst[pos], &dstlen, FS_GetArchiveName(context->arc), NULL, NULL);
221 pos += dstlen;
222 dst[pos++] = L':';
223 dst[pos++] = L'/';
224 dstlen = FS_ARCHIVE_FULLPATH_MAX - pos;
225 (void)FSi_ConvertStringSjisToUnicode(&dst[pos], &dstlen, relpath, NULL, NULL);
226 pos += dstlen;
227 // Remove trailing forward slashes ('/')
228 if ((pos > 0) && ((dst[pos - 1] == L'\\') || (dst[pos - 1] == L'/')))
229 {
230 --pos;
231 }
232 dst[pos] = L'\0';
233 }
234 return dst;
235 }
236
237 /*---------------------------------------------------------------------------*
238 Name: FSi_DostimeToFstime
239
240 Description: Converts FAT DOS time stamp to an FSDateTime format.
241
242 Arguments: dst: FSDateTime structure that stores the conversion results
243 src: DOS time stamp that is the conversion source
244
245 Returns: None.
246 *---------------------------------------------------------------------------*/
FSi_DostimeToFstime(FSDateTime * dst,u32 src)247 static void FSi_DostimeToFstime(FSDateTime *dst, u32 src)
248 {
249 dst->year = FATFS_DOSTIME_TO_YEAR(src);
250 dst->month = FATFS_DOSTIME_TO_MON(src);
251 dst->day = FATFS_DOSTIME_TO_MDAY(src);
252 dst->hour = FATFS_DOSTIME_TO_HOUR(src);
253 dst->minute = FATFS_DOSTIME_TO_MIN(src);
254 dst->second = FATFS_DOSTIME_TO_SEC(src);
255 }
256
257 /*---------------------------------------------------------------------------*
258 Name: FSi_FstimeToDostime
259
260 Description: Converts FSDateTime to a FAT DOS time stamp format.
261
262 Arguments: dst: DOS time stamp that stores the conversion results
263 src: FSDateTime structure that is the conversion source
264
265 Returns: None.
266 *---------------------------------------------------------------------------*/
FSi_FstimeToDostime(u32 * dst,const FSDateTime * src)267 static void FSi_FstimeToDostime(u32 *dst, const FSDateTime *src)
268 {
269 *dst = FATFS_DATETIME_TO_DOSTIME(src->year, src->month, src->day,
270 src->hour, src->minute, src->second);
271 }
272
273 /*---------------------------------------------------------------------------*
274 Name: FSi_CheckFstime
275
276 Description: Checks the FSDateTime.
277
278 Arguments: src: FSDateTime structure
279
280 Returns: TRUE or FALSE.
281 *---------------------------------------------------------------------------*/
FSi_CheckFstime(const FSDateTime * fstime)282 static BOOL FSi_CheckFstime( const FSDateTime *fstime)
283 {
284 if( fstime->month / 13 != 0) { return FALSE;}
285 // if( fstime->day / 32 != 0) { return FALSE;}
286 if( fstime->hour / 24 != 0) { return FALSE;}
287 if( fstime->minute/ 60 != 0) { return FALSE;}
288 if( fstime->second/ 61 != 0) { return FALSE;}
289 return( TRUE);
290 }
291
292 /*---------------------------------------------------------------------------*
293 Name: FSi_GetUnicodeSpanExcluding
294
295 Description: Gets the string length not including specified characters.
296
297 Arguments: src: Scanning target string
298 pattern: Characters to be searched for
299
300 Returns: String length, not including specified characters.
301 *---------------------------------------------------------------------------*/
FSi_GetUnicodeSpanExcluding(const u16 * src,const u16 * pattern)302 static int FSi_GetUnicodeSpanExcluding(const u16 *src, const u16 *pattern)
303 {
304 int pos = 0;
305 BOOL found = FALSE;
306 for (; src[pos]; ++pos)
307 {
308 int i;
309 for (i = 0; pattern[i]; ++i)
310 {
311 if (src[pos] == pattern[i])
312 {
313 found = TRUE;
314 break;
315 }
316 }
317 if (found)
318 {
319 break;
320 }
321 }
322 return pos;
323 }
324
325 /*---------------------------------------------------------------------------*
326 Name: FSi_UsingInvalidCharacterW
327
328 Description: Determines whether an inappropriate character is being used as the path name.
329 However, the "arcname:/<***>" is allowed as a special path.
330
331 Arguments: path: Full path string targeted for scanning
332
333 Returns: TRUE if using an inappropriate character.
334 *---------------------------------------------------------------------------*/
FSi_UsingInvalidCharacterW(const u16 * path)335 static BOOL FSi_UsingInvalidCharacterW(const u16 *path)
336 {
337 BOOL retval = FALSE;
338 const u16 *list = FSiPathInvalidCharactersW;
339 if (list && *list)
340 {
341 BOOL foundLT = FALSE;
342 int pos = 0;
343 // Skip archive name
344 while (path[pos] && (path[pos] != L':'))
345 {
346 ++pos;
347 }
348 // Skip archive separation
349 pos += (path[pos] == L':');
350 pos += (path[pos] == L'/');
351 // Search for prohibited characters considering special paths
352 if (path[pos] == L'<')
353 {
354 foundLT = TRUE;
355 ++pos;
356 }
357 // Confirm whether prohibited characters are being used
358 while (path[pos])
359 {
360 pos += FSi_GetUnicodeSpanExcluding(&path[pos], list);
361 if (path[pos])
362 {
363 if (foundLT && (path[pos] == L'>') && (path[pos + 1] == L'\0'))
364 {
365 foundLT = FALSE;
366 pos += 1;
367 }
368 else
369 {
370 retval = TRUE;
371 break;
372 }
373 }
374 }
375 retval |= foundLT;
376 // Warn if using prohibited characters
377 if (retval)
378 {
379 static BOOL logOnce = FALSE;
380 if (!logOnce)
381 {
382 OS_TWarning("specified path includes invalid character '%c'\n", (char)path[pos]);
383 logOnce = TRUE;
384 }
385 }
386 }
387 return retval;
388 }
389
390 /*---------------------------------------------------------------------------*
391 Name: FSi_ConvertError
392
393 Description: Converts FATFS library error codes to FS library error codes.
394
395 Arguments: error: FATFS library error codes
396
397 Returns: FS library error codes.
398 *---------------------------------------------------------------------------*/
FSi_ConvertError(u32 error)399 FSResult FSi_ConvertError(u32 error)
400 {
401 if (error == FATFS_RESULT_SUCCESS)
402 {
403 return FS_RESULT_SUCCESS;
404 }
405 else if (error == FATFS_RESULT_BUSY)
406 {
407 return FS_RESULT_BUSY;
408 }
409 else if (error == FATFS_RESULT_FAILURE)
410 {
411 return FS_RESULT_FAILURE;
412 }
413 else if (error == FATFS_RESULT_UNSUPPORTED)
414 {
415 return FS_RESULT_UNSUPPORTED;
416 }
417 else if (error == FATFS_RESULT_INVALIDPARAM)
418 {
419 return FS_RESULT_INVALID_PARAMETER;
420 }
421 else if (error == FATFS_RESULT_ALREADYDONE)
422 {
423 return FS_RESULT_ALREADY_DONE;
424 }
425 else if (error == FATFS_RESULT_PERMISSIONDENIDED)
426 {
427 return FS_RESULT_PERMISSION_DENIED;
428 }
429 else if (error == FATFS_RESULT_NOMORERESOURCE)
430 {
431 return FS_RESULT_NO_MORE_RESOURCE;
432 }
433 else if (error == FATFS_RESULT_MEDIAFATAL)
434 {
435 return FS_RESULT_MEDIA_FATAL;
436 }
437 else if (error == FATFS_RESULT_NOENTRY)
438 {
439 return FS_RESULT_NO_ENTRY;
440 }
441 else if (error == FATFS_RESULT_MEDIANOTHING)
442 {
443 return FS_RESULT_MEDIA_NOTHING;
444 }
445 else if (error == FATFS_RESULT_MEDIAUNKNOWN)
446 {
447 return FS_RESULT_MEDIA_UNKNOWN;
448 }
449 else if (error == FATFS_RESULT_BADFORMAT)
450 {
451 return FS_RESULT_BAD_FORMAT;
452 }
453 else if (error == FATFS_RESULT_CANCELED)
454 {
455 return FS_RESULT_CANCELED;
456 }
457 else
458 {
459 return FS_RESULT_ERROR;
460 }
461 }
462
463 /*---------------------------------------------------------------------------*
464 Name: FSi_FATFSAsyncDone
465
466 Description: Notifies completion of FATFS asynchronous process.
467
468 Arguments: buffer: Request structure
469
470 Returns: None.
471 *---------------------------------------------------------------------------*/
FSi_FATFSAsyncDone(FATFSRequestBuffer * buffer)472 static void FSi_FATFSAsyncDone(FATFSRequestBuffer *buffer)
473 {
474 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)buffer->userdata;
475 FS_NotifyArchiveAsyncEnd(context->arc, FSi_ConvertError(buffer->header.result));
476 }
477
478 /*---------------------------------------------------------------------------*
479 Name: FSi_FATFS_GetArchiveCaps
480
481 Description: The FS_COMMAND_GETARCHIVECAPS command.
482
483 Arguments: arc: Calling archive
484 caps: Location to save the device capability flag
485
486 Returns: The processing result for the command.
487 *---------------------------------------------------------------------------*/
FSi_FATFS_GetArchiveCaps(FSArchive * arc,u32 * caps)488 static FSResult FSi_FATFS_GetArchiveCaps(FSArchive *arc, u32 *caps)
489 {
490 (void)arc;
491 *caps = FS_ARCHIVE_CAPS_UNICODE;
492 return FS_RESULT_SUCCESS;
493 }
494
495 /*---------------------------------------------------------------------------*
496 Name: FSi_FATFS_GetPathInfo
497
498 Description: The FS_COMMAND_GETPATHINFO command.
499
500 Arguments: arc: Calling archive
501 baseid: Base directory ID (0 for the root)
502 relpath: Path
503 info: Location to save file information
504
505 Returns: The processing result for the command.
506 *---------------------------------------------------------------------------*/
FSi_FATFS_GetPathInfo(FSArchive * arc,u32 baseid,const char * relpath,FSPathInfo * info)507 static FSResult FSi_FATFS_GetPathInfo(FSArchive *arc, u32 baseid, const char *relpath, FSPathInfo *info)
508 {
509 FSResult result = FS_RESULT_ERROR;
510 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
511 FATFSFileInfoW stat[1];
512 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
513 FATFSResultBuffer tls[1];
514 FATFS_RegisterResultBuffer(tls, TRUE);
515 (void)baseid;
516 if (FSi_UsingInvalidCharacterW(path))
517 {
518 result = FS_RESULT_INVALID_PARAMETER;
519 }
520 else if (FATFS_GetFileInfoW(path, stat))
521 {
522 info->attributes = stat->attributes;
523 if ((stat->attributes & FATFS_ATTRIBUTE_DOS_DIRECTORY) != 0)
524 {
525 info->attributes |= FS_ATTRIBUTE_IS_DIRECTORY;
526 }
527 info->filesize = stat->length;
528 FSi_DostimeToFstime(&info->atime, stat->dos_atime);
529 FSi_DostimeToFstime(&info->mtime, stat->dos_mtime);
530 FSi_DostimeToFstime(&info->ctime, stat->dos_ctime);
531 info->id = FS_INVALID_FILE_ID;
532 result = FS_RESULT_SUCCESS;
533 }
534 else
535 {
536 result = FSi_ConvertError(tls->result);
537 }
538 FSi_ReleaseUnicodeBuffer(path);
539 FATFS_RegisterResultBuffer(tls, FALSE);
540 return result;
541 }
542
543 /*---------------------------------------------------------------------------*
544 Name: FSi_FATFS_SetPathInfo
545
546 Description: The FS_COMMAND_SETPATHINFO command.
547
548 Arguments: arc: Calling archive
549 baseid: Base directory ID (0 for the root)
550 relpath: Path
551 info: Storage source of file information
552
553 Returns: The processing result for the command.
554 *---------------------------------------------------------------------------*/
FSi_FATFS_SetPathInfo(FSArchive * arc,u32 baseid,const char * relpath,FSPathInfo * info)555 static FSResult FSi_FATFS_SetPathInfo(FSArchive *arc, u32 baseid, const char *relpath, FSPathInfo *info)
556 {
557 FSResult result = FS_RESULT_ERROR;
558 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
559 FATFSFileInfoW stat[1];
560 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
561 FATFSResultBuffer tls[1];
562 FATFS_RegisterResultBuffer(tls, TRUE);
563 (void)baseid;
564 FSi_FstimeToDostime(&stat->dos_atime, &info->atime);
565 FSi_FstimeToDostime(&stat->dos_mtime, &info->mtime);
566 FSi_FstimeToDostime(&stat->dos_ctime, &info->ctime);
567 stat->attributes = (info->attributes & (FATFS_ATTRIBUTE_DOS_MASK | FATFS_PROPERTY_CTRL_MASK));
568 info->attributes &= ~FATFS_PROPERTY_CTRL_MASK;
569 if (((stat->attributes & FATFS_PROPERTY_CTRL_MASK) != 0) && !FSi_CheckFstime(&info->mtime))
570 {
571 result = FS_RESULT_INVALID_PARAMETER;
572 }
573 else if (FSi_UsingInvalidCharacterW(path))
574 {
575 result = FS_RESULT_INVALID_PARAMETER;
576 }
577 else if (FATFS_SetFileInfoW(path, stat))
578 {
579 result = FS_RESULT_SUCCESS;
580 }
581 else
582 {
583 result = FSi_ConvertError(tls->result);
584 }
585 FSi_ReleaseUnicodeBuffer(path);
586 FATFS_RegisterResultBuffer(tls, FALSE);
587 return result;
588 }
589
590 /*---------------------------------------------------------------------------*
591 Name: FSi_FATFS_CreateFile
592
593 Description: The FATFS_COMMAND_CREATE_FILE command.
594
595 Arguments:
596
597 Returns: The processing result for the command.
598 *---------------------------------------------------------------------------*/
FSi_FATFS_CreateFile(FSArchive * arc,u32 baseid,const char * relpath,u32 permit)599 static FSResult FSi_FATFS_CreateFile(FSArchive *arc, u32 baseid, const char *relpath, u32 permit)
600 {
601 FSResult result = FS_RESULT_ERROR;
602 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
603 char permitstring[16];
604 char *s = permitstring;
605 BOOL tranc = TRUE;
606 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
607 FATFSResultBuffer tls[1];
608 FATFS_RegisterResultBuffer(tls, TRUE);
609 if ((permit & FS_PERMIT_R) != 0)
610 {
611 *s++ = 'r';
612 }
613 if ((permit & FS_PERMIT_W) != 0)
614 {
615 *s++ = 'w';
616 }
617 *s++ = '\0';
618 if (FSi_UsingInvalidCharacterW(path))
619 {
620 result = FS_RESULT_INVALID_PARAMETER;
621 }
622 else if (FATFS_CreateFileW(path, tranc, permitstring))
623 {
624 result = FS_RESULT_SUCCESS;
625 }
626 else
627 {
628 result = FSi_ConvertError(tls->result);
629 }
630 FSi_ReleaseUnicodeBuffer(path);
631 FATFS_RegisterResultBuffer(tls, FALSE);
632 (void)baseid;
633 return result;
634 }
635
636 /*---------------------------------------------------------------------------*
637 Name: FSi_FATFS_DeleteFile
638
639 Description: The FATFS_COMMAND_DELETE_FILE command.
640
641 Arguments:
642
643 Returns: The processing result for the command.
644 *---------------------------------------------------------------------------*/
FSi_FATFS_DeleteFile(FSArchive * arc,u32 baseid,const char * relpath)645 static FSResult FSi_FATFS_DeleteFile(FSArchive *arc, u32 baseid, const char *relpath)
646 {
647 FSResult result = FS_RESULT_ERROR;
648 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
649 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
650 FATFSResultBuffer tls[1];
651 FATFS_RegisterResultBuffer(tls, TRUE);
652 if (FSi_UsingInvalidCharacterW(path))
653 {
654 result = FS_RESULT_INVALID_PARAMETER;
655 }
656 else if (FATFS_DeleteFileW(path))
657 {
658 result = FS_RESULT_SUCCESS;
659 }
660 else
661 {
662 result = FSi_ConvertError(tls->result);
663 }
664 FSi_ReleaseUnicodeBuffer(path);
665 FATFS_RegisterResultBuffer(tls, FALSE);
666 (void)baseid;
667 return result;
668 }
669
670 /*---------------------------------------------------------------------------*
671 Name: FSi_FATFS_RenameFile
672
673 Description: The FATFS_COMMAND_RENAME_FILE command.
674
675 Arguments:
676
677 Returns: The processing result for the command.
678 *---------------------------------------------------------------------------*/
FSi_FATFS_RenameFile(FSArchive * arc,u32 baseid_src,const char * relpath_src,u32 baseid_dst,const char * relpath_dst)679 static FSResult FSi_FATFS_RenameFile(FSArchive *arc, u32 baseid_src, const char *relpath_src, u32 baseid_dst, const char *relpath_dst)
680 {
681 FSResult result = FS_RESULT_ERROR;
682 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
683 u16 *src = FSi_AllocUnicodeFullPath(context, relpath_src);
684 u16 *dst = FSi_AllocUnicodeFullPath(context, relpath_dst);
685 FATFSResultBuffer tls[1];
686 FATFS_RegisterResultBuffer(tls, TRUE);
687 if (FSi_UsingInvalidCharacterW(src))
688 {
689 result = FS_RESULT_INVALID_PARAMETER;
690 }
691 else if (FSi_UsingInvalidCharacterW(dst))
692 {
693 result = FS_RESULT_INVALID_PARAMETER;
694 }
695 else if (FATFS_RenameFileW(src, dst))
696 {
697 result = FS_RESULT_SUCCESS;
698 }
699 else
700 {
701 result = FSi_ConvertError(tls->result);
702 }
703 FSi_ReleaseUnicodeBuffer(src);
704 FSi_ReleaseUnicodeBuffer(dst);
705 FATFS_RegisterResultBuffer(tls, FALSE);
706 (void)baseid_src;
707 (void)baseid_dst;
708 return result;
709 }
710
711 /*---------------------------------------------------------------------------*
712 Name: FSi_FATFS_CreateDirectory
713
714 Description: The FATFS_COMMAND_CREATE_DIRECTORY command.
715
716 Arguments:
717
718 Returns: The processing result for the command.
719 *---------------------------------------------------------------------------*/
FSi_FATFS_CreateDirectory(FSArchive * arc,u32 baseid,const char * relpath,u32 permit)720 static FSResult FSi_FATFS_CreateDirectory(FSArchive *arc, u32 baseid, const char *relpath, u32 permit)
721 {
722 FSResult result = FS_RESULT_ERROR;
723 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
724 char permitstring[16];
725 char *s = permitstring;
726 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
727 FATFSResultBuffer tls[1];
728 FATFS_RegisterResultBuffer(tls, TRUE);
729 if ((permit & FS_PERMIT_R) != 0)
730 {
731 *s++ = 'r';
732 }
733 if ((permit & FS_PERMIT_W) != 0)
734 {
735 *s++ = 'w';
736 }
737 *s++ = '\0';
738 if (FSi_UsingInvalidCharacterW(path))
739 {
740 result = FS_RESULT_INVALID_PARAMETER;
741 }
742 else if (FATFS_CreateDirectoryW(path, permitstring))
743 {
744 result = FS_RESULT_SUCCESS;
745 }
746 else
747 {
748 result = FSi_ConvertError(tls->result);
749 }
750 FSi_ReleaseUnicodeBuffer(path);
751 FATFS_RegisterResultBuffer(tls, FALSE);
752 (void)baseid;
753 return result;
754 }
755
756 /*---------------------------------------------------------------------------*
757 Name: FSi_FATFS_DeleteDirectory
758
759 Description: The FATFS_COMMAND_DELETE_DIRECTORY command.
760
761 Arguments:
762
763 Returns: The processing result for the command.
764 *---------------------------------------------------------------------------*/
FSi_FATFS_DeleteDirectory(FSArchive * arc,u32 baseid,const char * relpath)765 static FSResult FSi_FATFS_DeleteDirectory(FSArchive *arc, u32 baseid, const char *relpath)
766 {
767 FSResult result = FS_RESULT_ERROR;
768 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
769 u16 *path = FSi_AllocUnicodeFullPath(context, relpath);
770 FATFSResultBuffer tls[1];
771 FATFS_RegisterResultBuffer(tls, TRUE);
772 if (FSi_UsingInvalidCharacterW(path))
773 {
774 result = FS_RESULT_INVALID_PARAMETER;
775 }
776 else if (FATFS_DeleteDirectoryW(path))
777 {
778 result = FS_RESULT_SUCCESS;
779 }
780 else
781 {
782 result = FSi_ConvertError(tls->result);
783 }
784 FSi_ReleaseUnicodeBuffer(path);
785 FATFS_RegisterResultBuffer(tls, FALSE);
786 (void)baseid;
787 return result;
788 }
789
790 /*---------------------------------------------------------------------------*
791 Name: FSi_FATFS_RenameDirectory
792
793 Description: The FATFS_COMMAND_RENAME_DIRECTORY command.
794
795 Arguments:
796
797 Returns: The processing result for the command.
798 *---------------------------------------------------------------------------*/
FSi_FATFS_RenameDirectory(FSArchive * arc,u32 baseid_src,const char * relpath_src,u32 baseid_dst,const char * relpath_dst)799 static FSResult FSi_FATFS_RenameDirectory(FSArchive *arc, u32 baseid_src, const char *relpath_src, u32 baseid_dst, const char *relpath_dst)
800 {
801 FSResult result = FS_RESULT_ERROR;
802 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
803 u16 *src = FSi_AllocUnicodeFullPath(context, relpath_src);
804 u16 *dst = FSi_AllocUnicodeFullPath(context, relpath_dst);
805 FATFSResultBuffer tls[1];
806 FATFS_RegisterResultBuffer(tls, TRUE);
807 if (FSi_UsingInvalidCharacterW(src))
808 {
809 result = FS_RESULT_INVALID_PARAMETER;
810 }
811 else if (FSi_UsingInvalidCharacterW(dst))
812 {
813 result = FS_RESULT_INVALID_PARAMETER;
814 }
815 else if (FATFS_RenameDirectoryW(src, dst))
816 {
817 result = FS_RESULT_SUCCESS;
818 }
819 else
820 {
821 result = FSi_ConvertError(tls->result);
822 }
823 FSi_ReleaseUnicodeBuffer(src);
824 FSi_ReleaseUnicodeBuffer(dst);
825 FATFS_RegisterResultBuffer(tls, FALSE);
826 (void)baseid_src;
827 (void)baseid_dst;
828 return result;
829 }
830
831 /*---------------------------------------------------------------------------*
832 Name: FSi_FATFS_GetArchiveResource
833
834 Description: The FATFS_COMMAND_GETARCHIVERESOURCE command.
835
836 Arguments: arc: Calling archive
837 resource: Storage destination of resource information
838
839 Returns: The processing result for the command.
840 *---------------------------------------------------------------------------*/
FSi_FATFS_GetArchiveResource(FSArchive * arc,FSArchiveResource * resource)841 static FSResult FSi_FATFS_GetArchiveResource(FSArchive *arc, FSArchiveResource *resource)
842 {
843 FSResult result = FS_RESULT_ERROR;
844 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
845 u16 *path = FSi_AllocUnicodeFullPath(context, "/");
846 FATFSResultBuffer tls[1];
847 FATFS_RegisterResultBuffer(tls, TRUE);
848 if (FSi_UsingInvalidCharacterW(path))
849 {
850 result = FS_RESULT_INVALID_PARAMETER;
851 }
852 else if (FATFS_GetDriveResourceW(path, context->resource))
853 {
854 resource->totalSize = context->resource->totalSize;
855 resource->availableSize = context->resource->availableSize;
856 resource->maxFileHandles = context->resource->maxFileHandles;
857 resource->currentFileHandles = context->resource->currentFileHandles;
858 resource->maxDirectoryHandles = context->resource->maxDirectoryHandles;
859 resource->currentDirectoryHandles = context->resource->currentDirectoryHandles;
860 // For FAT archives
861 resource->bytesPerSector = context->resource->bytesPerSector;
862 resource->sectorsPerCluster = context->resource->sectorsPerCluster;
863 resource->totalClusters = context->resource->totalClusters;
864 resource->availableClusters = context->resource->availableClusters;
865 result = FS_RESULT_SUCCESS;
866 }
867 else
868 {
869 result = FSi_ConvertError(tls->result);
870 }
871 FSi_ReleaseUnicodeBuffer(path);
872 FATFS_RegisterResultBuffer(tls, FALSE);
873 return result;
874 }
875
876 /*---------------------------------------------------------------------------*
877 Name: FSi_FATFS_OpenFile
878
879 Description: The FS_COMMAND_OPENFILE command.
880
881 Arguments: arc: Calling archive
882 file: Target file
883 baseid: Base directory (0 for the root)
884 path: File path
885 mode: Access mode
886
887 Returns: The processing result for the command.
888 *---------------------------------------------------------------------------*/
FSi_FATFS_OpenFile(FSArchive * arc,FSFile * file,u32 baseid,const char * path,u32 mode)889 static FSResult FSi_FATFS_OpenFile(FSArchive *arc, FSFile *file, u32 baseid, const char *path, u32 mode)
890 {
891 FSResult result = FS_RESULT_ERROR;
892 FATFSFileHandle handle = FATFS_INVALID_HANDLE;
893 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
894 char modestring[16];
895 char *s = modestring;
896 FATFSResultBuffer tls[1];
897 FATFS_RegisterResultBuffer(tls, TRUE);
898 if ((mode & FS_FILEMODE_R) != 0)
899 {
900 *s++ = 'r';
901 if ((mode & FS_FILEMODE_W) != 0)
902 {
903 *s++ = '+';
904 }
905 }
906 else if ((mode & FS_FILEMODE_W) != 0)
907 {
908 *s++ = 'w';
909 }
910 if ((mode & FS_FILEMODE_L) != 0)
911 {
912 *s++ = 'l';
913 }
914 *s++ = '\0';
915 {
916 const u16 *unipath = NULL;
917 u16 *fpath = NULL;
918 // Store Unicode as it is if the Unicode version structure was passed
919 if ((file->stat & FS_FILE_STATUS_UNICODE_MODE) != 0)
920 {
921 unipath = (const u16 *)path;
922 }
923 // If not, store as Shift_JIS version
924 // (However, this is a tentative implementation; in the future, nothing other than the Unicode version will be passed to archives that declare CAPS_UNICODE.)
925 //
926 else
927 {
928 fpath = FSi_AllocUnicodeFullPath(context, path);
929 unipath = fpath;
930 }
931 if (FSi_UsingInvalidCharacterW(unipath))
932 {
933 result = FS_RESULT_INVALID_PARAMETER;
934 }
935 else
936 {
937 handle = FATFS_OpenFileW(unipath, modestring);
938 if (handle != FATFS_INVALID_HANDLE)
939 {
940 FS_SetFileHandle(file, arc, (void*)handle);
941 result = FS_RESULT_SUCCESS;
942 }
943 else
944 {
945 result = FSi_ConvertError(tls->result);
946 }
947 }
948 FSi_ReleaseUnicodeBuffer(fpath);
949 }
950 FATFS_RegisterResultBuffer(tls, FALSE);
951 (void)baseid;
952 return result;
953 }
954
955 /*---------------------------------------------------------------------------*
956 Name: FSi_FATFS_CloseFile
957
958 Description: The FS_COMMAND_CLOSEFILE command.
959
960 Arguments: arc: Calling archive
961 file: Target file
962
963 Returns: The processing result for the command.
964 *---------------------------------------------------------------------------*/
FSi_FATFS_CloseFile(FSArchive * arc,FSFile * file)965 static FSResult FSi_FATFS_CloseFile(FSArchive *arc, FSFile *file)
966 {
967 FSResult result = FS_RESULT_ERROR;
968 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
969 FATFSResultBuffer tls[1];
970 FATFS_RegisterResultBuffer(tls, TRUE);
971 if (FATFS_CloseFile(handle))
972 {
973 FS_DetachHandle(file);
974 result = FS_RESULT_SUCCESS;
975 }
976 else
977 {
978 result = FSi_ConvertError(tls->result);
979 }
980 FATFS_RegisterResultBuffer(tls, FALSE);
981 (void)arc;
982 return result;
983 }
984
985 /*---------------------------------------------------------------------------*
986 Name: FSi_FATFS_ReadFile
987
988 Description: The FS_COMMAND_READFILE command.
989
990 Arguments: arc: Calling archive
991 file: Target file
992 buffer: Memory to transfer to
993 length: Transfer size
994
995 Returns: The processing result for the command.
996 *---------------------------------------------------------------------------*/
FSi_FATFS_ReadFile(FSArchive * arc,FSFile * file,void * buffer,u32 * length)997 static FSResult FSi_FATFS_ReadFile(FSArchive *arc, FSFile *file, void *buffer, u32 *length)
998 {
999 FSResult result = FS_RESULT_SUCCESS;
1000 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
1001 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1002 u32 rest = *length;
1003 BOOL async = ((file->stat & FS_FILE_STATUS_BLOCKING) == 0);
1004 FATFSResultBuffer tls[1];
1005 FATFS_RegisterResultBuffer(tls, TRUE);
1006 while (rest > 0)
1007 {
1008 void *dst = buffer;
1009 u32 len = rest;
1010 int read;
1011 // If the ARM7 cannot directly access the specified memory, substitute it with a temporary buffer
1012 if (!FSi_IsValidAddressForARM7(buffer, rest))
1013 {
1014 dst = context->tmpbuf;
1015 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1016 }
1017 // If the specified memory is not 32-byte aligned, substitute it with a temporary buffer
1018 else if ((((u32)buffer | len) & 31) != 0)
1019 {
1020 // No special adjustment is needed if the next transfer is the last
1021 if (len <= FS_TMPBUF_LENGTH)
1022 {
1023 dst = context->tmpbuf;
1024 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1025 }
1026 // If the start of the buffer is not aligned, align it with the next transfer
1027 else if (((u32)buffer & 31) != 0)
1028 {
1029 dst = context->tmpbuf;
1030 len = MATH_ROUNDUP((u32)buffer, 32) - (u32)buffer;
1031 }
1032 // If only the transfer size is not aligned, truncate the end and transfer directly
1033 else
1034 {
1035 len = MATH_ROUNDDOWN(len, 32);
1036 }
1037 }
1038 // Even if a temporary buffer is not used, write back a dirty cache for main memory
1039 //
1040 if ((dst == buffer) &&
1041 (((u32)dst >= HW_TWL_MAIN_MEM) && ((u32)dst + len <= HW_TWL_MAIN_MEM_END)))
1042 {
1043 DC_FlushRange(dst, len);
1044 }
1045 // If an asynchronous process was requested and an asynchronous process is actually possible
1046 // Set a request buffer here
1047 async &= ((dst == buffer) && (len == rest));
1048 if (async)
1049 {
1050 FATFSi_SetRequestBuffer(&FSiFATFSAsyncRequest[context - FSiFATFSDrive], FSi_FATFSAsyncDone, context);
1051 }
1052 // Actually call
1053 read = FATFS_ReadFile(handle, dst, (int)len);
1054 if (async)
1055 {
1056 rest -= len;
1057 result = FS_RESULT_PROC_ASYNC;
1058 break;
1059 }
1060 // If switched with the temporary buffer, copy here
1061 if ((dst != buffer) && (read > 0))
1062 {
1063 DC_InvalidateRange(dst, (u32)read);
1064 MI_CpuCopy8(dst, buffer, (u32)read);
1065 }
1066 buffer = (u8 *)buffer + read;
1067 rest -= read;
1068 if (read != len)
1069 {
1070 result = FSi_ConvertError(tls->result);
1071 break;
1072 }
1073 }
1074 *length -= rest;
1075 FATFS_RegisterResultBuffer(tls, FALSE);
1076 return result;
1077 }
1078
1079 /*---------------------------------------------------------------------------*
1080 Name: FSi_FATFS_WriteFile
1081
1082 Description: The FS_COMMAND_WRITEFILE command.
1083
1084 Arguments: arc: Calling archive
1085 file: Target file
1086 buffer: Memory to transfer from
1087 length: Transfer size
1088
1089 Returns: The processing result for the command.
1090 *---------------------------------------------------------------------------*/
FSi_FATFS_WriteFile(FSArchive * arc,FSFile * file,const void * buffer,u32 * length)1091 static FSResult FSi_FATFS_WriteFile(FSArchive *arc, FSFile *file, const void *buffer, u32 *length)
1092 {
1093 FSResult result = FS_RESULT_SUCCESS;
1094 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
1095 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1096 u32 rest = *length;
1097 BOOL async = ((file->stat & FS_FILE_STATUS_BLOCKING) == 0);
1098 FATFSResultBuffer tls[1];
1099 FATFS_RegisterResultBuffer(tls, TRUE);
1100 while (rest > 0)
1101 {
1102 // If the ARM7 cannot directly access the specified memory, substitute it with a temporary buffer
1103 const void *dst = buffer;
1104 u32 len = rest;
1105 int written;
1106 if (!FSi_IsValidAddressForARM7(buffer, rest) || ((((u32)buffer | len) & 31) != 0))
1107 {
1108 dst = context->tmpbuf;
1109 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1110 }
1111 // If the specified memory is not 32-byte aligned, substitute it with a temporary buffer
1112 else if ((((u32)buffer | len) & 31) != 0)
1113 {
1114 // No special adjustment is needed if the next transfer is the last
1115 if (len <= FS_TMPBUF_LENGTH)
1116 {
1117 dst = context->tmpbuf;
1118 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1119 }
1120 // If the start of the buffer is not aligned, align it with the next transfer
1121 else if (((u32)buffer & 31) != 0)
1122 {
1123 dst = context->tmpbuf;
1124 len = MATH_ROUNDUP((u32)buffer, 32) - (u32)buffer;
1125 }
1126 // If only the transfer size is not aligned, truncate the end and transfer directly
1127 else
1128 {
1129 len = MATH_ROUNDDOWN(len, 32);
1130 }
1131 }
1132 // If a temporary buffer is used, copy data that should be written
1133 if (dst != buffer)
1134 {
1135 MI_CpuCopy8(buffer, context->tmpbuf, len);
1136 }
1137 // If the buffer is in main memory, data write-back is necessary to make it visible from the ARM7
1138 if (((u32)dst >= HW_TWL_MAIN_MEM) && ((u32)dst + len <= HW_TWL_MAIN_MEM_END))
1139 {
1140 DC_StoreRange(dst, len);
1141 }
1142 // If an asynchronous process was requested and an asynchronous process is actually possible
1143 // Set a request buffer here
1144 async &= ((dst == buffer) && (len == rest));
1145 if (async)
1146 {
1147 FATFSi_SetRequestBuffer(&FSiFATFSAsyncRequest[context - FSiFATFSDrive], FSi_FATFSAsyncDone, context);
1148 }
1149 // Actually call
1150 written = FATFS_WriteFile(handle, dst, (int)len);
1151 if (async)
1152 {
1153 rest -= len;
1154 result = FS_RESULT_PROC_ASYNC;
1155 break;
1156 }
1157 buffer = (u8 *)buffer + written;
1158 rest -= written;
1159 if (written != len)
1160 {
1161 result = FSi_ConvertError(tls->result);
1162 break;
1163 }
1164 }
1165 *length -= rest;
1166 FATFS_RegisterResultBuffer(tls, FALSE);
1167 return result;
1168 }
1169
1170 /*---------------------------------------------------------------------------*
1171 Name: FSi_FATFS_SetSeekCache
1172
1173 Description: The FS_COMMAND_SETSEEKCACHE command.
1174
1175 Arguments: arc: Calling archive
1176 file: Target file
1177 buf: Cache buffer
1178 buf_size: Cache buffer size
1179
1180 Returns: The processing result for the command.
1181 *---------------------------------------------------------------------------*/
FSi_FATFS_SetSeekCache(FSArchive * arc,FSFile * file,void * buf,u32 buf_size)1182 static FSResult FSi_FATFS_SetSeekCache(FSArchive *arc, FSFile *file, void* buf, u32 buf_size)
1183 {
1184 FSResult result = FS_RESULT_ERROR;
1185 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1186 FATFSResultBuffer tls[1];
1187 FATFS_RegisterResultBuffer(tls, TRUE);
1188
1189 if ((buf != NULL) &&
1190 (((u32)buf < HW_TWL_MAIN_MEM) || (((u32)buf + buf_size) > HW_TWL_MAIN_MEM_END)))
1191 {
1192 // A buffer that is not in main memory causes a parameter error
1193 result = FS_RESULT_INVALID_PARAMETER;
1194 }
1195 else if ((buf != NULL) && (buf_size < 32))
1196 {
1197 // Fail if memory size is insufficient to share with the ARM7
1198 result = FS_RESULT_FAILURE;
1199 }
1200 else if ((((u32)buf & 31) != 0) && ((buf_size - (32 - ((u32)buf & 31))) < 32))
1201 {
1202 // Also fail if it is too small after being 32-byte aligned
1203 result = FS_RESULT_FAILURE;
1204 }
1205 else
1206 {
1207 void *cache;
1208 u32 cache_size;
1209
1210 if (buf != NULL) {
1211 // Flush this because it may have existed in the cache before being used by this function
1212 DC_FlushRange(buf, buf_size);
1213 }
1214
1215 // Extract a region that is 32-byte aligned to allow sharing with the ARM7
1216 if (((u32)buf & 31) != 0) {
1217 cache = (void *)((u32)buf + (32 - ((u32)buf & 31))); // 32-byte boundary
1218 cache_size = buf_size - (32 - ((u32)buf & 31));
1219 } else {
1220 cache = buf;
1221 cache_size = buf_size;
1222 }
1223 cache_size = cache_size & ~31; // Reduce to 32 bytes
1224
1225 if( FATFS_SetSeekCache(handle, cache, cache_size) != FALSE)
1226 {
1227 result = FS_RESULT_SUCCESS;
1228 }
1229 else
1230 {
1231 result = FSi_ConvertError(tls->result);
1232 }
1233 }
1234 (void)arc;
1235 FATFS_RegisterResultBuffer(tls, FALSE);
1236 return result;
1237 }
1238
1239 /*---------------------------------------------------------------------------*
1240 Name: FSi_FATFS_SeekFile
1241
1242 Description: The FS_COMMAND_SEEKFILE command.
1243
1244 Arguments: arc: Calling archive
1245 file: Target file
1246 offset: Displacement and moved-to position
1247 from: Starting point to seek from
1248
1249 Returns: The processing result for the command.
1250 *---------------------------------------------------------------------------*/
FSi_FATFS_SeekFile(FSArchive * arc,FSFile * file,int * offset,FSSeekFileMode from)1251 static FSResult FSi_FATFS_SeekFile(FSArchive *arc, FSFile *file, int *offset, FSSeekFileMode from)
1252 {
1253 FSResult result = FS_RESULT_ERROR;
1254 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1255 FATFSSeekMode mode = FATFS_SEEK_CUR;
1256 FATFSResultBuffer tls[1];
1257 FATFS_RegisterResultBuffer(tls, TRUE);
1258 if (from == FS_SEEK_SET)
1259 {
1260 mode = FATFS_SEEK_SET;
1261 }
1262 else if (from == FS_SEEK_CUR)
1263 {
1264 mode = FATFS_SEEK_CUR;
1265 }
1266 else if (from == FS_SEEK_END)
1267 {
1268 mode = FATFS_SEEK_END;
1269 }
1270 *offset = FATFS_SeekFile(handle, *offset, mode);
1271 if (*offset >= 0)
1272 {
1273 result = FS_RESULT_SUCCESS;
1274 }
1275 else
1276 {
1277 result = FSi_ConvertError(tls->result);
1278 }
1279 FATFS_RegisterResultBuffer(tls, FALSE);
1280 (void)arc;
1281 return result;
1282 }
1283
1284 /*---------------------------------------------------------------------------*
1285 Name: FSi_FATFS_GetFileLength
1286
1287 Description: The FS_COMMAND_GETFILELENGTH command.
1288
1289 Arguments: arc: Calling archive
1290 file: Target file
1291 length: Location to save the obtained size
1292
1293 Returns: The processing result for the command.
1294 *---------------------------------------------------------------------------*/
FSi_FATFS_GetFileLength(FSArchive * arc,FSFile * file,u32 * length)1295 static FSResult FSi_FATFS_GetFileLength(FSArchive *arc, FSFile *file, u32 *length)
1296 {
1297 FSResult result = FS_RESULT_ERROR;
1298 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1299 int n = FATFS_GetFileLength(handle);
1300 FATFSResultBuffer tls[1];
1301 FATFS_RegisterResultBuffer(tls, TRUE);
1302 if (n >= 0)
1303 {
1304 *length = (u32)n;
1305 result = FS_RESULT_SUCCESS;
1306 }
1307 else
1308 {
1309 result = FSi_ConvertError(tls->result);
1310 }
1311 FATFS_RegisterResultBuffer(tls, FALSE);
1312 (void)arc;
1313 return result;
1314 }
1315
1316 /*---------------------------------------------------------------------------*
1317 Name: FSi_FATFS_SetFileLength
1318
1319 Description: The FS_COMMAND_SETFILELENGTH command.
1320
1321 Arguments: arc: Calling archive
1322 file: Target file
1323 length: File size to be set
1324
1325 Returns: The processing result for the command.
1326 *---------------------------------------------------------------------------*/
FSi_FATFS_SetFileLength(FSArchive * arc,FSFile * file,u32 length)1327 static FSResult FSi_FATFS_SetFileLength(FSArchive *arc, FSFile *file, u32 length)
1328 {
1329 FSResult result = FS_RESULT_ERROR;
1330 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1331 FATFSResultBuffer tls[1];
1332 FATFS_RegisterResultBuffer(tls, TRUE);
1333 if (FATFS_SetFileLength(handle, (int)length))
1334 {
1335 result = FS_RESULT_SUCCESS;
1336 }
1337 else
1338 {
1339 result = FSi_ConvertError(tls->result);
1340 }
1341 FATFS_RegisterResultBuffer(tls, FALSE);
1342 (void)arc;
1343 return result;
1344 }
1345
1346 /*---------------------------------------------------------------------------*
1347 Name: FSi_FATFS_GetFilePosition
1348
1349 Description: The FS_COMMAND_GETFILEPOSITION command.
1350
1351 Arguments: arc: Calling archive
1352 file: Target file
1353 position: Location to store the obtained position
1354
1355 Returns: The processing result for the command.
1356 *---------------------------------------------------------------------------*/
FSi_FATFS_GetFilePosition(FSArchive * arc,FSFile * file,u32 * position)1357 static FSResult FSi_FATFS_GetFilePosition(FSArchive *arc, FSFile *file, u32 *position)
1358 {
1359 *position = 0;
1360 return FSi_FATFS_SeekFile(arc, file, (int*)position, FS_SEEK_CUR);
1361 }
1362
1363 /*---------------------------------------------------------------------------*
1364 Name: FSi_FATFS_FlushFile
1365
1366 Description: The FS_COMMAND_FLUSHFILE command.
1367
1368 Arguments: arc: Calling archive
1369 file: Target file
1370
1371 Returns: The processing result for the command.
1372 *---------------------------------------------------------------------------*/
FSi_FATFS_FlushFile(FSArchive * arc,FSFile * file)1373 static FSResult FSi_FATFS_FlushFile(FSArchive *arc, FSFile *file)
1374 {
1375 FSResult result = FS_RESULT_ERROR;
1376 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1377 FATFSResultBuffer tls[1];
1378 FATFS_RegisterResultBuffer(tls, TRUE);
1379 if (FATFS_FlushFile(handle))
1380 {
1381 result = FS_RESULT_SUCCESS;
1382 }
1383 else
1384 {
1385 result = FSi_ConvertError(tls->result);
1386 }
1387 FATFS_RegisterResultBuffer(tls, FALSE);
1388 (void)arc;
1389 return result;
1390 }
1391
1392 /*---------------------------------------------------------------------------*
1393 Name: FSi_FATFS_OpenDirectory
1394
1395 Description: The FS_COMMAND_OPENDIRECTORY command.
1396
1397 Arguments: arc: Calling archive
1398 file: Target file
1399 baseid: Base directory ID (0 for the root)
1400 path: Path
1401 mode: Access mode
1402
1403 Returns: The processing result for the command.
1404 *---------------------------------------------------------------------------*/
FSi_FATFS_OpenDirectory(FSArchive * arc,FSFile * file,u32 baseid,const char * path,u32 mode)1405 static FSResult FSi_FATFS_OpenDirectory(FSArchive *arc, FSFile *file, u32 baseid, const char *path, u32 mode)
1406 {
1407 FSResult result = FS_RESULT_ERROR;
1408 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
1409 FATFSDirectoryHandle handle = FATFS_INVALID_HANDLE;
1410 char modestring[16];
1411 char *s = modestring;
1412 FATFSResultBuffer tls[1];
1413 FATFS_RegisterResultBuffer(tls, TRUE);
1414 if ((mode & FS_FILEMODE_R) != 0)
1415 {
1416 *s++ = 'r';
1417 }
1418 if ((mode & FS_FILEMODE_W) != 0)
1419 {
1420 *s++ = 'w';
1421 }
1422 if ((mode & FS_DIRMODE_SHORTNAME_ONLY) != 0)
1423 {
1424 *s++ = 's';
1425 }
1426 *s++ = '\0';
1427 {
1428 u16 *unipath = NULL;
1429 u16 *fpath = NULL;
1430 // Store Unicode as it is if the Unicode version structure was passed
1431 if ((file->stat & FS_FILE_STATUS_UNICODE_MODE) != 0)
1432 {
1433 unipath = (u16 *)path;
1434 }
1435 // If not, store as Shift_JIS version
1436 // (However, this is a tentative implementation; in the future, nothing other than the Unicode version will be passed to archives that declare CAPS_UNICODE.)
1437 //
1438 else
1439 {
1440 fpath = FSi_AllocUnicodeFullPath(context, path);
1441 unipath = fpath;
1442 }
1443 // Disable last special wildcard specifications
1444 // Because the path always normalizes and passes the FS library, the possibility of changes to the buffer content is guaranteed.
1445 //
1446 if (*unipath)
1447 {
1448 int pos;
1449 for (pos = 0; unipath[pos]; ++pos)
1450 {
1451 }
1452 for (--pos; (pos > 0) && (unipath[pos] == L'*'); --pos)
1453 {
1454 }
1455 if (unipath[pos] != L'/')
1456 {
1457 unipath[++pos] = L'/';
1458 }
1459 unipath[++pos] = L'*';
1460 unipath[++pos] = L'\0';
1461 }
1462 handle = FATFS_OpenDirectoryW(unipath, modestring);
1463 if (handle != FATFS_INVALID_HANDLE)
1464 {
1465 FS_SetDirectoryHandle(file, arc, (void*)handle);
1466 result = FS_RESULT_SUCCESS;
1467 }
1468 else
1469 {
1470 result = FSi_ConvertError(tls->result);
1471 }
1472 FSi_ReleaseUnicodeBuffer(fpath);
1473 }
1474 FATFS_RegisterResultBuffer(tls, FALSE);
1475 (void)baseid;
1476 return result;
1477 }
1478
1479 /*---------------------------------------------------------------------------*
1480 Name: FSi_FATFS_CloseDirectory
1481
1482 Description: The FS_COMMAND_CLOSEDIRECTORY command.
1483
1484 Arguments: arc: Calling archive
1485 file: Target file
1486
1487 Returns: The processing result for the command.
1488 *---------------------------------------------------------------------------*/
FSi_FATFS_CloseDirectory(FSArchive * arc,FSFile * file)1489 static FSResult FSi_FATFS_CloseDirectory(FSArchive *arc, FSFile *file)
1490 {
1491 FSResult result = FS_RESULT_ERROR;
1492 FATFSDirectoryHandle handle = (FATFSDirectoryHandle)FS_GetFileUserData(file);
1493 FATFSResultBuffer tls[1];
1494 FATFS_RegisterResultBuffer(tls, TRUE);
1495 if (FATFS_CloseDirectory(handle))
1496 {
1497 FS_DetachHandle(file);
1498 result = FS_RESULT_SUCCESS;
1499 }
1500 else
1501 {
1502 result = FSi_ConvertError(tls->result);
1503 }
1504 FATFS_RegisterResultBuffer(tls, FALSE);
1505 (void)arc;
1506 return result;
1507 }
1508
1509 /*---------------------------------------------------------------------------*
1510 Name: FSi_FATFS_ReadDirectory
1511
1512 Description: The FS_COMMAND_READDIR command.
1513
1514 Arguments: arc: Calling archive
1515 file: Target file
1516 info: Location to store the information
1517
1518 Returns: The processing result for the command.
1519 *---------------------------------------------------------------------------*/
FSi_FATFS_ReadDirectory(FSArchive * arc,FSFile * file,FSDirectoryEntryInfo * info)1520 static FSResult FSi_FATFS_ReadDirectory(FSArchive *arc, FSFile *file, FSDirectoryEntryInfo *info)
1521 {
1522 FSResult result = FS_RESULT_ERROR;
1523 FATFSDirectoryHandle handle = (FATFSDirectoryHandle)FS_GetFileUserData(file);
1524 FATFSFileInfoW tmp[1];
1525 FATFSResultBuffer tls[1];
1526 FATFS_RegisterResultBuffer(tls, TRUE);
1527 if (FATFS_ReadDirectoryW(handle, tmp))
1528 {
1529 // Store Unicode as is if the Unicode version structure was passed
1530 if ((file->stat & FS_FILE_STATUS_UNICODE_MODE) != 0)
1531 {
1532 FSDirectoryEntryInfoW *infow = (FSDirectoryEntryInfoW *)info;
1533 infow->shortname_length = (u32)STD_GetStringLength(tmp->shortname);
1534 (void)STD_CopyLString(infow->shortname, tmp->shortname, sizeof(infow->shortname));
1535 {
1536 int n;
1537 for (n = 0; (n < FS_ENTRY_LONGNAME_MAX - 1) && tmp->longname[n]; ++n)
1538 {
1539 infow->longname[n] = tmp->longname[n];
1540 }
1541 infow->longname[n] = L'\0';
1542 infow->longname_length = (u32)n;
1543 }
1544 infow->attributes = tmp->attributes;
1545 if ((tmp->attributes & FATFS_ATTRIBUTE_DOS_DIRECTORY) != 0)
1546 {
1547 infow->attributes |= FS_ATTRIBUTE_IS_DIRECTORY;
1548 }
1549 infow->filesize = tmp->length;
1550 FSi_DostimeToFstime(&infow->atime, tmp->dos_atime);
1551 FSi_DostimeToFstime(&infow->mtime, tmp->dos_mtime);
1552 FSi_DostimeToFstime(&infow->ctime, tmp->dos_ctime);
1553 }
1554 // If not, store as Shift_JIS version
1555 // (However, this is a tentative implementation; in the future, nothing other than the Unicode version will be passed to archives that declare CAPS_UNICODE.)
1556 //
1557 else
1558 {
1559 FSDirectoryEntryInfo *infoa = (FSDirectoryEntryInfo *)info;
1560 infoa->shortname_length = (u32)STD_GetStringLength(tmp->shortname);
1561 (void)STD_CopyLString(infoa->shortname, tmp->shortname, sizeof(infoa->shortname));
1562 {
1563 int dstlen = sizeof(infoa->longname) - 1;
1564 int srclen = 0;
1565 (void)FSi_ConvertStringUnicodeToSjis(infoa->longname, &dstlen, tmp->longname, NULL, NULL);
1566 infoa->longname[dstlen] = L'\0';
1567 infoa->longname_length = (u32)dstlen;
1568 }
1569 infoa->attributes = tmp->attributes;
1570 if ((tmp->attributes & FATFS_ATTRIBUTE_DOS_DIRECTORY) != 0)
1571 {
1572 infoa->attributes |= FS_ATTRIBUTE_IS_DIRECTORY;
1573 }
1574 infoa->filesize = tmp->length;
1575 FSi_DostimeToFstime(&infoa->atime, tmp->dos_atime);
1576 FSi_DostimeToFstime(&infoa->mtime, tmp->dos_mtime);
1577 FSi_DostimeToFstime(&infoa->ctime, tmp->dos_ctime);
1578 }
1579 result = FS_RESULT_SUCCESS;
1580 }
1581 else
1582 {
1583 result = FSi_ConvertError(tls->result);
1584 }
1585 FATFS_RegisterResultBuffer(tls, FALSE);
1586 (void)arc;
1587 return result;
1588 }
1589
1590 static PMSleepCallbackInfo FSiPreSleepInfo;
1591 static PMExitCallbackInfo FSiPostExitInfo;
FSi_SleepProcedure(void * arg)1592 static void FSi_SleepProcedure(void *arg)
1593 {
1594 (void)arg;
1595 (void)FATFS_FlushAll();
1596 }
1597
FSi_ShutdownProcedure(void * arg)1598 static void FSi_ShutdownProcedure(void *arg)
1599 {
1600 (void)arg;
1601 (void)FATFS_UnmountAll();
1602 }
1603
1604 /*---------------------------------------------------------------------------*
1605 Name: FSi_MountFATFSArchive
1606
1607 Description: Mounts the FATFS archive.
1608
1609 Arguments: None.
1610
1611 Returns: None.
1612 *---------------------------------------------------------------------------*/
FSi_MountFATFSArchive(FSFATFSArchiveContext * context,const char * arcname,u8 * tmpbuf)1613 static void FSi_MountFATFSArchive(FSFATFSArchiveContext *context, const char *arcname, u8 *tmpbuf)
1614 {
1615 static const FSArchiveInterface FSiArchiveFATFSInterface =
1616 {
1617 // Commands that are compatible with the old specifications
1618 FSi_FATFS_ReadFile,
1619 FSi_FATFS_WriteFile,
1620 NULL, // SeekDirectory
1621 FSi_FATFS_ReadDirectory,
1622 NULL, // FindPath
1623 NULL, // GetPath
1624 NULL, // OpenFileFast
1625 NULL, // OpenFileDirect
1626 FSi_FATFS_CloseFile,
1627 NULL, // Activate
1628 NULL, // Idle
1629 NULL, // Suspend
1630 NULL, // Resume
1631 // New commands that are compatible with the old specifications
1632 FSi_FATFS_OpenFile,
1633 FSi_FATFS_SeekFile,
1634 FSi_FATFS_GetFileLength,
1635 FSi_FATFS_GetFilePosition,
1636 // Commands extended by the new specifications (UNSUPPORTED if NULL)
1637 NULL, // Mount
1638 NULL, // Unmount
1639 FSi_FATFS_GetArchiveCaps,
1640 FSi_FATFS_CreateFile,
1641 FSi_FATFS_DeleteFile,
1642 FSi_FATFS_RenameFile,
1643 FSi_FATFS_GetPathInfo,
1644 FSi_FATFS_SetPathInfo,
1645 FSi_FATFS_CreateDirectory,
1646 FSi_FATFS_DeleteDirectory,
1647 FSi_FATFS_RenameDirectory,
1648 FSi_FATFS_GetArchiveResource,
1649 NULL, // 29UL
1650 FSi_FATFS_FlushFile,
1651 FSi_FATFS_SetFileLength,
1652 FSi_FATFS_OpenDirectory,
1653 FSi_FATFS_CloseDirectory,
1654 FSi_FATFS_SetSeekCache,
1655 };
1656 u32 arcnamelen = (u32)STD_GetStringLength(arcname);
1657 context->tmpbuf = tmpbuf;
1658 FS_InitArchive(context->arc);
1659 if (FS_RegisterArchiveName(context->arc, arcname, arcnamelen))
1660 {
1661 (void)FS_MountArchive(context->arc, context, &FSiArchiveFATFSInterface, 0);
1662 }
1663 }
1664
1665 /*---------------------------------------------------------------------------*
1666 Name: FSi_MountDefaultArchives
1667
1668 Description: Mounts the default archive by referencing a startup argument given to IPL.
1669
1670 Arguments: None.
1671
1672 Returns: None.
1673 *---------------------------------------------------------------------------*/
FSi_MountDefaultArchives(void)1674 void FSi_MountDefaultArchives(void)
1675 {
1676 // Wait until FATFS mounts various physical media
1677 FATFS_Init();
1678 FSi_SetupFATBuffers();
1679 // Set the callback to set flash before sleep and before shutdown
1680 FSiPreSleepInfo.callback = FSi_SleepProcedure;
1681 FSiPostExitInfo.callback = FSi_ShutdownProcedure;
1682 PMi_InsertPreSleepCallbackEx(&FSiPreSleepInfo, PM_CALLBACK_PRIORITY_FS);
1683 PMi_InsertPostExitCallbackEx(&FSiPostExitInfo, PM_CALLBACK_PRIORITY_FS);
1684 // Mount to FS only the physical drive that actually has access rights
1685 if (FSiFATFSDrive && FSiTemporaryBuffer)
1686 {
1687 int index = 0;
1688 static const int max = FS_MOUNTDRIVE_MAX;
1689 const char *arcname = FATFSi_GetArcnameList();
1690 while ((index < max) && *arcname)
1691 {
1692 FSi_MountFATFSArchive(&FSiFATFSDrive[index], arcname, &FSiTemporaryBuffer[FS_TMPBUF_LENGTH * index]);
1693 arcname += STD_GetStringLength(arcname) + 1;
1694 ++index;
1695 }
1696 }
1697 }
1698
1699 /*---------------------------------------------------------------------------*
1700 Name: FSi_MountSpecialArchive
1701
1702 Description: Directly mounts a special archive.
1703
1704 Arguments: param: Mounting target
1705 arcname: Archive name to mount
1706 "otherPub" or "otherPrv" can be specified; when NULL is specified, unmount the previous archive
1707
1708 pWork: Work region used for mounting
1709 It is necessary to retain while mounted
1710
1711 Returns: FS_RESULT_SUCCESS if processing was successful.
1712 *---------------------------------------------------------------------------*/
FSi_MountSpecialArchive(u64 param,const char * arcname,FSFATFSArchiveWork * pWork)1713 FSResult FSi_MountSpecialArchive(u64 param, const char *arcname, FSFATFSArchiveWork* pWork)
1714 {
1715 FSResult result = FS_RESULT_ERROR;
1716 FATFSResultBuffer tls[1];
1717 FATFS_RegisterResultBuffer(tls, TRUE);
1718 if (!FATFS_MountSpecial(param, arcname, &pWork->slot))
1719 {
1720 result = FSi_ConvertError(tls->result);
1721 }
1722 else
1723 {
1724 if (arcname && *arcname)
1725 {
1726 FSi_MountFATFSArchive(&pWork->context, arcname, pWork->tmpbuf);
1727 }
1728 else
1729 {
1730 (void)FS_UnmountArchive(pWork->context.arc);
1731 (void)FS_ReleaseArchiveName(pWork->context.arc);
1732 }
1733 result = FS_RESULT_SUCCESS;
1734 }
1735 FATFS_RegisterResultBuffer(tls, FALSE);
1736 return result;
1737 }
1738
1739 /*---------------------------------------------------------------------------*
1740 Name: FSi_FormatSpecialArchive
1741
1742 Description: Formats content of special archive that satisfies the following conditions.
1743 - Currently mounted
1744 - Hold your own ownership rights (dataPub, dataPrv, share*)
1745
1746 Arguments: path: Path name that includes the archive name
1747
1748 Returns: FS_RESULT_SUCCESS if processing was successful.
1749 *---------------------------------------------------------------------------*/
FSi_FormatSpecialArchive(const char * path)1750 FSResult FSi_FormatSpecialArchive(const char *path)
1751 {
1752 FSResult result = FS_RESULT_ERROR;
1753 FATFSResultBuffer tls[1];
1754 FATFS_RegisterResultBuffer(tls, TRUE);
1755 if (!FATFS_FormatSpecial(path))
1756 {
1757 result = FSi_ConvertError(tls->result);
1758 }
1759 else
1760 {
1761 result = FS_RESULT_SUCCESS;
1762 }
1763 FATFS_RegisterResultBuffer(tls, FALSE);
1764 return result;
1765 }
1766
1767
1768 #include <twl/ltdmain_end.h>
1769
1770
1771 #endif /* FS_IMPLEMENT */
1772
1773 #endif /* SDK_TWL */
1774
1775 /*---------------------------------------------------------------------------*
1776 Name: FS_ForceToEnableLatencyEmulation
1777
1778 Description: Pseudo-reproduction of random driver latency generated when accessing a degraded NAND device.
1779
1780
1781 Arguments: None.
1782
1783 Returns: None.
1784 *---------------------------------------------------------------------------*/
FS_ForceToEnableLatencyEmulation(void)1785 void FS_ForceToEnableLatencyEmulation(void)
1786 {
1787 #if defined(SDK_TWL)
1788 if (OS_IsRunOnTwl())
1789 {
1790 (void)FATFS_SetLatencyEmulation(TRUE);
1791 }
1792 #endif
1793 }
1794