Add keypress detection

This commit is contained in:
2024-08-11 13:03:13 +02:00
parent 1e385af53c
commit c2ea7f1446
14 changed files with 1652 additions and 127 deletions

View File

@@ -8,6 +8,7 @@ all: myos.iso
SOURCE_DIR := src
BUILD_DIR := build
CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \
--workdir="/scratch" \
--network=none \
@@ -20,7 +21,7 @@ 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 '*.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))
@@ -60,7 +61,6 @@ $(BUILD_DIR)/kernel/interrupts.o: $(SOURCE_DIR)/kernel/interrupts.c Makefile
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -mgeneral-regs-only -mno-red-zone $< -o $@
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c Makefile
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) $< -o $@
@@ -69,3 +69,26 @@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.S Makefile
@mkdir -p $(@D)
$(AS) $(ASFLAGS) $< -o $@
###################
# TESTS #
###################
TEST_SOURCE_DIR := $(SOURCE_DIR)/test
TEST_BUILD_DIR := $(BUILD_DIR)/test
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=))
$(info TEST_SOURCES is $(TEST_SOURCES))
$(info TEST_OUTPUT is $(TEST_OUTPUT))
tests: $(TEST_OUTPUT)
-include $(TEST_DEPENDS)
$(TEST_BUILD_DIR)/test_%: $(TEST_SOURCE_DIR)/test_%.c $(SOURCE_DIR)/lib/%.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 $@ $^

View File

@@ -1,7 +1,7 @@
#include "ps2-keyboard.h"
const struct str ps2_cmd_str[PS2CMD_COUNT] = {
const struct str ps2_cmd_str[] = {
[PS2CMD_SET_LEDS ] = str_attach("PS2CMD_SET_LEDS"),
[PS2CMD_ECHO ] = str_attach("PS2CMD_ECHO"),
[PS2CMD_GET_SCAN ] = str_attach("PS2CMD_GET_SCAN"),
@@ -21,7 +21,7 @@ const struct str ps2_cmd_str[PS2CMD_COUNT] = {
[PS2CMD_RESEND_RESET_AND_SELF_TEST] = str_attach("PS2CMD_RESEND_RESET_AND_SELF_TEST"),
};
const struct str ps2_response_str[PS2RESPONSE_COUNT] = {
const struct str ps2_response_str[] = {
[PS2RESPONSE_ERROR_1 ] = str_attach("PS2RESPONSE_ERROR_1"),
[PS2RESPONSE_ERROR_2 ] = str_attach("PS2RESPONSE_ERROR_2"),
[PS2RESPONSE_SELF_TEST_PASSED ] = str_attach("PS2RESPONSE_SELF_TEST_PASSED"),
@@ -32,4 +32,178 @@ const struct str ps2_response_str[PS2RESPONSE_COUNT] = {
[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

@@ -1,9 +1,10 @@
#pragma once
#include "str.h"
#include <stdint.h>
/* commands that the system sends to the keyboard */
enum ps2_cmd {
enum ps2_cmd : uint8_t {
/* Set LEDs */
PS2CMD_SET_LEDS = 0xED,
@@ -55,12 +56,11 @@ enum ps2_cmd {
/* Reset and start self-test */
PS2CMD_RESEND_RESET_AND_SELF_TEST = 0xFF,
PS2CMD_COUNT,
};
extern const struct str ps2_cmd_str[];
/* commands that the keyboard sends to the system */
enum ps2_response {
enum ps2_response : uint8_t {
/* Self test passed (sent after "0xFF (reset)" command or keyboard power up) */
PS2RESPONSE_SELF_TEST_PASSED = 0xAA,
@@ -81,11 +81,141 @@ enum ps2_response {
/* Key detection error or internal buffer overrun */
PS2RESPONSE_ERROR_1 = 0x00,
PS2RESPONSE_ERROR_2 = 0xFF,
};
extern const struct str ps2_response_str[];
PS2RESPONSE_COUNT,
enum ps2_keys {
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 ps2_key_str[];
enum ps2_extended_key : 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
*/
};
extern const struct str ps2_cmd_str[PS2CMD_COUNT];
extern const struct str ps2_response_str[PS2RESPONSE_COUNT];

22
src/include/ring_buffer.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
constexpr size_t RING_BUFFER_MAX = 1024;
struct ring_buffer {
size_t head;
size_t tail;
size_t len;
size_t entry_size;
uint8_t data[RING_BUFFER_MAX];
};
#define make_ring_buffer(type) (struct ring_buffer){.entry_size = sizeof(type)}
size_t ring_buffer_remaining(struct ring_buffer* q);
bool ring_buffer_push(struct ring_buffer* q, const void* data);
bool ring_buffer_get(struct ring_buffer* q, void* out);

View File

@@ -4,7 +4,9 @@
#include "interrupts.h"
#include "kernel_state.h"
#define EXCEPTION_DEPTH_MAX 5
#include "pic.h"
#define EXCEPTION_DEPTH_MAX 3
struct __attribute__((packed)) interrupt_frame {
uword_t ip;
@@ -31,6 +33,25 @@ static void print_interrupt_frame(struct interrupt_frame* f)
f->ss);
}
/* not an interrupt/exception, but called by exception stubs */
__attribute__((noreturn))
static void panic_exception_not_implemented(struct interrupt_frame* frame, int exception_no)
{
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);
}
if (frame != NULL) {
print_interrupt_frame(frame);
} else {
printf(str_attach("(no interrupt frame)n"));
}
__asm__ volatile("cli; hlt");
__builtin_unreachable();
}
/**
* Exceptions
* ==========
@@ -89,18 +110,6 @@ void exception_handler_page_fault(struct interrupt_frame* frame, int err)
__builtin_unreachable();
}
__attribute__((interrupt, noreturn))
void exception_default(struct interrupt_frame* frame)
{
(void)frame;
if (kernel.nested_exception_counter++ > EXCEPTION_DEPTH_MAX) {
panic(str_attach("fatal: too many nested exceptions\n"));
}
panic(str_attach("non-implemented exception occured"));
kernel.nested_exception_counter = 0;
}
/**
* Interrupts
* ==========
@@ -129,16 +138,320 @@ void interrupt_handler_1(struct interrupt_frame* frame)
kernel.nested_exception_counter = 0;
}
__attribute__((interrupt))
void interrupt_handler_userspace_exit(struct interrupt_frame* frame)
/*
* IRQs
* ====
* */
static void irq_stub(struct interrupt_frame* frame, int line)
{
(void)frame;
(void)line;
if (kernel.nested_exception_counter++ > EXCEPTION_DEPTH_MAX) {
panic(str_attach("fatal: too many nested exceptions\n"));
}
(void)frame;
printf(str_attach("interrupt_handler_userspace_exit called!\n"));
//printf(str_attach("irq handler {i32} called!\n"), line);
outb(PIC1_COMMAND, OCW2_EOI);
kernel.nested_exception_counter = 0;
}
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame* frame) { irq_stub(frame, 0); }
/* IRQ1 - keyboard controller */
#include "ps2-keyboard.h"
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame* frame)
{
/* TODO: move keyboard logic to a separate compilation unit */
(void)frame;
uint8_t key = inb(PIC_KEYBOARD);
bool released = key & KEY_RELEASED;
printf(str_attach("key {str}\n"), ps2_key_str[key]);
outb(PIC1_COMMAND, OCW2_EOI);
}
__attribute__((interrupt)) void irq_handler_2(struct interrupt_frame* frame) { irq_stub(frame, 2); }
__attribute__((interrupt)) void irq_handler_3(struct interrupt_frame* frame) { irq_stub(frame, 3); }
__attribute__((interrupt)) void irq_handler_4(struct interrupt_frame* frame) { irq_stub(frame, 4); }
__attribute__((interrupt)) void irq_handler_5(struct interrupt_frame* frame) { irq_stub(frame, 5); }
__attribute__((interrupt)) void irq_handler_6(struct interrupt_frame* frame) { irq_stub(frame, 6); }
__attribute__((interrupt)) void irq_handler_7(struct interrupt_frame* frame) { irq_stub(frame, 7); }
__attribute__((interrupt)) void irq_handler_8(struct interrupt_frame* frame) { irq_stub(frame, 8); }
__attribute__((interrupt)) void irq_handler_9(struct interrupt_frame* frame) { irq_stub(frame, 9); }
__attribute__((interrupt)) void irq_handler_10(struct interrupt_frame* frame) { irq_stub(frame, 10); }
__attribute__((interrupt)) void irq_handler_11(struct interrupt_frame* frame) { irq_stub(frame, 11); }
__attribute__((interrupt)) void irq_handler_12(struct interrupt_frame* frame) { irq_stub(frame, 12); }
__attribute__((interrupt)) void irq_handler_13(struct interrupt_frame* frame) { irq_stub(frame, 13); }
__attribute__((interrupt)) void irq_handler_14(struct interrupt_frame* frame) { irq_stub(frame, 14); }
__attribute__((interrupt)) void irq_handler_15(struct interrupt_frame* frame) { irq_stub(frame, 15); }
/**
* Exception Stubs
* ===============
*/
#define DEFINE_EXCEPTION_STUB(n) \
__attribute__((interrupt, noreturn)) \
void EXCEPTION_STUB(n)(struct interrupt_frame* frame) \
{ \
panic_exception_not_implemented(frame, n); \
}
DEFINE_EXCEPTION_STUB(0)
DEFINE_EXCEPTION_STUB(1)
DEFINE_EXCEPTION_STUB(2)
DEFINE_EXCEPTION_STUB(3)
DEFINE_EXCEPTION_STUB(4)
DEFINE_EXCEPTION_STUB(5)
DEFINE_EXCEPTION_STUB(6)
DEFINE_EXCEPTION_STUB(7)
DEFINE_EXCEPTION_STUB(8)
DEFINE_EXCEPTION_STUB(9)
DEFINE_EXCEPTION_STUB(10)
DEFINE_EXCEPTION_STUB(11)
DEFINE_EXCEPTION_STUB(12)
DEFINE_EXCEPTION_STUB(13)
DEFINE_EXCEPTION_STUB(14)
DEFINE_EXCEPTION_STUB(15)
DEFINE_EXCEPTION_STUB(16)
DEFINE_EXCEPTION_STUB(17)
DEFINE_EXCEPTION_STUB(18)
DEFINE_EXCEPTION_STUB(19)
DEFINE_EXCEPTION_STUB(20)
DEFINE_EXCEPTION_STUB(21)
DEFINE_EXCEPTION_STUB(22)
DEFINE_EXCEPTION_STUB(23)
DEFINE_EXCEPTION_STUB(24)
DEFINE_EXCEPTION_STUB(25)
DEFINE_EXCEPTION_STUB(26)
DEFINE_EXCEPTION_STUB(27)
DEFINE_EXCEPTION_STUB(28)
DEFINE_EXCEPTION_STUB(29)
DEFINE_EXCEPTION_STUB(30)
DEFINE_EXCEPTION_STUB(31)
DEFINE_EXCEPTION_STUB(32)
DEFINE_EXCEPTION_STUB(33)
DEFINE_EXCEPTION_STUB(34)
DEFINE_EXCEPTION_STUB(35)
DEFINE_EXCEPTION_STUB(36)
DEFINE_EXCEPTION_STUB(37)
DEFINE_EXCEPTION_STUB(38)
DEFINE_EXCEPTION_STUB(39)
DEFINE_EXCEPTION_STUB(40)
DEFINE_EXCEPTION_STUB(41)
DEFINE_EXCEPTION_STUB(42)
DEFINE_EXCEPTION_STUB(43)
DEFINE_EXCEPTION_STUB(44)
DEFINE_EXCEPTION_STUB(45)
DEFINE_EXCEPTION_STUB(46)
DEFINE_EXCEPTION_STUB(47)
DEFINE_EXCEPTION_STUB(48)
DEFINE_EXCEPTION_STUB(49)
DEFINE_EXCEPTION_STUB(50)
DEFINE_EXCEPTION_STUB(51)
DEFINE_EXCEPTION_STUB(52)
DEFINE_EXCEPTION_STUB(53)
DEFINE_EXCEPTION_STUB(54)
DEFINE_EXCEPTION_STUB(55)
DEFINE_EXCEPTION_STUB(56)
DEFINE_EXCEPTION_STUB(57)
DEFINE_EXCEPTION_STUB(58)
DEFINE_EXCEPTION_STUB(59)
DEFINE_EXCEPTION_STUB(60)
DEFINE_EXCEPTION_STUB(61)
DEFINE_EXCEPTION_STUB(62)
DEFINE_EXCEPTION_STUB(63)
DEFINE_EXCEPTION_STUB(64)
DEFINE_EXCEPTION_STUB(65)
DEFINE_EXCEPTION_STUB(66)
DEFINE_EXCEPTION_STUB(67)
DEFINE_EXCEPTION_STUB(68)
DEFINE_EXCEPTION_STUB(69)
DEFINE_EXCEPTION_STUB(70)
DEFINE_EXCEPTION_STUB(71)
DEFINE_EXCEPTION_STUB(72)
DEFINE_EXCEPTION_STUB(73)
DEFINE_EXCEPTION_STUB(74)
DEFINE_EXCEPTION_STUB(75)
DEFINE_EXCEPTION_STUB(76)
DEFINE_EXCEPTION_STUB(77)
DEFINE_EXCEPTION_STUB(78)
DEFINE_EXCEPTION_STUB(79)
DEFINE_EXCEPTION_STUB(80)
DEFINE_EXCEPTION_STUB(81)
DEFINE_EXCEPTION_STUB(82)
DEFINE_EXCEPTION_STUB(83)
DEFINE_EXCEPTION_STUB(84)
DEFINE_EXCEPTION_STUB(85)
DEFINE_EXCEPTION_STUB(86)
DEFINE_EXCEPTION_STUB(87)
DEFINE_EXCEPTION_STUB(88)
DEFINE_EXCEPTION_STUB(89)
DEFINE_EXCEPTION_STUB(90)
DEFINE_EXCEPTION_STUB(91)
DEFINE_EXCEPTION_STUB(92)
DEFINE_EXCEPTION_STUB(93)
DEFINE_EXCEPTION_STUB(94)
DEFINE_EXCEPTION_STUB(95)
DEFINE_EXCEPTION_STUB(96)
DEFINE_EXCEPTION_STUB(97)
DEFINE_EXCEPTION_STUB(98)
DEFINE_EXCEPTION_STUB(99)
DEFINE_EXCEPTION_STUB(100)
DEFINE_EXCEPTION_STUB(101)
DEFINE_EXCEPTION_STUB(102)
DEFINE_EXCEPTION_STUB(103)
DEFINE_EXCEPTION_STUB(104)
DEFINE_EXCEPTION_STUB(105)
DEFINE_EXCEPTION_STUB(106)
DEFINE_EXCEPTION_STUB(107)
DEFINE_EXCEPTION_STUB(108)
DEFINE_EXCEPTION_STUB(109)
DEFINE_EXCEPTION_STUB(110)
DEFINE_EXCEPTION_STUB(111)
DEFINE_EXCEPTION_STUB(112)
DEFINE_EXCEPTION_STUB(113)
DEFINE_EXCEPTION_STUB(114)
DEFINE_EXCEPTION_STUB(115)
DEFINE_EXCEPTION_STUB(116)
DEFINE_EXCEPTION_STUB(117)
DEFINE_EXCEPTION_STUB(118)
DEFINE_EXCEPTION_STUB(119)
DEFINE_EXCEPTION_STUB(120)
DEFINE_EXCEPTION_STUB(121)
DEFINE_EXCEPTION_STUB(122)
DEFINE_EXCEPTION_STUB(123)
DEFINE_EXCEPTION_STUB(124)
DEFINE_EXCEPTION_STUB(125)
DEFINE_EXCEPTION_STUB(126)
DEFINE_EXCEPTION_STUB(127)
DEFINE_EXCEPTION_STUB(128)
DEFINE_EXCEPTION_STUB(129)
DEFINE_EXCEPTION_STUB(130)
DEFINE_EXCEPTION_STUB(131)
DEFINE_EXCEPTION_STUB(132)
DEFINE_EXCEPTION_STUB(133)
DEFINE_EXCEPTION_STUB(134)
DEFINE_EXCEPTION_STUB(135)
DEFINE_EXCEPTION_STUB(136)
DEFINE_EXCEPTION_STUB(137)
DEFINE_EXCEPTION_STUB(138)
DEFINE_EXCEPTION_STUB(139)
DEFINE_EXCEPTION_STUB(140)
DEFINE_EXCEPTION_STUB(141)
DEFINE_EXCEPTION_STUB(142)
DEFINE_EXCEPTION_STUB(143)
DEFINE_EXCEPTION_STUB(144)
DEFINE_EXCEPTION_STUB(145)
DEFINE_EXCEPTION_STUB(146)
DEFINE_EXCEPTION_STUB(147)
DEFINE_EXCEPTION_STUB(148)
DEFINE_EXCEPTION_STUB(149)
DEFINE_EXCEPTION_STUB(150)
DEFINE_EXCEPTION_STUB(151)
DEFINE_EXCEPTION_STUB(152)
DEFINE_EXCEPTION_STUB(153)
DEFINE_EXCEPTION_STUB(154)
DEFINE_EXCEPTION_STUB(155)
DEFINE_EXCEPTION_STUB(156)
DEFINE_EXCEPTION_STUB(157)
DEFINE_EXCEPTION_STUB(158)
DEFINE_EXCEPTION_STUB(159)
DEFINE_EXCEPTION_STUB(160)
DEFINE_EXCEPTION_STUB(161)
DEFINE_EXCEPTION_STUB(162)
DEFINE_EXCEPTION_STUB(163)
DEFINE_EXCEPTION_STUB(164)
DEFINE_EXCEPTION_STUB(165)
DEFINE_EXCEPTION_STUB(166)
DEFINE_EXCEPTION_STUB(167)
DEFINE_EXCEPTION_STUB(168)
DEFINE_EXCEPTION_STUB(169)
DEFINE_EXCEPTION_STUB(170)
DEFINE_EXCEPTION_STUB(171)
DEFINE_EXCEPTION_STUB(172)
DEFINE_EXCEPTION_STUB(173)
DEFINE_EXCEPTION_STUB(174)
DEFINE_EXCEPTION_STUB(175)
DEFINE_EXCEPTION_STUB(176)
DEFINE_EXCEPTION_STUB(177)
DEFINE_EXCEPTION_STUB(178)
DEFINE_EXCEPTION_STUB(179)
DEFINE_EXCEPTION_STUB(180)
DEFINE_EXCEPTION_STUB(181)
DEFINE_EXCEPTION_STUB(182)
DEFINE_EXCEPTION_STUB(183)
DEFINE_EXCEPTION_STUB(184)
DEFINE_EXCEPTION_STUB(185)
DEFINE_EXCEPTION_STUB(186)
DEFINE_EXCEPTION_STUB(187)
DEFINE_EXCEPTION_STUB(188)
DEFINE_EXCEPTION_STUB(189)
DEFINE_EXCEPTION_STUB(190)
DEFINE_EXCEPTION_STUB(191)
DEFINE_EXCEPTION_STUB(192)
DEFINE_EXCEPTION_STUB(193)
DEFINE_EXCEPTION_STUB(194)
DEFINE_EXCEPTION_STUB(195)
DEFINE_EXCEPTION_STUB(196)
DEFINE_EXCEPTION_STUB(197)
DEFINE_EXCEPTION_STUB(198)
DEFINE_EXCEPTION_STUB(199)
DEFINE_EXCEPTION_STUB(200)
DEFINE_EXCEPTION_STUB(201)
DEFINE_EXCEPTION_STUB(202)
DEFINE_EXCEPTION_STUB(203)
DEFINE_EXCEPTION_STUB(204)
DEFINE_EXCEPTION_STUB(205)
DEFINE_EXCEPTION_STUB(206)
DEFINE_EXCEPTION_STUB(207)
DEFINE_EXCEPTION_STUB(208)
DEFINE_EXCEPTION_STUB(209)
DEFINE_EXCEPTION_STUB(210)
DEFINE_EXCEPTION_STUB(211)
DEFINE_EXCEPTION_STUB(212)
DEFINE_EXCEPTION_STUB(213)
DEFINE_EXCEPTION_STUB(214)
DEFINE_EXCEPTION_STUB(215)
DEFINE_EXCEPTION_STUB(216)
DEFINE_EXCEPTION_STUB(217)
DEFINE_EXCEPTION_STUB(218)
DEFINE_EXCEPTION_STUB(219)
DEFINE_EXCEPTION_STUB(220)
DEFINE_EXCEPTION_STUB(221)
DEFINE_EXCEPTION_STUB(222)
DEFINE_EXCEPTION_STUB(223)
DEFINE_EXCEPTION_STUB(224)
DEFINE_EXCEPTION_STUB(225)
DEFINE_EXCEPTION_STUB(226)
DEFINE_EXCEPTION_STUB(227)
DEFINE_EXCEPTION_STUB(228)
DEFINE_EXCEPTION_STUB(229)
DEFINE_EXCEPTION_STUB(230)
DEFINE_EXCEPTION_STUB(231)
DEFINE_EXCEPTION_STUB(232)
DEFINE_EXCEPTION_STUB(233)
DEFINE_EXCEPTION_STUB(234)
DEFINE_EXCEPTION_STUB(235)
DEFINE_EXCEPTION_STUB(236)
DEFINE_EXCEPTION_STUB(237)
DEFINE_EXCEPTION_STUB(238)
DEFINE_EXCEPTION_STUB(239)
DEFINE_EXCEPTION_STUB(240)
DEFINE_EXCEPTION_STUB(241)
DEFINE_EXCEPTION_STUB(242)
DEFINE_EXCEPTION_STUB(243)
DEFINE_EXCEPTION_STUB(244)
DEFINE_EXCEPTION_STUB(245)
DEFINE_EXCEPTION_STUB(246)
DEFINE_EXCEPTION_STUB(247)
DEFINE_EXCEPTION_STUB(248)
DEFINE_EXCEPTION_STUB(249)
DEFINE_EXCEPTION_STUB(250)
DEFINE_EXCEPTION_STUB(251)
DEFINE_EXCEPTION_STUB(252)
DEFINE_EXCEPTION_STUB(253)
DEFINE_EXCEPTION_STUB(254)
DEFINE_EXCEPTION_STUB(255)

View File

@@ -10,6 +10,9 @@ struct __attribute__((packed)) interrupt_frame {
uword_t ss;
};
/*
* Exceptions
* ==========*/
__attribute__((interrupt, noreturn))
void exception_handler_div_by_zero(struct interrupt_frame* frame);
@@ -22,12 +25,318 @@ void exception_handler_double_fault(struct interrupt_frame* frame);
__attribute__((interrupt, noreturn))
void exception_default(struct interrupt_frame* frame);
/**
* Interrupts
* ==========
*/
__attribute__((interrupt, noreturn))
void interrupt_default(struct interrupt_frame* frame);
__attribute__((interrupt))
void interrupt_handler_1(struct interrupt_frame* frame);
__attribute__((interrupt))
void interrupt_handler_userspace_exit(struct interrupt_frame* frame);
/**
* IRQs
* ====
*/
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_2(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_3(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_4(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_5(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_6(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_7(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_8(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_9(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_10(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_11(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_12(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_13(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_14(struct interrupt_frame*);
__attribute__((interrupt)) void irq_handler_15(struct interrupt_frame*);
/*
* Exception and interrupt stubs
* =============================
* Everything below this line is a horrible compile time crime.
* */
#include "idt.h"
#include "kernel_state.h"
/* This function is a horrible crime */
static void idt_init_stubs(struct idt_gate_descriptor idt[]) {
#define EXCEPTION_STUB(n) exception_stub_##n
#define DESC(func) \
idt_encode_descriptor( \
func, \
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0), \
IDT_DPL_3, \
IDT_GATE_TYPE_TRAP32)
#define DECLARE_EXCEPTION_STUB(n) \
__attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*); \
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);
#undef DESC
#undef DECLARE_EXCEPTION_STUB
}

View File

@@ -8,29 +8,17 @@
#include "interrupts.h"
#include "types.h"
#include "kernel_state.h"
#include "pic.h"
// Future user-space
#include "libc.h"
#include "tty.h"
#include "str.h"
static void pic_disable()
{
__asm__ volatile ("outb %0, %1"
:
: "a"((uint8_t)0xff), "Nd"((uint16_t)0x21)
: "memory");
__asm__ volatile ("outb %0, %1"
:
: "a"((uint8_t)0xff), "Nd"((uint16_t)0xA1)
: "memory");
}
static void user_mode_code(void*)
{
printf(str_attach("hello from user-space before interrupt :)\n"));
__asm__ volatile ("int $0x80");
__asm__ volatile ("int $0x81");
//__asm__ volatile ("int $0x80");
//while (1) /* busy loop */;
#if 0
@@ -82,8 +70,9 @@ void kernel_main(void)
{
__asm__ volatile("cli");
_Static_assert(sizeof(kernel.gdt) == 0x30);
/* Set up the GDT
* ============== */
kernel.gdt[SEGMENT_NULL] = gdt_encode_entry((struct gdt_entry_content){0});
/* kernel */
@@ -140,86 +129,80 @@ void kernel_main(void)
| GDT_ACCESS_PRESENT,
.flags = 0});
/* Setup the TSS */
memset(&kernel.tss, 0, sizeof kernel.tss);
kernel.tss.ss0 = segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0);
#if 1
static uint8_t kernel_stack[1024];
kernel.tss.esp0 = (uint32_t)kernel_stack;
#else
kernel.tss.esp0 = 0;
#endif
#if 1
/* Setup the IDT */
for (size_t i = 0; i < 32; i++) {
kernel.idt[i] = idt_encode_descriptor(
exception_default,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_TRAP32);
}
for (size_t i = 32; i < IDT_COUNT; i++) {
kernel.idt[i] = idt_encode_descriptor(
interrupt_default,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_INTERRUPT32);
}
kernel.idt[0x0] = idt_encode_descriptor(
exception_handler_div_by_zero,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_TRAP32
);
kernel.idt[0x8] = idt_encode_descriptor(
exception_handler_double_fault,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_TRAP32
);
kernel.idt[0xD] = idt_encode_descriptor(
exception_handler_general_protection_fault,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_TRAP32
);
// Interrupts
kernel.idt[0x80] = idt_encode_descriptor(
interrupt_handler_1,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_INTERRUPT32
);
kernel.idt[0x81] = idt_encode_descriptor(
interrupt_handler_userspace_exit,
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
IDT_DPL_3,
IDT_GATE_TYPE_INTERRUPT32
);
#endif
/* Flush the gdt and tss */
gdt_load(kernel.gdt,
sizeof kernel.gdt,
segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0),
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0));
/*
* Setup the TSS
* ============= */
static uint8_t kernel_stack[KERNEL_STACK_SIZE];
kernel.tss.ss0 = segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0);
kernel.tss.esp0 = (uint32_t)kernel_stack;
tss_load(segment(SEGMENT_TASK_STATE, SEGMENT_GDT, 0));
/**
* Setup the IDT
* ============= */
#define m_idt_default(func, type) \
idt_encode_descriptor( \
func, \
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0), \
IDT_DPL_3, \
type)
#define mtrap(func) m_idt_default(func, IDT_GATE_TYPE_TRAP32);
#define mint(func) m_idt_default(func, IDT_GATE_TYPE_INTERRUPT32);
idt_init_stubs(kernel.idt);
/* Exceptions */
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);
/* IRQs */
kernel.idt[IDT_DESC_PIC1 + 0] = mint(irq_handler_0);
kernel.idt[IDT_DESC_PIC1 + 1] = mint(irq_handler_1);
kernel.idt[IDT_DESC_PIC1 + 2] = mint(irq_handler_2);
kernel.idt[IDT_DESC_PIC1 + 3] = mint(irq_handler_3);
kernel.idt[IDT_DESC_PIC1 + 4] = mint(irq_handler_4);
kernel.idt[IDT_DESC_PIC1 + 5] = mint(irq_handler_5);
kernel.idt[IDT_DESC_PIC1 + 6] = mint(irq_handler_6);
kernel.idt[IDT_DESC_PIC1 + 7] = mint(irq_handler_7);
kernel.idt[IDT_DESC_PIC2 + 0] = mint(irq_handler_8);
kernel.idt[IDT_DESC_PIC2 + 1] = mint(irq_handler_9);
kernel.idt[IDT_DESC_PIC2 + 2] = mint(irq_handler_10);
kernel.idt[IDT_DESC_PIC2 + 3] = mint(irq_handler_11);
kernel.idt[IDT_DESC_PIC2 + 4] = mint(irq_handler_12);
kernel.idt[IDT_DESC_PIC2 + 5] = mint(irq_handler_13);
kernel.idt[IDT_DESC_PIC2 + 6] = mint(irq_handler_14);
kernel.idt[IDT_DESC_PIC2 + 7] = mint(irq_handler_15);
/* Interrupts */
kernel.idt[IDT_DESC_INTERRUPT_SYSCALL] = mint(interrupt_handler_1);
#undef mtrap
#undef mint
#undef m_idt_default
idt_load(kernel.idt, sizeof kernel.idt);
/**
* PIC setup
* =========
*/
//irq_set_mask(0xff); /* Disable all IRQs */
pic8259_remap(IDT_DESC_PIC1, IDT_DESC_PIC2);
/* enable interrupts */
__asm__ volatile("sti");
/* Finally go to ring 3 */
printf(str_attach("hello from kernel space!\n"));
pic_disable(); // temporary duct-tape
/* Finally go to ring 3 */
ring3_mode(segment(SEGMENT_USER_DATA, SEGMENT_GDT, 3),
segment(SEGMENT_USER_CODE, SEGMENT_GDT, 3),
user_mode_code);

View File

@@ -12,7 +12,34 @@ const struct str gdt_segment_index_str[SEGMENT_COUNT] = {
[SEGMENT_TASK_STATE ] = str_attach("SEGMENT_TASK_STATE"),
};
const struct str idt_index_str[IDT_COUNT] = {
const struct str idt_desc_index_str[IDT_DESC_COUNT] = {
[IDT_DESC_EXCEPTION_DIVISION_ERROR ] = str_attach("IDT_DESC_EXCEPTION_DIVISION_ERROR"),
[IDT_DESC_EXCEPTION_DEBUG ] = str_attach("IDT_DESC_EXCEPTION_DEBUG"),
[IDT_DESC_EXCEPTION_NON_MASKABLE ] = str_attach("IDT_DESC_EXCEPTION_NON_MASKABLE"),
[IDT_DESC_EXCEPTION_BREAKPOINT ] = str_attach("IDT_DESC_EXCEPTION_BREAKPOINT"),
[IDT_DESC_EXCEPTION_OVERFLOW ] = str_attach("IDT_DESC_EXCEPTION_OVERFLOW"),
[IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED ] = str_attach("IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED"),
[IDT_DESC_EXCEPTION_INVALID_OPCODE ] = str_attach("IDT_DESC_EXCEPTION_INVALID_OPCODE"),
[IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE ] = str_attach("IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE"),
[IDT_DESC_EXCEPTION_DOUBLE_FAULT ] = str_attach("IDT_DESC_EXCEPTION_DOUBLE_FAULT"),
[IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN] = str_attach("IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN"),
[IDT_DESC_EXCEPTION_INVALID_TSS ] = str_attach("IDT_DESC_EXCEPTION_INVALID_TSS"),
[IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT ] = str_attach("IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT"),
[IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT ] = str_attach("IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT"),
[IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT ] = str_attach("IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT"),
[IDT_DESC_EXCEPTION_PAGE_FAULT ] = str_attach("IDT_DESC_EXCEPTION_PAGE_FAULT"),
[IDT_DESC_EXCEPTION_X87_FLOATING_POINT ] = str_attach("IDT_DESC_EXCEPTION_X87_FLOATING_POINT"),
[IDT_DESC_EXCEPTION_ALIGNMENT_CHECK ] = str_attach("IDT_DESC_EXCEPTION_ALIGNMENT_CHECK"),
[IDT_DESC_EXCEPTION_MACHINE_CHECK ] = str_attach("IDT_DESC_EXCEPTION_MACHINE_CHECK"),
[IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT ] = str_attach("IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT"),
[IDT_DESC_EXCEPTION_VIRTUALIZATION ] = str_attach("IDT_DESC_EXCEPTION_VIRTUALIZATION"),
[IDT_DESC_EXCEPTION_CONTROL_PROTECTION ] = str_attach("IDT_DESC_EXCEPTION_CONTROL_PROTECTION"),
[IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION ] = str_attach("IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION"),
[IDT_DESC_EXCEPTION_VMM_COMMUNICATION ] = str_attach("IDT_DESC_EXCEPTION_VMM_COMMUNICATION"),
[IDT_DESC_EXCEPTION_SECURITY ] = str_attach("IDT_DESC_EXCEPTION_SECURITY"),
[IDT_DESC_PIC1 ] = str_attach("IDT_DESC_IRQ_MASTER"),
[IDT_DESC_PIC2 ] = str_attach("IDT_DESC_IRQ_SLAVE"),
[IDT_DESC_INTERRUPT_SYSCALL ] = str_attach("IDT_DESC_INTERRUPT_SYSCALL"),
};
struct kernel_state kernel = { 0 };

View File

@@ -6,6 +6,9 @@
#include "idt.h"
#include "gdt.h"
/*
* Constants for the GDT
* */
enum gdt_segment_index : size_t {
SEGMENT_NULL,
SEGMENT_KERNEL_CODE,
@@ -17,18 +20,65 @@ enum gdt_segment_index : size_t {
};
extern const struct str gdt_segment_index_str[SEGMENT_COUNT]; // reverse lookup enum -> str
enum idt_index : size_t {
IDT_COUNT = 256
/**
* 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;
static constexpr size_t IDT_IRQ_SLAVE_COUNT = 8;
enum idt_desc_index : size_t {
/* Exceptions */
IDT_DESC_EXCEPTION_DIVISION_ERROR = 0,
IDT_DESC_EXCEPTION_DEBUG = 1,
IDT_DESC_EXCEPTION_NON_MASKABLE = 2,
IDT_DESC_EXCEPTION_BREAKPOINT = 3,
IDT_DESC_EXCEPTION_OVERFLOW = 4,
IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED = 5,
IDT_DESC_EXCEPTION_INVALID_OPCODE = 6,
IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE = 7,
IDT_DESC_EXCEPTION_DOUBLE_FAULT = 8,
IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN = 9,
IDT_DESC_EXCEPTION_INVALID_TSS = 10,
IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT = 11,
IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT = 12,
IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT = 13,
IDT_DESC_EXCEPTION_PAGE_FAULT = 14,
/* 15 is reserved */
IDT_DESC_EXCEPTION_X87_FLOATING_POINT = 16,
IDT_DESC_EXCEPTION_ALIGNMENT_CHECK = 17,
IDT_DESC_EXCEPTION_MACHINE_CHECK = 18,
IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT = 19,
IDT_DESC_EXCEPTION_VIRTUALIZATION = 20,
IDT_DESC_EXCEPTION_CONTROL_PROTECTION = 21,
/* 21 to 27 are reserved */
IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION = 28,
IDT_DESC_EXCEPTION_VMM_COMMUNICATION = 29,
IDT_DESC_EXCEPTION_SECURITY = 30,
/* 31 is reserved */
/* IRQ offsets */
IDT_DESC_PIC1 = 32,
IDT_DESC_PIC2 = IDT_DESC_PIC1 + 8,
IDT_DESC_INTERRUPT_SYSCALL = 128,
IDT_DESC_COUNT = 256,
};
extern const struct str idt_index_str[IDT_COUNT]; // reverse lookup enum -> str
constexpr size_t BACKTRACE_MAX = 256;
extern const struct str idt_desc_index_str[IDT_DESC_COUNT]; // reverse lookup enum -> str
/**
* The global kernel state object
*/
struct kernel_state {
struct tss tss;
struct gdt_table_entry gdt[SEGMENT_COUNT];
struct idt_gate_descriptor idt[IDT_COUNT];
struct idt_gate_descriptor idt[IDT_DESC_COUNT];
int nested_exception_counter;
};
extern struct kernel_state kernel;

91
src/kernel/pic.c Normal file
View File

@@ -0,0 +1,91 @@
#include "pic.h"
void pic8259_remap(int offset1, int offset2)
{
/* ICW1: restart PIC1 and PIC2 with
- icw4
- cascade
- 8 bit interval
- edge triggered mode
*/
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
/* ICW2: Send new offsets */
outb(PIC1_DATA, offset1);
outb(PIC2_DATA, offset2);
/* ICW2 and ICW3: Setup cascading */
outb(PIC1_DATA, 1<<2); /* tell master PIC that IR input 2 has a slave */
outb(PIC2_DATA, 2); /* set ID of slave PIC */
/* ICW4: 8086/88 mode */
outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086);
}
static inline void irq_set(enum pic8259_port port, uint8_t mask)
{
outb(port, inb(port) | mask);
}
static inline void irq_clear(enum pic8259_port port, uint8_t mask)
{
outb(port, inb(port) & ~(mask));
}
void pic8259_set_irq_mask(uint16_t mask)
{
const uint8_t pic1_mask = mask & 0xF;
mask >>= 8;
const uint8_t pic2_mask = mask & 0xF;
if (pic1_mask) {
irq_set(PIC1_DATA, pic1_mask);
}
if (pic2_mask) {
irq_set(PIC2_DATA, pic2_mask);
}
}
void pic8259_clear_irq_mask(uint16_t mask)
{
const uint8_t pic1_mask = mask & 0xF;
mask >>= 8;
const uint8_t pic2_mask = mask & 0xF;
if (pic1_mask) {
irq_clear(PIC1_DATA, pic1_mask);
}
if (pic2_mask) {
irq_clear(PIC2_DATA, pic2_mask);
}
}
/**
* https://wiki.osdev.org/8259_PIC#ISR_and_IRR
* ===========================================
* */
static uint16_t get_irq_reg(int ocw3)
{
/* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
outb(PIC1_COMMAND, ocw3);
outb(PIC2_COMMAND, ocw3);
return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
}
/* Returns the combined value of the cascaded PICs irq request register */
uint16_t pic8259_get_irr(void)
{
return get_irq_reg(OCW3_READ_IRR);
}
/* Returns the combined value of the cascaded PICs in-service register */
uint16_t pic8259_get_isr(void)
{
return get_irq_reg(OCW3_READ_ISR);
}
/* =========================================== */

171
src/kernel/pic.h Normal file
View File

@@ -0,0 +1,171 @@
#pragma once
#include <stdint.h>
#include "str.h"
enum pic8259_port : uint16_t {
PIC1_COMMAND = 0x20,
PIC1_DATA = 0x21,
PIC2_COMMAND = 0xA0,
PIC2_DATA = 0xA1,
PIC_KEYBOARD = 0x60,
};
static const struct str pic8259_port_str[] = {
[PIC1_COMMAND ] = str_attach("PIC1_COMMAND"),
[PIC1_DATA ] = str_attach("PIC1_DATA"),
[PIC2_COMMAND ] = str_attach("PIC2_COMMAND"),
[PIC2_DATA ] = str_attach("PIC2_DATA"),
};
enum irq : uint16_t {
IRQ_SYSTEM_TIMER = 0,
IRQ_KEYBOARD_CONTROLLER = 1,
IRQ_SERIAL_COM2 = 3,
IRQ_SERIAL_COM1 = 4,
IRQ_LINE_PRINT_TERMINAL_2 = 5,
IRQ_FLOPPY_CONTROLLER = 6,
IRQ_LINE_PRINT_TERMINAL_1 = 7,
IRQ_RTC_TIMER = 8,
IRQ_ACPI = 9,
IRQ_MOUSE_CONTROLLER = 12,
IRQ_MATH_COPROCESSOR = 13,
IRQ_ATA_CHANNEL_1 = 14,
IRQ_ATA_CHANNEL_2 = 15,
};
static const struct str irq_str[] = {
[IRQ_SYSTEM_TIMER ] = str_attach("IRQ_SYSTEM_TIMER"),
[IRQ_KEYBOARD_CONTROLLER ] = str_attach("IRQ_KEYBOARD_CONTROLLER"),
[IRQ_SERIAL_COM2 ] = str_attach("IRQ_SERIAL_COM2"),
[IRQ_SERIAL_COM1 ] = str_attach("IRQ_SERIAL_COM1"),
[IRQ_LINE_PRINT_TERMINAL_2] = str_attach("IRQ_LINE_PRINT_TERMINAL_2"),
[IRQ_FLOPPY_CONTROLLER ] = str_attach("IRQ_FLOPPY_CONTROLLER"),
[IRQ_LINE_PRINT_TERMINAL_1] = str_attach("IRQ_LINE_PRINT_TERMINAL_1"),
[IRQ_RTC_TIMER ] = str_attach("IRQ_RTC_TIMER"),
[IRQ_ACPI ] = str_attach("IRQ_ACPI"),
[IRQ_MOUSE_CONTROLLER ] = str_attach("IRQ_MOUSE_CONTROLLER"),
[IRQ_MATH_COPROCESSOR ] = str_attach("IRQ_MATH_COPROCESSOR"),
[IRQ_ATA_CHANNEL_1 ] = str_attach("IRQ_ATA_CHANNEL_1"),
[IRQ_ATA_CHANNEL_2 ] = str_attach("IRQ_ATA_CHANNEL_2"),
};
/**
Initialization Command Words
=======================
From the Intel manuals:
https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf
https://web.archive.org/web/20240606163819/https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf
> Whenever a command is issued with A0 = 0 and D4 = 1, this is interpreted
> as Initialization Command Word 1 (ICW1) CW1 starts the intiitalization
> sequence during which the following automatically occur:
> a. The edge sense circuit is reset, which means that following
> initialization, an interrupt request (IR) input must make a
> low-to-high transistion to generate an interrupt.
> b. The Interrupt Mask Register is cleared.
> c. IR7 input is assigned priority 7.
> d. The slave mode address is set to 7.
> e. Special Mask Mode is cleared and Status Read is set to IRR
> f. If IC4 = 0, then all functions selected in ICW4 are set to zero.
> (Non-Buffered mode*, no Auto-EOI, MCS-80, 85 system).
> [*]: Master/Slave in ICW4 is only used in the buffered mode
*/
enum icw1 : uint8_t {
ICW1_ICW4 = 1<<0, /* 1: ICW4 Needed
0: ICW4 Not needed */
ICW1_SINGLE = 1<<1, /* 1: Single
0: Cascade mode */
ICW1_INTERVAL4 = 1<<2, /* Call Address Interval:
1: interval of 4
0: interval of 8 */
ICW1_LEVEL = 1<<3, /* 1: Level triggered mode
0: Edge triggered mode */
ICW1_INIT = 1<<4, /* Must be present */
};
enum icw4 : uint8_t {
ICW4_8086 = 1<<0, /* 1: 8086/88 mode
0: MCS-80/85 mode */
ICW4_AUTO = 1<<1, /* 1: Auto EOI
0: Normal EOI */
ICW4_BUF1 = 0b11<<2, /* Buffered mode master */
ICW4_BUF2 = 0b10<<2, /* Buffered mode slave */
ICW4_SFNM = 1<<4, /* 1: Special fully nested mode
0: Not special fully nested mode */
};
/* OCW2 */
enum ocw2_command : uint8_t {
OCW2_EOI = 1<<5,
OCW2_SPECIFIC = 1<<6,
OCW2_ROTATE = 1<<7,
/* Determines the interrupt level acted upon when the specific flag is set */
OCW2_IR_LEVEL_0 = 0,
OCW2_IR_LEVEL_1 = 1,
OCW2_IR_LEVEL_2 = 2,
OCW2_IR_LEVEL_3 = 3,
OCW2_IR_LEVEL_4 = 4,
OCW2_IR_LEVEL_5 = 5,
OCW2_IR_LEVEL_6 = 6,
OCW2_IR_LEVEL_7 = 7,
};
/* OCW3 */
enum ocw3_bits : uint8_t {
OCW3_BIT_RIS = (1<<0),
OCW3_BIT_RR = (1<<1),
OCW3_BIT_P = (1<<2),
/* bit 3 and 4 must be 0b01 for OCW3 to be selected */
OCW3_BIT_SMM = (1<<5),
OCW3_BIT_ESMM = (1<<6),
};
enum ocw3_command : uint8_t {
OCW3_READ_ISR = (1<<3) | OCW3_BIT_RR | OCW3_BIT_RIS,
OCW3_READ_IRR = (1<<3) | OCW3_BIT_RR,
OCW3_POLL = (1<<3) | OCW3_BIT_P,
OCW3_RESET_SPECIAL_MASK = (1<<3) | OCW3_BIT_SMM,
OCW3_SET_SPECIAL_MASK = (1<<3) | OCW3_BIT_ESMM | OCW3_BIT_SMM,
};
static inline void outb(uint16_t port, uint8_t signal)
{
__asm__ volatile ("outb %[signal], %[port]"
:
: [signal] "a" (signal),
[port] "Nd" (port)
: "memory");
#ifdef ADD_IO_WAIT
/* do an I/O operation on an unused port to wait 1-4 microseconds */
outb(0x80, 0);
#endif
}
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
__asm__ volatile ( "inb %w1, %b0"
: "=a"(ret)
: "Nd"(port)
: "memory");
return ret;
}
void pic8259_remap(int offset1, int offset2);
void pic8259_set_irq_mask(uint16_t mask);
void pic8259_clear_irq_mask(uint16_t mask);

View File

@@ -77,7 +77,7 @@ static int print_i32(struct printf_state* s, int padding, char pad_char)
{
padding = padding ? padding : 0;
pad_char = pad_char ? pad_char : ' ';
long n = va_arg(s->ap, int32_t);
uint32_t n = va_arg(s->ap, int32_t);
return print_long(n, str_attach("0123456789"), true, padding, pad_char);
}
@@ -85,7 +85,7 @@ static int print_u32(struct printf_state* s, int padding, char pad_char)
{
padding = padding ? padding : 0;
pad_char = pad_char ? pad_char : ' ';
unsigned long n = va_arg(s->ap, uint32_t);
uint32_t n = va_arg(s->ap, uint32_t);
return print_long(n, str_attach("0123456789"), false, padding, pad_char);
}
@@ -93,7 +93,7 @@ static int print_x32(struct printf_state* s, int padding, char pad_char)
{
padding = padding ? padding : 0;
pad_char = pad_char ? pad_char : '0';
unsigned long n = va_arg(s->ap, uint32_t);
uint32_t n = va_arg(s->ap, uint32_t);
struct str alphabet = str_attach("0123456789abcdef");
return print_long(n, alphabet, false, padding, pad_char);
}
@@ -102,7 +102,7 @@ static int print_b32(struct printf_state* s, int padding, char pad_char)
{
padding = padding ? padding : 32;
pad_char = pad_char ? pad_char : '0';
unsigned long n = va_arg(s->ap, uint32_t);
uint32_t n = va_arg(s->ap, uint32_t);
struct str alphabet = str_attach("01");
return print_long(n, alphabet, false, padding, pad_char);
}
@@ -119,7 +119,19 @@ static int print_str(struct printf_state* s, int padding, char pad_char)
return str.len;
}
#pragma GCC diagnostic ignored "-Wmultichar"
static int print_char(struct printf_state* s)
{
// char is promoted to int when passed through va_arg
const int ch = va_arg(s->ap, int);
if (ch >= 32 && ch < 127) {
terminal_putchar(ch);
return 1;
} else {
return print_long(ch, str_attach("0123456789abcdef"), false, 0, 0);
}
}
static int parse_format_cmd(struct printf_state* s)
{
int c;
@@ -137,16 +149,21 @@ static int parse_format_cmd(struct printf_state* s)
if (c == EOF)
return -1;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmultichar"
switch (cmd) {
// 16 bit types are promoted to 32 bit by va_arg(...) anyways
case 'int':
case 'i16':
case 'i32':
return print_i32(s, pad, pad_char);
case 'uint':
case 'u16':
case 'u32':
return print_u32(s, pad, pad_char);
case 'hex':
case 'x16':
case 'x32':
return print_x32(s, pad, pad_char);
@@ -154,9 +171,13 @@ static int parse_format_cmd(struct printf_state* s)
case 'str':
return print_str(s, pad, pad_char);
case 'char':
return print_char(s);
default:
return -1;
}
#pragma GCC diagnostic pop
}
int printf(struct str format, ...)

35
src/lib/ring_buffer.c Normal file
View File

@@ -0,0 +1,35 @@
#include "ring_buffer.h"
size_t ring_buffer_remaining(struct ring_buffer* q)
{
return (RING_BUFFER_MAX - q->len) / q->entry_size;
}
bool ring_buffer_push(struct ring_buffer* q, const void* data)
{
if (q->len + q->entry_size > RING_BUFFER_MAX) {
return false;
}
q->len += q->entry_size;
for (size_t i = 0; i < q->entry_size; i++) {
q->data[q->tail] = ((uint8_t*)data)[i];
q->tail += 1;
q->tail %= RING_BUFFER_MAX;
}
return true;
}
bool ring_buffer_get(struct ring_buffer* q, void* out)
{
if (q->len == 0) {
return false;
}
q->len -= q->entry_size;
for (size_t i = 0; i < q->entry_size; i++) {
((uint8_t*)out)[i] = q->data[q->head];
q->head += 1;
q->head %= RING_BUFFER_MAX;
}
return true;
}

176
src/test/test_ring_buffer.c Normal file
View File

@@ -0,0 +1,176 @@
#include "ring_buffer.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
struct myObj {
int32_t a;
int32_t b;
};
static int g_status = EXIT_SUCCESS;
static int test_no = 0;
static bool test_ongoing = false;
#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()
{
struct ring_buffer q = make_ring_buffer(struct myObj);
test_begin("entry_size");
{
if (q.entry_size != sizeof (struct myObj)) {
test_fail("wrong entry_size");
} else {
test_ok("entry_size is %zu", q.entry_size);
}
}
test_begin("ring_buffer_remaining");
size_t max_items = ring_buffer_remaining(&q); // used later
{
if (max_items != RING_BUFFER_MAX / sizeof(struct myObj)) {
test_fail("unexpected ring_buffer_remaining()");
} else {
test_ok("ring_buffer_remaining() is %zu", max_items);
}
}
test_begin("ring_buffer_push");
{
bool ok = true;
size_t remaining = ring_buffer_remaining(&q);
for (size_t i = 0; i < remaining; i++) {
if (ring_buffer_push(&q, &(struct myObj){i, i}) == false) {
ok = false;
break;
}
}
if (!ok) {
test_fail("expected ring_buffer push to work");
} else {
test_ok("successfully pushed %zu times", remaining);
}
}
test_begin("ring_buffer_push on full ring buffer");
{
if (ring_buffer_push(&q, &(struct myObj){}) == true) {
test_fail("ring buffer should be full by now, ring_buffer_remaining is %zu", ring_buffer_remaining(&q));
} else {
test_ok("correctly failed to push when ring buffer is full");
}
}
test_begin("ring_buffer_get");
{
for (size_t i = 0; i < max_items; i++) {
struct myObj o;
bool ok = ring_buffer_get(&q, &o);
if (!ok) {
test_fail("ring_buffer_get() didn't fetch when buffer had data");
goto end_test;
}
if (o.a != (int32_t)i
|| o.b != (int32_t)i
){
test_fail("ring_buffer_get() retrived faulty data {%i, %i}", o.a, o.b);
goto end_test;
}
}
test_ok("ring_buffer_get() works");
end_test:
}
test_begin("ring_buffer_get on empty ring buffer");
{
struct myObj o;
bool ok = ring_buffer_get(&q, &o);
if (ok) {
test_fail("ring_buffer_get() on empty ring buffer succeeded, got {%i, %i}", o.a, o.b);
} else {
test_ok("ring_buffer_get() on empty ring buffer didn't succeed");
}
}
test_begin("stress test");
{
struct ring_buffer rb = make_ring_buffer(struct myObj);
bool fail = false;
for (volatile size_t i = 0; i < RING_BUFFER_MAX * 10; i++) {
bool ok;
struct myObj before = {i, i};
struct myObj after = {-1, -1};
ok = ring_buffer_push(&rb, &before);
if (!ok) {
test_fail("failed to push during stress-test");
fail = true;
break;
}
ok = ring_buffer_get(&rb, &after);
if (!ok) {
test_fail("failed to get during stress-test");
fail = true;
break;
}
if (before.a != after.a || before.b != after.b) {
test_fail("data got damaged in queue");
fail = true;
break;
}
}
if (!fail) {
test_ok("stress test succeeded");
}
}
if (g_status == EXIT_SUCCESS) {
printf("\nAll tests succeeded\n");
} else {
printf("\nOne or more tests failed\n");
}
return g_status;
}