summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-01-27 23:14:29 -0500
committerBenji Dial <benji@benjidial.net>2024-01-27 23:14:29 -0500
commita8a80d326de9550b2a25b1255a2093ab43219ede (patch)
treed42a800f735caf93679d1728e2d5f20004db3b65 /kernel
parent7199e74aa22e592a3b77bdd81f735edca5470596 (diff)
downloadhilbert-os-a8a80d326de9550b2a25b1255a2093ab43219ede.tar.gz
keyboard input
Diffstat (limited to 'kernel')
-rw-r--r--kernel/entry.cpp19
-rw-r--r--kernel/include/hilbert/kernel/input.hpp26
-rw-r--r--kernel/include/hilbert/kernel/panic.hpp6
-rw-r--r--kernel/include/hilbert/kernel/utility.hpp50
-rw-r--r--kernel/include/hilbert/kernel/vfile.hpp8
-rw-r--r--kernel/input.cpp13
-rw-r--r--kernel/interrupts.asm96
-rw-r--r--kernel/interrupts.cpp111
-rw-r--r--kernel/panic.cpp10
-rw-r--r--kernel/syscall.cpp44
-rw-r--r--kernel/vfile.cpp12
11 files changed, 351 insertions, 44 deletions
diff --git a/kernel/entry.cpp b/kernel/entry.cpp
index 3a42df7..cc74e69 100644
--- a/kernel/entry.cpp
+++ b/kernel/entry.cpp
@@ -4,6 +4,8 @@
#include <hilbert/kernel/framebuffer.hpp>
#include <hilbert/kernel/terminal.hpp>
#include <hilbert/kernel/paging.hpp>
+#include <hilbert/kernel/input.hpp>
+#include <hilbert/kernel/panic.hpp>
#include <hilbert/kernel/vfile.hpp>
#include "../limine/limine.h"
@@ -184,12 +186,6 @@ extern "C" [[noreturn]] void entry() {
}
-[[noreturn]] static void print_and_halt(const char *msg) {
- terminal::put_string_sz(msg);
- while (1)
- asm ("hlt");
-}
-
extern "C" [[noreturn]] void start_user_mode(
uint64_t rip, uint64_t rsp, uint64_t p4_paddr);
@@ -208,22 +204,25 @@ extern "C" [[noreturn]] void start_user_mode(
if (initfs_fs->get_root_node(initfs_root.dir_entry.node) !=
storage::fs_result::success)
- print_and_halt("failed to get root node of initfs.");
+ panic("failed to get root node of initfs.");
vfile::set_root(initfs_root);
+ input::init_input();
+
utility::string init_path_string("/bin/init.elf", 13);
vfile::canon_path init_path;
vfile::canonize_path(init_path_string, init_path);
vfile::vfile init_file;
- if (vfile::lookup_path(init_path, init_file) != storage::fs_result::success)
- print_and_halt("failed to look up /bin/init.elf.");
+ if (vfile::lookup_path(init_path, init_file, true) !=
+ storage::fs_result::success)
+ panic("failed to look up /bin/init.elf.");
application::app_instance *init;
if (application::create_app(init_file, init, initfs_root) !=
application::create_app_result::success)
- print_and_halt("failed to parse /bin/init.elf.");
+ panic("failed to parse /bin/init.elf.");
application::running_app = init;
start_user_mode(init->saved_regs.rip, init->saved_regs.rsp, init->p4_paddr);
diff --git a/kernel/include/hilbert/kernel/input.hpp b/kernel/include/hilbert/kernel/input.hpp
new file mode 100644
index 0000000..cccb71f
--- /dev/null
+++ b/kernel/include/hilbert/kernel/input.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <hilbert/kernel/utility.hpp>
+
+namespace hilbert::kernel::input {
+
+ enum : uint32_t {
+ LEFT_SHIFT = 1 << 8,
+ RIGHT_SHIFT = 1 << 9,
+ LEFT_CTRL = 1 << 10,
+ RIGHT_CTRL = 1 << 11,
+ LEFT_ALT = 1 << 12,
+ RIGHT_ALT = 1 << 13,
+ LEFT_WIN = 1 << 14,
+ RIGHT_WIN = 1 << 15,
+ CAPS_LOCK = 1 << 16,
+ NUM_LOCK = 1 << 17,
+ BREAK = 1 << 18,
+ };
+
+ extern utility::queue<uint32_t> *key_queue;
+
+ //must be post switch to kernel page tables and mounting of file systems
+ void init_input();
+
+}
diff --git a/kernel/include/hilbert/kernel/panic.hpp b/kernel/include/hilbert/kernel/panic.hpp
new file mode 100644
index 0000000..545d703
--- /dev/null
+++ b/kernel/include/hilbert/kernel/panic.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+namespace hilbert::kernel {
+ //prints to terminal and then halts.
+ [[noreturn]] void panic(const char *string_sz);
+}
diff --git a/kernel/include/hilbert/kernel/utility.hpp b/kernel/include/hilbert/kernel/utility.hpp
index 2df1d65..47f78ea 100644
--- a/kernel/include/hilbert/kernel/utility.hpp
+++ b/kernel/include/hilbert/kernel/utility.hpp
@@ -294,4 +294,54 @@ namespace hilbert::kernel::utility {
};
+ template <class value_t>
+ struct queue {
+
+ value_t *buffer;
+ unsigned buffer_len;
+ unsigned count;
+ unsigned next_read_index;
+
+ queue(unsigned initial_len = 1024) : buffer(new value_t[initial_len]),
+ buffer_len(initial_len), count(0), next_read_index(0) { }
+
+ ~queue() {
+ delete[] buffer;
+ }
+
+ void insert(const value_t &v) {
+
+ if (count == buffer_len) {
+ value_t *new_buffer = new value_t[buffer_len * 2];
+ for (unsigned i = 0; i < buffer_len - next_read_index; ++i)
+ new_buffer[i] = move(buffer[i + next_read_index]);
+ for (unsigned i = buffer_len - next_read_index; i < buffer_len; ++i)
+ new_buffer[i] = move(buffer[i + next_read_index - buffer_len]);
+ delete[] buffer;
+ buffer = new_buffer;
+ buffer_len *= 2;
+ next_read_index = 0;
+ }
+
+ buffer[(count + next_read_index) % buffer_len] = v;
+ ++count;
+
+ }
+
+ //assumes not empty
+ const value_t &peek() const {
+ return buffer[next_read_index];
+ }
+
+ //assumes not empty
+ value_t &&take() {
+ value_t &&ret = move(buffer[next_read_index]);
+ if (++next_read_index == buffer_len)
+ next_read_index = 0;
+ --count;
+ return move(ret);
+ }
+
+ };
+
}
diff --git a/kernel/include/hilbert/kernel/vfile.hpp b/kernel/include/hilbert/kernel/vfile.hpp
index f8a387d..b64ae63 100644
--- a/kernel/include/hilbert/kernel/vfile.hpp
+++ b/kernel/include/hilbert/kernel/vfile.hpp
@@ -55,9 +55,9 @@ namespace hilbert::kernel::vfile {
//TODO: see comment at top of file.
void set_root(const vfile &root);
- //path must be absolute. follows symlinks on all but the last node.
- //relative_to should be a directory to do the lookup inside; e.g.,
- //if relative_to is /a/b and path is c, then out becomes /a/b/c.
- storage::fs_result lookup_path(const canon_path &path, vfile &out);
+ //path must be absolute. follows symlinks on all but the last node
+ //always, and on the last node when follow_final_symlink is true.
+ storage::fs_result lookup_path(
+ const canon_path &path, vfile &out, bool follow_final_symlink);
}
diff --git a/kernel/input.cpp b/kernel/input.cpp
new file mode 100644
index 0000000..6bed7f5
--- /dev/null
+++ b/kernel/input.cpp
@@ -0,0 +1,13 @@
+#include <hilbert/kernel/input.hpp>
+#include <hilbert/kernel/panic.hpp>
+#include <hilbert/kernel/vfile.hpp>
+
+namespace hilbert::kernel::input {
+
+ utility::queue<uint32_t> *key_queue;
+
+ void init_input() {
+ key_queue = new utility::queue<uint32_t>();
+ }
+
+}
diff --git a/kernel/interrupts.asm b/kernel/interrupts.asm
index 4827cfd..c096ddb 100644
--- a/kernel/interrupts.asm
+++ b/kernel/interrupts.asm
@@ -220,27 +220,111 @@ gdt:
.tss:
dq 0x0000e90000000067
dq 0;tss is 2 qwords wide
- dq 0x00209b0000000000
- dq 0x00009b0000000000
- dq 0x0000fb0000000000
- dq 0x0020fb0000000000
+ dq 0x002f98000000ffff
+ dq 0x002f92000000ffff
+ dq 0x002ff2000000ffff
+ dq 0x002ff8000000ffff
+
+section .bss
section .text
+write_keyboard_byte:
+ in al, 0x64
+ test al, 0x02
+ jnz write_keyboard_byte
+ mov al, dil
+ out 0x60, al
+ ret
+
+extern on_keyboard_interrupt
+
+keyboard_isr:
+
+ push r11
+ push r10
+ push r9
+ push r8
+ push rsi
+ push rdi
+ push rdx
+ push rcx
+ push rax
+
+ in al, 0x60
+ mov dil, al
+
+ call on_keyboard_interrupt
+
+ mov al, 0x20
+ out 0x20, al
+
+ pop rax
+ pop rcx
+ pop rdx
+ pop rdi
+ pop rsi
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+
+ iretq
+
load_gdt_and_idt:
+ ;fill exception entries in idt
+
mov rcx, 16
.loop:
mov rdi, rcx
dec rdi
- mov sil, 0
+ mov sil, 1
mov rdx, qword [exception_isrs + rdi * 8]
call set_isr
loop .loop
+ ;reset pic and map irqs to 0x20 - 0x2f
+
+ mov al, 0x11
+ out 0x20, al
+ mov al, 0x20
+ out 0x21, al
+ mov al, 0x04
+ out 0x21, al
+ mov al, 0x01
+ out 0x21, al
+ mov al, 0xfd ;mask all but irq 1
+ out 0x21, al
+
+ mov al, 0x11
+ out 0xa0, al
+ mov al, 0x28
+ out 0xa1, al
+ mov al, 0x02
+ out 0xa1, al
+ mov al, 0x01
+ out 0xa1, al
+ mov al, 0xff ;mask all
+ out 0xa1, al
+
+ mov rdi, 0x21
+ xor sil, sil
+ mov rdx, keyboard_isr
+ call set_isr
+
+ ;set keyboard config
+
+ mov al, 0x60
+ out 0x64, al
+ mov dil, 0x01
+ call write_keyboard_byte
+
+ ;make tss entry in gdt
+
mov rax, tss
mov word [gdt.tss + 2], ax
@@ -250,6 +334,8 @@ load_gdt_and_idt:
shr rax, 16
mov dword [gdt.tss + 8], eax
+ ;load gdt, idt, tss
+
lgdt [gdtr]
lidt [idtr]
mov ax, 0x18
diff --git a/kernel/interrupts.cpp b/kernel/interrupts.cpp
index 1a95f22..cd57c4f 100644
--- a/kernel/interrupts.cpp
+++ b/kernel/interrupts.cpp
@@ -1,4 +1,6 @@
#include <hilbert/kernel/terminal.hpp>
+#include <hilbert/kernel/input.hpp>
+#include <hilbert/kernel/panic.hpp>
using namespace hilbert::kernel;
@@ -34,7 +36,7 @@ struct [[gnu::packed]] exception_info_t {
extern exception_info_t exception_info;
-const char *exception_types[] = {
+static const char *exception_types[] = {
"division error",
"",
"non-maskable interrupt",
@@ -53,7 +55,7 @@ const char *exception_types[] = {
""
};
-const char *flag_names[] = {
+static const char *flag_names[] = {
" cf",
"",
" pf",
@@ -72,7 +74,7 @@ const char *flag_names[] = {
" md"
};
-void print_line(const char *r1, const char *r2, uint64_t r1v, uint64_t r2v) {
+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");
@@ -123,3 +125,106 @@ extern "C" [[noreturn]] void print_exception() {
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;
+ }
+
+}
diff --git a/kernel/panic.cpp b/kernel/panic.cpp
new file mode 100644
index 0000000..233fcf4
--- /dev/null
+++ b/kernel/panic.cpp
@@ -0,0 +1,10 @@
+#include <hilbert/kernel/terminal.hpp>
+#include <hilbert/kernel/panic.hpp>
+
+namespace hilbert::kernel {
+ [[noreturn]] void panic(const char *string_sz) {
+ terminal::put_string_sz(string_sz);
+ while (1)
+ asm ("hlt");
+ }
+}
diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp
index 3c72d23..e194eb1 100644
--- a/kernel/syscall.cpp
+++ b/kernel/syscall.cpp
@@ -1,6 +1,7 @@
#include <hilbert/kernel/application.hpp>
#include <hilbert/kernel/framebuffer.hpp>
#include <hilbert/kernel/paging.hpp>
+#include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/vfile.hpp>
namespace hilbert::kernel::syscall {
@@ -82,7 +83,7 @@ namespace hilbert::kernel::syscall {
set_zero(rax, rdi, rsi, rdx);
vfile::vfile file;
- switch (vfile::lookup_path(cp, file)) {
+ switch (vfile::lookup_path(cp, file, true)) {
case storage::fs_result::success:
break;
case storage::fs_result::device_error:
@@ -96,28 +97,13 @@ namespace hilbert::kernel::syscall {
return;
}
- vfile::vfile real_file;
- switch (file.follow_symlinks(real_file)) {
- case storage::fs_result::success:
- break;
- case storage::fs_result::device_error:
- rax = file_result_device_error;
- return;
- case storage::fs_result::fs_corrupt:
- rax = file_result_file_system_corrupt;
- return;
- case storage::fs_result::does_not_exist:
- rax = file_result_does_not_exist;
- return;
- }
-
- if (real_file.dir_entry.type != storage::file_type::regular_file) {
+ if (file.dir_entry.type != storage::file_type::regular_file) {
rax = file_result_directory;
return;
}
unsigned handler =
- application::running_app->open_files.add_new(utility::move(real_file));
+ application::running_app->open_files.add_new(utility::move(file));
rax = file_result_success;
rdi = (uint64_t)handler;
@@ -226,6 +212,23 @@ namespace hilbert::kernel::syscall {
}
+ void read_key_packet_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
+ ) {
+
+ set_zero(rax, rdi, rsi, rdx);
+
+ asm ("cli");
+
+ while (input::key_queue->count == 0)
+ asm ("sti\nhlt\ncli");
+
+ rax = (uint64_t)input::key_queue->take();
+
+ asm ("sti");
+
+ }
+
typedef void (*syscall_handler)(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx);
@@ -237,10 +240,11 @@ namespace hilbert::kernel::syscall {
&read_from_file_syscall,
&end_this_process_syscall,
&get_new_pages_syscall,
- &close_file_syscall
+ &close_file_syscall,
+ &read_key_packet_syscall
};
- static constexpr int max_syscall_number = 7;
+ static constexpr int max_syscall_number = 8;
}
diff --git a/kernel/vfile.cpp b/kernel/vfile.cpp
index 028db6d..89c95e6 100644
--- a/kernel/vfile.cpp
+++ b/kernel/vfile.cpp
@@ -94,7 +94,7 @@ namespace hilbert::kernel::vfile {
full_path.rel(target_path);
vfile next;
- RET_NOT_SUC(lookup_path(full_path, next))
+ RET_NOT_SUC(lookup_path(full_path, next, false))
next.path = path;
return next.follow_symlinks(out);
@@ -175,7 +175,9 @@ namespace hilbert::kernel::vfile {
kernel::vfile::root = new vfile(root);
}
- storage::fs_result lookup_path(const canon_path &path, vfile &out) {
+ storage::fs_result lookup_path(
+ const canon_path &path, vfile &out, bool follow_final_symlink
+ ) {
//assume path is absolute.
@@ -191,6 +193,12 @@ namespace hilbert::kernel::vfile {
}
+ if (follow_final_symlink) {
+ vfile result;
+ RET_NOT_SUC(out.follow_symlinks(result))
+ out = utility::move(result);
+ }
+
return storage::fs_result::success;
}