fixing the remaining issues in the kernel directory

This commit is contained in:
Gregory Kenneth Bowne 2025-06-16 15:13:37 -07:00
parent 69762b6650
commit 109e554524
11 changed files with 422 additions and 60 deletions

View File

@ -11,7 +11,7 @@ acpi_rsdp_t* acpi_find_rsdp() {
acpi_rsdp_t* rsdp = (acpi_rsdp_t*)addr; acpi_rsdp_t* rsdp = (acpi_rsdp_t*)addr;
if (memcmp(rsdp->signature, "RSD PTR ", 8) == 0) { if (memcmp(rsdp->signature, "RSD PTR ", 8) == 0) {
uint8_t checksum = 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]; checksum += ((uint8_t*)rsdp)[i];
} }
if (checksum == 0) { 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; acpi_rsdt_t* rsdt = (acpi_rsdt_t*)rsdt_or_xsdt;
uint32_t num_tables = (rsdt->length - sizeof(acpi_rsdt_t)) / sizeof(uint32_t); 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]; uint32_t table_addr = rsdt->tables[i];
acpi_fadt_t* fadt = (acpi_fadt_t*)table_addr; acpi_fadt_t* fadt = (acpi_fadt_t*)table_addr;
if (fadt->signature == 0x50434146) { // "FACP" in ASCII if (fadt->signature == 0x50434146) {
uint8_t checksum = 0; 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]; checksum += ((uint8_t*)fadt)[j];
} }
if (checksum == 0) { if (checksum == 0) {
return fadt; // Valid FADT found return fadt;
} }
} }
} }
return NULL; // FADT not found return NULL;
} }

View File

@ -1,5 +1,45 @@
#include "debug.h" #include "debug.h"
#include "vga.h"
#include <stdint.h>
#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) { 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++;
}
} }

View File

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

View File

@ -0,0 +1,14 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <stdint.h>
#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

View File

@ -48,7 +48,6 @@ void kmain(void) {
kmalloc_init(0xC0100000); // Virtual heap start address (must be mapped!) kmalloc_init(0xC0100000); // Virtual heap start address (must be mapped!)
serial_write("kmalloc initialized.\n"); serial_write("kmalloc initialized.\n");
void* ptr = kmalloc(128); // Allocation test
serial_write("Allocated 128 bytes.\n"); serial_write("Allocated 128 bytes.\n");
terminal_write("Initializing timer...\n"); terminal_write("Initializing timer...\n");

View File

@ -1,66 +1,27 @@
// mouse.c
#include "mouse.h" #include "mouse.h"
#include "usb.h" #include "usb.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
// Struct to store mouse state
typedef struct {
int x;
int y;
bool left_button;
bool right_button;
} mouse_data_t;
// Mouse buffer // Mouse buffer
static mouse_data_t mouse_data; 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 // Read USB mouse data
mouse_data_t usb_read_mouse(void) { mouse_data_t usb_read_mouse(void) {
uint8_t buffer[3]; // USB HID Mouse reports typically use 3 bytes 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 // Process the received data
mouse_data.x += buffer[1]; // X movement mouse_data.x += buffer[1]; // X movement
mouse_data.y += buffer[2]; // Y movement mouse_data.y += buffer[2]; // Y movement
mouse_data.left_button = buffer[0] & 0x01; mouse_data.left_button = buffer[0] & 0x01;
mouse_data.right_button = buffer[0] & 0x02; 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; 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;
}

View File

@ -23,3 +23,4 @@ bool uhci_init(void);
bool ohci_init(void); bool ohci_init(void);
#endif // MOUSE_H #endif // MOUSE_H

View File

@ -1,5 +1,118 @@
#include "threading.h" #include "threading.h"
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
void threading_init() { #define MAX_THREADS 16 // Maximum number of threads
// Threading initialization code #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);
} }

View File

@ -1,6 +1,36 @@
#ifndef THREADING_H #ifndef THREADING_H
#define THREADING_H #define THREADING_H
void threading_init(); #include <stdint.h>
#include <stddef.h>
// 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 #endif // THREADING_H

View File

@ -1,4 +1,20 @@
#include "vga.h" #include "vga.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h> // Include for vsnprintf
#include <string.h> // Include for strlen
#include <stdarg.h> // 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) { uint8_t vga_entry_color(vga_color fg, vga_color bg) {
return fg | bg << 4; return fg | bg << 4;
@ -7,3 +23,129 @@ uint8_t vga_entry_color(vga_color fg, vga_color bg) {
uint16_t vga_entry(unsigned char uc, uint8_t color) { uint16_t vga_entry(unsigned char uc, uint8_t color) {
return (uint16_t)uc | (uint16_t)color << 8; return (uint16_t)uc | (uint16_t)color << 8;
} }
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
}

View File

@ -2,7 +2,11 @@
#define VGA_H #define VGA_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdarg.h> // For va_list, va_start, etc.
// VGA color definitions
typedef enum { typedef enum {
VGA_COLOR_BLACK = 0, VGA_COLOR_BLACK = 0,
VGA_COLOR_BLUE = 1, VGA_COLOR_BLUE = 1,
@ -22,7 +26,28 @@ typedef enum {
VGA_COLOR_WHITE = 15, VGA_COLOR_WHITE = 15,
} vga_color; } 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); uint8_t vga_entry_color(vga_color fg, vga_color bg);
uint16_t vga_entry(unsigned char uc, uint8_t color); uint16_t vga_entry(unsigned char uc, uint8_t color);
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 #endif