Add minimal shell, find out that stuff is broken :'(
This commit is contained in:
parent
41e3953d2c
commit
2a82f01493
4 changed files with 117 additions and 3 deletions
|
@ -26,10 +26,11 @@ The kernel is based on [the bare bones kernel from the OSDev wiki](https://wiki.
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- [x] Terminal output (with newlines!)
|
- [x] Terminal output (with newlines!)
|
||||||
- [x] _Very_ basic memory management
|
- [x] _Very_ basic (and probably broken) memory management
|
||||||
- [x] Interrupt handling
|
- [x] Interrupt handling
|
||||||
- [x] Keyboard input
|
- [x] Keyboard input
|
||||||
- [x] Exception handling
|
- [x] Exception handling
|
||||||
|
- [x] Minimal shell
|
||||||
- [ ] Filesystem interaction
|
- [ ] Filesystem interaction
|
||||||
- [ ] Show files in directory
|
- [ ] Show files in directory
|
||||||
- [ ] Read 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
|
- [ ] Tests
|
||||||
- [ ] Running executables from filesystem
|
- [ ] Running executables from filesystem
|
||||||
- [ ] Better memory management
|
- [ ] 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).
|
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).
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "terminal.c"
|
#include "terminal.c"
|
||||||
#include "memory.c"
|
#include "memory.c"
|
||||||
#include "interrupts.c"
|
#include "interrupts.c"
|
||||||
|
#include "shell.c"
|
||||||
|
|
||||||
static inline bool are_interrupts_enabled() {
|
static inline bool are_interrupts_enabled() {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -61,7 +62,6 @@ void kernel_main(void)
|
||||||
interrupt_init();
|
interrupt_init();
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
char curr_char = getchar();
|
shell_step();
|
||||||
terminal_putchar(curr_char);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
111
kernel/shell.c
Normal file
111
kernel/shell.c
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#ifndef SHELL_C
|
||||||
|
#define SHELL_C
|
||||||
|
|
||||||
|
#define SHELL_CMD_BUFFER_SIZE 128
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -77,6 +77,7 @@ void terminal_putchar(char c) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c == 0x08) {
|
if (c == 0x08) {
|
||||||
|
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
|
||||||
if (terminal_column == 0) {
|
if (terminal_column == 0) {
|
||||||
if(terminal_row != 0) {
|
if(terminal_row != 0) {
|
||||||
terminal_row--;
|
terminal_row--;
|
||||||
|
|
Loading…
Reference in a new issue