This commit is contained in:
2024-08-11 19:11:44 +02:00
parent c2ea7f1446
commit 04b67a0ad5
28 changed files with 1666 additions and 487 deletions

View File

@@ -1,14 +1,13 @@
.SUFFIXES: .SUFFIXES:
.PHONY: all clean .PHONY: all clean test tests
all: myos.iso all: myos.iso
SOURCE_DIR := src SOURCE_DIR := src
BUILD_DIR := build BUILD_DIR := build
CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \ CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \
--workdir="/scratch" \ --workdir="/scratch" \
--network=none \ --network=none \
@@ -16,17 +15,23 @@ CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \
-t \ -t \
cc-i686:latest cc-i686:latest
QEMU := qemu-system-i386
QEMU_FLAGS := -d int -no-reboot
CC := $(CONTAINER_CMD) i686-elf-gcc CC := $(CONTAINER_CMD) i686-elf-gcc
LD := $(CONTAINER_CMD) i686-elf-ld LD := $(CONTAINER_CMD) i686-elf-ld
AS := $(CONTAINER_CMD) i686-elf-as AS := $(CONTAINER_CMD) i686-elf-as
AR := $(CONTAINER_CMD) i686-elf-ar 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') ASM_SOURCES := $(shell find $(SOURCE_DIR) -name '*.S')
OBJECTS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.S=.o)) OBJECTS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.S=.o))
DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.d)) 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-function
CFLAGS += -Wno-unused-variable CFLAGS += -Wno-unused-variable
ASFLAGS := ASFLAGS :=
@@ -37,7 +42,7 @@ ASFLAGS :=
#$(info DEPENDS is $(DEPENDS)) #$(info DEPENDS is $(DEPENDS))
run: myos.iso 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 cross-compiler: cross-compiler-image/Dockerfile
podman build cross-compiler-image -t cc-i686 podman build cross-compiler-image -t cc-i686
@@ -74,21 +79,23 @@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.S Makefile
# TESTS # # TESTS #
################### ###################
TEST_SOURCE_DIR := $(SOURCE_DIR)/test TEST_BUILD_DIR := $(BUILD_DIR)/tests
TEST_BUILD_DIR := $(BUILD_DIR)/test
TEST_SOURCES := $(shell find $(TEST_SOURCE_DIR) -name 'test_*.c') #TEST_SOURCES := $(shell find $(SOURCE_DIR) -name '*_test.c')
TEST_DEPENDS := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=.d)) #TEST_DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=.d))
TEST_OUTPUT := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=)) #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) 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) -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) @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 $@ $^
./$@

4
kernel.d Normal file
View File

@@ -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

View File

@@ -50,6 +50,7 @@ SECTIONS
.data BLOCK(4K) : ALIGN(4K) .data BLOCK(4K) : ALIGN(4K)
{ {
*(.data) *(.data)
kernel_data_end = .;
} }
/* Read-write data (uninitialized) and stack */ /* Read-write data (uninitialized) and stack */
@@ -57,6 +58,8 @@ SECTIONS
{ {
*(COMMON) *(COMMON)
*(.bss) *(.bss)
kernel_memory_end = .;
} }
/* The compiler may produce other sections, by default it will put them in /* The compiler may produce other sections, by default it will put them in

View File

@@ -32,178 +32,3 @@ const struct str ps2_response_str[] = {
[PS2RESPONSE_RESEND ] = str_attach("PS2RESPONSE_RESEND"), [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)"),
};

View File

@@ -176,6 +176,9 @@ enum ps2_keys {
}; };
extern const struct str ps2_key_str[]; 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 { enum ps2_extended_key : uint8_t {
KEY_E_MULTIMEDIA_PREV_TRACK = 0x10, KEY_E_MULTIMEDIA_PREV_TRACK = 0x10,
KEY_E_MULTIMEDIA_NEXT_TRACK = 0x19, KEY_E_MULTIMEDIA_NEXT_TRACK = 0x19,

View File

@@ -1,4 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include "libc.h" #include "libc.h"
#include "tty.h" #include "tty.h"
#include "interrupts.h" #include "interrupts.h"
@@ -22,7 +23,7 @@ static void print_interrupt_frame(struct interrupt_frame* f)
"Interrupt frame:\n" "Interrupt frame:\n"
"================\n" "================\n"
"ip: {x32}\n" "ip: {x32}\n"
"cs: {x32}\n" "cs: {x32} == {cs}\n"
"flags: {x32}\n" "flags: {x32}\n"
"sp: {x32}\n" "sp: {x32}\n"
"ss: {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 */ /* not an interrupt/exception, but called by exception stubs */
__attribute__((noreturn)) __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); terminal_set_color(VGA_COLOR_WHITE, VGA_COLOR_RED);
printf(str_attach("non-implemented exception {i32} occurred\n"), exception_no); printf(str_attach("non-implemented exception {i32} occurred\n"), exception_no);
struct str name = idt_desc_index_str[exception_no]; struct str name = idt_desc_index_str[exception_no];
if (name.len != 0) { 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) { if (frame != NULL) {
print_interrupt_frame(frame); print_interrupt_frame(frame);
} else { } else {
@@ -94,6 +96,7 @@ void exception_handler_div_by_zero(struct interrupt_frame* frame)
panic(str_attach("div by zero occured :(")); panic(str_attach("div by zero occured :("));
} }
#include "page.h"
__attribute__((interrupt, noreturn)) __attribute__((interrupt, noreturn))
void exception_handler_page_fault(struct interrupt_frame* frame, int err) 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); terminal_set_color(VGA_COLOR_WHITE, VGA_COLOR_RED);
printf(str_attach( printf(str_attach(
"page fault :(, err: 0x{x32}\n"), "page fault :(, err: 0x{x32}: ["),
err, err);
gdt_segment_index_str[err/8]);
/* 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<<i)) && error_names[i].data) {
printf(str_attach("{str} | "), error_names[i]);
}
}
printf(str_attach("0]\n"));
print_interrupt_frame(frame);
__asm__ volatile("cli; hlt"); __asm__ volatile("cli; hlt");
__builtin_unreachable(); __builtin_unreachable();
} }
@@ -158,16 +193,54 @@ static void irq_stub(struct interrupt_frame* frame, int line)
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame* frame) { irq_stub(frame, 0); } __attribute__((interrupt)) void irq_handler_0(struct interrupt_frame* frame) { irq_stub(frame, 0); }
/* IRQ1 - keyboard controller */ /* IRQ1 - keyboard controller */
#include "ps2-keyboard.h" #include "keys.h"
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame* frame)
__attribute__((interrupt))
void irq_handler_1(struct interrupt_frame* frame)
{ {
/* TODO: move keyboard logic to a separate compilation unit */ /* TODO: move keyboard logic to a separate compilation unit */
(void)frame; (void)frame;
for (struct kernel_hook* p = kernel.keypress_hooks;
p != NULL;
p = p->next)
{
// TODO
//proc_send(p->);
}
#if 0
uint8_t key = inb(PIC_KEYBOARD); uint8_t key = inb(PIC_KEYBOARD);
bool released = key & KEY_RELEASED; 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); outb(PIC1_COMMAND, OCW2_EOI);
} }
@@ -191,12 +264,13 @@ __attribute__((interrupt)) void irq_handler_15(struct interrupt_frame* frame) {
* Exception Stubs * Exception Stubs
* =============== * ===============
*/ */
#define EXCEPTION_STUB(n) exception_stub_##n
#define DEFINE_EXCEPTION_STUB(n) \ #define DEFINE_EXCEPTION_STUB(n) \
__attribute__((interrupt, noreturn)) \ __attribute__((interrupt, noreturn)) \
void EXCEPTION_STUB(n)(struct interrupt_frame* frame) \ void EXCEPTION_STUB(n)(struct interrupt_frame* frame, uint32_t err) \
{ \ { \
panic_exception_not_implemented(frame, n); \ panic_exception_not_implemented(frame, n, err); \
} }
DEFINE_EXCEPTION_STUB(0) DEFINE_EXCEPTION_STUB(0)

View File

@@ -2,14 +2,6 @@
#include "types.h" #include "types.h"
struct __attribute__((packed)) interrupt_frame {
uword_t ip;
uword_t cs;
uword_t flags;
uword_t sp;
uword_t ss;
};
/* /*
* Exceptions * Exceptions
* ==========*/ * ==========*/
@@ -22,6 +14,9 @@ void exception_handler_general_protection_fault(struct interrupt_frame* frame, i
__attribute__((interrupt, noreturn)) __attribute__((interrupt, noreturn))
void exception_handler_double_fault(struct interrupt_frame* frame); 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)) __attribute__((interrupt, noreturn))
void exception_default(struct interrupt_frame* frame); 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_DPL_3, \
IDT_GATE_TYPE_TRAP32) IDT_GATE_TYPE_TRAP32)
#define DECLARE_EXCEPTION_STUB(n) \ #define SET_EXCEPTION_STUB(n) \
__attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*); \ __attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*, uint32_t err); \
idt[n] = DESC(EXCEPTION_STUB(n)) idt[n] = DESC(EXCEPTION_STUB(n))
DECLARE_EXCEPTION_STUB(0); SET_EXCEPTION_STUB(0);
DECLARE_EXCEPTION_STUB(1); SET_EXCEPTION_STUB(1);
DECLARE_EXCEPTION_STUB(2); SET_EXCEPTION_STUB(2);
DECLARE_EXCEPTION_STUB(3); SET_EXCEPTION_STUB(3);
DECLARE_EXCEPTION_STUB(4); SET_EXCEPTION_STUB(4);
DECLARE_EXCEPTION_STUB(5); SET_EXCEPTION_STUB(5);
DECLARE_EXCEPTION_STUB(6); SET_EXCEPTION_STUB(6);
DECLARE_EXCEPTION_STUB(7); SET_EXCEPTION_STUB(7);
DECLARE_EXCEPTION_STUB(8); SET_EXCEPTION_STUB(8);
DECLARE_EXCEPTION_STUB(9); SET_EXCEPTION_STUB(9);
DECLARE_EXCEPTION_STUB(10); SET_EXCEPTION_STUB(10);
DECLARE_EXCEPTION_STUB(11); SET_EXCEPTION_STUB(11);
DECLARE_EXCEPTION_STUB(12); SET_EXCEPTION_STUB(12);
DECLARE_EXCEPTION_STUB(13); SET_EXCEPTION_STUB(13);
DECLARE_EXCEPTION_STUB(14); SET_EXCEPTION_STUB(14);
DECLARE_EXCEPTION_STUB(15); SET_EXCEPTION_STUB(15);
DECLARE_EXCEPTION_STUB(16); SET_EXCEPTION_STUB(16);
DECLARE_EXCEPTION_STUB(17); SET_EXCEPTION_STUB(17);
DECLARE_EXCEPTION_STUB(18); SET_EXCEPTION_STUB(18);
DECLARE_EXCEPTION_STUB(19); SET_EXCEPTION_STUB(19);
DECLARE_EXCEPTION_STUB(20); SET_EXCEPTION_STUB(20);
DECLARE_EXCEPTION_STUB(21); SET_EXCEPTION_STUB(21);
DECLARE_EXCEPTION_STUB(22); SET_EXCEPTION_STUB(22);
DECLARE_EXCEPTION_STUB(23); SET_EXCEPTION_STUB(23);
DECLARE_EXCEPTION_STUB(24); SET_EXCEPTION_STUB(24);
DECLARE_EXCEPTION_STUB(25); SET_EXCEPTION_STUB(25);
DECLARE_EXCEPTION_STUB(26); SET_EXCEPTION_STUB(26);
DECLARE_EXCEPTION_STUB(27); SET_EXCEPTION_STUB(27);
DECLARE_EXCEPTION_STUB(28); SET_EXCEPTION_STUB(28);
DECLARE_EXCEPTION_STUB(29); SET_EXCEPTION_STUB(29);
DECLARE_EXCEPTION_STUB(30); SET_EXCEPTION_STUB(30);
DECLARE_EXCEPTION_STUB(31); SET_EXCEPTION_STUB(31);
DECLARE_EXCEPTION_STUB(32); SET_EXCEPTION_STUB(32);
DECLARE_EXCEPTION_STUB(33); SET_EXCEPTION_STUB(33);
DECLARE_EXCEPTION_STUB(34); SET_EXCEPTION_STUB(34);
DECLARE_EXCEPTION_STUB(35); SET_EXCEPTION_STUB(35);
DECLARE_EXCEPTION_STUB(36); SET_EXCEPTION_STUB(36);
DECLARE_EXCEPTION_STUB(37); SET_EXCEPTION_STUB(37);
DECLARE_EXCEPTION_STUB(38); SET_EXCEPTION_STUB(38);
DECLARE_EXCEPTION_STUB(39); SET_EXCEPTION_STUB(39);
DECLARE_EXCEPTION_STUB(40); SET_EXCEPTION_STUB(40);
DECLARE_EXCEPTION_STUB(41); SET_EXCEPTION_STUB(41);
DECLARE_EXCEPTION_STUB(42); SET_EXCEPTION_STUB(42);
DECLARE_EXCEPTION_STUB(43); SET_EXCEPTION_STUB(43);
DECLARE_EXCEPTION_STUB(44); SET_EXCEPTION_STUB(44);
DECLARE_EXCEPTION_STUB(45); SET_EXCEPTION_STUB(45);
DECLARE_EXCEPTION_STUB(46); SET_EXCEPTION_STUB(46);
DECLARE_EXCEPTION_STUB(47); SET_EXCEPTION_STUB(47);
DECLARE_EXCEPTION_STUB(48); SET_EXCEPTION_STUB(48);
DECLARE_EXCEPTION_STUB(49); SET_EXCEPTION_STUB(49);
DECLARE_EXCEPTION_STUB(50); SET_EXCEPTION_STUB(50);
DECLARE_EXCEPTION_STUB(51); SET_EXCEPTION_STUB(51);
DECLARE_EXCEPTION_STUB(52); SET_EXCEPTION_STUB(52);
DECLARE_EXCEPTION_STUB(53); SET_EXCEPTION_STUB(53);
DECLARE_EXCEPTION_STUB(54); SET_EXCEPTION_STUB(54);
DECLARE_EXCEPTION_STUB(55); SET_EXCEPTION_STUB(55);
DECLARE_EXCEPTION_STUB(56); SET_EXCEPTION_STUB(56);
DECLARE_EXCEPTION_STUB(57); SET_EXCEPTION_STUB(57);
DECLARE_EXCEPTION_STUB(58); SET_EXCEPTION_STUB(58);
DECLARE_EXCEPTION_STUB(59); SET_EXCEPTION_STUB(59);
DECLARE_EXCEPTION_STUB(60); SET_EXCEPTION_STUB(60);
DECLARE_EXCEPTION_STUB(61); SET_EXCEPTION_STUB(61);
DECLARE_EXCEPTION_STUB(62); SET_EXCEPTION_STUB(62);
DECLARE_EXCEPTION_STUB(63); SET_EXCEPTION_STUB(63);
DECLARE_EXCEPTION_STUB(64); SET_EXCEPTION_STUB(64);
DECLARE_EXCEPTION_STUB(65); SET_EXCEPTION_STUB(65);
DECLARE_EXCEPTION_STUB(66); SET_EXCEPTION_STUB(66);
DECLARE_EXCEPTION_STUB(67); SET_EXCEPTION_STUB(67);
DECLARE_EXCEPTION_STUB(68); SET_EXCEPTION_STUB(68);
DECLARE_EXCEPTION_STUB(69); SET_EXCEPTION_STUB(69);
DECLARE_EXCEPTION_STUB(70); SET_EXCEPTION_STUB(70);
DECLARE_EXCEPTION_STUB(71); SET_EXCEPTION_STUB(71);
DECLARE_EXCEPTION_STUB(72); SET_EXCEPTION_STUB(72);
DECLARE_EXCEPTION_STUB(73); SET_EXCEPTION_STUB(73);
DECLARE_EXCEPTION_STUB(74); SET_EXCEPTION_STUB(74);
DECLARE_EXCEPTION_STUB(75); SET_EXCEPTION_STUB(75);
DECLARE_EXCEPTION_STUB(76); SET_EXCEPTION_STUB(76);
DECLARE_EXCEPTION_STUB(77); SET_EXCEPTION_STUB(77);
DECLARE_EXCEPTION_STUB(78); SET_EXCEPTION_STUB(78);
DECLARE_EXCEPTION_STUB(79); SET_EXCEPTION_STUB(79);
DECLARE_EXCEPTION_STUB(80); SET_EXCEPTION_STUB(80);
DECLARE_EXCEPTION_STUB(81); SET_EXCEPTION_STUB(81);
DECLARE_EXCEPTION_STUB(82); SET_EXCEPTION_STUB(82);
DECLARE_EXCEPTION_STUB(83); SET_EXCEPTION_STUB(83);
DECLARE_EXCEPTION_STUB(84); SET_EXCEPTION_STUB(84);
DECLARE_EXCEPTION_STUB(85); SET_EXCEPTION_STUB(85);
DECLARE_EXCEPTION_STUB(86); SET_EXCEPTION_STUB(86);
DECLARE_EXCEPTION_STUB(87); SET_EXCEPTION_STUB(87);
DECLARE_EXCEPTION_STUB(88); SET_EXCEPTION_STUB(88);
DECLARE_EXCEPTION_STUB(89); SET_EXCEPTION_STUB(89);
DECLARE_EXCEPTION_STUB(90); SET_EXCEPTION_STUB(90);
DECLARE_EXCEPTION_STUB(91); SET_EXCEPTION_STUB(91);
DECLARE_EXCEPTION_STUB(92); SET_EXCEPTION_STUB(92);
DECLARE_EXCEPTION_STUB(93); SET_EXCEPTION_STUB(93);
DECLARE_EXCEPTION_STUB(94); SET_EXCEPTION_STUB(94);
DECLARE_EXCEPTION_STUB(95); SET_EXCEPTION_STUB(95);
DECLARE_EXCEPTION_STUB(96); SET_EXCEPTION_STUB(96);
DECLARE_EXCEPTION_STUB(97); SET_EXCEPTION_STUB(97);
DECLARE_EXCEPTION_STUB(98); SET_EXCEPTION_STUB(98);
DECLARE_EXCEPTION_STUB(99); SET_EXCEPTION_STUB(99);
DECLARE_EXCEPTION_STUB(100); SET_EXCEPTION_STUB(100);
DECLARE_EXCEPTION_STUB(101); SET_EXCEPTION_STUB(101);
DECLARE_EXCEPTION_STUB(102); SET_EXCEPTION_STUB(102);
DECLARE_EXCEPTION_STUB(103); SET_EXCEPTION_STUB(103);
DECLARE_EXCEPTION_STUB(104); SET_EXCEPTION_STUB(104);
DECLARE_EXCEPTION_STUB(105); SET_EXCEPTION_STUB(105);
DECLARE_EXCEPTION_STUB(106); SET_EXCEPTION_STUB(106);
DECLARE_EXCEPTION_STUB(107); SET_EXCEPTION_STUB(107);
DECLARE_EXCEPTION_STUB(108); SET_EXCEPTION_STUB(108);
DECLARE_EXCEPTION_STUB(109); SET_EXCEPTION_STUB(109);
DECLARE_EXCEPTION_STUB(110); SET_EXCEPTION_STUB(110);
DECLARE_EXCEPTION_STUB(111); SET_EXCEPTION_STUB(111);
DECLARE_EXCEPTION_STUB(112); SET_EXCEPTION_STUB(112);
DECLARE_EXCEPTION_STUB(113); SET_EXCEPTION_STUB(113);
DECLARE_EXCEPTION_STUB(114); SET_EXCEPTION_STUB(114);
DECLARE_EXCEPTION_STUB(115); SET_EXCEPTION_STUB(115);
DECLARE_EXCEPTION_STUB(116); SET_EXCEPTION_STUB(116);
DECLARE_EXCEPTION_STUB(117); SET_EXCEPTION_STUB(117);
DECLARE_EXCEPTION_STUB(118); SET_EXCEPTION_STUB(118);
DECLARE_EXCEPTION_STUB(119); SET_EXCEPTION_STUB(119);
DECLARE_EXCEPTION_STUB(120); SET_EXCEPTION_STUB(120);
DECLARE_EXCEPTION_STUB(121); SET_EXCEPTION_STUB(121);
DECLARE_EXCEPTION_STUB(122); SET_EXCEPTION_STUB(122);
DECLARE_EXCEPTION_STUB(123); SET_EXCEPTION_STUB(123);
DECLARE_EXCEPTION_STUB(124); SET_EXCEPTION_STUB(124);
DECLARE_EXCEPTION_STUB(125); SET_EXCEPTION_STUB(125);
DECLARE_EXCEPTION_STUB(126); SET_EXCEPTION_STUB(126);
DECLARE_EXCEPTION_STUB(127); SET_EXCEPTION_STUB(127);
DECLARE_EXCEPTION_STUB(128); SET_EXCEPTION_STUB(128);
DECLARE_EXCEPTION_STUB(129); SET_EXCEPTION_STUB(129);
DECLARE_EXCEPTION_STUB(130); SET_EXCEPTION_STUB(130);
DECLARE_EXCEPTION_STUB(131); SET_EXCEPTION_STUB(131);
DECLARE_EXCEPTION_STUB(132); SET_EXCEPTION_STUB(132);
DECLARE_EXCEPTION_STUB(133); SET_EXCEPTION_STUB(133);
DECLARE_EXCEPTION_STUB(134); SET_EXCEPTION_STUB(134);
DECLARE_EXCEPTION_STUB(135); SET_EXCEPTION_STUB(135);
DECLARE_EXCEPTION_STUB(136); SET_EXCEPTION_STUB(136);
DECLARE_EXCEPTION_STUB(137); SET_EXCEPTION_STUB(137);
DECLARE_EXCEPTION_STUB(138); SET_EXCEPTION_STUB(138);
DECLARE_EXCEPTION_STUB(139); SET_EXCEPTION_STUB(139);
DECLARE_EXCEPTION_STUB(140); SET_EXCEPTION_STUB(140);
DECLARE_EXCEPTION_STUB(141); SET_EXCEPTION_STUB(141);
DECLARE_EXCEPTION_STUB(142); SET_EXCEPTION_STUB(142);
DECLARE_EXCEPTION_STUB(143); SET_EXCEPTION_STUB(143);
DECLARE_EXCEPTION_STUB(144); SET_EXCEPTION_STUB(144);
DECLARE_EXCEPTION_STUB(145); SET_EXCEPTION_STUB(145);
DECLARE_EXCEPTION_STUB(146); SET_EXCEPTION_STUB(146);
DECLARE_EXCEPTION_STUB(147); SET_EXCEPTION_STUB(147);
DECLARE_EXCEPTION_STUB(148); SET_EXCEPTION_STUB(148);
DECLARE_EXCEPTION_STUB(149); SET_EXCEPTION_STUB(149);
DECLARE_EXCEPTION_STUB(150); SET_EXCEPTION_STUB(150);
DECLARE_EXCEPTION_STUB(151); SET_EXCEPTION_STUB(151);
DECLARE_EXCEPTION_STUB(152); SET_EXCEPTION_STUB(152);
DECLARE_EXCEPTION_STUB(153); SET_EXCEPTION_STUB(153);
DECLARE_EXCEPTION_STUB(154); SET_EXCEPTION_STUB(154);
DECLARE_EXCEPTION_STUB(155); SET_EXCEPTION_STUB(155);
DECLARE_EXCEPTION_STUB(156); SET_EXCEPTION_STUB(156);
DECLARE_EXCEPTION_STUB(157); SET_EXCEPTION_STUB(157);
DECLARE_EXCEPTION_STUB(158); SET_EXCEPTION_STUB(158);
DECLARE_EXCEPTION_STUB(159); SET_EXCEPTION_STUB(159);
DECLARE_EXCEPTION_STUB(160); SET_EXCEPTION_STUB(160);
DECLARE_EXCEPTION_STUB(161); SET_EXCEPTION_STUB(161);
DECLARE_EXCEPTION_STUB(162); SET_EXCEPTION_STUB(162);
DECLARE_EXCEPTION_STUB(163); SET_EXCEPTION_STUB(163);
DECLARE_EXCEPTION_STUB(164); SET_EXCEPTION_STUB(164);
DECLARE_EXCEPTION_STUB(165); SET_EXCEPTION_STUB(165);
DECLARE_EXCEPTION_STUB(166); SET_EXCEPTION_STUB(166);
DECLARE_EXCEPTION_STUB(167); SET_EXCEPTION_STUB(167);
DECLARE_EXCEPTION_STUB(168); SET_EXCEPTION_STUB(168);
DECLARE_EXCEPTION_STUB(169); SET_EXCEPTION_STUB(169);
DECLARE_EXCEPTION_STUB(170); SET_EXCEPTION_STUB(170);
DECLARE_EXCEPTION_STUB(171); SET_EXCEPTION_STUB(171);
DECLARE_EXCEPTION_STUB(172); SET_EXCEPTION_STUB(172);
DECLARE_EXCEPTION_STUB(173); SET_EXCEPTION_STUB(173);
DECLARE_EXCEPTION_STUB(174); SET_EXCEPTION_STUB(174);
DECLARE_EXCEPTION_STUB(175); SET_EXCEPTION_STUB(175);
DECLARE_EXCEPTION_STUB(176); SET_EXCEPTION_STUB(176);
DECLARE_EXCEPTION_STUB(177); SET_EXCEPTION_STUB(177);
DECLARE_EXCEPTION_STUB(178); SET_EXCEPTION_STUB(178);
DECLARE_EXCEPTION_STUB(179); SET_EXCEPTION_STUB(179);
DECLARE_EXCEPTION_STUB(180); SET_EXCEPTION_STUB(180);
DECLARE_EXCEPTION_STUB(181); SET_EXCEPTION_STUB(181);
DECLARE_EXCEPTION_STUB(182); SET_EXCEPTION_STUB(182);
DECLARE_EXCEPTION_STUB(183); SET_EXCEPTION_STUB(183);
DECLARE_EXCEPTION_STUB(184); SET_EXCEPTION_STUB(184);
DECLARE_EXCEPTION_STUB(185); SET_EXCEPTION_STUB(185);
DECLARE_EXCEPTION_STUB(186); SET_EXCEPTION_STUB(186);
DECLARE_EXCEPTION_STUB(187); SET_EXCEPTION_STUB(187);
DECLARE_EXCEPTION_STUB(188); SET_EXCEPTION_STUB(188);
DECLARE_EXCEPTION_STUB(189); SET_EXCEPTION_STUB(189);
DECLARE_EXCEPTION_STUB(190); SET_EXCEPTION_STUB(190);
DECLARE_EXCEPTION_STUB(191); SET_EXCEPTION_STUB(191);
DECLARE_EXCEPTION_STUB(192); SET_EXCEPTION_STUB(192);
DECLARE_EXCEPTION_STUB(193); SET_EXCEPTION_STUB(193);
DECLARE_EXCEPTION_STUB(194); SET_EXCEPTION_STUB(194);
DECLARE_EXCEPTION_STUB(195); SET_EXCEPTION_STUB(195);
DECLARE_EXCEPTION_STUB(196); SET_EXCEPTION_STUB(196);
DECLARE_EXCEPTION_STUB(197); SET_EXCEPTION_STUB(197);
DECLARE_EXCEPTION_STUB(198); SET_EXCEPTION_STUB(198);
DECLARE_EXCEPTION_STUB(199); SET_EXCEPTION_STUB(199);
DECLARE_EXCEPTION_STUB(200); SET_EXCEPTION_STUB(200);
DECLARE_EXCEPTION_STUB(201); SET_EXCEPTION_STUB(201);
DECLARE_EXCEPTION_STUB(202); SET_EXCEPTION_STUB(202);
DECLARE_EXCEPTION_STUB(203); SET_EXCEPTION_STUB(203);
DECLARE_EXCEPTION_STUB(204); SET_EXCEPTION_STUB(204);
DECLARE_EXCEPTION_STUB(205); SET_EXCEPTION_STUB(205);
DECLARE_EXCEPTION_STUB(206); SET_EXCEPTION_STUB(206);
DECLARE_EXCEPTION_STUB(207); SET_EXCEPTION_STUB(207);
DECLARE_EXCEPTION_STUB(208); SET_EXCEPTION_STUB(208);
DECLARE_EXCEPTION_STUB(209); SET_EXCEPTION_STUB(209);
DECLARE_EXCEPTION_STUB(210); SET_EXCEPTION_STUB(210);
DECLARE_EXCEPTION_STUB(211); SET_EXCEPTION_STUB(211);
DECLARE_EXCEPTION_STUB(212); SET_EXCEPTION_STUB(212);
DECLARE_EXCEPTION_STUB(213); SET_EXCEPTION_STUB(213);
DECLARE_EXCEPTION_STUB(214); SET_EXCEPTION_STUB(214);
DECLARE_EXCEPTION_STUB(215); SET_EXCEPTION_STUB(215);
DECLARE_EXCEPTION_STUB(216); SET_EXCEPTION_STUB(216);
DECLARE_EXCEPTION_STUB(217); SET_EXCEPTION_STUB(217);
DECLARE_EXCEPTION_STUB(218); SET_EXCEPTION_STUB(218);
DECLARE_EXCEPTION_STUB(219); SET_EXCEPTION_STUB(219);
DECLARE_EXCEPTION_STUB(220); SET_EXCEPTION_STUB(220);
DECLARE_EXCEPTION_STUB(221); SET_EXCEPTION_STUB(221);
DECLARE_EXCEPTION_STUB(222); SET_EXCEPTION_STUB(222);
DECLARE_EXCEPTION_STUB(223); SET_EXCEPTION_STUB(223);
DECLARE_EXCEPTION_STUB(224); SET_EXCEPTION_STUB(224);
DECLARE_EXCEPTION_STUB(225); SET_EXCEPTION_STUB(225);
DECLARE_EXCEPTION_STUB(226); SET_EXCEPTION_STUB(226);
DECLARE_EXCEPTION_STUB(227); SET_EXCEPTION_STUB(227);
DECLARE_EXCEPTION_STUB(228); SET_EXCEPTION_STUB(228);
DECLARE_EXCEPTION_STUB(229); SET_EXCEPTION_STUB(229);
DECLARE_EXCEPTION_STUB(230); SET_EXCEPTION_STUB(230);
DECLARE_EXCEPTION_STUB(231); SET_EXCEPTION_STUB(231);
DECLARE_EXCEPTION_STUB(232); SET_EXCEPTION_STUB(232);
DECLARE_EXCEPTION_STUB(233); SET_EXCEPTION_STUB(233);
DECLARE_EXCEPTION_STUB(234); SET_EXCEPTION_STUB(234);
DECLARE_EXCEPTION_STUB(235); SET_EXCEPTION_STUB(235);
DECLARE_EXCEPTION_STUB(236); SET_EXCEPTION_STUB(236);
DECLARE_EXCEPTION_STUB(237); SET_EXCEPTION_STUB(237);
DECLARE_EXCEPTION_STUB(238); SET_EXCEPTION_STUB(238);
DECLARE_EXCEPTION_STUB(239); SET_EXCEPTION_STUB(239);
DECLARE_EXCEPTION_STUB(240); SET_EXCEPTION_STUB(240);
DECLARE_EXCEPTION_STUB(241); SET_EXCEPTION_STUB(241);
DECLARE_EXCEPTION_STUB(242); SET_EXCEPTION_STUB(242);
DECLARE_EXCEPTION_STUB(243); SET_EXCEPTION_STUB(243);
DECLARE_EXCEPTION_STUB(244); SET_EXCEPTION_STUB(244);
DECLARE_EXCEPTION_STUB(245); SET_EXCEPTION_STUB(245);
DECLARE_EXCEPTION_STUB(246); SET_EXCEPTION_STUB(246);
DECLARE_EXCEPTION_STUB(247); SET_EXCEPTION_STUB(247);
DECLARE_EXCEPTION_STUB(248); SET_EXCEPTION_STUB(248);
DECLARE_EXCEPTION_STUB(249); SET_EXCEPTION_STUB(249);
DECLARE_EXCEPTION_STUB(250); SET_EXCEPTION_STUB(250);
DECLARE_EXCEPTION_STUB(251); SET_EXCEPTION_STUB(251);
DECLARE_EXCEPTION_STUB(252); SET_EXCEPTION_STUB(252);
DECLARE_EXCEPTION_STUB(253); SET_EXCEPTION_STUB(253);
DECLARE_EXCEPTION_STUB(254); SET_EXCEPTION_STUB(254);
DECLARE_EXCEPTION_STUB(255); SET_EXCEPTION_STUB(255);
#undef DESC #undef DESC
#undef DECLARE_EXCEPTION_STUB #undef SET_EXCEPTION_STUB
#undef EXCEPTION_STUB
} }

View File

@@ -10,16 +10,23 @@
#include "kernel_state.h" #include "kernel_state.h"
#include "pic.h" #include "pic.h"
#include "page.h"
// Future user-space // Future user-space
#include "libc.h" #include "libc.h"
#include "tty.h" #include "tty.h"
#include "str.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*) static void user_mode_code(void*)
{ {
printf(str_attach("hello from user-space before interrupt :)\n")); printf(str_attach("hello from user-space before interrupt :)\n"));
//__asm__ volatile ("int $0x80"); __asm__ volatile ("int $0x80");
//while (1) /* busy loop */;
#if 0 #if 0
printf(str_attach("hello from user-space before exception :)\n")); 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" "push %%ax\n"
"mov %%esp, %%eax\n" "mov %%esp, %%eax\n"
"push %%eax\n" // esp "push %%eax\n"
"pushf\n" // eflags "pushf\n"
"push %[ucode]\n" "push %[ucode]\n"
"push %[callback]\n" // instruction address to return to "push %[callback]\n"
"iret" "iret"
: :
: [udata] "i"(udata_segment), : [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_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_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_GENERAL_PROTECTION_FAULT] = mtrap(exception_handler_general_protection_fault);
kernel.idt[IDT_DESC_EXCEPTION_PAGE_FAULT] = mtrap(exception_handler_page_fault);
/* IRQs */ /* IRQs */
kernel.idt[IDT_DESC_PIC1 + 0] = mint(irq_handler_0); kernel.idt[IDT_DESC_PIC1 + 0] = mint(irq_handler_0);
@@ -200,11 +208,42 @@ void kernel_main(void)
/* enable interrupts */ /* enable interrupts */
__asm__ volatile("sti"); __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 */ /* Finally go to ring 3 */
ring3_mode(segment(SEGMENT_USER_DATA, SEGMENT_GDT, 3), ring3_mode(segment(SEGMENT_USER_DATA, SEGMENT_GDT, 3),
segment(SEGMENT_USER_CODE, SEGMENT_GDT, 3), segment(SEGMENT_USER_CODE, SEGMENT_GDT, 3),
user_mode_code); user_mode_code);
printf(str_attach("back to kernel mode...\n"));
while (1)
/* busy loop */;
__asm__ volatile ("hlt");
} }

View File

@@ -3,6 +3,8 @@
#include "kernel_state.h" #include "kernel_state.h"
struct kernel_state kernel = { 0 };
const struct str gdt_segment_index_str[SEGMENT_COUNT] = { const struct str gdt_segment_index_str[SEGMENT_COUNT] = {
[SEGMENT_NULL ] = str_attach("SEGMENT_NULL"), [SEGMENT_NULL ] = str_attach("SEGMENT_NULL"),
[SEGMENT_KERNEL_CODE] = str_attach("SEGMENT_KERNEL_CODE"), [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"), [IDT_DESC_INTERRUPT_SYSCALL ] = str_attach("IDT_DESC_INTERRUPT_SYSCALL"),
}; };
struct kernel_state kernel = { 0 };

View File

@@ -6,8 +6,12 @@
#include "idt.h" #include "idt.h"
#include "gdt.h" #include "gdt.h"
/* defined in linker.ld */
extern char kernel_memory_end[];
/* /*
* Constants for the GDT * Constants for the GDT
* =====================
* */ * */
enum gdt_segment_index : size_t { enum gdt_segment_index : size_t {
SEGMENT_NULL, SEGMENT_NULL,
@@ -22,11 +26,13 @@ extern const struct str gdt_segment_index_str[SEGMENT_COUNT]; // reverse lookup
/** /**
* Constants for the TSS * Constants for the TSS
* =====================
*/ */
constexpr size_t KERNEL_STACK_SIZE = 1024; constexpr size_t KERNEL_STACK_SIZE = 1024;
/* /*
* Constants for IDT descriptors * Constants for IDT descriptors
* =============================
* */ * */
static constexpr size_t IDT_EXCEPTION_COUNT = 32; static constexpr size_t IDT_EXCEPTION_COUNT = 32;
static constexpr size_t IDT_IRQ_MASTER_COUNT = 8; 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_PIC1 = 32,
IDT_DESC_PIC2 = IDT_DESC_PIC1 + 8, IDT_DESC_PIC2 = IDT_DESC_PIC1 + 8,
/* Software Interrupts */
IDT_DESC_INTERRUPT_SYSCALL = 128, IDT_DESC_INTERRUPT_SYSCALL = 128,
IDT_DESC_COUNT = 256, IDT_DESC_COUNT = 256,
}; };
extern const struct str idt_desc_index_str[IDT_DESC_COUNT]; // reverse lookup enum -> str 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 * The global kernel state object
* ==============================
*/ */
struct kernel_state { struct kernel_state {
struct tss tss; struct tss tss;
struct gdt_table_entry gdt[SEGMENT_COUNT];
struct gdt_table_entry gdt[SEGMENT_COUNT];
struct idt_gate_descriptor idt[IDT_DESC_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; extern struct kernel_state kernel;

58
src/kernel/malloc.c Normal file
View File

@@ -0,0 +1,58 @@
#include <limits.h>
#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;
}

134
src/kernel/page.h Normal file
View File

@@ -0,0 +1,134 @@
#pragma once
#include <stdint.h>
#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;
}

View File

@@ -62,6 +62,9 @@ void terminal_scroll(int n)
void terminal_putchar(int c) void terminal_putchar(int c)
{ {
/* clear the cursor marker */
terminal_putentryat(' ', t.color, t.column, t.row);
// TODO: implement other control characters // TODO: implement other control characters
switch (c) { switch (c) {
@@ -83,6 +86,9 @@ void terminal_putchar(int c)
if (t.row == VGA_HEIGHT) { if (t.row == VGA_HEIGHT) {
terminal_scroll(1); 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) void terminal_write(struct str str)

View File

@@ -11,6 +11,14 @@ typedef unsigned long long int uword_t;
typedef unsigned int uword_t; typedef unsigned int uword_t;
#endif #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 */ /* segment selectors identifies segments either in the gdt or the ldt */
typedef uint16_t segment_t; 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); return (index << 3) | ((ti & 0xF) << 1) | (rpl & 0xFF);
} }

145
src/lib/bitmap.c Normal file
View File

@@ -0,0 +1,145 @@
#include "bitmap.h"
#include <limits.h>
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;
}

296
src/lib/bitmap_test.c Normal file
View File

@@ -0,0 +1,296 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#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;
}

49
src/lib/include/bitmap.h Normal file
View File

@@ -0,0 +1,49 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <limits.h>
#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);

146
src/lib/include/keys.h Normal file
View File

@@ -0,0 +1,146 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#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
*/
};

View File

@@ -2,7 +2,6 @@
#include <stddef.h> #include <stddef.h>
#include "str.h" #include "str.h"
#include "tty.h"
__attribute__((noreturn)) __attribute__((noreturn))
void panic(struct str s); void panic(struct str s);

6
src/lib/include/macros.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

303
src/lib/keys.c Normal file
View File

@@ -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 ] = ' ',
};

View File

@@ -5,7 +5,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "tty.h" #include "kernel/tty.h"
#include "str.h" #include "str.h"
/* /*

View File

@@ -1,8 +1,10 @@
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits.h>
#include <stdint.h>
#include "libc.h" #include "libc.h"
#include "kernel/tty.h"
typedef int (*printf_function)(struct printf_state* s, void* data); 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<<i) && cs_bit_names[i].data) {
n = printf(str_attach("{str} | "), cs_bit_names[i]);
if (n == -1) {
return -1;
}
sum += n;
}
}
unsigned int ring = (cs>>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) static int parse_format_cmd(struct printf_state* s)
{ {
int c; int c;
@@ -174,6 +212,9 @@ static int parse_format_cmd(struct printf_state* s)
case 'char': case 'char':
return print_char(s); return print_char(s);
case 'cs':
return print_cs(s);
default: default:
return -1; return -1;
} }