diff options
Diffstat (limited to 'kernel/fs')
-rw-r--r-- | kernel/fs/fs.c | 158 |
1 files changed, 142 insertions, 16 deletions
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c index 4682e41..4b6bc5d 100644 --- a/kernel/fs/fs.c +++ b/kernel/fs/fs.c @@ -1,18 +1,49 @@ #include <lib.h> #include <comus/fs.h> +#include <comus/mboot.h> -struct disk fs_disks[MAX_DISKS]; -struct file_system fs_loaded_file_systems[MAX_DISKS]; +struct disk fs_disks[N_DISKS]; +struct file_system fs_loaded_file_systems[N_DISKS]; void fs_init(void) { + size_t idx = 0; + // zero structures memsetv(fs_disks, 0, sizeof(fs_disks)); memsetv(fs_loaded_file_systems, 0, sizeof(fs_loaded_file_systems)); - // TODO: go though ide and/or sata drivers to load all disks into `fs_disks` structures + // check for initrd + size_t rd_len; + void *rd = mboot_get_initrd(&rd_len); + if (rd != NULL) { + assert(idx < N_DISKS, "Too many disks, limit is: %d\n", N_DISKS); + fs_disks[idx] = (struct disk) { + .present = 1, + .id = idx, + .type = DISK_TYPE_RAMDISK, + .rd.start = rd, + .rd.len = rd_len, + }; + idx++; + } + + // check for ide/ata devices + struct ide_devicelist ide_list = ide_devices_enumerate(); + for (size_t i = 0; i < ide_list.num_devices; i++) { + assert(idx < N_DISKS, "Too many disks, limit is: %d\n", N_DISKS); + fs_disks[idx] = (struct disk) { + .present = 1, + .id = idx, + .type = DISK_TYPE_ATA, + .ide = ide_list.devices[i], + }; + idx++; + } + + INFO("loaded %zu disks\n", idx); - // TODO: go though each disk and attempt to load a file system + // TODO: load filesystems on disks } struct disk *fs_get_root_disk(void) @@ -20,7 +51,7 @@ struct disk *fs_get_root_disk(void) // NOTE: currently im just getting the first disk // found, is this fine? - for (int i = 0; i < MAX_DISKS; i++) { + for (int i = 0; i < N_DISKS; i++) { struct disk *disk = &fs_disks[i]; if (disk->present) return disk; @@ -34,7 +65,7 @@ struct file_system *fs_get_root_file_system(void) // NOTE: currently im just getting the first file system // found, is this fine? - for (int i = 0; i < MAX_DISKS; i++) { + for (int i = 0; i < N_DISKS; i++) { struct file_system *fs = &fs_loaded_file_systems[i]; if (fs->present) return fs; @@ -61,22 +92,117 @@ int fs_find_file_rel(struct file *rel, char *rel_path, struct file *res) panic("fs_find_file_rel NOT YET IMPLEMENTED"); } +static int disk_read_rd(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) +{ + if (offset + len >= disk->rd.len) { + WARN("attempted to read past length of ramdisk"); + return 1; + } + + memcpy(buffer, disk->rd.start + offset, len); + return 0; +} + +static int disk_read_ata(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) +{ + static size_t atabuf_len = 0; + static uint16_t *atabuf = NULL; + + uint32_t numsects = (len + ATA_SECT_SIZE - 1) / ATA_SECT_SIZE; + uint32_t err = offset % ATA_SECT_SIZE; + int ret = 0; + + if (atabuf == NULL || atabuf_len < numsects*ATA_SECT_SIZE) { + if ((atabuf = krealloc(atabuf, numsects*ATA_SECT_SIZE)) == NULL) + return 1; + atabuf_len = numsects*ATA_SECT_SIZE; + } + + // read sectors + if ((ret = ide_device_read_sectors(disk->ide, numsects, offset / ATA_SECT_SIZE, atabuf))) + return 1; + + // copy over to buffer + memcpy(buffer, atabuf + err, len); + + return ret; +} + + int disk_read(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) { - (void)disk; - (void)offset; - (void)len; - (void)buffer; + int ret = 0; - panic("disk_read NOT YET IMPLEMENTED"); + switch(disk->type) { + case DISK_TYPE_RAMDISK: + ret = disk_read_rd(disk, offset, len, buffer); + break; + case DISK_TYPE_ATA: + ret = disk_read_ata(disk, offset, len, buffer); + break; + default: + ERROR("attempted to read from disk with invalid type: %d\n", disk->type); + ret = 1; + } + + return ret; +} + +static int disk_write_rd(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) +{ + if (offset + len >= disk->rd.len) { + WARN("attempted to write past length of ramdisk"); + return 1; + } + + memcpy(disk->rd.start + offset, buffer, len); + return 0; +} + +static int disk_write_ata(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) +{ + static size_t atabuf_len = 0; + static uint16_t *atabuf = NULL; + + uint32_t numsects = (len + ATA_SECT_SIZE - 1) / ATA_SECT_SIZE; + uint32_t err = offset % ATA_SECT_SIZE; + int ret = 0; + + if (atabuf == NULL || atabuf_len < numsects*ATA_SECT_SIZE) { + if ((atabuf = krealloc(atabuf, numsects*ATA_SECT_SIZE)) == NULL) + return 1; + atabuf_len = numsects*ATA_SECT_SIZE; + } + + // read sectors what will be overwritten + if ((ret = ide_device_read_sectors(disk->ide, numsects, offset / ATA_SECT_SIZE, atabuf))) + return 1; + + // copy custom data over + memcpy(atabuf + err, buffer, len); + + // write back sectors + if ((ret = ide_device_write_sectors(disk->ide, numsects, offset / ATA_SECT_SIZE, atabuf))) + return 1; + + return ret; } int disk_write(struct disk *disk, size_t offset, size_t len, uint8_t *buffer) { - (void)disk; - (void)offset; - (void)len; - (void)buffer; + int ret = 0; + + switch(disk->type) { + case DISK_TYPE_RAMDISK: + ret = disk_write_rd(disk, offset, len, buffer); + break; + case DISK_TYPE_ATA: + ret = disk_write_ata(disk, offset, len, buffer); + break; + default: + ERROR("attempted to write to disk with invalid type: %d\n", disk->type); + ret = 1; + } - panic("disk_write NOT YET IMPLEMENTED"); + return ret; } |