From a9b31d6bfde3646f1ab8befe1cc4f58068bb0cbc Mon Sep 17 00:00:00 2001 From: mintsuki Date: Sat, 25 Jan 2020 03:06:56 +0100 Subject: [PATCH] Add command line editor --- src/drivers/vga_textmode.c | 3 +++ src/lib/blib.c | 20 ++++++++++++++++++-- src/lib/blib.h | 3 ++- src/main.c | 10 ++++++++++ src/sys/interrupt.c | 16 +++++++++++++--- src/sys/interrupt.h | 1 + 6 files changed, 47 insertions(+), 6 deletions(-) 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 #include #include +#include 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 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 #include -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 extern volatile uint64_t global_pit_tick; +extern volatile int kbd_int; extern uint8_t rm_pic0_mask; extern uint8_t rm_pic1_mask;