diff --git a/kernel/fs/portlfs/portlfs.c b/kernel/fs/portlfs/portlfs.c index fe32166..77f7880 100644 --- a/kernel/fs/portlfs/portlfs.c +++ b/kernel/fs/portlfs/portlfs.c @@ -219,13 +219,27 @@ int32_t littlefs_fetchdirent(struct VfsMountPoint *vmp, const char *path, IoctlD 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); + + uint64_t byteaddr = (uint64_t)block * c->block_size + off; + ptrdiff_t sector = byteaddr / vmp->backingsd->sectorsize; + ptrdiff_t sector_off = byteaddr % vmp->backingsd->sectorsize; + + int32_t ret = vmp->backingsd->read(vmp->backingsd, (const uint8_t *)buffer, sector, sector_off, size); + if (ret != E_OK) + return LFS_ERR_IO; 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); + + uint64_t byteaddr = (uint64_t)block * c->block_size + off; + ptrdiff_t sector = byteaddr / vmp->backingsd->sectorsize; + ptrdiff_t sector_off = byteaddr % vmp->backingsd->sectorsize; + + int32_t ret = vmp->backingsd->write(vmp->backingsd, (const uint8_t *)buffer, sector, sector_off, size); + if (ret != E_OK) + return LFS_ERR_IO; return 0; } diff --git a/kernel/fs/portlfs/portlfs.h b/kernel/fs/portlfs/portlfs.h index 10de2ec..2523312 100644 --- a/kernel/fs/portlfs/portlfs.h +++ b/kernel/fs/portlfs/portlfs.h @@ -6,7 +6,7 @@ #include "fs/littlefs/lfs.h" #include "sysdefs/ioctl.h" -#define LITTLEFS_BLOCK_SIZE 4096 +#define LITTLEFS_BLOCK_SIZE 512 struct VfsMountPoint; struct VfsObj; diff --git a/kernel/hal/x86_64/gdt.c b/kernel/hal/x86_64/gdt.c index 6e15619..e69c7e8 100644 --- a/kernel/hal/x86_64/gdt.c +++ b/kernel/hal/x86_64/gdt.c @@ -7,7 +7,7 @@ #define GDT_PRESENT 0x80 #define GDT_TSS 0x89 -#define KSTACK (1024*4*4096) +#define KSTACK (1024*2*4096) ALIGNED(16) static uint8_t kernelstack[KSTACK]; typedef struct { diff --git a/kernel/hal/x86_64/io.c b/kernel/hal/x86_64/io.c index 212941c..448f422 100644 --- a/kernel/hal/x86_64/io.c +++ b/kernel/hal/x86_64/io.c @@ -26,3 +26,21 @@ uint32_t io_in32(uint16_t port) { void io_out32(uint16_t port, uint32_t value) { asm volatile("outl %%eax, %%dx" :: "d"(port), "a"(value)); } + +void io_ins16(uint16_t port, void *addr, int cnt) { + asm volatile( + "cld; rep insw" + : "+D"(addr), "+c"(cnt) + : "d"(port) + : "memory", "cc" + ); +} + +void io_outs16(uint16_t port, const void *addr, int cnt) { + asm volatile( + "cld; rep outsw" + : "+S"(addr), "+c"(cnt) + : "d"(port) + : "memory", "cc" + ); +} diff --git a/kernel/hal/x86_64/io.h b/kernel/hal/x86_64/io.h index cb00c11..0611bfd 100644 --- a/kernel/hal/x86_64/io.h +++ b/kernel/hal/x86_64/io.h @@ -12,4 +12,7 @@ void io_out16(uint16_t port, uint16_t value); uint32_t io_in32(uint16_t port); void io_out32(uint16_t port, uint32_t value); +void io_ins16(uint16_t port, void *addr, int cnt); +void io_outs16(uint16_t port, const void *addr, int cnt); + #endif // HAL_IO_H_ diff --git a/kernel/kmain.c b/kernel/kmain.c index ae4a016..48d8765 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -14,37 +14,6 @@ #include "dev/dev.h" #include "randcrypto/randcrypto.h" -const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { - static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; - int unit = 0; - - // Scale down until value fits nicely - uint64_t rem = 0; - while (bytes >= 1024 && unit < (int)(sizeof(units)/sizeof(units[0])) - 1) { - rem = bytes % 1024; - bytes /= 1024; - unit++; - } - - if (unit == 0) { - // Just bytes - ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]); - } else { - // Show one decimal place without using floats - // Multiply remainder by 10 to get first decimal digit - uint64_t frac = (rem * 10 + 512) / 1024; // rounded - if (frac == 10) { // handle carry, e.g. 1023.9 -> 1024.0 - bytes++; - frac = 0; - } - - if (frac > 0) ksnprintf(buf, bufsize, "%llu.%llu %s", (unsigned long long)bytes, (unsigned long long)frac, units[unit]); - else ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]); - } - - return buf; -} - void log_bootinfo(void) { char buf[100]; LOG("kmain", "Memory total = %s\n", human_size(BOOT_INFO.memmap_total, buf, sizeof(buf))); diff --git a/kernel/storedev/atasd.c b/kernel/storedev/atasd.c new file mode 100644 index 0000000..8f61380 --- /dev/null +++ b/kernel/storedev/atasd.c @@ -0,0 +1,223 @@ +#include +#include +#include +#include "atasd.h" +#include "storedev.h" +#include "hal/hal.h" +#include "util/util.h" +#include "kprintf.h" +#include "errors.h" +#include "hshtb.h" +#include "vfs/vfs.h" + +#define ATA_REG_DATA 0x1f0 +#define ATA_REG_ERROR 0x1f1 +#define ATA_REG_SECCOUNT0 0x1f2 +#define ATA_REG_LBA0 0x1f3 +#define ATA_REG_LBA1 0x1f4 +#define ATA_REG_LBA2 0x1f5 +#define ATA_REG_DRIVE 0x1f6 +#define ATA_REG_STATUS 0x1f7 +#define ATA_REG_COMMAND 0x1f7 +#define ATA_REG_CTRL 0x3f6 + +#define ATA_BSY 0x80 +#define ATA_DRDY 0x40 +#define ATA_DF 0x20 +#define ATA_ERR 0x01 +#define ATA_DRQ 0x08 + +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_IDENTIFY 0xEC + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + +int ata_wait(uint32_t timeout, bool require_drq, int checkerr) { + uint32_t i = 0; + uint8_t st; + for(;;) { + st = io_in8(ATA_REG_STATUS); + if (!(st & ATA_BSY)) + break; + if (++i >= timeout) + return -1; + } + if (require_drq) { + i = 0; + while (!(st & ATA_DRQ)) { + if (st & ATA_ERR) + return -1; + st = io_in8(ATA_REG_STATUS); + if (++i >= timeout) + return -1; + } + } + if (checkerr && (st & (ATA_DF | ATA_ERR))) + return -1; + return 0; +} + +void ata_delay400ns(void) { + io_in8(ATA_REG_CTRL); + io_in8(ATA_REG_CTRL); + io_in8(ATA_REG_CTRL); + io_in8(ATA_REG_CTRL); +} + +// caller must synchronize +uint64_t ata_probesize_bytes(int devno) { + uint16_t identifydata[0x100]; + + io_out8(ATA_REG_DRIVE, 0xA0 | (devno << 4)); + ata_delay400ns(); + + io_out8(ATA_REG_SECCOUNT0, 0); + io_out8(ATA_REG_LBA0, 0); + io_out8(ATA_REG_LBA1, 0); + io_out8(ATA_REG_LBA2, 0); + + io_out8(ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + if (ata_wait(100000, false, 0) < 0) + return 0; + + uint8_t st = io_in8(ATA_REG_STATUS); + if (st == 0) + return 0; + + if (ata_wait(100000, true, 1) < 0) + return 0; + + io_ins16(ATA_REG_DATA, identifydata, 256); + + bool lba48 = (identifydata[83] & (1<<10)) != 0; + if (lba48) { + uint64_t sectors = (uint64_t)identifydata[100] + | ((uint64_t)identifydata[101] << 16) + | ((uint64_t)identifydata[102] << 32) + | ((uint64_t)identifydata[103] << 48); + return sectors * (uint64_t)STOREDEV_ATASD_SECTORSIZE; + } else { + uint64_t sectors = (uint64_t)identifydata[60] + | ((uint64_t)identifydata[61] << 16); + return sectors * (uint64_t)STOREDEV_ATASD_SECTORSIZE; + } +} + +bool ata_probe1(int drive) { + io_out8(ATA_REG_DRIVE, 0xA0 | (drive << 4)); + for (int i = 0; i < 1000; i++) { + uint8_t status = io_in8(ATA_REG_STATUS); + if (status != 0 && status != 0xFF) + return true; // got something + } + return false; +} + +void ata_probe(void) { + if (ata_probe1(ATA_MASTER)) { + uint64_t probesize = ata_probesize_bytes(ATA_MASTER); + + char hs[20]; + LOG("ata", "found ATA Master, size = %s\n", human_size(probesize, hs, sizeof(hs))); + + AtaSdInitExtra extra = { + .devno = ATA_MASTER, + .capacity = probesize, + }; + StoreDev *sd = storedev_create(STOREDEV_ATASD, (void *)&extra); + } +} + +void ata_setup(int devno, uint16_t sectors, uint64_t lba) { + io_out8(ATA_REG_CTRL, 0x02); + + io_out8(ATA_REG_DRIVE, 0x40 | (devno << 4)); + ata_delay400ns(); + + io_out8(ATA_REG_SECCOUNT0, (sectors >> 8) & 0xFF); + io_out8(ATA_REG_LBA0, (lba >> 24) & 0xFF); + io_out8(ATA_REG_LBA1, (lba >> 32) & 0xFF); + io_out8(ATA_REG_LBA2, (lba >> 40) & 0xFF); + + io_out8(ATA_REG_SECCOUNT0, sectors & 0xFF); + io_out8(ATA_REG_LBA0, (uint8_t)(lba & 0xFF)); + io_out8(ATA_REG_LBA1, (uint8_t)((lba >> 8) & 0xFF)); + io_out8(ATA_REG_LBA2, (uint8_t)((lba >> 16) & 0xFF)); + +} + +int32_t atasd_init(struct StoreDev *sd, void *extra) { + AtaSdInitExtra *e = (AtaSdInitExtra *)extra; + sd->sd.atasd.devno = e->devno; + sd->sd.atasd.capacity = e->capacity; + return E_OK; +} + +int32_t atasd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) { + int32_t ret; + spinlock_acquire(&sd->spinlock); + + AtaSd *ata = &sd->sd.atasd; + + uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sd->sectorsize + off) / (uint64_t)STOREDEV_ATASD_SECTORSIZE; + size_t sectors = size / STOREDEV_ATASD_SECTORSIZE; + if (size % STOREDEV_ATASD_SECTORSIZE) sectors++; + + ata_setup(ata->devno, sectors, lba); + io_out8(ATA_REG_COMMAND, ATA_CMD_READ_PIO_EXT); + + for (size_t s = 0; s < sectors; s++) { + if (ata_wait(100000, true, 1) < 0) { ret = E_BADIO; goto done; } + io_ins16(ATA_REG_DATA, (uint16_t *)(buffer + s * STOREDEV_ATASD_SECTORSIZE), STOREDEV_ATASD_SECTORSIZE/2); + } + + ret = E_OK; + +done: + spinlock_release(&sd->spinlock); + return ret; +} + +int32_t atasd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) { + int32_t ret; + spinlock_acquire(&sd->spinlock); + + AtaSd *ata = &sd->sd.atasd; + + uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sd->sectorsize + off) / (uint64_t)STOREDEV_ATASD_SECTORSIZE; + size_t sectors = size / STOREDEV_ATASD_SECTORSIZE; + if (size % STOREDEV_ATASD_SECTORSIZE) sectors++; + + ata_setup(ata->devno, sectors, lba); + io_out8(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO_EXT); + + for (size_t s = 0; s < sectors; s++) { + if (ata_wait(100000, true, 1) < 0) { ret = E_BADIO; goto done; } + io_outs16(ATA_REG_DATA, (uint16_t *)(buffer + s * STOREDEV_ATASD_SECTORSIZE), STOREDEV_ATASD_SECTORSIZE/2); + } + + io_out8(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH_EXT); + if (ata_wait(100000, false, 1) < 0) { ret = E_BADIO; goto done; } + + ret = E_OK; + +done: + spinlock_release(&sd->spinlock); + return ret; +} + +int32_t atasd_cleanup(struct StoreDev *sd) { + return E_OK; +} + +size_t atasd_capacity(struct StoreDev *sd) { + size_t c = 0; + spinlock_acquire(&sd->spinlock); + c = sd->sd.atasd.capacity; + spinlock_release(&sd->spinlock); + return c; +} diff --git a/kernel/storedev/atasd.h b/kernel/storedev/atasd.h new file mode 100644 index 0000000..60650f3 --- /dev/null +++ b/kernel/storedev/atasd.h @@ -0,0 +1,30 @@ +#ifndef STOREDEV_ATASD_H_ +#define STOREDEV_ATASD_H_ + +#include +#include +#include + +#define STOREDEV_ATASD_SECTORSIZE 512 + +struct StoreDev; + +typedef struct { + int devno; + size_t capacity; +} AtaSdInitExtra; + +typedef struct { + int devno; + size_t capacity; +} AtaSd; + +int32_t atasd_init(struct StoreDev *sd, void *extra); +int32_t atasd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); +int32_t atasd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); +int32_t atasd_cleanup(struct StoreDev *sd); +size_t atasd_capacity(struct StoreDev *sd); + +void ata_probe(void); + +#endif // STOREDEV_ATASD_H_ diff --git a/kernel/storedev/ramsd.c b/kernel/storedev/ramsd.c index cadfa3c..89ca8cc 100644 --- a/kernel/storedev/ramsd.c +++ b/kernel/storedev/ramsd.c @@ -23,16 +23,18 @@ int32_t ramsd_init(struct StoreDev *sd, void *extra) { return E_OK; } -int32_t ramsd_read(struct StoreDev *sd, uint8_t *const buffer, size_t n, size_t off) { +int32_t ramsd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) { + RamSd *ramsd = &sd->sd.ramsd; spinlock_acquire(&sd->spinlock); - hal_memcpy(buffer, sd->sd.ramsd.buffer + off, MIN(n, sd->sd.ramsd.capacity - off)); + hal_memcpy(buffer, ramsd->buffer + (sector * sd->sectorsize + off), size); spinlock_release(&sd->spinlock); return E_OK; } -int32_t ramsd_write(struct StoreDev *sd, const uint8_t *const buffer, size_t n, size_t off) { +int32_t ramsd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) { + RamSd *ramsd = &sd->sd.ramsd; spinlock_acquire(&sd->spinlock); - hal_memcpy(sd->sd.ramsd.buffer + off, buffer, MIN(n, sd->sd.ramsd.capacity - off)); + hal_memcpy(ramsd->buffer + (sector * sd->sectorsize + off), buffer, size); spinlock_release(&sd->spinlock); return E_OK; } diff --git a/kernel/storedev/ramsd.h b/kernel/storedev/ramsd.h index ffbdfb0..c5aabd7 100644 --- a/kernel/storedev/ramsd.h +++ b/kernel/storedev/ramsd.h @@ -4,6 +4,8 @@ #include #include +#define STOREDEV_RAMSD_SECTORSIZE 512 + struct StoreDev; typedef struct { @@ -17,8 +19,8 @@ typedef struct { } RamSdInitExtra; int32_t ramsd_init(struct StoreDev *sd, void *extra); -int32_t ramsd_read(struct StoreDev *sd, uint8_t *const buffer, size_t n, size_t off); -int32_t ramsd_write(struct StoreDev *sd, const uint8_t *const buffer, size_t n, size_t off); +int32_t ramsd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); +int32_t ramsd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); int32_t ramsd_cleanup(struct StoreDev *sd); size_t ramsd_capacity(struct StoreDev *sd); diff --git a/kernel/storedev/storedev.c b/kernel/storedev/storedev.c index fa13a2c..2902418 100644 --- a/kernel/storedev/storedev.c +++ b/kernel/storedev/storedev.c @@ -6,6 +6,7 @@ #include "errors.h" #include "dlmalloc/malloc.h" #include "ramsd.h" +#include "atasd.h" #include "util/util.h" #include "dev/dev.h" #include "hshtb.h" @@ -19,16 +20,20 @@ void storedev_init(void) { STOREDEV_LIST.head = NULL; LOG("storedev", "init\n"); + + ata_probe(); } void storedev_register_dev_entry(StoreDev *sd, int32_t sdtype) { - char uniq[5]; - randcrypto_gen_uniqid(uniq, 4); - char key[20]; hal_memset(key, 0, sizeof(key)); + if (sdtype == STOREDEV_RAMSD) { + char uniq[5]; + randcrypto_gen_uniqid(uniq, 4); ksprintf(key, "ramsd-%s", uniq); + } else if (sdtype == STOREDEV_ATASD) { + ksprintf(key, "atasd-%s", sd->sd.atasd.devno == 0x00 ? "mst" : "slv"); } spinlock_acquire(&DEVTABLE.spinlock); @@ -70,18 +75,29 @@ StoreDev *storedev_create(int32_t sdtype, void *extra) { sd->read = &ramsd_read; sd->write = &ramsd_write; sd->capacity = &ramsd_capacity; - - int32_t err = sd->init(sd, extra); - if (err != E_OK) { - spinlock_release(&STOREDEV_LIST.spinlock); - return NULL; - } - LL_APPEND(STOREDEV_LIST.head, sd); + sd->sectorsize = STOREDEV_RAMSD_SECTORSIZE; + } break; + case STOREDEV_ATASD: { + spinlock_init(&sd->spinlock); + sd->sdtype = STOREDEV_ATASD; + sd->init = &atasd_init; + sd->cleanup = &atasd_cleanup; + sd->read = &atasd_read; + sd->write = &atasd_write; + sd->capacity = &atasd_capacity; + sd->sectorsize = STOREDEV_ATASD_SECTORSIZE; } break; default: spinlock_release(&STOREDEV_LIST.spinlock); return NULL; } + int32_t err = sd->init(sd, extra); + if (err != E_OK) { + dlfree(sd); + spinlock_release(&STOREDEV_LIST.spinlock); + return NULL; + } + LL_APPEND(STOREDEV_LIST.head, sd); spinlock_release(&STOREDEV_LIST.spinlock); storedev_register_dev_entry(sd, sdtype); diff --git a/kernel/storedev/storedev.h b/kernel/storedev/storedev.h index 941444e..c98e73e 100644 --- a/kernel/storedev/storedev.h +++ b/kernel/storedev/storedev.h @@ -5,6 +5,7 @@ #include #include "spinlock/spinlock.h" #include "ramsd.h" +#include "atasd.h" #include "compiler/attr.h" #include "dev/dev.h" @@ -12,25 +13,28 @@ enum { STOREDEV_RAMSD, + STOREDEV_ATASD, }; UNUSED static const char *storedev_strings[] = { - "RAMSD", + "RAMSD", "ATASD" }; typedef struct StoreDev { uint32_t _magic; struct StoreDev *next; int32_t sdtype; + size_t sectorsize; int32_t (*init)(struct StoreDev *sd, void *extra); - int32_t (*read)(struct StoreDev *sd, uint8_t *const buffer, size_t n, size_t off); - int32_t (*write)(struct StoreDev *sd, const uint8_t *const buffer, size_t n, size_t off); + int32_t (*read)(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); + int32_t (*write)(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size); int32_t (*cleanup)(struct StoreDev *sd); size_t (*capacity)(struct StoreDev *sd); union { RamSd ramsd; + AtaSd atasd; } sd; SpinLock spinlock; } StoreDev; diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index a82be02..7c1bbdb 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -10,6 +10,7 @@ #include "sched.h" #include "devctl.h" #include "randcrypto.h" +#include "vfs.h" int32_t SYSCALL1(sys_debugprint, string) { char *p = (char *)string; @@ -27,4 +28,6 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = { [SYS_SCHEDRELEASE] = &sys_schedrelease, [SYS_DEVCTL] = &sys_devctl, [SYS_RAND] = &sys_rand, + [SYS_VFSMOUNT] = &sys_vfsmount, + [SYS_VFSUNMOUNT] = &sys_vfsunmount, }; diff --git a/kernel/syscall/vfs.c b/kernel/syscall/vfs.c new file mode 100644 index 0000000..09e9150 --- /dev/null +++ b/kernel/syscall/vfs.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include "hal/hal.h" +#include "syscall.h" +#include "vfs.h" +#include "errors.h" +#include "sysdefs/devctl.h" +#include "vfs/vfs.h" +#include "spinlock/spinlock.h" +#include "dev/dev.h" +#include "proc/proc.h" +#include "storedev/storedev.h" + +int32_t SYSCALL4(sys_vfsmount, mountpoint1, fstypestr1, devid1, format1) { + int32_t ret = E_OK; + char *mountpoint = (char *)mountpoint1; + char *fstypestr = (char *)fstypestr1; + Dev_t *dev = (Dev_t *)devid1; + bool format = (bool)format1; + + if (mountpoint == NULL) { ret = E_INVALIDARGUMENT; goto done; } + if (fstypestr == NULL) { ret = E_INVALIDARGUMENT; goto done; } + if (dev == NULL) { ret = E_INVALIDARGUMENT; goto done; } + + if (*dev >= PROC_DEVHANDLES_MAX) { ret = E_INVALIDARGUMENT; goto done; } + + int32_t fstype; + + if (hal_strcmp(fstypestr, "LittleFS") == 0) { + fstype = VFS_LITTLEFS; + } else { + ret = E_INVALIDARGUMENT; + goto done; + } + + spinlock_acquire(&PROCS.spinlock); + Proc *proc = PROCS.current; + spinlock_release(&PROCS.spinlock); + + Dev *dp = proc->devs[*dev]; + if (dp == NULL) { ret = E_NOENTRY; goto done; } + + StoreDev *sd = (StoreDev *)dp->extra; + if (sd != NULL && sd->_magic != STOREDEV_MAGIC) { ret = E_NOENTRY; goto done; } + + ret = vfs_mount(mountpoint, fstype, sd, format); + +done: + return ret; +} + +int32_t SYSCALL1(sys_vfsunmount, mountpoint1) { + int32_t ret = E_OK; + char *mountpoint = (char *)mountpoint1; + + if (mountpoint == NULL) { ret = E_INVALIDARGUMENT; goto done; } + + ret = vfs_unmount(mountpoint); + +done: + return ret; +} diff --git a/kernel/syscall/vfs.h b/kernel/syscall/vfs.h new file mode 100644 index 0000000..9e4fb2f --- /dev/null +++ b/kernel/syscall/vfs.h @@ -0,0 +1,11 @@ +#ifndef SYSCALL_VFS_H_ +#define SYSCALL_VFS_H_ + +#include +#include +#include "syscall.h" + +int32_t SYSCALL4(sys_vfsmount, mountpoint1, fstypestr1, devid1, format1); +int32_t SYSCALL1(sys_vfsunmount, mountpoint1); + +#endif // SYSCALL_VFS_H_ diff --git a/kernel/util/util.c b/kernel/util/util.c index 93f3711..a2c5226 100644 --- a/kernel/util/util.c +++ b/kernel/util/util.c @@ -1,3 +1,6 @@ +#include +#include +#include "kprintf.h" #include "util.h" char *util_get_filename(char *path) { @@ -13,3 +16,33 @@ char *util_get_filename(char *path) { return lastslash; } +const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { + static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; + int unit = 0; + + // Scale down until value fits nicely + uint64_t rem = 0; + while (bytes >= 1024 && unit < (int)(sizeof(units)/sizeof(units[0])) - 1) { + rem = bytes % 1024; + bytes /= 1024; + unit++; + } + + if (unit == 0) { + // Just bytes + ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]); + } else { + // Show one decimal place without using floats + // Multiply remainder by 10 to get first decimal digit + uint64_t frac = (rem * 10 + 512) / 1024; // rounded + if (frac == 10) { // handle carry, e.g. 1023.9 -> 1024.0 + bytes++; + frac = 0; + } + + if (frac > 0) ksnprintf(buf, bufsize, "%llu.%llu %s", (unsigned long long)bytes, (unsigned long long)frac, units[unit]); + else ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]); + } + + return buf; +} diff --git a/kernel/util/util.h b/kernel/util/util.h index c9b7de6..f0419ec 100644 --- a/kernel/util/util.h +++ b/kernel/util/util.h @@ -1,6 +1,9 @@ #ifndef UTIL_UTIL_H_ #define UTIL_UTIL_H_ +#include +#include + #define _DIV_ROUNDUP(num, div) ((num + div - 1) / div) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -74,5 +77,6 @@ var = tmp, tmp = (var ? var->next : NULL), (idx)++) char *util_get_filename(char *path); +const char *human_size(uint64_t bytes, char *buf, size_t bufsize); #endif // UTIL_UTIL_H_ diff --git a/kernel/vfs/vfs.c b/kernel/vfs/vfs.c index efee9b0..f172912 100644 --- a/kernel/vfs/vfs.c +++ b/kernel/vfs/vfs.c @@ -25,11 +25,11 @@ void vfs_init_littlefs(VfsMountPoint *mp, bool format) { 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->read_size = LITTLEFS_BLOCK_SIZE; + cfg->prog_size = LITTLEFS_BLOCK_SIZE; cfg->block_cycles = 16; - cfg->cache_size = 64; - cfg->lookahead_size = 64; + cfg->cache_size = LITTLEFS_BLOCK_SIZE; + cfg->lookahead_size = LITTLEFS_BLOCK_SIZE; cfg->read_buffer = NULL; cfg->prog_buffer = NULL; cfg->lookahead_buffer = NULL; diff --git a/share/sysdefs/syscall.h b/share/sysdefs/syscall.h index 597c46d..157f3a2 100644 --- a/share/sysdefs/syscall.h +++ b/share/sysdefs/syscall.h @@ -10,5 +10,7 @@ #define SYS_SCHEDRELEASE 7 #define SYS_DEVCTL 8 #define SYS_RAND 9 +#define SYS_VFSMOUNT 10 +#define SYS_VFSUNMOUNT 11 #endif // SHARE_HDRS_SYSCALL_H_