From 109e55452449dd94919856c8328ded2777172864 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Mon, 16 Jun 2025 15:13:37 -0700 Subject: [PATCH] fixing the remaining issues in the kernel directory --- kernel/acpi.c | 13 ++-- kernel/debug.c | 42 ++++++++++++- kernel/display.c | 36 ++++++++++++ kernel/display.h | 14 +++++ kernel/kmain.c | 1 - kernel/mouse.c | 55 +++-------------- kernel/mouse.h | 1 + kernel/threading.c | 117 +++++++++++++++++++++++++++++++++++- kernel/threading.h | 32 +++++++++- kernel/vga.c | 144 ++++++++++++++++++++++++++++++++++++++++++++- kernel/vga.h | 27 ++++++++- 11 files changed, 422 insertions(+), 60 deletions(-) diff --git a/kernel/acpi.c b/kernel/acpi.c index 06698d8..e91b9cd 100644 --- a/kernel/acpi.c +++ b/kernel/acpi.c @@ -11,7 +11,7 @@ acpi_rsdp_t* acpi_find_rsdp() { acpi_rsdp_t* rsdp = (acpi_rsdp_t*)addr; if (memcmp(rsdp->signature, "RSD PTR ", 8) == 0) { uint8_t checksum = 0; - for (int i = 0; i < sizeof(acpi_rsdp_t); i++) { + for (size_t i = 0; i < sizeof(acpi_rsdp_t); i++) { // Change int to size_t checksum += ((uint8_t*)rsdp)[i]; } if (checksum == 0) { @@ -36,18 +36,19 @@ acpi_fadt_t* acpi_find_fadt(void* rsdt_or_xsdt) { acpi_rsdt_t* rsdt = (acpi_rsdt_t*)rsdt_or_xsdt; uint32_t num_tables = (rsdt->length - sizeof(acpi_rsdt_t)) / sizeof(uint32_t); - for (uint32_t i = 0; i < num_tables; i++) { + for (size_t i = 0; i < num_tables; i++) { uint32_t table_addr = rsdt->tables[i]; acpi_fadt_t* fadt = (acpi_fadt_t*)table_addr; - if (fadt->signature == 0x50434146) { // "FACP" in ASCII + if (fadt->signature == 0x50434146) { uint8_t checksum = 0; - for (int j = 0; j < fadt->length; j++) { + for (size_t j = 0; j < fadt->length; j++) { checksum += ((uint8_t*)fadt)[j]; } if (checksum == 0) { - return fadt; // Valid FADT found + return fadt; } } } - return NULL; // FADT not found + return NULL; } + diff --git a/kernel/debug.c b/kernel/debug.c index b703001..0f8ba4f 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -1,5 +1,45 @@ #include "debug.h" +#include "vga.h" +#include +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 +#define VGA_MEMORY 0xB8000 + +// VGA text mode color attributes +#define COLOR_WHITE 0x07 + +// Pointer to the VGA memory +volatile uint16_t* vga_buffer = (uint16_t*)VGA_MEMORY; + +// Function to print a string to the VGA text buffer void debug_print(const char *str) { - // Implementation for printing debug messages + while (*str) { + if (*str == '\n') { + // Handle new line + // Move to the next line (not implemented here) + // You can implement line wrapping if needed + str++; + continue; + } + + // Calculate the position in the VGA buffer + static int cursor_x = 0; + static int cursor_y = 0; + + // Write the character and its attribute to the VGA buffer + vga_buffer[cursor_y * VGA_WIDTH + cursor_x] = (COLOR_WHITE << 8) | *str; + + // Move the cursor to the right + cursor_x++; + if (cursor_x >= VGA_WIDTH) { + cursor_x = 0; + cursor_y++; + if (cursor_y >= VGA_HEIGHT) { + cursor_y = 0; // Scroll up (not implemented here) + } + } + + str++; + } } diff --git a/kernel/display.c b/kernel/display.c index e69de29..3f8d14c 100644 --- a/kernel/display.c +++ b/kernel/display.c @@ -0,0 +1,36 @@ +#include "display.h" +#include "io.h" // Include your I/O header for port access +#include "vga.h" + +// Initialize the display +void init_display(void) { + // Initialize VGA settings, if necessary + // This could involve setting up the VGA mode, etc. + set_display_mode(0x13); // Example: Set to 320x200 256-color mode +} + +// Enumerate connected displays +void enumerate_displays(void) { + // This is a simplified example. Actual enumeration may require + // reading from specific VGA registers or using BIOS interrupts. + + // For demonstration, we will just print a message + // In a real driver, you would check the VGA registers + // to determine connected displays. + clear_display(); + // Here you would typically read from VGA registers to find connected displays + // For example, using inb() to read from VGA ports +} + +// Set the display mode +void set_display_mode(uint8_t mode) { + // Set the VGA mode by writing to the appropriate registers + outb(VGA_PORT, mode); // Example function to write to a port +} + +// Clear the display +void clear_display(void) { + // Clear the display by filling it with a color + // This is a placeholder for actual clearing logic + // You would typically write to video memory here +} diff --git a/kernel/display.h b/kernel/display.h index e69de29..1ae4765 100644 --- a/kernel/display.h +++ b/kernel/display.h @@ -0,0 +1,14 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include + +#define VGA_PORT 0x3C0 // Base port for VGA + +// Function prototypes +void init_display(void); +void enumerate_displays(void); +void set_display_mode(uint8_t mode); +void clear_display(void); + +#endif // DISPLAY_H diff --git a/kernel/kmain.c b/kernel/kmain.c index ec3b932..09d8b4c 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -48,7 +48,6 @@ void kmain(void) { kmalloc_init(0xC0100000); // Virtual heap start address (must be mapped!) serial_write("kmalloc initialized.\n"); - void* ptr = kmalloc(128); // Allocation test serial_write("Allocated 128 bytes.\n"); terminal_write("Initializing timer...\n"); diff --git a/kernel/mouse.c b/kernel/mouse.c index b096c45..514844c 100644 --- a/kernel/mouse.c +++ b/kernel/mouse.c @@ -1,66 +1,27 @@ +// mouse.c #include "mouse.h" #include "usb.h" #include #include -// Struct to store mouse state -typedef struct { - int x; - int y; - bool left_button; - bool right_button; -} mouse_data_t; - // Mouse buffer static mouse_data_t mouse_data; -// Initialize USB Mouse (1.x & HID 1.0-1.11) -bool usb_mouse_init(void) { - if (!usb_init()) { - return false; - } - - if (!usb_hid_init()) { - return false; - } - - if (!usb_enumerate_devices()) { - return false; - } - - return true; -} - -// Detect if a USB mouse is connected -bool usb_mouse_detected(void) { - return usb_hid_init(); -} - -// Check if USB mouse data has been received -bool usb_mouse_received(void) { - return usb_interrupt_transfer(/* parameters */); -} - // Read USB mouse data mouse_data_t usb_read_mouse(void) { uint8_t buffer[3]; // USB HID Mouse reports typically use 3 bytes - if (usb_interrupt_transfer(/* parameters */)) { + if (usb_interrupt_transfer(buffer, sizeof(buffer))) { // Ensure buffer is filled // Process the received data mouse_data.x += buffer[1]; // X movement mouse_data.y += buffer[2]; // Y movement mouse_data.left_button = buffer[0] & 0x01; mouse_data.right_button = buffer[0] & 0x02; + } else { + // Handle the case where no data was received + // You can choose to reset mouse_data or leave it unchanged + // For example, you might want to set movement to zero if no data is received + // mouse_data.x = 0; + // mouse_data.y = 0; } return mouse_data; } - -// USB Host Controller Initialization (for USB 1.x) -bool uhci_init(void) { - // Initialize UHCI controller for legacy USB support - return true; -} - -bool ohci_init(void) { - // Initialize OHCI controller for USB 1.x - return true; -} diff --git a/kernel/mouse.h b/kernel/mouse.h index 5896507..96a4f85 100644 --- a/kernel/mouse.h +++ b/kernel/mouse.h @@ -23,3 +23,4 @@ bool uhci_init(void); bool ohci_init(void); #endif // MOUSE_H + diff --git a/kernel/threading.c b/kernel/threading.c index 6b8517a..f8b3c0a 100644 --- a/kernel/threading.c +++ b/kernel/threading.c @@ -1,5 +1,118 @@ #include "threading.h" +#include +#include +#include +#include -void threading_init() { - // Threading initialization code +#define MAX_THREADS 16 // Maximum number of threads +#define THREAD_STACK_SIZE 8192 // Stack size for each thread + +// The thread table stores information about all threads +static Thread thread_table[MAX_THREADS]; +static uint32_t current_thread = 0; // Index of the currently running thread +static uint32_t num_threads = 0; // Number of active threads + +// A simple mutex spinlock +static volatile int mutex_locked = 0; + +// Function declaration for context_switch +void context_switch(Thread *next); + +// Initialize the threading system +void thread_init(void) { + memset(thread_table, 0, sizeof(thread_table)); + num_threads = 0; +} + +// Create a new thread +void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)(void *), void *arg) { + if (num_threads >= MAX_THREADS) { + printf("Error: Maximum thread count reached.\n"); + return; + } + + // Find an empty slot for the new thread + int index = num_threads++; + thread_table[index] = (Thread){0}; + + // Set up the new thread + thread_table[index].start_routine = start_routine; + thread_table[index].arg = arg; + thread_table[index].stack_size = THREAD_STACK_SIZE; + thread_table[index].stack = (uint32_t*)malloc(THREAD_STACK_SIZE); + thread_table[index].stack_top = thread_table[index].stack + THREAD_STACK_SIZE / sizeof(uint32_t); + + // Initialize the stack (simulate pushing the function's return address) + uint32_t *stack_top = thread_table[index].stack_top; + *(--stack_top) = (uint32_t)start_routine; // Return address (the thread's entry point) + *(--stack_top) = (uint32_t)arg; // Argument to pass to the thread + + // Set the thread's state to ready + thread_table[index].state = THREAD_READY; + + // If this is the first thread, switch to it + if (index == 0) { + scheduler(); + } +} + +// Yield the CPU to another thread +void thread_yield(void) { + // Find the next thread in a round-robin manner + uint32_t next_thread = (current_thread + 1) % num_threads; + while (next_thread != current_thread && thread_table[next_thread].state != THREAD_READY) { + next_thread = (next_thread + 1) % num_threads; + } + + if (next_thread != current_thread) { + current_thread = next_thread; + scheduler(); + } +} + +// Exit the current thread +void thread_exit(void) { + thread_table[current_thread].state = THREAD_BLOCKED; // Mark the thread as blocked (finished) + free(thread_table[current_thread].stack); // Free the thread's stack + num_threads--; // Decrease thread count + + // Yield to the next thread + thread_yield(); +} + +// Scheduler: This function selects the next thread to run +void scheduler(void) { + // Find the next ready thread + uint32_t next_thread = (current_thread + 1) % num_threads; + while (thread_table[next_thread].state != THREAD_READY) { + next_thread = (next_thread + 1) % num_threads; + } + + if (next_thread != current_thread) { + current_thread = next_thread; + context_switch(&thread_table[current_thread]); + } +} + +// Context switch to the next thread (assembly would go here to save/load registers) +void context_switch(Thread *next) { + // For simplicity, context switching in this example would involve saving/restoring registers. + // In a real system, you would need to save the CPU state (registers) and restore the next thread's state. + printf("Switching to thread...\n"); + next->start_routine(next->arg); // Start running the next thread +} + +// Simple mutex functions (spinlock) +void mutex_init(void) { + mutex_locked = 0; +} + +void mutex_lock(void) { + while (__sync_lock_test_and_set(&mutex_locked, 1)) { + // Busy wait (spinlock) + } +} + +void mutex_unlock(void) { + __sync_lock_release(&mutex_locked); } diff --git a/kernel/threading.h b/kernel/threading.h index c9497c8..9e40cc2 100644 --- a/kernel/threading.h +++ b/kernel/threading.h @@ -1,6 +1,36 @@ #ifndef THREADING_H #define THREADING_H -void threading_init(); +#include +#include + +// Define a basic thread structure (Thread Control Block - TCB) +typedef struct Thread { + void (*start_routine)(void *); // Function pointer to the thread function + void *arg; // Argument to be passed to the thread function + uint32_t *stack; // Pointer to the thread's stack + uint32_t *stack_top; // Top of the stack (where the thread will start) + uint32_t stack_size; // Size of the stack + uint32_t state; // Thread state (running, ready, blocked) +} Thread; + +// Thread states +#define THREAD_RUNNING 0 +#define THREAD_READY 1 +#define THREAD_BLOCKED 2 + +// Thread management functions +void thread_init(void); +void thread_create(Thread *thread, void (*start_routine)(void *), void *arg); +void thread_yield(void); +void thread_exit(void); + +// Scheduler function +void scheduler(void); + +// Synchronization functions (mutex spinlocks) +void mutex_init(void); +void mutex_lock(void); +void mutex_unlock(void); #endif // THREADING_H diff --git a/kernel/vga.c b/kernel/vga.c index ee5e358..bb8a1c2 100644 --- a/kernel/vga.c +++ b/kernel/vga.c @@ -1,4 +1,20 @@ #include "vga.h" +#include +#include +#include // Include for vsnprintf +#include // Include for strlen +#include // Include for va_list, va_start, etc. + +void outb(uint16_t port, uint8_t value) { + __asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port)); +} + +// Read a byte from the specified port +uint8_t inb(uint16_t port) { + uint8_t value; + __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port)); + return value; +} uint8_t vga_entry_color(vga_color fg, vga_color bg) { return fg | bg << 4; @@ -6,4 +22,130 @@ uint8_t vga_entry_color(vga_color fg, vga_color bg) { uint16_t vga_entry(unsigned char uc, uint8_t color) { return (uint16_t)uc | (uint16_t)color << 8; -} \ No newline at end of file +} + +void vga_put_entry_at(char c, uint8_t color, size_t x, size_t y) { + const size_t index = y * 80 + x; + ((uint16_t*) 0xB8000)[index] = vga_entry(c, color); +} + +void vga_clear(uint8_t color) { + uint16_t blank = vga_entry(' ', color); + for (size_t i = 0; i < 80 * 25; ++i) { + ((uint16_t*) 0xB8000)[i] = blank; + } +} + +void vga_write_string(const char* data, size_t size) { + size_t x = 0; + size_t y = 0; + for (size_t i = 0; i < size; ++i) { + if (x >= 80) { // If we reach the end of a line, move to the next line + x = 0; + y++; + } + + if (y >= 25) { // If we reach the bottom of the screen, scroll + vga_scroll(); + y = 24; // Reset to the last row + } + + vga_put_entry_at(data[i], vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK), x, y); + x++; // Move to the next column + } +} + +void vga_scroll(void) { + uint16_t* video_memory = (uint16_t*)0xB8000; + // Shift all lines up by one row (80 columns per row) + for (size_t i = 0; i < 24 * 80; ++i) { + video_memory[i] = video_memory[i + 80]; // Move one row up + } + + // Clear the last row (bottom row) + for (size_t i = 24 * 80; i < 25 * 80; ++i) { + video_memory[i] = vga_entry(' ', vga_entry_color(VGA_COLOR_BLACK, VGA_COLOR_WHITE)); + } +} + +void vga_set_cursor_position(size_t x, size_t y) { + uint16_t position = y * 80 + x; // Calculate linear index (y * 80 + x) + + // Set the high byte of the cursor position + outb(VGA_PORT_INDEX, 0x0E); // Cursor high byte register + outb(VGA_PORT_DATA, position >> 8); + + // Set the low byte of the cursor position + outb(VGA_PORT_INDEX, 0x0F); // Cursor low byte register + outb(VGA_PORT_DATA, position & 0xFF); +} + +size_t vga_get_cursor_position(void) { + outb(VGA_PORT_INDEX, 0x0E); // Cursor high byte register + uint8_t high = inb(VGA_PORT_DATA); // Read high byte + + outb(VGA_PORT_INDEX, 0x0F); // Cursor low byte register + uint8_t low = inb(VGA_PORT_DATA); // Read low byte + + return (high << 8) | low; // Combine the high and low bytes +} + +void vga_set_cursor_blinking(bool enable) { + outb(VGA_PORT_INDEX, 0x0A); // Cursor control register + uint8_t cursor = inb(VGA_PORT_DATA); + if (enable) { + cursor |= 0x01; // Enable blinking + } else { + cursor &= ~0x01; // Disable blinking + } + outb(VGA_PORT_INDEX, 0x0A); // Cursor control register + outb(VGA_PORT_DATA, cursor); +} + +void vga_set_cursor_shape(uint8_t start, uint8_t end) { + outb(VGA_PORT_INDEX, 0x0A); // Cursor control register + uint8_t cursor = inb(VGA_PORT_DATA); + cursor = (cursor & 0xC0) | (start & 0x3F); // Set start of cursor shape + outb(VGA_PORT_DATA, cursor); + + outb(VGA_PORT_INDEX, 0x0B); // Cursor start register + outb(VGA_PORT_DATA, end & 0x3F); // Set end of cursor shape +} + +void vga_set_cursor_color(uint8_t color) { + outb(VGA_PORT_INDEX, 0x0A); // Cursor control register + uint8_t cursor = inb(VGA_PORT_DATA); + cursor = (cursor & 0xC0) | (color & 0x3F); // Set cursor color + outb(VGA_PORT_DATA, cursor); +} + +void vga_set_cursor_blink_rate(uint8_t rate) { + outb(VGA_PORT_INDEX, 0x0A); // Cursor control register + uint8_t cursor = inb(VGA_PORT_DATA); + cursor = (cursor & 0xC0) | (rate & 0x3F); // Set cursor blink rate + outb(VGA_PORT_DATA, cursor); +} + +void vga_printf(const char* format, ...) { + char buffer[256]; // Buffer to store the formatted string + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + // Now you can use the buffer with vga_write_string + vga_write_string(buffer, strlen(buffer)); +} + +void vga_init(void) { + // Clear the screen + vga_clear(vga_entry_color(VGA_COLOR_BLACK, VGA_COLOR_LIGHT_GREY)); + + // Set the cursor to the top-left corner + vga_set_cursor_position(0, 0); + + // Optionally, set cursor blinking and shape + vga_set_cursor_blinking(true); + vga_set_cursor_shape(0x20, 0x3F); // Default shape +} + diff --git a/kernel/vga.h b/kernel/vga.h index f3a4883..e37b2cf 100644 --- a/kernel/vga.h +++ b/kernel/vga.h @@ -2,7 +2,11 @@ #define VGA_H #include +#include +#include +#include // For va_list, va_start, etc. +// VGA color definitions typedef enum { VGA_COLOR_BLACK = 0, VGA_COLOR_BLUE = 1, @@ -22,7 +26,28 @@ typedef enum { VGA_COLOR_WHITE = 15, } vga_color; +// VGA port addresses +typedef enum { + VGA_PORT_INDEX = 0x3D4, // Index register for VGA + VGA_PORT_DATA = 0x3D5 // Data register for VGA +} vga_io_port_t; + +// Function prototypes uint8_t vga_entry_color(vga_color fg, vga_color bg); uint16_t vga_entry(unsigned char uc, uint8_t color); -#endif +void vga_put_entry_at(char c, uint8_t color, size_t x, size_t y); +void vga_clear(uint8_t color); +void vga_write_string(const char* data, size_t size); +void vga_scroll(void); +void vga_set_cursor_position(size_t x, size_t y); +size_t vga_get_cursor_position(void); + +void vga_set_cursor_blinking(bool enable); +void vga_set_cursor_shape(uint8_t start, uint8_t end); +void vga_set_cursor_color(uint8_t color); +void vga_set_cursor_blink_rate(uint8_t rate); + +void vga_printf(const char* format, ...); + +#endif \ No newline at end of file