A file system which can mount, read, and enumerate a file system image which has been appended to the compiled .bin code file before being uploaded to the mbed device.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FlashFileSystem.h Source File

FlashFileSystem.h

00001 /* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/)
00002 
00003    Licensed under the Apache License, Version 2.0 (the "License");
00004    you may not use this file except in compliance with the License.
00005    You may obtain a copy of the License at
00006 
00007        http://www.apache.org/licenses/LICENSE-2.0
00008 
00009    Unless required by applicable law or agreed to in writing, software
00010    distributed under the License is distributed on an "AS IS" BASIS,
00011    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012    See the License for the specific language governing permissions and
00013    limitations under the License.
00014 */
00015 /* Specifies the classes used to implement the FlashFileSystem which is a
00016    read-only file system that exists in the internal FLASH of the mbed
00017    device.
00018 */
00019 #ifndef _FLASHFILESYSTEM_H_
00020 #define _FLASHFILESYSTEM_H_
00021 
00022 #include "FileSystemLike.h"
00023 
00024 
00025 // Forward declare file system entry structure used internally in 
00026 // FlashFileSystem.
00027 struct _SFileSystemEntry;
00028 
00029 
00030 
00031 // Represents an opened file object in the FlashFileSystem.
00032 class FlashFileSystemFileHandle : public FileHandle 
00033 {
00034 public:
00035     FlashFileSystemFileHandle();
00036     FlashFileSystemFileHandle(const char* pFileStart, const char* pFileEnd);
00037     
00038     // FileHandle interface methods.
00039     virtual ssize_t write(const void* buffer, size_t length);
00040     virtual int close();
00041     virtual ssize_t read(void* buffer, size_t length);
00042     virtual int isatty();
00043     virtual off_t lseek(off_t offset, int whence);
00044     virtual int fsync();
00045     virtual off_t flen();
00046 
00047     // Used by FlashFileSystem to maintain entries in its handle table.
00048     void SetEntry(const char* pFileStart, const char* pFileEnd)
00049     {
00050         m_pFileStart = pFileStart;
00051         m_pFileEnd = pFileEnd;
00052         m_pCurr = pFileStart;
00053     }
00054     int IsClosed()
00055     {
00056         return (NULL == m_pFileStart);
00057     }
00058     
00059 protected:
00060     // Beginning offset of file in FLASH memory.
00061     const char*         m_pFileStart;
00062     // Ending offset of file in FLASH memory.
00063     const char*         m_pFileEnd;
00064     // Current position in file to be updated by read and seek operations.
00065     const char*         m_pCurr;
00066 };
00067 
00068 
00069 // Represents an open directory in the FlashFileSystem.
00070 class FlashFileSystemDirHandle : public DirHandle
00071 {
00072  public:
00073     // Constructors
00074     FlashFileSystemDirHandle();
00075     FlashFileSystemDirHandle(const char*              pFLASHBase,
00076                              const _SFileSystemEntry* pFirstFileEntry,
00077                              unsigned int             FileEntriesLeft,
00078                              unsigned int             DirectoryNameLength);
00079                              
00080     // Used by FlashFileSystem to maintain DirHandle entries in its cache.
00081     void SetEntry(const char*              pFLASHBase,
00082                   const _SFileSystemEntry* pFirstFileEntry,
00083                   unsigned int             FileEntriesLeft,
00084                   unsigned int             DirectoryNameLength)
00085     {
00086         m_pFLASHBase = pFLASHBase;
00087         m_pFirstFileEntry = pFirstFileEntry;
00088         m_pCurrentFileEntry = pFirstFileEntry;
00089         m_FileEntriesLeft = FileEntriesLeft;
00090         m_DirectoryNameLength = DirectoryNameLength;
00091     }
00092     int IsClosed()
00093     {
00094         return (NULL == m_pFirstFileEntry);
00095     }
00096     
00097     // Methods defined by DirHandle interface.
00098     virtual int    closedir();
00099     virtual struct dirent *readdir();
00100     virtual void   rewinddir();
00101     virtual off_t  telldir();
00102     virtual void   seekdir(off_t location);
00103 
00104 protected:
00105     // The first file entry for this directory.  rewinddir() takes the
00106     // iterator back to here.
00107     const _SFileSystemEntry*    m_pFirstFileEntry;
00108     // The next file entry to be returned for this directory enumeration.
00109     const _SFileSystemEntry*    m_pCurrentFileEntry;
00110     // Pointer to where the file system image is located in the device's FLASH.
00111     const char*                 m_pFLASHBase;
00112     // Contents of previously return directory entry structure.
00113     struct dirent               m_DirectoryEntry;
00114     // This is the length of the directory name which was opened.  When the
00115     // first m_DirectoryNameLength characters change then we have iterated
00116     // through to a different directory.
00117     unsigned int                m_DirectoryNameLength;
00118     // The number of entries left in the file system file entries array.
00119     unsigned int                m_FileEntriesLeft;
00120 };
00121 
00122 
00123 
00124 /** A filesystem for accessing a read-only file system placed in the internal\n
00125  *  FLASH memory of the mbed board.
00126  *\n
00127  *  The file system to be mounted by this file system should be created through\n
00128  *  the use of the fsbld utility on the PC.\n
00129  *\n
00130  *  As fsbld creates two output files (a binary and a header file), there are two\n
00131  *  ways to add the resulting file system image:\n
00132  *  -# Concatenate the binary file system to the end of the .bin file created\n
00133  *     by the mbed online compiler before uploading to the mbed device.\n
00134  *  -# Import the header file into your project, include this file in your main\n
00135  *     file and add 'roFlashDrive' to the FlashfileSystem constructor call.\n
00136  *     eg : static FlashFileSystem flash("flash", roFlashDrive);\n
00137  *
00138  *  A third (optional) parameter in the FlashfileSystem constructor call allows\n
00139  *  you to specify the size of the FLASH (KB) on the device (default = 512).\n
00140  *  eg (for a KL25Z device) : static FlashFileSystem flash("flash", NULL, 128);\n
00141  *  Note that in this example, the pointer to the header file has been omitted,\n
00142  *  so we need to append the binary file system ourselves (see above).\n
00143  *  When you use the binary file system header in your main file, you can\n
00144  *  use the roFlashDrive pointer.\n
00145  *  eg (for a KL25Z device) : static FlashFileSystem flash("flash", roFlashDrive, 128);\n
00146  *\n
00147  *  NOTE: This file system is case-sensitive.  Calling fopen("/flash/INDEX.html")\n
00148  *        won't successfully open a file named index.html in the root directory\n
00149  *        of the flash file system.\n
00150  *
00151  * Example:
00152  * @code
00153 #include <mbed.h>
00154 #include "FlashFileSystem.h"
00155 // Uncomment the line below when you imported the header file built with fsbld
00156 // and replace <Flashdrive> with its correct filename
00157 //#include "<FlashDrive>.h"
00158 
00159 static void _RecursiveDir(const char* pDirectoryName, DIR* pDirectory = NULL)
00160 {
00161     DIR* pFreeDirectory = NULL;
00162     
00163     size_t DirectoryNameLength = strlen(pDirectoryName);
00164  
00165     // Open the specified directory.
00166     if (!pDirectory)
00167     {
00168         pDirectory = opendir(pDirectoryName);
00169         if (!pDirectory)
00170         {
00171             error("Failed to open directory '%s' for enumeration.\r\n", 
00172                   pDirectoryName);
00173         }
00174         
00175         // Remember to free this directory enumerator.
00176         pFreeDirectory = pDirectory;
00177     }
00178         
00179     // Determine if we should remove a trailing slash from future *printf()
00180     // calls.
00181     if (DirectoryNameLength && '/' == pDirectoryName[DirectoryNameLength-1])
00182     {
00183         DirectoryNameLength--;
00184     }
00185     
00186     // Iterate though each item contained within this directory and display
00187     // it to the console.
00188     struct dirent* DirEntry;
00189     while((DirEntry = readdir(pDirectory)) != NULL) 
00190     {
00191         char RecurseDirectoryName[256];
00192         DIR* pSubdirectory;
00193 
00194         // Try opening this file as a directory to see if it succeeds or not.
00195         snprintf(RecurseDirectoryName, sizeof(RecurseDirectoryName),
00196                  "%.*s/%s",
00197                  DirectoryNameLength,
00198                  pDirectoryName,
00199                  DirEntry->d_name);
00200         pSubdirectory = opendir(RecurseDirectoryName);
00201         
00202         if (pSubdirectory)
00203         {
00204             _RecursiveDir(RecurseDirectoryName, pSubdirectory);
00205             closedir(pSubdirectory);
00206         }
00207         else
00208         {
00209             printf("    %.*s/%s\n", 
00210                    DirectoryNameLength, 
00211                    pDirectoryName, 
00212                    DirEntry->d_name);
00213         }
00214     }
00215     
00216     // Close the directory enumerator if it was opened by this call.
00217     if (pFreeDirectory)
00218     {
00219         closedir(pFreeDirectory);
00220     }
00221 }
00222 
00223 int main() 
00224 {
00225     static const char* Filename = "/flash/index.html";
00226     char*              ReadResult = NULL;
00227     int                SeekResult = -1;
00228     char               Buffer[128];
00229 
00230     // Create the file system under the name "flash".
00231     // NOTE : When you include the the header file built with fsbld,
00232     //        disable the first static FlashFileSystem... line
00233     //        and enable the second static FlashFileSystem... line.
00234     static FlashFileSystem flash("flash");
00235 //    static FlashFileSystem flash("flash, roFlashDrive");
00236     if (!flash.IsMounted())
00237     {
00238         error("Failed to mount FlashFileSystem.\r\n");
00239     }
00240 
00241     // Open "index.html" on the file system for reading.
00242     FILE *fp = fopen(Filename, "r");
00243     if (NULL == fp)
00244     {
00245         error("Failed to open %s\r\n", Filename);
00246     }
00247     
00248     // Use seek to determine the length of the file
00249     SeekResult = fseek(fp, 0, SEEK_END);
00250     if (SeekResult)
00251     {
00252         error("Failed to seek to end of %s.\r\n", Filename);
00253     }
00254     long FileLength = ftell(fp);
00255     printf("%s is %ld bytes in length.\r\n", Filename, FileLength);
00256     
00257     // Reset the file pointer to the beginning of the file
00258     SeekResult = fseek(fp, 0, SEEK_SET);
00259     if (SeekResult)
00260     {
00261         error("Failed to seek to beginning of %s.\r\n", Filename);
00262     }
00263     
00264     // Read the first line into Buffer and then display to user.
00265     ReadResult = fgets(Buffer, sizeof(Buffer)/sizeof(Buffer[0]), fp);
00266     if (NULL == ReadResult)
00267     {
00268         error("Failed to read first line of %s.\r\n", Filename);
00269     }
00270     printf("%s:1  %s", Filename, Buffer);
00271     
00272     // Done with the file so close it.
00273     fclose(fp);                               
00274 
00275     // Enumerate all content on mounted file systems.
00276     printf("\r\nList all files in /flash...\r\n");
00277     _RecursiveDir("/flash");
00278         
00279     printf("\r\nFlashFileSystem example has completed.\r\n");
00280 }
00281  * @endcode
00282  */
00283 class FlashFileSystem : public FileSystemLike 
00284 {
00285 public:
00286     FlashFileSystem(const char* pName, const uint8_t *pFlashDrive = NULL, const uint32_t FlashSize = 512);
00287     
00288     virtual FileHandle* open(const char* pFilename, int Flags);
00289     virtual DirHandle*  opendir(const char *pDirectoryName);
00290 
00291     virtual int         IsMounted() { return (m_FileCount != 0); }
00292 
00293 protected:
00294     FlashFileSystemFileHandle*  FindFreeFileHandle();
00295     FlashFileSystemDirHandle*   FindFreeDirHandle();
00296     
00297     // File handle table used by this file system so that it doesn't need
00298     // to dynamically allocate file handles at runtime.
00299     FlashFileSystemFileHandle   m_FileHandles[16];
00300     // Directory handle table used by this file system so that it doesn't need
00301     // to dynamically allocate file handles at runtime.
00302     FlashFileSystemDirHandle    m_DirHandles[16];
00303     // Pointer to where the file system image is located in the device's FLASH.
00304     const char*                 m_pFLASHBase;
00305     // Pointer to where the file entries are located in the device's FLASH.
00306     const _SFileSystemEntry*    m_pFileEntries;
00307     // The number of files in the file system image.
00308     unsigned int                m_FileCount;
00309 };
00310 
00311 #endif // _FLASHFILESYSTEM_H_