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;
