feature: functional shell with help and merdella commands

TOOD: reboot, poweroff, echo, color
This commit is contained in:
0x35c 2024-09-10 20:03:33 +02:00
parent 232b19666a
commit 15bdb4743a
8 changed files with 232 additions and 19 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ build
obj
.*
compile_commands.json
tags

View File

@ -1,5 +1,7 @@
#pragma once
#include <stdint.h>
static const char *keymap[128] = {
[2] = "1!", [3] = "2@", [4] = "3#", [5] = "4$", [6] = "5%",
[7] = "6^", [8] = "7&", [9] = "8*", [10] = "9(", [11] = "0)",
@ -93,6 +95,11 @@ static const char *keymap[128] = {
#define KEY_RIGHT 0x4D
#define KEY_SPACE 0x39
#define KEY_UP 0x48
#define KET_LEFT_SHIFT 0x2A
#define KEY_LEFT_SHIFT 0x2A
#define KEY_RIGHT_SHIFT 0x36
#define KEY_CAPSLOCK 0x3A
struct key_event {
uint8_t c;
uint8_t scan_code;
};

49
headers/shell.h Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#define PROMPT "> "
static const char *POOP =
" / ____/ / _ \\\n"
" _/ ___/_ / / \\___ \\_\n"
" / _/'-, `---._ / / \\_ \\\n"
" / ______/(0} `, , ` , ) / / \\_ \\\n"
" / V ; ` , ` ( / / ,'~~~~~~`, \\\n"
" | `.____,- ' (, ` , ) / / :`,-'\"\"`. \"; "
"|\n"
" | `-------._); , ` `, / / \\;: )``: |\n"
" / / ) ) ; ` ,, : / / `` : '; "
"\\\n"
"/ / ( (`;: ; ` ;:\\ / / ;;;, "
"\\\n"
"| / (: )``;:;;)`'`'`--./ / ____ _,-';;` "
"|\n"
"| | :` )`;)`)`' : / / ~~~~~ ~~~`--',.;;;| "
"|\n"
"| | `--;~~~~~ ` / /, \" \" \"` \",, \\ ;`` | "
" |\n"
"| | ( ; , / / ; `; ; | "
"|\n"
"| | (; ; ; ` / / ,` ` : | "
"><\n"
"| | (; / / / ` ; ; : |\n"
"| \\ ;(_; ; : / /` ; ; ,,,\"\"\";} `; / "
"><\n"
"\\ \\ : `; `; ` / /,;,'''' );;`); ; / >< "
" ><\n"
" \\ | ;' :; ;/ / (;` :( ; , ; | "
"><\n"
" | | |, `;; ,/ / `)`; `(; ` `; | "
"(`\\\n"
" | \\ ; ;; ``: / `).:` \\;, `. / _> "
")_\n"
" \\ \\_ ,-' ;`;;:;` / ;;'`;; `) )/ ,-' "
",-. `;\n"
" \\ \\_ ~~~,-`;`;,\" / ~~~~~ ,-' ; "
"`\"\"/ /\"\"\n"
" \\_ \\___\"\"\"/\"\" / `\"\"/\"\" "
"\n";
typedef enum { HELP, REBOOT, POWEROFF, ECHO, COLOR, MERDELLA, ERROR } CMD_TOK;
void reboot(void);
void shell_init(void);

View File

@ -1,5 +1,6 @@
#pragma once
#include "keyboard.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -14,6 +15,7 @@ struct screen {
size_t column;
uint8_t color;
uint16_t buffer[VGA_WIDTH * VGA_HEIGHT];
char line[256];
};
enum vga_color {
@ -35,13 +37,16 @@ enum vga_color {
VGA_COLOR_WHITE = 15,
};
enum cursor_direction { LEFT, RIGHT, UP, DOWN };
void terminal_initialize(void);
void terminal_setcolor(uint8_t color);
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y);
int terminal_putchar(char c);
int terminal_write(const char *data, size_t size);
int terminal_writestring(const char *data);
int terminal_writelong(long number);
void terminal_set_screen(int pos);
uint8_t terminal_getkey(void);
struct key_event terminal_getkey(void);
void update_cursor(void);
void move_cursor(int direction);
struct screen *get_screen(void);

View File

@ -1,4 +1,5 @@
#include "kprintf.h"
#include "gdt.h"
#include "shell.h"
#include "terminal.h"
#include <stdbool.h>
@ -21,11 +22,6 @@ void kernel_main(void)
/* Initialize terminal interface */
terminal_initialize();
/* Newline support is left as an exercise. */
for (int i = 100; i; i--)
kprintf(0, "%d\n", i);
void initGdt();
kprintf(0, "mange ta mere avec ton argument a kprintf fdp\n");
while (true)
terminal_getkey();
/* initGdt(); */
shell_init();
}

View File

@ -0,0 +1,111 @@
#include "kprintf.h"
#include "shell.h"
#include "string.h"
#include "terminal.h"
extern struct screen *screen;
static CMD_TOK find_command(char *line)
{
size_t i = 0;
bool uwu = false;
CMD_TOK command = ERROR;
if (!line[0])
return command;
while (line[i]) {
if (line[i] == ' ') {
uwu = true;
break;
}
i++;
}
line[i] = '\0';
if (!strcmp(line, "help"))
command = HELP;
else if (!strcmp(line, "reboot"))
command = REBOOT;
else if (!strcmp(line, "poweroff"))
command = POWEROFF;
else if (!strcmp(line, "echo"))
command = ECHO;
else if (!strcmp(line, "color"))
command = COLOR;
else if (!strcmp(line, "merdella"))
command = MERDELLA;
else
kprintf(0, "invalid command: %s\n", line);
if (uwu)
line[i] = ' ';
return command;
}
static void read_line(char *buf, size_t size)
{
size_t i = 0;
struct key_event ev;
uint8_t prev_scan_code = 0;
while (1) {
ev = terminal_getkey();
if (ev.c == '\n')
break;
if (prev_scan_code != ev.scan_code && ev.scan_code) {
if (ev.scan_code == KEY_BACKSPACE && i) {
buf[--i] = '\0';
move_cursor(LEFT);
terminal_putchar(' ');
move_cursor(LEFT);
}
if (ev.c && i < size - 1) {
kprintf(0, "%c", ev.c);
buf[i++] = ev.c;
}
if (i >= size)
break;
}
prev_scan_code = ev.scan_code;
}
kprintf(0, "\n");
buf[i] = '\0';
}
void shell_init(void)
{
while (1) {
kprintf(0, PROMPT);
read_line(screen->line, sizeof(screen->line));
switch (find_command(screen->line)) {
case HELP:
kprintf(0, "Welcome to bozOShell, the shell of "
"bozOS\nAvailable commands: help, reboot, "
"poweroff, echo, color, merdella\n");
break;
case REBOOT:
kprintf(0, "rebooting\n");
break;
case POWEROFF:
kprintf(0, "powering off\n");
break;
case ECHO:
kprintf(0, "echoing\n");
break;
case COLOR:
kprintf(0, "coloring\n");
break;
case MERDELLA: {
kprintf(0, POOP);
if (!strcmp("--credits", strchr(screen->line, ' ') + 1))
kprintf(
0,
"\nThis ascii masterpiece has been created "
"by Targon (/)\n");
break;
}
case ERROR:
break;
default:
break;
}
}
}

View File

@ -1,31 +1,32 @@
#include <stdbool.h>
#include "keyboard.h"
#include "kprintf.h"
#include "sys/io.h"
#include "terminal.h"
uint8_t terminal_getkey(void)
struct key_event terminal_getkey(void)
{
static bool caps_mode = false;
static uint8_t prev_scan_code = 0;
struct key_event ev = {0};
uint8_t scan_code;
scan_code = inb(KEYBOARD_PORT);
if (scan_code == 0x3A || scan_code == 0x58) {
caps_mode = !caps_mode;
outb(0xED, (caps_mode << 2)); // turn on/off capslock led
}
else if (scan_code == KEY_RIGHT_SHIFT || scan_code == KET_LEFT_SHIFT)
} else if (scan_code == KEY_RIGHT_SHIFT || scan_code == KEY_LEFT_SHIFT)
caps_mode = true;
else if (scan_code == KEY_RIGHT_SHIFT + 128 || scan_code == KET_LEFT_SHIFT + 128)
else if (scan_code == KEY_RIGHT_SHIFT + 128 ||
scan_code == KEY_LEFT_SHIFT + 128)
caps_mode = false;
else if (scan_code != prev_scan_code && prev_scan_code != 0) {
if (scan_code < 128 && keymap[scan_code])
kprintf(0, "%c", keymap[scan_code][caps_mode]);
ev.c = keymap[scan_code][caps_mode];
if (scan_code >= KEY_F1 && scan_code <= KEY_F10)
terminal_set_screen(scan_code - KEY_F1);
}
prev_scan_code = scan_code;
return scan_code;
ev.scan_code = scan_code;
return ev;
}

View File

@ -129,3 +129,46 @@ void update_cursor(void)
outb(0x3D4, 0x0E);
outb(0x3D5, (pos >> 8) & 0xFF);
}
void move_cursor(int direction)
{
switch (direction) {
case LEFT:
if (screen->column) {
screen->column--;
} else if (screen->row) {
screen->column = VGA_WIDTH - 1;
screen->row--;
}
break;
case RIGHT:
if (screen->column < VGA_WIDTH - 1) {
screen->column++;
} else if (screen->row < VGA_HEIGHT - 1) {
screen->column = 0;
screen->row++;
} else {
terminal_new_line();
}
break;
case UP:
break;
case DOWN:
break;
default:
break;
}
uint16_t pos = screen->row * VGA_WIDTH + screen->column;
outb(0x3D4, 0x0F);
outb(0x3D5, pos & 0xFF);
outb(0x3D4, 0x0E);
outb(0x3D5, (pos >> 8) & 0xFF);
}
struct screen *get_screen(void)
{
return screen;
}