diff --git a/Makefile b/Makefile index 0e2dce7..ec51135 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ $(BUILD)/isr.o: $(ARCH_DIR)/isr.asm | $(BUILD) $(BUILD)/kmain.o: kernel/core/kmain.c include/console.h include/idt.h include/pic.h include/pit.h include/serial.h include/keyboard.h | $(BUILD) $(CC) $(CFLAGS) -c $< -o $@ -$(BUILD)/console.o: $(ARCH_DIR)/console.c include/console.h | $(BUILD) +$(BUILD)/console.o: $(ARCH_DIR)/console.c include/console.h include/io.h | $(BUILD) $(CC) $(CFLAGS) -c $< -o $@ $(BUILD)/idt.o: $(ARCH_DIR)/idt.c include/idt.h include/console.h include/pic.h | $(BUILD) diff --git a/kernel/arch/x86_64/console.c b/kernel/arch/x86_64/console.c index e365a4a..3bea16d 100644 --- a/kernel/arch/x86_64/console.c +++ b/kernel/arch/x86_64/console.c @@ -3,13 +3,21 @@ #include #include "console.h" +#include "io.h" #define VGA_WIDTH 80 #define VGA_HEIGHT 25 #define VGA_ADDR 0xB8000 #define COLOR_DEFAULT 0x0FU /* white on black */ -/* Cursor position. Lives in BSS. */ +/* VGA CRT controller ports: index selects the register, data reads/writes + * it. Registers 0x0E/0x0F hold the high/low byte of the cursor offset. */ +#define VGA_CRT_INDEX 0x3D4U +#define VGA_CRT_DATA 0x3D5U +#define VGA_CRT_CURSOR_HIGH 0x0EU +#define VGA_CRT_CURSOR_LOW 0x0FU + +/* Cursor position, lives in BSS. */ static uint8_t cursor_row; static uint8_t cursor_col; @@ -18,6 +26,20 @@ static uint8_t cursor_col; * store in order. */ static volatile uint16_t *const vga = (uint16_t *)VGA_ADDR; +/* Sync the blinking hardware cursor to cursor_row/cursor_col. + * Runs at Ring 0 (CPL 0): `out` traps with #GP(0) if CPL > IOPL, so this + * must never run in userspace. A wrong port value cannot fault, + * it would only misplace the visible cursor. */ +static void update_hw_cursor(void) +{ + uint16_t pos = (uint16_t)(cursor_row * VGA_WIDTH + cursor_col); + + outb(VGA_CRT_INDEX, VGA_CRT_CURSOR_LOW); + outb(VGA_CRT_DATA, (uint8_t)(pos & 0xFFU)); + outb(VGA_CRT_INDEX, VGA_CRT_CURSOR_HIGH); + outb(VGA_CRT_DATA, (uint8_t)((pos >> 8) & 0xFFU)); +} + static void scroll(void) { for (uint8_t row = 1; row < VGA_HEIGHT; row++) { @@ -38,6 +60,7 @@ void console_clear(void) } cursor_row = 0; cursor_col = 0; + update_hw_cursor(); } void console_putchar(char c) @@ -75,6 +98,7 @@ void console_putchar(char c) scroll(); cursor_row = VGA_HEIGHT - 1; } + update_hw_cursor(); } void console_puts(const char *s)