From 65409d2312e702a48d3cf5b32479d25266bda3c3 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 1 Jan 2020 18:22:19 -0800 Subject: 5858 Move script to create a Soso boot image into a sub-directory. I'm trying to streamline newcomer attention to just a couple of use cases. --- tools/iso/kernel.soso/fatfilesystem.c | 601 ++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 tools/iso/kernel.soso/fatfilesystem.c (limited to 'tools/iso/kernel.soso/fatfilesystem.c') diff --git a/tools/iso/kernel.soso/fatfilesystem.c b/tools/iso/kernel.soso/fatfilesystem.c new file mode 100644 index 00000000..9e3c2116 --- /dev/null +++ b/tools/iso/kernel.soso/fatfilesystem.c @@ -0,0 +1,601 @@ +#include "fatfilesystem.h" +#include "common.h" +#include "fs.h" +#include "alloc.h" +#include "fatfs_ff.h" +#include "fatfs_diskio.h" +#include "screen.h" + +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 + +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 + +static BOOL mount(const char* sourcePath, const char* targetPath, uint32 flags, void *data); +static BOOL checkMount(const char* sourcePath, const char* targetPath, uint32 flags, void *data); +static FileSystemDirent* readdir(FileSystemNode *node, uint32 index); +static FileSystemNode* finddir(FileSystemNode *node, char *name); +static int32 read(File *file, uint32 size, uint8 *buffer); +static int32 write(File *file, uint32 size, uint8 *buffer); +static int32 lseek(File *file, int32 offset, int32 whence); +static int32 stat(FileSystemNode *node, struct stat* buf); +static BOOL open(File *file, uint32 flags); +static void close(File *file); + +static FileSystemDirent gFileSystemDirent; + +static FileSystemNode* gMountedBlockDevices[FF_VOLUMES]; + + +void initializeFatFileSystem() { + FileSystem fs; + memset((uint8*)&fs, 0, sizeof(fs)); + strcpy(fs.name, "fat"); + fs.mount = mount; + fs.checkMount = checkMount; + + registerFileSystem(&fs); + + for (int i = 0; i < FF_VOLUMES; ++i) { + gMountedBlockDevices[i] = NULL; + } +} + +static BOOL mount(const char* sourcePath, const char* targetPath, uint32 flags, void *data) { + printkf("fat mount source: %s\n", sourcePath); + + FileSystemNode* node = getFileSystemNode(sourcePath); + if (node && node->nodeType == FT_BlockDevice) { + FileSystemNode* targetNode = getFileSystemNode(targetPath); + if (targetNode) { + if (targetNode->nodeType == FT_Directory) { + printkf("fat mount target: %s\n", targetPath); + + int32 volume = -1; + for (int32 v = 0; v < FF_VOLUMES; ++v) { + if (NULL == gMountedBlockDevices[v]) { + volume = v; + break; + } + } + + if (volume < 0) { + return FALSE; + } + + FileSystemNode* newNode = kmalloc(sizeof(FileSystemNode)); + + memset((uint8*)newNode, 0, sizeof(FileSystemNode)); + strcpy(newNode->name, targetNode->name); + newNode->nodeType = FT_Directory; + newNode->open = open; + newNode->readdir = readdir; + newNode->finddir = finddir; + newNode->parent = targetNode->parent; + newNode->mountSource = node; + newNode->privateNodeData = (void*)volume; + + gMountedBlockDevices[volume] = node; + + FATFS* fatFs = (FATFS*)kmalloc(sizeof(FATFS)); + //uint8 work[512]; + //FRESULT fr = f_mkfs("", FM_FAT | FM_SFD, 512, work, 512); + //printkf("f_mkfs: %d\n", fr); + char path[8]; + sprintf(path, "%d:", volume); + FRESULT fr = f_mount(fatFs, path, 1); + //printkf("f_mount: fr:%d drv:%d\n", fr, fatFs->pdrv); + + if (FR_OK == fr) { + targetNode->nodeType |= FT_MountPoint; + targetNode->mountPoint = newNode; + + return TRUE; + } + else { + kfree(newNode); + + kfree(fatFs); + + gMountedBlockDevices[volume] = NULL; + } + } + } + } + + return FALSE; +} + +static BOOL checkMount(const char* sourcePath, const char* targetPath, uint32 flags, void *data) { + FileSystemNode* node = getFileSystemNode(sourcePath); + if (node && node->nodeType == FT_BlockDevice) { + FileSystemNode* targetNode = getFileSystemNode(targetPath); + if (targetNode) { + if (targetNode->nodeType == FT_Directory) { + return TRUE; + } + } + } + + return FALSE; +} + +static FileSystemDirent* readdir(FileSystemNode *node, uint32 index) { + //when node is the root of mounted filesystem, + //node->mountSource is the source node (eg. disk partition /dev/hd1p1) + + //printkf("readdir1: node->name:%s\n", node->name); + + uint8 targetPath[128]; + + FileSystemNode *n = node; + int charIndex = 126; + memset(targetPath, 0, 128); + while (NULL == n->mountSource) { + int length = strlen(n->name); + + charIndex -= length; + + if (charIndex < 2) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), n->name); + charIndex -= 1; + targetPath[charIndex] = '/'; + + n = n->parent; + } + + char number[8]; + sprintf(number, "%d", n->privateNodeData);//volume nuber + + targetPath[charIndex] = ':'; + int length = strlen(number); + charIndex -= length; + if (charIndex < 0) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), number); + uint8* target = targetPath + charIndex; + + //printkf("readdir: targetpath:[%s]\n", target); + + DIR dir; + FRESULT fr = f_opendir(&dir, (TCHAR*)target); + if (FR_OK == fr) { + FILINFO fileInfo; + for (int i = 0; i <= index; ++i) { + memset((uint8*)&fileInfo, 0, sizeof(FILINFO)); + fr = f_readdir(&dir, &fileInfo); + + if (strlen(fileInfo.fname) <= 0) { + f_closedir(&dir); + + return NULL; + } + } + + gFileSystemDirent.inode = 0; + strcpy(gFileSystemDirent.name, fileInfo.fname); + if ((fileInfo.fattrib & AM_DIR) == AM_DIR) { + gFileSystemDirent.fileType = FT_Directory; + } + else { + gFileSystemDirent.fileType = FT_File; + } + + f_closedir(&dir); + + return &gFileSystemDirent; + } + + return NULL; +} + +static FileSystemNode* finddir(FileSystemNode *node, char *name) { + //when node is the root of mounted filesystem, + //node->mountSource is the source node (eg. disk partition /dev/hd1p1) + + //printkf("finddir1: node->name:%s name:%s\n", node->name, name); + + FileSystemNode* child = node->firstChild; + while (NULL != child) { + if (strcmp(name, child->name) == 0) { + return child; + } + + child = child->nextSibling; + } + + //If we are here, this file is accesed first time in this session. + //So we create its node... + + uint8 targetPath[128]; + + FileSystemNode *n = node; + int charIndex = 126; + memset(targetPath, 0, 128); + int length = strlen(name); + charIndex -= length; + strcpyNonNull((char*)(targetPath + charIndex), name); + charIndex -= 1; + targetPath[charIndex] = '/'; + while (NULL == n->mountSource) { + length = strlen(n->name); + charIndex -= length; + + if (charIndex < 2) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), n->name); + charIndex -= 1; + targetPath[charIndex] = '/'; + + n = n->parent; + } + + char number[8]; + sprintf(number, "%d", n->privateNodeData);//volume nuber + + targetPath[charIndex] = ':'; + length = strlen(number); + charIndex -= length; + if (charIndex < 0) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), number); + uint8* target = targetPath + charIndex; + + //printkf("finddir: targetpath:[%s]\n", target); + + FILINFO fileInfo; + memset((uint8*)&fileInfo, 0, sizeof(FILINFO)); + FRESULT fr = f_stat((TCHAR*)target, &fileInfo); + if (FR_OK == fr) { + FileSystemNode* newNode = kmalloc(sizeof(FileSystemNode)); + + memset((uint8*)newNode, 0, sizeof(FileSystemNode)); + strcpy(newNode->name, name); + newNode->parent = node; + newNode->readdir = readdir; + newNode->finddir = finddir; + newNode->open = open; + newNode->close = close; + newNode->read = read; + newNode->write = write; + newNode->lseek = lseek; + newNode->stat = stat; + newNode->length = fileInfo.fsize; + + if ((fileInfo.fattrib & AM_DIR) == AM_DIR) { + newNode->nodeType = FT_Directory; + } + else { + newNode->nodeType = FT_File; + } + + if (NULL == node->firstChild) { + node->firstChild = newNode; + } + else { + FileSystemNode* child = node->firstChild; + while (NULL != child->nextSibling) { + child = child->nextSibling; + } + child->nextSibling = newNode; + } + + //printkf("finddir: returning [%s]\n", name); + return newNode; + } + else { + //printkf("finddir error: fr: %d]\n", fr); + } + + return NULL; +} + +static int32 read(File *file, uint32 size, uint8 *buffer) { + if (file->privateData == NULL) { + return -1; + } + + FIL* f = (FIL*)file->privateData; + + UINT br = 0; + FRESULT fr = f_read(f, buffer, size, &br); + file->offset = f->fptr; + //printkf("fat read: name:%s size:%d hasRead:%d, fr:%d\n", file->node->name, size, br, fr); + if (FR_OK == fr) { + return br; + } + + return -1; +} + +static int32 write(File *file, uint32 size, uint8 *buffer) { + if (file->privateData == NULL) { + return -1; + } + + FIL* f = (FIL*)file->privateData; + + UINT bw = 0; + FRESULT fr = f_write(f, buffer, size, &bw); + file->offset = f->fptr; + if (FR_OK == fr) { + return bw; + } + + return -1; +} + +static int32 lseek(File *file, int32 offset, int32 whence) { + if (file->privateData == NULL) { + return -1; + } + + FIL* f = (FIL*)file->privateData; + + FRESULT fr = FR_INVALID_OBJECT; + + switch (whence) { + case SEEK_SET: + fr = f_lseek(f, offset); + break; + case SEEK_CUR: + fr = f_lseek(f, f_tell(f) + offset); + break; + case SEEK_END: + fr = f_lseek(f, f_size(f) + offset); + break; + default: + break; + } + + + if (FR_OK == fr) { + file->offset = f->fptr; + + return file->offset; + } + + return -1; +} + +static int32 stat(FileSystemNode *node, struct stat* buf) { + //printkf("fat stat [%s]\n", node->name); + + uint8 targetPath[128]; + + FileSystemNode *n = node; + int charIndex = 126; + memset(targetPath, 0, 128); + while (NULL == n->mountSource) { + int length = strlen(n->name); + charIndex -= length; + + if (charIndex < 2) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), n->name); + charIndex -= 1; + targetPath[charIndex] = '/'; + + n = n->parent; + } + + char number[8]; + sprintf(number, "%d", n->privateNodeData);//volume nuber + + targetPath[charIndex] = ':'; + int length = strlen(number); + charIndex -= length; + if (charIndex < 0) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), number); + uint8* target = targetPath + charIndex; + + //printkf("fat stat target:[%s]\n", target); + + FILINFO fileInfo; + memset((uint8*)&fileInfo, 0, sizeof(FILINFO)); + FRESULT fr = f_stat((TCHAR*)target, &fileInfo); + if (FR_OK == fr) { + if ((fileInfo.fattrib & AM_DIR) == AM_DIR) { + node->nodeType = FT_Directory; + } + else { + node->nodeType = FT_File; + } + + node->length = fileInfo.fsize; + + return 1; + } + + return -1; //Error +} + +static BOOL open(File *file, uint32 flags) { + //printkf("fat open %s\n", file->node->name); + + FileSystemNode *node = file->node; + + if (node->nodeType == FT_Directory) { + return TRUE; + } + + uint8 targetPath[128]; + + FileSystemNode *n = node; + int charIndex = 126; + memset(targetPath, 0, 128); + while (NULL == n->mountSource) { + int length = strlen(n->name); + charIndex -= length; + + if (charIndex < 2) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), n->name); + charIndex -= 1; + targetPath[charIndex] = '/'; + + n = n->parent; + } + + char number[8]; + sprintf(number, "%d", n->privateNodeData);//volume nuber + + targetPath[charIndex] = ':'; + int length = strlen(number); + charIndex -= length; + if (charIndex < 0) { + return NULL; + } + + strcpyNonNull((char*)(targetPath + charIndex), number); + uint8* target = targetPath + charIndex; + + //printkf("fat open %s\n", target); + + int fatfsMode = FA_READ; + + switch (flags) { + case O_RDONLY: + fatfsMode = FA_READ; + break; + case O_WRONLY: + fatfsMode = FA_WRITE; + break; + case O_RDWR: + fatfsMode = (FA_READ | FA_WRITE); + break; + //TODO: append, create + default: + break; + } + + FIL* f = (FIL*)kmalloc(sizeof(FIL)); + FRESULT fr = f_open(f, (TCHAR*)target, fatfsMode); + if (FR_OK == fr) { + file->offset = f->fptr; + + file->privateData = f; + + return TRUE; + } + + return FALSE; +} + +static void close(File *file) { + if (file->privateData == NULL) { + return; + } + + FIL* f = (FIL*)file->privateData; + + f_close(f); + + kfree(f); + + file->privateData = NULL; +} + +DSTATUS disk_initialize( + BYTE pdrv //Physical drive nmuber +) { + return 0; +} + +DSTATUS disk_status(BYTE pdrv) { + return 0; +} + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber (0) */ + BYTE *buff, /* Pointer to the data buffer to store read data */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Number of sectors to read */ +) { + //printkf("disk_read() drv:%d sector:%d count:%d\n", pdrv, sector, count); + + if (gMountedBlockDevices[pdrv] == NULL) return RES_NOTRDY; + + //if (sector >= RamDiskSize) return RES_PARERR; + + gMountedBlockDevices[pdrv]->readBlock(gMountedBlockDevices[pdrv], (uint32)sector, count, buff); + + return RES_OK; +} + +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber (0) */ + const BYTE *buff, /* Pointer to the data to be written */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Number of sectors to write */ +) { + if (gMountedBlockDevices[pdrv] == NULL) return RES_NOTRDY; + + //if (sector >= RamDiskSize) return RES_PARERR; + + gMountedBlockDevices[pdrv]->writeBlock(gMountedBlockDevices[pdrv], (uint32)sector, count, (uint8*)buff); + + return RES_OK; +} + +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0) */ + BYTE ctrl, /* Control code */ + void* buff /* Buffer to send/receive data block */ +) { + if (gMountedBlockDevices[pdrv] == NULL) return RES_ERROR; + + DRESULT dr = RES_ERROR; + + File* f = NULL; + + uint32 value = 0; + + switch (ctrl) { + case CTRL_SYNC: + dr = RES_OK; + break; + case GET_SECTOR_COUNT: + f = open_fs(gMountedBlockDevices[pdrv], 0); + if (f) { + ioctl_fs(f, IC_GetSectorCount, &value); + *(DWORD*)buff = value; + dr = RES_OK; + close_fs(f); + } + printkf("disk_ioctl GET_SECTOR_COUNT: %d\n", value); + break; + case GET_BLOCK_SIZE: + f = open_fs(gMountedBlockDevices[pdrv], 0); + if (f) { + ioctl_fs(f, IC_GetSectorSizeInBytes, &value); + *(DWORD*)buff = value; + dr = RES_OK; + close_fs(f); + } + printkf("disk_ioctl GET_BLOCK_SIZE: %d\n", value); + *(DWORD*)buff = value; + dr = RES_OK; + break; + } + return dr; +} -- cgit 1.4.1-2-gfad0