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