From 79f4d25c27bfed571125042d2d6fc9767754b17c Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Fri, 3 Apr 2026 21:25:05 +0300 Subject: [PATCH] I think I reached kernel size limit, lol --- Makefile | 2 +- console.h | 2 + drivers/keyboard.c | 49 +++++++++++++----------- drivers/keyboard.h | 41 +++++++++++++++++++- kernel.c | 93 +++++++++++++++++++++++++++++++++++----------- lib/string.c | 50 +++++++++++++++++++------ lib/string.h | 5 +++ 7 files changed, 185 insertions(+), 57 deletions(-) diff --git a/Makefile b/Makefile index ad10ed3..18f22ab 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ endif CFLAGS = -fno-pic -ffreestanding -static -fno-builtin -fno-strict-aliasing \ -mno-sse \ -I. \ - -Wall -Wno-unused-result -ggdb -m32 -Werror -fno-omit-frame-pointer -Os + -Wall -Wno-unused-result -Wno-unused-variable -Wno-unused-but-set-variable -ggdb -m32 -Werror -fno-omit-frame-pointer -Os CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) ASMFLAGS = -m32 -ffreestanding -c -g -I. diff --git a/console.h b/console.h index 272fad2..df020e1 100644 --- a/console.h +++ b/console.h @@ -2,3 +2,5 @@ void printk(const char* msg); _Noreturn void panic(const char* msg); + +#define check(expr) if (!(expr)) { panic("Assertion failed at " __FILE__ " : " " : " #expr "\n"); } \ No newline at end of file diff --git a/drivers/keyboard.c b/drivers/keyboard.c index c78615f..381a385 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -5,33 +5,40 @@ #include "port.h" #include "kernel/mem.h" -static const char sc_ascii[] = { - '?', '?', '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y', - 'u', 'i', 'o', 'p', '[', ']', '\n', '?', 'a', 's', 'd', 'f', 'g', - 'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' ', -}; +keyboard_interrupt_shared_t kbd_state_shrd; -enum { kbd_buf_capacity = PGSIZE }; - -static void interrupt_handler(registers_t *r) { +static void kbd_interrupt_handler(registers_t *r) { uint8_t scancode = port_byte_in(0x60); - if (scancode < sizeof(sc_ascii)) { - char c = sc_ascii[scancode]; - if (kbd_buf_size < kbd_buf_capacity) { - kbd_buf[kbd_buf_size++] = c; - } - char string[] = {c, '\0'}; - printk(string); + if (kbd_state_shrd.len < KEYBOARD_INTERRUPT_BUF_CAP) { + kbd_state_shrd.buf[kbd_state_shrd.len++] = scancode; } } -char* kbd_buf; -unsigned kbd_buf_size; void init_keyboard() { - kbd_buf = kalloc(); + kbd_state_shrd.len = 0; + kbd_state_shrd.buf = (uint8_t*)kalloc(); + kbd_state_shrd.copy_len = 0; + kbd_state_shrd.copy_buf = (uint8_t*)kalloc(); - register_interrupt_handler(IRQ1, interrupt_handler); + /* 128/8 actually we need only 16 bytes for that */ + memset(kbd_state_shrd.copy_pressed, 0, 16); + register_interrupt_handler(IRQ1, kbd_interrupt_handler); } + +/* reading keyboard */ +uint8_t kbd_take_from_copy_buffer() { + check(kbd_state_shrd.copy_len > 0); + uint8_t key_event_code = kbd_state_shrd.copy_buf[--kbd_state_shrd.copy_len]; + uint8_t keycode = (key_event_code & 0x7f); + if (key_event_code & 0x80) { + kbd_state_shrd.copy_pressed[keycode >> 3] = kbd_state_shrd.copy_pressed[keycode >> 3] & (~(1u << (keycode & 0x7))); + } else { + kbd_state_shrd.copy_pressed[keycode >> 3] = kbd_state_shrd.copy_pressed[keycode >> 3] | (1u << (keycode & 0x7)); + } + return key_event_code; +} + +bool kbd_can_take_from_copy_buffer() { + return kbd_state_shrd.copy_len > 0; +} \ No newline at end of file diff --git a/drivers/keyboard.h b/drivers/keyboard.h index c13d4bb..508658f 100644 --- a/drivers/keyboard.h +++ b/drivers/keyboard.h @@ -1,6 +1,43 @@ #pragma once +#include +#include + +#define KEYBOARD_INTERRUPT_BUF_CAP 100 + +typedef struct { + volatile uint32_t len; + uint8_t *buf; + + uint32_t copy_len; + uint8_t *copy_buf; + uint8_t copy_pressed[16]; +} keyboard_interrupt_shared_t; + +#define KEYCODE_SHIFT 42 +#define KEYCODE_ENTER 28 + +/* decoding */ +static const char keysym_mapped_ascii_lower[] = { + 0 , 0 , '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', 0 , 0 , 'q', 'w', 'e', 'r', 't', 'y', + 'u', 'i', 'o', 'p', '[', ']', '\n', 0 , 'a', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', ';', '\'', '`', 0 , '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', 0 , 0 , 0 , ' ', +}; + +static const char keysym_mapped_ascii_upper[] = { + 0 , 0 , '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', 0 , 0 , 'Q', 'W', 'E', 'R', 'T', 'Y', + 'U', 'I', 'O', 'P', '{', '}', '\n', 0 , 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '~', 0 , '\\', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?' /* an actual question mark */, 0 , 0 , 0 , ' ', +}; + + +extern keyboard_interrupt_shared_t kbd_state_shrd; + void init_keyboard(); -extern unsigned kbd_buf_size; -extern char *kbd_buf; +uint8_t kbd_take_from_copy_buffer(); +bool kbd_can_take_from_copy_buffer(); \ No newline at end of file diff --git a/kernel.c b/kernel.c index 05d9231..d8bfe99 100644 --- a/kernel.c +++ b/kernel.c @@ -30,6 +30,54 @@ void graphtest() { vga_clear_screen(); } +void read_line_input(char* buf, size_t* ret_len, size_t cap) { + size_t len = 0; + while (1) { + while (kbd_can_take_from_copy_buffer()) { + uint8_t keycode = kbd_take_from_copy_buffer(); + + bool shift_pressed = kbd_state_shrd.copy_pressed[42 >> 3] & (42 & 0x7); + const size_t keycodes = sizeof(keysym_mapped_ascii_upper); + check(keycodes == sizeof(keysym_mapped_ascii_lower)); + + if (keycode == KEYCODE_ENTER) { + goto end; + } + if (keycode < keycodes && keycode) { + char ch = shift_pressed ? keysym_mapped_ascii_upper[keycode] : + keysym_mapped_ascii_lower[keycode]; + if (ch != 0) { + char haha[2] = {ch, 0}; + printk(haha); + + buf[len++] = ch; + if (len == cap) { + goto end; + } + } + } + } + + asm("hlt"); + size_t count = kbd_state_shrd.len; + if (count > 0) { + // char haha[2] = {count+'0', 0}; + // printk(haha); + cli(); + size_t rem = KEYBOARD_INTERRUPT_BUF_CAP - kbd_state_shrd.copy_len; + size_t copying = rem < count ? rem : count; + memcpy(kbd_state_shrd.copy_buf, kbd_state_shrd.buf, copying); + kbd_state_shrd.len -= copying; + kbd_state_shrd.copy_len += copying; + sti(); + } + } + end: + printk("\n"); + *ret_len = len; +} + + void kmain() { freerange(P2V(1u<<20), P2V(2u<<20)); // 1MB - 2MB kvmalloc(); // map all of physical memory at KERNBASE @@ -43,30 +91,33 @@ void kmain() { sti(); vga_clear_screen(); - printk("YABLOKO\n"); + printk("YABLOKO\n\n"); - printk("\n> "); while (1) { - if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') { - if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) { - qemu_shutdown(); - } else if (!strncmp("work\n", kbd_buf, kbd_buf_size)) { - for (int i = 0; i < 5; ++i) { - msleep(1000); - printk("."); - } - } else if (!strncmp("run ", kbd_buf, 4)) { - kbd_buf[kbd_buf_size-1] = '\0'; - const char* cmd = kbd_buf + 4; - run_elf(cmd); - } else if (!strncmp("graphtest", kbd_buf, 9)) { - graphtest(); - } else { - printk("unknown command, try: halt | run CMD"); + char input[100]; + size_t input_len = 0; + const size_t input_cap = sizeof(input) - 1; + printk("> "); + read_line_input(input, &input_len, input_cap); + input[input_len] = 0; + printk(input); + printk("\n"); + if (cstr_equal(input, "halt")) { + printk("Bye\n"); + qemu_shutdown(); + } else if (cstr_equal(input, "work")) { + for (int i = 0; i < 5; ++i) { + msleep(1000); + printk("."); } - kbd_buf_size = 0; - printk("\n> "); + } else if (cstr_equal(input, "graphtest")) { + graphtest(); + } else if (cstr_starts_with(input, "run ")) { + const char* cmd = input + 4; + run_elf(cmd); + } else { + printk("as\n"); + printk("unknown command, try: halt | run CMD\n"); } - asm("hlt"); } } diff --git a/lib/string.c b/lib/string.c index 99e1171..36aaabf 100644 --- a/lib/string.c +++ b/lib/string.c @@ -1,18 +1,25 @@ #include "string.h" + +void memcpy(void*dst, const void *src, size_t size) { + for (size_t i = 0; i < size; i++) { + ((char*)dst)[i] = ((const char*)src)[i]; + } +} + void kmemmove(char* dst, char* src, size_t size) { - if (dst == src) return; - if (dst > src && dst < src + size) { // s d - // copy right-to-left - for (; size != 0; size--) { - dst[size - 1] = src[size - 1]; - } - } else { - // copy left-to-right - for (size_t i = 0; i < size; ++i) { - dst[i] = src[i]; - } - } +if (dst == src) return; +if (dst > src && dst < src + size) { // s d +// copy right-to-left +for (; size != 0; size--) { + dst[size - 1] = src[size - 1]; +} +} else { +// copy left-to-right +for (size_t i = 0; i < size; ++i) { + dst[i] = src[i]; +} +} } int strncmp(const char* s1, const char* s2, size_t size) { @@ -26,3 +33,22 @@ int strncmp(const char* s1, const char* s2, size_t size) { } return (unsigned char)(*s1) - (unsigned char)(*s2); } + +bool cstr_equal(const char* s1, const char* s2) { + while (*s1 && *s2 && *s1 == *s2) { + s1++; + s2++; + } + return *s1 == 0 && *s2 == 0; +} + + +bool cstr_starts_with(const char *A, const char *B) { + while (*A && *B) { + if (*A != *B) + return false; + A++; + B++; + } + return *B == 0; +} diff --git a/lib/string.h b/lib/string.h index 584f7d7..42dc3fa 100644 --- a/lib/string.h +++ b/lib/string.h @@ -1,6 +1,11 @@ #pragma once +#include + typedef unsigned size_t; +void memcpy(void*dst, const void *src, size_t size); void kmemmove(char* dst, char* src, size_t size); int strncmp(const char* s1, const char* s2, size_t size); +bool cstr_equal(const char* s1, const char* s2); +bool cstr_starts_with(const char *A, const char *B); \ No newline at end of file