From 2a82f0149318c520591c67512a2fdc2a3864065e Mon Sep 17 00:00:00 2001 From: Robbe Van Herck Date: Thu, 9 Jan 2020 18:32:12 +0100 Subject: [PATCH] Add minimal shell, find out that stuff is broken :'( --- README.md | 4 +- kernel/kernel.c | 4 +- kernel/shell.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/terminal.c | 1 + 4 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 kernel/shell.c diff --git a/README.md b/README.md index acd52fa..f6d55a0 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,11 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki. ### Features - [x] Terminal output (with newlines!) -- [x] _Very_ basic memory management +- [x] _Very_ basic (and probably broken) memory management - [x] Interrupt handling - [x] Keyboard input - [x] Exception handling +- [x] Minimal shell - [ ] Filesystem interaction - [ ] Show files in directory - [ ] Read files in directory @@ -37,5 +38,6 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki. - [ ] Tests - [ ] Running executables from filesystem - [ ] Better memory management +- [ ] Better shell As a test, I've implemented day 1 of [advent of code](https://adventofcode.com/) on the [AoC branch](https://github.com/Robbe7730/RoBoot/tree/AoC). diff --git a/kernel/kernel.c b/kernel/kernel.c index 60f50db..7fa4427 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -15,6 +15,7 @@ #include "terminal.c" #include "memory.c" #include "interrupts.c" +#include "shell.c" static inline bool are_interrupts_enabled() { unsigned long flags; @@ -61,7 +62,6 @@ void kernel_main(void) interrupt_init(); for(;;) { - char curr_char = getchar(); - terminal_putchar(curr_char); + shell_step(); } } \ No newline at end of file diff --git a/kernel/shell.c b/kernel/shell.c new file mode 100644 index 0000000..a404a8c --- /dev/null +++ b/kernel/shell.c @@ -0,0 +1,111 @@ +#ifndef SHELL_C +#define SHELL_C + +#define SHELL_CMD_BUFFER_SIZE 128 + +#include + +#include "terminal.c" +#include "drivers/keyboard/keyboard.c" + +char buffer[SHELL_CMD_BUFFER_SIZE]; +int buffer_idx = 0; + +int echo(char* input) { + terminal_writestring(input); + terminal_putchar('\n'); + return 0; +} + +int hello(char* unused) { + terminal_writestring("Hello, world!\n"); + return 0; +} + +int cls(char* unused) { + terminal_initialize(); + return 0; +} + +int ree(char* unused) { + terminal_initialize(); + terminal_putchar('R'); + for (int i = 1; i < VGA_WIDTH * VGA_HEIGHT; i++) { + terminal_putchar('e'); + } + return 0; +} + +int run_command(char* buffer) { + // TODO If I make these 2 global, it breaks... + // TODO This is ugly, fix this + const char* shell_commands_strings[] = { + "echo", + "hello", + "cls", + "ree", + NULL + }; + + int (*shell_commands_functions[]) (char*) = { + echo, + hello, + cls, + ree + }; + + if(buffer[0] == 0) { + return 0; + } + char command[SHELL_CMD_BUFFER_SIZE] = {0}; + int i = 0; + while (buffer[i] != 0 && buffer[i] != ' ') { + command[i] = buffer[i]; + i++; + } + + int command_idx = 0; + + while(shell_commands_strings[command_idx] != NULL) { + int check_idx = 0; + while(command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) { + check_idx++; + } + if (command[check_idx] == 0 && shell_commands_strings[command_idx][check_idx] == 0) { + return (shell_commands_functions[command_idx])(buffer + i + 1); + } + command_idx++; + } + return -1; +} + +void shell_step() { + char curr_char = getchar(); + + + if (curr_char == '\n') { + terminal_putchar(curr_char); + buffer[buffer_idx] = 0; + int result = run_command(buffer); + for (int i = 0; i < SHELL_CMD_BUFFER_SIZE; i++) { + buffer[i] = 0; + } + buffer_idx = 0; + + if (result == -1) { + terminal_writestring("No such command\n"); + } + } else if (curr_char == 0x08) { + if (buffer_idx != 0) { + buffer_idx--; + buffer[buffer_idx] = 0; + terminal_putchar(curr_char); + } + } else { + buffer[buffer_idx] = curr_char; + buffer_idx++; + terminal_putchar(curr_char); + } +} + +#endif //SHELL_C \ No newline at end of file diff --git a/kernel/terminal.c b/kernel/terminal.c index 40e51e3..5b9698a 100644 --- a/kernel/terminal.c +++ b/kernel/terminal.c @@ -77,6 +77,7 @@ void terminal_putchar(char c) { return; } if (c == 0x08) { + terminal_putentryat(' ', terminal_color, terminal_column, terminal_row); if (terminal_column == 0) { if(terminal_row != 0) { terminal_row--;