diff --git a/includes/miniffs.h b/includes/miniffs.h index 2ed6003..91e78bb 100644 --- a/includes/miniffs.h +++ b/includes/miniffs.h @@ -10,6 +10,15 @@ #define MINIFFS_H #include +#include + +#define MINIFFS_VERSION_MAJOR (1) +#define MINIFFS_VERSION_MINOR (0) +#define MINIFFS_FILENAME_LENGTH (8) +#define MINIFFS_EXTENSION_LENGTH (3) + +/* the full name is FILENAME + '.' + EXTENSION */ +#define MINIFFS_FULLNAME_LENGTH (MINIFFS_FILENAME_LENGTH + MINIFFS_EXTENSION_LENGTH + 1) /* * The pack(1) may not be needed, but better be safe than sorry to @@ -18,8 +27,8 @@ #pragma pack(1) typedef struct fileentry_t { - char name[8]; - char ext[3]; + char name[MINIFFS_FILENAME_LENGTH]; + char ext[MINIFFS_EXTENSION_LENGTH]; uint32_t size; uint32_t offset; } fileentry_t; @@ -27,6 +36,10 @@ typedef struct fileentry_t typedef struct miniffs_header_t { uint32_t magic; + uint8_t fs_version_major; + uint8_t fs_version_minor; + uint8_t fs_filename_len; + uint8_t fs_extention_len; uint32_t entry_count; fileentry_t fent[]; } miniffs_header_t; @@ -49,9 +62,9 @@ typedef struct file_t } file_t; #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define MAKE4(_a, _b, _c, _d) (((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF) +#define MAKE4(_a, _b, _c, _d) ((((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF)) #else -#define MAKE4(_d, _c, _b, _a) (((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF) +#define MAKE4(_d, _c, _b, _a) ((((_a) & 0xFF) << 24) | (((_b) & 0xFF) << 16) | (((_c) & 0xFF) << 8) | ((_d) & 0xFF)) #endif #define MINIFFS_MAGIC MAKE4('M', 'F', 'F', 'S') @@ -67,18 +80,23 @@ enum { */ /* miniffs_openfs is backend specific and will be found in the backend header file */ -file_t *miniffs_open(miniffs_t *fs, char *filename); /***< Open a file */ -int miniffs_close(file_t *file); /***< Close a file */ -void *miniffs_map(file_t *file); /***< Map a file to memory */ -int miniffs_read(void *ptr, size_t size, size_t nmemb, file_t *file); /***< Read bytes from a file */ -int miniffs_seek(file_t *file, size_t offset, int whence); /***< Set position in a file */ -size_t miniffs_tell(file_t *file); /***< Get current position in a file*/ +file_t *miniffs_open(miniffs_t *fs, char *filename); /***< Open a file */ +int miniffs_close(file_t *file); /***< Close a file */ +void *miniffs_map(file_t *file); /***< Map a file to memory */ +int miniffs_read_blocks(void *ptr, size_t size, size_t nmemb, file_t *file); /***< Read blocks of bytes from a file */ +uint8_t miniffs_read(file_t *file); /***< Read a single byte from a file */ +int miniffs_seek(file_t *file, size_t offset, int whence); /***< Set position in a file */ +size_t miniffs_tell(file_t *file); /***< Get current position in a file*/ typedef enum miniffs_error_t { MINIFFS_NOERROR = 0, MINIFFS_INVALID_FS, + MINIFFS_INVALID_NAME, + MINIFFS_INVALID_PARAMS, MINIFFS_FILE_NOT_FOUND, + MINIFFS_ALLOCATION_ERROR, + MINIFFS_END_OF_FILE, //MINIFFS_, } miniffs_error_t; @@ -99,9 +117,10 @@ int miniffs_closefs(miniffs_t *fs); /* * Function that are private to the library */ -int miniffs_checkfs(miniffs_t *fs); +bool miniffs_isvalidfs(miniffs_t *fs); fileentry_t *miniffs_findfile(miniffs_t *fs, char *filename); - +void miniffs_seterror(miniffs_error_t err); +void *miniffs_getfileaddr(miniffs_t *fs, fileentry_t *fent); #endif /* __miniffs_internal */ #endif /* MINIFFS_H */ diff --git a/includes/platform/file.h b/includes/platform/file.h index f512a3c..10428d1 100644 --- a/includes/platform/file.h +++ b/includes/platform/file.h @@ -15,8 +15,8 @@ #ifdef BUILD_HOST_TOOLS typedef struct fs_fent_t { - char name[8]; - char ext[3]; + char name[MINIFFS_FILENAME_LENGTH]; + char ext[MINIFFS_EXTENSION_LENGTH]; bool deleted; bool mapped; uint32_t size; @@ -27,6 +27,7 @@ typedef struct fs_fent_t typedef struct miniffs_t { miniffs_header_t *header; + #ifdef BUILD_HOST_TOOLS uint32_t file_count; /***< Number of valid files in the list */ uint32_t file_list_count; /***< Number of items in the list */ @@ -35,9 +36,11 @@ typedef struct miniffs_t #endif } miniffs_t; -size_t host_map_file(char *filename, char **dest); -void host_unmap_file(char **dest, size_t length); - miniffs_t *miniffs_openfs(char *host_file); /***< Open a MiniFFS filesystem */ +#ifdef __miniffs_internal +size_t host_map_file(char *filename, char **dest); +void host_unmap_file(char **dest, size_t length); +#endif + #endif /* MINIFFS_PLATFORM_FILE_H */ diff --git a/includes/platform/memory.h b/includes/platform/memory.h index fdc0d9b..8a6c69a 100644 --- a/includes/platform/memory.h +++ b/includes/platform/memory.h @@ -15,4 +15,6 @@ typedef struct miniffs_t void *memoryOffset; } miniffs_t; +miniffs_t *miniffs_openfs(uintptr_t address); /***< Open a MiniFFS filesystem */ + #endif /* MINIFFS_PLATFORM_MEMORY_H */ diff --git a/miniffs.c b/miniffs.c index 8dbac4f..d0cfb2b 100644 --- a/miniffs.c +++ b/miniffs.c @@ -6,16 +6,180 @@ * ******************************************************************************/ +#include +#include + #define __miniffs_internal #include -int miniffs_checkfs(miniffs_t *fs) +static miniffs_error_t last_error = MINIFFS_NOERROR; + +/* Public API */ + +file_t *miniffs_open(miniffs_t *fs, char *filename) { - return 0; + file_t *ret = (file_t *)calloc(1, sizeof(file_t)); + if (ret == NULL) + { + miniffs_seterror(MINIFFS_ALLOCATION_ERROR); + goto exit; + } + + ret->private = fs; + ret->fent = miniffs_findfile(fs, filename); + if (!ret->fent) + { + miniffs_seterror(MINIFFS_FILE_NOT_FOUND); + goto free_and_exit; + } + + ret->offset = 0; + goto exit; + +free_and_exit: + free(ret); + ret = NULL; + +exit: + return ret; +} + +int miniffs_close(file_t *file) +{ + /* Let's poison the struct */ + file->private = NULL; + file->offset = 0; + file->fent = NULL; + + free(file); +} + +void *miniffs_map(file_t *file) +{ + miniffs_t *fs = (miniffs_t *)file->private; + return miniffs_getfileaddr(fs, file->fent); +} + +uint8_t miniffs_read(file_t *file) +{ + miniffs_t *fs = (miniffs_t *) file->private; + uint8_t *filePtr = miniffs_getfileaddr(fs, file->fent); + uint8_t ret = filePtr[file->offset]; + + file->offset++; + + if (file->offset >= file->fent->size) + { + miniffs_seterror(MINIFFS_END_OF_FILE); + file->offset = file->fent->size - 1; + } + + return ret; +} + +int miniffs_read_blocks(void *ptr, size_t size, size_t nmemb, file_t *file) +{ + int i; + miniffs_t *fs = (miniffs_t *) file->private; + uint8_t *filePtr = miniffs_getfileaddr(fs, file->fent); + size_t fileOffset = file->offset; + size_t bufferOffset = 0; + int blockCount = 0; + + for(i = 0; i < nmemb; i++) + { + if (file->fent->size > (fileOffset + size)) + { + memcpy(ptr + bufferOffset, &filePtr[fileOffset], size); + bufferOffset += size; + fileOffset += size; + blockCount++; + } + } + file->offset = fileOffset; + return blockCount; +} + +int miniffs_seek(file_t *file, size_t offset, int whence) +{ + switch(whence) + { + default: + miniffs_seterror(MINIFFS_INVALID_PARAMS); + return -1; + + case MFFS_SEEK_SET: + file->offset = offset; + break; + case MFFS_SEEK_CUR: + file->offset += offset; + break; + case MFFS_SEEK_END: + file->offset = file->fent->size - offset; + break; + } +} + +size_t miniffs_tell(file_t *file) +{ + return file->offset; +} + +miniffs_error_t miniffs_geterror() +{ + return last_error; +} + +/* Private API */ +bool miniffs_isvalidfs(miniffs_t *fs) +{ + return (fs->header->magic == MINIFFS_MAGIC) && + (fs->header->fs_version_major == MINIFFS_VERSION_MAJOR) && + (fs->header->fs_version_minor == MINIFFS_VERSION_MINOR) && + (fs->header->fs_filename_len == MINIFFS_FILENAME_LENGTH) && + (fs->header->fs_extention_len == MINIFFS_EXTENSION_LENGTH); +} + +static void make_fullname(char *name, char *ext, char *out) +{ + uint8_t nameLen = strnlen(name, MINIFFS_FILENAME_LENGTH); + uint8_t extLen = strnlen(ext, MINIFFS_EXTENSION_LENGTH); + + memcpy(out, name, nameLen); + memcpy(out + nameLen, ".", 1); + memcpy(out + nameLen + 1, ext, extLen); } fileentry_t *miniffs_findfile(miniffs_t *fs, char *filename) { + int i; + char entryFullName[MINIFFS_FULLNAME_LENGTH]; + uint8_t filenameLength = strlen(filename); + fileentry_t *ret = NULL; + if (filenameLength > MINIFFS_FULLNAME_LENGTH) + { + miniffs_seterror(MINIFFS_INVALID_NAME); + goto exit; + } - return NULL; + for(i = 0; i < fs->header->entry_count; i++) + { + fileentry_t *cur = &fs->header->fent[i]; + make_fullname(cur->name, cur->ext, entryFullName); + + if (memcmp(filename, entryFullName, filenameLength) == 0) + { + /* File found! */ + ret = cur; + break; + } + } + +exit: + return ret; +} + +void miniffs_seterror(miniffs_error_t err) +{ + last_error = err; } \ No newline at end of file diff --git a/miniffs_tools.c b/miniffs_tools.c index 34cbe5f..60bce49 100644 --- a/miniffs_tools.c +++ b/miniffs_tools.c @@ -8,11 +8,9 @@ #include #include #include - -#ifdef _WIN32 #include -#endif +#define __miniffs_internal #include miniffs_t *miniffs_createfs() @@ -28,8 +26,8 @@ miniffs_t *miniffs_createfs() int miniffs_addfile(miniffs_t *fs, char *name, char *ext, char *host_path) { fs_fent_t *cur; - uint8_t nameLen = strnlen(name, 8); - uint8_t extLen = strnlen(ext, 3); + uint8_t nameLen = strnlen(name, MINIFFS_FILENAME_LENGTH); + uint8_t extLen = strnlen(ext, MINIFFS_EXTENSION_LENGTH); if (fs->file_list_count == fs->file_list_size) { @@ -69,14 +67,18 @@ int miniffs_writeimage(miniffs_t *fs, char *host_path) header = (miniffs_header_t *)calloc(1, headerSize); header->magic = MINIFFS_MAGIC; + header->fs_version_major = MINIFFS_VERSION_MAJOR; + header->fs_version_minor = MINIFFS_VERSION_MINOR; + header->fs_filename_len = MINIFFS_FILENAME_LENGTH; + header->fs_extention_len = MINIFFS_EXTENSION_LENGTH; header->entry_count = fs->file_count; for(i = 0; i < fs->file_list_count; i++) { if (fs->files[i].deleted == false) { - memcpy(header->fent[fileIndex].name, fs->files[i].name, 8); - memcpy(header->fent[fileIndex].ext, fs->files[i].ext, 3); + memcpy(header->fent[fileIndex].name, fs->files[i].name, MINIFFS_FILENAME_LENGTH); + memcpy(header->fent[fileIndex].ext, fs->files[i].ext, MINIFFS_EXTENSION_LENGTH); header->fent[fileIndex].size = fs->files[i].size; header->fent[fileIndex].offset = filePosition; fileIndex ++; diff --git a/platform/file.c b/platform/file.c index 6d7db04..caadb94 100644 --- a/platform/file.c +++ b/platform/file.c @@ -18,6 +18,20 @@ #define __miniffs_internal #include +/* Exported API */ +miniffs_t *miniffs_openfs(char *host_file) +{ + return NULL; +} + + +/* Some internal functions */ +void *miniffs_getfileaddr(miniffs_t *fs, fileentry_t *fent) +{ + +} + + size_t host_map_file(char *filename, char **dest) { char *ret_ptr; diff --git a/platform/memory.c b/platform/memory.c index ed3476d..4c27078 100644 --- a/platform/memory.c +++ b/platform/memory.c @@ -7,4 +7,40 @@ ******************************************************************************/ #define __miniffs_internal -#include \ No newline at end of file +#include + +#include + +/* Public API */ +miniffs_t *miniffs_openfs(uintptr_t address) +{ + miniffs_t *fs = (miniffs_t *)calloc(1, sizeof(miniffs_t)); + if (fs == NULL) + { + miniffs_seterror(MINIFFS_ALLOCATION_ERROR); + goto exit; + } + + fs->header = (miniffs_header_t *)address; + + if (!miniffs_isvalidfs(fs)) + { + miniffs_seterror(MINIFFS_INVALID_FS); + goto free_and_exit; + } + + goto exit; + +free_and_exit: + free(fs); + fs = NULL; + +exit: + return fs; +} + +/* Private API */ +void *miniffs_getfileaddr(miniffs_t *fs, fileentry_t *fent) +{ + return fs->memoryOffset + fent->offset; +} \ No newline at end of file