diff --git a/.gitignore b/.gitignore index 922937d..63b52a8 100644 --- a/.gitignore +++ b/.gitignore @@ -112,4 +112,5 @@ modules.xml # End of https://www.toptal.com/developers/gitignore/api/cmake,jetbrains+all *.old -**/__pycache__ \ No newline at end of file +**/__pycache__ +*.img \ No newline at end of file diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index add0829..0e8d322 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -10,6 +10,7 @@ #include #include #include +#include const char scancode_map_lowercase[] = { @@ -88,7 +89,7 @@ char getc() { KeyEvent *get_next_event() { KeyEvent *target = malloc(sizeof(KeyEvent)); if (!ring_buffer_get(keyboard_event_buffer, target)) { - asm("hlt"); + k_wait_for_interrupt(); free(target); return NULL; } diff --git a/kernel/kernel.c b/kernel/kernel.c index e097349..b4fd934 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -11,22 +11,111 @@ #include #include #include +#include + +#define BOOTLOADER_NAME_MAX_LENGTH 64 +#define CMDLINE_MAX_LENGTH 256 const char *msg_booted = "Booted Successfully!\n"; const char *newline = "\n"; const char *msg_unknown_command = "Unknown command: "; -const char *cmd_echo = "echo"; -const char *cmd_print_mmap = "print_mmap"; -const char *cmd_print_malloc = "print_malloc"; -const char *cmd_print_tick = "print_tick"; +char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH]; +char cmdline[CMDLINE_MAX_LENGTH]; + +typedef void (*cmd_handler_func)(const char *); + +typedef struct { + char *cmd; + cmd_handler_func handler; +} cmd_handler; + +void print(const char *arg); +void echo(const char *arg); +void help(const char *arg); + +cmd_handler cmd_handlers[] = { + {"help", help}, + {"echo", echo}, + {"print", print}, + {NULL, NULL}, +}; + +void print_bootinfo() { + kprint("Bootloader name: "); + kprint(bootloader_name[0] == 0 ? "NULL" : bootloader_name); + kprint(newline); + kprint("cmdline: "); + kprint(cmdline[0] == 0 ? "NULL" : cmdline); + kprint(newline); +} + +void help(const char* arg) { + kprint("Available commands:\n"); + int index = 0; + while (true) { + if (cmd_handlers[index].cmd == NULL) { + break; + } + kprint(cmd_handlers[index].cmd); + kprint(newline); + index += 1; + } + +} + +void echo(const char *arg) { + kprint(arg); + kprint(newline); +} + +void print(const char *arg) { + if (strcmp(arg, "mmap") == 0) { + print_mmap_info(); + } else if (strcmp(arg, "malloc") == 0) { + print_malloc_info(); + } else if (strcmp(arg, "tick") == 0) { + print_current_tick(); + } else if (strcmp(arg, "bootinfo") == 0) { + print_bootinfo(); + } else { + kprint("Unknown print "); + kprint(arg); + kprint(newline); + } +} void main_loop(); -void panic() { - kprint("PANIC!"); - asm("cli;" - "hlt;"); +void store_bootloader_info(multiboot_info_t *multiboot_info) { + // get bootloader and cmdline + if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) { + int cmdline_length = strlen((const char *) multiboot_info->cmdline); + if (cmdline_length > CMDLINE_MAX_LENGTH) { + kprint("cmdline to long!"); + k_panic(); + } + memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length); + } + if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) { + int bootloader_length = strlen((const char *) multiboot_info->boot_loader_name); + if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) { + kprint("bootloader name to long!"); + k_panic(); + } + memcpy(bootloader_name, (char *) multiboot_info->boot_loader_name, bootloader_length); + } +} + +void init_mmap(multiboot_info_t *multiboot_info) { + if (multiboot_info->flags & (1 << 6)) { + init_mmap_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr, + multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry)); + // todo fallback on other mechanisms? + } else { + kprint("mmap invalid!\n"); + k_panic(); + } } void kmain(multiboot_info_t *multiboot_info) { @@ -36,66 +125,43 @@ void kmain(multiboot_info_t *multiboot_info) { kprint_register(vga_kprint); serial_init(); kprint_register(serial_kprint); - if (multiboot_info->flags & (1 << 6)) { - kprint("mmap valid\n"); - init_mmap((struct multiboot_mmap_entry *) multiboot_info->mmap_addr, - multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry)); - } else { - kprint("mmap invalid!\n"); - panic(); - } -// vga_print_string(msg_booted, VGA_WHITE | (VGA_DARK_GRAY << VGA_SHIFT_BG)); + store_bootloader_info(multiboot_info); + init_mmap(multiboot_info); + kprint(msg_booted); - kprint((char *) multiboot_info->boot_loader_name); kprint(newline); -// multiboot_memory_map_t *fe = multiboot_info->mmap_addr; -// port_byte_out(0x3d4, 14); -// int pos = port_byte_in(0x3d5); -// pos <<= 8; -// -// port_byte_out(0x3d4, 15); -// pos += port_byte_in(0x3d5); - asm volatile("sti"); + // init done, enable interrupts + __asm__ __volatile__("sti"); + // init timer for future task switching init_timer(50); + // setup PS/2 keyboard init_keyboard(); -// print_mmap_info(); + // enter main loop while (true) { main_loop(); } - -// vga_set_raw(pos * 2, 'X'); -// vga_set_raw(pos * 2 + 1, 0xf); - do {} while (1); } void main_loop() { char *msg = readline(NULL); char *args = strchr(msg, ' ') + 1; args[-1] = 0; - if (strcmp(cmd_echo, msg) == 0) { - kprint(args); - kprint(newline); - goto _main_loop_end; + int test_index = 0; + while (true) { + if (cmd_handlers[test_index].cmd == 0) { + kprint(msg_unknown_command); + kprint(msg); + kprint(newline); + break; + } + if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) { + cmd_handlers[test_index].handler(args); + break; + } + test_index++; } - if (strcmp(cmd_print_mmap, msg) == 0) { - print_mmap_info(); - goto _main_loop_end; - } - if (strcmp(cmd_print_malloc, msg) == 0) { - print_malloc_info(); - goto _main_loop_end; - } - if (strcmp(cmd_print_tick, msg) == 0) { - print_current_tick(); - goto _main_loop_end; - } - - kprint(msg_unknown_command); - kprint(msg); - kprint(newline); - _main_loop_end: free(msg); } \ No newline at end of file diff --git a/kernel/libc/libc.c b/kernel/libc/libc.c index 44f3bb8..869e74f 100644 --- a/kernel/libc/libc.c +++ b/kernel/libc/libc.c @@ -88,3 +88,10 @@ int maxi(int a, int b) { } return b; } + +int mini(int a, int b) { + if (a <= b) { + return a; + } + return b; +} diff --git a/kernel/libc/libc.h b/kernel/libc/libc.h index d5a3e7c..bdf9128 100644 --- a/kernel/libc/libc.h +++ b/kernel/libc/libc.h @@ -18,4 +18,6 @@ int abs(int val); int maxi(int a, int b); +int mini(int a, int b); + #endif /* KERNEL_LIBC_LIBC_H_ */ diff --git a/kernel/libk.c b/kernel/libk.c new file mode 100644 index 0000000..66f6191 --- /dev/null +++ b/kernel/libk.c @@ -0,0 +1,16 @@ +// +// Created by rick on 02-02-21. +// + +#include "libk.h" +#include "kprint.h" + +void k_wait_for_interrupt() { + __asm__ __volatile__("hlt;"); +} + +void k_panic() { + kprint("PANIC!"); + __asm__ __volatile__("cli;" + "hlt;"); +} diff --git a/kernel/libk.h b/kernel/libk.h new file mode 100644 index 0000000..f78d12f --- /dev/null +++ b/kernel/libk.h @@ -0,0 +1,12 @@ +// +// Created by rick on 02-02-21. +// + +#ifndef NEW_KERNEL_LIBK_H +#define NEW_KERNEL_LIBK_H + +void k_wait_for_interrupt(); + +void k_panic(); + +#endif //NEW_KERNEL_LIBK_H diff --git a/kernel/mem/mem.c b/kernel/mem/mem.c index d21f37d..6c6e385 100644 --- a/kernel/mem/mem.c +++ b/kernel/mem/mem.c @@ -107,7 +107,7 @@ void use_mmap_entry(struct multiboot_mmap_entry *entry) { } } -void init_mmap(struct multiboot_mmap_entry *entries, u32 count) { +void init_mmap_multiboot(struct multiboot_mmap_entry *entries, u32 count) { for (u32 i = 0; i < count; ++i) { use_mmap_entry(&entries[i]); } diff --git a/kernel/mem/mem.h b/kernel/mem/mem.h index 8ff0825..d7be42f 100644 --- a/kernel/mem/mem.h +++ b/kernel/mem/mem.h @@ -7,7 +7,7 @@ #include -void init_mmap(struct multiboot_mmap_entry *entries, u32 count); +void init_mmap_multiboot(struct multiboot_mmap_entry *entries, u32 count); void print_malloc_info(); diff --git a/qemu-debug.sh b/qemu-debug.sh index a198355..7bb6299 100755 --- a/qemu-debug.sh +++ b/qemu-debug.sh @@ -1,3 +1,3 @@ #!/bin/bash -nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -d guest_errors,int -m 1G > /dev/null & +nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -hda tmp.img -d guest_errors,int -m 1G > /dev/null & disown