From fca025a9bf19c6825eacba9f995362320cd38ba9 Mon Sep 17 00:00:00 2001 From: David Goeke Date: Tue, 17 Jun 2025 15:50:07 -0500 Subject: [PATCH] Espresso 0.0.1a --- drivers/fs/duckfs.c | 279 +++++++------------------- drivers/fs/ramfs.c | 348 +++++++++++++++++++++++++++++++++ drivers/fs/vfs.c | 230 ++++++++++++++++++++++ drivers/ide.c | 47 ++--- drivers/irq.c | 4 +- drivers/pit.c | 53 +++-- drivers/ps2_keyboard.c | 80 +++++++- drivers/timer.c | 21 -- drivers/tty.c | 6 +- include/drivers/pit.h | 7 +- include/drivers/ps2_keyboard.h | 3 + include/drivers/timer.h | 11 -- include/fs/duckfs.h | 75 +------ include/fs/ramfs.h | 73 +++---- include/fs/vfs.h | 20 ++ include/stdio.h | 8 + include/stdlib.h | 5 +- include/string.h | 3 + kernel/kernel.c | 60 ++++-- lib/fs/ramfs/ramfs.c | 190 ------------------ lib/mm/heap.c | 2 +- lib/stdio.c | 62 ++++++ lib/stdlib.c | 13 ++ lib/string.c | 80 +++++++- 24 files changed, 1080 insertions(+), 600 deletions(-) create mode 100644 drivers/fs/ramfs.c create mode 100644 drivers/fs/vfs.c delete mode 100644 drivers/timer.c delete mode 100644 include/drivers/timer.h create mode 100644 include/fs/vfs.h delete mode 100644 lib/fs/ramfs/ramfs.c create mode 100644 lib/stdio.c create mode 100644 lib/stdlib.c diff --git a/drivers/fs/duckfs.c b/drivers/fs/duckfs.c index b201580..8598a0c 100644 --- a/drivers/fs/duckfs.c +++ b/drivers/fs/duckfs.c @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -7,214 +5,89 @@ #include +#define DFS_MAGIC 0xDF1984CC + +#define DFS_BLOCK_SIZE 512 + +#define DFS_VERSION_0 "DuckFS, wheresDax?" +#define DFS_VERSION_1 "DuckFS, Terminator" +#define DFS_VERSION_2 "DuckFS-Terminator2" +#define DFS_VERSION_3 "DuckFS,StarWarsEIV" +#define DFS_VERSION_4 "DuckFS QUACK,QUACK" + + +#define DFS_FILE_ERROR -8 +#define DFS_FILE_UNUSED -1 +#define DFS_FILE_USED 0 +#define DFS_FILE_TEXT 0 +#define DFS_FILE_BINARY 1 +#define DFS_FILE_DIRECTORY 2 + +/* encryption algorithms */ +#define DFS_CAESAR_5 88 +#define DFS_CAESAR_8 84 +#define DFS_CAESAR_2 09 +#define DFS_QUACK_32 99 + +#define DFS_MAX_FILENAME_LEN 64 +#define DFS_MAX_FILES 256 + + +typedef struct duckfs_file_header { + char filename[DFS_MAX_FILENAME_LEN + 1]; /* + 1 for the \0 */ + char permissions[3]; /* Same thing here */ + + /* + 512 Bytes per sector, meaning a 2 sector file is 1024 bytes, or 1 KiB. + Only valid if this file is not a directory. + */ + int32_t num_sectors; + + int16_t type; /* Indicates the file type. -1 for null file, 0 for a text file, 1 for a binary file, and 2 for a directory. */ + + uint16_t _reserved0; /* (align to 4) */ + + struct duckfs_file_header* next; /* Next file in the directory this file is in. */ + struct duckfs_file_header* contents; /* contains the first file in the directory. only valid if this file is a directory. */ + struct duckfs_file_header* parent; /* The directory this file is in. */ + + uint64_t next_lba; /* The LBA of the next file's file header on the disk. */ + uint64_t contents_lba; + uint64_t parent_lba; + + uint64_t lba_start; /* only is valid if this file is not a directory. */ + uint64_t lba_end; /* only is valid if this file is not a directory. */ + + uint8_t _reserved1[126]; /* padding to 256 bytes total */ +} duckfs_file_header_t; + +typedef struct duckfs_superblock { + int32_t duckfs_magic; /* must be DFS_MAGIC. */ + char duckfs_version_string[19]; + char volume_label[19]; /* 18 characters and a null zero. */ + + int16_t encryption; + + uint64_t duckfs_root; /* LBA of the root directory's file header */ + + uint32_t _padding[115]; /* padding to 512 bytes total */ +} duckfs_superblock_t; + + static uint16_t duckfs_initialized = 0; static duckfs_file_header_t duckfs_root; const char* duckfs_versions[18] = { DFS_VERSION_0, DFS_VERSION_1, DFS_VERSION_2, DFS_VERSION_3, DFS_VERSION_4 }; -int32_t duckfs_init(int16_t drive) +void duckfs_init(void) { - char duckfs_header_block[512]; - if (ide_read48(drive, 0xA, 1, duckfs_header_block) != 0) - { - printf("[ DEBUG ] Disk read error on drive #%i\n", drive); - return -1; - } + printf("\t%i\n", (sizeof(duckfs_file_header_t))); + printf("\t\t%i\n", (sizeof(duckfs_superblock_t))); + /* int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer) */ + /* int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const void* buffer) */ - duckfs_superblock_t* superblock = (duckfs_superblock_t*)duckfs_header_block; - /* - if (superblock->duckfs_magic != (int32_t) DFS_MAGIC) - { - return -2; - } - - bool compliant = false; - for (int16_t i = 0; i < 5; ++i) - { - if (strcmp(superblock->duckfs_version_string, duckfs_versions[i]) == 0) - { - compliant = true; - } - } - - if (compliant == false) - { - return -3; - }*/ - - memset(&duckfs_root, 0, sizeof(duckfs_root)); - - strncpy(duckfs_root.filename, "/", DFS_MAX_FILENAME_LEN); - strncpy(duckfs_root.permissions, "RW", sizeof(duckfs_root.permissions)); - - duckfs_root.num_sectors = -1; - duckfs_root.type = DFS_FILE_DIRECTORY; - duckfs_root.next = NULL; - duckfs_root.prev = NULL; - duckfs_root.contents = NULL; - duckfs_root.lba_start = 0; - duckfs_root.lba_end = 0; - - duckfs_root.contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES); - if (!duckfs_root.contents) { - printf("Memory allocation failed for duckfs_root.contents\n"); - return -4; - } - - for (int32_t i = 0; i < DFS_MAX_FILES; i++) { - duckfs_root.contents[i].type = DFS_FILE_UNUSED; - } - - - duckfs_initialized = 1; - return 0; -} - - -void duckfs_format(int16_t drive) -{ - /* Nothing to do, DuckFS does not require formatting. */ -} - -int32_t duckfs_makedir(const char* filename, const char* perms) -{ - duckfs_file_header_t* dir = malloc(sizeof(duckfs_file_header_t)); - if (!dir) - { - return -1; - } - - if (strlen(perms) < 3) - { - return -2; - } - - char p[3] = { "." }; - p[0] = perms[0]; - p[1] = perms[1]; - p[2] = perms[2]; - - char filen[DFS_MAX_FILENAME_LEN + 1]; - char perma[3]; - - strcpy(filen, filename); - - - strcpy(perma, perms); - - strncpy(dir->filename, filen, sizeof(dir->filename) - 1); - dir->filename[sizeof(dir->filename) - 1] = '\0'; - - strncpy(dir->permissions, p, sizeof(dir->permissions)); - - dir->type = DFS_FILE_DIRECTORY; - dir->contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES); - - if (!dir->contents) { - free(dir); - return -1; - } - - for (int i = 0; i < DFS_MAX_FILES; i++) { - dir->contents[i].type = DFS_FILE_UNUSED; - } - - return 0; -} - -void duckfs_free_directory(duckfs_file_header_t* dir) -{ - if (!dir || dir->type != DFS_FILE_DIRECTORY || !dir->contents) - { - return; - } - - for (int i = 0; i < DFS_MAX_FILES; i++) { - duckfs_file_header_t* entry = &dir->contents[i]; - - if (entry->type == DFS_FILE_UNUSED) - { - continue; - } - - if (entry->type == DFS_FILE_DIRECTORY) { - duckfs_free_directory(entry); - } - } - - free(dir->contents); - dir->contents = NULL; -} - - -bool duckfs_add_entry(duckfs_file_header_t* dir, duckfs_file_header_t* entry) -{ - if (dir->type != DFS_FILE_DIRECTORY || !dir->contents) - { - return false; - } - - for (int i = 0; i < DFS_MAX_FILES; i++) { - if (dir->contents[i].type == DFS_FILE_UNUSED) { - dir->contents[i] = *entry; - return true; - } - } - return false; /* Directory full */ -} - -duckfs_file_header_t duckfs_create_entry(const char* name, const char* perms, const char* type) -{ - duckfs_file_header_t entry = {0}; - - strncpy(entry.filename, name, DFS_MAX_FILENAME_LEN); - strncpy(entry.permissions, perms, sizeof(entry.permissions) - 1); - - int16_t itype = DFS_FILE_UNUSED; - - if (strcmp(type, "text") == 0) - { - itype = DFS_FILE_TEXT; - } - else if (strcmp(type, "bin") == 0) - { - itype = DFS_FILE_BINARY; - } - else if (strcmp(type, "dir") == 0) - { - itype = DFS_FILE_BINARY; - } - else - { - duckfs_file_header_t vvvv = { .type = DFS_FILE_ERROR }; - return vvvv; - } - - entry.num_sectors = 0; - entry.type = itype; - entry.next = NULL; - entry.prev = NULL; - entry.contents = NULL; - entry.lba_start = 0; - entry.lba_end = 0; - - if (itype == DFS_FILE_DIRECTORY) - { - entry.contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES); - if (entry.contents) - { - for (int i = 0; i < DFS_MAX_FILES; i++) - { - entry.contents[i].type = DFS_FILE_UNUSED; - } - } - } - - return entry; -} - -duckfs_file_header_t duckfs_makefile(const char* filename, const char* perms, duckfs_file_header_t parent) -{ + /*uint8_t superblock_sector[512] = { 0 }; + ide_read*/ } diff --git a/drivers/fs/ramfs.c b/drivers/fs/ramfs.c new file mode 100644 index 0000000..b5caf90 --- /dev/null +++ b/drivers/fs/ramfs.c @@ -0,0 +1,348 @@ +#include +#include +#include + +#include + + + +static ramfs_file_header_t* ramfs_root = NULL; +static int32_t ramfs_num_files = 0; +static int32_t next_fd = 2; + +bool ramfs_initialized = false; + +void ramfs_init(void) +{ + if (!ramfs_initialized) + { + /*printf("%i\n", (int32_t)sizeof(ramfs_file_header_t));*/ + + ramfs_initialized = true; + } +} + +ramfs_file_header_t* ramfs_make_root(void) +{ + ramfs_root = (ramfs_file_header_t*)malloc(sizeof(ramfs_file_header_t)); + + if (!ramfs_root) + { + printf("RAMFS: Error: malloc failed on attempt to malloc ramfs_root\n"); + return NULL; + } + + strcpy(ramfs_root->filename, "/"); + ramfs_root->type = RAMFS_FILE_DIR; + ramfs_root->encryption = RAMFS_ENCR_NONE; + ramfs_root->content = NULL; + ramfs_root->parent = NULL; + ramfs_root->next = NULL; + ramfs_root->link_target = NULL; + ramfs_root->fd = 0; + + return ramfs_root; +} + +ramfs_file_header_t* ramfs_get_root(void) +{ + if (!ramfs_root) + { + return NULL; + } + + return ramfs_root; +} + +int32_t ramfs_get_files(void) +{ + return ramfs_num_files; +} + +bool ramfs_get_initialized(void) +{ + return ramfs_initialized; +} + +ramfs_file_header_t* ramfs_create_file(char* name, char type, char encryption, ramfs_file_header_t* parent) +{ + if (!parent) + { + return NULL; + } + + if ((strlen(name) + 1) > RAMFS_FILENAME_LEN) + { + return NULL; + } + + ramfs_file_header_t* _file = (ramfs_file_header_t*)malloc(sizeof(ramfs_file_header_t)); + + if (!_file) + { + printf("RAMFS: Error: malloc failed on attempt to malloc _file (in ramfs_create_file)\n"); + return NULL; + } + + strcpy(_file->filename, name); + + _file->type = type; + _file->encryption = encryption; + _file->content = NULL; + _file->parent = parent; + _file->next = NULL; + _file->link_target = NULL; + _file->fd = (next_fd - 1); + _file->data_begin = (void*)0x0; + _file->data_end = (void*)0x0; + + if (parent->content != NULL) + { + ramfs_file_header_t* current = parent->content; + + /* Traverse to the end of the linked list */ + while (current->next != NULL) + { + current = current->next; + } + + /* Append the new file at the end */ + current->next = _file; + } + else + { + /* If no content yet, this is the first child */ + parent->content = _file; + } + + ramfs_num_files++; + next_fd++; + + return _file; +} + +ramfs_file_header_t* ramfs_write_file(ramfs_file_header_t* file, void* data, size_t len) +{ + if (!file || !data || !len || file->type == RAMFS_FILE_DIR) + { + return NULL; + } + + /* Free existing data */ + if (file->data_begin) + { + free(file->data_begin); + file->data_begin = NULL; + file->data_end = NULL; + } + + void* new_buf = malloc(len); + if (!new_buf) + { + return NULL; + } + + memcpy(new_buf, data, len); + file->data_begin = new_buf; + file->data_end = (uint8_t*)new_buf + len; + + + return file; +} + + +int32_t ramfs_read_file(ramfs_file_header_t* file, void* buffer, size_t buffer_len) +{ + if (!file) + { + return -1; + } + + if (!buffer) + { + return -2; + } + + if (file->type == RAMFS_FILE_DIR) + { + return -3; + } + + if (!file->data_begin || !file->data_end) + { + return -4; /* No data to read */ + } + + size_t data_len = (size_t)((char*)file->data_end - (char*)file->data_begin); + + if (buffer_len < data_len) + { + return -5; /* Buffer too small */ + } + + memcpy(buffer, file->data_begin, data_len); + + return (int32_t)data_len; /* return number of bytes copied */ +} + +int32_t ramfs_delete_file(ramfs_file_header_t* file) +{ + if (!file) + { + return -1; + } + + if (!file->parent) + { + return -2; /* Don't delete the root or orphaned files */ + } + + ramfs_file_header_t* parent = file->parent; + ramfs_file_header_t* current = parent->content; + ramfs_file_header_t* prev = NULL; + + /* Find the file in the linked list */ + while (current && current != file) + { + prev = current; + current = current->next; + } + + if (!current) + { + return -3; /* File not found in parent's content list */ + } + + /* Unlink the file from the list */ + if (prev) + { + prev->next = current->next; + } + else + { + parent->content = current->next; + } + + /* Recursively delete content if it's a directory */ + if (file->type == RAMFS_FILE_DIR && file->content) + { + ramfs_file_header_t* child = file->content; + while (child) + { + ramfs_file_header_t* next_child = child->next; + ramfs_delete_file(child); + child = next_child; + } + } + + /* Free file data if applicable */ + if ((file->type == RAMFS_FILE_TEXT || file->type == RAMFS_FILE_BINARY) && file->data_begin) + { + free(file->data_begin); + } + + /* Free the file header itself */ + free(file); + + next_fd--; + + return 0; +} + +ramfs_file_header_t* ramfs_resolve_path(const char* path) +{ + if (!path || !ramfs_get_root()) + { + return NULL; + } + + ramfs_file_header_t* current; + + /* Start from root if absolute path */ + if (path[0] == '/') + { + current = ramfs_get_root(); + path++; + } + else + { + /* TODO: make a ramfs_get_cwd and use it instead */ + current = ramfs_get_root(); + } + + char* path_copy = strdup(path); + if (!path_copy) + { + return NULL; + } + + char* token = strtok(path_copy, "/"); + + while (token && current) + { + if (strcmp(token, ".") == 0) + { + /* Stay in the same directory */ + } + else if (strcmp(token, "..") == 0) + { + if (current->parent) + { + current = current->parent; + } + } + else + { + /* Traverse to matching child */ + ramfs_file_header_t* child = current->content; + current = NULL; + + while (child) + { + if (strcmp(child->filename, token) == 0) + { + current = child; + break; + } + child = child->next; + } + + if (!current) + { + /* Not found */ + break; + } + } + + token = strtok(NULL, "/"); + } + + free(path_copy); + return current; /* NULL if not found or invalid path */ +} + +ramfs_file_header_t* ramfs_resolve_fd_dir(ramfs_file_header_t* current, int32_t fd) +{ + if (!current) + { + return NULL; + } + + if (current->fd == fd) + { + return current; + } + + ramfs_file_header_t* found = ramfs_resolve_fd_dir(current->content, fd); + if (found) + { + return found; + } + + return ramfs_resolve_fd_dir(current->next, fd); +} + +ramfs_file_header_t* ramfs_resolve_fd(int32_t fd) +{ + return ramfs_resolve_fd_dir(ramfs_root, fd); +} diff --git a/drivers/fs/vfs.c b/drivers/fs/vfs.c new file mode 100644 index 0000000..cf097cc --- /dev/null +++ b/drivers/fs/vfs.c @@ -0,0 +1,230 @@ +#include +#include +#include + +#include + + +/* + Note: the special FILE value -128 means the current directory. + -32 means stdin + -33 means stdout (which can be read) +*/ + +bool vfs_initialized = false; +ramfs_file_header_t* vfs_current_dir = NULL; + +void vfs_init(void) +{ + if (!vfs_initialized) + { + ramfs_init(); + + ramfs_make_root(); + + vfs_initialized = true; + vfs_current_dir = ramfs_get_root(); + } +} + +/* ramfs_file_header_t* ramfs_create_file(char* name, char type, char encryption, ramfs_file_header_t* parent); */ + +FILE create_file(char* filename, char type, char encryption, FILE parent) +{ + if (!filename) + { + return -1; + } + + if (parent == -128) + { + parent = vfs_current_dir->fd; + } + + ramfs_file_header_t* file = ramfs_create_file(filename, type, encryption, ramfs_resolve_fd(parent)); + if (!file) + { + return -4; /* error code for failed creation */ + } + + return file->fd; +} + +int32_t delete_file(FILE file) +{ + /* + XXX WARNING: ANY AND ALL PROCESSES CAN DELETE A FILE VIA THIS INTERFACE!!! XXX + XXX THIS MUST BE PACHED SOON!!! OR AT LEAST ADD PERMISSION CHECKING IN THE SYSCALL INTERFACE XXX + XXX OR IN THE C LIBRARIES!!! XXX + */ + + if (file < 1) + { + return -4; + } + + ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file); + return ramfs_delete_file(_file); +} + + +/* + Open a file based on a string. + Return a file descriptor on success, a negative value on failure. + + return values: + (positive non-zero value) - File descriptor + -1 - Insufficient permissions to open file + -2 - File does not exist ( or at least, File not found. ) + -3 - No filesystem is initialized + -4 - Internal error, perhaps try again +*/ +FILE open_file(char* filename) +{ + if (ramfs_get_initialized() && vfs_initialized) + { + ramfs_file_header_t* _file = ramfs_resolve_path(filename); + + if (!_file) + { + return (FILE)-2; + } + + return (FILE)_file->fd; + } + + return (FILE)-3; +} + + +FILE write_file(FILE file, void* data, size_t len) +{ + + if (file < 1 || !data || len == 0) + { + return file; + } + + if (ramfs_get_initialized() && vfs_initialized) + { + + ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file); + + if (!_file) + { + return -4; + } + + if (_file->type == RAMFS_FILE_DIR) + { + return -1; + } + + if (_file->data_begin) + { + free(_file->data_begin); + _file->data_begin = NULL; + _file->data_end = NULL; + } + + void* new_buf = malloc(len); + if (!new_buf) + { + return -2; + } + + memcpy(new_buf, data, len); + + _file->data_begin = new_buf; + _file->data_end = (void*)((uint8_t*)new_buf + len); + + return file; + } + + return -3; +} + + +int32_t read_file(FILE file, void* buf, size_t buflen) +{ + if (file < 1 || !buf || buflen == 0) + { + return -1; /* Invalid arguments */ + } + + if (ramfs_get_initialized() && vfs_initialized) + { + ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file); + + if (!_file || _file->type == RAMFS_FILE_DIR) + { + return -2; /* Not a file or trying to read a directory */ + } + + if (!_file->data_begin || !_file->data_end) + { + return 0; /* Empty file */ + } + + size_t total_len = (size_t)((uint8_t*)_file->data_end - (uint8_t*)_file->data_begin); + + if (_file->read_offset >= (int32_t)total_len) + { + return 0; /* End of file */ + } + + size_t available = total_len - _file->read_offset; + size_t to_copy = (buflen < available) ? buflen : available; + + memcpy(buf, (uint8_t*)_file->data_begin + _file->read_offset, to_copy); + + _file->read_offset += to_copy; + + return (int32_t)to_copy; + } + + return -3; /* FS not initialized */ +} + +int32_t reset_read_offset(FILE file) +{ + if (file < 1) + { + return -1; + } + + ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file); + + if (!_file) + { + return -2; + } + + _file->read_offset = 0; + return 0; +} + +int32_t seek_file(FILE file, int32_t offset) +{ + if (file < 0 && file != -32 && file != -33) + { + return -1; /* Invalid file descriptor */ + } + + ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file); + + if (!_file || _file->type == RAMFS_FILE_DIR) + return -2; // Invalid file or directory + + if (!_file->data_begin || !_file->data_end) + return -3; // Empty file + + size_t file_size = (size_t)((uint8_t*)_file->data_end - (uint8_t*)_file->data_begin); + + if (offset < 0 || (size_t)offset > file_size) + return -4; // Offset out of bounds + + _file->read_offset = offset; + return 0; // Success +} + diff --git a/drivers/ide.c b/drivers/ide.c index fe08f4b..bcedfec 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -1,35 +1,38 @@ #include - +#include #include #include -static void io_delay() { - for (int32_t i = 0; i < 1000; i++) { - outb(0x80, 0); +static int32_t ide_wait(uint16_t io, int32_t check_drq) +{ + for (int32_t i = 0; i < 5000; i++) + { + uint8_t status = inb(io + ATA_REG_STATUS); + if (!(status & ATA_SR_BSY)) + { + if (!check_drq || (status & ATA_SR_DRQ)) + { + return 0; + } } + pit_sleep(4); + } + return 1; } - -static int32_t ide_wait(uint16_t io, int32_t check_drq) { - for (int32_t i = 0; i < 5000; i++) { - uint8_t status = inb(io + ATA_REG_STATUS); - if (!(status & ATA_SR_BSY)) { - if (!check_drq || (status & ATA_SR_DRQ)) - return 0; - } - io_delay(1); +static int32_t ide_wait_ready(uint16_t io) +{ + for (int32_t i = 0; i < 100000; i++) + { + uint8_t status = inb(io + ATA_REG_STATUS); + if (!(status & ATA_SR_BSY)) + { + return 0; } - return 1; -} - -static int32_t ide_wait_ready(uint16_t io) { - for (int32_t i = 0; i < 100000; i++) { - uint8_t status = inb(io + ATA_REG_STATUS); - if (!(status & ATA_SR_BSY)) return 0; - } - return 1; + } + return 1; } diff --git a/drivers/irq.c b/drivers/irq.c index f72ad7e..d36093c 100644 --- a/drivers/irq.c +++ b/drivers/irq.c @@ -1,11 +1,9 @@ #include #include +#include #include -static void pit_handler(void) -{ -} void irq_handler(uint8_t irq_number) { diff --git a/drivers/pit.c b/drivers/pit.c index b6c89bc..70cac16 100644 --- a/drivers/pit.c +++ b/drivers/pit.c @@ -1,32 +1,43 @@ -/*#include +#include #include -#include +#include -#define PIT_CHANNEL0 0x40 -#define PIT_COMMAND 0x43 -#define PIT_FREQUENCY 1193182 +#include -static uint32_t tick = 0; -void pit_callback(struct regs* r) +#define PIT_CHANNEL0 0x40 +#define PIT_COMMAND 0x43 +#define PIT_IRQ_LINE 0 +#define PIT_FREQUENCY_BASE 1193182 + +volatile uint64_t pit_ticks = 0; +bool pit_initialized = false; + +void pit_init(void) { - (void)r; - tick++; + uint16_t divisor = (uint16_t)1193; + + /* Send command byte */ + outb(PIT_COMMAND, 0x36); /* Channel 0, low/high byte, mode 3 (square wave), binary */ + + /* Send divisor low and high byte */ + outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF)); /* Low byte */ + outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); /* High byte */ + + pit_initialized = true; } -void pit_init(uint32_t frequency) +void pit_handler(void) { - uint32_t divisor = PIT_FREQUENCY / frequency; - - outb(PIT_COMMAND, 0x36); - outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF)); - outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); - - register_interrupt_handler(32, pit_callback); + pit_ticks++; } -void sleep(uint32_t milliseconds) +void pit_sleep(uint64_t ms) { - uint32_t target = tick + milliseconds; - while (tick < target); -}*/ + uint64_t target = pit_ticks + ms; + while (pit_ticks < target) + { + asm volatile ("hlt"); + } +} + diff --git a/drivers/ps2_keyboard.c b/drivers/ps2_keyboard.c index fa1c6ad..8e25430 100644 --- a/drivers/ps2_keyboard.c +++ b/drivers/ps2_keyboard.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -27,10 +28,20 @@ #define KEYBOARD_IRQ 1 +bool ps2keyboard_initialized = false; /* State for shift key */ static bool shift_pressed = false; +/* State for caps-lock key */ +static bool capslock_pressed = false; + +volatile char current_char; +volatile char* current_string = NULL; +volatile int32_t current_length = 0; +volatile int32_t capacity = 0; + + static const char scancode_map[128] = { 0, 27, '1','2','3','4','5','6','7','8','9','0','-','=','\b', /* Backspace */ '\t', // Tab @@ -51,6 +62,55 @@ static const char scancode_map[128] = { void keyboard_init(void) { outb(0x64, 0xAE); /* Enable keyboard interface (often optional, but here for safety) */ + ps2keyboard_initialized = true; +} + +char get_char(void) +{ + return current_char; +} + +char* get_string(void) +{ + return current_string; +} + +static void append_char(char c) +{ + if (current_length + 1 >= capacity) + { + /* Need more space (+1 for '\0') */ + int new_capacity = (capacity == 0) ? 16 : capacity * 2; + + char* new_str = (char*)malloc(new_capacity); + if (!new_str) { + return; + } + + if (current_string) + { + memcpy(new_str, current_string, current_length); + free(current_string); + } + + current_string = new_str; + capacity = new_capacity; + } + + current_string[current_length] = c; + current_length++; + current_string[current_length] = '\0'; /* Maintain null terminator */ +} + +static void free_current_string(void) +{ + if (current_string) + { + free(current_string); + current_string = NULL; + current_length = 0; + capacity = 0; + } } void keyboard_handler(void) { @@ -67,6 +127,12 @@ void keyboard_handler(void) { shift_pressed = false; return; } + else if (scancode == 0x3A) + { + capslock_pressed = !capslock_pressed; + return; + } + if (scancode & 0x80) { @@ -74,7 +140,7 @@ void keyboard_handler(void) { } else { char c = scancode_map[scancode]; - if (shift_pressed && c >= 'a' && c <= 'z') { + if ((shift_pressed ^ capslock_pressed) && c >= 'a' && c <= 'z') { c -= 32; /* Convert to uppercase */ } else if (shift_pressed) @@ -84,7 +150,17 @@ void keyboard_handler(void) { if (c) { - printf("%c", c); + current_char = c; + + if (c == '\n') + { + free_current_string(); + } + else + { + append_char(c); + printf("%c", c); + } } } } diff --git a/drivers/timer.c b/drivers/timer.c deleted file mode 100644 index 552659f..0000000 --- a/drivers/timer.c +++ /dev/null @@ -1,21 +0,0 @@ -/*#include -#include - -#include - -volatile uint32_t tick_count = 0; - -void irq0_handler(regs_t* regs) -{ - tick_count++; -} - -void timer_sleep(uint32_t ms) -{ - uint32_t target = tick_count + ms; - while (tick_count < target) - { - asm volatile("hlt"); - } -} -*/ diff --git a/drivers/tty.c b/drivers/tty.c index 16ddb6f..2693ec4 100644 --- a/drivers/tty.c +++ b/drivers/tty.c @@ -208,7 +208,7 @@ unsigned char terminal_get_shifted(unsigned char uc) unsigned char syms1[] = { ',', '.', '/', ';', '\'', '[', ']', '`', '-', '=', '\\', '\0' }; unsigned char syms2[] = { '<', '>', '?', ':', '\"', '{', '}', '~', '_', '+', '|', '\0' }; - for (int32_t i = 0; i < (int32_t)(strlen((char*)lowerc) - 1); ++i) + for (int32_t i = 0; i < (int32_t)(strlen((char*)lowerc)); ++i) { if (uc == lowerc[i]) { @@ -220,7 +220,7 @@ unsigned char terminal_get_shifted(unsigned char uc) } } - for (int32_t i = 0; i < (int32_t)(strlen((char*)nums) - 1); ++i) + for (int32_t i = 0; i < (int32_t)(strlen((char*)nums)); ++i) { if (uc == nums[i]) { @@ -232,7 +232,7 @@ unsigned char terminal_get_shifted(unsigned char uc) } } - for (int32_t i = 0; i < (int32_t)(strlen((char*)syms1) - 1); ++i) + for (int32_t i = 0; i < (int32_t)(strlen((char*)syms1)); ++i) { if (uc == syms1[i]) { diff --git a/include/drivers/pit.h b/include/drivers/pit.h index 291e3db..b4a3f5f 100644 --- a/include/drivers/pit.h +++ b/include/drivers/pit.h @@ -3,7 +3,10 @@ #include -void pit_init(uint32_t freq); -void sleep(uint32_t millis); +extern volatile uint64_t pit_ticks; + +void pit_init(void); +void pit_handler(void); +void pit_sleep(uint64_t ms); #endif diff --git a/include/drivers/ps2_keyboard.h b/include/drivers/ps2_keyboard.h index 6743f36..e043914 100644 --- a/include/drivers/ps2_keyboard.h +++ b/include/drivers/ps2_keyboard.h @@ -6,4 +6,7 @@ void keyboard_init(void); void keyboard_handler(void); +char get_char(void); +char* get_string(void); + #endif diff --git a/include/drivers/timer.h b/include/drivers/timer.h deleted file mode 100644 index b7a8d67..0000000 --- a/include/drivers/timer.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _TIMER_H -#define _TIMER_H - -#include - -extern volatile uint32_t tick_count; - -void timer_sleep(uint32_t ms); -void pit_init(uint32_t frequency); - -#endif diff --git a/include/fs/duckfs.h b/include/fs/duckfs.h index 1dd97e9..bfe097f 100644 --- a/include/fs/duckfs.h +++ b/include/fs/duckfs.h @@ -1,79 +1,8 @@ #ifndef _DUCKFS_H #define _DUCKFS_H -#include +#include -#define DFS_MAGIC 0xDF1984CC - -#define DFS_BLOCK_SIZE 512 - -#define DFS_VERSION_0 "DuckFS, wheresDax?" -#define DFS_VERSION_1 "DuckFS, Terminator" -#define DFS_VERSION_2 "DuckFS-Terminator2" -#define DFS_VERSION_3 "DuckFS,StarWarsEIV" -#define DFS_VERSION_4 "DuckFS QUACK,QUACK" - - -#define DFS_FILE_ERROR -8 -#define DFS_FILE_UNUSED -1 -#define DFS_FILE_USED 0 -#define DFS_FILE_TEXT 0 -#define DFS_FILE_BINARY 1 -#define DFS_FILE_DIRECTORY 2 - -/* encryption algorithms */ -#define DFS_CAESAR_5 88 -#define DFS_CAESAR_8 84 -#define DFS_CAESAR_2 09 -#define DFS_QUACK_32 99 - -#define DFS_MAX_FILENAME_LEN 64 -#define DFS_MAX_FILES 256 - - -typedef struct duckfs_file_header { - char filename[DFS_MAX_FILENAME_LEN + 1]; /* + 1 for the \0 */ - char permissions[3]; /* Same thing here */ - - /* - 512 Bytes per sector, meaning a 2 sector file is 1024 bytes, or 1 KiB. - Only valid if this file is not a directory. - */ - int32_t num_sectors; - - int16_t type; /* Indicates the file type. -1 for null file, 0 for a text file, 1 for a binary file, and 2 for a directory. */ - - uint16_t _reserved0; /* (align to 4) */ - - struct duckfs_file_header* next; - struct duckfs_file_header* prev; - struct duckfs_file_header* contents; /* contains the directories files. only valid if this file is a directory. */ - - uint32_t lba_start; /* only is valid if this file is not a directory. */ - uint32_t lba_end; /* only is valid if this file is not a directory. */ - - uint8_t _reserved1[158]; /* padding to 256 bytes total */ -} duckfs_file_header_t; - -typedef struct duckfs_superblock { - int32_t duckfs_magic; /* must be DFS_MAGIC. */ - char duckfs_version_string[19]; - char volume_label[19]; /* 18 characters and a null zero. */ - - int16_t encryption; - - struct duckfs_file_header* duckfs_root; - - uint32_t _padding[116]; -} duckfs_superblock_t; - -int32_t duckfs_init(int16_t drive); -void duckfs_format(int16_t drive); - -int32_t duckfs_makedir(const char* filename, const char* perms); -void duckfs_free_directory(duckfs_file_header_t* dir); - -duckfs_file_header_t duckfs_create_entry(const char* name, const char* perms, const char* type); -bool duckfs_add_entry(duckfs_file_header_t* dir, duckfs_file_header_t* entry); +void duckfs_init(void); #endif diff --git a/include/fs/ramfs.h b/include/fs/ramfs.h index 18a6ea5..68b20bf 100644 --- a/include/fs/ramfs.h +++ b/include/fs/ramfs.h @@ -1,53 +1,56 @@ #ifndef _RAM_FS_H #define _RAM_FS_H -#include -#include +#include - -#define RAMFS_MAX_FILES 128 -#define RAMFS_BLOCK_SIZE 4096 -#define RAMFS_MAX_PATH_LEN 255 +#define RAMFS_FILENAME_LEN 32 #define RAMFS_PERM_READ 0x01 #define RAMFS_PERM_WRITE 0x02 #define RAMFS_PERM_EXEC 0x04 #define RAMFS_PERM_ALL (RAMFS_PERM_READ | RAMFS_PERM_WRITE | RAMFS_PERM_EXEC) -typedef struct ramfs_file { - char name[RAMFS_MAX_PATH_LEN]; - uint32_t size; - uint8_t* data; - uint8_t permissions; -} ramfs_file_t; +#define RAMFS_FILE_DIR 'd' +#define RAMFS_FILE_TEXT 't' +#define RAMFS_FILE_BINARY 'b' +#define RAMFS_FILE_LINK 'l' +#define RAMFS_FILE_NOFILE 'n' -typedef struct ramfs_directory { - char name[RAMFS_MAX_PATH_LEN]; - ramfs_file_t* files[RAMFS_MAX_FILES]; - uint32_t file_count; -} ramfs_directory_t; +#define RAMFS_ENCR_NONE 'n' +#define RAMFS_ENCR_SIMPLE 's' +typedef struct ramfs_file_header { + char filename[RAMFS_FILENAME_LEN + 1]; + char type; + char encryption; + + struct ramfs_file_header* content; + struct ramfs_file_header* parent; + struct ramfs_file_header* next; + struct ramfs_file_header* link_target; + + void* data_begin; + void* data_end; + + int32_t read_offset; + + int32_t fd; +} ramfs_file_header_t; -void ramfs_init(); +void ramfs_init(void); -ramfs_file_t* ramfs_create_file(const char* name, uint32_t size, uint8_t permissions); -bool ramfs_delete_file(const char* name); -ramfs_file_t* ramfs_find_file(const char* name); +ramfs_file_header_t* ramfs_make_root(void); +ramfs_file_header_t* ramfs_get_root(void); +int32_t ramfs_get_files(void); +bool ramfs_get_initialized(void); -bool ramfs_create_directory(const char* name); -bool ramfs_delete_directory(const char* name); +ramfs_file_header_t* ramfs_resolve_path(const char* path); +ramfs_file_header_t* ramfs_resolve_fd_dir(ramfs_file_header_t* current, int32_t fd); +ramfs_file_header_t* ramfs_resolve_fd(int32_t fd); -bool ramfs_check_permissions(const char* name, uint8_t required_permissions); - -bool ramfs_resize_file(const char* name, uint32_t new_size); -bool ramfs_append_to_file(const char* name, const uint8_t* data, uint32_t data_size); - -bool ramfs_read_file(const char* name, uint8_t* buffer, uint32_t buffer_size); -bool ramfs_write_file(const char* name, const uint8_t* data, uint32_t size); -bool ramfs_overwrite_file(const char* name, const uint8_t* data, uint32_t size); - - -void ramfs_list_files(); -void ramfs_list_directories(); +ramfs_file_header_t* ramfs_create_file(char* name, char type, char encryption, ramfs_file_header_t* parent); +int32_t ramfs_delete_file(ramfs_file_header_t* file); +ramfs_file_header_t* ramfs_write_file(ramfs_file_header_t* file, void* data, size_t len); +int32_t ramfs_read_file(ramfs_file_header_t* file, void* buffer, size_t buffer_len); #endif diff --git a/include/fs/vfs.h b/include/fs/vfs.h new file mode 100644 index 0000000..9ea7e42 --- /dev/null +++ b/include/fs/vfs.h @@ -0,0 +1,20 @@ +#ifndef _VFS_H +#define _VFS_H + +#include + +typedef int32_t FILE; + +void vfs_init(void); + +FILE create_file(char* filename, char type, char encryption, FILE parent); +int32_t delete_file(FILE file); + +FILE open_file(char* filename); + +FILE write_file(FILE file, void* data, size_t len); +int32_t read_file(FILE file, void* buf, size_t buflen); + +int32_t reset_read_offset(FILE file); + +#endif diff --git a/include/stdio.h b/include/stdio.h index 72306a4..9427410 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -1,2 +1,10 @@ +#ifndef STDIO_H +#define STDIO_H +#include #include + +char getchar(void); +char* getstring(void); + +#endif diff --git a/include/stdlib.h b/include/stdlib.h index 3652b4c..e91b14e 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -1,9 +1,12 @@ #ifndef STDLIB_H #define STDLIB_H + +#include #include #include #include -#include + +void sleep(uint64_t millis); #endif diff --git a/include/string.h b/include/string.h index 12cfe04..54eab87 100644 --- a/include/string.h +++ b/include/string.h @@ -11,6 +11,9 @@ int32_t strncmp(const char *s1, const char *s2, size_t n); size_t strcpy(char *dst, const char *src); char *strncpy(char *dest, const char *src, uint32_t n); void strcat(char *dest, const char *src); +char* strdup(const char* s); +char* strtok(char* str, const char* delim); +char* strchr(const char* s, int c); int32_t ischar(int32_t c); int32_t isspace(char c); diff --git a/kernel/kernel.c b/kernel/kernel.c index a96df78..7e45b92 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -25,12 +25,13 @@ #include #include #include +#include /*#include */ #include #include -#include #include #include +#include #include @@ -106,6 +107,10 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic) printd("SSE test succeeded\n"); } + printd("Initializing the PIT...\n"); + pit_init(); + printd("PIT initialized\n"); + printd("Initializing the PS/2 keyboard...\n"); keyboard_init(); printd("PS/2 Keyboard initialized\n"); @@ -116,33 +121,66 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic) printd("AHCI initialized\n"); */ - /*printd("Initializing RAMFS...\n"); - ramfs_init(); - printd("RAMFS initialized.\n");*/ + printd("Initializing VFS...\n"); + vfs_init(); + printd("VFS initialized.\n"); printd("Initializing IDE system...\n"); ide_initialize(); printd("IDE initialized\n"); /*printd("Initializing DuckFS...\n"); - int32_t duckfs_init_rv = duckfs_init(0); - printf("[ DEBUG ] DuckFS initialized with RV %d\n", duckfs_init_rv);*/ + duckfs_init(); + printd("DuckFS initialized\n");*/ /*printd("Initializing FAT32...\n"); fat32_init(0); printd("FAT32 initialized\n");*/ - /*printd("Initializing the PIT...\n"); - pit_init(1000); - printd("PIT initialized\n");*/ + /* --- END INITIALIZATION SECTION --- */ terminal_setcolor(VGA_COLOR_LIGHT_GREEN); - /*sleep(1000);*/ - //begin_anim(espresso_kernel_version); + /*pit_sleep(4000); + begin_anim(espresso_kernel_version);*/ + + printf("Creating file via VFS...\n"); + + FILE file = create_file("test.txt", 't', 'n', -128); + printf("file = %d\n", file); + + char buf[32] = "Hello from VFS"; + char bufr[32] = { 0 }; + + write_file(file, buf, strlen(buf)); + + read_file(file, bufr, sizeof(bufr)); + + printf("Read data: %s\n", bufr); + + /*printf("Creating file...\n"); + + ramfs_file_header_t* fil = ramfs_create_file("text", "txt", 't', 'n', ramfs_get_root()); + + if (!fil) + { + printf("File creation failed!\n"); + return; + } + + printf("File created\n"); + + char buf[32] = "hello from RAMFS"; + char bufr[32] = { 0 }; + + ramfs_write_file(fil, buf, strlen(buf)); + ramfs_read_file(fil, bufr, sizeof(bufr)); + + printf("Read data: %s\n", bufr);*/ + printf("Guten tag and welcome to Espresso\n"); diff --git a/lib/fs/ramfs/ramfs.c b/lib/fs/ramfs/ramfs.c deleted file mode 100644 index 026edbd..0000000 --- a/lib/fs/ramfs/ramfs.c +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include - -#include -#include -#include - -#include - - -static ramfs_file_t ramfs_files[RAMFS_MAX_FILES]; -static ramfs_directory_t root_directory = { .name = "/", .file_count = 0 }; - -void ramfs_init() -{ - memset(ramfs_files, 0, sizeof(ramfs_files)); - root_directory.file_count = 0; -} - -ramfs_file_t* ramfs_create_file(const char* name, uint32_t size, uint8_t permissions) -{ - for (uint32_t i = 0; i < RAMFS_MAX_FILES; i++) { - if (ramfs_files[i].name[0] == '\0') { - // Create the file - ramfs_file_t* file = &ramfs_files[i]; - strncpy(file->name, name, RAMFS_MAX_PATH_LEN); - file->size = size; - file->data = (size > 0) ? malloc(size) : NULL; - file->permissions = permissions; - - if (root_directory.file_count < RAMFS_MAX_FILES) { - root_directory.files[root_directory.file_count++] = file; - } - - return file; - } - } - return NULL; -} - -bool ramfs_delete_file(const char* name) -{ - for (uint32_t i = 0; i < root_directory.file_count; i++) { - if (strcmp(root_directory.files[i]->name, name) == 0) { - free(root_directory.files[i]->data); - root_directory.files[i] = root_directory.files[root_directory.file_count - 1]; - root_directory.file_count--; - return true; - } - } - return false; -} - -ramfs_file_t* ramfs_find_file(const char* name) -{ - for (uint32_t i = 0; i < root_directory.file_count; i++) { - if (strcmp(root_directory.files[i]->name, name) == 0) { - return root_directory.files[i]; - } - } - return NULL; -} - -bool ramfs_resize_file(const char* name, uint32_t new_size) -{ - ramfs_file_t* file = ramfs_find_file(name); - if (file) - { - file->data = realloc(file->data, new_size); - file->size = new_size; - return true; - } - return false; -} - -bool ramfs_append_to_file(const char* name, const uint8_t* data, uint32_t data_size) -{ - ramfs_file_t* file = ramfs_find_file(name); - if (file && (file->permissions & RAMFS_PERM_WRITE)) - { - file->data = realloc(file->data, file->size + data_size + 1); - if (!file->data) return false; - - memcpy(file->data + file->size, data, data_size); - file->size += data_size; - file->data[file->size] = '\0'; - return true; - } - return false; -} - -bool ramfs_create_directory(const char* name) -{ - if (root_directory.file_count < RAMFS_MAX_FILES) { - ramfs_directory_t* dir = (ramfs_directory_t*)malloc(sizeof(ramfs_directory_t)); - strncpy(dir->name, name, RAMFS_MAX_PATH_LEN); - dir->file_count = 0; - root_directory.files[root_directory.file_count++] = (ramfs_file_t*)dir; - return true; - } - return false; -} - -bool ramfs_delete_directory(const char* name) -{ - for (uint32_t i = 0; i < root_directory.file_count; i++) { - if (strcmp(root_directory.files[i]->name, name) == 0) { - // Delete the directory (along with its files) - ramfs_directory_t* dir = (ramfs_directory_t*)root_directory.files[i]; - for (uint32_t j = 0; j < dir->file_count; j++) { - free(dir->files[j]->data); - } - free(dir); - root_directory.files[i] = root_directory.files[root_directory.file_count - 1]; - root_directory.file_count--; - return true; - } - } - return false; -} - -bool ramfs_check_permissions(const char* name, uint8_t required_permissions) -{ - ramfs_file_t* file = ramfs_find_file(name); - if (file) { - return (file->permissions & required_permissions) == required_permissions; - } - return false; -} - -void ramfs_list_files() -{ - printf("Files in RAMFS:\n"); - for (uint32_t i = 0; i < root_directory.file_count; i++) { - printf("%s (Size: %u bytes)\n", root_directory.files[i]->name, root_directory.files[i]->size); - } -} - -void ramfs_list_directories() -{ - printf("Directories in RAMFS:\n"); - for (uint32_t i = 0; i < root_directory.file_count; i++) { - if (root_directory.files[i]->data != NULL) { - printf("%s\n", root_directory.files[i]->name); - } - } -} - -bool ramfs_read_file(const char* name, uint8_t* buffer, uint32_t buffer_size) -{ - ramfs_file_t* file = ramfs_find_file(name); - if (file && (file->permissions & RAMFS_PERM_READ)) - { - uint32_t bytes_to_read = (file->size < buffer_size) ? file->size : buffer_size; - memcpy(buffer, file->data, bytes_to_read); - return true; - } - return false; -} - -bool ramfs_write_file(const char* name, const uint8_t* data, uint32_t size) -{ - return ramfs_append_to_file(name, data, size); -} - -bool ramfs_overwrite_file(const char* name, const uint8_t* data, uint32_t size) -{ - ramfs_file_t* file = ramfs_find_file(name); - if (!file || !(file->permissions & RAMFS_PERM_WRITE)) { - return false; - } - - // Allocate space for data + null terminator - uint8_t* new_data = realloc(file->data, size + 1); - if (!new_data && size > 0) { - return false; // realloc failed - } - - file->data = new_data; - - if (size > 0 && data) { - memcpy(file->data, data, size); - } - - file->data[size] = '\0'; // Ensure null-terminated - file->size = size; - - return true; -} - diff --git a/lib/mm/heap.c b/lib/mm/heap.c index 28fc841..e7d4705 100644 --- a/lib/mm/heap.c +++ b/lib/mm/heap.c @@ -69,7 +69,7 @@ void* calloc(size_t nmemb, size_t size) void* ptr = malloc(total); if (ptr) { - memset(ptr, 0, total); + memset(ptr, 0, total); } return ptr; } diff --git a/lib/stdio.c b/lib/stdio.c new file mode 100644 index 0000000..8233dab --- /dev/null +++ b/lib/stdio.c @@ -0,0 +1,62 @@ +#include +#include + +#include + +extern bool ps2keyboard_initialized; + +char getchar(void) +{ + if (ps2keyboard_initialized) + { + return get_char(); + } + + return '\0'; +} + +char* getstring(void) +{ + if (ps2keyboard_initialized) + { + return get_string(); + } + + return "HELLO\0"; +} + +char* fgets(char* buf, int n, FILE file) +{ + if (!buf || n <= 1 || file < 1) + { + return NULL; + } + + int total_read = 0; + char c; + + while (total_read < n - 1) + { + int bytes = read_file(file, &c, 1); + + if (bytes <= 0) + { + break; /* EOF or error */ + } + + buf[total_read++] = c; + + if (c == '\n') + { + break; /* Stop at newline */ + } + } + + if (total_read == 0) + { + return NULL; /* Nothing read (e.g. EOF) */ + } + + buf[total_read] = '\0'; + return buf; +} diff --git a/lib/stdlib.c b/lib/stdlib.c new file mode 100644 index 0000000..4e4781d --- /dev/null +++ b/lib/stdlib.c @@ -0,0 +1,13 @@ +#include + +#include + +extern bool pit_initialized; + +void sleep(uint64_t millis) +{ + if (pit_initialized) + { + pit_sleep(millis); + } +} diff --git a/lib/string.c b/lib/string.c index 47660be..a9f3013 100644 --- a/lib/string.c +++ b/lib/string.c @@ -1,6 +1,8 @@ +#include +#include + #include -#include extern int16_t sse_initialized; @@ -77,6 +79,82 @@ void strcat(char *dest, const char *src) *end = '\0'; } +char* strdup(const char* s) +{ + if (!s) + { + return NULL; + } + + size_t len = strlen(s); + char* copy = (char*)malloc(len + 1); + + if (!copy) + { + return NULL; + } + + memcpy(copy, s, len); + copy[len] = '\0'; + + return copy; +} + +char* strtok(char* str, const char* delim) +{ + static char* next_token = NULL; + + if (str != NULL) + { + next_token = str; + } + else if (next_token == NULL) + { + return NULL; + } + + while (*next_token && strchr(delim, *next_token)) + { + next_token++; + } + + if (*next_token == '\0') + { + return NULL; + } + + char* token_start = next_token; + + while (*next_token && !strchr(delim, *next_token)) + { + next_token++; + } + + if (*next_token) + { + *next_token = '\0'; + next_token++; + } + + return token_start; +} + +char* strchr(const char* s, int c) +{ + while (*s) + { + if (*s == (char)c) + { + return (char*)s; + } + s++; + } + + return NULL; +} + + + void *memset(void *dst, char c, uint32_t n) { char *temp = dst;