about summary refs log tree commit diff stats
path: root/tools/iso/kernel.soso/fatfilesystem.c
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-01-01 18:22:19 -0800
committerKartik Agaram <vc@akkartik.com>2020-01-01 18:42:48 -0800
commit65409d2312e702a48d3cf5b32479d25266bda3c3 (patch)
tree62a7262fce61f2302109246da4536ce6f8e9ef80 /tools/iso/kernel.soso/fatfilesystem.c
parenta6da50ad30d2e1825575ffef497ab450a8f26e94 (diff)
downloadmu-65409d2312e702a48d3cf5b32479d25266bda3c3.tar.gz
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.
Diffstat (limited to 'tools/iso/kernel.soso/fatfilesystem.c')
-rw-r--r--tools/iso/kernel.soso/fatfilesystem.c601
1 files changed, 601 insertions, 0 deletions
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;
+}