#include #include #include "vfs.h" #include "kprintf.h" #include "spinlock/spinlock.h" #include "hal/hal.h" #include "util/util.h" #include "hshtb.h" #include "assert.h" #include "errors.h" #include "fs/portlfs/portlfs.h" #include "storedev/storedev.h" #include "baseimg/baseimg.h" #include "dlmalloc/malloc.h" VfsTable VFS_TABLE; void vfs_init_littlefs(VfsMountPoint *mp, bool format) { struct lfs_config *cfg = dlmalloc(sizeof(*cfg)); hal_memset(cfg, 0, sizeof(*cfg)); cfg->context = mp; cfg->read = &portlfs_read; cfg->prog = &portlfs_prog; cfg->erase = &portlfs_erase; cfg->sync = &portlfs_sync; cfg->block_size = LITTLEFS_BLOCK_SIZE; cfg->block_count = mp->backingsd->capacity(mp->backingsd) / LITTLEFS_BLOCK_SIZE; cfg->read_size = 64; cfg->prog_size = 64; cfg->block_cycles = 16; cfg->cache_size = 64; cfg->lookahead_size = 64; cfg->read_buffer = NULL; cfg->prog_buffer = NULL; cfg->lookahead_buffer = NULL; cfg->name_max = 0; cfg->file_max = 0; cfg->attr_max = 0; if (format) { lfs_format(&mp->fs.littlefs.instance, cfg); } int err = lfs_mount(&mp->fs.littlefs.instance, cfg); if (err < 0) { ERR("vfs", "Little FS mount failed %d\n", err); } mp->cleanup = &littlefs_cleanup; mp->open = &littlefs_open; } int32_t vfs_mount(char *mountpoint, int32_t fstype, StoreDev *backingsd, bool format) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_ALLOC(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOMEMORY; } hal_memcpy(mp->label, mountpoint, hal_strlen(mountpoint)); mp->backingsd = backingsd; mp->fstype = fstype; switch (fstype) { case VFS_LITTLEFS: vfs_init_littlefs(mp, format); break; default: return E_UNKNOWN_FSTYPE; } return E_OK; } int32_t vfs_unmount(char *mountpoint) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return E_NOENTRY; } spinlock_acquire(&mp->spinlock); int32_t err = mp->cleanup(mp); if (err != E_OK) { spinlock_release(&mp->spinlock); return err; } hal_memset(mp, 0, sizeof(*mp)); spinlock_release(&mp->spinlock); return E_OK; } VfsObj *vfs_open(char *mountpoint, const char *path, uint32_t flags) { VfsMountPoint *mp = NULL; spinlock_acquire(&VFS_TABLE.spinlock); HSHTB_GET(&VFS_TABLE, mountpoints, mountpoint, label, mp); spinlock_release(&VFS_TABLE.spinlock); if (mp == NULL) { return NULL; } return mp->open(mp, path, flags); } void vfs_close(VfsObj *vobj) { vobj->cleanup(vobj); } void vfs_init(void) { hal_memset(&VFS_TABLE, 0, sizeof(VFS_TABLE)); spinlock_init(&VFS_TABLE.spinlock); { RamSdInitExtra extra = { .capacity = baseimg_getsize(), .preallocbuffer = (uint8_t *)baseimg_getaddr() }; StoreDev *backingsd = storedev_create(STOREDEV_RAMSD, &extra); if (backingsd == NULL) { return; } vfs_mount("base", VFS_LITTLEFS, backingsd, false); } { RamSdInitExtra extra = { .capacity = (1024*1024*10) }; StoreDev *backingsd = storedev_create(STOREDEV_RAMSD, &extra); if (backingsd == NULL) { return; } vfs_mount("temp", VFS_LITTLEFS, backingsd, true); } LOG("vfs", "init\n"); for (size_t i = 0; i < LEN(VFS_TABLE.mountpoints); i++) { if (!VFS_TABLE.mountpoints[i].taken) continue; VfsMountPoint *vmp = &VFS_TABLE.mountpoints[i]; LOG("vfs", "mount point %s: %s, backing device: %s\n", vmp->label, vfs_strings[vmp->fstype], storedev_strings[vmp->backingsd->sdtype]); } }