summaryrefslogtreecommitdiff
path: root/stage3/shell.c
diff options
context:
space:
mode:
authorLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-19 01:54:39 +0100
committerLizzy Fleckenstein <lizzy@vlhl.dev>2023-12-19 02:11:32 +0100
commit6d263c7d4e0f4b1d34694b5d3d159ccb20b3db02 (patch)
tree41578268cf68b2d9ea1737687a0f98af979948d8 /stage3/shell.c
parent5881b4d5c1040c762599f90e091e4cc4c3abe6b1 (diff)
downloadcuddles-6d263c7d4e0f4b1d34694b5d3d159ccb20b3db02.tar.xz
keyboard driver and threads
* PS/2 keyboard driver * interactive shell * move away from \0 terminated strings to sized slices * coroutine threads and IRQ queues
Diffstat (limited to 'stage3/shell.c')
-rw-r--r--stage3/shell.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/stage3/shell.c b/stage3/shell.c
new file mode 100644
index 0000000..f8d5ada
--- /dev/null
+++ b/stage3/shell.c
@@ -0,0 +1,172 @@
+#include "shell.h"
+#include "font.h"
+#include "heap.h"
+#include "fs.h"
+#include "gfx.h"
+#include "string.h"
+#include "pci.h"
+#include "memory.h"
+
+static void cmd_echo(str arg)
+{
+ print(arg);
+ print_char('\n');
+}
+
+static void cmd_cat(str arg)
+{
+ str f = fs_read(arg);
+
+ if (f.data == nil) {
+ print(S("cat: file not found: "));
+ print(arg);
+ print(S("\n"));
+ } else {
+ print(f);
+ free(f.data);
+ }
+}
+
+static void cmd_font(str arg)
+{
+ str f = fs_read(arg);
+
+ if (f.data == nil) {
+ print(S("font: file not found: "));
+ print(arg);
+ print(S("\n"));
+ } else {
+ if (f.len == 16*256)
+ font_load_blob(f.data);
+ else
+ print(S("font: invalid file size\n"));
+
+ free(f.data);
+ }
+}
+
+static void cmd_fontdemo()
+{
+ const u8 max = '~' - '!' + 1;
+ char buf[max];
+
+ for (u8 i = 0; i < max; i++)
+ buf[i] = i + '!';
+
+ print(S("fontdemo:\n"));
+ print((str) { max, buf });
+ print(S("\n"));
+}
+
+static void cmd_img(str arg)
+{
+ str f = fs_read(arg);
+
+ if (f.data == nil) {
+ print(S("img: file not found: "));
+ print(arg);
+ print(S("\n"));
+ } else {
+ if (f.len < 2 * sizeof(u32))
+ print(S("img: missing header\n"));
+ else {
+ u32 width = ((u32 *) f.data)[0];
+ u32 height = ((u32 *) f.data)[1];
+
+ if (f.len != 2 * sizeof(u32) + width * height * sizeof(color))
+ print(S("img: invalid file size\n"));
+ else
+ gfx_draw_img(gfx_info->width-width, 0, width, height,
+ (void *) (f.data + 2 * sizeof(u32)));
+ }
+
+ free(f.data);
+ }
+}
+
+static void cmd_lspci(str arg)
+{
+ (void) arg;
+ pci_enumerate();
+}
+
+static void cmd_run(str arg)
+{
+ shell_run_file(arg);
+}
+
+extern char keymap[256];
+
+static void cmd_loadkeys(str arg)
+{
+ str f = fs_read(arg);
+
+ if (f.data == nil) {
+ print(S("loadkeys: file not found: "));
+ print(arg);
+ print(S("\n"));
+ } else {
+ if (f.len == 256)
+ memcpy(keymap, f.data, 256);
+ else
+ print(S("loadkeys: invalid file size\n"));
+
+ free(f.data);
+ }
+}
+
+typedef struct {
+ str name;
+ void (*fn)(str arg);
+} command;
+
+static command registry[] = {
+ { S("echo"), &cmd_echo },
+ { S("cat"), &cmd_cat },
+ { S("font"), &cmd_font },
+ { S("fontdemo"), &cmd_fontdemo },
+ { S("img"), &cmd_img },
+ { S("lspci"), &cmd_lspci },
+ { S("run"), &cmd_run },
+ { S("loadkeys"), &cmd_loadkeys },
+};
+
+void shell_run_cmd(str cmd)
+{
+ str prog = str_split_walk(&cmd, S(" \t"));
+
+ if (prog.len == 0)
+ return;
+
+ for (usize i = 0; i < sizeof registry / sizeof *registry; i++) {
+ if (str_cmp(prog, registry[i].name) == 0) {
+ registry[i].fn(cmd);
+ return;
+ }
+ }
+
+ print(S("shell: unknown command: "));
+ print(prog);
+ print(S("\n"));
+}
+
+void shell_run_file(str filename)
+{
+ str f = fs_read(filename);
+
+ if (f.data == nil) {
+ print(S("shell: file not found: "));
+ print(filename);
+ print(S("\n"));
+ } else {
+ str iter = f;
+ for (;;) {
+ str cmd = str_split_walk(&iter, S("\n"));
+ if (cmd.data == nil)
+ break;
+ shell_run_cmd(cmd);
+ }
+
+ free(f.data);
+ }
+}