/*************************************************************************************************/ /*! * \file wsf_efs.c * * \brief Embedded File System service. * * $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $ * $Revision: 11460 $ * * Copyright (c) 2014-2017 ARM Ltd., all rights reserved. * ARM Ltd. confidential and proprietary. * * IMPORTANT. Your use of this file is governed by a Software License Agreement * ("Agreement") that must be accepted in order to download or otherwise receive a * copy of this file. You may not use or copy this file for any purpose other than * as described in the Agreement. If you do not agree to all of the terms of the * Agreement do not use this file and delete all copies in your possession or control; * if you do not have a copy of the Agreement, you must contact ARM Ltd. prior * to any use, copying or further distribution of this software. */ /*************************************************************************************************/ #include #include "wsf_types.h" #include "wsf_efs.h" #include "wsf_assert.h" #include "wsf_trace.h" #include "wsf_cs.h" #include "bstream.h" /* Media Control Block */ static pWsfEfsMedia_t wsfEfsMediaTbl[WSF_EFS_MAX_MEDIA]; /* File Control Block */ static wsfEfsControl_t wsfEfsFileTbl[WSF_EFS_MAX_FILES]; /*************************************************************************************************/ /*! * \fn wsfEfsMediaValid * * \brief Checks if the given physical media identifier has been registered with the file system. * * \param media The physical media identifier * * \return TRUE if valid, else FALSE. */ /*************************************************************************************************/ static bool_t wsfEfsMediaValid(uint8_t media) { if (media < WSF_EFS_MAX_MEDIA && wsfEfsMediaTbl[media]) { return TRUE; } return FALSE; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileByHandle * * \brief Returns the file control block for the given handle. * * \param handle Handle of the file * * \return File control block, or NULL. */ /*************************************************************************************************/ wsfEfsControl_t *WsfEfsGetFileByHandle(wsfEfsHandle_t handle) { if ((handle < WSF_EFS_MAX_FILES) && (wsfEfsFileTbl[handle].maxSize != WSF_EFS_INVALID_SIZE)) { return &wsfEfsFileTbl[handle]; } return NULL; } /*************************************************************************************************/ /*! * \fn wsfEfsFileOverlap * * \brief Checks if the given offset and size overlaps with a given file. * * \param handle The handle of the file to check against * \param media The physical medium the new file will be in * \param address The starting address in the physical medium * \param size The max size of the file * * \return TRUE if overlap, else FALSE. */ /*************************************************************************************************/ static bool_t wsfEfsFileOverlap(wsfEfsHandle_t handle, uint8_t media, uint32_t address, uint32_t size) { if (wsfEfsMediaValid(media)) { /* Check if the table entry is in use and the physical media are the same */ if (size && (wsfEfsFileTbl[handle].maxSize) && (wsfEfsFileTbl[handle].maxSize != WSF_EFS_INVALID_SIZE) && (wsfEfsFileTbl[handle].media == media)) { /* Calculate the top and bottom addresses of the files */ uint32_t top1 = wsfEfsFileTbl[handle].address; uint32_t bottom1 = wsfEfsFileTbl[handle].address + wsfEfsFileTbl[handle].maxSize - 1; uint32_t top2 = address; uint32_t bottom2 = address + size - 1; /* Check for overlap */ if ((top2 >= top1) && (top2 <= bottom1)) return TRUE; if ((bottom2 >= top1) && (bottom2 <= bottom1)) return TRUE; } } return FALSE; } /*************************************************************************************************/ /*! * \fn wsfEfsFindAvailableOffset * * \brief Finds the offset of an unused area of the physical media big enough for a file * of the given size. * * \param media The physical medium * \param size The max size of the file * * \return The next available offset. */ /*************************************************************************************************/ static uint32_t wsfEfsFindAvailableOffset(uint8_t media, uint32_t size) { if (wsfEfsMediaValid(media)) { int8_t i; uint32_t address = wsfEfsMediaTbl[media]->startAddress; for (i=0; ipageSize; i = -1; if (address + size > wsfEfsMediaTbl[media]->endAddress) return WSF_EFS_INVALID_OFFSET; } } return address; } return WSF_EFS_INVALID_OFFSET; } /*************************************************************************************************/ /*! * \fn WsfEfsInit * * \brief Initialize the embedded file system. * * \return none. */ /*************************************************************************************************/ void WsfEfsInit(void) { int8_t i; /* Clear control structures */ memset((void *) wsfEfsMediaTbl, 0, sizeof(wsfEfsMediaTbl)); /* Set maxSize to invalid indicating file is unused */ for (i=0; istartAddress; /* Increment the address to a page boundry */ if (wsfEfsMediaTbl[media]->pageSize) { address += address % wsfEfsMediaTbl[media]->pageSize; } /* Verify the given offset doesn't overlap another file */ for (i=0; isize = 0; pFile->media = media; pFile->address = address; memcpy(&pFile->attributes, pAttr, sizeof(wsfEsfAttributes_t)); /* Set the maxSize, and increment the maxSize such that it */ /* occupies a full page in the physical medium */ pFile->maxSize = maxSize; if (wsfEfsMediaTbl[media]->pageSize) { pFile->maxSize += maxSize % wsfEfsMediaTbl[media]->pageSize; } return handle; } } return WSF_EFS_INVALID_HANDLE; } /*************************************************************************************************/ /*! * \fn WsfEfsRemoveFile * * \brief Deletes a file in the embedded file system. * * \param handle Handle identifying the file. * * \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE. */ /*************************************************************************************************/ uint8_t WsfEfsRemoveFile(wsfEfsHandle_t handle) { if (handle < WSF_EFS_MAX_FILES) { wsfEfsFileTbl[handle].maxSize = WSF_EFS_INVALID_SIZE; return WSF_EFS_SUCCESS; } return WSF_EFS_FAILURE; } /*************************************************************************************************/ /*! * \fn WsfEfsErase * * \brief Clears the contents of a file without deleting the file. * * \param handle Handle identifying the file. * * \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE. */ /*************************************************************************************************/ uint8_t WsfEfsErase(wsfEfsHandle_t handle) { uint8_t status = WSF_EFS_FAILURE; wsfEfsControl_t *pFile; if ((pFile = WsfEfsGetFileByHandle(handle)) != NULL) { if (pFile->attributes.permissions & (WSF_EFS_REMOTE_ERASE_PERMITTED | WSF_EFS_LOCAL_ERASE_PERMITTED)) { uint8_t media = pFile->media; if (wsfEfsMediaTbl[media]->erase) { uint32_t address = pFile->address; uint32_t size = pFile->maxSize; status = wsfEfsMediaTbl[media]->erase(address, size); pFile->size = 0; } } } return status; } /*************************************************************************************************/ /*! * \fn WsfEfsGetAttributes * * \brief Gets the attributes of a file. * * \param handle Handle identifying the file. * \param pAttr Pointer to memory to store the attributes. * * \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE. */ /*************************************************************************************************/ uint8_t WsfEfsGetAttributes(wsfEfsHandle_t handle, wsfEsfAttributes_t *pAttr) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pAttr) { memcpy(pAttr, &pFile->attributes, sizeof(wsfEsfAttributes_t)); return WSF_EFS_SUCCESS; } return WSF_EFS_FAILURE; } /*************************************************************************************************/ /*! * \fn WsfEfsSetAttributes * * \brief Updates the attributes of a file. * * \param handle Handle identifying the file. * \param pAttr Pointer to memory to with the new attributes. * * \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE. */ /*************************************************************************************************/ uint8_t WsfEfsSetAttributes(wsfEfsHandle_t handle, wsfEsfAttributes_t *pAttr) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pAttr) { memcpy(&pFile->attributes, pAttr, sizeof(wsfEsfAttributes_t)); return WSF_EFS_SUCCESS; } return WSF_EFS_FAILURE; } /*************************************************************************************************/ /*! * \fn WsfEfsGet * * \brief Copies data from a file. * * \param handle Handle identifying the file. * \param offset Offset into the file to begin copying from. * \param pBuffer Location to copy the data to. * \param len Number of bytes to copy into pBuffer. * * \return The number of bytes read from the file. */ /*************************************************************************************************/ uint16_t WsfEfsGet(wsfEfsHandle_t handle, uint32_t offset, uint8_t *pBuffer, uint16_t len) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pBuffer) { if (pFile->attributes.permissions & (WSF_EFS_REMOTE_GET_PERMITTED | WSF_EFS_LOCAL_GET_PERMITTED)) { uint8_t media = pFile->media; if (wsfEfsMediaTbl[media]->read) { if (pFile->attributes.type == WSF_EFS_FILE_TYPE_STREAM) { wsfEfsMediaTbl[media]->read(pBuffer, 0, len); return len; } else if (offset < pFile->size) { uint32_t address = pFile->address + offset; if (offset + len > pFile->size) { len = (uint16_t) (pFile->size - offset); } wsfEfsMediaTbl[media]->read(pBuffer, address, len); return len; } } } } return 0; } /*************************************************************************************************/ /*! * \fn WsfEfsPut * * \brief Writes data to a file. * * \param handle Handle identifying the file. * \param offset Offset into the file to begin writing to. * \param pBuffer Data to write to the file. * \param len Number of bytes to write to the file. * * \return The number of bytes written to the file */ /*************************************************************************************************/ uint16_t WsfEfsPut(wsfEfsHandle_t handle, uint32_t offset, const uint8_t *pBuffer, uint16_t len) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL) && pBuffer) { if (pFile->attributes.permissions & (WSF_EFS_REMOTE_PUT_PERMITTED | WSF_EFS_LOCAL_PUT_PERMITTED)) { uint8_t media = pFile->media; if (wsfEfsMediaTbl[media]->write) { if (pFile->attributes.type == WSF_EFS_FILE_TYPE_STREAM) { wsfEfsMediaTbl[media]->write(pBuffer, 0, len); return len; } else if (offset < pFile->maxSize) { uint32_t address = pFile->address + offset; if (offset + len > pFile->maxSize) { len = (uint16_t) (pFile->maxSize - offset); } wsfEfsMediaTbl[media]->write(pBuffer, address, len); /* If writing to the end of the file, update the file size */ if (offset + len > pFile->size) { pFile->size = offset + len; } return len; } } } } return 0; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileName * * \brief Get the name of a file. * * \param handle File Handle. * * \return Filename string of a file. */ /*************************************************************************************************/ char *WsfEfsGetFileName(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->attributes.name; } return "Unknown"; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileVersion * * \brief Get the version of a file. * * \param handle File Handle. * * \return Version string of a file. */ /*************************************************************************************************/ char *WsfEfsGetFileVersion(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->attributes.version; } return "Unknown"; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileMaxSize * * \brief Get the number of bytes of memory reserved for use by a file. * * \param handle File Handle. * * \return Max size of the file. */ /*************************************************************************************************/ uint32_t WsfEfsGetFileMaxSize(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->maxSize; } return 0; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileSize * * \brief Get the size of a file. * * \param handle File Handle. * * \return Size of the file. */ /*************************************************************************************************/ uint32_t WsfEfsGetFileSize(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->size; } return 0; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFileType * * \brief Get the type of a file. * * \param handle File Handle. * * \return Type of file (bulk or stream). */ /*************************************************************************************************/ uint8_t WsfEfsGetFileType(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->attributes.type; } return WSF_EFS_FILE_TYPE_BULK; } /*************************************************************************************************/ /*! * \fn WsfEfsGetFilePermissions * * \brief Get the permissions of a file. * * \param handle File Handle. * * \return Permissions of the file. */ /*************************************************************************************************/ uint16_t WsfEfsGetFilePermissions(wsfEfsHandle_t handle) { wsfEfsControl_t *pFile; if (((pFile = WsfEfsGetFileByHandle(handle)) != NULL)) { return pFile->attributes.permissions; } return 0; } /*************************************************************************************************/ /*! * \fn WsfEfsMediaSpecificCommand * * \brief Execute a media specific command on a file. * * \param handle File Handle. * \param cmd Media specific command identifier. * \param param Ccommand specific parameter. * * \return Status of the operation. */ /*************************************************************************************************/ uint8_t WsfEfsMediaSpecificCommand(wsfEfsHandle_t handle, uint8_t cmd, uint32_t param) { if (WsfEfsGetFileByHandle(handle)) { uint8_t media = wsfEfsFileTbl[handle].media; /* Call the command handler if it exists */ if (wsfEfsMediaTbl[media]->handleCmd) { return wsfEfsMediaTbl[media]->handleCmd(cmd, param); } } return FALSE; } /*************************************************************************************************/ /*! * \fn WsfEfsRegisterMedia * * \brief Registers a File Storage Medium with the Embedded File System. * * \param pMedia Pointer to the media control structure. * \param mediaID Identifier of the media. * * \return WSF_EFS_SUCCESS or WSF_EFS_FAILURE. */ /*************************************************************************************************/ uint8_t WsfEfsRegisterMedia(const wsfEfsMedia_t *pMediaCtrl, uint8_t mediaID) { if (mediaID < WSF_EFS_MAX_MEDIA && pMediaCtrl) { wsfEfsMediaTbl[mediaID] = pMediaCtrl; /* Call the initialization function for the media */ if (pMediaCtrl->init) { pMediaCtrl->init(); } return WSF_EFS_SUCCESS; } return WSF_EFS_FAILURE; }