CeDOS - Commit c910d744

Merge branch 'feature/files' into develop Added file offsets and lseek function
Celina Sophie Kalus
Sat, 29 Apr 2023 15:03:56 +0200
7 files changed, 107 insertions(+), 33 deletions(-)
M include/cedos/fat.hinclude/cedos/fat.h

@@ -8,7 +8,8 @@

void FAT_init(); int FAT_dir_next(file_t *file, int index, char *fname_buffer); int FAT_openat(file_t *root, file_t *handle, const char *fname, int flags); -uint32_t FAT_read(file_t *file, void *buffer, int count); +uint32_t FAT_read(file_t *file, uint8_t *buffer, uint32_t count); +off_t FAT_lseek(file_t *file, off_t offset, int whence); extern file_operations_t FAT_fops;
M include/cedos/file.hinclude/cedos/file.h

@@ -6,6 +6,11 @@

#include "cedos/mm/paging.h" typedef uint32_t fpos_t; +typedef int32_t off_t; + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 struct file; struct file_operations;

@@ -26,12 +31,14 @@ int (*openat)(file_t *root, file_t *handle, const char *fname, int flags);

int (*read)(file_t *file, char *buffer, uint32_t size); int (*write)(file_t *file, char *buffer, uint32_t size); int (*dir_next)(file_t *file, int index, char *fname_buffer); + off_t (*lseek)(file_t *file, off_t offset, int whence); }; int file_init(); int file_open(const char *pathname, int flags); int file_openat(int fd, const char *fname, int flags); int file_read(int fd, char *buffer, uint32_t size); +off_t file_lseek(int fd, off_t offset, int whence); int file_write(int fd, char *buffer, uint32_t size); int file_dir_next(int fd, int index, char *fname_buffer);
M src/kernel/drivers/tty.csrc/kernel/drivers/tty.c

@@ -9,7 +9,8 @@ tty_open, /* open */

tty_openat, /* openat */ tty_read, /* read */ tty_write, /* write */ - NULL /* dir_next */ + NULL, /* dir_next */ + NULL /* lseek */ }; int tty_open(const char *pathname, int flags) {
M src/kernel/elf.csrc/kernel/elf.c

@@ -5,6 +5,8 @@

#include "cedos/file.h" #include "cedos/sched/process.h" +#include "cedos/mm/memory.h" + #include "assert.h" #ifdef DEBUG

@@ -126,7 +128,6 @@

PROCESS_ID elf_exec(const char *fname, char *args) { crit_enter(); PRINT_DBG("Loading ELF executable \"%s\".\n", fname); - VIRT_ADDR elf_addr = (VIRT_ADDR*)(0xA0000000); // TODO: needs to change when we have other file systems int fd = file_open(fname, 0); PRINT_DBG("File handle: %i\n", fd);

@@ -135,47 +136,60 @@ if (fd == -1) {

printk("Executable file not found: %s\n", fname); return -1; } - int size = file_read(fd, elf_addr, 0); - assert(size != 0); + //int size = file_read(fd, elf_addr, 0xFFFF); + //assert(size != 0); - ELF_HEADER *header = (ELF_HEADER*)(elf_addr); + ELF_HEADER header; + file_lseek(fd, 0, SEEK_SET); + int header_size = file_read(fd, (void*)(&header), sizeof(ELF_HEADER)); // magic number correct - assert(((uint32_t*)(elf_addr))[0] == 0x464C457F); + assert(*(uint32_t*)(header.e_ident) == 0x464C457F); // header size correct assert(sizeof(ELF_HEADER) == 52); + assert(header_size == sizeof(ELF_HEADER)); // get section table - int sh_offset = header->secthead_offset; - SECT_HEADER *sect_headers = (SECT_HEADER*)(elf_addr + sh_offset); + int sh_offset = header.secthead_offset; + + SECT_HEADER sect_headers[16]; + file_lseek(fd, sh_offset, SEEK_SET); + int sect_headers_size = file_read(fd, (void*)(&sect_headers), sizeof(sect_headers)); + + assert(sect_headers_size != 0); - int num_sections = header->sh_num; - int section_size = header->sh_entry_size; + int num_sections = header.sh_num; + int section_size = header.sh_entry_size; - SECT_HEADER sect_names_sh = sect_headers[header->sh_strndx]; - VIRT_ADDR sect_names_addr = elf_addr + sect_names_sh.offset; + SECT_HEADER *sect_names_sh = &sect_headers[header.sh_strndx]; + + char *sect_names = os_kernel_malloc(sect_names_sh->size); + file_lseek(fd, sect_names_sh->offset, SEEK_SET); + file_read(fd, sect_names, sect_names_sh->size); assert(sizeof(SECT_HEADER) == section_size); // go through all sections and copy/allocate memory as necessary PRINT_DBG("Enumerating %i sections:\n", num_sections); for (int i = 0; i < num_sections; i++) { - SECT_HEADER sh = sect_headers[i]; - char *name = (char*)(sect_names_addr + sh.name); + SECT_HEADER *sh = &sect_headers[i]; + char *name = (char*)(sect_names + sh->name); - if ((sh.flags & SHF_ALLOC) && (sh.flags & SHF_EXECINSTR)) { - VIRT_ADDR lma = elf_addr + sh.offset; - VIRT_ADDR vma = sh.addr; - uint32_t size = sh.size; - PRINT_DBG("%p\n", sh.flags); + if ((sh->flags & SHF_ALLOC) && (sh->flags & SHF_EXECINSTR)) { + uint32_t lma = sh->offset; + uint32_t vma = sh->addr; + uint32_t sect_size = sh->size; + PRINT_DBG("%p\n", sh->flags); PRINT_DBG("Copying code section %s to its destination ", name); PRINT_DBG("(LMA: %p, VMA: %p)\n", lma, vma); - memcpy(vma, lma, size); - } else if (sh.flags & SHF_ALLOC) { - VIRT_ADDR lma = elf_addr + sh.offset; - VIRT_ADDR vma = sh.addr; + file_lseek(fd, sh->offset, SEEK_SET); + int read_size = file_read(fd, vma, sect_size); + assert(sect_size == read_size); + } else if (sh->flags & SHF_ALLOC) { + uint32_t lma = sh->offset; + uint32_t vma = sh->addr; PRINT_DBG("Allocating space for section %s ", name); PRINT_DBG("(LMA: %p, VMA: %p)\n", lma, vma);

@@ -187,11 +201,11 @@ }

PRINT_DBG("\n"); - PRINT_DBG("Entry point: %p\n", header->entry); + PRINT_DBG("Entry point: %p\n", header.entry); crit_exit(); // enter the process - PROCESS_MAIN *entry = (PROCESS_MAIN*)(header->entry); + PROCESS_MAIN *entry = (PROCESS_MAIN*)(header.entry); entry(args); return 0;
M src/kernel/fat.csrc/kernel/fat.c

@@ -3,6 +3,8 @@ #include "cedos/fat.h"

#include "string.h" #include "assert.h" +#include "cedos/mm/memory.h" + #include <stdint.h> file_operations_t FAT_fops = {

@@ -10,7 +12,8 @@ NULL, /* open */

FAT_openat, /* openat */ FAT_read, /* read */ NULL, /* write */ - FAT_dir_next /* dir_next */ + FAT_dir_next, /* dir_next */ + FAT_lseek /* lseek */ }; typedef struct {

@@ -218,6 +221,7 @@ if (i <= 0) { return -1; }

if (strcmp(buffer, fname) == 0) { // file found + handle->pos = 0; handle->fops = &FAT_fops; handle->fat_cluster = first_cluster; return 0;

@@ -225,17 +229,55 @@ }

} } -uint32_t FAT_read(file_t *file, void *buffer, int count) { +uint32_t FAT_read(file_t *file, uint8_t *buffer, uint32_t count) { uint16_t cluster = file->fat_cluster; + fpos_t offset = file->pos; uint32_t size = 0; - while (1) { - buffer = FAT_read_cluster(cluster, buffer); + uint32_t cluster_size = boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; + uint8_t *cluster_buffer = os_kernel_malloc(cluster_size); + + while (offset >= cluster_size) { cluster = FAT_next_cluster(cluster); - size += boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; - + if (cluster == 0xFFF || cluster == 0x000) { return -1; } + offset -= cluster_size; + } + + while (count > 0) { if (cluster == 0xFFF || cluster == 0x000) { break; } + + FAT_read_cluster(cluster, cluster_buffer); + cluster = FAT_next_cluster(cluster); + + uint32_t memcpy_size; + + if (offset + count > cluster_size) { + memcpy_size = (cluster_size - offset); + } else { + memcpy_size = count; + } + + memcpy(buffer, (cluster_buffer + offset), memcpy_size); + + offset = 0; + count -= memcpy_size; + buffer += memcpy_size; + size += memcpy_size; } + + file->pos += size; return size; +} + +off_t FAT_lseek(file_t *file, off_t offset, int whence) { + if (whence == SEEK_SET) { + file->pos = offset; + } else if (whence == SEEK_CUR) { + file->pos += offset; + } else if (whence == SEEK_END) { + // to be implemented + } else { + kpanic("Wrong whence!"); + } }
M src/kernel/file.csrc/kernel/file.c

@@ -109,3 +109,11 @@ if (file->fops->dir_next == NULL) { return -1; }

file->fops->dir_next(file, index, fname_buffer); } + +off_t file_lseek(int fd, off_t offset, int whence) { + file_t *file = get_process_local_file(fd); + + if (file->fops->lseek == NULL) { return -1; } + + return file->fops->lseek(file, offset, whence); +}
M src/kernel/pipe.csrc/kernel/pipe.c

@@ -7,7 +7,8 @@ NULL, /* open */

NULL, /* openat */ pipe_read, /* read */ pipe_write, /* write */ - NULL /* dir_next */ + NULL, /* dir_next */ + NULL /* lseek */ }; #define PIPE_BUFFER_SIZE 512