diff --git a/Makefile b/Makefile index 58259ef..5156a16 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,13 @@ .SUFFIXES: -.PHONY: all clean +.PHONY: all clean test tests all: myos.iso SOURCE_DIR := src BUILD_DIR := build - CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \ --workdir="/scratch" \ --network=none \ @@ -16,17 +15,23 @@ CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \ -t \ cc-i686:latest +QEMU := qemu-system-i386 +QEMU_FLAGS := -d int -no-reboot + CC := $(CONTAINER_CMD) i686-elf-gcc LD := $(CONTAINER_CMD) i686-elf-ld AS := $(CONTAINER_CMD) i686-elf-as AR := $(CONTAINER_CMD) i686-elf-ar -C_SOURCES := $(shell find $(SOURCE_DIR) ! -name 'test_*' -name '*.c') +C_SOURCES := $(shell find $(SOURCE_DIR) ! -name '*_test*' -name '*.c') ASM_SOURCES := $(shell find $(SOURCE_DIR) -name '*.S') -OBJECTS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.S=.o)) -DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.d)) +OBJECTS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.S=.o)) +DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.d)) -CFLAGS := -MMD -ffreestanding -nostdlib -O1 -Wall -Wextra -Werror -std=c2x -I$(SOURCE_DIR)/include -no-pie -fstack-protector-strong -g3 +CFLAGS := -ffreestanding -nostdlib -std=c2x -MMD -I$(SOURCE_DIR)/lib/include -I$(SOURCE_DIR) -no-pie +CFLAGS += -O1 -g3 +CFLAGS += -Wall -Wextra -Werror +CFLAGS += -fstack-protector-strong -g3 CFLAGS += -Wno-unused-function CFLAGS += -Wno-unused-variable ASFLAGS := @@ -37,7 +42,7 @@ ASFLAGS := #$(info DEPENDS is $(DEPENDS)) run: myos.iso - qemu-system-i386 -d int -no-reboot -cdrom myos.iso + $(QEMU) $(QEMU_FLAGS) -cdrom myos.iso cross-compiler: cross-compiler-image/Dockerfile podman build cross-compiler-image -t cc-i686 @@ -74,21 +79,23 @@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.S Makefile # TESTS # ################### -TEST_SOURCE_DIR := $(SOURCE_DIR)/test -TEST_BUILD_DIR := $(BUILD_DIR)/test +TEST_BUILD_DIR := $(BUILD_DIR)/tests -TEST_SOURCES := $(shell find $(TEST_SOURCE_DIR) -name 'test_*.c') -TEST_DEPENDS := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=.d)) -TEST_OUTPUT := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=)) +#TEST_SOURCES := $(shell find $(SOURCE_DIR) -name '*_test.c') +#TEST_DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=.d)) +#TEST_OUTPUT := $(patsubst $(SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=)) -$(info TEST_SOURCES is $(TEST_SOURCES)) -$(info TEST_OUTPUT is $(TEST_OUTPUT)) tests: $(TEST_OUTPUT) + $(info TEST_SOURCES is $(TEST_SOURCES)) + $(info TEST_DEPENDS is $(TEST_DEPENDS)) + $(info TEST_OUTPUT is $(TEST_OUTPUT)) +test: tests -include $(TEST_DEPENDS) -$(TEST_BUILD_DIR)/test_%: $(TEST_SOURCE_DIR)/test_%.c $(SOURCE_DIR)/lib/%.c | Makefile +$(TEST_BUILD_DIR)/%_test: $(SOURCE_DIR)/%.c $(SOURCE_DIR)/%_test.c | Makefile @mkdir -p $(@D) - gcc -O1 -fsanitize=address,undefined -Wall -Wextra -Werror -g3 -std=c2x -D_FORTIFY_SOURCE=2 -I$(SOURCE_DIR)/include -o $@ $^ + gcc -O1 -fsanitize=address,undefined -Wall -Wextra -Werror -g3 -std=c2x -D_FORTIFY_SOURCE=2 -I$(SOURCE_DIR)/lib/include -o $@ $^ + ./$@ diff --git a/kernel.d b/kernel.d new file mode 100644 index 0000000..c5d5a8a --- /dev/null +++ b/kernel.d @@ -0,0 +1,4 @@ +kernel.o: src/kernel/kernel.c src/kernel/gdt.h src/kernel/types.h \ + src/kernel/tss.h src/kernel/idt.h src/kernel/interrupts.h \ + src/kernel/kernel_state.h src/lib/include/str.h src/kernel/pic.h \ + src/kernel/page.h src/lib/include/libc.h src/kernel/tty.h diff --git a/linker.ld b/linker.ld index 281f08c..b33280d 100644 --- a/linker.ld +++ b/linker.ld @@ -50,6 +50,7 @@ SECTIONS .data BLOCK(4K) : ALIGN(4K) { *(.data) + kernel_data_end = .; } /* Read-write data (uninitialized) and stack */ @@ -57,6 +58,8 @@ SECTIONS { *(COMMON) *(.bss) + + kernel_memory_end = .; } /* The compiler may produce other sections, by default it will put them in diff --git a/src/drivers/ps2-keyboard.c b/src/drivers/ps2-keyboard.c index dd8ba5e..6b752d0 100644 --- a/src/drivers/ps2-keyboard.c +++ b/src/drivers/ps2-keyboard.c @@ -32,178 +32,3 @@ const struct str ps2_response_str[] = { [PS2RESPONSE_RESEND ] = str_attach("PS2RESPONSE_RESEND"), }; -const struct str ps2_key_str[] = { - [KEY_EXTENDED ] = str_attach("KEY_EXTENDED (PRESSED)"), - [KEY_ESCAPE ] = str_attach("KEY_ESCAPE (PRESSED)"), - [KEY_1 ] = str_attach("KEY_1 (PRESSED)"), - [KEY_2 ] = str_attach("KEY_2 (PRESSED)"), - [KEY_3 ] = str_attach("KEY_3 (PRESSED)"), - [KEY_4 ] = str_attach("KEY_4 (PRESSED)"), - [KEY_5 ] = str_attach("KEY_5 (PRESSED)"), - [KEY_6 ] = str_attach("KEY_6 (PRESSED)"), - [KEY_7 ] = str_attach("KEY_7 (PRESSED)"), - [KEY_8 ] = str_attach("KEY_8 (PRESSED)"), - [KEY_9 ] = str_attach("KEY_9 (PRESSED)"), - [KEY_0 ] = str_attach("KEY_0 (PRESSED)"), - [KEY_MINUS ] = str_attach("KEY_MINUS (PRESSED)"), - [KEY_EQUALS ] = str_attach("KEY_EQUALS (PRESSED)"), - [KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (PRESSED)"), - [KEY_TAB ] = str_attach("KEY_TAB (PRESSED)"), - [KEY_Q ] = str_attach("KEY_Q (PRESSED)"), - [KEY_W ] = str_attach("KEY_W (PRESSED)"), - [KEY_E ] = str_attach("KEY_E (PRESSED)"), - [KEY_R ] = str_attach("KEY_R (PRESSED)"), - [KEY_T ] = str_attach("KEY_T (PRESSED)"), - [KEY_Y ] = str_attach("KEY_Y (PRESSED)"), - [KEY_U ] = str_attach("KEY_U (PRESSED)"), - [KEY_I ] = str_attach("KEY_I (PRESSED)"), - [KEY_O ] = str_attach("KEY_O (PRESSED)"), - [KEY_P ] = str_attach("KEY_P (PRESSED)"), - [KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (PRESSED)"), - [KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (PRESSED)"), - [KEY_ENTER ] = str_attach("KEY_ENTER (PRESSED)"), - [KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (PRESSED)"), - [KEY_A ] = str_attach("KEY_A (PRESSED)"), - [KEY_S ] = str_attach("KEY_S (PRESSED)"), - [KEY_D ] = str_attach("KEY_D (PRESSED)"), - [KEY_F ] = str_attach("KEY_F (PRESSED)"), - [KEY_G ] = str_attach("KEY_G (PRESSED)"), - [KEY_H ] = str_attach("KEY_H (PRESSED)"), - [KEY_J ] = str_attach("KEY_J (PRESSED)"), - [KEY_K ] = str_attach("KEY_K (PRESSED)"), - [KEY_L ] = str_attach("KEY_L (PRESSED)"), - [KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (PRESSED)"), - [KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (PRESSED)"), - [KEY_BACKTICK ] = str_attach("KEY_BACKTICK (PRESSED)"), - [KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (PRESSED)"), - [KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (PRESSED)"), - [KEY_Z ] = str_attach("KEY_Z (PRESSED)"), - [KEY_X ] = str_attach("KEY_X (PRESSED)"), - [KEY_C ] = str_attach("KEY_C (PRESSED)"), - [KEY_V ] = str_attach("KEY_V (PRESSED)"), - [KEY_B ] = str_attach("KEY_B (PRESSED)"), - [KEY_N ] = str_attach("KEY_N (PRESSED)"), - [KEY_M ] = str_attach("KEY_M (PRESSED)"), - [KEY_COMMA ] = str_attach("KEY_COMMA (PRESSED)"), - [KEY_DOT ] = str_attach("KEY_DOT (PRESSED)"), - [KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (PRESSED)"), - [KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (PRESSED)"), - [KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (PRESSED)"), - [KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (PRESSED)"), - [KEY_SPACE ] = str_attach("KEY_SPACE (PRESSED)"), - [KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (PRESSED)"), - [KEY_F1 ] = str_attach("KEY_F1 (PRESSED)"), - [KEY_F2 ] = str_attach("KEY_F2 (PRESSED)"), - [KEY_F3 ] = str_attach("KEY_F3 (PRESSED)"), - [KEY_F4 ] = str_attach("KEY_F4 (PRESSED)"), - [KEY_F5 ] = str_attach("KEY_F5 (PRESSED)"), - [KEY_F6 ] = str_attach("KEY_F6 (PRESSED)"), - [KEY_F7 ] = str_attach("KEY_F7 (PRESSED)"), - [KEY_F8 ] = str_attach("KEY_F8 (PRESSED)"), - [KEY_F9 ] = str_attach("KEY_F9 (PRESSED)"), - [KEY_F10 ] = str_attach("KEY_F10 (PRESSED)"), - [KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (PRESSED)"), - [KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (PRESSED)"), - [KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (PRESSED)"), - [KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (PRESSED)"), - [KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (PRESSED)"), - [KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (PRESSED)"), - [KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (PRESSED)"), - [KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (PRESSED)"), - [KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (PRESSED)"), - [KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (PRESSED)"), - [KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (PRESSED)"), - [KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (PRESSED)"), - [KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (PRESSED)"), - [KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (PRESSED)"), - [KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (PRESSED)"), - [KEY_F11 ] = str_attach("KEY_F11 (PRESSED)"), - [KEY_F12 ] = str_attach("KEY_F12 (PRESSED)"), - - [KEY_RELEASED | KEY_ESCAPE ] = str_attach("KEY_ESCAPE (RELEASED)"), - [KEY_RELEASED | KEY_1 ] = str_attach("KEY_1 (RELEASED)"), - [KEY_RELEASED | KEY_2 ] = str_attach("KEY_2 (RELEASED)"), - [KEY_RELEASED | KEY_3 ] = str_attach("KEY_3 (RELEASED)"), - [KEY_RELEASED | KEY_4 ] = str_attach("KEY_4 (RELEASED)"), - [KEY_RELEASED | KEY_5 ] = str_attach("KEY_5 (RELEASED)"), - [KEY_RELEASED | KEY_6 ] = str_attach("KEY_6 (RELEASED)"), - [KEY_RELEASED | KEY_7 ] = str_attach("KEY_7 (RELEASED)"), - [KEY_RELEASED | KEY_8 ] = str_attach("KEY_8 (RELEASED)"), - [KEY_RELEASED | KEY_9 ] = str_attach("KEY_9 (RELEASED)"), - [KEY_RELEASED | KEY_0 ] = str_attach("KEY_0 (RELEASED)"), - [KEY_RELEASED | KEY_MINUS ] = str_attach("KEY_MINUS (RELEASED)"), - [KEY_RELEASED | KEY_EQUALS ] = str_attach("KEY_EQUALS (RELEASED)"), - [KEY_RELEASED | KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (RELEASED)"), - [KEY_RELEASED | KEY_TAB ] = str_attach("KEY_TAB (RELEASED)"), - [KEY_RELEASED | KEY_Q ] = str_attach("KEY_Q (RELEASED)"), - [KEY_RELEASED | KEY_W ] = str_attach("KEY_W (RELEASED)"), - [KEY_RELEASED | KEY_E ] = str_attach("KEY_E (RELEASED)"), - [KEY_RELEASED | KEY_R ] = str_attach("KEY_R (RELEASED)"), - [KEY_RELEASED | KEY_T ] = str_attach("KEY_T (RELEASED)"), - [KEY_RELEASED | KEY_Y ] = str_attach("KEY_Y (RELEASED)"), - [KEY_RELEASED | KEY_U ] = str_attach("KEY_U (RELEASED)"), - [KEY_RELEASED | KEY_I ] = str_attach("KEY_I (RELEASED)"), - [KEY_RELEASED | KEY_O ] = str_attach("KEY_O (RELEASED)"), - [KEY_RELEASED | KEY_P ] = str_attach("KEY_P (RELEASED)"), - [KEY_RELEASED | KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (RELEASED)"), - [KEY_RELEASED | KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (RELEASED)"), - [KEY_RELEASED | KEY_ENTER ] = str_attach("KEY_ENTER (RELEASED)"), - [KEY_RELEASED | KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (RELEASED)"), - [KEY_RELEASED | KEY_A ] = str_attach("KEY_A (RELEASED)"), - [KEY_RELEASED | KEY_S ] = str_attach("KEY_S (RELEASED)"), - [KEY_RELEASED | KEY_D ] = str_attach("KEY_D (RELEASED)"), - [KEY_RELEASED | KEY_F ] = str_attach("KEY_F (RELEASED)"), - [KEY_RELEASED | KEY_G ] = str_attach("KEY_G (RELEASED)"), - [KEY_RELEASED | KEY_H ] = str_attach("KEY_H (RELEASED)"), - [KEY_RELEASED | KEY_J ] = str_attach("KEY_J (RELEASED)"), - [KEY_RELEASED | KEY_K ] = str_attach("KEY_K (RELEASED)"), - [KEY_RELEASED | KEY_L ] = str_attach("KEY_L (RELEASED)"), - [KEY_RELEASED | KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (RELEASED)"), - [KEY_RELEASED | KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (RELEASED)"), - [KEY_RELEASED | KEY_BACKTICK ] = str_attach("KEY_BACKTICK (RELEASED)"), - [KEY_RELEASED | KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (RELEASED)"), - [KEY_RELEASED | KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (RELEASED)"), - [KEY_RELEASED | KEY_Z ] = str_attach("KEY_Z (RELEASED)"), - [KEY_RELEASED | KEY_X ] = str_attach("KEY_X (RELEASED)"), - [KEY_RELEASED | KEY_C ] = str_attach("KEY_C (RELEASED)"), - [KEY_RELEASED | KEY_V ] = str_attach("KEY_V (RELEASED)"), - [KEY_RELEASED | KEY_B ] = str_attach("KEY_B (RELEASED)"), - [KEY_RELEASED | KEY_N ] = str_attach("KEY_N (RELEASED)"), - [KEY_RELEASED | KEY_M ] = str_attach("KEY_M (RELEASED)"), - [KEY_RELEASED | KEY_COMMA ] = str_attach("KEY_COMMA (RELEASED)"), - [KEY_RELEASED | KEY_DOT ] = str_attach("KEY_DOT (RELEASED)"), - [KEY_RELEASED | KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (RELEASED)"), - [KEY_RELEASED | KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (RELEASED)"), - [KEY_RELEASED | KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (RELEASED)"), - [KEY_RELEASED | KEY_SPACE ] = str_attach("KEY_SPACE (RELEASED)"), - [KEY_RELEASED | KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (RELEASED)"), - [KEY_RELEASED | KEY_F1 ] = str_attach("KEY_F1 (RELEASED)"), - [KEY_RELEASED | KEY_F2 ] = str_attach("KEY_F2 (RELEASED)"), - [KEY_RELEASED | KEY_F3 ] = str_attach("KEY_F3 (RELEASED)"), - [KEY_RELEASED | KEY_F4 ] = str_attach("KEY_F4 (RELEASED)"), - [KEY_RELEASED | KEY_F5 ] = str_attach("KEY_F5 (RELEASED)"), - [KEY_RELEASED | KEY_F6 ] = str_attach("KEY_F6 (RELEASED)"), - [KEY_RELEASED | KEY_F7 ] = str_attach("KEY_F7 (RELEASED)"), - [KEY_RELEASED | KEY_F8 ] = str_attach("KEY_F8 (RELEASED)"), - [KEY_RELEASED | KEY_F9 ] = str_attach("KEY_F9 (RELEASED)"), - [KEY_RELEASED | KEY_F10 ] = str_attach("KEY_F10 (RELEASED)"), - [KEY_RELEASED | KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (RELEASED)"), - [KEY_RELEASED | KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (RELEASED)"), - [KEY_RELEASED | KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (RELEASED)"), - [KEY_RELEASED | KEY_F11 ] = str_attach("KEY_F11 (RELEASED)"), - [KEY_RELEASED | KEY_F12 ] = str_attach("KEY_F12 (RELEASED)"), -}; - diff --git a/src/include/ps2-keyboard.h b/src/drivers/ps2-keyboard.h similarity index 98% rename from src/include/ps2-keyboard.h rename to src/drivers/ps2-keyboard.h index 15b0c40..780b31e 100644 --- a/src/include/ps2-keyboard.h +++ b/src/drivers/ps2-keyboard.h @@ -176,6 +176,9 @@ enum ps2_keys { }; extern const struct str ps2_key_str[]; +constexpr size_t KEY_MODIFIER_SHIFT = 0x80; /* used by ps2_key_char[] */ +extern const char ps2_key_char[]; + enum ps2_extended_key : uint8_t { KEY_E_MULTIMEDIA_PREV_TRACK = 0x10, KEY_E_MULTIMEDIA_NEXT_TRACK = 0x19, diff --git a/src/kernel/interrupts.c b/src/kernel/interrupts.c index 74a9ae8..977125c 100644 --- a/src/kernel/interrupts.c +++ b/src/kernel/interrupts.c @@ -1,4 +1,5 @@ #include + #include "libc.h" #include "tty.h" #include "interrupts.h" @@ -22,7 +23,7 @@ static void print_interrupt_frame(struct interrupt_frame* f) "Interrupt frame:\n" "================\n" "ip: {x32}\n" - "cs: {x32}\n" + "cs: {x32} == {cs}\n" "flags: {x32}\n" "sp: {x32}\n" "ss: {x32}\n"), @@ -35,14 +36,15 @@ static void print_interrupt_frame(struct interrupt_frame* f) /* not an interrupt/exception, but called by exception stubs */ __attribute__((noreturn)) -static void panic_exception_not_implemented(struct interrupt_frame* frame, int exception_no) +static void panic_exception_not_implemented(struct interrupt_frame* frame, int exception_no, uint32_t err) { terminal_set_color(VGA_COLOR_WHITE, VGA_COLOR_RED); printf(str_attach("non-implemented exception {i32} occurred\n"), exception_no); struct str name = idt_desc_index_str[exception_no]; if (name.len != 0) { - printf(str_attach("exception name: {str})\n"), name); + printf(str_attach("exception name: {str}\n"), name, err); } + printf(str_attach("error: {x32}\n"), err); if (frame != NULL) { print_interrupt_frame(frame); } else { @@ -94,6 +96,7 @@ void exception_handler_div_by_zero(struct interrupt_frame* frame) panic(str_attach("div by zero occured :(")); } +#include "page.h" __attribute__((interrupt, noreturn)) void exception_handler_page_fault(struct interrupt_frame* frame, int err) { @@ -103,9 +106,41 @@ void exception_handler_page_fault(struct interrupt_frame* frame, int err) } terminal_set_color(VGA_COLOR_WHITE, VGA_COLOR_RED); printf(str_attach( - "page fault :(, err: 0x{x32}\n"), - err, - gdt_segment_index_str[err/8]); + "page fault :(, err: 0x{x32}: ["), + err); + + /* page fault error bits */ + enum { + present = 1<<0, + write = 1<<1, + user = 1<<2, + reserved_write = 1<<3, + instruction_fetch = 1<<4, + protection_key = 1<<5, + shadow_stack = 1<<6, + software_guard_ex = 1<<15, + }; + + const struct str error_names[] = { + [0] = str_attach("present"), + [1] = str_attach("write"), + [2] = str_attach("user"), + [3] = str_attach("reserved_write"), + [4] = str_attach("instruction_fetch"), + [5] = str_attach("protection_key"), + [6] = str_attach("shadow_stack"), + [15] = str_attach("software_guard_ex"), + }; + + for (size_t i = 0; i < sizeof error_names / sizeof *error_names; i++) { + if ((err & (1<next) + { + // TODO + //proc_send(p->); + } + +#if 0 uint8_t key = inb(PIC_KEYBOARD); - bool released = key & KEY_RELEASED; + key &= ~KEY_RELEASED; + + if (key == KEY_RIGHT_SHIFT || key == KEY_LEFT_SHIFT) { + shift = !released; + outb(PIC1_COMMAND, OCW2_EOI); + return; + } + + if (key == KEY_E_RIGHT_CONTROL || key == KEY_LEFT_CONTROL) { + ctrl = !released; + (void)ctrl; + outb(PIC1_COMMAND, OCW2_EOI); + return; + } + + if (!released) { + if (shift) { + key |= KEY_MODIFIER_SHIFT; + } + const char ch = ps2_key_char[key]; + if (ch) { + terminal_putchar(ch); + kernel_input_buffer_push(ch); + } else { + printf(str_attach("[{str}]"), ps2_key_str[key]); + } + } +#endif - printf(str_attach("key {str}\n"), ps2_key_str[key]); outb(PIC1_COMMAND, OCW2_EOI); } @@ -191,12 +264,13 @@ __attribute__((interrupt)) void irq_handler_15(struct interrupt_frame* frame) { * Exception Stubs * =============== */ +#define EXCEPTION_STUB(n) exception_stub_##n -#define DEFINE_EXCEPTION_STUB(n) \ - __attribute__((interrupt, noreturn)) \ - void EXCEPTION_STUB(n)(struct interrupt_frame* frame) \ - { \ - panic_exception_not_implemented(frame, n); \ +#define DEFINE_EXCEPTION_STUB(n) \ + __attribute__((interrupt, noreturn)) \ + void EXCEPTION_STUB(n)(struct interrupt_frame* frame, uint32_t err) \ + { \ + panic_exception_not_implemented(frame, n, err); \ } DEFINE_EXCEPTION_STUB(0) diff --git a/src/kernel/interrupts.h b/src/kernel/interrupts.h index 4d61873..f10a34b 100644 --- a/src/kernel/interrupts.h +++ b/src/kernel/interrupts.h @@ -2,14 +2,6 @@ #include "types.h" -struct __attribute__((packed)) interrupt_frame { - uword_t ip; - uword_t cs; - uword_t flags; - uword_t sp; - uword_t ss; -}; - /* * Exceptions * ==========*/ @@ -22,6 +14,9 @@ void exception_handler_general_protection_fault(struct interrupt_frame* frame, i __attribute__((interrupt, noreturn)) void exception_handler_double_fault(struct interrupt_frame* frame); +__attribute__((interrupt, noreturn)) +void exception_handler_page_fault(struct interrupt_frame* frame, int err); + __attribute__((interrupt, noreturn)) void exception_default(struct interrupt_frame* frame); @@ -78,265 +73,266 @@ static void idt_init_stubs(struct idt_gate_descriptor idt[]) { IDT_DPL_3, \ IDT_GATE_TYPE_TRAP32) - #define DECLARE_EXCEPTION_STUB(n) \ - __attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*); \ + #define SET_EXCEPTION_STUB(n) \ + __attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*, uint32_t err); \ idt[n] = DESC(EXCEPTION_STUB(n)) - DECLARE_EXCEPTION_STUB(0); - DECLARE_EXCEPTION_STUB(1); - DECLARE_EXCEPTION_STUB(2); - DECLARE_EXCEPTION_STUB(3); - DECLARE_EXCEPTION_STUB(4); - DECLARE_EXCEPTION_STUB(5); - DECLARE_EXCEPTION_STUB(6); - DECLARE_EXCEPTION_STUB(7); - DECLARE_EXCEPTION_STUB(8); - DECLARE_EXCEPTION_STUB(9); - DECLARE_EXCEPTION_STUB(10); - DECLARE_EXCEPTION_STUB(11); - DECLARE_EXCEPTION_STUB(12); - DECLARE_EXCEPTION_STUB(13); - DECLARE_EXCEPTION_STUB(14); - DECLARE_EXCEPTION_STUB(15); - DECLARE_EXCEPTION_STUB(16); - DECLARE_EXCEPTION_STUB(17); - DECLARE_EXCEPTION_STUB(18); - DECLARE_EXCEPTION_STUB(19); - DECLARE_EXCEPTION_STUB(20); - DECLARE_EXCEPTION_STUB(21); - DECLARE_EXCEPTION_STUB(22); - DECLARE_EXCEPTION_STUB(23); - DECLARE_EXCEPTION_STUB(24); - DECLARE_EXCEPTION_STUB(25); - DECLARE_EXCEPTION_STUB(26); - DECLARE_EXCEPTION_STUB(27); - DECLARE_EXCEPTION_STUB(28); - DECLARE_EXCEPTION_STUB(29); - DECLARE_EXCEPTION_STUB(30); - DECLARE_EXCEPTION_STUB(31); - DECLARE_EXCEPTION_STUB(32); - DECLARE_EXCEPTION_STUB(33); - DECLARE_EXCEPTION_STUB(34); - DECLARE_EXCEPTION_STUB(35); - DECLARE_EXCEPTION_STUB(36); - DECLARE_EXCEPTION_STUB(37); - DECLARE_EXCEPTION_STUB(38); - DECLARE_EXCEPTION_STUB(39); - DECLARE_EXCEPTION_STUB(40); - DECLARE_EXCEPTION_STUB(41); - DECLARE_EXCEPTION_STUB(42); - DECLARE_EXCEPTION_STUB(43); - DECLARE_EXCEPTION_STUB(44); - DECLARE_EXCEPTION_STUB(45); - DECLARE_EXCEPTION_STUB(46); - DECLARE_EXCEPTION_STUB(47); - DECLARE_EXCEPTION_STUB(48); - DECLARE_EXCEPTION_STUB(49); - DECLARE_EXCEPTION_STUB(50); - DECLARE_EXCEPTION_STUB(51); - DECLARE_EXCEPTION_STUB(52); - DECLARE_EXCEPTION_STUB(53); - DECLARE_EXCEPTION_STUB(54); - DECLARE_EXCEPTION_STUB(55); - DECLARE_EXCEPTION_STUB(56); - DECLARE_EXCEPTION_STUB(57); - DECLARE_EXCEPTION_STUB(58); - DECLARE_EXCEPTION_STUB(59); - DECLARE_EXCEPTION_STUB(60); - DECLARE_EXCEPTION_STUB(61); - DECLARE_EXCEPTION_STUB(62); - DECLARE_EXCEPTION_STUB(63); - DECLARE_EXCEPTION_STUB(64); - DECLARE_EXCEPTION_STUB(65); - DECLARE_EXCEPTION_STUB(66); - DECLARE_EXCEPTION_STUB(67); - DECLARE_EXCEPTION_STUB(68); - DECLARE_EXCEPTION_STUB(69); - DECLARE_EXCEPTION_STUB(70); - DECLARE_EXCEPTION_STUB(71); - DECLARE_EXCEPTION_STUB(72); - DECLARE_EXCEPTION_STUB(73); - DECLARE_EXCEPTION_STUB(74); - DECLARE_EXCEPTION_STUB(75); - DECLARE_EXCEPTION_STUB(76); - DECLARE_EXCEPTION_STUB(77); - DECLARE_EXCEPTION_STUB(78); - DECLARE_EXCEPTION_STUB(79); - DECLARE_EXCEPTION_STUB(80); - DECLARE_EXCEPTION_STUB(81); - DECLARE_EXCEPTION_STUB(82); - DECLARE_EXCEPTION_STUB(83); - DECLARE_EXCEPTION_STUB(84); - DECLARE_EXCEPTION_STUB(85); - DECLARE_EXCEPTION_STUB(86); - DECLARE_EXCEPTION_STUB(87); - DECLARE_EXCEPTION_STUB(88); - DECLARE_EXCEPTION_STUB(89); - DECLARE_EXCEPTION_STUB(90); - DECLARE_EXCEPTION_STUB(91); - DECLARE_EXCEPTION_STUB(92); - DECLARE_EXCEPTION_STUB(93); - DECLARE_EXCEPTION_STUB(94); - DECLARE_EXCEPTION_STUB(95); - DECLARE_EXCEPTION_STUB(96); - DECLARE_EXCEPTION_STUB(97); - DECLARE_EXCEPTION_STUB(98); - DECLARE_EXCEPTION_STUB(99); - DECLARE_EXCEPTION_STUB(100); - DECLARE_EXCEPTION_STUB(101); - DECLARE_EXCEPTION_STUB(102); - DECLARE_EXCEPTION_STUB(103); - DECLARE_EXCEPTION_STUB(104); - DECLARE_EXCEPTION_STUB(105); - DECLARE_EXCEPTION_STUB(106); - DECLARE_EXCEPTION_STUB(107); - DECLARE_EXCEPTION_STUB(108); - DECLARE_EXCEPTION_STUB(109); - DECLARE_EXCEPTION_STUB(110); - DECLARE_EXCEPTION_STUB(111); - DECLARE_EXCEPTION_STUB(112); - DECLARE_EXCEPTION_STUB(113); - DECLARE_EXCEPTION_STUB(114); - DECLARE_EXCEPTION_STUB(115); - DECLARE_EXCEPTION_STUB(116); - DECLARE_EXCEPTION_STUB(117); - DECLARE_EXCEPTION_STUB(118); - DECLARE_EXCEPTION_STUB(119); - DECLARE_EXCEPTION_STUB(120); - DECLARE_EXCEPTION_STUB(121); - DECLARE_EXCEPTION_STUB(122); - DECLARE_EXCEPTION_STUB(123); - DECLARE_EXCEPTION_STUB(124); - DECLARE_EXCEPTION_STUB(125); - DECLARE_EXCEPTION_STUB(126); - DECLARE_EXCEPTION_STUB(127); - DECLARE_EXCEPTION_STUB(128); - DECLARE_EXCEPTION_STUB(129); - DECLARE_EXCEPTION_STUB(130); - DECLARE_EXCEPTION_STUB(131); - DECLARE_EXCEPTION_STUB(132); - DECLARE_EXCEPTION_STUB(133); - DECLARE_EXCEPTION_STUB(134); - DECLARE_EXCEPTION_STUB(135); - DECLARE_EXCEPTION_STUB(136); - DECLARE_EXCEPTION_STUB(137); - DECLARE_EXCEPTION_STUB(138); - DECLARE_EXCEPTION_STUB(139); - DECLARE_EXCEPTION_STUB(140); - DECLARE_EXCEPTION_STUB(141); - DECLARE_EXCEPTION_STUB(142); - DECLARE_EXCEPTION_STUB(143); - DECLARE_EXCEPTION_STUB(144); - DECLARE_EXCEPTION_STUB(145); - DECLARE_EXCEPTION_STUB(146); - DECLARE_EXCEPTION_STUB(147); - DECLARE_EXCEPTION_STUB(148); - DECLARE_EXCEPTION_STUB(149); - DECLARE_EXCEPTION_STUB(150); - DECLARE_EXCEPTION_STUB(151); - DECLARE_EXCEPTION_STUB(152); - DECLARE_EXCEPTION_STUB(153); - DECLARE_EXCEPTION_STUB(154); - DECLARE_EXCEPTION_STUB(155); - DECLARE_EXCEPTION_STUB(156); - DECLARE_EXCEPTION_STUB(157); - DECLARE_EXCEPTION_STUB(158); - DECLARE_EXCEPTION_STUB(159); - DECLARE_EXCEPTION_STUB(160); - DECLARE_EXCEPTION_STUB(161); - DECLARE_EXCEPTION_STUB(162); - DECLARE_EXCEPTION_STUB(163); - DECLARE_EXCEPTION_STUB(164); - DECLARE_EXCEPTION_STUB(165); - DECLARE_EXCEPTION_STUB(166); - DECLARE_EXCEPTION_STUB(167); - DECLARE_EXCEPTION_STUB(168); - DECLARE_EXCEPTION_STUB(169); - DECLARE_EXCEPTION_STUB(170); - DECLARE_EXCEPTION_STUB(171); - DECLARE_EXCEPTION_STUB(172); - DECLARE_EXCEPTION_STUB(173); - DECLARE_EXCEPTION_STUB(174); - DECLARE_EXCEPTION_STUB(175); - DECLARE_EXCEPTION_STUB(176); - DECLARE_EXCEPTION_STUB(177); - DECLARE_EXCEPTION_STUB(178); - DECLARE_EXCEPTION_STUB(179); - DECLARE_EXCEPTION_STUB(180); - DECLARE_EXCEPTION_STUB(181); - DECLARE_EXCEPTION_STUB(182); - DECLARE_EXCEPTION_STUB(183); - DECLARE_EXCEPTION_STUB(184); - DECLARE_EXCEPTION_STUB(185); - DECLARE_EXCEPTION_STUB(186); - DECLARE_EXCEPTION_STUB(187); - DECLARE_EXCEPTION_STUB(188); - DECLARE_EXCEPTION_STUB(189); - DECLARE_EXCEPTION_STUB(190); - DECLARE_EXCEPTION_STUB(191); - DECLARE_EXCEPTION_STUB(192); - DECLARE_EXCEPTION_STUB(193); - DECLARE_EXCEPTION_STUB(194); - DECLARE_EXCEPTION_STUB(195); - DECLARE_EXCEPTION_STUB(196); - DECLARE_EXCEPTION_STUB(197); - DECLARE_EXCEPTION_STUB(198); - DECLARE_EXCEPTION_STUB(199); - DECLARE_EXCEPTION_STUB(200); - DECLARE_EXCEPTION_STUB(201); - DECLARE_EXCEPTION_STUB(202); - DECLARE_EXCEPTION_STUB(203); - DECLARE_EXCEPTION_STUB(204); - DECLARE_EXCEPTION_STUB(205); - DECLARE_EXCEPTION_STUB(206); - DECLARE_EXCEPTION_STUB(207); - DECLARE_EXCEPTION_STUB(208); - DECLARE_EXCEPTION_STUB(209); - DECLARE_EXCEPTION_STUB(210); - DECLARE_EXCEPTION_STUB(211); - DECLARE_EXCEPTION_STUB(212); - DECLARE_EXCEPTION_STUB(213); - DECLARE_EXCEPTION_STUB(214); - DECLARE_EXCEPTION_STUB(215); - DECLARE_EXCEPTION_STUB(216); - DECLARE_EXCEPTION_STUB(217); - DECLARE_EXCEPTION_STUB(218); - DECLARE_EXCEPTION_STUB(219); - DECLARE_EXCEPTION_STUB(220); - DECLARE_EXCEPTION_STUB(221); - DECLARE_EXCEPTION_STUB(222); - DECLARE_EXCEPTION_STUB(223); - DECLARE_EXCEPTION_STUB(224); - DECLARE_EXCEPTION_STUB(225); - DECLARE_EXCEPTION_STUB(226); - DECLARE_EXCEPTION_STUB(227); - DECLARE_EXCEPTION_STUB(228); - DECLARE_EXCEPTION_STUB(229); - DECLARE_EXCEPTION_STUB(230); - DECLARE_EXCEPTION_STUB(231); - DECLARE_EXCEPTION_STUB(232); - DECLARE_EXCEPTION_STUB(233); - DECLARE_EXCEPTION_STUB(234); - DECLARE_EXCEPTION_STUB(235); - DECLARE_EXCEPTION_STUB(236); - DECLARE_EXCEPTION_STUB(237); - DECLARE_EXCEPTION_STUB(238); - DECLARE_EXCEPTION_STUB(239); - DECLARE_EXCEPTION_STUB(240); - DECLARE_EXCEPTION_STUB(241); - DECLARE_EXCEPTION_STUB(242); - DECLARE_EXCEPTION_STUB(243); - DECLARE_EXCEPTION_STUB(244); - DECLARE_EXCEPTION_STUB(245); - DECLARE_EXCEPTION_STUB(246); - DECLARE_EXCEPTION_STUB(247); - DECLARE_EXCEPTION_STUB(248); - DECLARE_EXCEPTION_STUB(249); - DECLARE_EXCEPTION_STUB(250); - DECLARE_EXCEPTION_STUB(251); - DECLARE_EXCEPTION_STUB(252); - DECLARE_EXCEPTION_STUB(253); - DECLARE_EXCEPTION_STUB(254); - DECLARE_EXCEPTION_STUB(255); + SET_EXCEPTION_STUB(0); + SET_EXCEPTION_STUB(1); + SET_EXCEPTION_STUB(2); + SET_EXCEPTION_STUB(3); + SET_EXCEPTION_STUB(4); + SET_EXCEPTION_STUB(5); + SET_EXCEPTION_STUB(6); + SET_EXCEPTION_STUB(7); + SET_EXCEPTION_STUB(8); + SET_EXCEPTION_STUB(9); + SET_EXCEPTION_STUB(10); + SET_EXCEPTION_STUB(11); + SET_EXCEPTION_STUB(12); + SET_EXCEPTION_STUB(13); + SET_EXCEPTION_STUB(14); + SET_EXCEPTION_STUB(15); + SET_EXCEPTION_STUB(16); + SET_EXCEPTION_STUB(17); + SET_EXCEPTION_STUB(18); + SET_EXCEPTION_STUB(19); + SET_EXCEPTION_STUB(20); + SET_EXCEPTION_STUB(21); + SET_EXCEPTION_STUB(22); + SET_EXCEPTION_STUB(23); + SET_EXCEPTION_STUB(24); + SET_EXCEPTION_STUB(25); + SET_EXCEPTION_STUB(26); + SET_EXCEPTION_STUB(27); + SET_EXCEPTION_STUB(28); + SET_EXCEPTION_STUB(29); + SET_EXCEPTION_STUB(30); + SET_EXCEPTION_STUB(31); + SET_EXCEPTION_STUB(32); + SET_EXCEPTION_STUB(33); + SET_EXCEPTION_STUB(34); + SET_EXCEPTION_STUB(35); + SET_EXCEPTION_STUB(36); + SET_EXCEPTION_STUB(37); + SET_EXCEPTION_STUB(38); + SET_EXCEPTION_STUB(39); + SET_EXCEPTION_STUB(40); + SET_EXCEPTION_STUB(41); + SET_EXCEPTION_STUB(42); + SET_EXCEPTION_STUB(43); + SET_EXCEPTION_STUB(44); + SET_EXCEPTION_STUB(45); + SET_EXCEPTION_STUB(46); + SET_EXCEPTION_STUB(47); + SET_EXCEPTION_STUB(48); + SET_EXCEPTION_STUB(49); + SET_EXCEPTION_STUB(50); + SET_EXCEPTION_STUB(51); + SET_EXCEPTION_STUB(52); + SET_EXCEPTION_STUB(53); + SET_EXCEPTION_STUB(54); + SET_EXCEPTION_STUB(55); + SET_EXCEPTION_STUB(56); + SET_EXCEPTION_STUB(57); + SET_EXCEPTION_STUB(58); + SET_EXCEPTION_STUB(59); + SET_EXCEPTION_STUB(60); + SET_EXCEPTION_STUB(61); + SET_EXCEPTION_STUB(62); + SET_EXCEPTION_STUB(63); + SET_EXCEPTION_STUB(64); + SET_EXCEPTION_STUB(65); + SET_EXCEPTION_STUB(66); + SET_EXCEPTION_STUB(67); + SET_EXCEPTION_STUB(68); + SET_EXCEPTION_STUB(69); + SET_EXCEPTION_STUB(70); + SET_EXCEPTION_STUB(71); + SET_EXCEPTION_STUB(72); + SET_EXCEPTION_STUB(73); + SET_EXCEPTION_STUB(74); + SET_EXCEPTION_STUB(75); + SET_EXCEPTION_STUB(76); + SET_EXCEPTION_STUB(77); + SET_EXCEPTION_STUB(78); + SET_EXCEPTION_STUB(79); + SET_EXCEPTION_STUB(80); + SET_EXCEPTION_STUB(81); + SET_EXCEPTION_STUB(82); + SET_EXCEPTION_STUB(83); + SET_EXCEPTION_STUB(84); + SET_EXCEPTION_STUB(85); + SET_EXCEPTION_STUB(86); + SET_EXCEPTION_STUB(87); + SET_EXCEPTION_STUB(88); + SET_EXCEPTION_STUB(89); + SET_EXCEPTION_STUB(90); + SET_EXCEPTION_STUB(91); + SET_EXCEPTION_STUB(92); + SET_EXCEPTION_STUB(93); + SET_EXCEPTION_STUB(94); + SET_EXCEPTION_STUB(95); + SET_EXCEPTION_STUB(96); + SET_EXCEPTION_STUB(97); + SET_EXCEPTION_STUB(98); + SET_EXCEPTION_STUB(99); + SET_EXCEPTION_STUB(100); + SET_EXCEPTION_STUB(101); + SET_EXCEPTION_STUB(102); + SET_EXCEPTION_STUB(103); + SET_EXCEPTION_STUB(104); + SET_EXCEPTION_STUB(105); + SET_EXCEPTION_STUB(106); + SET_EXCEPTION_STUB(107); + SET_EXCEPTION_STUB(108); + SET_EXCEPTION_STUB(109); + SET_EXCEPTION_STUB(110); + SET_EXCEPTION_STUB(111); + SET_EXCEPTION_STUB(112); + SET_EXCEPTION_STUB(113); + SET_EXCEPTION_STUB(114); + SET_EXCEPTION_STUB(115); + SET_EXCEPTION_STUB(116); + SET_EXCEPTION_STUB(117); + SET_EXCEPTION_STUB(118); + SET_EXCEPTION_STUB(119); + SET_EXCEPTION_STUB(120); + SET_EXCEPTION_STUB(121); + SET_EXCEPTION_STUB(122); + SET_EXCEPTION_STUB(123); + SET_EXCEPTION_STUB(124); + SET_EXCEPTION_STUB(125); + SET_EXCEPTION_STUB(126); + SET_EXCEPTION_STUB(127); + SET_EXCEPTION_STUB(128); + SET_EXCEPTION_STUB(129); + SET_EXCEPTION_STUB(130); + SET_EXCEPTION_STUB(131); + SET_EXCEPTION_STUB(132); + SET_EXCEPTION_STUB(133); + SET_EXCEPTION_STUB(134); + SET_EXCEPTION_STUB(135); + SET_EXCEPTION_STUB(136); + SET_EXCEPTION_STUB(137); + SET_EXCEPTION_STUB(138); + SET_EXCEPTION_STUB(139); + SET_EXCEPTION_STUB(140); + SET_EXCEPTION_STUB(141); + SET_EXCEPTION_STUB(142); + SET_EXCEPTION_STUB(143); + SET_EXCEPTION_STUB(144); + SET_EXCEPTION_STUB(145); + SET_EXCEPTION_STUB(146); + SET_EXCEPTION_STUB(147); + SET_EXCEPTION_STUB(148); + SET_EXCEPTION_STUB(149); + SET_EXCEPTION_STUB(150); + SET_EXCEPTION_STUB(151); + SET_EXCEPTION_STUB(152); + SET_EXCEPTION_STUB(153); + SET_EXCEPTION_STUB(154); + SET_EXCEPTION_STUB(155); + SET_EXCEPTION_STUB(156); + SET_EXCEPTION_STUB(157); + SET_EXCEPTION_STUB(158); + SET_EXCEPTION_STUB(159); + SET_EXCEPTION_STUB(160); + SET_EXCEPTION_STUB(161); + SET_EXCEPTION_STUB(162); + SET_EXCEPTION_STUB(163); + SET_EXCEPTION_STUB(164); + SET_EXCEPTION_STUB(165); + SET_EXCEPTION_STUB(166); + SET_EXCEPTION_STUB(167); + SET_EXCEPTION_STUB(168); + SET_EXCEPTION_STUB(169); + SET_EXCEPTION_STUB(170); + SET_EXCEPTION_STUB(171); + SET_EXCEPTION_STUB(172); + SET_EXCEPTION_STUB(173); + SET_EXCEPTION_STUB(174); + SET_EXCEPTION_STUB(175); + SET_EXCEPTION_STUB(176); + SET_EXCEPTION_STUB(177); + SET_EXCEPTION_STUB(178); + SET_EXCEPTION_STUB(179); + SET_EXCEPTION_STUB(180); + SET_EXCEPTION_STUB(181); + SET_EXCEPTION_STUB(182); + SET_EXCEPTION_STUB(183); + SET_EXCEPTION_STUB(184); + SET_EXCEPTION_STUB(185); + SET_EXCEPTION_STUB(186); + SET_EXCEPTION_STUB(187); + SET_EXCEPTION_STUB(188); + SET_EXCEPTION_STUB(189); + SET_EXCEPTION_STUB(190); + SET_EXCEPTION_STUB(191); + SET_EXCEPTION_STUB(192); + SET_EXCEPTION_STUB(193); + SET_EXCEPTION_STUB(194); + SET_EXCEPTION_STUB(195); + SET_EXCEPTION_STUB(196); + SET_EXCEPTION_STUB(197); + SET_EXCEPTION_STUB(198); + SET_EXCEPTION_STUB(199); + SET_EXCEPTION_STUB(200); + SET_EXCEPTION_STUB(201); + SET_EXCEPTION_STUB(202); + SET_EXCEPTION_STUB(203); + SET_EXCEPTION_STUB(204); + SET_EXCEPTION_STUB(205); + SET_EXCEPTION_STUB(206); + SET_EXCEPTION_STUB(207); + SET_EXCEPTION_STUB(208); + SET_EXCEPTION_STUB(209); + SET_EXCEPTION_STUB(210); + SET_EXCEPTION_STUB(211); + SET_EXCEPTION_STUB(212); + SET_EXCEPTION_STUB(213); + SET_EXCEPTION_STUB(214); + SET_EXCEPTION_STUB(215); + SET_EXCEPTION_STUB(216); + SET_EXCEPTION_STUB(217); + SET_EXCEPTION_STUB(218); + SET_EXCEPTION_STUB(219); + SET_EXCEPTION_STUB(220); + SET_EXCEPTION_STUB(221); + SET_EXCEPTION_STUB(222); + SET_EXCEPTION_STUB(223); + SET_EXCEPTION_STUB(224); + SET_EXCEPTION_STUB(225); + SET_EXCEPTION_STUB(226); + SET_EXCEPTION_STUB(227); + SET_EXCEPTION_STUB(228); + SET_EXCEPTION_STUB(229); + SET_EXCEPTION_STUB(230); + SET_EXCEPTION_STUB(231); + SET_EXCEPTION_STUB(232); + SET_EXCEPTION_STUB(233); + SET_EXCEPTION_STUB(234); + SET_EXCEPTION_STUB(235); + SET_EXCEPTION_STUB(236); + SET_EXCEPTION_STUB(237); + SET_EXCEPTION_STUB(238); + SET_EXCEPTION_STUB(239); + SET_EXCEPTION_STUB(240); + SET_EXCEPTION_STUB(241); + SET_EXCEPTION_STUB(242); + SET_EXCEPTION_STUB(243); + SET_EXCEPTION_STUB(244); + SET_EXCEPTION_STUB(245); + SET_EXCEPTION_STUB(246); + SET_EXCEPTION_STUB(247); + SET_EXCEPTION_STUB(248); + SET_EXCEPTION_STUB(249); + SET_EXCEPTION_STUB(250); + SET_EXCEPTION_STUB(251); + SET_EXCEPTION_STUB(252); + SET_EXCEPTION_STUB(253); + SET_EXCEPTION_STUB(254); + SET_EXCEPTION_STUB(255); #undef DESC - #undef DECLARE_EXCEPTION_STUB + #undef SET_EXCEPTION_STUB + #undef EXCEPTION_STUB } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 8cbbdd7..2423032 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -10,16 +10,23 @@ #include "kernel_state.h" #include "pic.h" +#include "page.h" + // Future user-space #include "libc.h" #include "tty.h" #include "str.h" +#include "bitmap.h" + +uint32_t page_directory[1024] __attribute__((aligned(4096))); +uint32_t page_table[1024] __attribute__((aligned(4096))); +_Static_assert(((uint32_t)page_table & 0xfff) == 0); +_Static_assert(((uint32_t)page_directory & 0xfff) == 0); static void user_mode_code(void*) { printf(str_attach("hello from user-space before interrupt :)\n")); - //__asm__ volatile ("int $0x80"); - //while (1) /* busy loop */; + __asm__ volatile ("int $0x80"); #if 0 printf(str_attach("hello from user-space before exception :)\n")); @@ -47,10 +54,10 @@ static void ring3_mode(segment_t udata_segment, segment_t ucode_segment, func_t "push %%ax\n" "mov %%esp, %%eax\n" - "push %%eax\n" // esp - "pushf\n" // eflags + "push %%eax\n" + "pushf\n" "push %[ucode]\n" - "push %[callback]\n" // instruction address to return to + "push %[callback]\n" "iret" : : [udata] "i"(udata_segment), @@ -161,6 +168,7 @@ void kernel_main(void) kernel.idt[IDT_DESC_EXCEPTION_DIVISION_ERROR] = mtrap(exception_handler_div_by_zero); kernel.idt[IDT_DESC_EXCEPTION_DOUBLE_FAULT] = mtrap(exception_handler_double_fault); kernel.idt[IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT] = mtrap(exception_handler_general_protection_fault); + kernel.idt[IDT_DESC_EXCEPTION_PAGE_FAULT] = mtrap(exception_handler_page_fault); /* IRQs */ kernel.idt[IDT_DESC_PIC1 + 0] = mint(irq_handler_0); @@ -200,11 +208,42 @@ void kernel_main(void) /* enable interrupts */ __asm__ volatile("sti"); - printf(str_attach("hello from kernel space!\n")); + printf(str_attach("setting up paging...\n")); + /** + * Paging setup + * ============ + * We align by 1<<12 because page directory and page table entries store + * addresses from bit 12-31 + * + * For now give user access to pages to avoid a page fault + */ + for (size_t i = 0; i < sizeof page_table / sizeof *page_table; i++) { + page_directory[i] = PDE_WRITE; + } + + for (size_t i = 0; i < sizeof page_table / sizeof *page_table; i++) { + page_table[i] = PTE_ADDRESS(i) | PTE_WRITE | PTE_PRESENT | PTE_USER; + } + + page_directory[0] = ((uint32_t)page_table) | PDE_WRITE | PDE_PRESENT | PDE_USER_ACCESS; + + cr3_set((uint32_t)page_directory); + cr0_flags_set(CR0_PAGING); + + printf(str_attach("done!\n")); + + printf(str_attach("starting code in ring 3...\n")); /* Finally go to ring 3 */ ring3_mode(segment(SEGMENT_USER_DATA, SEGMENT_GDT, 3), segment(SEGMENT_USER_CODE, SEGMENT_GDT, 3), user_mode_code); + + printf(str_attach("back to kernel mode...\n")); + + while (1) + /* busy loop */; + + __asm__ volatile ("hlt"); } diff --git a/src/kernel/kernel_state.c b/src/kernel/kernel_state.c index 0f58377..0c5c6fd 100644 --- a/src/kernel/kernel_state.c +++ b/src/kernel/kernel_state.c @@ -3,6 +3,8 @@ #include "kernel_state.h" +struct kernel_state kernel = { 0 }; + const struct str gdt_segment_index_str[SEGMENT_COUNT] = { [SEGMENT_NULL ] = str_attach("SEGMENT_NULL"), [SEGMENT_KERNEL_CODE] = str_attach("SEGMENT_KERNEL_CODE"), @@ -42,4 +44,3 @@ const struct str idt_desc_index_str[IDT_DESC_COUNT] = { [IDT_DESC_INTERRUPT_SYSCALL ] = str_attach("IDT_DESC_INTERRUPT_SYSCALL"), }; -struct kernel_state kernel = { 0 }; diff --git a/src/kernel/kernel_state.h b/src/kernel/kernel_state.h index 57dae53..4573796 100644 --- a/src/kernel/kernel_state.h +++ b/src/kernel/kernel_state.h @@ -6,8 +6,12 @@ #include "idt.h" #include "gdt.h" +/* defined in linker.ld */ +extern char kernel_memory_end[]; + /* * Constants for the GDT + * ===================== * */ enum gdt_segment_index : size_t { SEGMENT_NULL, @@ -22,11 +26,13 @@ extern const struct str gdt_segment_index_str[SEGMENT_COUNT]; // reverse lookup /** * Constants for the TSS + * ===================== */ constexpr size_t KERNEL_STACK_SIZE = 1024; /* * Constants for IDT descriptors + * ============================= * */ static constexpr size_t IDT_EXCEPTION_COUNT = 32; static constexpr size_t IDT_IRQ_MASTER_COUNT = 8; @@ -66,19 +72,51 @@ enum idt_desc_index : size_t { IDT_DESC_PIC1 = 32, IDT_DESC_PIC2 = IDT_DESC_PIC1 + 8, + /* Software Interrupts */ IDT_DESC_INTERRUPT_SYSCALL = 128, IDT_DESC_COUNT = 256, }; extern const struct str idt_desc_index_str[IDT_DESC_COUNT]; // reverse lookup enum -> str +/** + * hook objects (placeholder for files I guess) + * ==================== + * Processes can subscribe to objects and will be signaled when the object is + * ready. + */ +struct kernel_hook { + struct kernel_hook* next; + size_t process; +}; + +/** + * The process object + * ================== + */ +constexpr size_t PROC_MAX = 1024; + +struct kernel_process { + struct interrupt_frame frame; +}; + /** * The global kernel state object + * ============================== */ struct kernel_state { - struct tss tss; - struct gdt_table_entry gdt[SEGMENT_COUNT]; + struct tss tss; + + struct gdt_table_entry gdt[SEGMENT_COUNT]; + struct idt_gate_descriptor idt[IDT_DESC_COUNT]; - int nested_exception_counter; + + struct kernel_process processes[PROC_MAX]; + size_t process_count; + + int nested_exception_counter; + + struct kernel_hook* keypress_hooks; }; extern struct kernel_state kernel; + diff --git a/src/kernel/malloc.c b/src/kernel/malloc.c new file mode 100644 index 0000000..1cda46b --- /dev/null +++ b/src/kernel/malloc.c @@ -0,0 +1,58 @@ + +#include + +#include "kernel_state.h" +#include "libc.h" + +static constexpr size_t HEAP_SIZE = 1024*1024; +static constexpr size_t HEAP_ALIGN = 16; + +static uint8_t heap[HEAP_SIZE] = {0}; + +#if 0 +static uint8_t bitmap[HEAP_SIZE / CHAR_BIT] = {0}; + +static inline void bitmap_set(size_t i) +{ + bitmap[i / CHAR_BIT] |= 1<<(i%CHAR_BIT); +} + +static inline void bitmap_clear(size_t i) +{ + bitmap[i / CHAR_BIT] &= ~(1<<(i%CHAR_BIT)); +} + +static inline bool bitmap_get(size_t i) +{ + return bitmap[i / CHAR_BIT] & (1<<(i%CHAR_BIT)); +} +#endif + +void* kalloc(size_t size) +{ + static int n = 0; + + if (n + size > HEAP_SIZE) { + panic(str_attach("no more heap space!\n")); + } + + void* ptr = &(heap[n]); + n += size; + return ptr; +} + +void kfree(void* ptr) +{ + /* do nothing, lol */ + (void)ptr; +} + +void* krealloc(void* ptr, size_t size) +{ + void* new = kalloc(size); + if (new == NULL) + return NULL; + memmove(new, ptr, size); // this overflows but it's ok + kfree(ptr); + return new; +} diff --git a/src/kernel/page.h b/src/kernel/page.h new file mode 100644 index 0000000..a54bdbd --- /dev/null +++ b/src/kernel/page.h @@ -0,0 +1,134 @@ +#pragma once + +#include +#include "kernel_state.h" /* kernel_memory_end */ +#include "bitmap.h" + +constexpr uint32_t PAGE_SIZE = 4 * 1024; + +typedef uint32_t pageframe_t; + +typedef uint32_t cr0_flags_t; +enum cr0_flags : cr0_flags_t { + CR0_PROTECTED_MODE = 1U<<0, + CR0_MONITOR_COPROCESSOR = 1U<<1, + CR0_EMULATION = 1U<<2, + CR0_TASK_SWITCHED = 1U<<3, + CR0_EXTENSION_TYPE = 1U<<4, + CR0_NUMERIC_ERROR = 1U<<5, + CR0_WRITE_PROTECT = 1U<<16, + CR0_ALIGNMENT_MASK = 1U<<18, + CR0_NOT_WRITETHROUGH = 1U<<29, + CR0_CACHE_DISABLE = 1U<<30, + CR0_PAGING = 1U<<31, +}; + +typedef uint32_t cr4_flags_t; +enum cr4_flags : cr4_flags_t { + CR4_VME = 1U<<0, + CR4_PVI = 1U<<1, + CR4_TSD = 1U<<2, + CR4_DE = 1U<<3, + CR4_PSE = 1U<<4, + CR4_PAE = 1U<<5, + CR4_MCE = 1U<<6, + CR4_PGE = 1U<<7, + CR4_PCE = 1U<<8, + CR4_OSFXSR = 1U<<9, + CR4_OSXMMEXCPT = 1U<<10, + CR4_UMIP = 1U<<11, + CR4_LA57 = 1U<<12, + CR4_VMXE = 1U<<13, + CR4_SMXE = 1U<<14, + CR4_RESERVED_0 = 1U<<15, + CR4_FSGSBASE = 1U<<16, + CR4_PCIDE = 1U<<17, + CR4_OSXSAVE = 1U<<18, + CR4_KL = 1U<<19, + CR4_SMEP = 1U<<20, + CR4_SMAP = 1U<<21, + CR4_PKE = 1U<<22, + CR4_CET = 1U<<23, + CR4_PKS = 1U<<24, + CR4_UINTR = 1U<<25, +}; + +enum page_directory_entry_flags : pageframe_t { + PDE_PRESENT = 1<<0, + PDE_WRITE = 1<<1, + PDE_USER_ACCESS = 1<<2, + PDE_WRITE_THROUGH = 1<<3, + PDE_DISABLE_CACHE = 1<<4, + PDE_ACCESSED = 1<<5, + PDE_DIRTY = 1<<6, + PDE_AVAILABLE = 1<<6, + PDE_4MB = 1<<7, + PDE_GLOBAL = 1<<8, + PDE_PAT = 1<<12, +}; +#define PDE_ADDRESS_4KB(x) ((x)<<12) + +#define PDE_ADDRESS_4MB(x) (((x)<<13) & ~(1<<21)) + +enum page_table_entry_flags : pageframe_t { + PTE_PRESENT = 1<<0, + PTE_WRITE = 1<<1, + PTE_USER = 1<<2, + PTE_WRITE_THROUGH = 1<<3, + PTE_DISABLE_CACHE = 1<<4, + PTE_ACCESSED = 1<<5, + PTE_DIRTY = 1<<6, + PTE_PAGE_ATTRIBUTE_TABLE = 1<<7, + PTE_GLOBAL = 1<<8, +}; +#define PTE_ADDRESS(x) ((x)<<12) + +static inline void cr3_set(uint32_t page_directory) +{ + __asm__ volatile ( + "mov %[page_directory], %%eax\n\t" + "mov %%eax, %%cr3\n\t" + : /* no output */ + : /* inputs: */ [page_directory] "m" (page_directory) + : /* clobber: */ "eax" + ); +} + +/* these are macros so that they can compile on O0 due to the "i" constraint */ +#define cr0_flags_set(flags) \ + __asm__ volatile ( \ + "mov %%cr0, %%eax\n\t" \ + "or %0, %%eax\n\t" \ + "mov %%eax, %%cr0\n\t" \ + : /* no outputs */ \ + : /* inputs: */ "i"((flags)) \ + : /* clobbers: */ "eax" \ + ) + +#define cr0_flags_unset(flags) \ + __asm__ volatile ( \ + "mov %%cr0, %%eax\n\t" \ + "and %0, %%eax\n\t" \ + "mov %%eax, %%cr0\n\t" \ + : /* no outputs */ \ + : /* inputs: */ "i"(~(flags)) \ + : /* clobbers: */ "eax" \ + ) + +static pageframe_t kalloc_frame(struct bitmap* frame_map, uint32_t startframe) +{ + for (size_t i = 0; i < frame_map->bit_count; i++) { + if (bitmap_get(frame_map, i) == 0) { + bitmap_set(frame_map, i); + return (startframe + PTE_ADDRESS(i)); + } + } + return 0; +} + +static pageframe_t kfree_frame(uint32_t frame) +{ + /* TODO */ + (void)frame; + return 0; +} diff --git a/src/lib/tty.c b/src/kernel/tty.c similarity index 90% rename from src/lib/tty.c rename to src/kernel/tty.c index 350b565..9e1a0aa 100644 --- a/src/lib/tty.c +++ b/src/kernel/tty.c @@ -62,6 +62,9 @@ void terminal_scroll(int n) void terminal_putchar(int c) { + /* clear the cursor marker */ + terminal_putentryat(' ', t.color, t.column, t.row); + // TODO: implement other control characters switch (c) { @@ -83,6 +86,9 @@ void terminal_putchar(int c) if (t.row == VGA_HEIGHT) { terminal_scroll(1); } + + /* set the cursor marker */ + terminal_putentryat(' ', vga_color(VGA_COLOR_BLACK, VGA_COLOR_LIGHT_GREY), t.column, t.row); } void terminal_write(struct str str) diff --git a/src/include/tty.h b/src/kernel/tty.h similarity index 100% rename from src/include/tty.h rename to src/kernel/tty.h diff --git a/src/kernel/types.h b/src/kernel/types.h index 3f01789..37cd95e 100644 --- a/src/kernel/types.h +++ b/src/kernel/types.h @@ -11,6 +11,14 @@ typedef unsigned long long int uword_t; typedef unsigned int uword_t; #endif +struct __attribute__((packed)) interrupt_frame { + uword_t ip; + uword_t cs; + uword_t flags; + uword_t sp; + uword_t ss; +}; + /* segment selectors identifies segments either in the gdt or the ldt */ typedef uint16_t segment_t; @@ -23,5 +31,3 @@ static inline segment_t segment(uint16_t index, enum segment_ti ti, uint16_t rpl { return (index << 3) | ((ti & 0xF) << 1) | (rpl & 0xFF); } - - diff --git a/src/lib/bitmap.c b/src/lib/bitmap.c new file mode 100644 index 0000000..fa13621 --- /dev/null +++ b/src/lib/bitmap.c @@ -0,0 +1,145 @@ + +#include "bitmap.h" +#include + +static constexpr struct bitmap B = {0}; +static constexpr size_t bits_per_index = sizeof (B.data[0]) * CHAR_BIT; + +#define mask(n) ((1<<(n))-1) +_Static_assert(mask(0) == 0b0000); +_Static_assert(mask(1) == 0b0001); +_Static_assert(mask(2) == 0b0011); +_Static_assert(mask(3) == 0b0111); + +static inline int trailing_zeroes(int n) +{ + return __builtin_ctz(n); +} + +int bitmap_set_range(struct bitmap* bitmap, size_t begin, size_t end) +{ + if (end < begin) { + return bitmap_set_range(bitmap, end, begin); + } + + if (unlikely(begin > bitmap->bit_count)) { + return -1; + } + + if (unlikely(end > bitmap->bit_count)) { + return -2; + } + + /* begin and end are within the same index: */ + if ((begin / bits_per_index) == (end / bits_per_index)) { + #define expr(begin, end) (~mask((begin) % bits_per_index) & mask((end) % bits_per_index)) + _Static_assert(expr(1,6) == 0b0000111110, "bitmap range logic invalid!"); + bitmap->data[begin / bits_per_index] |= expr(begin, end); + #undef expr + } else { + bitmap->data[begin / bits_per_index] |= ~mask(begin % bits_per_index); + for (size_t i = 1 + begin/bits_per_index; + i < end/bits_per_index; + i++) + { + bitmap->data[i] |= ~0; + } + bitmap->data[end / bits_per_index] |= mask(end % bits_per_index); + } + + return 0; +} + +int bitmap_clear_range(struct bitmap* bitmap, size_t begin, size_t end) +{ + if (end < begin) { + return bitmap_set_range(bitmap, end, begin); + } + + if (unlikely(begin > bitmap->bit_count)) { + return -1; + } + + if (unlikely(end > bitmap->bit_count)) { + return -2; + } + + /* begin and end are within the same index: */ + if ((begin / bits_per_index) == (end / bits_per_index)) { + #define expr(begin, end) (~mask((begin) % bits_per_index) & mask((end) % bits_per_index)) + _Static_assert(expr(1,6) == 0b0000111110, "bitmap range logic invalid!"); + bitmap->data[begin / bits_per_index] &= ~expr(begin, end); + #undef expr + } else { + bitmap->data[begin / bits_per_index] &= mask(begin % bits_per_index); + for (size_t i = 1 + begin/bits_per_index; + i < end/bits_per_index; + i++) + { + bitmap->data[i] = 0; + } + bitmap->data[end / bits_per_index] &= ~mask(end % bits_per_index); + } + + return 0; +} + +/* This 4 am code is almost certainly wrong. No tests have been written yet. + * + * Returns 0 if range is empty. + * If range is not emtpy, it returns the offset of the first non-zero bit + * from `begin` + * + * TODO: write tests */ +int bitmap_range_empty(struct bitmap* bitmap, size_t begin, size_t end) +{ + if (end < begin) { + return bitmap_set_range(bitmap, end, begin); + } + + if (unlikely(begin > bitmap->bit_count)) { + return -1; + } + + if (unlikely(end > bitmap->bit_count)) { + return -2; + } + + /* begin and end are within the same index: */ + if ((begin / bits_per_index) == (end / bits_per_index)) { + #define expr(begin, end) (~mask((begin) % bits_per_index) & mask((end) % bits_per_index)) + _Static_assert(expr(1,6) == 0b0000111110, "bitmap range logic invalid!"); + const typeof(bitmap->data[0]) n = bitmap->data[begin / bits_per_index]; + if (n & expr(begin, end)) { + return trailing_zeroes(n) - (begin % bits_per_index) ; + }; + #undef expr + } else { + { + const typeof(bitmap->data[0]) n = bitmap->data[begin / bits_per_index]; + if (n & ~mask(begin % bits_per_index)) { + return trailing_zeroes(n) - (begin % bits_per_index); + } + } + + for (size_t i = 1 + begin/bits_per_index; + i < end/bits_per_index; + i++) + { + const typeof(bitmap->data[0]) n = bitmap->data[i]; + if (n != 0) { + return i*bits_per_index + trailing_zeroes(n); + } + } + + { + const typeof(bitmap->data[0]) n = bitmap->data[end / bits_per_index]; + if (n & mask(end % bits_per_index)) { + return (end % bits_per_index) - trailing_zeroes(n); + } + bitmap->data[end / bits_per_index] &= ~mask(end % bits_per_index); + } + } + + return 0; +} diff --git a/src/lib/bitmap_test.c b/src/lib/bitmap_test.c new file mode 100644 index 0000000..870a537 --- /dev/null +++ b/src/lib/bitmap_test.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include +#include +#include "bitmap.h" + +static int g_status = EXIT_SUCCESS; +static int test_no = 0; +static bool test_ongoing = false; + +static void bitmap_print(struct bitmap* bitmap) +{ + static constexpr size_t bits_per_index = sizeof (bitmap->data[0]) * CHAR_BIT; + fprintf(stderr, "printing bitmap... (bit_count: %zu, indices: %zu)\n", bitmap->bit_count, bitmap->bit_count / bits_per_index); + for (size_t i = 0; i < bitmap->bit_count / bits_per_index; i++) { + typeof(bitmap->data[0]) n = bitmap->data[i]; + for (size_t i = 0; i < bits_per_index; i++) { + fprintf(stderr, "%d", n & 1); + n >>= 1; + } + } + fprintf(stderr, "\n"); +} + +#define test_begin(name) _test_begin(name, __LINE__) +static void _test_begin(const char* name, int line) +{ + (void)line; // unused for now + assert(!test_ongoing); + test_ongoing = true; + printf("\n#%i - %s:\n", test_no, name); + test_no += 1; +} + +static void test_ok(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + printf("OK: "); + vprintf(format, ap); + printf("\n"); + va_end(ap); + test_ongoing = false; +} + +static void test_fail(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + printf("FAIL: "); + vprintf(format, ap); + printf("\n"); + va_end(ap); + g_status = EXIT_FAILURE; + test_ongoing = false; +} + + +int main() +{ + + test_begin("test bitmap_set()"); + do { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + constexpr size_t index = 3; + int ok = bitmap_set(&b, index); + if (ok != 0) { + test_fail("bitmap_set(%zu) returned non-zero value", index); + break; + } + bitmap_print(&b); + if (b.data[0] != 0b1000) { + test_fail("bitmap_set(%zu) failed", index); + break; + } + + test_ok("bitmap_set(%zu) ok", index); + } while (0); + + test_begin("test bitmap_get()"); + do { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + constexpr size_t index = 3; + int ok = bitmap_set(&b, index); + if (ok != 0) { + test_fail("bitmap_set(%zu) failed when testing bitmap_get(%zu)", index, index); + break; + } + bitmap_print(&b); + int v = bitmap_get(&b, 3); + if (v < 0) { + test_fail("bitmap_get(%zu) returned negative value", index); + break; + } + if (v != 1) { + test_fail("expected 1, got 0"); + break; + } + test_ok("bitmap_get(%zu) ok", index); + } while (0); + + test_begin("test bitmap_set_range() within one cell"); + { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + + constexpr size_t begin = 3; + constexpr size_t end = 6; + int ok = bitmap_set_range(&b, begin, end); + if (ok < 0) { + test_fail("bitmap_set_range returned negative value"); + goto end_set_range; + } + bitmap_print(&b); + for (size_t i = 0; i < begin; i++) { + if (bitmap_get(&b, i) == 1) { + test_fail("bitmap_set_range setting bad values"); + goto end_set_range; + } + } + for (size_t i = begin; i < end; i++) { + if (bitmap_get(&b, i) == 0) { + test_fail("bitmap_set_range setting bad values"); + goto end_set_range; + } + } + for (size_t i = end; i < b.bit_count; i++) { + if (bitmap_get(&b, i) == 1) { + test_fail("bitmap_set_range setting bad values"); + goto end_set_range; + } + } + test_ok("bitmap_set_range(..., 3, 6) ok!"); + end_set_range: + }; + + test_begin("test bitmap_set_range() across two cells"); + { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + + constexpr size_t begin = 14; + constexpr size_t end = 14 + 2 * sizeof (b.data[0]) * CHAR_BIT; + int ok = bitmap_set_range(&b, begin, end); + + if (ok < 0) { + test_fail("bitmap_set_range returned negative value"); + goto multi_cell_set_range_fail; + } + bitmap_print(&b); + + for (size_t i = 0; i < begin; i++) { + if (bitmap_get(&b, i) != 0) { + test_fail("bitmap_set_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_set_range_fail; + } + } + for (size_t i = begin; i < end; i++) { + if (bitmap_get(&b, i) != 1) { + test_fail("bitmap_set_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_set_range_fail; + } + } + for (size_t i = end; i < b.bit_count; i++) { + if (bitmap_get(&b, i) != 0) { + test_fail("bitmap_set_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_set_range_fail; + } + } + + test_ok("bitmap_set_range(..., %zu, %zu) ok!", begin, end); + + multi_cell_set_range_fail: + }; + + test_begin("test bitmap_clear_range() within one cell"); + { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + + memset(data, 0xff, sizeof data); + + constexpr size_t begin = 3; + constexpr size_t end = 7; + int ok = bitmap_clear_range(&b, begin, end); + if (ok < 0) { + test_fail("bitmap_clear_range(..., %zu, %zu) returned negative value", begin, end); + goto single_cell_clear_fail; + } + bitmap_print(&b); + + for (size_t i = 0; i < begin; i++) { + if (bitmap_get(&b, i) != 1) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto single_cell_clear_fail; + } + } + for (size_t i = begin; i < end; i++) { + if (bitmap_get(&b, i) != 0) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto single_cell_clear_fail; + } + } + for (size_t i = end; i < b.bit_count; i++) { + if (bitmap_get(&b, i) != 1) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto single_cell_clear_fail; + } + } + + test_ok("bitmap_clear_range(..., %zu, %zu) ok!", begin, end); + single_cell_clear_fail: + } + + test_begin("test bitmap_clear_range() within multiple cells"); + { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + + memset(data, 0xff, sizeof data); + + constexpr size_t begin = 3; + constexpr size_t end = begin + 2 * sizeof(b.data[0]) * CHAR_BIT; + int ok = bitmap_clear_range(&b, begin, end); + if (ok < 0) { + test_fail("bitmap_clear_range(..., %zu, %zu) returned negative value", begin, end); + goto multi_cell_clear_fail; + } + bitmap_print(&b); + + for (size_t i = 0; i < begin; i++) { + if (bitmap_get(&b, i) != 1) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_clear_fail; + } + } + for (size_t i = begin; i < end; i++) { + if (bitmap_get(&b, i) != 0) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_clear_fail; + } + } + for (size_t i = end; i < b.bit_count; i++) { + if (bitmap_get(&b, i) != 1) { + test_fail("bitmap_clear_range(..., %zu, %zu) setting bad values", begin, end); + goto multi_cell_clear_fail; + } + } + + test_ok("bitmap_clear_range(..., %zu, %zu) ok!", begin, end); + multi_cell_clear_fail: + } + + test_begin("test bitmap_empty()"); + do { + static uint32_t data[4] = {0}; + struct bitmap b = BITMAP_ATTACH(data, sizeof data); + + constexpr size_t roadblock = 14; + int ok = bitmap_set(&b, roadblock); + if (ok != 0) { + test_fail("bitmap_set(..., %zu) failed when testing bitmap_empty", roadblock); + break; + } + bitmap_print(&b); + + { + constexpr size_t begin = 0; + constexpr size_t end = roadblock - 1; + size_t v = bitmap_range_empty(&b, begin, end); + if (v != 0) { + test_fail("bitmap_range_empty(..., %zu, %zu) returned %d when it should return %d", begin, end, v, 0); + break; + } + } + + { + constexpr size_t begin = 4; + constexpr size_t end = 32; + int v = bitmap_range_empty(&b, begin, end); + if (v != roadblock - begin) { + test_fail("expected bitmap_range_empty(..., %zu, %zu) to return %d, got %d", begin, end, roadblock - begin, v); + break; + } + } + + test_ok("bitmap_range_empty() ok!"); + + } while (0); + + return g_status; +} diff --git a/src/lib/include/bitmap.h b/src/lib/include/bitmap.h new file mode 100644 index 0000000..771cde9 --- /dev/null +++ b/src/lib/include/bitmap.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include "macros.h" + +struct bitmap { + size_t bit_count; + uint32_t* data; +}; + +/* buf: buffer to use for bitmap + * buf_size: size of buffer in bytes */ +#define BITMAP_ATTACH(buf, buf_size) (struct bitmap){.bit_count = buf_size * CHAR_BIT, .data = buf} + +static inline int bitmap_set(struct bitmap* bitmap, size_t index) +{ + constexpr size_t bits_per_index = sizeof (bitmap->data[0]) * CHAR_BIT; + _Static_assert(bits_per_index == 32); + if (unlikely(index > bitmap->bit_count)) { + return -1; + } + bitmap->data[index / bits_per_index] |= (1 << (index % bits_per_index)); + return 0; +} + +static inline int bitmap_unset(struct bitmap* bitmap, size_t index) +{ + constexpr size_t bits_per_index = sizeof (bitmap->data[0]) * CHAR_BIT; + if (unlikely(index > bitmap->bit_count)) { + return -1; + } + bitmap->data[index / bits_per_index] &= ~(1 << (index % bits_per_index)); + return 0; +} + +static inline int bitmap_get(struct bitmap* bitmap, size_t index) +{ + constexpr size_t bits_per_index = sizeof (bitmap->data[0]) * CHAR_BIT; + if (unlikely(index > bitmap->bit_count)) { + return -1; + } + return !!(bitmap->data[index / bits_per_index] & (1ULL << (index % bits_per_index))); +} + +int bitmap_set_range(struct bitmap* bitmap, size_t begin, size_t end); +int bitmap_clear_range(struct bitmap* bitmap, size_t begin, size_t end); +int bitmap_range_empty(struct bitmap* bitmap, size_t begin, size_t end); diff --git a/src/lib/include/keys.h b/src/lib/include/keys.h new file mode 100644 index 0000000..43f712a --- /dev/null +++ b/src/lib/include/keys.h @@ -0,0 +1,146 @@ +#pragma once + +#include +#include +#include "str.h" + +enum key { + KEY_RELEASED = 0x80, + KEY_EXTENDED = 0xE0, + + KEY_ESCAPE = 0x01, + KEY_1 = 0x02, + KEY_2 = 0x03, + KEY_3 = 0x04, + KEY_4 = 0x05, + KEY_5 = 0x06, + KEY_6 = 0x07, + KEY_7 = 0x08, + KEY_8 = 0x09, + KEY_9 = 0x0A, + KEY_0 = 0x0B, + KEY_MINUS = 0x0C, + KEY_EQUALS = 0x0D, + KEY_BACKSPACE = 0x0E, + KEY_TAB = 0x0F, + KEY_Q = 0x10, + KEY_W = 0x11, + KEY_E = 0x12, + KEY_R = 0x13, + KEY_T = 0x14, + KEY_Y = 0x15, + KEY_U = 0x16, + KEY_I = 0x17, + KEY_O = 0x18, + KEY_P = 0x19, + KEY_SQUARE_BRACKET_LEFT = 0x1A, + KEY_SQUARE_BRACKET_RIGHT = 0x1B, + KEY_ENTER = 0x1C, + KEY_LEFT_CONTROL = 0x1D, + KEY_A = 0x1E, + KEY_S = 0x1F, + KEY_D = 0x20, + KEY_F = 0x21, + KEY_G = 0x22, + KEY_H = 0x23, + KEY_J = 0x24, + KEY_K = 0x25, + KEY_L = 0x26, + KEY_SEMICOLON = 0x27, + KEY_SINGLE_QUOTE = 0x28, + KEY_BACKTICK = 0x29, + KEY_LEFT_SHIFT = 0x2A, + KEY_BACKSLASH = 0x2B, + KEY_Z = 0x2C, + KEY_X = 0x2D, + KEY_C = 0x2E, + KEY_V = 0x2F, + KEY_B = 0x30, + KEY_N = 0x31, + KEY_M = 0x32, + KEY_COMMA = 0x33, + KEY_DOT = 0x34, + KEY_FORWARD_SLASH = 0x35, + KEY_RIGHT_SHIFT = 0x36, + KEY_KEYPAD_ASTERISK = 0x37, + KEY_LEFT_ALT = 0x38, + KEY_SPACE = 0x39, + KEY_CAPSLOCK = 0x3A, + KEY_F1 = 0x3B, + KEY_F2 = 0x3C, + KEY_F3 = 0x3D, + KEY_F4 = 0x3E, + KEY_F5 = 0x3F, + KEY_F6 = 0x40, + KEY_F7 = 0x41, + KEY_F8 = 0x42, + KEY_F9 = 0x43, + KEY_F10 = 0x44, + KEY_NUMBERLOCK = 0x45, + KEY_SCROLLLOCK = 0x46, + KEY_KEYPAD_7 = 0x47, + KEY_KEYPAD_8 = 0x48, + KEY_KEYPAD_9 = 0x49, + KEY_KEYPAD_MINUS = 0x4A, + KEY_KEYPAD_4 = 0x4B, + KEY_KEYPAD_5 = 0x4C, + KEY_KEYPAD_6 = 0x4D, + KEY_KEYPAD_PLUS = 0x4E, + KEY_KEYPAD_1 = 0x4F, + KEY_KEYPAD_2 = 0x50, + KEY_KEYPAD_3 = 0x51, + KEY_KEYPAD_0 = 0x52, + KEY_KEYPAD_DOT = 0x53, + KEY_F11 = 0x57, + KEY_F12 = 0x58, +}; +extern const struct str key_str[]; + + /* keys_default_keymap[k | KEY_MODIFIER_SHIFT] --> shift key value of key `k` */ +constexpr size_t KEY_MODIFIER_SHIFT = 0x80; + +extern const char keys_default_keymap[]; + +/* Not supported at the moment */ +enum extended_keys : uint8_t { + KEY_E_MULTIMEDIA_PREV_TRACK = 0x10, + KEY_E_MULTIMEDIA_NEXT_TRACK = 0x19, + KEY_E_KEYPAD_ENTER = 0x1C, + KEY_E_RIGHT_CONTROL = 0x1D, + KEY_E_MULTIMEDIA_MUTE = 0x20, + KEY_E_MULTIMEDIA_CALCULATOR = 0x21, + KEY_E_MULTIMEDIA_PLAY = 0x22, + KEY_E_MULTIMEDIA_STOP = 0x24, + KEY_E_MULTIMEDIA_VOLUME_DOWN = 0x2E, + KEY_E_MULTIMEDIA_VOLUME_UP = 0x30, + KEY_E_MULTIMEDIA_WWW_HOME = 0x32, + KEY_E_KEYPAD_FORWARD_SLASH = 0x35, + KEY_E_RIGHT_ALT = 0x38, + KEY_E_HOME = 0x47, + KEY_E_CURSOR_UP = 0x48, + KEY_E_PAGE_UP = 0x49, + KEY_E_CURSOR_LEFT = 0x4B, + KEY_E_CURSOR_RIGHT = 0x4D, + KEY_E_END = 0x4F, + KEY_E_CURSOR_DOWN = 0x50, + KEY_E_PAGE_DOWN = 0x51, + KEY_E_DELETE = 0x53, + KEY_E_LEFT_GUI = 0x5B, + KEY_E_RIGHT_GUI = 0x5C, + KEY_E_APPS = 0x5D, + KEY_E_ACPI_SLEEP = 0x5F, + KEY_E_ACPI_WAKE = 0x63, + KEY_E_MULTIMEDIA_WWW_SEARCH = 0x65, + KEY_E_MULTIMEDIA_WWW_REFRESH = 0x67, + KEY_E_MULTIMEDIA_WWW_STOP = 0x68, + KEY_E_MULTIMEDIA_WWW_FORWARD = 0x69, + KEY_E_MULTIMEDIA_MY_COMPUTER = 0x6B, + KEY_E_MULTIMEDIA_EMAIL = 0x6C, + KEY_E_MULTIMEDIA_MEDIA_SELECT = 0x6D, + /* TODO: implement these: + 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 pause pressed + 0x2A, 0xE0, 0x37 print screen pressed + 0xB7, 0xE0, 0xAA print screen released + */ +}; + diff --git a/src/include/libc.h b/src/lib/include/libc.h similarity index 95% rename from src/include/libc.h rename to src/lib/include/libc.h index 9e9b8e6..20ebbce 100644 --- a/src/include/libc.h +++ b/src/lib/include/libc.h @@ -2,7 +2,6 @@ #include #include "str.h" -#include "tty.h" __attribute__((noreturn)) void panic(struct str s); diff --git a/src/lib/include/macros.h b/src/lib/include/macros.h new file mode 100644 index 0000000..6f2fffa --- /dev/null +++ b/src/lib/include/macros.h @@ -0,0 +1,6 @@ + +#pragma once + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + diff --git a/src/include/printf.h b/src/lib/include/printf.h similarity index 100% rename from src/include/printf.h rename to src/lib/include/printf.h diff --git a/src/include/ring_buffer.h b/src/lib/include/ring_buffer.h similarity index 100% rename from src/include/ring_buffer.h rename to src/lib/include/ring_buffer.h diff --git a/src/include/str.h b/src/lib/include/str.h similarity index 100% rename from src/include/str.h rename to src/lib/include/str.h diff --git a/src/lib/keys.c b/src/lib/keys.c new file mode 100644 index 0000000..8193856 --- /dev/null +++ b/src/lib/keys.c @@ -0,0 +1,303 @@ + +#include "keys.h" + +const struct str ps2_key_str[] = { + [KEY_EXTENDED ] = str_attach("KEY_EXTENDED (PRESSED)"), + [KEY_ESCAPE ] = str_attach("KEY_ESCAPE (PRESSED)"), + [KEY_1 ] = str_attach("KEY_1 (PRESSED)"), + [KEY_2 ] = str_attach("KEY_2 (PRESSED)"), + [KEY_3 ] = str_attach("KEY_3 (PRESSED)"), + [KEY_4 ] = str_attach("KEY_4 (PRESSED)"), + [KEY_5 ] = str_attach("KEY_5 (PRESSED)"), + [KEY_6 ] = str_attach("KEY_6 (PRESSED)"), + [KEY_7 ] = str_attach("KEY_7 (PRESSED)"), + [KEY_8 ] = str_attach("KEY_8 (PRESSED)"), + [KEY_9 ] = str_attach("KEY_9 (PRESSED)"), + [KEY_0 ] = str_attach("KEY_0 (PRESSED)"), + [KEY_MINUS ] = str_attach("KEY_MINUS (PRESSED)"), + [KEY_EQUALS ] = str_attach("KEY_EQUALS (PRESSED)"), + [KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (PRESSED)"), + [KEY_TAB ] = str_attach("KEY_TAB (PRESSED)"), + [KEY_Q ] = str_attach("KEY_Q (PRESSED)"), + [KEY_W ] = str_attach("KEY_W (PRESSED)"), + [KEY_E ] = str_attach("KEY_E (PRESSED)"), + [KEY_R ] = str_attach("KEY_R (PRESSED)"), + [KEY_T ] = str_attach("KEY_T (PRESSED)"), + [KEY_Y ] = str_attach("KEY_Y (PRESSED)"), + [KEY_U ] = str_attach("KEY_U (PRESSED)"), + [KEY_I ] = str_attach("KEY_I (PRESSED)"), + [KEY_O ] = str_attach("KEY_O (PRESSED)"), + [KEY_P ] = str_attach("KEY_P (PRESSED)"), + [KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (PRESSED)"), + [KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (PRESSED)"), + [KEY_ENTER ] = str_attach("KEY_ENTER (PRESSED)"), + [KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (PRESSED)"), + [KEY_A ] = str_attach("KEY_A (PRESSED)"), + [KEY_S ] = str_attach("KEY_S (PRESSED)"), + [KEY_D ] = str_attach("KEY_D (PRESSED)"), + [KEY_F ] = str_attach("KEY_F (PRESSED)"), + [KEY_G ] = str_attach("KEY_G (PRESSED)"), + [KEY_H ] = str_attach("KEY_H (PRESSED)"), + [KEY_J ] = str_attach("KEY_J (PRESSED)"), + [KEY_K ] = str_attach("KEY_K (PRESSED)"), + [KEY_L ] = str_attach("KEY_L (PRESSED)"), + [KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (PRESSED)"), + [KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (PRESSED)"), + [KEY_BACKTICK ] = str_attach("KEY_BACKTICK (PRESSED)"), + [KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (PRESSED)"), + [KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (PRESSED)"), + [KEY_Z ] = str_attach("KEY_Z (PRESSED)"), + [KEY_X ] = str_attach("KEY_X (PRESSED)"), + [KEY_C ] = str_attach("KEY_C (PRESSED)"), + [KEY_V ] = str_attach("KEY_V (PRESSED)"), + [KEY_B ] = str_attach("KEY_B (PRESSED)"), + [KEY_N ] = str_attach("KEY_N (PRESSED)"), + [KEY_M ] = str_attach("KEY_M (PRESSED)"), + [KEY_COMMA ] = str_attach("KEY_COMMA (PRESSED)"), + [KEY_DOT ] = str_attach("KEY_DOT (PRESSED)"), + [KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (PRESSED)"), + [KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (PRESSED)"), + [KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (PRESSED)"), + [KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (PRESSED)"), + [KEY_SPACE ] = str_attach("KEY_SPACE (PRESSED)"), + [KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (PRESSED)"), + [KEY_F1 ] = str_attach("KEY_F1 (PRESSED)"), + [KEY_F2 ] = str_attach("KEY_F2 (PRESSED)"), + [KEY_F3 ] = str_attach("KEY_F3 (PRESSED)"), + [KEY_F4 ] = str_attach("KEY_F4 (PRESSED)"), + [KEY_F5 ] = str_attach("KEY_F5 (PRESSED)"), + [KEY_F6 ] = str_attach("KEY_F6 (PRESSED)"), + [KEY_F7 ] = str_attach("KEY_F7 (PRESSED)"), + [KEY_F8 ] = str_attach("KEY_F8 (PRESSED)"), + [KEY_F9 ] = str_attach("KEY_F9 (PRESSED)"), + [KEY_F10 ] = str_attach("KEY_F10 (PRESSED)"), + [KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (PRESSED)"), + [KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (PRESSED)"), + [KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (PRESSED)"), + [KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (PRESSED)"), + [KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (PRESSED)"), + [KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (PRESSED)"), + [KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (PRESSED)"), + [KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (PRESSED)"), + [KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (PRESSED)"), + [KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (PRESSED)"), + [KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (PRESSED)"), + [KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (PRESSED)"), + [KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (PRESSED)"), + [KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (PRESSED)"), + [KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (PRESSED)"), + [KEY_F11 ] = str_attach("KEY_F11 (PRESSED)"), + [KEY_F12 ] = str_attach("KEY_F12 (PRESSED)"), + + [KEY_RELEASED | KEY_ESCAPE ] = str_attach("KEY_ESCAPE (RELEASED)"), + [KEY_RELEASED | KEY_1 ] = str_attach("KEY_1 (RELEASED)"), + [KEY_RELEASED | KEY_2 ] = str_attach("KEY_2 (RELEASED)"), + [KEY_RELEASED | KEY_3 ] = str_attach("KEY_3 (RELEASED)"), + [KEY_RELEASED | KEY_4 ] = str_attach("KEY_4 (RELEASED)"), + [KEY_RELEASED | KEY_5 ] = str_attach("KEY_5 (RELEASED)"), + [KEY_RELEASED | KEY_6 ] = str_attach("KEY_6 (RELEASED)"), + [KEY_RELEASED | KEY_7 ] = str_attach("KEY_7 (RELEASED)"), + [KEY_RELEASED | KEY_8 ] = str_attach("KEY_8 (RELEASED)"), + [KEY_RELEASED | KEY_9 ] = str_attach("KEY_9 (RELEASED)"), + [KEY_RELEASED | KEY_0 ] = str_attach("KEY_0 (RELEASED)"), + [KEY_RELEASED | KEY_MINUS ] = str_attach("KEY_MINUS (RELEASED)"), + [KEY_RELEASED | KEY_EQUALS ] = str_attach("KEY_EQUALS (RELEASED)"), + [KEY_RELEASED | KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (RELEASED)"), + [KEY_RELEASED | KEY_TAB ] = str_attach("KEY_TAB (RELEASED)"), + [KEY_RELEASED | KEY_Q ] = str_attach("KEY_Q (RELEASED)"), + [KEY_RELEASED | KEY_W ] = str_attach("KEY_W (RELEASED)"), + [KEY_RELEASED | KEY_E ] = str_attach("KEY_E (RELEASED)"), + [KEY_RELEASED | KEY_R ] = str_attach("KEY_R (RELEASED)"), + [KEY_RELEASED | KEY_T ] = str_attach("KEY_T (RELEASED)"), + [KEY_RELEASED | KEY_Y ] = str_attach("KEY_Y (RELEASED)"), + [KEY_RELEASED | KEY_U ] = str_attach("KEY_U (RELEASED)"), + [KEY_RELEASED | KEY_I ] = str_attach("KEY_I (RELEASED)"), + [KEY_RELEASED | KEY_O ] = str_attach("KEY_O (RELEASED)"), + [KEY_RELEASED | KEY_P ] = str_attach("KEY_P (RELEASED)"), + [KEY_RELEASED | KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (RELEASED)"), + [KEY_RELEASED | KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (RELEASED)"), + [KEY_RELEASED | KEY_ENTER ] = str_attach("KEY_ENTER (RELEASED)"), + [KEY_RELEASED | KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (RELEASED)"), + [KEY_RELEASED | KEY_A ] = str_attach("KEY_A (RELEASED)"), + [KEY_RELEASED | KEY_S ] = str_attach("KEY_S (RELEASED)"), + [KEY_RELEASED | KEY_D ] = str_attach("KEY_D (RELEASED)"), + [KEY_RELEASED | KEY_F ] = str_attach("KEY_F (RELEASED)"), + [KEY_RELEASED | KEY_G ] = str_attach("KEY_G (RELEASED)"), + [KEY_RELEASED | KEY_H ] = str_attach("KEY_H (RELEASED)"), + [KEY_RELEASED | KEY_J ] = str_attach("KEY_J (RELEASED)"), + [KEY_RELEASED | KEY_K ] = str_attach("KEY_K (RELEASED)"), + [KEY_RELEASED | KEY_L ] = str_attach("KEY_L (RELEASED)"), + [KEY_RELEASED | KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (RELEASED)"), + [KEY_RELEASED | KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (RELEASED)"), + [KEY_RELEASED | KEY_BACKTICK ] = str_attach("KEY_BACKTICK (RELEASED)"), + [KEY_RELEASED | KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (RELEASED)"), + [KEY_RELEASED | KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (RELEASED)"), + [KEY_RELEASED | KEY_Z ] = str_attach("KEY_Z (RELEASED)"), + [KEY_RELEASED | KEY_X ] = str_attach("KEY_X (RELEASED)"), + [KEY_RELEASED | KEY_C ] = str_attach("KEY_C (RELEASED)"), + [KEY_RELEASED | KEY_V ] = str_attach("KEY_V (RELEASED)"), + [KEY_RELEASED | KEY_B ] = str_attach("KEY_B (RELEASED)"), + [KEY_RELEASED | KEY_N ] = str_attach("KEY_N (RELEASED)"), + [KEY_RELEASED | KEY_M ] = str_attach("KEY_M (RELEASED)"), + [KEY_RELEASED | KEY_COMMA ] = str_attach("KEY_COMMA (RELEASED)"), + [KEY_RELEASED | KEY_DOT ] = str_attach("KEY_DOT (RELEASED)"), + [KEY_RELEASED | KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (RELEASED)"), + [KEY_RELEASED | KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (RELEASED)"), + [KEY_RELEASED | KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (RELEASED)"), + [KEY_RELEASED | KEY_SPACE ] = str_attach("KEY_SPACE (RELEASED)"), + [KEY_RELEASED | KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (RELEASED)"), + [KEY_RELEASED | KEY_F1 ] = str_attach("KEY_F1 (RELEASED)"), + [KEY_RELEASED | KEY_F2 ] = str_attach("KEY_F2 (RELEASED)"), + [KEY_RELEASED | KEY_F3 ] = str_attach("KEY_F3 (RELEASED)"), + [KEY_RELEASED | KEY_F4 ] = str_attach("KEY_F4 (RELEASED)"), + [KEY_RELEASED | KEY_F5 ] = str_attach("KEY_F5 (RELEASED)"), + [KEY_RELEASED | KEY_F6 ] = str_attach("KEY_F6 (RELEASED)"), + [KEY_RELEASED | KEY_F7 ] = str_attach("KEY_F7 (RELEASED)"), + [KEY_RELEASED | KEY_F8 ] = str_attach("KEY_F8 (RELEASED)"), + [KEY_RELEASED | KEY_F9 ] = str_attach("KEY_F9 (RELEASED)"), + [KEY_RELEASED | KEY_F10 ] = str_attach("KEY_F10 (RELEASED)"), + [KEY_RELEASED | KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (RELEASED)"), + [KEY_RELEASED | KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (RELEASED)"), + [KEY_RELEASED | KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (RELEASED)"), + [KEY_RELEASED | KEY_F11 ] = str_attach("KEY_F11 (RELEASED)"), + [KEY_RELEASED | KEY_F12 ] = str_attach("KEY_F12 (RELEASED)"), +}; + +const char ps2_key_char[] = { + [KEY_1 ] = '1', + [KEY_2 ] = '2', + [KEY_3 ] = '3', + [KEY_4 ] = '4', + [KEY_5 ] = '5', + [KEY_6 ] = '6', + [KEY_7 ] = '7', + [KEY_8 ] = '8', + [KEY_9 ] = '9', + [KEY_0 ] = '0', + + [KEY_A ] = 'a', + [KEY_B ] = 'b', + [KEY_C ] = 'c', + [KEY_D ] = 'd', + [KEY_E ] = 'e', + [KEY_F ] = 'f', + [KEY_G ] = 'g', + [KEY_H ] = 'h', + [KEY_I ] = 'i', + [KEY_J ] = 'j', + [KEY_K ] = 'k', + [KEY_L ] = 'l', + [KEY_M ] = 'm', + [KEY_N ] = 'n', + [KEY_O ] = 'o', + [KEY_P ] = 'p', + [KEY_Q ] = 'q', + [KEY_R ] = 'r', + [KEY_S ] = 's', + [KEY_T ] = 't', + [KEY_U ] = 'u', + [KEY_V ] = 'v', + [KEY_W ] = 'w', + [KEY_X ] = 'x', + [KEY_Y ] = 'y', + [KEY_Z ] = 'z', + + [KEY_MINUS ] = '-', + [KEY_EQUALS ] = '=', + [KEY_BACKSPACE ] = '\b', + [KEY_TAB ] = '\t', + [KEY_SQUARE_BRACKET_LEFT ] = '[', + [KEY_SQUARE_BRACKET_RIGHT ] = ']', + [KEY_ENTER ] = '\n', + [KEY_SEMICOLON ] = ';', + [KEY_SINGLE_QUOTE ] = '\'', + [KEY_BACKTICK ] = '`', + [KEY_BACKSLASH ] = '\\', + [KEY_COMMA ] = ',', + [KEY_DOT ] = '.', + [KEY_FORWARD_SLASH ] = '/', + [KEY_KEYPAD_ASTERISK ] = '*', + [KEY_SPACE ] = ' ', + + [KEY_KEYPAD_0 ] = '0', + [KEY_KEYPAD_1 ] = '1', + [KEY_KEYPAD_2 ] = '2', + [KEY_KEYPAD_3 ] = '3', + [KEY_KEYPAD_4 ] = '4', + [KEY_KEYPAD_5 ] = '5', + [KEY_KEYPAD_6 ] = '6', + [KEY_KEYPAD_7 ] = '7', + [KEY_KEYPAD_8 ] = '8', + [KEY_KEYPAD_9 ] = '9', + [KEY_KEYPAD_DOT ] = '.', + [KEY_KEYPAD_MINUS ] = '-', + [KEY_KEYPAD_PLUS ] = '+', + + [KEY_MODIFIER_SHIFT | KEY_0] = ')', + [KEY_MODIFIER_SHIFT | KEY_9] = '(', + [KEY_MODIFIER_SHIFT | KEY_8] = '*', + [KEY_MODIFIER_SHIFT | KEY_7] = '&', + [KEY_MODIFIER_SHIFT | KEY_6] = '^', + [KEY_MODIFIER_SHIFT | KEY_5] = '%', + [KEY_MODIFIER_SHIFT | KEY_4] = '$', + [KEY_MODIFIER_SHIFT | KEY_3] = '#', + [KEY_MODIFIER_SHIFT | KEY_2] = '@', + [KEY_MODIFIER_SHIFT | KEY_1] = '!', + + [KEY_MODIFIER_SHIFT | KEY_A] = 'A', + [KEY_MODIFIER_SHIFT | KEY_B] = 'B', + [KEY_MODIFIER_SHIFT | KEY_C] = 'C', + [KEY_MODIFIER_SHIFT | KEY_D] = 'D', + [KEY_MODIFIER_SHIFT | KEY_E] = 'E', + [KEY_MODIFIER_SHIFT | KEY_F] = 'F', + [KEY_MODIFIER_SHIFT | KEY_G] = 'G', + [KEY_MODIFIER_SHIFT | KEY_H] = 'H', + [KEY_MODIFIER_SHIFT | KEY_I] = 'I', + [KEY_MODIFIER_SHIFT | KEY_J] = 'J', + [KEY_MODIFIER_SHIFT | KEY_K] = 'K', + [KEY_MODIFIER_SHIFT | KEY_L] = 'L', + [KEY_MODIFIER_SHIFT | KEY_M] = 'M', + [KEY_MODIFIER_SHIFT | KEY_N] = 'N', + [KEY_MODIFIER_SHIFT | KEY_O] = 'O', + [KEY_MODIFIER_SHIFT | KEY_P] = 'P', + [KEY_MODIFIER_SHIFT | KEY_Q] = 'Q', + [KEY_MODIFIER_SHIFT | KEY_R] = 'R', + [KEY_MODIFIER_SHIFT | KEY_S] = 'S', + [KEY_MODIFIER_SHIFT | KEY_T] = 'T', + [KEY_MODIFIER_SHIFT | KEY_U] = 'U', + [KEY_MODIFIER_SHIFT | KEY_V] = 'V', + [KEY_MODIFIER_SHIFT | KEY_W] = 'W', + [KEY_MODIFIER_SHIFT | KEY_X] = 'X', + [KEY_MODIFIER_SHIFT | KEY_Y] = 'Y', + [KEY_MODIFIER_SHIFT | KEY_Z] = 'Z', + + [KEY_MODIFIER_SHIFT | KEY_MINUS ] = '_', + [KEY_MODIFIER_SHIFT | KEY_EQUALS ] = '+', + [KEY_MODIFIER_SHIFT | KEY_BACKSPACE ] = '\b', + [KEY_MODIFIER_SHIFT | KEY_TAB ] = '\t', + [KEY_MODIFIER_SHIFT | KEY_SQUARE_BRACKET_LEFT ] = '{', + [KEY_MODIFIER_SHIFT | KEY_SQUARE_BRACKET_RIGHT ] = '}', + [KEY_MODIFIER_SHIFT | KEY_ENTER ] = '\n', + [KEY_MODIFIER_SHIFT | KEY_SEMICOLON ] = ':', + [KEY_MODIFIER_SHIFT | KEY_SINGLE_QUOTE ] = '"', + [KEY_MODIFIER_SHIFT | KEY_BACKTICK ] = '~', + [KEY_MODIFIER_SHIFT | KEY_BACKSLASH ] = '|', + [KEY_MODIFIER_SHIFT | KEY_COMMA ] = '<', + [KEY_MODIFIER_SHIFT | KEY_DOT ] = '>', + [KEY_MODIFIER_SHIFT | KEY_FORWARD_SLASH ] = '?', + [KEY_MODIFIER_SHIFT | KEY_SPACE ] = ' ', +}; + diff --git a/src/lib/libc.c b/src/lib/libc.c index 6e95f44..5d048a0 100644 --- a/src/lib/libc.c +++ b/src/lib/libc.c @@ -5,7 +5,7 @@ #include #include -#include "tty.h" +#include "kernel/tty.h" #include "str.h" /* diff --git a/src/lib/printf.c b/src/lib/printf.c index eddc791..c29352a 100644 --- a/src/lib/printf.c +++ b/src/lib/printf.c @@ -1,8 +1,10 @@ #include #include +#include #include "libc.h" +#include "kernel/tty.h" typedef int (*printf_function)(struct printf_state* s, void* data); @@ -132,6 +134,42 @@ static int print_char(struct printf_state* s) } } +static int print_cs(struct printf_state* s) +{ + int n; + int sum = 0; + + const uint8_t cs = va_arg(s->ap, uint32_t); + + const struct str cs_bit_names[] = { + [0] = str_attach("ACCESSED"), + [1] = str_attach("RW"), + [2] = str_attach("DC"), + [3] = str_attach("EXEC"), + [4] = str_attach("DESCRIPTOR"), + [7] = str_attach("PRESENT"), + }; + + for (size_t i = 0; i < sizeof cs_bit_names / sizeof *cs_bit_names; i++) { + if (cs & (1<>5) & 0b11; + n = printf(str_attach("DPL({uint})"), ring); + if (n == -1) { + return -1; + } + sum += n; + + return sum; +} + static int parse_format_cmd(struct printf_state* s) { int c; @@ -174,6 +212,9 @@ static int parse_format_cmd(struct printf_state* s) case 'char': return print_char(s); + case 'cs': + return print_cs(s); + default: return -1; } diff --git a/src/test/test_ring_buffer.c b/src/lib/ring_buffer_test.c similarity index 100% rename from src/test/test_ring_buffer.c rename to src/lib/ring_buffer_test.c