#include #include #include "fs/littlefs/lfs.h" #include "vfs/vfs.h" #include "hdrs/errors.h" #include "kprintf.h" #include "dlmalloc/malloc.h" #include "hal/hal.h" int32_t littlefs_cleanup(struct VfsMountPoint *vmp) { dlfree(vmp->fs.littlefs.instance.cfg); int32_t err = vmp->backingsd->cleanup(vmp->backingsd); if (err != E_OK) { return err; } err = lfs_unmount(&vmp->fs.littlefs.instance); if (err < 0) { return E_BADIO; } return E_OK; } void littlefs_vobj_cleanup(struct VfsObj *vobj) { if (vobj->extra != NULL) { lfs_file_close(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra); dlfree(vobj->extra); } dlfree(vobj); } int32_t littlefs_vobj_read(struct VfsObj *vobj, uint8_t *const buffer, size_t n, size_t off) { spinlock_acquire(&vobj->spinlock); int ok = lfs_file_seek(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, off, LFS_SEEK_SET); if (ok < 0) { spinlock_release(&vobj->spinlock); return E_BADIO; } ok = lfs_file_read(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, buffer, n); if (ok < 0) { spinlock_release(&vobj->spinlock); return E_BADIO; } spinlock_release(&vobj->spinlock); return E_OK; } int32_t littlefs_vobj_stat(struct VfsObj *vobj, struct VfsStat *stat) { struct lfs_info statbuf; spinlock_acquire(&vobj->spinlock); int ok = lfs_stat(&vobj->vmp->fs.littlefs.instance, vobj->path, &statbuf); if (ok < 0) { spinlock_release(&vobj->spinlock); return E_BADIO; } if (statbuf.type == LFS_TYPE_REG) { stat->type = VFS_TYPE_FILE; } else if (statbuf.type == LFS_TYPE_DIR) { stat->type = VFS_TYPE_DIR; } stat->size = statbuf.size; spinlock_release(&vobj->spinlock); return E_OK; } struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32_t flags) { VfsObj *vobj = dlmalloc(sizeof(*vobj)); if (vobj == NULL) { return NULL; } hal_memset(vobj, 0, sizeof(*vobj)); spinlock_init(&vobj->spinlock); int lfs_flags = 0; lfs_file_t *file = dlmalloc(sizeof(*file)); if (file == NULL) { dlfree(vobj); return NULL; } spinlock_acquire(&vmp->spinlock); LittleFs *fs = &vmp->fs.littlefs; if (flags & VFS_FLAG_MAKE) { lfs_flags |= LFS_O_CREAT; } if (flags == VFS_FLAG_READ) { lfs_flags |= LFS_O_RDONLY; } else if (flags == VFS_FLAG_WRITE) { lfs_flags |= LFS_O_WRONLY; } else if ((flags & VFS_FLAG_READ) && (flags & VFS_FLAG_WRITE)) { lfs_flags |= LFS_O_RDWR; } int ok = lfs_file_open(&fs->instance, file, path, lfs_flags); if (ok < 0) { dlfree(vobj); dlfree(file); spinlock_release(&vmp->spinlock); return NULL; } vobj->extra = file; vobj->extrasize = sizeof(*file); vobj->vmp = vmp; vobj->cleanup = &littlefs_vobj_cleanup; vobj->read = &littlefs_vobj_read; vobj->stat = &littlefs_vobj_stat; hal_strcpy(vobj->path, path); spinlock_release(&vmp->spinlock); return vobj; } int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { VfsMountPoint *vmp = c->context; vmp->backingsd->read(vmp->backingsd, buffer, size, block * LITTLEFS_BLOCK_SIZE + off); return 0; } int portlfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { VfsMountPoint *vmp = c->context; vmp->backingsd->write(vmp->backingsd, buffer, size, block * LITTLEFS_BLOCK_SIZE + off); return 0; } int portlfs_erase(const struct lfs_config *c, lfs_block_t block) { (void)c; (void)block; return 0; } int portlfs_sync(const struct lfs_config *c) { (void)c; return 0; }