#include #include #include using namespace hilbert::kernel; struct [[gnu::packed]] exception_info_t { uint64_t rax; uint64_t rbx; uint64_t rcx; uint64_t rdx; uint64_t rdi; uint64_t rsi; uint64_t rbp; uint64_t rsp; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t cr2; uint64_t cr3; uint64_t rip; uint64_t rflags; uint64_t error; uint8_t has_error;//0 or 1 uint8_t exception_number; }; extern exception_info_t exception_info; static const char *exception_types[] = { "division error", "", "non-maskable interrupt", "", "", "", "invalid opcode", "", "double fault (uh oh)", "", "", "", "stack fault", "general protection fault", "page fault", "" }; static const char *flag_names[] = { " cf", "", " pf", "", " af", "", " zf", " sf", " tf", " if", " df", " of", "", "", " nt", " md" }; static void print_line(const char *r1, const char *r2, uint64_t r1v, uint64_t r2v) { terminal::put_string_sz("\n "); terminal::put_string_sz(r1); terminal::put_string_sz(": 0x"); terminal::put_int_hex(r1v, 16); terminal::put_string_sz(" "); terminal::put_string_sz(r2); terminal::put_string_sz(": 0x"); terminal::put_int_hex(r2v, 16); } extern "C" [[noreturn]] void print_exception() { terminal::put_string_sz("exception handler:\n type: "); terminal::put_string_sz(exception_types[exception_info.exception_number]); terminal::put_string_sz(" (0x"); terminal::put_int_hex(exception_info.exception_number, 2); terminal::put_char(')'); if (exception_info.has_error == 1) { terminal::put_string_sz("\n error code: 0x"); terminal::put_int_hex(exception_info.error, 16); } terminal::put_string_sz("\n flags:"); if (exception_info.rflags == 0) terminal::put_string_sz(" [none]"); else for (int i = 0; i < 16; ++i) if (((exception_info.rflags >> i) & 1) == 1) terminal::put_string_sz(flag_names[i]); if (exception_info.exception_number == 0x0e) { terminal::put_string_sz("\n cr2: 0x"); terminal::put_int_hex(exception_info.cr2, 16); } print_line("cr3", "rip", exception_info.cr3, exception_info.rip); print_line("rax", "rbx", exception_info.rax, exception_info.rbx); print_line("rcx", "rdx", exception_info.rcx, exception_info.rdx); print_line("rdi", "rsi", exception_info.rdi, exception_info.rsi); print_line("rbp", "rsp", exception_info.rbp, exception_info.rsp); print_line("r8 ", "r9 ", exception_info.r8 , exception_info.r9 ); print_line("r10", "r11", exception_info.r10, exception_info.r11); print_line("r12", "r13", exception_info.r12, exception_info.r13); print_line("r14", "r15", exception_info.r14, exception_info.r15); while (1) asm ("hlt"); } static uint32_t current_flags = 0; #define SETBIT(field, bit, cond) \ field = (cond) ? (field | (bit)) : (field & ~(bit)); static void got_key(uint32_t key) { input::key_queue->insert(current_flags | key); if (key == (input::BREAK | 0x77)) current_flags ^= input::NUM_LOCK; else if (key == (input::BREAK | 0x58)) current_flags ^= input::CAPS_LOCK; else if ((key & 0xff) == 0xa7) SETBIT(current_flags, input::RIGHT_WIN, !(key & input::BREAK)) else if ((key & 0xff) == 0x9f) SETBIT(current_flags, input::LEFT_WIN, !(key & input::BREAK)) else if ((key & 0xff) == 0x91) SETBIT(current_flags, input::RIGHT_ALT, !(key & input::BREAK)) else if ((key & 0xff) == 0x11) SETBIT(current_flags, input::LEFT_ALT, !(key & input::BREAK)) else if ((key & 0xff) == 0x94) SETBIT(current_flags, input::RIGHT_CTRL, !(key & input::BREAK)) else if ((key & 0xff) == 0x14) SETBIT(current_flags, input::LEFT_CTRL, !(key & input::BREAK)) else if ((key & 0xff) == 0x59) SETBIT(current_flags, input::RIGHT_SHIFT, !(key & input::BREAK)) else if ((key & 0xff) == 0x12) SETBIT(current_flags, input::LEFT_SHIFT, !(key & input::BREAK)) } static uint8_t key_so_far[8]; uint8_t key_so_far_len = 0; extern "C" void on_keyboard_interrupt(uint8_t byte) { key_so_far[key_so_far_len++] = byte; if (key_so_far_len == 1) { if (byte != 0xe0 && byte != 0xe1 && byte != 0xf0) { got_key(byte); key_so_far_len = 0; } } else if (key_so_far_len == 2) { if (key_so_far[0] == 0xe0 && byte != 0xf0 && byte != 0x12) { got_key(byte | 0x80); key_so_far_len = 0; } else if (key_so_far[0] == 0xf0) { got_key(input::BREAK | byte); key_so_far_len = 0; } } else if (key_so_far_len == 3) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 && byte != 0x7c) { got_key(input::BREAK | byte | 0x80); key_so_far_len = 0; } } else if (key_so_far_len == 4) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0x12 && key_so_far[2] == 0xe0 && byte == 0x7c) { got_key(0xe0); key_so_far_len = 0; } } else if (key_so_far_len == 6) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 && key_so_far[2] == 0x7c && key_so_far[3] == 0xe0 && key_so_far[4] == 0xf0 && byte == 0x12) { got_key(input::BREAK | 0xe0); key_so_far_len = 0; } } else if (key_so_far_len == 8) { if (key_so_far[0] == 0xe1 && key_so_far[1] == 0x14 && key_so_far[2] == 0x77 && key_so_far[3] == 0xe1 && key_so_far[2] == 0xf0 && key_so_far[3] == 0x14 && key_so_far[4] == 0xf0 && byte == 0x77) { got_key(0xe1); got_key(input::BREAK | 0xe1); } key_so_far_len = 0; } }