1
0
uboot-1.1.4-kirkwood/board/mv_feroceon/USP/mv_fs.c

2963 lines
114 KiB
C
Raw Normal View History

2024-01-09 13:41:15 +01:00
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
*******************************************************************************/
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#include "mvSysHwConfig.h"
#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_FFS)
#include "mvTypes.h"
#include "norflash/mvFlash.h"
#include "mvCpuIf.h"
/*#include "mv_mon.h"*/
#include "mv_fs.h"
#if CONFIG_COMMANDS & CFG_CMD_BSP
/* #define DEBUG */
#ifdef DEBUG
#define DB(x) x
#else
#define DB(x)
#endif
static MV_FLASH_INFO *mvFlashInfo;
/* File system data base variables */
/* FAT signature */
char FATsignature[] = "FAT024136764000";
unsigned int initializationFlag;
unsigned int mvFSTimeStamp;
unsigned int operationMode;
unsigned int mvFSOffset;
unsigned int mvFSTopOffset;
unsigned int nextFreeBlock;
FS_FILE_TABLE_ENTRY mvFSEntries[FS_MAX_NUM_OF_ENTRIES];
FS_FILE_CACHE_BLOCK mvFSCacheBlocks[FS_NUMBER_OF_BLOCKS_FOR_CACHE];
/* Functions */
extern void d_i_cache_clean(unsigned int Address, unsigned int byteCount);
extern int load_net(MV_U32 *loadnet_addr);
extern unsigned int VIRTUAL_TO_PHY(unsigned int address);
extern void mv_go(unsigned long addr,int argc, char *argv[]);
extern MV_FLASH_INFO* getMvFlashInfo(int index);
/*******************************************************************************
* mvFSFormat - Formats the mvFlash mvMemory for file system usage.
*
* DESCRIPTION:
* This function formats the flash memory for file system usage. It
* allocates 10 blocks for FAT in a form of a linked list and write the
* signature (signature defind in mvFS.h) in each FAT header block
* within the flash. The format starts from the <EFBFBD>offset<EFBFBD> parameter value
* within the flash if the offset is aligned with one of the flash's
* sectors start address, otherwise it will be incremented to the nearest
* sector start address and then perform the format.The format can be
* accomplished in 2 modes as described below.
*
* INPUT:
* offset - Starting point of the format within the flash.
*
* mode - Defines whether an erasing counter will be enabled or not .
* When erasing counter is enabled , the function will allocate one
* block at the end of each sector to act as a counter for the
* number of erasures of that sector . The possible values :
* - ENABLE_ERASING_COUNTER
* - NO_ERASING_COUNTER
* OUTPUT:
* Initialized flash for file system usage.
*
* RETURN:
* The actual offset (after alignment to the nearest sector start address)
* or:
* FLASH_MEMORY_NOT_PRESENT - if no flash memory present .
* VALID_FILE_SYS_IN_LOWER_OFFSET - if a valid file system residing in a
* lower offset.
*
*******************************************************************************/
unsigned int mvFSFormat(unsigned int offset,unsigned int mode)
{
unsigned int i,sectorSize,tempOffset,limit,previousCount;
unsigned int erasingCounterWasEnabled = 0,status;
DB(printf("start mvFSFormat\n"));
DB(printf("Flash base addr 0x%x\n",mvFlashInfo->baseAddr));
if(offset != mvFlashSecOffsGet(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset)))
{
offset = mvFlashSecOffsGet(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset) + 1);
}
if(offset != 0xffffffff)
{
if(mode == FS_ENABLE_ERASING_COUNTER)
{
tempOffset = mvFSSearchForSignature();
if(tempOffset != FS_NO_VALID_FAT_STRING)
{
if(tempOffset < offset)
return FS_VALID_FILE_SYS_IN_LOWER_OFFSET;
if(mvFlash32Rd(mvFlashInfo, tempOffset + FS_ERSAING_COUNTER_FLAG_OFFSET)
== FS_ENABLE_ERASING_COUNTER)
{
erasingCounterWasEnabled = 1;
}
}
}
tempOffset = offset;
/* Eraseing the sectors dedicated for the file system */
while(mvFlashInWhichSec(mvFlashInfo, offset) != 0xffffffff)
{
if(mode == FS_NO_ERASING_COUNTER)
{
DB(printf("mvFSFormat - mode = FS_NO_ERASING_COUNTER\n"));
i = mvFlashInWhichSec(mvFlashInfo, offset);
sectorSize = mvFlashSecSizeGet(mvFlashInfo, i);
limit = offset + sectorSize;
for(; offset < limit ; offset+=4)
{
if(mvFlash32Rd(mvFlashInfo, offset) != 0xffffffff)
{
DB(printf("mvFSFormat - Erase flash sector 0x%x\n", mvFlashInWhichSec(mvFlashInfo, offset)));
status = mvFlashSecErase(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset));
if (status != MV_OK)
{
printf("mvFlashSecErase - FAIL!\n");
return status;
}
break;
}
}
offset += sectorSize;
}
else /* mode == FS_ENABLE_ERASING_COUNTER */
{
DB(printf("mvFSFormat - mode = FS_ENABLE_ERASING_COUNTER\n"));
i = mvFlashInWhichSec(mvFlashInfo, offset);
sectorSize = mvFlashSecSizeGet(mvFlashInfo, i);
limit = offset + sectorSize - FS_BLOCK_SIZE;
previousCount = mvFlash32Rd(mvFlashInfo, limit);
for(; offset <= (limit + 4) ; offset+=4)
{
if(mvFlash32Rd(mvFlashInfo, offset) != 0xffffffff)
{
mvFlashSecErase(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset));
if(erasingCounterWasEnabled)
{
/* Increment the counter */
mvFlash32Wr(mvFlashInfo, limit, previousCount + 1);
mvFlash8Wr(mvFlashInfo, limit+FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_USED_FOR_ERASING_COUNTER);
}
break;
}
}
if(!erasingCounterWasEnabled)
{
/* Initialize the counter */
mvFlash32Wr(mvFlashInfo, limit, 0);
mvFlash8Wr(mvFlashInfo, limit + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_USED_FOR_ERASING_COUNTER);
}
offset = limit + FS_BLOCK_SIZE;
}
}
/* Fill the FAT's header */
offset = tempOffset;
/* Update the status flag */
mvFlash8Wr(mvFlashInfo, offset + FS_BLOCK_STATUS_FLAG_OFFSET,FS_FAT_BLOCK);
/* Write the FAT's signature */
mvFlashBlockWr(mvFlashInfo, offset + FS_SIGNATURE_OFFSET, FS_FAT_SIGNATURE_SIZE,
(MV_U8 *)FATsignature);
/* Check if we were able to burn the mvFlash */
for(i = 0 ; i < FS_FAT_SIGNATURE_SIZE ; i++)
{
if(mvFlash8Rd(mvFlashInfo, offset + FS_SIGNATURE_OFFSET + i) != FATsignature[i])
return FS_FLASH_MEMORY_NOT_PRESENT;
}
if(mode == FS_ENABLE_ERASING_COUNTER)
{
mvFlash32Wr(mvFlashInfo, offset + FS_ERSAING_COUNTER_FLAG_OFFSET,
FS_ENABLE_ERASING_COUNTER);
}
mvFlash32Wr(mvFlashInfo, offset, offset + FS_BLOCK_SIZE);
/* Alocate 9 more blocks for the FAT */
for(i = 1 ; i < (FS_MAX_NUM_OF_FAT_BLOCKS - 1) ; i++)
{
/* Next block pointer */
mvFlash32Wr(mvFlashInfo, offset+(FS_BLOCK_SIZE*(i)),offset+
(FS_BLOCK_SIZE*(i+1)));
/* Flag */
mvFlash8Wr(mvFlashInfo, offset+(FS_BLOCK_SIZE*(i)) +
FS_BLOCK_STATUS_FLAG_OFFSET, FS_FAT_BLOCK);
}
/* The last block's next pointer is 0xffffffff since it is the last */
mvFlash8Wr(mvFlashInfo, offset + (FS_BLOCK_SIZE * i) +
FS_BLOCK_STATUS_FLAG_OFFSET, FS_FAT_BLOCK);
}
return offset;
}
/*******************************************************************************
* mvFSInit - Initializes the flash system's data base variables.
*
* DESCRIPTION:
* This function initializes the flash system's database variables residing
* in the systems dynamic memory (SDRAM) . It searches within the flash
* memory from the begining, for the first occurrence of a valid signature.
* If found, a valid file system is assumed to be exist starting from the
* sector the signature was found and all the database variables will than
* be initialized ,otherwise it returns NO_VALID_FAT_STRING or
* OFFSET_OUT_OF_RANGE to indicate that no valid file system was found
* within the flash .If a valid file system was found ,the function returns
* the number of files within the flash .The <EFBFBD>mode<EFBFBD> parameter delivered to
* the function is for future needs to support two cache modes(cache mode,
* non - cache mode) and currently this feature is not implemented in this
* current version of this function.
* NOTE!!!!:
* It is a MUST to call this function before any attempt to use file-system
* driver.
* INPUT:
* mode - For future needs to support cache or non-cache modes (currently
* not implemented).
*
* OUTPUT:
* Initialized data base for the file system.
*
* RETURN:
* Number of files currently on the system or:
* NO_VALID_FAT_STRING - if no file system was found (Try to use
* <EFBFBD>fileSysFormat<EFBFBD> function in this case).
* OFFSET_OUT_OF_RANGE - if there was an error finding a signature found is
* SYSTEM_ALREADY_INITIALIZED.
*
*******************************************************************************/
unsigned int mvFSInit(unsigned int mode)
{
/* Initially we are not going to support the FS_ENABLE_CACHE mode */
unsigned int offset = 0,i = 0,numOfFiles,nextBlockOffset;
unsigned int fileEntryOffset,tempOffset;
/* set the global flash info structure */
mvFlashInfo = getMvFlashInfo(MAIN_FLASH_INDEX);
/* Seek for the FAT signature */
offset = mvFSSearchForSignature();
if(offset == FS_NO_VALID_FAT_STRING)
return FS_NO_VALID_FAT_STRING;
if(offset >= mvFlashSizeGet(mvFlashInfo))
return FS_OFFSET_OUT_OF_RANGE;
mvFSTopOffset = mvFlashSizeGet(mvFlashInfo);
/* Check if the system is already initialized , if so we will not
re-initialize */
if(initializationFlag == FS_FILE_SYSTEM_INITIALIZED)
return FS_SYSTEM_ALREADY_INITIALIZED;
/* We found the FAT's signature, now we need to initialize the file system
data base and count the number of files */
mvFSTimeStamp = 0;
operationMode = mode;
mvFSOffset = offset;
nextFreeBlock = 0xffffffff - FS_BLOCK_SIZE;
/* Initialize the files entries */
for(i = 0 ; i < FS_MAX_NUM_OF_ENTRIES ; i++)
{
mvFSEntries[i].filePointer = 0;
mvFSEntries[i].statusFlag = FS_FREE_ENTRY;
mvFSEntries[i].mode[0] = '\0';
mvFSEntries[i].pointerToFAT = 0xffffffff;
mvFSEntries[i].EOFpointer = 0;
}
/* Initialize the cache blocks */
for(i = 0 ; i < FS_NUMBER_OF_BLOCKS_FOR_CACHE ; i++)
{
mvFSCacheBlocks[i].currentBlockAddress = 0xffffffff;
mvFSCacheBlocks[i].fileHandler = 0;
mvFSCacheBlocks[i].usageCounter = 0;
mvFSCacheBlocks[i].timeStamp = 0;
}
/* Count the number of files currently on the system */
numOfFiles = 0;
nextBlockOffset = mvFSOffset;
while(nextBlockOffset != 0xffffffff)
{
/* Skip the block's header */
fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE;
for(i = 0 ; i < 15 ; i++)
{
if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_USE)
numOfFiles++;
/* If we have files which were not properly closed we need to
to remove them from the system */
if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_UPDATE)
{
mvFlash8Wr(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET,
FS_FREE_DIRTY_ENTRY);
/* Free the file's data blocks */
tempOffset = mvFlash32Rd(mvFlashInfo, fileEntryOffset);
while(tempOffset != 0xffffffff)
{
tempOffset = tempOffset & FS_BLOCK_OFFSET_MASK;
mvFlash8Wr(mvFlashInfo, tempOffset + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_FREE_DIRTY_BLOCK);
tempOffset = mvFlash32Rd(mvFlashInfo, tempOffset);
}
}
/* point to the next entry */
fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE;
}
nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset);
}
initializationFlag = FS_FILE_SYSTEM_INITIALIZED;
return numOfFiles;
}
/*******************************************************************************
* mvFSDelete - Deletes a file for the file system.
*
* DESCRIPTION:
* This function deletes a file in the file-system. The function actually
* marks the file's entry status flag as FREE_DIRTY_ENTRY and the file's
* status flag of each data block with the value FREE_DIRTY_BLOCKs to
* indicate that this entery and all the file<EFBFBD>s data blocks are no longer
* associated by this file. If the file has valid handles associated with
* it the file will not be deleted .
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
*
* INPUT:
* fileName - A string containing the file name.
*
* OUTPUT:
* On success the file will be deleted..
*
* RETURN:
* On success - The return value will be FS_FILE_DELETED.
* On failure one of the following parameters:
* FS_FILE_NOT_FOUND - if the data base was initialized or file was not
* found.
* FS_FILE_IS_NOT_CLOSED - if the file has valid handles associated with
* it.
*******************************************************************************/
unsigned int mvFSDelete(char * fileName)
{
unsigned int fileOffset,numOfHandles,tempOffset;
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return FS_FILE_NOT_FOUND;
if((fileOffset = mvFSFileFind(fileName)) == FS_FILE_NOT_FOUND)
return FS_FILE_NOT_FOUND;
if((numOfHandles = mvFSNumOfHandles(fileName)) == FS_FILE_NOT_FOUND)
return FS_FILE_NOT_FOUND;
if(numOfHandles > 0)
return FS_FILE_IS_NOT_CLOSED;
mvFlash8Wr(mvFlashInfo, fileOffset + FS_ENTRY_STATUS_FLAG_OFFSET,
FS_FREE_DIRTY_ENTRY);
/* Free the file's data blocks */
tempOffset = mvFlash32Rd(mvFlashInfo, fileOffset);
while(tempOffset != 0xffffffff)
{
tempOffset = tempOffset & FS_BLOCK_OFFSET_MASK;
mvFlash8Wr(mvFlashInfo, tempOffset + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_FREE_DIRTY_BLOCK);
tempOffset = mvFlash32Rd(mvFlashInfo, tempOffset);
}
return FS_FILE_DELETED;
}
/*******************************************************************************
* mvFSFileFind - Check if a file exists in the file system.
*
* DESCRIPTION:
* This function checks if the file <EFBFBD>fileName<EFBFBD> exists in the file system.
* The function will search for the file with the matching name and
* extension and if found , the file's entry offset in the FAT is returned.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
*
* INPUT:
* fileName - A string containing the file name.
*
* OUTPUT:
* None.
*
* RETURN:
* FILE_NOT_FOUND or the file's entery offset in the FAT.
*
*******************************************************************************/
unsigned int mvFSFileFind(char * fileName)
{
unsigned int nextBlockOffset,fileEntryOffset,index;
char tempString[20];
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return FS_FILE_NOT_FOUND;
nextBlockOffset = mvFSOffset;
while(nextBlockOffset != 0xffffffff)
{
/* Skip the block's header */
for(fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE;
fileEntryOffset < (nextBlockOffset + FS_BLOCK_SIZE);
fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE)
{
index = 0;
if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_USE)
{
/* Read the file's name */
mvFSReadFileNameFromFATentry(fileEntryOffset,tempString);
if(strcmp(tempString,fileName) == 0) return fileEntryOffset;
/* else , try the next entry */
}
}
nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset);
}
return FS_FILE_NOT_FOUND;
}
/*******************************************************************************
* mvFSNumOfHandles - Counts the number of handles currently pointing to a file.
*
* DESCRIPTION:
* This function counts the number of handles currently associated to the
* file <EFBFBD>fileName<EFBFBD>.The entry table in the dynamic database is formed from
* an array of FILE_TABLE_ENTRY (structure defined in mvFS.h) and the
* file handler acts as the index of that array . The function counts each
* entry within the array that points to the file <EFBFBD>fileName<EFBFBD> and return
* that value.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
*
* INPUT:
* fileName - A string containing the file name.
*
* OUTPUT:
* None.
*
* RETURN:
* on success , the Number of handlers currently associated to the file
* <EFBFBD>fileName<EFBFBD>.
* on failure , FS_FILE_NOT_FOUND.
*
*******************************************************************************/
unsigned int mvFSNumOfHandles(char * fileName)
{
unsigned int fileEntryOffset,i,numOfHandles;
if((fileEntryOffset = mvFSFileFind(fileName)) == 0xffffffff)
return FS_FILE_NOT_FOUND;
numOfHandles = 0;
for(i = 0 ; i < FS_MAX_NUM_OF_ENTRIES ; i++)
{
if(fileEntryOffset == mvFSEntries[i].filePointer)
numOfHandles++;
}
return numOfHandles;
}
/*******************************************************************************
* mvFSSearchForSignature - Searches for the FAT's signature string, if the
* string is found we are assuming a valid file system.
*
* DESCRIPTION:
* This function searches within the flash memory from the begining for the
* first occurrence of a valid signature .If found , it returns the sector
* offset on which the signature first occurred , otherwise it returns
* NO_VALID_FAT_STRING to indicate the flash is not formated , in that case
* you might want to use fileSysformat function.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* The offset of the sector in which the signature was found,
* otherwise FS_NO_VALID_FAT_STRING .
*
*******************************************************************************/
unsigned int mvFSSearchForSignature(void)
{
unsigned int offset = 0,i,sectorNumber;
sectorNumber = mvFlashInWhichSec(mvFlashInfo, offset);
while((offset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber)) != 0xffffffff)
{
for(i = 0 ; i < FS_FAT_SIGNATURE_SIZE ; i++)
{
if(mvFlash8Rd(mvFlashInfo, offset + FS_SIGNATURE_OFFSET +
i) != FATsignature[i])
break;
}
if(i == FS_FAT_SIGNATURE_SIZE) break;
offset += mvFlashSecSizeGet(mvFlashInfo, sectorNumber);
sectorNumber = mvFlashInWhichSec(mvFlashInfo, offset);
if(sectorNumber == 0xffffffff) return FS_NO_VALID_FAT_STRING;
}
if(offset == 0xffffffff) return FS_NO_VALID_FAT_STRING;
return offset;
}
/*******************************************************************************
* mvFSOpen - Opens a file for read/write/append.
*
* DESCRIPTION:
* This function opens a file for reading , writing or appending data .The
* function will act differantly upon each mode delivered by the parameter
* <EFBFBD>mode<EFBFBD>.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
*
* INPUT:
* mode - defines on which mode the file will be open .All possible values
* for <EFBFBD>mode<EFBFBD> parameter are described below:
*
<EFBFBD> "r" - Opens the file for reading only . If the file does not
* exist or cannot be found , the function fails . After the
* file has been found , the function searches for an empty
* entry within the dynamic data base entry table and if it
* found one , it associates the file <EFBFBD>fileName<EFBFBD> to that
* entry and returns the handler of the file.
* "r+" - Opens the file for both reading and writing. If the file
* does not exist or cannot be found , the function fails.
* After the file has been found , the function searches
* for an empty entry within the dynamic data base entry
* table and if found , it associates the file <EFBFBD>fileName<EFBFBD>
* to that entry and returns the handler of the file . When
* a file is opened with the <EFBFBD>r+<EFBFBD> all write operations
* occur at the end of the file. The file pointer can be
* repositioned using fileSysSeek or fileSysRewind , but is
* always moved back to the end of the file before any write
* operation is carried out. Thus ,existing data cannot be
* overwritten.
* "w" - Opens an empty file for writing only. If the file does
* not exist the function will create it, otherwise if the
* given file exists the function will open it but its
* content will be destroyed . On both cases the function
* searches for an empty entry within the dynamic data base
* entry table and if found , it associates the file
* <EFBFBD>fileName<EFBFBD> to that entry and returns the handler of the
* file .
* "w+" - Opens an empty file for both reading and writing data. If
* the given file exists, its contents is destroyed . When a
* file is opened with the "w+" access type , all write
* operations occur at the end of the file. The file pointer
* can be repositioned using fileSysSeek or fileSysRewind ,
* but is always moved back to the end of the file before any
* write operation is carried out. Thus ,existing data cannot
* be overwritten.
* "a+" - Opens a file for reading and appending data. If the given
* file exists ,its contents is destroyed .The appending
* operation includes the removal of the EOF marker before
* new data is written to the file and the EOF marker is
* restored after the writing has completed . When a file is
* opened with the "a+" access type ,all write operations
* occur at the end of the file. The file pointer can be
* repositioned using fileSysSeek or fileSysRewind , but is
* always moved back to the end of the file before any write
* operation is carried out .Thus , existing data cannot be
* overwritten.
* fileName - A string containing the file name.
*
* OUTPUT:
* None.
*
* RETURN:
* File handler on success or FILE_OPEN_ERROR in one of the following
* reasons:
* - File system not initialized.
* - In cases of the modes "r" or "r+" and the file is not found.
* - No free entries in the file system's data base.
* - In modes "w" and w+" if we try to open a file which already exists it
* must be deleted first , an error can occur at the delete function.
* - No more free entries on the flash memory.
* - Not supported mode.
*
*******************************************************************************/
FS_FILE_HANDLER mvFSOpen(char * fileName,char *mode)
{
unsigned int fileFAToffset,fh;
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
{
return FS_FILE_OPEN_ERROR;
}
/* Mode == "r" or "r+" - the file must exist */
if((mode[0] == 'r') &&
(mode[1] == '\0'|| (mode[1] == '+' && mode[2] == '\0')))
{
fileFAToffset = mvFSFileFind(fileName);
if(fileFAToffset == FS_FILE_NOT_FOUND)
return FS_FILE_OPEN_ERROR;
for(fh = 0 ; fh < FS_MAX_NUM_OF_ENTRIES ; fh++)
{
if(mvFSEntries[fh].statusFlag == FS_FREE_ENTRY)
{
mvFSEntries[fh].statusFlag = FS_ENTRY_IN_USE;
mvFSEntries[fh].filePointer = 0;
mvFSEntries[fh].mode[0] = mode[0];
mvFSEntries[fh].mode[1] = mode[1];
mvFSEntries[fh].mode[2] = mode[2];
mvFSEntries[fh].pointerToFAT = fileFAToffset;
mvFSEntries[fh].EOFpointer = mvFSGetEOFoffset(fileName);
return fh;
}
}
return FS_FILE_OPEN_ERROR;
}
/* Mode == "w" ,"w+" or "a+" */
if((mode[0] == 'w' || mode[0] == 'a') &&
(mode[1] == '\0'||(mode[1] == '+' && mode[2] == '\0')))
{
/* Check if the file exists on the system */
fileFAToffset = mvFSFileFind(fileName);
if(fileFAToffset != FS_FILE_NOT_FOUND)
{
if( mode[0] != 'a')
{
if(mvFSDelete(fileName) != FS_FILE_DELETED)
return FS_FILE_OPEN_ERROR;
/* Get a free entry on the FAT */
fileFAToffset = mvFSGetFreeEntry();
if(fileFAToffset == FS_NO_FREE_ENTRIES)
return FS_FILE_OPEN_ERROR;
}
}
else
{
/* Get a free entry on the FAT */
fileFAToffset = mvFSGetFreeEntry();
if(fileFAToffset == FS_NO_FREE_ENTRIES)
return FS_FILE_OPEN_ERROR;
}
/* Search for a free entry on the file system's data base */
for(fh = 0 ; fh < FS_MAX_NUM_OF_ENTRIES ; fh++)
{
if(mvFSEntries[fh].statusFlag == FS_FREE_ENTRY)
{
mvFSEntries[fh].statusFlag = FS_ENTRY_IN_USE;
mvFSEntries[fh].filePointer = 0;
mvFSEntries[fh].mode[0] = mode[0];
mvFSEntries[fh].mode[1] = mode[1];
mvFSEntries[fh].mode[2] = mode[2];
mvFSEntries[fh].pointerToFAT= fileFAToffset;
mvFSEntries[fh].EOFpointer = mvFSGetEOFoffset(fileName);
/* Update the entry on the FAT */
/* Write the file's name */
mvFSWriteFileNameToFATentry(fileFAToffset,fileName);
/* Update the status flag */
mvFlash8Wr(mvFlashInfo, fileFAToffset + FS_ENTRY_STATUS_FLAG_OFFSET,
FS_ENTRY_IN_UPDATE);
return fh;
}
}
return FS_FILE_OPEN_ERROR;
}
return FS_FILE_OPEN_ERROR; /* Has no meaning, just for the compiler */
}
/*******************************************************************************
* mvFSClose - Closes a file.
*
* DESCRIPTION:
* This function closes a file by removing the file's entry from the file
* system's data base , updating the file's FAT entry and data block's
* status flags and offset . After calling this function , the virtual EOF
* character is created by updating the last block<EFBFBD>s 9 bits of the next
* block pointer if data was not appended to that block . If data was
* appended , the offset field of the last block of data will be updated
* (as described at the Introduction ).
*
* INPUT:
* fileName - A string containing the file name.
*
* OUTPUT:
* None.
*
* RETURN:
* The return value can be either FS_FILE_CLOSED on seccess or
* FILE_CLOSE_ERROR in one of the following reasons:
* - If the handler is out of range (bigger or equal to MAX_NUM_OF_ENTRIES
* defind in mvFS.h).
* - If the handler points to an entry with a FREE_ENTRY status.
*
*******************************************************************************/
unsigned int mvFSClose(FS_FILE_HANDLER fileHandler)
{
unsigned int FATentryOffset,nextBlockPointer,prevBlockPointer;
unsigned int offset;
if(fileHandler >= FS_MAX_NUM_OF_ENTRIES)
return FS_FILE_CLOSE_ERROR;
if(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY)
return FS_FILE_CLOSE_ERROR;
/* mode = "r" */
if(mvFSEntries[fileHandler].mode[0] == 'r' &&
mvFSEntries[fileHandler].mode[1] == '\0')
{
mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY;
return FS_FILE_CLOSED;
}
/* mode = "r+","w","w+" or "a+" */
FATentryOffset = mvFSEntries[fileHandler].pointerToFAT;
/* Empty file => next block pointer == 0xFFFFFFFF */
nextBlockPointer = mvFlash32Rd(mvFlashInfo, FATentryOffset);
if(nextBlockPointer == 0xffffffff)
{
if(mvFlash8Rd(mvFlashInfo, FATentryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) ==
FS_ENTRY_IN_UPDATE)
{
/* Update the file's entry status flag */
mvFlash8Wr(mvFlashInfo, FATentryOffset + FS_ENTRY_STATUS_FLAG_OFFSET,
FS_ENTRY_IN_USE);
}
mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY;
return FS_FILE_CLOSED;
}
/* search for the last block */
prevBlockPointer = FATentryOffset;
while(mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK) != 0xffffffff)
{
prevBlockPointer = nextBlockPointer;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK);
}
if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_STATUS_FLAG_OFFSET) == FS_BLOCK_IN_USE)
{
/* Old block, need to use the offset field */
if(!((mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK) ||
(mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_OFFSET) != 0xffff)))
{
/* File was modified */
/* We need to update the offset field */
if(prevBlockPointer == FATentryOffset)
{
offset = mvFlash32Rd(mvFlashInfo, prevBlockPointer) & FS_BLOCK_OFFSET;
}
else
{
offset = mvFlash32Rd(mvFlashInfo, prevBlockPointer &
FS_BLOCK_OFFSET_MASK) & FS_BLOCK_OFFSET;
}
offset = (mvFSEntries[fileHandler].EOFpointer
& FS_BLOCK_OFFSET) - offset;
mvFlash16Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_OFFSET,offset);
}
/* else - File not modified */
mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY;
return FS_FILE_CLOSED;
}
else
{
/* Update the block's status flag */
mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_STATUS_FLAG_OFFSET,FS_BLOCK_IN_USE);
/* Update the offset at the previous block's next block pointer */
offset = mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET;
if(prevBlockPointer != FATentryOffset)
{
offset = (mvFlash32Rd(mvFlashInfo, prevBlockPointer & FS_BLOCK_OFFSET_MASK)
& FS_BLOCK_OFFSET_MASK) | offset;
mvFlash32Wr(mvFlashInfo, prevBlockPointer & FS_BLOCK_OFFSET_MASK,offset);
}
else /* prevBlockPointer == FATentryOffset */
{
offset = (mvFlash32Rd(mvFlashInfo, prevBlockPointer) & FS_BLOCK_OFFSET_MASK)
| offset;
mvFlash32Wr(mvFlashInfo, prevBlockPointer, offset);
}
mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY;
}
return FS_FILE_CLOSED;
}
/*******************************************************************************
* mvFSFileSize - Counts the number of bytes the file consist of.
*
* DESCRIPTION:
* This function counts and return the number of bytes the file consist of.
* If the file handler delivered to the function is erroneous the function
* will return the value 0xFFFFFFFF.
*
* INPUT:
* fileHandler - The file handler to count its bytes.
*
* OUTPUT:
* None.
*
* RETURN:
* The file's number of bytes of the on success or 0xFFFFFFFF on failier.
*
*******************************************************************************/
unsigned int mvFSFileSize(FS_FILE_HANDLER fileHandler)
{
unsigned int numOfBytes = 0,nextBlockPointer;
if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) ||
(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY))
return 0xffffffff;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
if(nextBlockPointer == 0xffffffff)
return 0;
while(nextBlockPointer != 0xffffffff)
{
if(((nextBlockPointer & FS_BLOCK_OFFSET) + 1) != FS_BLOCK_SIZE)
{
if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK)
{
numOfBytes += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE);
}
else
{
if(mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_OFFSET) != 0xffff)
{
numOfBytes += ((nextBlockPointer & FS_BLOCK_OFFSET) +
mvFlash16Rd(mvFlashInfo, (nextBlockPointer &
FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_OFFSET) -
FS_BLOCK_HEADER_SIZE + 1);
}
else
{
numOfBytes += ((nextBlockPointer & FS_BLOCK_OFFSET) -
FS_BLOCK_HEADER_SIZE + 1);
}
}
}
else
{
if((mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET_MASK) ==
(nextBlockPointer & FS_BLOCK_OFFSET_MASK)) /* Last block */
{
numOfBytes += ((mvFSEntries[fileHandler].EOFpointer
& FS_BLOCK_OFFSET)- FS_BLOCK_HEADER_SIZE + 1);
}
else
{
numOfBytes += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE);
}
}
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK);
}
if(numOfBytes == 0)
return 0;
return numOfBytes;
}
/*******************************************************************************
* mvFSGetEOFoffset - Gets the file's EOF offset in the flash memory.
*
* DESCRIPTION:
* This function searches for the file<EFBFBD>s EOF offset relatively to the
* begining of the last block offset . The EOF offset could be either the 9
* least significant bits of the next block pointer or , if data was
* appended to last block , the offset field within that block .
*
* INPUT:
* fileName - The file name to get its EOF offset .
*
* OUTPUT:
* None.
*
* RETURN:
* The file's EOF offset or FILE_NOT_FOUND.
*
*******************************************************************************/
unsigned int mvFSGetEOFoffset(char * fileName)
{
unsigned int EOFoffset = 0,fileFAToffset,nextBlockOffset;
fileFAToffset = mvFSFileFind(fileName);
if(fileFAToffset == FS_FILE_NOT_FOUND)
return FS_FILE_NOT_FOUND;
nextBlockOffset = mvFlash32Rd(mvFlashInfo, fileFAToffset);
if(nextBlockOffset == 0xffffffff)
return 0;
while(nextBlockOffset != 0xffffffff)
{
EOFoffset = nextBlockOffset;
nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset &
FS_BLOCK_OFFSET_MASK);
}
nextBlockOffset = EOFoffset & FS_BLOCK_OFFSET_MASK;
if(mvFlash8Rd(mvFlashInfo, nextBlockOffset + FS_BLOCK_OFFSET_FLAG_OFFSET) ==
FS_FULL_BLOCK)
{
EOFoffset = nextBlockOffset + (FS_BLOCK_SIZE -
FS_BLOCK_HEADER_SIZE - 1);
}
else
{
if(mvFlash16Rd(mvFlashInfo, nextBlockOffset + FS_BLOCK_OFFSET_OFFSET)
!= 0xffff)
{
EOFoffset = EOFoffset + mvFlash16Rd(mvFlashInfo, nextBlockOffset +
FS_BLOCK_OFFSET_OFFSET);
}
else
{
return EOFoffset; /* Not necessary - just for readability */
}
}
return EOFoffset;
}
/*******************************************************************************
* mvFSGetFreeBlockForWrite - Returns the offset of a free block (if found).
*
* DESCRIPTION:
* This function searches for a free block in more efficient way than
* <EFBFBD>fileSysGetFreeBlock<EFBFBD> function by saving the last free block offset
* that was found in the previous search and searches from that point. In
* case it couldnt find a free block , it uses the function
* <EFBFBD>fileSysGetFreeBlock<EFBFBD>.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
* If during the copying of the sector containing the most free dirty block
* to the dynamic memory the system will loose power the file system will
* crash.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Offset to a free block , FS_NO_FREE_BLOCKS if there are no more free
* blocks or the file system was not initilized (use <EFBFBD>fileSysInit<EFBFBD> before
* using this function in that case).
*
*******************************************************************************/
unsigned int mvFSGetFreeBlockForWrite()
{
unsigned char status;
nextFreeBlock += FS_BLOCK_SIZE;
if((nextFreeBlock == 0xffffffff) ||
((nextFreeBlock != 0xffffffff) && (nextFreeBlock >= mvFSTopOffset)))
{
nextFreeBlock = mvFSGetFreeBlock();
return nextFreeBlock;
}
else
{
while(1)
{
status = mvFlash8Rd(mvFlashInfo, nextFreeBlock +
FS_BLOCK_STATUS_FLAG_OFFSET);
if(status == FS_FREE_BLOCK)
{
return nextFreeBlock;
}
nextFreeBlock += FS_BLOCK_SIZE;
if(nextFreeBlock >= mvFSTopOffset || status == FS_FREE_DIRTY_BLOCK)
{
nextFreeBlock = mvFSGetFreeBlock();
return nextFreeBlock;
}
}
}
}
/*******************************************************************************
* mvFSGetFreeBlock - Returns the offset of a free block (if found).
*
* DESCRIPTION:
* This function searches for a free block from the begining of the file
* system ( from <EFBFBD>fileSysOffset<EFBFBD> parameter initialized by <EFBFBD>fileSysInit<EFBFBD>
* function ) to the last sector and return its offset in case it found
* one .While the function perform the search for a free block within each
* sector it also searches for the sector containing the most free dirty
* block in case a free block will not be found .If indeed a free block was
* not found ,the function erases that sector ( the one with the most free
* dirty blocks ) after copying it to a temporary buffer in the dynamic
* memory (SDRAM) and write back only the valid blocks to it .In that way
* the function free blocks from the sector containing the most free dirty
* blocks and return the next free block within that sector.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
* If during the copying of the sector containing the most free dirty block
* to the dynamic memory the system will loose power the file system will
* crash.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Offset to a free block , NO_FREE_BLOCKS if there are no more free blocks
* or the file system was not initilized (use <EFBFBD>fileSysInit<EFBFBD> before using
* this function in that case).
*
*******************************************************************************/
unsigned int mvFSGetFreeBlock()
{
unsigned int freeBlockOffset,sectorTopOffset,i;
unsigned int maxFreeDirtyBlocks = 0,sectorNumber,lastSector;
unsigned int dirtyBlocksCounter = 0,dirtyBlocksSector,blockSize;
unsigned int sectorBaseOffset,previousCounter,counterOffset;
char * rmwBlockPointer,* tempBlockPointer;
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return FS_NO_FREE_BLOCKS;
freeBlockOffset = mvFSOffset + FS_BLOCK_SIZE;
sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset);
lastSector = mvFlashNumOfSecsGet(mvFlashInfo);
dirtyBlocksSector = sectorNumber;
/* Search for a free block, while doing that I am searching for the sector
with the most dirty free blocks in case I will not find a free block */
for(i = sectorNumber ; i < lastSector ; i++)
{
sectorTopOffset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber) +
mvFlashSecSizeGet(mvFlashInfo, sectorNumber) - 1;
dirtyBlocksCounter = 0;
while(freeBlockOffset < sectorTopOffset)
{
if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FREE_BLOCK)
{
return freeBlockOffset;
}
if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FREE_DIRTY_BLOCK) dirtyBlocksCounter++;
freeBlockOffset += FS_BLOCK_SIZE;
}
if(dirtyBlocksCounter > maxFreeDirtyBlocks)
{
maxFreeDirtyBlocks = dirtyBlocksCounter;
dirtyBlocksSector = sectorNumber;
}
sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset);
}
/* We are here since we have'nt found a free block */
/* Lets check if we have a free dirty block */
if(maxFreeDirtyBlocks > 0)
{
/* Now we need to perform the read modify write dispensing the free
dirty blocks */
blockSize = mvFlashSecSizeGet(mvFlashInfo, dirtyBlocksSector);
sectorBaseOffset = mvFlashSecOffsGet(mvFlashInfo, dirtyBlocksSector);
rmwBlockPointer = (char *)malloc(blockSize);
if(rmwBlockPointer == NULL) return FS_NO_FREE_BLOCKS;
/* Read the block */
for(i = 0 ; i < blockSize ; i++)
{
rmwBlockPointer[i] = mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i);
}
/* Erase the sector */
if(mvFlash32Rd(mvFlashInfo, mvFSOffset + FS_ERSAING_COUNTER_FLAG_OFFSET)
== FS_ENABLE_ERASING_COUNTER)
{
counterOffset = sectorBaseOffset + blockSize - FS_BLOCK_SIZE;
previousCounter = mvFlash32Rd(mvFlashInfo, counterOffset);
mvFlashSecErase(mvFlashInfo, dirtyBlocksSector);
mvFlash32Wr(mvFlashInfo, counterOffset, previousCounter + 1);
mvFlash8Wr(mvFlashInfo, counterOffset + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_USED_FOR_ERASING_COUNTER);
blockSize -= FS_BLOCK_SIZE;
}
else
{
mvFlashSecErase(mvFlashInfo, dirtyBlocksSector);
}
/* Write back only the valid blocks */
for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE)
{
if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] ==
FS_BLOCK_IN_USE || rmwBlockPointer[i +
FS_BLOCK_STATUS_FLAG_OFFSET] == FS_BLOCK_IN_UPDATE ||
rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == FS_FAT_BLOCK)
{
tempBlockPointer = rmwBlockPointer + i;
mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + i, FS_BLOCK_SIZE,
(MV_U8 *)tempBlockPointer);
}
}
free(rmwBlockPointer);
for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE)
{
if(mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i +
FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FREE_BLOCK)
return (sectorBaseOffset + i);
}
}
return FS_NO_FREE_BLOCKS;
}
/*******************************************************************************
* mvFSGetFreeEntry - Finds a free entry in the FAT and returns its offset.
*
* DESCRIPTION:
* This function finds a free entry in the FAT and returns its offset.
* During the search for a free entry the function also finds the sector
* containing the most free dirty entries . If the fuction cant find any
* free entry within the FAT it copies the sector containing the most free
* dirty entries to the dynamic memory (SDRAM), erase that sector and write
* back only the valid entries. In that way the function free space for
* new entries and return the next free entry offset.
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
* If during the copying of the sector containing the most free dirty
* enrties to the dynamic memory the system will loose power the file
* system will crash.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Offset to a free entry , NO_FREE_ENTRIES if there are no more free
* entries in the file system`s FAT or the file system was not initialized
* (use <EFBFBD>fileSysInit<EFBFBD> before using this function in that case).
*
*******************************************************************************/
unsigned int mvFSGetFreeEntry()
{
unsigned int nextBlockOffset,sectorNumber,i,previousSector;
unsigned int dirtyEntriesCounter = 0,dirtyEntriesSector,blockSize,j;
unsigned int maxFreeDirtyBlocks = 0;
unsigned int sectorBaseOffset,previousCounter,counterOffset;
char * rmwBlockPointer,* tempBlockPointer;
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return FS_NO_FREE_ENTRIES;
/* First FAT block */
nextBlockOffset = mvFSOffset;
sectorNumber = mvFlashInWhichSec(mvFlashInfo, nextBlockOffset);
dirtyEntriesSector = sectorNumber;
previousSector = sectorNumber;
while(nextBlockOffset != 0xffffffff)
{
if(previousSector != sectorNumber)
{
if(dirtyEntriesSector > maxFreeDirtyBlocks)
{
maxFreeDirtyBlocks = dirtyEntriesSector;
dirtyEntriesSector = sectorNumber;
}
previousSector = sectorNumber;
dirtyEntriesSector = 0;
}
sectorNumber = mvFlashInWhichSec(mvFlashInfo, nextBlockOffset);
for(i = 0 ; i < FS_BLOCK_SIZE ; i += FS_FAT_FILE_ENTRY_SIZE)
{
if(mvFlash8Rd(mvFlashInfo, nextBlockOffset +i+ FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_FREE_ENTRY)
return (nextBlockOffset + i);
if(mvFlash8Rd(mvFlashInfo, nextBlockOffset +i+ FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_FREE_DIRTY_ENTRY)
dirtyEntriesCounter++;
}
nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset);
}
/* Now we need to perform the read modify write dispensing the free
dirty entries and blocks */
blockSize = mvFlashSecSizeGet(mvFlashInfo, dirtyEntriesSector);
sectorBaseOffset = mvFlashSecOffsGet(mvFlashInfo, dirtyEntriesSector);
rmwBlockPointer = (char *)malloc(blockSize);
if(rmwBlockPointer == NULL) return FS_NO_FREE_ENTRIES;
/* Read the block */
for(i = 0 ; i < blockSize ; i++)
{
rmwBlockPointer[i] = mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i);
}
/* Erase the sector */
if(mvFlash32Rd(mvFlashInfo, mvFSOffset + 20) == FS_ENABLE_ERASING_COUNTER)
{
counterOffset = sectorBaseOffset + blockSize - FS_BLOCK_SIZE;
previousCounter = mvFlash32Rd(mvFlashInfo, counterOffset);
mvFlashSecErase(mvFlashInfo, dirtyEntriesSector);
mvFlash32Wr(mvFlashInfo, counterOffset,previousCounter + 1);
mvFlash8Wr(mvFlashInfo, counterOffset + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_USED_FOR_ERASING_COUNTER);
blockSize -= FS_BLOCK_SIZE;
}
else
{
mvFlashSecErase(mvFlashInfo, dirtyEntriesSector);
}
/* Write back only the valid blocks */
for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE)
{
if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] ==
FS_BLOCK_IN_USE || rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET]
== FS_BLOCK_IN_UPDATE)
{
tempBlockPointer = rmwBlockPointer + i;
mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + i, FS_BLOCK_SIZE,
(MV_U8 *)tempBlockPointer);
}
if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == FS_FAT_BLOCK)
{
for(j = FS_FAT_FILE_ENTRY_SIZE ; j < FS_BLOCK_SIZE ;
j+= FS_FAT_FILE_ENTRY_SIZE)
{
if(rmwBlockPointer[j + FS_ENTRY_STATUS_FLAG_OFFSET]
== FS_ENTRY_IN_USE ||
rmwBlockPointer[j + FS_ENTRY_STATUS_FLAG_OFFSET]
== FS_ENTRY_IN_UPDATE)
{
tempBlockPointer = rmwBlockPointer + j;
mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + j,
FS_FAT_FILE_ENTRY_SIZE, (MV_U8 *)tempBlockPointer);
}
}
}
}
free(rmwBlockPointer);
for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE)
{
if(mvFlash32Rd(mvFlashInfo, sectorBaseOffset + i + FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FAT_BLOCK)
{
for(j = i + FS_FAT_FILE_ENTRY_SIZE ; j < (i + FS_BLOCK_SIZE) ;
j+= FS_FAT_FILE_ENTRY_SIZE)
{
if(mvFlash32Rd(mvFlashInfo, sectorBaseOffset +j+
FS_ENTRY_STATUS_FLAG_OFFSET) == FS_FREE_ENTRY)
return (sectorBaseOffset + j);
}
}
}
return FS_NO_FREE_ENTRIES;
}
/*******************************************************************************
* mvFSWriteFileNameToFATentry - Write the file name to an entry in the FAT .
*
* DESCRIPTION:
* This function writes the file name to an entry in the FAT.The function
* extarcts the file name and extention and write it to the entry at
* <EFBFBD>entryOffset<EFBFBD> within the FAT.
*
* INPUT:
* entryOffset - Pointer to the desired entry to write the file name at.
* fileName - The file name and extention.
*
* OUTPUT:
* None.
*
* RETURN:
* 0 for invalid file name, 1 for success.
*
*******************************************************************************/
unsigned int mvFSWriteFileNameToFATentry(unsigned int entryOffset,
char * fileName)
{
char name[FS_FILE_NAME_LENGTH];
char ext[FS_FILE_EXT_LENGTH];
unsigned int index,extIndex;
/* Extract the name */
for(index = 0 ; index < FS_FILE_NAME_LENGTH ; index++)
{
if(fileName[index] == '.' || fileName[index] == '\0')
{
break;
}
else
{
name[index] = fileName[index];
}
}
/* Write the name */
if(index != 0)
mvFlashBlockWr(mvFlashInfo, entryOffset + FS_FILE_NAME_OFFSET, index, (MV_U8 *)name);
if(index == 0 && fileName[index] == '\0') /* Not a valid name */
return 0;
if(fileName[index] == '\0') /* No extension */
return 1;
/* Extract the extension */
index++; /* Skip the dot */
for(extIndex = 0 ; extIndex < FS_FILE_EXT_LENGTH ; extIndex++)
{
if(fileName[index + extIndex] == '\0')
{
// ronen fix a bug ---> extIndex++;
break;
}
else
{
ext[extIndex] = fileName[index + extIndex];
}
}
/* Write the extension */
if(extIndex != 0)
mvFlashBlockWr(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET, extIndex, (MV_U8 *)ext);
return 1;
}
/*******************************************************************************
* mvFSReadFileNameFromFATentry - Read the file name from an entry in the FAT.
*
* DESCRIPTION:
* This function reads the file name from an entry in the FAT. If the given
* entry is not used by any file , the function will return 0 to remark a
* failier.
*
* INPUT:
* entryOffset - Pointer to the desired entry to read the file name from.
* fileName - pointer to an empty array to be filled by this functoin with
* the file name and extention.
* OUTPUT:
* None.
*
* RETURN:
* 0 for failure, 1 for success.
*
*
*******************************************************************************/
unsigned int mvFSReadFileNameFromFATentry(unsigned int entryOffset,
char * fileName)
{
unsigned int index = 0,offset;
unsigned char c;
if( (mvFlash8Rd(mvFlashInfo, entryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_USE) ||
(mvFlash8Rd(mvFlashInfo, entryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_UPDATE) )
{
for(offset = 0 ; offset < FS_FILE_NAME_LENGTH ; offset++)
{
c = mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_NAME_OFFSET + offset);
if(c == 0xff)
break;
fileName[index++] = c;
}
if(mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET) != 0xff)
{
fileName[index++] = '.';
for(offset = 0 ; offset < FS_FILE_EXT_LENGTH ; offset++)
{
c = mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET + offset);
if(c == 0xff) break;
fileName[index++] = c;
}
}
fileName[index++] = '\0';
return 1;
}
return 0;
}
/*******************************************************************************
* mvFSWrite - Writes a block of data to an opened file.
*
* DESCRIPTION:
* This function writes a block of data to a file opened by all modes
* except mode <EFBFBD>r<EFBFBD> indicating the file is a read only file. The function
* will append the data to the last block ( if the offset flag is not set
* yet ) or to a new block if this is a new file , the function also takes
* care of updating the EOF pointer , updating the file's entry and data
* blocks status flags. During the write attempt , the function will
* return 0 value in the following cases:
* - if the given file handler is invalid that is , grater or equal to
* MAX_NUM_OF_ENTRIES (defined in mvFS.h).
* - if the entry of the file handler holds the status FREE_ENTRY.
* - if the <EFBFBD>numberOfBytes<EFBFBD> parameter is 0.
* - if this is the first write attempt to the file ( new file ) , the
* function will allocate a new block for the data , in this case a
* failier can occur resulting from lack of free blocks. In all other
* cases the function will return the number of bytes actually written.
* Note that the number of bytes actually written returned by this
* function may not be equal to the <EFBFBD>numberOfBytes<EFBFBD> parameter , in that
* case consider the write action as a fatal error and do not try to
* re-write the data.
*
* INPUT:
* fileHandler - The file handler of the file to be written.
* numOfBytes - The number of bytes to be written from the data array.
* block - The data array to write to the file.
*
* OUTPUT:
* None.
*
* RETURN:
* Returns the number of bytes actually written, if the number of
* bytes actually written is not equal to the numberOfBytes consider it as
* a fatal error, do not try to re-write the data.
*
*******************************************************************************/
unsigned int mvFSWrite(FS_FILE_HANDLER fileHandler,
unsigned int numberOfBytes,char * block)
{
unsigned int remainingBytes,nextBlockPointer,newBlockPointer,blockSize;
unsigned int freeBytesInBlock,writtenBytes,blockIndex = 0;
unsigned int totalWrittenBytes = 0,numberOfBlocks,i;
blockSize = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE;
if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) ||
(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY) ||
numberOfBytes == 0)
return 0;
if(mvFSEntries[fileHandler].mode[0] == 'r' &&
mvFSEntries[fileHandler].mode[1] == '\0')
return 0; /* File was opened as read only */
nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
remainingBytes = numberOfBytes;
if(nextBlockPointer == 0xffffffff)
{
/* New file, no blocks allocated yet */
newBlockPointer = mvFSGetFreeBlock();
mvFSEntries[fileHandler].blockPointer = newBlockPointer;
if(newBlockPointer == FS_NO_FREE_BLOCKS)
return 0;
/* Update the entry's status flag and next block pointer */
mvFlash32Wr(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT,
newBlockPointer | FS_BLOCK_OFFSET);
mvFlash8Wr(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT +
FS_ENTRY_STATUS_FLAG_OFFSET, FS_ENTRY_IN_USE);
/* Start writing the data */
if(numberOfBytes <= blockSize)
{
/* Only one block needed */
/* Update the blocks status flag */
mvFlash8Wr(mvFlashInfo, newBlockPointer + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_IN_UPDATE);
/* Update the EOFpointer */
mvFSEntries[fileHandler].EOFpointer = newBlockPointer
+ numberOfBytes + FS_BLOCK_HEADER_SIZE - 1;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
/* Write the data */
return
mvFlashBlockWr(mvFlashInfo, newBlockPointer + FS_BLOCK_HEADER_SIZE,
numberOfBytes, (MV_U8 *)block);
}
else /* More than one block is needed */
{
/* I will take care of the first block in here, the rest
will be handled later in the fuction */
/* Update the block's status flag */
mvFlash8Wr(mvFlashInfo, newBlockPointer + FS_BLOCK_STATUS_FLAG_OFFSET,
FS_BLOCK_IN_USE);/* Fully exploited block */
/* Write the data */
writtenBytes = mvFlashBlockWr(mvFlashInfo, newBlockPointer +
FS_BLOCK_HEADER_SIZE, blockSize, (MV_U8 *)block);
/* Update the EOFpointer */
mvFSEntries[fileHandler].EOFpointer = newBlockPointer
+ writtenBytes + FS_BLOCK_HEADER_SIZE - 1;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
if(writtenBytes != blockSize)
return writtenBytes; /* Write operation failed */
totalWrittenBytes += writtenBytes;
remainingBytes = numberOfBytes - blockSize;
nextBlockPointer = newBlockPointer;
blockIndex += blockSize;
}
}
/* Search for the last block */
while(mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK) !=
0xffffffff)
{
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
}
freeBytesInBlock = FS_BLOCK_SIZE - 1 -
(mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET);
if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_STATUS_FLAG_OFFSET) == FS_BLOCK_IN_USE)
{
/* We can use the offset flag to append data, or the FS_FULL_BLOCK
flag in case the block will be fully exploited */
if(freeBytesInBlock != 0)
{
if((remainingBytes < freeBytesInBlock) &&
mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_OFFSET) == 0xffff)
{
writtenBytes = mvFlashBlockWr(mvFlashInfo,
mvFSEntries[fileHandler].EOFpointer + 1,
remainingBytes, (MV_U8 *)&block[blockIndex]);
mvFSEntries[fileHandler].EOFpointer += writtenBytes;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
if(remainingBytes == freeBytesInBlock)
{
mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_FLAG_OFFSET, FS_FULL_BLOCK);
}
/* else the OFFSET will be updated by mvFSClose */
return writtenBytes;
}
else
{
if(remainingBytes >= freeBytesInBlock)
{
writtenBytes = mvFlashBlockWr(mvFlashInfo,
mvFSEntries[fileHandler].EOFpointer + 1,
freeBytesInBlock, (MV_U8 *)&block[blockIndex]);
mvFSEntries[fileHandler].EOFpointer += freeBytesInBlock;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
totalWrittenBytes += writtenBytes;
if(writtenBytes != freeBytesInBlock) /* error */
return totalWrittenBytes;
mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_OFFSET_FLAG_OFFSET, FS_FULL_BLOCK);
remainingBytes -= freeBytesInBlock;
blockIndex += freeBytesInBlock;
}
}
}
}
else /* The block is not sealed yet, we can simply append the data */
{
if(remainingBytes <= freeBytesInBlock)
{
writtenBytes = mvFlashBlockWr(mvFlashInfo,
mvFSEntries[fileHandler].EOFpointer + 1,
remainingBytes, (MV_U8 *)&block[blockIndex]);
mvFSEntries[fileHandler].EOFpointer += writtenBytes;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
if(remainingBytes == freeBytesInBlock)
{
mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE);
}
return writtenBytes;
}
else /* More blocks are needed */
{
/* Fill the current block */
writtenBytes = mvFlashBlockWr(mvFlashInfo,
mvFSEntries[fileHandler].EOFpointer + 1,
freeBytesInBlock, (MV_U8 *)&block[blockIndex]);
mvFSEntries[fileHandler].EOFpointer += writtenBytes;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
totalWrittenBytes += writtenBytes;
if(writtenBytes != freeBytesInBlock) /* error */
return totalWrittenBytes;
mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE);
remainingBytes -= freeBytesInBlock;
blockIndex += freeBytesInBlock;
}
}
numberOfBlocks = remainingBytes / blockSize;
for(i = 0 ; i < numberOfBlocks ; i++)
{
/* All the blocks in this loop will be fully exploited */
newBlockPointer = mvFSGetFreeBlockForWrite();
if(newBlockPointer == FS_NO_FREE_BLOCKS)
return totalWrittenBytes;
/* Update the nextBlockPointer */
mvFlash32Wr(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK,
newBlockPointer | FS_BLOCK_OFFSET);
/* Update the status flag */
mvFlash8Wr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE);
/* Write The Data */
writtenBytes = mvFlashBlockWr(mvFlashInfo, (newBlockPointer &
FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_HEADER_SIZE, blockSize,
(MV_U8 *)&block[blockIndex]);
blockIndex += blockSize;
totalWrittenBytes += writtenBytes;
/* Make sure the EOFpointer is set for error handling */
mvFSEntries[fileHandler].EOFpointer = (newBlockPointer
& FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE + writtenBytes - 1;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
if(writtenBytes != blockSize)/* Error */
return totalWrittenBytes;
remainingBytes -= blockSize;
nextBlockPointer = newBlockPointer;
}
if(remainingBytes == 0)
return totalWrittenBytes;
/* Allocate a new block for the remaining bytes */
newBlockPointer = mvFSGetFreeBlockForWrite();
if(newBlockPointer == FS_NO_FREE_BLOCKS)
return totalWrittenBytes;
/* Update the nextBlockPointer */
mvFlash32Wr(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK,
newBlockPointer | FS_BLOCK_OFFSET);
/* Update the status flag */
mvFlash8Wr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_UPDATE);
/* Write The Data */
writtenBytes = mvFlashBlockWr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_HEADER_SIZE, remainingBytes,
(MV_U8 *)&block[blockIndex]);
mvFSEntries[fileHandler].EOFpointer = (newBlockPointer
& FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE + writtenBytes - 1;
/* Update the File pointer */
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
totalWrittenBytes += writtenBytes;
return totalWrittenBytes;
}
/*******************************************************************************
* mvFSGetNumOfValidBytes - Return the number of valid bytes from
* blockOffsetPointer to the end of the block.
*
* DESCRIPTION:
* None.
*
* INPUT:
* blockPointer - The offset of the block to read its valid bytes.
* blockOffsetPointer - The offset within the block to read the valid
* bytes from.
* EOFpointer - The EOF offset.
* OUTPUT:
* None.
*
* RETURN:
* Number of valid bytes.
*
*******************************************************************************/
unsigned int mvFSGetNumOfValidBytes(unsigned int blockPointer,
unsigned int blockOffsetPointer,
unsigned int EOFpointer)
{
if((blockOffsetPointer & FS_BLOCK_OFFSET_MASK) ==
(EOFpointer & FS_BLOCK_OFFSET_MASK))
{
/* This is the last block */
if(EOFpointer > blockOffsetPointer)
return (EOFpointer - blockOffsetPointer);
else
return 0;
}
else
{
if((mvFlash8Rd(mvFlashInfo, (blockOffsetPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK)
|| ((blockPointer & FS_BLOCK_OFFSET) == FS_BLOCK_OFFSET))
{
return (FS_BLOCK_SIZE - 1 - (blockOffsetPointer & FS_BLOCK_OFFSET));
}
else /* offset field is used */
{
return ((blockPointer & FS_BLOCK_OFFSET) + mvFlash16Rd(mvFlashInfo,
(blockPointer & FS_BLOCK_OFFSET_MASK) + FS_BLOCK_OFFSET_OFFSET)
- (blockOffsetPointer & FS_BLOCK_OFFSET));
}
}
}
/*******************************************************************************
* mvFSRead - Read a block of data into block from a file.
*
* DESCRIPTION:
* This function reads a block of data from a file opened by all modes
* except <EFBFBD> w <EFBFBD> mode , into a given block (<EFBFBD>block<EFBFBD> parameter ) .While the
* file is opened , the function will start reading the file from the
* begining if its the first read attempt after opening the file or from
* the last point within the block of data were the previous read action
* ended .The read action will not exceed the EOF pointer if the
* <EFBFBD>numberOfBytes<EFBFBD> parameter is larger than the whole file or the number of
* bytes left from the previous read action . During the read attempt , the
* function will return an error code or 0 in the following cases:
*
* - if the given file handler is invalid that is , grater or equal to
* MAX_NUM_OF_ENTRIES (defined in fileSys.h).
* - if the entry of the file handler within the dynamic database holds the
* status FREE_ENTRY .
* - if the mode of the opened file is write only - <EFBFBD> w<EFBFBD> .
* - if the EOF pointer is equal to the file pointer that indicates the
* curruent position within the file.
* - if the <EFBFBD>nextBlockPointer<EFBFBD> field within the entry in the FAT is equal
* to 0xFFFFFFFF indicating the file is empty.
* In a successfull read operation the function will return the number of
* bytes read , if this value is not equal to the <EFBFBD>numberOfBytes<EFBFBD>
* parameter delivered to the function , the read action reached EOF.
*
* INPUT:
* fileHandler - The file handler of the file to be read.
* numOfBytes - The number of bytes to be read from the file to the data
* array.
* block - The data array to hold the read data from the file.
*
* OUTPUT:
* block filled with data from the file.
*
* RETURN:
* The number of bytes actually read . If this value is not equal to the
* <EFBFBD>numberOfBytes<EFBFBD> parameter delivered to the function , the read action
* reached EOF.The function can also return the following values in case of
* an error :
* - FILE_READ_ERROR if the fileHandler is larger or equal to
* MAX_NUM_OF_ENTRIES defined in fileSys.h or if the status flag of the
* file entry in the dynamic database holds the value FREE_ENTRY.
* - 0 if the file was opened as write only , the EOF pointer is equal to
* the file pointer indicating the current loaction within the file or
* the <EFBFBD>nextBlockPointer<EFBFBD> field within the file entry in the flash is
* equal to 0xFFFFFFFF (empty file).
*
*******************************************************************************/
unsigned int mvFSRead(FS_FILE_HANDLER fileHandler,
unsigned int numberOfBytes,char * block)
{
unsigned int blockIndex = 0,nextBlockPointer,EOFpointer;
unsigned int remainingBytes,freeBytesInBlock,bytesRead;
unsigned int totalBytesRead = 0,blockSize;
if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) ||
(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY) ||
numberOfBytes == 0)
return FS_FILE_READ_ERROR;
if(mvFSEntries[fileHandler].mode[0] == 'w' &&
mvFSEntries[fileHandler].mode[1] == '\0')
return 0; /* File was opened as write only */
if(mvFSEntries[fileHandler].EOFpointer ==
mvFSEntries[fileHandler].filePointer)
return 0;
blockSize = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE;
EOFpointer = mvFSEntries[fileHandler].EOFpointer;
remainingBytes = numberOfBytes;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
if(nextBlockPointer == 0xffffffff)
return 0; /* An empty file */
if(mvFSEntries[fileHandler].filePointer == 0)
{
/* Read one byte and set the filePointer to the first block */
block[blockIndex] = mvFlash8Rd(mvFlashInfo, (nextBlockPointer
& FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE);
remainingBytes--;
totalBytesRead++;
mvFSEntries[fileHandler].filePointer = (nextBlockPointer
& FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_HEADER_SIZE;
blockIndex++;
mvFSEntries[fileHandler].blockPointer= nextBlockPointer;
}
else
{
/* update the block's file pointer */
nextBlockPointer = mvFSEntries[fileHandler].blockPointer;
}
while(1)
{
if((mvFSEntries[fileHandler].filePointer & FS_BLOCK_OFFSET_MASK) !=
(nextBlockPointer & FS_BLOCK_OFFSET_MASK))
{ /* Forward the file pointer to the current block */
block[blockIndex] = mvFlash8Rd(mvFlashInfo, (nextBlockPointer
& FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_HEADER_SIZE);
remainingBytes--;
totalBytesRead++;
mvFSEntries[fileHandler].filePointer = (nextBlockPointer
& FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_HEADER_SIZE;
blockIndex++;
}
freeBytesInBlock = mvFSGetNumOfValidBytes(nextBlockPointer,
mvFSEntries[fileHandler].filePointer,
EOFpointer);
if(freeBytesInBlock <= remainingBytes)
{
bytesRead = mvFlashBlockRd(mvFlashInfo, mvFSEntries[fileHandler].filePointer
+1,freeBytesInBlock, (MV_U8 *)&block[blockIndex]);
remainingBytes -= bytesRead;
totalBytesRead += bytesRead;
mvFSEntries[fileHandler].filePointer += bytesRead;
blockIndex += bytesRead;
if(bytesRead != freeBytesInBlock) /* Fatal error */
{
return totalBytesRead;
}
}
else
{
bytesRead = mvFlashBlockRd(mvFlashInfo, mvFSEntries[fileHandler].filePointer
+1,remainingBytes,(MV_U8 *)&block[blockIndex]);
totalBytesRead += bytesRead;
mvFSEntries[fileHandler].filePointer += bytesRead;
blockIndex += bytesRead;
if(bytesRead != remainingBytes) /* Fatal error */
{
return totalBytesRead;
}
remainingBytes -= bytesRead;
}
if(((nextBlockPointer & FS_BLOCK_OFFSET_MASK) ==
(EOFpointer & FS_BLOCK_OFFSET_MASK)) || remainingBytes == 0)
{ /* Last valid block */
return totalBytesRead;
}
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
}
return totalBytesRead;
}
/*******************************************************************************
* mvFSRewind - Set the file pointer the beginning of the file.
*
* DESCRIPTION:
* This function set the file pointer the beginning of the given file.
*
* INPUT:
* fileHandler - The file handler of the file to rewind its pointer.
*
* OUTPUT:
* None.
*
* RETURN:
* 0 on succes otherwise 0xffffffff.
*
*******************************************************************************/
unsigned int mvFSRewind(FS_FILE_HANDLER fileHandler)
{
if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) ||
(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY))
return 0xffffffff;
mvFSEntries[fileHandler].filePointer = 0;
return 0;
}
/*******************************************************************************
* mvFSSeek - Move the file pointer from the origin specified.
*
* DESCRIPTION:
* This function move<EFBFBD>s the file-pointer associated with <EFBFBD>filehandler<EFBFBD> to a
* new location that is <EFBFBD>offset<EFBFBD> bytes from <EFBFBD>origin<EFBFBD>.The argument <EFBFBD>origin<EFBFBD>
* must be one of the following constants , defined in mvFS.h :
*
* SEEK_CUR - Current position of file pointer.
* SEEK_END - End of file.
* SEEK_SET - Beginning of file.
*
* The <EFBFBD>offset<EFBFBD> argument indicates the number of bytes to move relatively
* to <EFBFBD>origin<EFBFBD>.
*
* INPUT:
* fileHandler - The file-handler of the file to reposition its
* file-pointer.
* Offset - The number of bytes to move the file pointer from <EFBFBD>origin<EFBFBD>.
* Origin - The relative point within the file to move the file-pointer
* <EFBFBD>offset<EFBFBD> bytes from it.Must be one of the three values
* described above.
*
* OUTPUT:
* File-pointer located on its new place ( on success ).
*
* RETURN:
* true on succes, 0xffffffff otherwise.
*
*******************************************************************************/
unsigned int mvFSSeek(FS_FILE_HANDLER fileHandler,int offset,int origin)
{
unsigned int nextBlockPointer,fileSize;
unsigned int validBytes,temp;
int tempSize = 0,tempOffset = 0;
if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) ||
(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY))
return 0xffffffff;
fileSize = mvFSFileSize(fileHandler);
if(fileSize == 0xffffffff || fileSize == 0)
return 0xffffffff;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
switch(origin)
{
case FS_SEEK_END:
if(offset <= 0)
return 1/*true*/;
if((unsigned int)offset >= fileSize)
{
mvFSEntries[fileHandler].filePointer = 0;
return 1/*true*/;
}
offset = fileSize - offset;
break;
case FS_SEEK_SET:
if(offset <= 0)
{
mvFSEntries[fileHandler].filePointer = 0;
return 1/*true*/;
}
if((unsigned int)offset >= fileSize)
{
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
return 1/*true*/;
}
while(tempOffset < offset)
{
validBytes = mvFSGetNumOfValidBytes(nextBlockPointer,
(nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_HEADER_SIZE,
mvFSEntries[fileHandler].EOFpointer);
if((tempOffset + (int)validBytes) >= offset)
break;
tempOffset += validBytes;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer
& FS_BLOCK_OFFSET_MASK);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
}
mvFSEntries[fileHandler].filePointer =
(nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
(offset - tempOffset) + FS_BLOCK_HEADER_SIZE - 1;
return 1/*true*/;
case FS_SEEK_CUR: /* In this case offset can be negative */
if(offset == 0)
return 1/*true*/;
/* tempSize = Size in bytes up-to filePointer */
temp = nextBlockPointer;
nextBlockPointer =
mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
while(nextBlockPointer != 0xffffffff)
{
if(mvFSEntries[fileHandler].filePointer == 0)
break;
if((mvFSEntries[fileHandler].filePointer & FS_BLOCK_OFFSET_MASK) ==
(nextBlockPointer & FS_BLOCK_OFFSET_MASK)) /* Last block for us*/
{
tempSize += (mvFSEntries[fileHandler].filePointer
& FS_BLOCK_OFFSET) - FS_BLOCK_HEADER_SIZE + 1;
break;
}
if(((nextBlockPointer & FS_BLOCK_OFFSET) + 1) != FS_BLOCK_SIZE)
{
if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK)
{
tempSize += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE);
}
else
{
if(mvFlash16Rd(mvFlashInfo, (nextBlockPointer &
FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_OFFSET) != 0xffff)
{
tempSize += ((nextBlockPointer & FS_BLOCK_OFFSET) +
mvFlash16Rd(mvFlashInfo, (nextBlockPointer &
FS_BLOCK_OFFSET_MASK) +
FS_BLOCK_OFFSET_OFFSET) -
FS_BLOCK_HEADER_SIZE + 1);
}
else
{
tempSize += ((nextBlockPointer & FS_BLOCK_OFFSET) -
FS_BLOCK_HEADER_SIZE + 1);
}
}
}
else
{
tempSize += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE);
}
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer &
FS_BLOCK_OFFSET_MASK);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
}
nextBlockPointer = temp;
offset = tempSize + offset;
if(offset >= (int)fileSize)
{
mvFSEntries[fileHandler].filePointer =
mvFSEntries[fileHandler].EOFpointer;
return 1/*true*/;
}
if(offset <= (int)0)
{
mvFSEntries[fileHandler].filePointer = 0;
return 1/*true*/;
}
while(tempOffset < offset)
{
validBytes = mvFSGetNumOfValidBytes(nextBlockPointer,
(nextBlockPointer & FS_BLOCK_OFFSET_MASK)
+ FS_BLOCK_HEADER_SIZE,
mvFSEntries[fileHandler].EOFpointer);
if((tempOffset + (int)validBytes) >= offset)
break;
tempOffset += validBytes;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer
& FS_BLOCK_OFFSET_MASK);
mvFSEntries[fileHandler].blockPointer = nextBlockPointer;
}
mvFSEntries[fileHandler].filePointer =
(nextBlockPointer & FS_BLOCK_OFFSET_MASK) +
(offset - tempOffset) + FS_BLOCK_HEADER_SIZE - 1;
return 1/*true*/;
default:
return 0xffffffff;
}
return 0xffffffff;
}
/*******************************************************************************
* mvFSReadErasingCounter - Reads the value of the erasing counter (if
* implemented).
*
* DESCRIPTION:
* This function reads the value of the erasing counter ( if implemented )
* of the given sector .The erasing counter is enabled by the function
* <EFBFBD>fileSysFormat<EFBFBD> (by the <EFBFBD>mode<EFBFBD> parameter) . It is implimented by
* allocating one block at the end of each sector and it helps monitoring
* the number of erasures of the sector the counter is at .
* NOTE:
* he file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD> function
* before using this function .
*
* INPUT:
* sectorNumber - The sector number to read its erasing counter
* (if implemented).
*
* OUTPUT:
* None.
*
* RETURN:
* The vlaue of the erasing counter, 0xffffffff in case the erasing
* counter was not implemented or the sector number is not valid.
*
*******************************************************************************/
unsigned int mvFSReadErasingCounter(unsigned int sectorNumber)
{
unsigned int counterValue,sectorBaseAddr,sectorSize;
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return 0xffffffff;
if(mvFlash32Rd(mvFlashInfo, mvFSOffset + FS_ERSAING_COUNTER_FLAG_OFFSET) !=
FS_ENABLE_ERASING_COUNTER)
return 0xffffffff;
if((sectorBaseAddr = mvFlashSecOffsGet(mvFlashInfo, sectorNumber)) == 0xffffffff)
return 0xffffffff;
if(sectorBaseAddr < mvFSOffset)
return 0xffffffff;
sectorSize = mvFlashSecSizeGet(mvFlashInfo, sectorNumber);
counterValue = mvFlash32Rd(mvFlashInfo, sectorBaseAddr + sectorSize - FS_BLOCK_SIZE);
return counterValue;
}
/*******************************************************************************
* mvFSGetFreeSize - Returns the number of free bytes in the file system.
*
* DESCRIPTION:
* This function returns the number of free bytes in the entire file
* system. It counts the number of free blocks and dirty blocks ( blocks
* that are no longer in use by any file ) from the begining of the
* file-system to the end , and return that value multiply by block size
* (in bytes).
* NOTE:
* The file system's data base must be initialized by <EFBFBD>fileSysInit<EFBFBD>
* function before using this function .
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Number of free bytes in the entire file-system on success, 0xFFFFFFFF
* otherwise.
*
*******************************************************************************/
unsigned int mvFSGetFreeSize()
{
unsigned int freeBlockOffset,sectorTopOffset,i;
unsigned int sectorNumber,lastSector;
unsigned int dirtyBlocksCounter = 0,dirtyBlocksSector;
unsigned int freeBlocksCounter = 0;
/* Check if the file system's data base was initialized */
if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED)
return 0xffffffff;
freeBlockOffset = mvFSOffset + FS_BLOCK_SIZE;
sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset);
lastSector = mvFlashNumOfSecsGet(mvFlashInfo);
dirtyBlocksSector = sectorNumber;
for(i = sectorNumber ; i < lastSector ; i++)
{
sectorTopOffset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber) +
mvFlashSecSizeGet(mvFlashInfo, sectorNumber) - 1;
while(freeBlockOffset < sectorTopOffset)
{
if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FREE_BLOCK) freeBlocksCounter++;
if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET)
== FS_FREE_DIRTY_BLOCK) dirtyBlocksCounter++;
freeBlockOffset += FS_BLOCK_SIZE;
}
sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset);
}
return (freeBlocksCounter + dirtyBlocksCounter) *
(FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE);
}
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/***********************************************************************/
/* ask the user to give a file name and chck if the file already exist.*/
/***********************************************************************/
MV_VOID get_filename(MV_8 *fileName, MV_BOOL exeType)
{
int i;
extern MV_8 console_buffer[];
while(1)
{
i = 0;
printf("Enter name & extension for the file (maximum %d characters for the name)\n",
FS_FILE_NAME_LENGTH);
readline(" # ");
strcpy(fileName, console_buffer);
while( i < FS_FILE_NAME_LENGTH &&
fileName[i] != '\0' && fileName[i] != ' ') i++;
fileName[i] = '\0';
if(i == 0)
{
strcpy(fileName,"NoName");
i = 6;
fileName[i] = '\0';
}
/* if exe file type */
if(exeType == MV_TRUE){
i = 0;
while(fileName[i] != '.' && i < FS_FILE_NAME_LENGTH &&
fileName[i] != '\0') i++;
fileName[i] = '.';
fileName[i+1] = 'e';
fileName[i+2] = 'x';
fileName[i+3] = 'e';
fileName[i+4] = '\0';
}
if (mvFSFileFind(fileName) != FS_FILE_NOT_FOUND)
{
printf("File already exists, overwrite? (Y/N)\n");
readline(" ? ");
if(strcmp(console_buffer,"N") == 0 || strcmp(console_buffer,"no") == 0 ||
strcmp(console_buffer,"n") == 0)
{
continue;
}
else
{
if(mvFSDelete(fileName) != FS_FILE_DELETED)
{
printf("File could not be deleted!\n");
continue;
}
else
{
break;
}
}
}
else
{
break;
}
}
return;
}
/***********************************************/
/* load a file to the flash FS using the tftp. */
/***********************************************/
int
tftpfs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
int filesize;
MV_8 fileName[CFG_CBSIZE];
MV_U32 status;
FS_FILE_HANDLER fileHandler;
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
load_addr = 0x400000;
if(argc == 2) {
copy_filename (BootFile, argv[1], sizeof(BootFile));
}else{ printf ("Usage:\n%s\n", cmdtp->usage);
return 0;
}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
if ((filesize = NetLoop(TFTP)) < 0)
return 0;
/* done if no file was loaded (no errors though) */
if (filesize <= 0)
return 0;
/* get a file name from the user */
get_filename(fileName,MV_FALSE);
fileHandler = mvFSOpen(fileName,"w");
if(fileHandler == FS_FILE_OPEN_ERROR)
{
printf("ERROR: Can't open file!\n");
return 0;
}
if(mvFSWrite(fileHandler,filesize,(MV_8 *)load_addr) != filesize)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
printf("File loaded to file system successfully...\n");
mvFSClose(fileHandler);
return 1;
}
U_BOOT_CMD(
FStftp, 2, 1, tftpfs_cmd,
"FStftp - tftp a file to the Flash MV FS\n",
" filename.\n"
"\tDownload a file through the network interface to the DRAM(0x400000) using\n"
"\ttftp, and copy the file to the MV Flash FS.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/***********************************************/
/* load a file to the flash FS using the tftp. */
/***********************************************/
int
tftpefs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int filesize;
char fileName[CFG_CBSIZE],c;
unsigned int status, entryAddress;
FS_FILE_HANDLER fileHandler;
unsigned char addressBuffer[8];
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
if(argc == 3) {
entryAddress = simple_strtoul(argv[1], NULL, 16);
load_addr = entryAddress;
copy_filename (BootFile, argv[2], sizeof(BootFile));
}else{
printf ("Usage:\n%s %d\n", cmdtp->usage,argc);
return 0;
}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
if ((filesize = NetLoop(TFTP)) < 0)
return 0;
/* done if no file was loaded (no errors though) */
if (filesize <= 0)
return 0;
/* get a file name from the user */
get_filename(fileName,MV_TRUE);
fileHandler = mvFSOpen(fileName,"w");
if(fileHandler == FS_FILE_OPEN_ERROR)
{
printf("ERROR: Can't open file!\n");
return 0;
}
/* Set the entry address for the file */
c = (entryAddress >> 28) & 0x0f;
if(c < 10)
addressBuffer[0] = c + '0';
else
addressBuffer[0] = c + 'A' - 10;
c = (entryAddress >> 24) & 0x0f;
if(c < 10)
addressBuffer[1] = c + '0';
else
addressBuffer[1] = c + 'A' - 10;
c = (entryAddress >> 20) & 0x0f;
if(c < 10)
addressBuffer[2] = c + '0';
else
addressBuffer[2] = c + 'A' - 10;
c = (entryAddress >> 16) & 0x0f;
if(c < 10)
addressBuffer[3] = c + '0';
else
addressBuffer[3] = c + 'A' - 10;
c = (entryAddress >> 12) & 0x0f;
if(c < 10)
addressBuffer[4] = c + '0';
else
addressBuffer[4] = c + 'A' - 10;
c = (entryAddress >> 8) & 0x0f;
if(c < 10)
addressBuffer[5] = c + '0';
else
addressBuffer[5] = c + 'A' - 10;
c = (entryAddress >> 4) & 0x0f;
if(c < 10)
addressBuffer[6] = c + '0';
else
addressBuffer[6] = c + 'A' - 10;
c = (entryAddress) & 0x0f;
if(c < 10)
addressBuffer[7] = c + '0';
else
addressBuffer[7] = c + 'A' - 10;
if(mvFSWrite(fileHandler,8,(char *)addressBuffer)!= 8)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
if(mvFSWrite(fileHandler,filesize,(char *)load_addr) != filesize)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
printf("File loaded to file system successfully...\n");
mvFSClose(fileHandler);
return 1;
}
U_BOOT_CMD(
FStftpe, 3, 1, tftpefs_cmd,
"FStftpe - tftp an exe file to the Flash MV FS\n",
" entry_address filename.\n"
"\tDownload a file through the network interface to entry_address using\n"
"\ttftp, and copy the file to the MV Flash FS.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/**************************************************/
/* load a file to the flash FS using the loadnet. */
/**************************************************/
#if 0
int
loadfs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
int filesize;
MV_8 fileName[CFG_CBSIZE];
MV_U32 status,addr = 0x20000;
FS_FILE_HANDLER fileHandler;
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
filesize = load_net(&addr);
printf("\nFile loaded successfully...\n");
printf("File size: %d bytes.\n",filesize);
/* done if no file was loaded (no errors though) */
if (filesize <= 0)
return 0;
/* get a file name from the user */
get_filename(fileName, MV_FALSE);
fileHandler = mvFSOpen(fileName,"w");
if(fileHandler == FS_FILE_OPEN_ERROR)
{
printf("ERROR: Can't open file!\n");
return 0;
}
if(mvFSWrite(fileHandler,filesize,(MV_8 *)addr) != filesize)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
printf("File loaded to file system successfully...\n");
mvFSClose(fileHandler);
return 1;
}
U_BOOT_CMD(
FSlf, 1, 1, loadfs_cmd,
"FSlf - Load a file to the Flash MV FS\n",
" \n"
"\tLoad S-Record file via the first available ethernet port, to the DRAM\n"
"\t(0x200000) and copy it to the MV Flash FS.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
#endif
/*******************************************************/
/* load an exe file to the flash FS using the loadnet. */
/*******************************************************/
#if 0
int
loadexefs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
int filesize;
MV_8 fileName[CFG_CBSIZE],c;
MV_U32 status,entryAddress = 0x0;
FS_FILE_HANDLER fileHandler;
MV_U8 addressBuffer[8];
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
filesize = load_net(&entryAddress);
printf("\nFile loaded successfully...\n");
printf("File size: %d bytes.\n",filesize);
/* done if no file was loaded (no errors though) */
if (filesize <= 0)
return 0;
/* get a file name from the user */
get_filename(fileName, MV_TRUE);
fileHandler = mvFSOpen(fileName,"w");
if(fileHandler == FS_FILE_OPEN_ERROR)
{
printf("ERROR: Can't open file!\n");
return 0;
}
/* Set the entry address for the file */
c = (entryAddress >> 28) & 0x0f;
if(c < 10)
addressBuffer[0] = c + '0';
else
addressBuffer[0] = c + 'A' - 10;
c = (entryAddress >> 24) & 0x0f;
if(c < 10)
addressBuffer[1] = c + '0';
else
addressBuffer[1] = c + 'A' - 10;
c = (entryAddress >> 20) & 0x0f;
if(c < 10)
addressBuffer[2] = c + '0';
else
addressBuffer[2] = c + 'A' - 10;
c = (entryAddress >> 16) & 0x0f;
if(c < 10)
addressBuffer[3] = c + '0';
else
addressBuffer[3] = c + 'A' - 10;
c = (entryAddress >> 12) & 0x0f;
if(c < 10)
addressBuffer[4] = c + '0';
else
addressBuffer[4] = c + 'A' - 10;
c = (entryAddress >> 8) & 0x0f;
if(c < 10)
addressBuffer[5] = c + '0';
else
addressBuffer[5] = c + 'A' - 10;
c = (entryAddress >> 4) & 0x0f;
if(c < 10)
addressBuffer[6] = c + '0';
else
addressBuffer[6] = c + 'A' - 10;
c = (entryAddress) & 0x0f;
if(c < 10)
addressBuffer[7] = c + '0';
else
addressBuffer[7] = c + 'A' - 10;
if(mvFSWrite(fileHandler,8,(MV_8 *)addressBuffer)!= 8)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
if(mvFSWrite(fileHandler,filesize,(MV_8 *)entryAddress)!= filesize)
{
printf("ERROR: Writing data to file.\n");
return 0;
}
printf("File loaded to file system successfully...\n");
mvFSClose(fileHandler);
return 1;
}
U_BOOT_CMD(
FSlef, 1, 1, loadexefs_cmd,
"FSlef - Load an exe file to the Flash MV FS\n",
" \n"
"\tLoad S-Record EXE file via the first available ethernet port to the DRAM\n"
"\t(0x200000) and copy it to the MV Flash FS.\n"
"\tAfter load is complete the EXE file can be run by using: FSrun filename.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
#endif
/*********************************************************************************
* Load Exe file from the Flash FS.
*********************************************************************************/
MV_U32 loadExe(MV_8 * fname)
{
register MV_U32 byteCount;
register MV_U32 entryAddress = 0xffffffff;
MV_8 addressBuffer[9];
FS_FILE_HANDLER fileHandler;
MV_U32 nextBlockPointer, sourceAddress, destAddress, status;
MV_U32 mvFlashBaseAddress;
mvFlashBaseAddress = MV_BOARD_FLASH_BASE_ADRS;
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return entryAddress;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return entryAddress;
}
if((fileHandler = mvFSOpen(fname,"r")) == FS_FILE_OPEN_ERROR)
{
printf("ERROR in file open\n");
return entryAddress;
}
/* Extract the file's entry address */
mvFSRead(fileHandler,8,addressBuffer);
addressBuffer[8]='\0';
entryAddress = simple_strtoul(addressBuffer, NULL, 16);
debug("entryAddress = %x \n",entryAddress);
nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT);
/* The First block contain the address, thus treated differently */
byteCount = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE - 8 /* Address size */ ;
destAddress = entryAddress;
sourceAddress = (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + mvFlashBaseAddress
+ FS_BLOCK_HEADER_SIZE + 8/* Address size */;
/* Flush the block from the cache before executing it */
debug("memcpy transfer src %x dst %x bytecnt %x\n",\
sourceAddress,destAddress,byteCount);
memcpy((void *)destAddress, (void *)sourceAddress, byteCount);
destAddress += byteCount;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK);
byteCount = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE;
while(nextBlockPointer != 0xffffffff)
{
sourceAddress = (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + mvFlashBaseAddress
+ FS_BLOCK_HEADER_SIZE;
memcpy((MV_U32*)destAddress,(MV_U32*)sourceAddress,byteCount);
destAddress += byteCount;
nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK);
}
mvFSClose(fileHandler);
return entryAddress;
}
int runexeFS_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
MV_8 fileName[CFG_CBSIZE];
MV_U32 i,entryAddress;
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
if(argc >= 2) {
copy_filename(fileName, argv[1], sizeof(fileName));
}else{ printf ("Usage:\n%s\n", cmdtp->usage);
return 0;
}
for(i = 0 ; i < FS_FILE_NAME_LENGTH; i++)
{
if(fileName[i] == '.')
break;
if(fileName[i] == '\0')
{
fileName[i] = '.';
fileName[i+1] = 'e';
fileName[i+2] = 'x';
fileName[i+3] = 'e';
fileName[i+4] = 0;
break;
}
}
if((entryAddress = loadExe(fileName)) == 0xffffffff)
{
printf ("%s: Command not found.\n", fileName);
return 0;
}
mv_go(entryAddress, --argc, &argv[1]);
return 1;
}
U_BOOT_CMD(
FSrun, CFG_MAXARGS, 1, runexeFS_cmd,
"FSrun - Load an exe file from the Flash MV FS and run it\n",
" filename\n"
"\tLoad an exe file 'filename' from the Flash MV FS and run it.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/******************************************************************************
* Functionality- The commands allows the user to view the contents of a file
* located in the file system.
*****************************************************************************/
int type_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
MV_8 fileName[128]={},readBuffer[101],key;
FS_FILE_HANDLER fileHandler;
MV_U32 readCount=0, newLineCount=0, flagm,readCounttmp, lineCount=0,i;
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
if(argc == 2) {
copy_filename(fileName, argv[1], sizeof(fileName));
}else{ printf ("Usage:\n%s\n", cmdtp->usage);
return 0;
}
fileHandler = mvFSOpen(fileName,"r");
if(fileHandler != FS_FILE_OPEN_ERROR)
{
while(readCount < mvFSFileSize(fileHandler))
{
readCounttmp = mvFSRead(fileHandler,100,readBuffer);
readBuffer[100] = '\0';
if(readCounttmp < 100)
readBuffer[readCounttmp] = '\0';
readCount += readCounttmp;
lineCount += readCounttmp;
for(i = 0 ; i <= readCounttmp ; i++)
if(readBuffer[i] == '\n')
newLineCount++;
printf("%s",readBuffer);
if(newLineCount >= 20 || lineCount > 1600)
{
flagm = 0;
while(1)
{
key = getc();
switch(key)
{
case ' ':
flagm = 1;
newLineCount = 0;
lineCount = 0;
break;
case 'x':
mvFSClose(fileHandler);
printf("\n");
return 1;
}
if(flagm == 1)
break;
}
}
}
}
mvFSClose(fileHandler);
printf("\n");
return 1;
}
U_BOOT_CMD(
FStype, CFG_MAXARGS, 1, type_cmd,
"FStype - cat file from the Flash MV FS\n",
" filename \n"
"\tDisplay an ascii file 'filename' found on the MV Flash FS.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/******************************************************************************
* Functionality- Formats the mvFlash mvMemory at a given offset
*****************************************************************************/
int format_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
MV_U32 offset =0,result;
extern MV_8 console_buffer[];
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
if(argc == 2) {
offset = simple_strtoul(argv[1], NULL, 16);
}else{ printf ("Usage:\n%s\n", cmdtp->usage);
return 0;
}
printf("\a\a\aThis action will erase the FLASH Memory!!!\n");
printf("Are you sure (y/n) ");
readline(" ? ");
if(strcmp(console_buffer,"y") == 0 || strcmp(console_buffer,"yes") == 0 || strcmp(console_buffer,"Y") == 0)
{
if(offset == 0xffffffff)
{
printf("Bad offset!\n");
}
result = mvFSFormat(offset,FS_NO_ERASING_COUNTER);
if(result == FS_VALID_FILE_SYS_IN_LOWER_OFFSET)
{
printf("ERROR: FS_VALID_FILE_SYS_IN_LOWER_OFFSET\n");
return 0;
}
if(result == FS_FLASH_MEMORY_NOT_PRESENT)
{
printf("ERROR: FS_FLASH_MEMORY_NOT_PRESENT\n");
return 1;
}
printf("Flash Memory formated successfully, actual offset is: %x\n"
,result);
}
return 1;
}
U_BOOT_CMD(
FSformat, 2, 1, format_cmd,
"FSformat- format the Flash MV FS\n",
" address \n"
"\tInitialize the MV Flash FS starting at offset 'address' in the Flash.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/******************************************************************************
* Functionality- Display the list of files currently on the system (file name + size)
*****************************************************************************/
int dir_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
MV_U32 fileEntryOffset,nextBlockOffset,mvFSOffset;
MV_U32 status,i,j,spaces = 20;
FS_FILE_HANDLER fileHandler;
MV_8 fileName[20];
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
if(status != FS_SYSTEM_ALREADY_INITIALIZED)
{
printf("Number of files in system: %d\n",status);
}
mvFSOffset = mvFSSearchForSignature();
nextBlockOffset = mvFSOffset;
while(nextBlockOffset != 0xffffffff)
{
/* Skip the block's header */
fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE;
for(i = 0 ; i < 15 ; i++)
{
if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET)
== FS_ENTRY_IN_USE)
{
mvFSReadFileNameFromFATentry(fileEntryOffset,fileName);
fileHandler = mvFSOpen(fileName,"r");
printf("%s",fileName);
spaces = 22 - strlen(fileName);
for(j = 0 ; j < spaces ; j++)
printf(" ");
printf("size: %d bytes\n",mvFSFileSize(fileHandler));
mvFSClose(fileHandler);
}
/* point to the next entry */
fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE;
}
nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset);
}
printf("\n %d free bytes\n",
mvFSGetFreeSize());
return 1;
}
U_BOOT_CMD(
FSdir, 1, 1, dir_cmd,
"FSdir - ls the Flash MV FS\n",
" \n"
"\tDisplay the MV Flash FS contents.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
/******************************************************************************
* Functionality- Deletes a file from the system
*****************************************************************************/
int del_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[])
{
MV_U32 status;
MV_8 cmd[30];
if(!enaMonExt()){
printf("This command can be used only if enaMonExt is set!\n");
return 0;}
if(argc == 2) {
copy_filename (cmd, argv[1], sizeof(cmd));
}else{ printf ("Usage:\n%s\n", cmdtp->usage);
return 0;
}
status = mvFSInit(FS_NO_CACHE);
if(status == FS_NO_VALID_FAT_STRING)
{
printf("ERROR: FS_NO_VALID_FAT_STRING\n");
return 0;
}
if(status == FS_OFFSET_OUT_OF_RANGE)
{
printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n");
return 0;
}
if(mvFSFileFind(cmd) != FS_FILE_NOT_FOUND)
{
if(mvFSDelete(cmd) == FS_FILE_DELETED)
{
printf("File deleted\n");
}
}
else
{
printf("%s:No such file\n",cmd);
}
return 1;
}
U_BOOT_CMD(
FSdel, 2, 1, del_cmd,
"FSdel - del a file from the Flash MV FS\n",
" filename \n"
"\tDelete a file 'filename' from the MV Flash FS.\n"
"\t(This command can be used only if enaMonExt is set!)\n"
);
#endif /* CONFIG_COMMANDS & CFG_CMD_BSP */
#endif /* MV_INC_BOARD_NOR_FLASH */