diff --git a/common/acpi.c b/common/acpi.c index 958da5a6..d4f19de7 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -752,4 +752,8 @@ void acpi_power_off(void) { AcpiEnterSleepState(ACPI_STATE_S5); panic("Power Off"); } + +void acpi_reboot(void) { + AcpiReset(); +} #endif /* KTF_ACPICA */ diff --git a/common/cmdline.c b/common/cmdline.c index dc7da9c5..9732ad96 100644 --- a/common/cmdline.c +++ b/common/cmdline.c @@ -73,6 +73,9 @@ string_cmd("com4", opt_com4); bool opt_fb_scroll = true; bool_cmd("fb_scroll", opt_fb_scroll); +unsigned long opt_reboot_timeout = 0; /* Disabled by default */ +ulong_cmd("reboot_timeout", opt_reboot_timeout); + const char *kernel_cmdline; void __text_init cmdline_parse(const char *cmdline) { diff --git a/common/kernel.c b/common/kernel.c index 3ab05eb6..873a1aa5 100644 --- a/common/kernel.c +++ b/common/kernel.c @@ -31,14 +31,34 @@ #include #include #include +#include #ifdef KTF_PMU #include #endif +void reboot(void) { + printk("Rebooting...\n"); + io_delay(); + +#ifdef KTF_ACPICA + acpi_reboot(); +#endif + keyboard_reboot(); + hard_reboot(); +} + static void __noreturn echo_loop(void) { + time_t reboot_timeout = opt_reboot_timeout * 1000; /* ms */ + time_t start_time = get_timer_ticks(); + while (1) { io_delay(); keyboard_process_keys(); + + if (reboot_timeout > 0) { + if (get_timer_ticks() - start_time >= reboot_timeout) + reboot(); + } } } diff --git a/drivers/keyboard.c b/drivers/keyboard.c index df9d2eca..8e6ddea0 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -61,12 +61,28 @@ struct keyboard_state { typedef struct keyboard_state keyboard_state_t; static keyboard_state_t keyboard_state; +static bool i8042_present = false; + +void keyboard_reboot(void) { + if (!i8042_present) + return; + + cli(); + + while ((inb(KEYBOARD_PORT_CMD) & KEYBOARD_STATUS_IN_FULL) != 0) + cpu_relax(); + + outb(KEYBOARD_PORT_CMD, KEYBOARD_RESET_CMD); + halt(); +} void init_keyboard(const cpu_t *cpu) { if (!boot_flags.i8042) { dprintk("No i8042 microcontroller detected\n"); + i8042_present = false; return; } + i8042_present = true; printk("Initializing keyboard driver\n"); @@ -182,6 +198,9 @@ unsigned int keyboard_process_keys(void) { unsigned n = 0; unsigned char key, scan; + if (!i8042_present) + return n; + while (keyboard_state.curr != keyboard_state.init) { scan = keyboard_state.buf[keyboard_state.init]; @@ -192,6 +211,10 @@ unsigned int keyboard_process_keys(void) { if (keyboard_state.shift) vga_scroll_up(); break; + case SCAN_DEL: + if (keyboard_state.alt && keyboard_state.ctrl) + reboot(); + break; case SCAN_PAGEDOWN: if (keyboard_state.shift) vga_scroll_down(); @@ -211,6 +234,11 @@ unsigned int keyboard_process_keys(void) { void keyboard_interrupt_handler(void) { unsigned char status; + if (!i8042_present) { + apic_EOI(); + return; + } + status = inb(KEYBOARD_PORT_CMD); if (status & KEYBOARD_STATUS_OUT_FULL) { char scan = inb(KEYBOARD_PORT_DATA); diff --git a/drivers/serial.c b/drivers/serial.c index 31cf0f28..2ccd8b68 100644 --- a/drivers/serial.c +++ b/drivers/serial.c @@ -221,6 +221,19 @@ int serial_write(io_port_t port, const char *buf, size_t len) { return rc; } +#define NUM_PLUS 3 +static inline void uart_reboot(char c) { + static uint8_t break_cmd = NUM_PLUS; + + if (c != '+') { + break_cmd = NUM_PLUS; + return; + } + + if (--break_cmd == 0) + reboot(); +} + void uart_interrupt_handler(void) { for (unsigned int i = 0; i < ARRAY_SIZE(com_ports); ++i) { com_port_t com_port = com_ports[i]; @@ -238,6 +251,7 @@ void uart_interrupt_handler(void) { input_state.curr = (input_state.curr + 1) % sizeof(input_state.buf); printk("%c", input); + uart_reboot(input); } } diff --git a/include/acpi_ktf.h b/include/acpi_ktf.h index 44ece47c..12988bd9 100644 --- a/include/acpi_ktf.h +++ b/include/acpi_ktf.h @@ -295,6 +295,7 @@ extern void acpi_walk_subtables(ACPI_SUBTABLE_HEADER *entry, uint32_t length, extern ACPI_STATUS init_acpi(void); extern void acpi_power_off(void); +extern void acpi_reboot(void); #endif /* KTF_ACPICA */ #endif /* KTF_ACPI_H */ diff --git a/include/cmdline.h b/include/cmdline.h index aa6a5188..56b2c107 100644 --- a/include/cmdline.h +++ b/include/cmdline.h @@ -68,6 +68,7 @@ extern bool opt_fpu; extern bool opt_qemu_console; extern bool opt_poweroff; extern bool opt_fb_scroll; +extern unsigned long opt_reboot_timeout; extern const char *kernel_cmdline; diff --git a/include/drivers/keyboard.h b/include/drivers/keyboard.h index 18eda214..a13ece11 100644 --- a/include/drivers/keyboard.h +++ b/include/drivers/keyboard.h @@ -33,13 +33,18 @@ #define KEYBOARD_PORT1_IRQ 0x01 #define KEYBOARD_PORT2_IRQ 0x04 /* Second port */ -#define KEYBOARD_PORT1_IRQ_OFFSET \ - (PIC_IRQ0_OFFSET + KEYBOARD_PORT1_IRQ) /* keyboard first channel irq offset */ +/* keyboard first channel irq offset */ +#define KEYBOARD_PORT1_IRQ_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_PORT1_IRQ) #define KEYBOARD_PORT1_IRQ_VECTOR KEYBOARD_PORT1_IRQ_OFFSET #define KEYBOARD_PORT2_IRQ_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_PORT2_IRQ) #define KEYBOARD_PORT2_IRQ_VECTOR KEYBOARD_PORT2_IRQ_OFFSET -#define KEYBOARD_STATUS_OUT_FULL 0x01 /* bit set when the keyboard buffer is full */ +/* bit set when the keyboard output buffer is full */ +#define KEYBOARD_STATUS_OUT_FULL 0x01 +/* bit set when the keyboard input buffer is full */ +#define KEYBOARD_STATUS_IN_FULL 0x02 + +#define KEYBOARD_RESET_CMD 0xFE typedef enum { KEYBOARD_CMD_WRITE_CONFIGURATION = 0x60, /* Write configuration byte */ @@ -117,6 +122,7 @@ typedef enum scan_code scan_code_t; /* External Declarations */ +extern void keyboard_reboot(void); extern void init_keyboard(const cpu_t *cpu); extern void keyboard_interrupt_handler(void); extern unsigned int keyboard_process_keys(void); diff --git a/include/ktf.h b/include/ktf.h index fa651b93..77347c92 100644 --- a/include/ktf.h +++ b/include/ktf.h @@ -40,6 +40,7 @@ typedef uint16_t io_port_t; extern bool opt_debug; +extern void reboot(void); extern void kernel_main(void) __noreturn; extern unsigned long test_main(void *unused); diff --git a/include/lib.h b/include/lib.h index a4f08ecd..172f17e1 100644 --- a/include/lib.h +++ b/include/lib.h @@ -167,6 +167,10 @@ static inline void hlt(void) { asm volatile("hlt"); } +static inline void int3(void) { + asm volatile("int3"); +} + static inline unsigned long read_flags(void) { unsigned long flags; @@ -469,6 +473,7 @@ static inline void enable_fpu(void) { /* External declarations */ extern void halt(void); +extern void hard_reboot(void); extern void srand(unsigned s); diff --git a/lib/lib.c b/lib/lib.c index 6e63cdc5..8ed0a77b 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -36,6 +36,17 @@ void __noreturn halt(void) { } } +/* Trigger Triple Fault */ +void __noreturn hard_reboot(void) { + idt_ptr_t idt_ptr = {0}; + + cli(); + lidt(&idt_ptr); + int3(); + + halt(); +} + static uint64_t seed; void srand(unsigned s) {