diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-21 11:41:34 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-21 11:41:34 -0400 |
commit | 2ee0e24dfd5319f128ed49b4f47679b7c13b21bf (patch) | |
tree | d250af94c434acd54180a1b529b0407d8013890e /kernel | |
parent | Merge branch 'main' of github.com:kenshineto/kern (diff) | |
download | comus-2ee0e24dfd5319f128ed49b4f47679b7c13b21bf.tar.gz comus-2ee0e24dfd5319f128ed49b4f47679b7c13b21bf.tar.bz2 comus-2ee0e24dfd5319f128ed49b4f47679b7c13b21bf.zip |
fs read/write functions, initrd
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/entry.S | 6 | ||||
-rw-r--r-- | kernel/fs/fs.c | 158 | ||||
-rw-r--r-- | kernel/include/comus/drivers/ata.h | 2 | ||||
-rw-r--r-- | kernel/include/comus/fs.h | 31 | ||||
-rw-r--r-- | kernel/include/comus/limits.h | 4 | ||||
-rw-r--r-- | kernel/include/comus/mboot.h | 5 | ||||
-rw-r--r-- | kernel/mboot/module.c | 24 |
7 files changed, 202 insertions, 28 deletions
diff --git a/kernel/entry.S b/kernel/entry.S index e1b4767..aa4c38d 100644 --- a/kernel/entry.S +++ b/kernel/entry.S @@ -26,6 +26,7 @@ mb_start: .short 1 .long 36 .long 1 # cmdline + .long 3 # module .long 6 # mmap .long 9 # elf section .long 12 # efi64 @@ -46,6 +47,11 @@ mb_start: .long 720 # width .long 480 # height .long 32 # bpp + # module align + .align 8 + .short 6 + .short 0 + .long 8 # efi boot services .align 8 .short 7 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; } diff --git a/kernel/include/comus/drivers/ata.h b/kernel/include/comus/drivers/ata.h index 66b3ba5..2f35e03 100644 --- a/kernel/include/comus/drivers/ata.h +++ b/kernel/include/comus/drivers/ata.h @@ -10,6 +10,8 @@ #ifndef ATA_H_ #define ATA_H_ +#define ATA_SECT_SIZE 512 + #include <stdint.h> #include <stdbool.h> diff --git a/kernel/include/comus/fs.h b/kernel/include/comus/fs.h index fe335ca..048c7c5 100644 --- a/kernel/include/comus/fs.h +++ b/kernel/include/comus/fs.h @@ -11,10 +11,13 @@ #include <stdint.h> #include <stddef.h> +#include <comus/limits.h> +#include <comus/drivers/ata.h> -// FIXME: aaaa -#define MAX_DISKS 8 -#define MAX_FILE_NAME_LEN 256 +enum disk_type { + DISK_TYPE_ATA, + DISK_TYPE_RAMDISK, +}; struct disk { /// set to 1 in array to state that fs is defined @@ -23,12 +26,16 @@ struct disk { /// index into disks array /// system use only int id; - /// TODO: pci? inb/outb? - /// we need a structure to access disks and how to define them - /// IDE / SATA / .... ??? - /// we should probable create ide_disk, or sata_disk, and so on - /// then convert this part to a union with a tag specifier - /// we then need drivers for ide and/or sata, ide is easier + /// disk type + enum disk_type type; + /// internal disk device + union { + struct { + char *start; + size_t len; + } rd; + ide_device_t ide; + }; }; /** @@ -67,7 +74,7 @@ enum file_type { struct file { /// name of the file - char name[MAX_FILE_NAME_LEN]; + char name[N_FILE_NAME]; /// parent directory of the file struct file_s *parent; /// type of the file @@ -159,10 +166,10 @@ struct file_system { }; // list of all disks on the system -extern struct disk fs_disks[MAX_DISKS]; +extern struct disk fs_disks[N_DISKS]; // list of all loaded file systems for each disk -extern struct file_system fs_loaded_file_systems[MAX_DISKS]; +extern struct file_system fs_loaded_file_systems[N_DISKS]; /** * Initalize file system structures diff --git a/kernel/include/comus/limits.h b/kernel/include/comus/limits.h index b6c596b..675df47 100644 --- a/kernel/include/comus/limits.h +++ b/kernel/include/comus/limits.h @@ -18,6 +18,10 @@ /// max memory entires #define N_MMAP_ENTRY 256 +/// max fs limits +#define N_FILE_NAME 256 +#define N_DISKS 8 + /// length of terminal buffer #define TERM_MAX_WIDTH 1920 #define TERM_MAX_HEIGHT 1080 diff --git a/kernel/include/comus/mboot.h b/kernel/include/comus/mboot.h index 036cc40..aba3e4e 100644 --- a/kernel/include/comus/mboot.h +++ b/kernel/include/comus/mboot.h @@ -42,4 +42,9 @@ EFI_SYSTEM_TABLE *mboot_get_efi_st(void); */ EFI_HANDLE mboot_get_efi_hdl(void); +/** + * Returns the pointer to the loaded init ram disk with size given by len + */ +void *mboot_get_initrd(size_t *len); + #endif /* mboot.h */ diff --git a/kernel/mboot/module.c b/kernel/mboot/module.c new file mode 100644 index 0000000..7a64f2e --- /dev/null +++ b/kernel/mboot/module.c @@ -0,0 +1,24 @@ +#include <comus/mboot.h> + +#include "mboot.h" + +#define MULTIBOOT_TAG_TYPE_MODULE 3 + +struct multiboot_tag_module { + uint32_t type; + uint32_t size; + uint32_t mod_start; + uint32_t mod_end; + char cmdline[]; +}; + +void *mboot_get_initrd(size_t *len) +{ + void *tag = locate_mboot_table(MULTIBOOT_TAG_TYPE_MODULE); + if (tag == NULL) + return NULL; + + struct multiboot_tag_module *mod = (struct multiboot_tag_module *)tag; + *len = mod->mod_end - mod->mod_start; + return (void*) (uintptr_t) mod->mod_start; +} |