1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - FS - libraries
3 File: fs_archive_fatfs.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-02-02#$
14 $Rev: 9950 $
15 $Author: nakayasu_toshiko $
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 With applications built using a special memory arrangment, it is possible to set the proper buffer by changing this variable internally by calling the FSi_SetupFATBuffers function that was over-ridden.
73
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 With applications built using a special memory arrangment, it is possible to set the proper buffer by changing this variable internally by calling the FSi_SetupFATBuffers function that was over-ridden.
89
90
91
92
93 Arguments: None.
94
95 Returns: Static command buffer of the FS_TEMPORARY_BUFFER_MAX byte
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 For applications constructed using a special memory layout, you can change these variables to set the appropriate buffer before calling the FS_Init function.
105
106
107
108
109 Arguments: None.
110
111 Returns: Static command buffer of the FS_TEMPORARY_BUFFER_MAX byte
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 arrangment, it is possible to independently set the various buffers by over-riding 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: WRAM-C slot bit collection
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: The 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: The calling archive
501 baseid: The base directory ID (0 for the root)
502 relpath: The 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: The calling archive
549 baseid: The base directory ID (0 for the root)
550 relpath: The 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: The 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: The calling archive
882 file: The target file
883 baseid: The 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 passsed.
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: The calling archive
961 file: The 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: The calling archive
991 file: The target file
992 buffer: The 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 // Switch with a temporary buffer for any of the following
1009 // (1) Memory was specified that cannot directly be accessed from ARM7
1010 // (2) Specified memory that cannot be 32-bit aligned
1011 void *dst = buffer;
1012 u32 len = rest;
1013 int read;
1014 if (!FSi_IsValidAddressForARM7(buffer, rest) || (((u32)buffer & 31) != 0))
1015 {
1016 dst = context->tmpbuf;
1017 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1018 }
1019 // Even if not so, just in case, write back if it is the content of the main memory
1020 // (Protect other variables that are together in a cache aligned, 32-bit range)
1021 else if (((u32)dst >= HW_TWL_MAIN_MEM) && ((u32)dst + len <= HW_TWL_MAIN_MEM_END))
1022 {
1023 DC_FlushRange(dst, len);
1024 }
1025 // If asynchronous processing was requested and is actually possible configure a request buffer here.
1026 //
1027 async &= ((dst == buffer) && (len == rest));
1028 if (async)
1029 {
1030 FATFSi_SetRequestBuffer(&FSiFATFSAsyncRequest[context - FSiFATFSDrive], FSi_FATFSAsyncDone, context);
1031 }
1032 // Actually call
1033 read = FATFS_ReadFile(handle, dst, (int)len);
1034 if (async)
1035 {
1036 rest -= len;
1037 result = FS_RESULT_PROC_ASYNC;
1038 break;
1039 }
1040 // If switched with the temporary buffer, copy here
1041 if( (dst != buffer)&&(read > 0))
1042 {
1043 DC_InvalidateRange(dst, (u32)read);
1044 MI_CpuCopy8(dst, buffer, (u32)read);
1045 }
1046 buffer = (u8 *)buffer + read;
1047 rest -= read;
1048
1049 if( read != len) {
1050 result = FSi_ConvertError(tls->result);
1051 break;
1052 }
1053 }
1054 *length -= rest;
1055 FATFS_RegisterResultBuffer(tls, FALSE);
1056 return result;
1057 }
1058
1059 /*---------------------------------------------------------------------------*
1060 Name: FSi_FATFS_WriteFile
1061
1062 Description: The FS_COMMAND_WRITEFILE command.
1063
1064 Arguments: arc: The calling archive
1065 file: The target file
1066 buffer: The memory to transfer from
1067 length: Transfer size
1068
1069 Returns: The processing result for the command.
1070 *---------------------------------------------------------------------------*/
FSi_FATFS_WriteFile(FSArchive * arc,FSFile * file,const void * buffer,u32 * length)1071 static FSResult FSi_FATFS_WriteFile(FSArchive *arc, FSFile *file, const void *buffer, u32 *length)
1072 {
1073 FSResult result = FS_RESULT_SUCCESS;
1074 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
1075 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1076 u32 rest = *length;
1077 BOOL async = ((file->stat & FS_FILE_STATUS_BLOCKING) == 0);
1078 FATFSResultBuffer tls[1];
1079 FATFS_RegisterResultBuffer(tls, TRUE);
1080 while (rest > 0)
1081 {
1082 // Switch with a temporary buffer for any of the following
1083 // (1) Memory was specified that cannot directly be accessed from ARM7
1084 // (2) Specified memory that cannot be 32-bit aligned
1085 const void *dst = buffer;
1086 u32 len = rest;
1087 int written;
1088 if (!FSi_IsValidAddressForARM7(buffer, rest) || (((u32)buffer & 31) != 0))
1089 {
1090 dst = context->tmpbuf;
1091 len = (u32)MATH_MIN(len, FS_TMPBUF_LENGTH);
1092 MI_CpuCopy8(buffer, context->tmpbuf, len);
1093 DC_StoreRange(context->tmpbuf, len);
1094 }
1095 // Even if not so, just in case, write back if it is the content of the main memory
1096 // (Protect other variables that are together in a cache aligned, 32-bit range)
1097 else if (((u32)dst >= HW_TWL_MAIN_MEM) && ((u32)dst + len <= HW_TWL_MAIN_MEM_END))
1098 {
1099 DC_StoreRange(dst, len);
1100 }
1101 // If asynchronous processing was requested and is actually possible configure a request buffer here.
1102 //
1103 async &= ((dst == buffer) && (len == rest));
1104 if (async)
1105 {
1106 FATFSi_SetRequestBuffer(&FSiFATFSAsyncRequest[context - FSiFATFSDrive], FSi_FATFSAsyncDone, context);
1107 }
1108 // Actually call
1109 written = FATFS_WriteFile(handle, dst, (int)len);
1110 if (async)
1111 {
1112 rest -= len;
1113 result = FS_RESULT_PROC_ASYNC;
1114 break;
1115 }
1116 buffer = (u8 *)buffer + written;
1117 rest -= written;
1118
1119 if( written != len) {
1120 result = FSi_ConvertError(tls->result);
1121 break;
1122 }
1123 }
1124 *length -= rest;
1125 FATFS_RegisterResultBuffer(tls, FALSE);
1126 return result;
1127 }
1128
1129 /*---------------------------------------------------------------------------*
1130 Name: FSi_FATFS_SetSeekCache
1131
1132 Description: The FS_COMMAND_SETSEEKCACHE command.
1133
1134 Arguments: arc: The calling archive
1135 file: The target file
1136 buf: Cache buffer
1137 buf_size: Cache buffer size
1138
1139 Returns: The processing result for the command.
1140 *---------------------------------------------------------------------------*/
FSi_FATFS_SetSeekCache(FSArchive * arc,FSFile * file,void * buf,u32 buf_size)1141 static FSResult FSi_FATFS_SetSeekCache(FSArchive *arc, FSFile *file, void* buf, u32 buf_size)
1142 {
1143 FSResult result = FS_RESULT_ERROR;
1144 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1145 FATFSResultBuffer tls[1];
1146 FATFS_RegisterResultBuffer(tls, TRUE);
1147
1148 if ((buf != NULL) &&
1149 (((u32)buf < HW_TWL_MAIN_MEM) || (((u32)buf + buf_size) > HW_TWL_MAIN_MEM_END)))
1150 {
1151 // A buffer that is not in main memory causes a parameter error
1152 result = FS_RESULT_INVALID_PARAMETER;
1153 }
1154 else if ((buf != NULL) && (buf_size < 32))
1155 {
1156 // Fail if memory size is inssuficient to share with the ARM7.
1157 result = FS_RESULT_FAILURE;
1158 }
1159 else if ((((u32)buf & 31) != 0) && ((buf_size - (32 - ((u32)buf & 31))) < 32))
1160 {
1161 // Also fail if it is too small after being 32-byte aligned
1162 result = FS_RESULT_FAILURE;
1163 }
1164 else
1165 {
1166 void *cache;
1167 u32 cache_size;
1168
1169 if (buf != NULL) {
1170 // Flush this because it may have existed in the cache before being used by this function
1171 DC_FlushRange(buf, buf_size);
1172 }
1173
1174 // Extract a region that is 32-byte aligned to allow sharing with the ARM7
1175 if (((u32)buf & 31) != 0) {
1176 cache = (void *)((u32)buf + (32 - ((u32)buf & 31))); // 32-byte boundary
1177 cache_size = buf_size - (32 - ((u32)buf & 31));
1178 } else {
1179 cache = buf;
1180 cache_size = buf_size;
1181 }
1182 cache_size = cache_size & ~31; // Reduce to 32 bytes
1183
1184 if( FATFS_SetSeekCache(handle, cache, cache_size) != FALSE)
1185 {
1186 result = FS_RESULT_SUCCESS;
1187 }
1188 else
1189 {
1190 result = FSi_ConvertError(tls->result);
1191 }
1192 }
1193 (void)arc;
1194 FATFS_RegisterResultBuffer(tls, FALSE);
1195 return result;
1196 }
1197
1198 /*---------------------------------------------------------------------------*
1199 Name: FSi_FATFS_SeekFile
1200
1201 Description: The FS_COMMAND_SEEKFILE command.
1202
1203 Arguments: arc: The calling archive
1204 file: The target file
1205 offset: The displacement and moved-to position
1206 from: The starting point to seek from
1207
1208 Returns: The processing result for the command.
1209 *---------------------------------------------------------------------------*/
FSi_FATFS_SeekFile(FSArchive * arc,FSFile * file,int * offset,FSSeekFileMode from)1210 static FSResult FSi_FATFS_SeekFile(FSArchive *arc, FSFile *file, int *offset, FSSeekFileMode from)
1211 {
1212 FSResult result = FS_RESULT_ERROR;
1213 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1214 FATFSSeekMode mode = FATFS_SEEK_CUR;
1215 FATFSResultBuffer tls[1];
1216 FATFS_RegisterResultBuffer(tls, TRUE);
1217 if (from == FS_SEEK_SET)
1218 {
1219 mode = FATFS_SEEK_SET;
1220 }
1221 else if (from == FS_SEEK_CUR)
1222 {
1223 mode = FATFS_SEEK_CUR;
1224 }
1225 else if (from == FS_SEEK_END)
1226 {
1227 mode = FATFS_SEEK_END;
1228 }
1229 *offset = FATFS_SeekFile(handle, *offset, mode);
1230 if (*offset >= 0)
1231 {
1232 result = FS_RESULT_SUCCESS;
1233 }
1234 else
1235 {
1236 result = FSi_ConvertError(tls->result);
1237 }
1238 FATFS_RegisterResultBuffer(tls, FALSE);
1239 (void)arc;
1240 return result;
1241 }
1242
1243 /*---------------------------------------------------------------------------*
1244 Name: FSi_FATFS_GetFileLength
1245
1246 Description: The FS_COMMAND_GETFILELENGTH command.
1247
1248 Arguments: arc: The calling archive
1249 file: The target file
1250 length: Location to save the obtained size
1251
1252 Returns: The processing result for the command.
1253 *---------------------------------------------------------------------------*/
FSi_FATFS_GetFileLength(FSArchive * arc,FSFile * file,u32 * length)1254 static FSResult FSi_FATFS_GetFileLength(FSArchive *arc, FSFile *file, u32 *length)
1255 {
1256 FSResult result = FS_RESULT_ERROR;
1257 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1258 int n = FATFS_GetFileLength(handle);
1259 FATFSResultBuffer tls[1];
1260 FATFS_RegisterResultBuffer(tls, TRUE);
1261 if (n >= 0)
1262 {
1263 *length = (u32)n;
1264 result = FS_RESULT_SUCCESS;
1265 }
1266 else
1267 {
1268 result = FSi_ConvertError(tls->result);
1269 }
1270 FATFS_RegisterResultBuffer(tls, FALSE);
1271 (void)arc;
1272 return result;
1273 }
1274
1275 /*---------------------------------------------------------------------------*
1276 Name: FSi_FATFS_SetFileLength
1277
1278 Description: The FS_COMMAND_SETFILELENGTH command.
1279
1280 Arguments: arc: The calling archive
1281 file: The target file
1282 length: File size to be set
1283
1284 Returns: The processing result for the command.
1285 *---------------------------------------------------------------------------*/
FSi_FATFS_SetFileLength(FSArchive * arc,FSFile * file,u32 length)1286 static FSResult FSi_FATFS_SetFileLength(FSArchive *arc, FSFile *file, u32 length)
1287 {
1288 FSResult result = FS_RESULT_ERROR;
1289 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1290 FATFSResultBuffer tls[1];
1291 FATFS_RegisterResultBuffer(tls, TRUE);
1292 if (FATFS_SetFileLength(handle, (int)length))
1293 {
1294 result = FS_RESULT_SUCCESS;
1295 }
1296 else
1297 {
1298 result = FSi_ConvertError(tls->result);
1299 }
1300 FATFS_RegisterResultBuffer(tls, FALSE);
1301 (void)arc;
1302 return result;
1303 }
1304
1305 /*---------------------------------------------------------------------------*
1306 Name: FSi_FATFS_GetFilePosition
1307
1308 Description: The FS_COMMAND_GETFILEPOSITION command.
1309
1310 Arguments: arc: The calling archive
1311 file: The target file
1312 position: Location to store the obtained position
1313
1314 Returns: The processing result for the command.
1315 *---------------------------------------------------------------------------*/
FSi_FATFS_GetFilePosition(FSArchive * arc,FSFile * file,u32 * position)1316 static FSResult FSi_FATFS_GetFilePosition(FSArchive *arc, FSFile *file, u32 *position)
1317 {
1318 *position = 0;
1319 return FSi_FATFS_SeekFile(arc, file, (int*)position, FS_SEEK_CUR);
1320 }
1321
1322 /*---------------------------------------------------------------------------*
1323 Name: FSi_FATFS_FlushFile
1324
1325 Description: The FS_COMMAND_FLUSHFILE command.
1326
1327 Arguments: arc: The calling archive
1328 file: The target file
1329
1330 Returns: The processing result for the command.
1331 *---------------------------------------------------------------------------*/
FSi_FATFS_FlushFile(FSArchive * arc,FSFile * file)1332 static FSResult FSi_FATFS_FlushFile(FSArchive *arc, FSFile *file)
1333 {
1334 FSResult result = FS_RESULT_ERROR;
1335 FATFSFileHandle handle = (FATFSFileHandle)FS_GetFileUserData(file);
1336 FATFSResultBuffer tls[1];
1337 FATFS_RegisterResultBuffer(tls, TRUE);
1338 if (FATFS_FlushFile(handle))
1339 {
1340 result = FS_RESULT_SUCCESS;
1341 }
1342 else
1343 {
1344 result = FSi_ConvertError(tls->result);
1345 }
1346 FATFS_RegisterResultBuffer(tls, FALSE);
1347 (void)arc;
1348 return result;
1349 }
1350
1351 /*---------------------------------------------------------------------------*
1352 Name: FSi_FATFS_OpenDirectory
1353
1354 Description: The FS_COMMAND_OPENDIRECTORY command.
1355
1356 Arguments: arc: The calling archive
1357 file: The target file
1358 baseid: The base directory ID (0 for the root)
1359 path: The path
1360 mode: Access mode
1361
1362 Returns: The processing result for the command.
1363 *---------------------------------------------------------------------------*/
FSi_FATFS_OpenDirectory(FSArchive * arc,FSFile * file,u32 baseid,const char * path,u32 mode)1364 static FSResult FSi_FATFS_OpenDirectory(FSArchive *arc, FSFile *file, u32 baseid, const char *path, u32 mode)
1365 {
1366 FSResult result = FS_RESULT_ERROR;
1367 FSFATFSArchiveContext *context = (FSFATFSArchiveContext *)FS_GetArchiveUserData(arc);
1368 FATFSDirectoryHandle handle = FATFS_INVALID_HANDLE;
1369 char modestring[16];
1370 char *s = modestring;
1371 FATFSResultBuffer tls[1];
1372 FATFS_RegisterResultBuffer(tls, TRUE);
1373 if ((mode & FS_FILEMODE_R) != 0)
1374 {
1375 *s++ = 'r';
1376 }
1377 if ((mode & FS_FILEMODE_W) != 0)
1378 {
1379 *s++ = 'w';
1380 }
1381 if ((mode & FS_DIRMODE_SHORTNAME_ONLY) != 0)
1382 {
1383 *s++ = 's';
1384 }
1385 *s++ = '\0';
1386 {
1387 u16 *unipath = NULL;
1388 u16 *fpath = NULL;
1389 // Store Unicode as it is if the Unicode version structure was passsed.
1390 if ((file->stat & FS_FILE_STATUS_UNICODE_MODE) != 0)
1391 {
1392 unipath = (u16 *)path;
1393 }
1394 // If not, store as Shift_JIS version
1395 // (However, this is a tentative implementation; in the future, nothing other than the Unicode version will be passed to archives that declare CAPS_UNICODE.)
1396 //
1397 else
1398 {
1399 fpath = FSi_AllocUnicodeFullPath(context, path);
1400 unipath = fpath;
1401 }
1402 // Disable last special wildcard specifications
1403 // Because the path always normalizes and passes the FS library, the possibility of changes to the buffer content is guaranteed.
1404 //
1405 if (*unipath)
1406 {
1407 int pos;
1408 for (pos = 0; unipath[pos]; ++pos)
1409 {
1410 }
1411 for (--pos; (pos > 0) && (unipath[pos] == L'*'); --pos)
1412 {
1413 }
1414 if (unipath[pos] != L'/')
1415 {
1416 unipath[++pos] = L'/';
1417 }
1418 unipath[++pos] = L'*';
1419 unipath[++pos] = L'\0';
1420 }
1421 handle = FATFS_OpenDirectoryW(unipath, modestring);
1422 if (handle != FATFS_INVALID_HANDLE)
1423 {
1424 FS_SetDirectoryHandle(file, arc, (void*)handle);
1425 result = FS_RESULT_SUCCESS;
1426 }
1427 else
1428 {
1429 result = FSi_ConvertError(tls->result);
1430 }
1431 FSi_ReleaseUnicodeBuffer(fpath);
1432 }
1433 FATFS_RegisterResultBuffer(tls, FALSE);
1434 (void)baseid;
1435 return result;
1436 }
1437
1438 /*---------------------------------------------------------------------------*
1439 Name: FSi_FATFS_CloseDirectory
1440
1441 Description: The FS_COMMAND_CLOSEDIRECTORY command.
1442
1443 Arguments: arc: The calling archive
1444 file: The target file
1445
1446 Returns: The processing result for the command.
1447 *---------------------------------------------------------------------------*/
FSi_FATFS_CloseDirectory(FSArchive * arc,FSFile * file)1448 static FSResult FSi_FATFS_CloseDirectory(FSArchive *arc, FSFile *file)
1449 {
1450 FSResult result = FS_RESULT_ERROR;
1451 FATFSDirectoryHandle handle = (FATFSDirectoryHandle)FS_GetFileUserData(file);
1452 FATFSResultBuffer tls[1];
1453 FATFS_RegisterResultBuffer(tls, TRUE);
1454 if (FATFS_CloseDirectory(handle))
1455 {
1456 FS_DetachHandle(file);
1457 result = FS_RESULT_SUCCESS;
1458 }
1459 else
1460 {
1461 result = FSi_ConvertError(tls->result);
1462 }
1463 FATFS_RegisterResultBuffer(tls, FALSE);
1464 (void)arc;
1465 return result;
1466 }
1467
1468 /*---------------------------------------------------------------------------*
1469 Name: FSi_FATFS_ReadDirectory
1470
1471 Description: The FS_COMMAND_READDIR command.
1472
1473 Arguments: arc: The calling archive
1474 file: The target file
1475 info: Location to store the information
1476
1477 Returns: The processing result for the command.
1478 *---------------------------------------------------------------------------*/
FSi_FATFS_ReadDirectory(FSArchive * arc,FSFile * file,FSDirectoryEntryInfo * info)1479 static FSResult FSi_FATFS_ReadDirectory(FSArchive *arc, FSFile *file, FSDirectoryEntryInfo *info)
1480 {
1481 FSResult result = FS_RESULT_ERROR;
1482 FATFSDirectoryHandle handle = (FATFSDirectoryHandle)FS_GetFileUserData(file);
1483 FATFSFileInfoW tmp[1];
1484 FATFSResultBuffer tls[1];
1485 FATFS_RegisterResultBuffer(tls, TRUE);
1486 if (FATFS_ReadDirectoryW(handle, tmp))
1487 {
1488 // Store Unicode as it is if the Unicode version structure was passsed.
1489 if ((file->stat & FS_FILE_STATUS_UNICODE_MODE) != 0)
1490 {
1491 FSDirectoryEntryInfoW *infow = (FSDirectoryEntryInfoW *)info;
1492 infow->shortname_length = (u32)STD_GetStringLength(tmp->shortname);
1493 (void)STD_CopyLString(infow->shortname, tmp->shortname, sizeof(infow->shortname));
1494 {
1495 int n;
1496 for (n = 0; (n < FS_ENTRY_LONGNAME_MAX - 1) && tmp->longname[n]; ++n)
1497 {
1498 infow->longname[n] = tmp->longname[n];
1499 }
1500 infow->longname[n] = L'\0';
1501 infow->longname_length = (u32)n;
1502 }
1503 infow->attributes = tmp->attributes;
1504 if ((tmp->attributes & FATFS_ATTRIBUTE_DOS_DIRECTORY) != 0)
1505 {
1506 infow->attributes |= FS_ATTRIBUTE_IS_DIRECTORY;
1507 }
1508 infow->filesize = tmp->length;
1509 FSi_DostimeToFstime(&infow->atime, tmp->dos_atime);
1510 FSi_DostimeToFstime(&infow->mtime, tmp->dos_mtime);
1511 FSi_DostimeToFstime(&infow->ctime, tmp->dos_ctime);
1512 }
1513 // If not, store as Shift_JIS version
1514 // (However, this is a tentative implementation; in the future, nothing other than the Unicode version will be passed to archives that declare CAPS_UNICODE.)
1515 //
1516 else
1517 {
1518 FSDirectoryEntryInfo *infoa = (FSDirectoryEntryInfo *)info;
1519 infoa->shortname_length = (u32)STD_GetStringLength(tmp->shortname);
1520 (void)STD_CopyLString(infoa->shortname, tmp->shortname, sizeof(infoa->shortname));
1521 {
1522 int dstlen = sizeof(infoa->longname) - 1;
1523 int srclen = 0;
1524 (void)FSi_ConvertStringUnicodeToSjis(infoa->longname, &dstlen, tmp->longname, NULL, NULL);
1525 infoa->longname[dstlen] = L'\0';
1526 infoa->longname_length = (u32)dstlen;
1527 }
1528 infoa->attributes = tmp->attributes;
1529 if ((tmp->attributes & FATFS_ATTRIBUTE_DOS_DIRECTORY) != 0)
1530 {
1531 infoa->attributes |= FS_ATTRIBUTE_IS_DIRECTORY;
1532 }
1533 infoa->filesize = tmp->length;
1534 FSi_DostimeToFstime(&infoa->atime, tmp->dos_atime);
1535 FSi_DostimeToFstime(&infoa->mtime, tmp->dos_mtime);
1536 FSi_DostimeToFstime(&infoa->ctime, tmp->dos_ctime);
1537 }
1538 result = FS_RESULT_SUCCESS;
1539 }
1540 else
1541 {
1542 result = FSi_ConvertError(tls->result);
1543 }
1544 FATFS_RegisterResultBuffer(tls, FALSE);
1545 (void)arc;
1546 return result;
1547 }
1548
1549 static PMSleepCallbackInfo FSiPreSleepInfo;
1550 static PMExitCallbackInfo FSiPostExitInfo;
FSi_SleepProcedure(void * arg)1551 static void FSi_SleepProcedure(void *arg)
1552 {
1553 (void)arg;
1554 (void)FATFS_FlushAll();
1555 }
1556
FSi_ShutdownProcedure(void * arg)1557 static void FSi_ShutdownProcedure(void *arg)
1558 {
1559 (void)arg;
1560 (void)FATFS_UnmountAll();
1561 }
1562
1563 /*---------------------------------------------------------------------------*
1564 Name: FSi_MountFATFSArchive
1565
1566 Description: Mounts the FATFS archive.
1567
1568 Arguments: None.
1569
1570 Returns: None.
1571 *---------------------------------------------------------------------------*/
FSi_MountFATFSArchive(FSFATFSArchiveContext * context,const char * arcname,u8 * tmpbuf)1572 static void FSi_MountFATFSArchive(FSFATFSArchiveContext *context, const char *arcname, u8 *tmpbuf)
1573 {
1574 static const FSArchiveInterface FSiArchiveFATFSInterface =
1575 {
1576 // Commands that are compatible with the old specifications
1577 FSi_FATFS_ReadFile,
1578 FSi_FATFS_WriteFile,
1579 NULL, // SeekDirectory
1580 FSi_FATFS_ReadDirectory,
1581 NULL, // FindPath
1582 NULL, // GetPath
1583 NULL, // OpenFileFast
1584 NULL, // OpenFileDirect
1585 FSi_FATFS_CloseFile,
1586 NULL, // Activate
1587 NULL, // Idle
1588 NULL, // Suspend
1589 NULL, // Resume
1590 // New commands that are compatible with the old specifications
1591 FSi_FATFS_OpenFile,
1592 FSi_FATFS_SeekFile,
1593 FSi_FATFS_GetFileLength,
1594 FSi_FATFS_GetFilePosition,
1595 // Command extended by the new specifications (UNSUPPORTED if NULL)
1596 NULL, // Mount
1597 NULL, // Unmount
1598 FSi_FATFS_GetArchiveCaps,
1599 FSi_FATFS_CreateFile,
1600 FSi_FATFS_DeleteFile,
1601 FSi_FATFS_RenameFile,
1602 FSi_FATFS_GetPathInfo,
1603 FSi_FATFS_SetPathInfo,
1604 FSi_FATFS_CreateDirectory,
1605 FSi_FATFS_DeleteDirectory,
1606 FSi_FATFS_RenameDirectory,
1607 FSi_FATFS_GetArchiveResource,
1608 NULL, // 29UL
1609 FSi_FATFS_FlushFile,
1610 FSi_FATFS_SetFileLength,
1611 FSi_FATFS_OpenDirectory,
1612 FSi_FATFS_CloseDirectory,
1613 FSi_FATFS_SetSeekCache,
1614 };
1615 u32 arcnamelen = (u32)STD_GetStringLength(arcname);
1616 context->tmpbuf = tmpbuf;
1617 FS_InitArchive(context->arc);
1618 if (FS_RegisterArchiveName(context->arc, arcname, arcnamelen))
1619 {
1620 (void)FS_MountArchive(context->arc, context, &FSiArchiveFATFSInterface, 0);
1621 }
1622 }
1623
1624 /*---------------------------------------------------------------------------*
1625 Name: FSi_MountDefaultArchives
1626
1627 Description: Mounts the default archive by referencing a startup argument given to IPL.
1628
1629 Arguments: None.
1630
1631 Returns: None.
1632 *---------------------------------------------------------------------------*/
FSi_MountDefaultArchives(void)1633 void FSi_MountDefaultArchives(void)
1634 {
1635 // Wait until FATFS mounts various physical media
1636 FATFS_Init();
1637 FSi_SetupFATBuffers();
1638 // Set the callback to set flash before sleep and before shutdown
1639 FSiPreSleepInfo.callback = FSi_SleepProcedure;
1640 FSiPostExitInfo.callback = FSi_ShutdownProcedure;
1641 PMi_InsertPreSleepCallbackEx(&FSiPreSleepInfo, PM_CALLBACK_PRIORITY_FS);
1642 PMi_InsertPostExitCallbackEx(&FSiPostExitInfo, PM_CALLBACK_PRIORITY_FS);
1643 // Mount to FS only the physical drive that actually has access rights
1644 if (FSiFATFSDrive && FSiTemporaryBuffer)
1645 {
1646 int index = 0;
1647 static const int max = FS_MOUNTDRIVE_MAX;
1648 const char *arcname = FATFSi_GetArcnameList();
1649 while ((index < max) && *arcname)
1650 {
1651 FSi_MountFATFSArchive(&FSiFATFSDrive[index], arcname, &FSiTemporaryBuffer[FS_TMPBUF_LENGTH * index]);
1652 arcname += STD_GetStringLength(arcname) + 1;
1653 ++index;
1654 }
1655 }
1656 }
1657
1658 /*---------------------------------------------------------------------------*
1659 Name: FSi_MountSpecialArchive
1660
1661 Description: Directly mounts a special archive.
1662
1663 Arguments: param: Parameter that specifies the mounting target
1664 arcname: Archive name to mount
1665 "otherPub" or "otherPrv" can be specified; when NULL is specified, unmount the previous archive
1666
1667 pWork: Work region that is used for mounting
1668 It is necessary to retain while mounted
1669
1670 Returns: FS_RESULT_SUCCESS if the processing was successful.
1671 *---------------------------------------------------------------------------*/
FSi_MountSpecialArchive(u64 param,const char * arcname,FSFATFSArchiveWork * pWork)1672 FSResult FSi_MountSpecialArchive(u64 param, const char *arcname, FSFATFSArchiveWork* pWork)
1673 {
1674 FSResult result = FS_RESULT_ERROR;
1675 FATFSResultBuffer tls[1];
1676 FATFS_RegisterResultBuffer(tls, TRUE);
1677 if (!FATFS_MountSpecial(param, arcname, &pWork->slot))
1678 {
1679 result = FSi_ConvertError(tls->result);
1680 }
1681 else
1682 {
1683 if (arcname && *arcname)
1684 {
1685 FSi_MountFATFSArchive(&pWork->context, arcname, pWork->tmpbuf);
1686 }
1687 else
1688 {
1689 (void)FS_UnmountArchive(pWork->context.arc);
1690 (void)FS_ReleaseArchiveName(pWork->context.arc);
1691 }
1692 result = FS_RESULT_SUCCESS;
1693 }
1694 FATFS_RegisterResultBuffer(tls, FALSE);
1695 return result;
1696 }
1697
1698 /*---------------------------------------------------------------------------*
1699 Name: FSi_FormatSpecialArchive
1700
1701 Description: Formats content of special archive that satisfies the following conditions.
1702 - Currently mounted
1703 - Hold your own ownership rights (dataPub, dataPrv, share*)
1704
1705 Arguments: path: Path name that includes the archive name
1706
1707 Returns: FS_RESULT_SUCCESS if the processing was successful.
1708 *---------------------------------------------------------------------------*/
FSi_FormatSpecialArchive(const char * path)1709 FSResult FSi_FormatSpecialArchive(const char *path)
1710 {
1711 FSResult result = FS_RESULT_ERROR;
1712 FATFSResultBuffer tls[1];
1713 FATFS_RegisterResultBuffer(tls, TRUE);
1714 if (!FATFS_FormatSpecial(path))
1715 {
1716 result = FSi_ConvertError(tls->result);
1717 }
1718 else
1719 {
1720 result = FS_RESULT_SUCCESS;
1721 }
1722 FATFS_RegisterResultBuffer(tls, FALSE);
1723 return result;
1724 }
1725
1726
1727 #include <twl/ltdmain_end.h>
1728
1729
1730 #endif /* FS_IMPLEMENT */
1731
1732 #endif /* SDK_TWL */
1733
1734 /*---------------------------------------------------------------------------*
1735 Name: FS_ForceToEnableLatencyEmulation
1736
1737 Description: Uses a driver to emulate the random wait times that occur when accessing a degraded NAND device.
1738
1739
1740 Arguments: None.
1741
1742 Returns: None.
1743 *---------------------------------------------------------------------------*/
FS_ForceToEnableLatencyEmulation(void)1744 void FS_ForceToEnableLatencyEmulation(void)
1745 {
1746 #if defined(SDK_TWL)
1747 if (OS_IsRunOnTwl())
1748 {
1749 (void)FATFS_SetLatencyEmulation(TRUE);
1750 }
1751 #endif
1752 }
1753
1754