:: commit a9b31d6bfde3646f1ab8befe1cc4f58068bb0cbc

mintsuki <mintsuki@protonmail.com> — 2020-01-25 02:06

parents: 2f4311b2c0

Add command line editor

diff --git a/src/drivers/vga_textmode.c b/src/drivers/vga_textmode.c
index e0bcc861..8ac334c6 100644
--- a/src/drivers/vga_textmode.c
+++ b/src/drivers/vga_textmode.c
@@ -146,6 +146,9 @@ static void text_putchar(char c) {
                 text_set_cursor_pos(0, (text_get_cursor_pos_y() + 1));
             }
             break;
+        case '\r':
+            text_set_cursor_pos(0, text_get_cursor_pos_y());
+            break;
         case 0x08:
             if (cursor_offset) {
                 clear_cursor();
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 701528e5..75b2fe32 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -5,6 +5,7 @@
 #include <drivers/vga_textmode.h>
 #include <lib/real.h>
 #include <sys/interrupt.h>
+#include <lib/libc.h>
 
 void pit_sleep(uint64_t pit_ticks) {
     uint64_t target = global_pit_tick + pit_ticks;
@@ -13,6 +14,18 @@ void pit_sleep(uint64_t pit_ticks) {
     }
 }
 
+int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks) {
+    uint64_t target = global_pit_tick + pit_ticks;
+    while (global_pit_tick < target && !kbd_int) {
+        asm volatile ("hlt");
+    }
+    if (kbd_int) {
+        kbd_int = 0;
+        return 1;
+    }
+    return 0;
+}
+
 uint64_t strtoui(const char *s) {
     uint64_t n = 0;
     while (*s)
@@ -26,8 +39,11 @@ char getchar(void) {
     return (char)(r.eax & 0xff);
 }
 
-void gets(char *buf, size_t limit) {
-    for (size_t i = 0; ; ) {
+void gets(const char *orig_str, char *buf, size_t limit) {
+    size_t orig_str_len = strlen(orig_str);
+    memmove(buf, orig_str, orig_str_len);
+    text_write(orig_str, orig_str_len);
+    for (size_t i = orig_str_len; ; ) {
         char c = getchar();
         switch (c) {
             case '\b':
diff --git a/src/lib/blib.h b/src/lib/blib.h
index aa1a8bd9..146b406a 100644
--- a/src/lib/blib.h
+++ b/src/lib/blib.h
@@ -5,10 +5,11 @@
 #include <stdint.h>
 
 void pit_sleep(uint64_t pit_ticks);
+int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks);
 
 void print(const char *fmt, ...);
 char getchar(void);
-void gets(char *buf, size_t limit);
+void gets(const char *orig_str, char *buf, size_t limit);
 uint64_t strtoui(const char *s);
 
 #define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
diff --git a/src/main.c b/src/main.c
index c857e0c1..e83c90d0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -67,6 +67,16 @@ void main(int boot_drive) {
         for (;;);
     }
 
+    print("\n");
+    for (int i = 3; i; i--) {
+        print("\rBooting in %d (press any key to edit command line)...", i);
+        if (pit_sleep_and_quit_on_keypress(18)) {
+            print("\n\n> ");
+            gets(cmdline, cmdline, 128);
+            break;
+        }
+    }
+
     load_echfs_file(drive, part, (void *)0x100000, path);
 
     // Boot the kernel.
diff --git a/src/sys/interrupt.c b/src/sys/interrupt.c
index 15328a4b..2362c9a7 100644
--- a/src/sys/interrupt.c
+++ b/src/sys/interrupt.c
@@ -4,19 +4,28 @@
 #include <lib/cio.h>
 #include <lib/blib.h>
 
-volatile uint64_t global_pit_tick = 0;
-
 __attribute__((interrupt)) static void unhandled_int(void *r) {
     (void)r;
     print("Warning: unhandled interrupt");
 }
 
+volatile uint64_t global_pit_tick = 0;
+
 __attribute__((interrupt)) static void pit_irq(void *r) {
     (void)r;
     global_pit_tick++;
     port_out_b(0x20, 0x20);
 }
 
+volatile int kbd_int = 0;
+
+__attribute__((interrupt)) static void keyboard_handler(void *r) {
+    (void)r;
+    kbd_int = 1;
+    (void)port_in_b(0x60);
+    port_out_b(0x20, 0x20);
+}
+
 uint8_t rm_pic0_mask = 0xff;
 uint8_t rm_pic1_mask = 0xff;
 uint8_t pm_pic0_mask = 0xff;
@@ -48,6 +57,7 @@ void init_idt(void) {
     }
 
     register_interrupt_handler(0x08, pit_irq, 0x8e);
+    register_interrupt_handler(0x09, keyboard_handler, 0x8e);
 
     struct idt_ptr_t idt_ptr = {
         sizeof(idt) - 1,
@@ -60,7 +70,7 @@ void init_idt(void) {
         : "m" (idt_ptr)
     );
 
-    pm_pic0_mask = 0xfe;
+    pm_pic0_mask = 0xfc;
     pm_pic1_mask = 0xff;
     port_out_b(0x21, pm_pic0_mask);
     port_out_b(0xa1, pm_pic1_mask);
diff --git a/src/sys/interrupt.h b/src/sys/interrupt.h
index 87966708..d22e5bd7 100644
--- a/src/sys/interrupt.h
+++ b/src/sys/interrupt.h
@@ -5,6 +5,7 @@
 #include <stddef.h>
 
 extern volatile uint64_t global_pit_tick;
+extern volatile int kbd_int;
 
 extern uint8_t rm_pic0_mask;
 extern uint8_t rm_pic1_mask;
tab: 248 wrap: offon