From 77c8dca72a54ebac6aa72144b6bfaf69e51a3bd2 Mon Sep 17 00:00:00 2001 From: Rick Rongen Date: Sun, 14 Mar 2021 21:14:22 +0100 Subject: [PATCH] feat: implemented errno, strtol. Started ustar. Reformatted headers and code. Added some self-tests. Started prepwork for vfs. --- CMakeLists.txt | 1 + include/{myke => }/elf.h | 2 +- include/errno.h | 37 +++++ include/myke/command.h | 2 +- include/myke/cpu/cpu.h | 1 + include/myke/cpu/cpuidx.h | 4 +- include/myke/cpu/idt.h | 1 + include/myke/cpu/isr.h | 2 +- include/myke/cpu/syscall_handler.h | 1 + include/myke/debug/debug.h | 8 + include/myke/driver.h | 5 +- include/myke/drivers/{ => pci}/ide.h | 0 include/myke/drivers/{ => pci}/pci.h | 0 include/myke/drivers/{ => pci}/pci_devices.h | 0 include/myke/fs/blockdev.h | 22 +-- include/myke/libk/kprint.h | 2 +- include/myke/libk/libk.h | 5 +- include/myke/libk/syscall.h | 1 + include/myke/mem/malloc.h | 2 + include/myke/mem/pmm.h | 7 +- include/myke/util/power.h | 1 + include/stdlib.h | 2 + include/string.h | 2 +- include/sys/param.h | 4 +- include/unistd.h | 9 +- kernel/command.c | 33 +++- kernel/debug/debug.c | 2 +- kernel/debug/self_test.c | 152 +++++++++++++++++++ kernel/drivers/{ => pci}/ide.c | 8 +- kernel/drivers/{ => pci}/pci.c | 4 +- kernel/fs/blockdev.c | 56 ++++++- kernel/fs/fat.c | 2 +- kernel/fs/mbr.c | 17 ++- kernel/fs/ustar.c | 96 ++++++++++++ kernel/kernel.c | 2 +- kernel/libc/stdlib.c | 56 +++++++ kernel/libc/string.c | 2 +- kernel/tasks/task.c | 11 +- launch-qemu.sh | 2 +- 39 files changed, 504 insertions(+), 60 deletions(-) rename include/{myke => }/elf.h (99%) rename include/myke/drivers/{ => pci}/ide.h (100%) rename include/myke/drivers/{ => pci}/pci.h (100%) rename include/myke/drivers/{ => pci}/pci_devices.h (100%) create mode 100644 kernel/debug/self_test.c rename kernel/drivers/{ => pci}/ide.c (99%) rename kernel/drivers/{ => pci}/pci.c (99%) create mode 100644 kernel/fs/ustar.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f2fde70..4f7e6f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ add_compile_definitions(__kernel__) # Run IDE in DMA mode if available (NYI) #add_compile_definitions(IDE_ENABLE_INTERRUPT) # Run the kernel shell as the main task +add_compile_definitions(ENABLE_SELF_TEST) # Support for pretty printing pci class/subclass/interface add_compile_definitions(ENABLE_PCIPP) # Support for pretty printing pci class/subclass/interface add_compile_definitions(K_SHELL) diff --git a/include/myke/elf.h b/include/elf.h similarity index 99% rename from include/myke/elf.h rename to include/elf.h index de61f73..d5a1c94 100644 --- a/include/myke/elf.h +++ b/include/elf.h @@ -68,6 +68,6 @@ struct elf32_symtab_entry { uint8_t st_info; uint8_t st_other; uint16_t st_shndx; -}; +} packed; #endif //NEW_KERNEL_ELF_H diff --git a/include/errno.h b/include/errno.h index 41d292c..c97247a 100644 --- a/include/errno.h +++ b/include/errno.h @@ -5,4 +5,41 @@ #ifndef NEW_KERNEL_ERRNO_H #define NEW_KERNEL_ERRNO_H +extern int errno; + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + #endif //NEW_KERNEL_ERRNO_H diff --git a/include/myke/command.h b/include/myke/command.h index d5b97cd..fd10cc7 100644 --- a/include/myke/command.h +++ b/include/myke/command.h @@ -9,6 +9,6 @@ void store_bootloader_info(multiboot_info_t *multiboot_info); -void main_loop(void* data); +void main_loop(void *data); #endif //NEW_KERNEL_COMMAND_H diff --git a/include/myke/cpu/cpu.h b/include/myke/cpu/cpu.h index d78156e..f475de3 100644 --- a/include/myke/cpu/cpu.h +++ b/include/myke/cpu/cpu.h @@ -4,6 +4,7 @@ #ifndef NEW_KERNEL_CPU_H #define NEW_KERNEL_CPU_H + #include typedef struct { diff --git a/include/myke/cpu/cpuidx.h b/include/myke/cpu/cpuidx.h index 46b07f3..91d28ec 100644 --- a/include/myke/cpu/cpuidx.h +++ b/include/myke/cpu/cpuidx.h @@ -36,7 +36,7 @@ typedef struct { bool xsave: 1; bool osxsave: 1; bool avx: 1; -} cpu_features_ecx ; +} cpu_features_ecx; typedef struct { bool fpu: 1; @@ -72,7 +72,7 @@ typedef struct { bool ia64: 1; bool pbe: 1; -} cpu_features_edx ; +} cpu_features_edx; enum cpu_features { CPUID_FEAT_ECX_SSE3 = 1 << 0, diff --git a/include/myke/cpu/idt.h b/include/myke/cpu/idt.h index 2c33864..d0b50f1 100644 --- a/include/myke/cpu/idt.h +++ b/include/myke/cpu/idt.h @@ -5,6 +5,7 @@ #ifndef MY_KERNEL_IDT_H #define MY_KERNEL_IDT_H + #include #define KERNEL_CS 0x08 diff --git a/include/myke/cpu/isr.h b/include/myke/cpu/isr.h index 837ae00..6442850 100644 --- a/include/myke/cpu/isr.h +++ b/include/myke/cpu/isr.h @@ -126,7 +126,7 @@ extern void isr128(); #define IRQ14 46 #define IRQ15 47 -typedef void (*isr_t)(isr_registers_t*); +typedef void (*isr_t)(isr_registers_t *); void register_interrupt_handler(uint8_t n, isr_t handler); diff --git a/include/myke/cpu/syscall_handler.h b/include/myke/cpu/syscall_handler.h index b378ac1..840ca4b 100644 --- a/include/myke/cpu/syscall_handler.h +++ b/include/myke/cpu/syscall_handler.h @@ -4,6 +4,7 @@ #ifndef NEW_KERNEL_SYSCALL_HANDLER_H #define NEW_KERNEL_SYSCALL_HANDLER_H + #include void syscall_handle(isr_registers_t *registers); diff --git a/include/myke/debug/debug.h b/include/myke/debug/debug.h index 6ce3430..bc4256f 100644 --- a/include/myke/debug/debug.h +++ b/include/myke/debug/debug.h @@ -8,9 +8,17 @@ #include #ifdef DEBUG_INIT + #include void debug_store_info(struct multiboot_info *info); + +#endif + +#ifdef ENABLE_SELF_TEST + +void self_test(); + #endif void debug_backtrace(bool do_sync); diff --git a/include/myke/driver.h b/include/myke/driver.h index 41bbf72..8386d51 100644 --- a/include/myke/driver.h +++ b/include/myke/driver.h @@ -4,6 +4,7 @@ #ifndef NEW_KERNEL_DRIVER_H #define NEW_KERNEL_DRIVER_H + #include #include @@ -12,8 +13,8 @@ #endif #define DRIVER_CAT(a, b) DRIVER_DUMMY() a ## _ ## b #define DRIVER_DUMMY() -#define SECT_NAME_(a,b) "." #a "." #b -#define SECT_NAME(a,b) SECT_NAME_(a, b) +#define SECT_NAME_(a, b) "." #a "." #b +#define SECT_NAME(a, b) SECT_NAME_(a, b) #define GENERIC_DRIVER(drivername, order) \ static struct drivername DRIVER_CAT(drivername, counter) \ diff --git a/include/myke/drivers/ide.h b/include/myke/drivers/pci/ide.h similarity index 100% rename from include/myke/drivers/ide.h rename to include/myke/drivers/pci/ide.h diff --git a/include/myke/drivers/pci.h b/include/myke/drivers/pci/pci.h similarity index 100% rename from include/myke/drivers/pci.h rename to include/myke/drivers/pci/pci.h diff --git a/include/myke/drivers/pci_devices.h b/include/myke/drivers/pci/pci_devices.h similarity index 100% rename from include/myke/drivers/pci_devices.h rename to include/myke/drivers/pci/pci_devices.h diff --git a/include/myke/fs/blockdev.h b/include/myke/fs/blockdev.h index ff0895f..7731733 100644 --- a/include/myke/fs/blockdev.h +++ b/include/myke/fs/blockdev.h @@ -5,6 +5,7 @@ #ifndef NEW_KERNEL_BLOCKDEV_H #define NEW_KERNEL_BLOCKDEV_H +#include #include #include @@ -24,18 +25,19 @@ #define BLOCK_DEV_REGISTER_FULL 1 -typedef struct block_device block_device; +typedef struct block_device block_device_t; -typedef uint8_t (*block_device_driver_check_device)(const block_device *device, uint8_t *first_sector); +typedef uint8_t (*block_device_driver_check_device)(const block_device_t *device, uint8_t *first_sector); -typedef uint8_t (*block_device_driver_free)(const block_device *device); +typedef uint8_t (*block_device_driver_free)(const block_device_t *device); -typedef uint8_t (*block_device_access)(const block_device *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target); +typedef uint8_t (*block_device_access)(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, + void *target); struct block_dev_driver { char name[16]; struct { - uint8_t root_only: 1; + uint8_t partitioning: 1; } flags; block_device_driver_check_device check_device; block_device_driver_free free_device; @@ -43,7 +45,7 @@ struct block_dev_driver { #define BLOCK_DEV_DRIVER(order) GENERIC_DRIVER(block_dev_driver, order) -typedef struct block_device { +struct block_device { struct { uint8_t present: 1; uint8_t scanned: 1; @@ -58,14 +60,16 @@ typedef struct block_device { struct block_dev_driver *driver; void *device_info; // pointer to driver defined structure // todo device info -} block_device; +}; -uint8_t block_dev_register(block_device *device); +uint8_t block_dev_register(block_device_t *device); -void block_dev_free(block_device *device); +void block_dev_free(block_device_t *device); void block_dev_start_task(); void block_dev_print_info(); +bool block_dev_mount(char *identifier, char *driver); + #endif //NEW_KERNEL_BLOCKDEV_H diff --git a/include/myke/libk/kprint.h b/include/myke/libk/kprint.h index 6503ead..e9f1cbd 100644 --- a/include/myke/libk/kprint.h +++ b/include/myke/libk/kprint.h @@ -15,7 +15,7 @@ void kprint_register(kprint_handler); void kprint(const char *msg); -void kprint_sync(const char* msg); +void kprint_sync(const char *msg); void kprint_init(); diff --git a/include/myke/libk/libk.h b/include/myke/libk/libk.h index 69a30c3..350d8f0 100644 --- a/include/myke/libk/libk.h +++ b/include/myke/libk/libk.h @@ -4,11 +4,12 @@ #ifndef NEW_KERNEL_LIBK_H #define NEW_KERNEL_LIBK_H + #include #include -extern void* _kernel_start; -extern void* _kernel_end; +extern void *_kernel_start; +extern void *_kernel_end; #define kernel_start ((uint32_t)(&_kernel_start)) #define kernel_end ((uint32_t)(&_kernel_end)) diff --git a/include/myke/libk/syscall.h b/include/myke/libk/syscall.h index 150cecf..da2d598 100644 --- a/include/myke/libk/syscall.h +++ b/include/myke/libk/syscall.h @@ -4,6 +4,7 @@ #ifndef NEW_KERNEL_SYSCALL_H #define NEW_KERNEL_SYSCALL_H + #include #include diff --git a/include/myke/mem/malloc.h b/include/myke/mem/malloc.h index 2caa61a..743ed5f 100644 --- a/include/myke/mem/malloc.h +++ b/include/myke/mem/malloc.h @@ -16,7 +16,9 @@ void *calloc(size_t, size_t); void free(void *); #ifndef INCLUDE_STDLIB + void print_malloc_info(); + #endif #endif //NEW_KERNEL_MALLOC_H diff --git a/include/myke/mem/pmm.h b/include/myke/mem/pmm.h index 5c71e16..b5643ff 100644 --- a/include/myke/mem/pmm.h +++ b/include/myke/mem/pmm.h @@ -4,13 +4,16 @@ #ifndef NEW_KERNEL_PMM_H #define NEW_KERNEL_PMM_H + #include // 4k blocks #define PAGE_SIZE 4096 -void pmm_init(void* start_addr, size_t size); +void pmm_init(void *start_addr, size_t size); + void *pmm_get_pages(uint32_t num_pages); -void pmm_free_pages(void* page, uint32_t num_pages); + +void pmm_free_pages(void *page, uint32_t num_pages); #endif //NEW_KERNEL_PMM_H diff --git a/include/myke/util/power.h b/include/myke/util/power.h index 7321eaf..88bfa64 100644 --- a/include/myke/util/power.h +++ b/include/myke/util/power.h @@ -4,6 +4,7 @@ #ifndef NEW_KERNEL_POWER_H #define NEW_KERNEL_POWER_H + #include void noreturn power_shutdown(); diff --git a/include/stdlib.h b/include/stdlib.h index 196789a..2d25a7b 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -33,4 +33,6 @@ long long llabs(long long val); void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)); +long strtol(const char *nptr, char **endptr, int base); + #endif //NEW_KERNEL_STDLIB_H diff --git a/include/string.h b/include/string.h index 844cd5f..745fd7a 100644 --- a/include/string.h +++ b/include/string.h @@ -11,7 +11,7 @@ int memcpy(void *dst, const void *src, size_t amount); int memset(void *dst, int data, size_t amount); -int strcpy(char *dst, char *src); +int strcpy(char *dst, const char *src); size_t strlen(const char *str); diff --git a/include/sys/param.h b/include/sys/param.h index bd9c3d5..af798a6 100644 --- a/include/sys/param.h +++ b/include/sys/param.h @@ -5,7 +5,7 @@ #ifndef NEW_KERNEL_PARAM_H #define NEW_KERNEL_PARAM_H -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a, b) (((a)<(b))?(a):(b)) +#define MAX(a, b) (((a)>(b))?(a):(b)) #endif //NEW_KERNEL_PARAM_H diff --git a/include/unistd.h b/include/unistd.h index 37f3085..e6ad5de 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -4,11 +4,14 @@ #ifndef NEW_KERNEL_UNISTD_H #define NEW_KERNEL_UNISTD_H + #include -int execv(const char*, char* const[]); -int execve(const char*, char* const[], char* const[]); -int execvp(const char*, char* const[]); +int execv(const char *, char *const[]); + +int execve(const char *, char *const[], char *const[]); + +int execvp(const char *, char *const[]); pid_t fork(void); diff --git a/kernel/command.c b/kernel/command.c index 89dfac9..18105c2 100644 --- a/kernel/command.c +++ b/kernel/command.c @@ -11,14 +11,20 @@ #include #include #include -#include -#include +#include +#include #include #include #include #include #include +#ifdef ENABLE_SELF_TEST + +#include + +#endif + #define BOOTLOADER_NAME_MAX_LENGTH 64 #define CMDLINE_MAX_LENGTH 256 @@ -44,16 +50,29 @@ void shutdown(const char *args); void explode(const char *args); +#ifdef ENABLE_SELF_TEST + +void exec_self_test(const char *args); + +#endif + cmd_handler cmd_handlers[] = { - {"help\0", help}, - {"echo\0", echo}, - {"print\0", print}, - {"ide\0", ide}, + {"help", help}, + {"echo", echo}, + {"print", print}, + {"ide", ide}, {"shutdown", shutdown}, - {"explode", explode}, + {"explode", explode}, +#ifdef ENABLE_SELF_TEST + {"self-test", exec_self_test}, +#endif {NULL, NULL}, }; +void exec_self_test(const char *args) { + self_test(); +} + void explode(const char *args) { uint32_t x = 0; diff --git a/kernel/debug/debug.c b/kernel/debug/debug.c index 7629a10..2894bd1 100644 --- a/kernel/debug/debug.c +++ b/kernel/debug/debug.c @@ -8,7 +8,7 @@ #define DEBUG_INIT #include -#include +#include #include #include diff --git a/kernel/debug/self_test.c b/kernel/debug/self_test.c new file mode 100644 index 0000000..be21bfd --- /dev/null +++ b/kernel/debug/self_test.c @@ -0,0 +1,152 @@ +// +// Created by rick on 13-03-21. +// + +#ifdef ENABLE_SELF_TEST + +#include +#include +#include +#include +#include + +void assert_int(int expected, int actual) { + if (expected != actual) { + debug_backtrace(true); + k_panics("Assertion failed, integers not equal\n"); + } +} + +void assert_long(long expected, long actual) { + if (expected != actual) { + debug_backtrace(true); + k_panics("Assertion failed, integers not equal\n"); + } +} + +void assert_long_long(long long expected, long long actual) { + if (expected != actual) { + debug_backtrace(true); + k_panics("Assertion failed, integers not equal\n"); + } +} + +void assert_ptr(const void *expected, const void *actual) { + if (expected != actual) { + debug_backtrace(true); + k_panics("Assertion failed, integers not equal\n"); + } +} + +void assert_array_equal(const uint8_t *a, const uint8_t *b, size_t size) { + for (size_t i = 0; i < size; ++i) { + if (a[i] != b[i]) { + debug_backtrace(true); + k_panics("Assertion failed, arrays differ\n"); + } + } +} + +void assert_array_all_entries(const uint8_t *a, uint8_t value, size_t size) { + for (size_t i = 0; i < size; ++i) { + if (a[i] != value) { + debug_backtrace(true); + k_panics("Assertion failed, arrays differ\n"); + } + } +} + +void test_string() { + // test strncmp + assert_int(0, strncmp("abc", "abc", 3)); + assert_int(1, strncmp("abcd", "abc", 4)); + assert_int(-1, strncmp("abc", "abcd", 4)); + + // test strcmp + assert_int(0, strcmp("abc", "abc")); + assert_int(1, strcmp("abc", "abd")); + assert_int(-1, strcmp("abc", "abb")); + assert_int(-1, strcmp("abc", "abcd")); + assert_int(1, strcmp("abcd", "abc")); + + uint8_t array_a[8] = {0}; + uint8_t array_b[16] = {0}; + // memset + assert_array_all_entries(array_b, 0, 16); + memset(array_b, 1, 8); + assert_array_all_entries(array_b, 1, 8); + assert_array_all_entries(array_b + 8, 0, 8); + memset(array_b, 1, 16); + assert_array_all_entries(array_b, 1, 16); + + // memcpy + memcpy(array_b, array_a, 8); + assert_array_all_entries(array_b, 0, 8); + assert_array_all_entries(array_b + 8, 1, 8); + memcpy(array_b + 8, array_a, 8); + assert_array_all_entries(array_b + 8, 0, 16); + + // strlen + assert_int(3, strlen("abc")); + assert_int(4, strlen("abcd")); + assert_int(5, strlen("abcde")); + assert_int(0, strlen("")); + + // strchr + const char *strchr_test = "abcdef"; + assert_ptr(&strchr_test[3], strchr(strchr_test, 'd')); + assert_ptr(NULL, strchr(strchr_test, '9')); + + // strcpy + const char *strcpy_src_test = "abc\0def"; + char *strcpy_dst_test = "\0\0\0\0\0\0\0"; + const char *strcpy_expected_test = "abc\0\0\0\0"; + assert_int(0, strcpy(strcpy_dst_test, strcpy_src_test)); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpointer-sign" + assert_array_equal(strcpy_dst_test, strcpy_expected_test, 8); +#pragma clang diagnostic pop +} + +void test_stdlib() { + // abs + assert_int(1, abs(1)); + assert_int(1, abs(-1)); + assert_int(0, abs(0)); + assert_int(0, abs(-0)); + + // labs + assert_long(1l, labs(1l)); + assert_long(1l, labs(-1l)); + assert_long(0l, labs(0l)); + assert_long(0l, labs(-0l)); + + // llabs + assert_long_long(1ll, llabs(1ll)); + assert_long_long(1ll, llabs(-1ll)); + assert_long_long(0ll, llabs(0ll)); + assert_long_long(0ll, llabs(-0ll)); + + assert_long(10, strtol("10", NULL, 10)); + assert_long(-10, strtol("-10", NULL, 10)); + assert_long(16, strtol("10", NULL, 16)); + assert_long(-16, strtol("-10", NULL, 16)); + assert_long(8, strtol("10", NULL, 8)); + assert_long(-8, strtol("-10", NULL, 8)); + assert_long(8, strtol("010", NULL, 8)); + assert_long(-8, strtol("-010", NULL, 8)); + assert_long(200, strtol("5K", NULL, 36)); + assert_long(-200, strtol("-5K", NULL, 36)); + assert_long(-200, strtol("-5k", NULL, 36)); + + errno = 0; + assert_long(-1, strtol("A", NULL, 10)); + assert_int(errno, EINVAL); +} + +void self_test() { + test_string(); + test_stdlib(); +} + +#endif \ No newline at end of file diff --git a/kernel/drivers/ide.c b/kernel/drivers/pci/ide.c similarity index 99% rename from kernel/drivers/ide.c rename to kernel/drivers/pci/ide.c index e7987f3..b03ffe2 100644 --- a/kernel/drivers/ide.c +++ b/kernel/drivers/pci/ide.c @@ -8,11 +8,11 @@ #include #include -#include +#include #include #include #include -#include +#include #include #include #include @@ -377,7 +377,7 @@ bool ide_pci_init_channels(pci_device *device) { } uint8_t -ide_block_dev_access(const block_device *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) { +ide_block_dev_access(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) { ide_block_device_info *info = device->device_info; uint8_t result = ide_access(direction, info->device_number, lba, sectors, target); if (result != 0) { @@ -399,7 +399,7 @@ void ide_register_block_devices() { info->device_number = i; info->print_error = 1; - block_device device = { + block_device_t device = { .flags.present = 1, .flags.root_device = 1, .device_info = info, diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci/pci.c similarity index 99% rename from kernel/drivers/pci.c rename to kernel/drivers/pci/pci.c index 90aa38b..002ec70 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci/pci.c @@ -6,13 +6,13 @@ #include #include -#include +#include #include #include #ifdef ENABLE_PCIPP -#include +#include #endif diff --git a/kernel/fs/blockdev.c b/kernel/fs/blockdev.c index 110a9f4..d9b3a2a 100644 --- a/kernel/fs/blockdev.c +++ b/kernel/fs/blockdev.c @@ -15,7 +15,7 @@ #define MAX_BLOCK_DEVS 64 int last_block_dev = 0; -block_device block_devices[MAX_BLOCK_DEVS] = {0}; +block_device_t block_devices[MAX_BLOCK_DEVS] = {0}; extern struct block_dev_driver __start_block_dev_driver[]; extern struct block_dev_driver __stop_block_dev_driver[]; @@ -25,12 +25,12 @@ extern struct block_dev_driver __stop_block_dev_driver[]; semaphore_t *block_semaphore; bool blockdev_task_running = false; -uint8_t block_dev_register(block_device *device) { +uint8_t block_dev_register(block_device_t *device) { if (last_block_dev >= MAX_BLOCK_DEVS - 1) { return BLOCK_DEV_REGISTER_FULL; } - memcpy((uint8_t *) &block_devices[last_block_dev++], (const uint8_t *) device, sizeof(block_device)); + memcpy((uint8_t *) &block_devices[last_block_dev++], (const uint8_t *) device, sizeof(block_device_t)); if (blockdev_task_running) { semaphore_signal(block_semaphore); @@ -38,7 +38,7 @@ uint8_t block_dev_register(block_device *device) { return BLOCK_DEV_REGISTER_OK; } -void block_dev_free(block_device *device) { +void block_dev_free(block_device_t *device) { //todo k_panics("block dev free not supported"); } @@ -51,6 +51,43 @@ int block_dev_num_not_scanned() { return not_scanned; } +bool block_dev_mount(char *identifier, char *driver_name) { + bool result = true; + block_device_t *device = NULL; + for (int i = 0; i < last_block_dev; ++i) { + if (strncmp(block_devices[i].identifier, identifier, 16) == 0) { + device = &block_devices[i]; + } + } + if (identifier == NULL) { + result = false; + goto _end; + } + struct block_dev_driver *driver = NULL; + for (size_t j = 0; j < NUM_DRIVERS; ++j) { + if (strncmp(DRIVER(j)->name, driver_name, 16) == 0) { + driver = DRIVER(j); + } + } + if (driver == NULL) { + result = false; + goto _end; + } + uint8_t *lba0 = malloc(device->block_size); + uint8_t read_result = device->access(device, BLOCK_DEV_DIRECTION_READ, 0, 1, lba0); + if (read_result != BLOCK_DEV_ACCESS_OK) { + result = false; + goto _access_fail; + } + if (driver->check_device(device, lba0) != BLOCK_DEV_DRIVER_CHECK_OK) { + result = false; + } + _access_fail: + free(lba0); + _end: + return result; +} + void block_dev_scan() { int c_last_block_dev = last_block_dev; for (int i = 0; i < c_last_block_dev; ++i) { @@ -62,9 +99,14 @@ void block_dev_scan() { goto _block_dev_scan_free; } for (size_t j = 0; j < NUM_DRIVERS; ++j) { - // validate if driver is appropriate at all - // don't use a root device driver (i.e. mbr) for a non-root device - if (DRIVER(j)->flags.root_only && !block_devices[i].flags.root_device) continue; + // only partitioning drivers are automatically assigned + if (!DRIVER(i)->flags.partitioning) { + continue; + } + // only root devices have partitions + if (!block_devices[i].flags.root_device) { + continue; + } // let the driver test the disk uint8_t driver_result = DRIVER(j)->check_device(&block_devices[i], lba0); diff --git a/kernel/fs/fat.c b/kernel/fs/fat.c index 91c147c..23ff654 100644 --- a/kernel/fs/fat.c +++ b/kernel/fs/fat.c @@ -107,7 +107,7 @@ void print_chars(char *chars, int amount) { } } -uint8_t used fat_check_device(const block_device *device, uint8_t *first_sector) { +uint8_t used fat_check_device(const block_device_t *device, uint8_t *first_sector) { fat_bpb bpb; memcpy((uint8_t *) &bpb, first_sector, sizeof(fat_bpb)); if (bpb.bpb.sectors_per_fat == 0 || bpb.bpb.sectors_per_cluster == 0) { diff --git a/kernel/fs/mbr.c b/kernel/fs/mbr.c index 1e5930a..a1567a1 100644 --- a/kernel/fs/mbr.c +++ b/kernel/fs/mbr.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -33,12 +33,12 @@ typedef struct { } packed mbr_table; typedef struct { - const block_device *device; + const block_device_t *device; uint32_t start_lba; } mbr_block_driver_info; uint8_t -mbr_block_dev_access(const block_device *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) { +mbr_block_dev_access(const block_device_t *device, uint8_t direction, uint32_t lba, uint8_t sectors, void *target) { if (!device->flags.present || lba > device->num_lba) { return BLOCK_DEV_ACCESS_ERR; } @@ -52,7 +52,7 @@ mbr_block_dev_access(const block_device *device, uint8_t direction, uint32_t lba return info->device->access(info->device, direction, actual_lba, sectors, target); } -uint8_t used mbr_check_device(const block_device *device, uint8_t *first_sector) { +uint8_t used mbr_check_device(const block_device_t *device, uint8_t *first_sector) { mbr_table table; memcpy((uint8_t *) &table, first_sector + (device->block_size - sizeof(mbr_table)), sizeof(mbr_table)); if (table.signature[0] != 0x55 && table.signature[1] != 0xAA) { // AA 55 but in little endian @@ -69,14 +69,16 @@ uint8_t used mbr_check_device(const block_device *device, uint8_t *first_sector) } } + int num_parts = 0; for (int i = 0; i < 4; ++i) { if (table.entries[i].system_id == 0) continue; + num_parts += 1; mbr_block_driver_info *info = malloc(sizeof(mbr_block_driver_info)); info->device = device; info->start_lba = table.entries[i].start_lba; - block_device logical_device = { + block_device_t logical_device = { .flags.present = 1, .num_lba = table.entries[i].num_lbas, @@ -88,7 +90,10 @@ uint8_t used mbr_check_device(const block_device *device, uint8_t *first_sector) sprintf(logical_device.identifier, "%sp%d", device->identifier, i); block_dev_register(&logical_device); + } + if (num_parts == 0) { + return BLOCK_DEV_DRIVER_CHECK_NO_MATCH; } return BLOCK_DEV_DRIVER_CHECK_OK; @@ -104,7 +109,7 @@ void mbr_read_from_ide(uint8_t ide_drive) { BLOCK_DEV_DRIVER(200) = { .name = "mbr", - .flags.root_only = 1, + .flags.partitioning = 1, .check_device = mbr_check_device, .free_device = NULL, // todo }; diff --git a/kernel/fs/ustar.c b/kernel/fs/ustar.c new file mode 100644 index 0000000..dc7e5bb --- /dev/null +++ b/kernel/fs/ustar.c @@ -0,0 +1,96 @@ +// +// Created by rick on 11-03-21. +// +#include + +#include +#include +#include +#include + +typedef struct { + char filename[100]; + uint64_t mode; + uint64_t uid; + uint64_t gid; + char filesize[12]; + char lastmod[12]; + uint64_t checksum; + char type; + char linked[100]; + char magic[6]; + char version[2]; + char username[32]; + char groupname[32]; + uint64_t device_major; + uint64_t device_minor; + char prefix[155]; +} packed ustar_sector; + +typedef struct { + ustar_sector sector; + uint32_t lba; +} ustar_inode; + +typedef struct { + ustar_inode *first_inode; + const block_device_t *device; +} ustar_fs; + +const char *ustar_magic = "ustar"; +const char *ustar_version = "00"; + +#define USTAR_TYPE_FILE '0' +#define USTAR_TYPE_LINK '1' +#define USTAR_TYPE_SYMBOL '2' +#define USTAR_TYPE_CHAR '3' +#define USTAR_TYPE_BLOCK '4' +#define USTAR_TYPE_DIR '5' +#define USTAR_TYPE_FIFO '6' + +#define SECTOR_SIZE 512 + +long ustar_oct_to_long(char *oct, uint32_t size) { + char value[size + 1]; + memcpy(value, oct, size); + value[size] = 0; + return strtol(value, NULL, 8); +} + +bool ustar_sector_valid(ustar_sector *sector) { + return strncmp(ustar_magic, sector->magic, 6) == 0; +} + +ustar_sector *ustar_next(ustar_sector *current) { + if (ustar_sector_valid(current)) { + return NULL; + } + + long filesize = ustar_oct_to_long(current->filesize, 12); + + long offset = (((filesize + SECTOR_SIZE - 1) / SECTOR_SIZE) + 1) * SECTOR_SIZE; + + ustar_sector *next = ((void *) current) + offset; + return ustar_sector_valid(next) ? next : NULL; +} + +uint8_t ustar_check_device(const block_device_t *device, uint8_t *first_sector) { + ustar_sector *sector = (ustar_sector *) first_sector; + if (!ustar_sector_valid(sector)) { + return BLOCK_DEV_DRIVER_CHECK_NO_MATCH; + } + + ustar_fs *fs = malloc(sizeof(ustar_fs)); + fs->first_inode = malloc(sizeof(ustar_inode)); + memcpy(&fs->first_inode->sector, first_sector, sizeof(ustar_sector)); + fs->first_inode->lba = 0; + fs->device = device; + + return BLOCK_DEV_DRIVER_CHECK_OK; +} + +BLOCK_DEV_DRIVER(300) = { + .name = "ustar", + .check_device = ustar_check_device, + .free_device = NULL, +}; \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index 4bac1b7..a1a2b01 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/kernel/libc/stdlib.c b/kernel/libc/stdlib.c index d3c1373..ee42bd2 100644 --- a/kernel/libc/stdlib.c +++ b/kernel/libc/stdlib.c @@ -6,6 +6,8 @@ */ #include +#include +#include /* everything of stdlib is implemented in this file except for: * - qsort @@ -76,3 +78,57 @@ char *itoa(int value, char *buffer, int base) { // reverse the string and return it return reverse(buffer, 0, i - 1); } + +long strtol(const char *nptr, char **endptr, int base) { + if (base > 36) { + errno = EINVAL; + return -1; + } + char sign = '+'; + long n = 0; + long i; + const char *c = nptr; + while (*c == ' ') { + c++; + } + if (*c == '+') { + c++; + } else if (*c == '-') { + sign = '-'; + c++; + } + while (*c != '\0') { + n *= base; + if (*c >= '0' && *c <= '9') { + i = *c - '0'; + } else if (*c >= 'a' && *c <= 'z') { + i = *c - 'a' + 10; + } else if (*c >= 'A' && *c <= 'Z') { + i = *c - 'A' + 10; + } else { + errno = EINVAL; + n = -1; + goto _set_endptr; + } + if (i >= base) { + errno = EINVAL; + n = -1; + goto _set_endptr; + } + if (i > (LONG_MAX - n)) { + errno = ERANGE; + n = sign == '-' ? LONG_MIN : LONG_MAX; + goto _set_endptr; + } + n += i; + c++; + } + if (sign == '-') { + n *= -1; + } + _set_endptr: + if (endptr != NULL) { + *endptr = c; + } + return n; +} diff --git a/kernel/libc/string.c b/kernel/libc/string.c index 55a251b..a97b54c 100644 --- a/kernel/libc/string.c +++ b/kernel/libc/string.c @@ -20,7 +20,7 @@ int memset(void *dst, int data, size_t amount) { } -int strcpy(char *dst, char *src) { +int strcpy(char *dst, const char *src) { return memcpy(dst, src, strlen(src) + 1); } diff --git a/kernel/tasks/task.c b/kernel/tasks/task.c index 028e1e3..525320a 100644 --- a/kernel/tasks/task.c +++ b/kernel/tasks/task.c @@ -23,6 +23,7 @@ #define TASK_STATE_STOPPED (1 << 6) #define TASK_STATE_ERROR (1 << 7) +int errno = 0; typedef struct task { bool present: 1; @@ -31,6 +32,8 @@ typedef struct task { uint32_t tid; + int errno; + struct task *next; void *stack; @@ -142,10 +145,14 @@ void task_switch_next_inner(task_t *next_task) { } task_t *previous_task = current_task; current_task = next_task; - if (previous_task->state == TASK_STATE_RUNNING) { - previous_task->state = TASK_STATE_RUNNABLE; + if (previous_task != NULL) { + previous_task->errno = errno; + if (previous_task->state == TASK_STATE_RUNNING) { + previous_task->state = TASK_STATE_RUNNABLE; + } } current_task->state = TASK_STATE_RUNNING; + errno = current_task->errno; // switch task switch_task(previous_task == NULL ? NULL : &previous_task->task_registers, current_task->task_registers); } diff --git a/launch-qemu.sh b/launch-qemu.sh index 52db6a9..f26d226 100755 --- a/launch-qemu.sh +++ b/launch-qemu.sh @@ -26,7 +26,7 @@ while [[ "$#" -gt 0 ]]; do ;; --net) cp cmake-build-debug/my-kernel.bin netdir/my-kernel.bin - KERNEL="-netdev user,id=n0,tftp=netdir,bootfile=/boot/grub/i386-pc/core.0 -device e1000,netdev=n0" + KERNEL="-netdev user,id=n0,tftp=netdir,bootfile=/boot/grub/i386-pc/core.0 -device e1000,netdev=n0,bootindex=1" shift ;; -i | --ide)