Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reboot functionality #306

Merged
merged 7 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions common/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,4 +752,8 @@ void acpi_power_off(void) {
AcpiEnterSleepState(ACPI_STATE_S5);
panic("Power Off");
}

void acpi_reboot(void) {
AcpiReset();
}
#endif /* KTF_ACPICA */
3 changes: 3 additions & 0 deletions common/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
20 changes: 20 additions & 0 deletions common/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,34 @@
#include <percpu.h>
#include <sched.h>
#include <setup.h>
#include <time.h>
#ifdef KTF_PMU
#include <perfmon/pfmlib.h>
#endif

void reboot(void) {
wipawel marked this conversation as resolved.
Show resolved Hide resolved
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();
}
}
}

Expand Down
28 changes: 28 additions & 0 deletions drivers/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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];

Expand All @@ -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();
Expand All @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions drivers/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
}
}

Expand Down
1 change: 1 addition & 0 deletions include/acpi_ktf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
1 change: 1 addition & 0 deletions include/cmdline.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 9 additions & 3 deletions include/drivers/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/ktf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
5 changes: 5 additions & 0 deletions include/lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);

Expand Down
11 changes: 11 additions & 0 deletions lib/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
wipawel marked this conversation as resolved.
Show resolved Hide resolved
}

static uint64_t seed;

void srand(unsigned s) {
Expand Down