This commit is contained in:
boreddevnl 2026-02-26 22:31:54 +01:00
parent a34aaa1070
commit f9d84d434e
18 changed files with 303 additions and 135 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
disk.img

Binary file not shown.

View file

@ -3,8 +3,6 @@ timeout: 3
# Graphics mode and Splash screen # Graphics mode and Splash screen
term_palette: ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff term_palette: ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff
term_background: #00000000 term_background: #00000000
# Hide terminal by placing it out of view or making it very small initially if possible,
# but Limine's wallapper will be the main background.
wallpaper: boot():/splash.jpg wallpaper: boot():/splash.jpg
/BoredOS /BoredOS

View file

@ -18,6 +18,7 @@ void cli_cmd_boredver(char *args);
void cli_cmd_clear(char *args); void cli_cmd_clear(char *args);
void cli_cmd_exit(char *args); void cli_cmd_exit(char *args);
// Filesystem commands // Filesystem commands
void cli_cmd_cd(char *args); void cli_cmd_cd(char *args);
void cli_cmd_pwd(char *args); void cli_cmd_pwd(char *args);

View file

@ -361,7 +361,6 @@ void pager_wrap_content(const char **lines, int count) {
pager_total_lines++; pager_total_lines++;
processed += chunk_len; processed += chunk_len;
// Skip the space we just split on
if (processed < len && line[processed] == ' ') { if (processed < len && line[processed] == ' ') {
processed++; processed++;
} }
@ -425,7 +424,6 @@ static void internal_cmd_cd(char *args) {
} }
path[i] = 0; path[i] = 0;
// For cmd_state, we need to build and validate the full path
if (cmd_state) { if (cmd_state) {
// Build full path for validation // Build full path for validation
char full_path[512] = {0}; char full_path[512] = {0};
@ -942,9 +940,7 @@ static void cmd_exec_single(char *cmd) {
if (needs_path) { if (needs_path) {
if (args && args[0]) { if (args && args[0]) {
// For echo with redirection, we need to prepend drive to redirect target too
if (is_echo_command) { if (is_echo_command) {
// Find > or >> and prepend drive to the filename after it
char temp_args[512] = {0}; char temp_args[512] = {0};
int i = 0; int i = 0;
int j = 0; int j = 0;

View file

@ -112,7 +112,7 @@ static int ata_identify(uint16_t port_base, bool slave) {
// Read 256 words (512 bytes) of identity data // Read 256 words (512 bytes) of identity data
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
uint16_t data = inw(port_base + ATA_REG_DATA); uint16_t data = inw(port_base + ATA_REG_DATA);
(void)data; // We discard identity data for now, just checking presence (void)data;
} }
return 1; return 1;

View file

@ -5,8 +5,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
// === RAMFS Implementation (Drive A:) ===
// We keep the original logic for Drive A to preserve existing OS functionality.
#define MAX_FILES 256 #define MAX_FILES 256
#define MAX_CLUSTERS 1024 #define MAX_CLUSTERS 1024
@ -149,17 +147,14 @@ static char parse_drive_from_path(const char **path_ptr) {
// Normalize path (remove .., ., etc) // Normalize path (remove .., ., etc)
void fat32_normalize_path(const char *path, char *normalized) { void fat32_normalize_path(const char *path, char *normalized) {
// Basic normalization
// If we have a drive letter, strip it for internal processing logic if needed,
// but the output 'normalized' should conceptually be the path *on that drive*.
char temp[FAT32_MAX_PATH]; char temp[FAT32_MAX_PATH];
int temp_len = 0; int temp_len = 0;
const char *p = path; const char *p = path;
char drive = parse_drive_from_path(&p); char drive = parse_drive_from_path(&p);
// Initialize with current directory or root
// If drive changed, we assume root of that drive
if (p[0] == '/') { if (p[0] == '/') {
fs_strcpy(temp, "/"); fs_strcpy(temp, "/");
temp_len = 1; temp_len = 1;
@ -632,7 +627,6 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
} }
if (!found) { if (!found) {
// Check if we want to create file
if ((mode[0] == 'w' || mode[0] == 'a') && *p == 0) { if ((mode[0] == 'w' || mode[0] == 'a') && *p == 0) {
// Create file logic // Create file logic
char dos_name[11]; char dos_name[11];
@ -1030,7 +1024,6 @@ static bool realfs_delete(char drive, const char *path) {
if (*p == 0) break; // End of path if (*p == 0) break; // End of path
} }
// We found the file entry - now delete it
// 1. Mark directory entry as deleted // 1. Mark directory entry as deleted
uint8_t *entry_buf = (uint8_t*)kmalloc(512); uint8_t *entry_buf = (uint8_t*)kmalloc(512);
@ -1090,16 +1083,11 @@ static int realfs_list_directory(char drive, const char *path, FAT32_FileInfo *e
} }
FAT32_Volume *vol = &volumes[vol_idx]; FAT32_Volume *vol = &volumes[vol_idx];
// Find directory start cluster
// Reuse realfs_open logic basically to find the cluster
// but without creating a handle.
// For simplicity, just use realfs_open and then read the directory entries
FAT32_FileHandle *dir_handle = realfs_open(drive, path, "r"); FAT32_FileHandle *dir_handle = realfs_open(drive, path, "r");
if (!dir_handle) return 0; if (!dir_handle) return 0;
// Extract start_cluster BEFORE closing the handle
uint32_t current_cluster = dir_handle->start_cluster; uint32_t current_cluster = dir_handle->start_cluster;
// We don't use the handle for reading via realfs_read because directories are special
fat32_close(dir_handle); // Return to pool - this invalidates the handle fat32_close(dir_handle); // Return to pool - this invalidates the handle
int count = 0; int count = 0;
@ -1236,9 +1224,7 @@ void fat32_close(FAT32_FileHandle *handle) {
entry->start_cluster_high = (handle->start_cluster >> 16); entry->start_cluster_high = (handle->start_cluster >> 16);
entry->start_cluster_low = (handle->start_cluster & 0xFFFF); entry->start_cluster_low = (handle->start_cluster & 0xFFFF);
} }
// Write back with error checking
if (d->write_sector(d, handle->dir_sector, buf) != 0) { if (d->write_sector(d, handle->dir_sector, buf) != 0) {
// Write failed - at least we tried
} }
} }
kfree(buf); kfree(buf);
@ -1506,26 +1492,13 @@ bool fat32_is_directory(const char *path) {
} else { } else {
FAT32_FileHandle *fh = realfs_open(drive, p, "r"); FAT32_FileHandle *fh = realfs_open(drive, p, "r");
if (fh) { if (fh) {
// Wait, open checks if file/dir.
// We need to check if what we opened is a directory.
// realfs_open returns handle for directory too if strictly reading?
// Actually my realfs_open logic tries to find the entry.
// If it returns a handle, how do we know if it was a dir?
// Handle doesn't store attributes.
// But we can check if size == 0 (often for dirs) or inferred from how we opened it.
// Better: use realfs_list_directory check or modify open to return attributes?
// For now, let's assume if we can open it and it has size 0 (or we opened root), it's dir.
// This is imperfect.
// Correct way: Add attributes to FAT32_FileHandle or separate check function.
// Let's rely on naming convention or just return false for now if not root.
if (fs_strcmp(p, "/") == 0 || fs_strcmp(p, "") == 0) is_dir = true; if (fs_strcmp(p, "/") == 0 || fs_strcmp(p, "") == 0) is_dir = true;
else { else {
// Hack: check if list_directory returns > 0 entries? No empty dirs exists.
// We need to improve realfs_open to store attr.
} }
fat32_close(fh); fat32_close(fh);
} }
// Workaround: assume true if path ends in /? No.
} }
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));
@ -1586,23 +1559,15 @@ bool fat32_chdir(const char *path) {
} }
} }
// Change dir on current drive
if (fat32_is_directory(path)) { if (fat32_is_directory(path)) {
// Normalize and set
if (drive == 'A') { if (drive == 'A') {
char normalized[FAT32_MAX_PATH]; char normalized[FAT32_MAX_PATH];
fat32_normalize_path(p, normalized); fat32_normalize_path(p, normalized);
fs_strcpy(current_dir, normalized); fs_strcpy(current_dir, normalized);
} else { } else {
// For real drive, just store path
// Need a way to validate path exists on real drive first
// fat32_is_directory call above should suffice?
// But my realfs is_directory is weak.
fs_strcpy(current_dir, p); fs_strcpy(current_dir, p);
// Ensure leading slash
if (current_dir[0] != '/') { if (current_dir[0] != '/') {
// Prepend /
// ... (skip for brevity, assume absolute paths mostly)
} }
} }
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));

View file

@ -3,7 +3,7 @@
extern void serial_write(const char *str); extern void serial_write(const char *str);
// Simple hex printer for debugging exceptions // Simple hex printer for debugging
static void print_hex(uint64_t val) { static void print_hex(uint64_t val) {
const char* digits = "0123456789ABCDEF"; const char* digits = "0123456789ABCDEF";
char buf[17]; char buf[17];
@ -19,40 +19,64 @@ static void print_hex(uint64_t val) {
#include "process.h" #include "process.h"
#include "cmd.h" #include "cmd.h"
void kernel_panic(registers_t *regs, const char *error_name);
static const char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non-Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved"
};
uint64_t exception_handler_c(registers_t *regs) { uint64_t exception_handler_c(registers_t *regs) {
uint64_t vector = regs->int_no; uint64_t vector = regs->int_no;
uint64_t rip = regs->rip;
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
// Serial Mirror
serial_write("\n*** EXCEPTION ***\nVector: "); serial_write("\n*** EXCEPTION ***\nVector: ");
print_hex(vector); print_hex(vector);
serial_write("\nError Code: ");
print_hex(regs->err_code);
serial_write("\nRIP: ");
print_hex(rip);
serial_write("\nCR2: ");
print_hex(cr2);
// Mirror to shell
if (cmd_get_cursor_col() != 0) cmd_write("\n");
cmd_write("*** EXCEPTION ***\nVector: "); cmd_write_hex(vector);
cmd_write("\nError Code: "); cmd_write_hex(regs->err_code);
cmd_write("\nRIP: "); cmd_write_hex(rip);
cmd_write("\nCR2: "); cmd_write_hex(cr2);
cmd_write("\n");
// Filter by CS selector to check if we are in user mode (RPL=3)
if ((regs->cs & 0x3) != 0) { if ((regs->cs & 0x3) != 0) {
serial_write("\nUSER MODE EXCEPTION - Terminating process.\n"); serial_write("\nUSER MODE EXCEPTION - Terminating process.\n");
cmd_write("USER MODE EXCEPTION - Terminating process.\n"); if (cmd_get_cursor_col() != 0) cmd_write("\n");
cmd_write("*** USER EXCEPTION ***\nVector: "); cmd_write_hex(vector);
cmd_write("\nRIP: "); cmd_write_hex(regs->rip);
cmd_write("\nTerminating process.\n");
return process_terminate_current(); return process_terminate_current();
} }
serial_write("\nKERNEL PANIC - CPU HALTED.\n"); // Kernel mode exception
cmd_write("KERNEL PANIC - CPU HALTED.\n"); const char *name = (vector < 32) ? exception_messages[vector] : "Unknown Kernel Exception";
while(1) { asm volatile("cli; hlt"); } kernel_panic(regs, name);
return (uint64_t)regs; // Unreachable but for completeness
return (uint64_t)regs; // Unreachable
} }
#define IDT_ENTRIES 256 #define IDT_ENTRIES 256
@ -145,10 +169,72 @@ void idt_register_interrupts(void) {
idt_set_gate(44, isr12_wrapper, cs, 0x8E); // Mouse (IRQ 12) idt_set_gate(44, isr12_wrapper, cs, 0x8E); // Mouse (IRQ 12)
// Exceptions // Exceptions
extern void isr8_wrapper(void); extern void exc0_wrapper(void);
extern void isr14_wrapper(void); extern void exc1_wrapper(void);
idt_set_gate(8, isr8_wrapper, cs, 0x8E); // Double Fault extern void exc2_wrapper(void);
idt_set_gate(14, isr14_wrapper, cs, 0x8E); // Page Fault extern void exc3_wrapper(void);
extern void exc4_wrapper(void);
extern void exc5_wrapper(void);
extern void exc6_wrapper(void);
extern void exc7_wrapper(void);
extern void exc8_wrapper(void);
extern void exc9_wrapper(void);
extern void exc10_wrapper(void);
extern void exc11_wrapper(void);
extern void exc12_wrapper(void);
extern void exc13_wrapper(void);
extern void exc14_wrapper(void);
extern void exc15_wrapper(void);
extern void exc16_wrapper(void);
extern void exc17_wrapper(void);
extern void exc18_wrapper(void);
extern void exc19_wrapper(void);
extern void exc20_wrapper(void);
extern void exc21_wrapper(void);
extern void exc22_wrapper(void);
extern void exc23_wrapper(void);
extern void exc24_wrapper(void);
extern void exc25_wrapper(void);
extern void exc26_wrapper(void);
extern void exc27_wrapper(void);
extern void exc28_wrapper(void);
extern void exc29_wrapper(void);
extern void exc30_wrapper(void);
extern void exc31_wrapper(void);
idt_set_gate(0, exc0_wrapper, cs, 0x8E);
idt_set_gate(1, exc1_wrapper, cs, 0x8E);
idt_set_gate(2, exc2_wrapper, cs, 0x8E);
idt_set_gate(3, exc3_wrapper, cs, 0x8E);
idt_set_gate(4, exc4_wrapper, cs, 0x8E);
idt_set_gate(5, exc5_wrapper, cs, 0x8E);
idt_set_gate(6, exc6_wrapper, cs, 0x8E);
idt_set_gate(7, exc7_wrapper, cs, 0x8E);
idt_set_gate(8, exc8_wrapper, cs, 0x8E);
idt_set_gate(9, exc9_wrapper, cs, 0x8E);
idt_set_gate(10, exc10_wrapper, cs, 0x8E);
idt_set_gate(11, exc11_wrapper, cs, 0x8E);
idt_set_gate(12, exc12_wrapper, cs, 0x8E);
idt_set_gate(13, exc13_wrapper, cs, 0x8E);
idt_set_gate(14, exc14_wrapper, cs, 0x8E);
idt_set_gate(15, exc15_wrapper, cs, 0x8E);
idt_set_gate(16, exc16_wrapper, cs, 0x8E);
idt_set_gate(17, exc17_wrapper, cs, 0x8E);
idt_set_gate(18, exc18_wrapper, cs, 0x8E);
idt_set_gate(19, exc19_wrapper, cs, 0x8E);
idt_set_gate(20, exc20_wrapper, cs, 0x8E);
idt_set_gate(21, exc21_wrapper, cs, 0x8E);
idt_set_gate(22, exc22_wrapper, cs, 0x8E);
idt_set_gate(23, exc23_wrapper, cs, 0x8E);
idt_set_gate(24, exc24_wrapper, cs, 0x8E);
idt_set_gate(25, exc25_wrapper, cs, 0x8E);
idt_set_gate(26, exc26_wrapper, cs, 0x8E);
idt_set_gate(27, exc27_wrapper, cs, 0x8E);
idt_set_gate(28, exc28_wrapper, cs, 0x8E);
idt_set_gate(29, exc29_wrapper, cs, 0x8E);
idt_set_gate(30, exc30_wrapper, cs, 0x8E);
idt_set_gate(31, exc31_wrapper, cs, 0x8E);
} }
void idt_load(void) { void idt_load(void) {

View file

@ -74,28 +74,66 @@ isr1_wrapper:
isr12_wrapper: isr12_wrapper:
ISR_NOERRCODE mouse_handler, 44 ISR_NOERRCODE mouse_handler, 44
; Common exception macro ; Common exception macro for exceptions WITHOUT error code
%macro EXCEPTION_ERRCODE 1 %macro EXCEPTION_NOERRCODE 1
isr%1_wrapper: global exc%1_wrapper
push %1 exc%1_wrapper:
push 0 ; Dummy error code
push %1 ; Vector
jmp exception_common jmp exception_common
%endmacro %endmacro
; Exception 8: Double Fault (has error code) ; Common exception macro for exceptions WITH error code
EXCEPTION_ERRCODE 8 %macro EXCEPTION_ERRCODE 1
global exc%1_wrapper
exc%1_wrapper:
push %1 ; Vector
jmp exception_common
%endmacro
; Exception 14: Page Fault (has error code) ; Define all 32 standard exceptions
EXCEPTION_ERRCODE 14 EXCEPTION_NOERRCODE 0 ; Divide Error
EXCEPTION_NOERRCODE 1 ; Debug
EXCEPTION_NOERRCODE 2 ; NMI
EXCEPTION_NOERRCODE 3 ; Breakpoint
EXCEPTION_NOERRCODE 4 ; Overflow
EXCEPTION_NOERRCODE 5 ; Bound Range Exceeded
EXCEPTION_NOERRCODE 6 ; Invalid Opcode
EXCEPTION_NOERRCODE 7 ; Device Not Available
EXCEPTION_ERRCODE 8 ; Double Fault
EXCEPTION_NOERRCODE 9 ; Coprocessor Segment Overrun
EXCEPTION_ERRCODE 10 ; Invalid TSS
EXCEPTION_ERRCODE 11 ; Segment Not Present
EXCEPTION_ERRCODE 12 ; Stack-Segment Fault
EXCEPTION_ERRCODE 13 ; General Protection Fault
EXCEPTION_ERRCODE 14 ; Page Fault
EXCEPTION_NOERRCODE 15 ; Reserved
EXCEPTION_NOERRCODE 16 ; x87 Floating-Point Exception
EXCEPTION_ERRCODE 17 ; Alignment Check
EXCEPTION_NOERRCODE 18 ; Machine Check
EXCEPTION_NOERRCODE 19 ; SIMD Floating-Point Exception
EXCEPTION_NOERRCODE 20 ; Virtualization Exception
EXCEPTION_ERRCODE 21 ; Control Protection Exception
EXCEPTION_NOERRCODE 22 ; Reserved
EXCEPTION_NOERRCODE 23 ; Reserved
EXCEPTION_NOERRCODE 24 ; Reserved
EXCEPTION_NOERRCODE 25 ; Reserved
EXCEPTION_NOERRCODE 26 ; Reserved
EXCEPTION_NOERRCODE 27 ; Reserved
EXCEPTION_NOERRCODE 28 ; Hypervisor Injection Exception
EXCEPTION_ERRCODE 29 ; VMM Communication Exception
EXCEPTION_ERRCODE 30 ; Security Exception
EXCEPTION_NOERRCODE 31 ; Reserved
exception_common: exception_common:
; Save registers ; Save registers (registers_t structure)
push rax push rax
push rbx
push rcx push rcx
push rdx push rdx
push rbx
push rbp push rbp
push rsi
push rdi push rdi
push rsi
push r8 push r8
push r9 push r9
push r10 push r10
@ -105,14 +143,15 @@ exception_common:
push r14 push r14
push r15 push r15
; Call C handler: uint64_t exception_handler_c(registers_t *regs) ; Pass current RSP as 1st argument (registers_t*)
mov rdi, rsp mov rdi, rsp
call exception_handler_c call exception_handler_c
; Switch stack if needed (for process termination) ; Switch stack if needed (for process termination)
mov rsp, rax mov rsp, rax
; Restore (in case we want to return, but usually we halt if kernel) ; Restore registers
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13
@ -121,12 +160,13 @@ exception_common:
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop rdi
pop rsi pop rsi
pop rdi
pop rbp pop rbp
pop rbx
pop rdx pop rdx
pop rcx pop rcx
pop rbx
pop rax pop rax
add rsp, 16 ; drop vector and error code add rsp, 16 ; drop vector and error code
iretq iretq

View file

@ -58,7 +58,6 @@ static void hcf(void) {
} }
} }
// Simple serial port initialization and output for debugging
static void init_serial() { static void init_serial() {
outb(0x3F8 + 1, 0x00); outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x80); outb(0x3F8 + 3, 0x80);
@ -84,7 +83,6 @@ void kmain(void) {
platform_init(); platform_init();
serial_write("[DEBUG] platform_init OK\n"); serial_write("[DEBUG] platform_init OK\n");
// 1. Memory Detection and Heap Init
uint64_t heap_phys_addr = 0; uint64_t heap_phys_addr = 0;
size_t heap_size = 0; size_t heap_size = 0;
if (memmap_request.response != NULL) { if (memmap_request.response != NULL) {
@ -99,7 +97,7 @@ void kmain(void) {
} }
} }
if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024; // Cap at 512MB if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024;
if (heap_phys_addr != 0) { if (heap_phys_addr != 0) {
memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size); memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size);
@ -109,7 +107,6 @@ void kmain(void) {
hcf(); hcf();
} }
// 2. Graphics Init
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) { if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
serial_write("[DEBUG] No framebuffer! Halting.\n"); serial_write("[DEBUG] No framebuffer! Halting.\n");
hcf(); hcf();
@ -119,19 +116,15 @@ void kmain(void) {
graphics_init(fb); graphics_init(fb);
serial_write("[DEBUG] graphics_init OK\n"); serial_write("[DEBUG] graphics_init OK\n");
// 3. GDT & TSS Init
gdt_init(); gdt_init();
serial_write("[DEBUG] gdt_init OK\n"); serial_write("[DEBUG] gdt_init OK\n");
// 4. Paging Init
paging_init(); paging_init();
serial_write("[DEBUG] paging_init OK\n"); serial_write("[DEBUG] paging_init OK\n");
// 5. Syscall Init
syscall_init(); syscall_init();
serial_write("[DEBUG] syscall_init OK\n"); serial_write("[DEBUG] syscall_init OK\n");
// 6. Interrupts Init
idt_init(); idt_init();
idt_register_interrupts(); idt_register_interrupts();
idt_load(); idt_load();
@ -141,13 +134,11 @@ void kmain(void) {
serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n"); serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n");
// Initialize FAT32 RAMFS and mount Limine modules
fat32_init(); fat32_init();
if (module_request.response != NULL) { if (module_request.response != NULL) {
for (uint64_t i = 0; i < module_request.response->module_count; i++) { for (uint64_t i = 0; i < module_request.response->module_count; i++) {
struct limine_file *mod = module_request.response->modules[i]; struct limine_file *mod = module_request.response->modules[i];
// mod->path typically starts with a '/' from Limine
FAT32_FileHandle *fh = fat32_open(mod->path, "w"); FAT32_FileHandle *fh = fat32_open(mod->path, "w");
if (fh && fh->valid) { if (fh && fh->valid) {
fat32_write(fh, mod->address, mod->size); fat32_write(fh, mod->address, mod->size);
@ -159,25 +150,20 @@ void kmain(void) {
} }
} }
int ENABLE_USER_TEST = 1; // Set to 1 to test User Mode ring 3 jump int ENABLE_USER_TEST = 1;
#ifdef ENABLE_USER_TEST #ifdef ENABLE_USER_TEST
process_init(); process_init();
// The desktop is PID 0
#endif #endif
// 3. PS/2 Init (Mouse/Keyboard)
asm("cli"); asm("cli");
ps2_init(); ps2_init();
asm("sti"); asm("sti");
// 4. Window Manager Init (Draws initial desktop)
wm_init(); wm_init();
// Re-enable interrupts since we removed sti from idt_load
asm volatile("sti"); asm volatile("sti");
// 5. Main loop - just wait for interrupts
// Timer interrupt will drive the redraw system
while (1) { while (1) {
wm_process_input(); wm_process_input();
wm_process_deferred_thumbs(); wm_process_deferred_thumbs();

View file

@ -159,11 +159,9 @@ void memory_manager_init_at(void *pool_address, size_t pool_size) {
} }
void memory_manager_init_with_size(size_t pool_size) { void memory_manager_init_with_size(size_t pool_size) {
// This is now just a wrapper if init_at wasn't called.
// However, in BoredOS we now prefer explicit init_at.
if (initialized) return; if (initialized) return;
// Fallback: we still need a buffer if no address is provided?
// Let's assume for now that BoredOS always calls init_at.
} }
void memory_manager_init(void) { void memory_manager_init(void) {
@ -183,7 +181,6 @@ void* kmalloc_aligned(size_t size, size_t alignment) {
return NULL; return NULL;
} }
// Check if we can allocate
if (total_allocated + size > memory_pool_size) { if (total_allocated + size > memory_pool_size) {
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));
return NULL; return NULL;

View file

@ -19,7 +19,6 @@ static void write_cr3(uint64_t cr3) {
// Helper to allocate a page table and clear it // Helper to allocate a page table and clear it
static uint64_t alloc_page_table_phys(void) { static uint64_t alloc_page_table_phys(void) {
// We allocate a page table in Virtual Memory (HHDM)
void* ptr = kmalloc(PAGE_SIZE * 2); void* ptr = kmalloc(PAGE_SIZE * 2);
if (!ptr) return 0; if (!ptr) return 0;
@ -41,8 +40,7 @@ static uint64_t alloc_page_table_phys(void) {
} }
void paging_init(void) { void paging_init(void) {
// Limine sets up a highly mapped page table for us.
// CR3 contains the physical address of the PML4.
current_pml4_phys = read_cr3() & PT_ADDR_MASK; current_pml4_phys = read_cr3() & PT_ADDR_MASK;
} }

116
src/kernel/panic.c Normal file
View file

@ -0,0 +1,116 @@
#include "process.h"
#include "graphics.h"
#include "io.h"
extern void serial_write(const char *str);
static void draw_string_centered(int y, const char *s, uint32_t color) {
if (!s) return;
int len = 0;
while (s[len]) len++;
int x = (get_screen_width() - (len * 8)) / 2;
draw_string(x, y, s, color);
}
void kernel_panic(registers_t *regs, const char *error_name) {
// Disable interrupts to prevent nested panics
asm volatile("cli");
// Clear back buffer to black
graphics_clear_back_buffer(0x00000000);
int sh = get_screen_height();
int cy = sh / 2;
// Draw header
draw_string_centered(cy - 150, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", 0xFFFF0000);
draw_string_centered(cy - 130, "KERNEL EXCEPTION OCCURRED", 0xFFFFFFFF);
draw_string_centered(cy - 110, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", 0xFFFF0000);
// Error name
char err_buf[256];
int pos = 0;
const char *prefix = "Exception: ";
while(prefix[pos]) { err_buf[pos] = prefix[pos]; pos++; }
int i = 0;
while(error_name[i]) { err_buf[pos++] = error_name[i++]; }
err_buf[pos] = 0;
draw_string_centered(cy - 70, err_buf, 0xFFFFCC00);
// Details - simplified centering by drawing them as a block or individually centered
char info_buf[64];
// Vector
pos = 0;
prefix = "Vector: ";
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
uint64_t v = regs->int_no;
const char* digits = "0123456789ABCDEF";
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
info_buf[pos + i] = digits[v & 0xF];
v >>= 4;
}
info_buf[pos + 16] = 0;
draw_string_centered(cy - 40, info_buf, 0xFFFFFFFF);
// Error Code
pos = 0;
prefix = "Error Code: ";
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
v = regs->err_code;
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
info_buf[pos + i] = digits[v & 0xF];
v >>= 4;
}
info_buf[pos + 16] = 0;
draw_string_centered(cy - 20, info_buf, 0xFFFFFFFF);
// RIP
pos = 0;
prefix = "RIP: ";
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
v = regs->rip;
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
info_buf[pos + i] = digits[v & 0xF];
v >>= 4;
}
info_buf[pos + 16] = 0;
draw_string_centered(cy, info_buf, 0xFFFFFFFF);
// CR2 for page faults
if (regs->int_no == 14) {
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
pos = 0;
prefix = "CR2: ";
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
info_buf[pos + i] = digits[cr2 & 0xF];
cr2 >>= 4;
}
info_buf[pos + 16] = 0;
draw_string_centered(cy + 20, info_buf, 0xFFFF5555);
}
// Message
draw_string_centered(cy + 100, "The system has been halted to prevent damage.", 0xFFFFFFFF);
draw_string_centered(cy + 120, "Please restart your computer.", 0xFFAAAAAA);
// Flip buffer to screen
graphics_mark_screen_dirty();
graphics_flip_buffer();
serial_write("\n*** KERNEL PANIC ***\n");
serial_write(error_name);
serial_write("\n");
// Halt
while(1) {
asm volatile("cli; hlt");
}
}

View file

@ -336,8 +336,6 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
asm volatile("pushfq; pop %0; cli" : "=r"(rflags)); asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (win->pixels) { if (win->pixels) {
// String clipping is handled by draw_char -> put_pixel,
// but we ensure coordinate sanity here
if (ux >= -100 && ux < win->w && uy >= -100 && uy < (win->h - 20)) { if (ux >= -100 && ux < win->w && uy >= -100 && uy < (win->h - 20)) {
graphics_set_render_target(win->pixels, win->w, win->h - 20); graphics_set_render_target(win->pixels, win->w, win->h - 20);
draw_string(ux, uy, kernel_str, color); draw_string(ux, uy, kernel_str, color);

View file

@ -325,8 +325,6 @@ static void editor_paint(ui_window_t win) {
ui_draw_rounded_rect_filled(win, padding, status_y + 2, content_width, footer_h - 4, 6, COLOR_DARK_PANEL); ui_draw_rounded_rect_filled(win, padding, status_y + 2, content_width, footer_h - 4, 6, COLOR_DARK_PANEL);
char status_text[128]; char status_text[128];
// Simple manual sprintf-like functionality for BoredOS userspace
// We'll just draw parts for now as before but cleaned up
ui_draw_string(win, padding + 15, status_y + 5, "Line:", COLOR_DKGRAY); ui_draw_string(win, padding + 15, status_y + 5, "Line:", COLOR_DKGRAY);
char line_str[32]; char line_str[32];

View file

@ -464,14 +464,9 @@ int vm_exec(const uint8_t *code, int code_size) {
vm_reset(); vm_reset();
// Reset Graphics Overlay
vm_rect_count = 0; vm_rect_count = 0;
wm_custom_paint_hook = vm_paint_overlay; wm_custom_paint_hook = vm_paint_overlay;
// Copy data segment if any?
// For this simple VM, we will copy the ENTIRE bytecode to the start of memory
// So code and data share the same space (Von Neumann)
// But we need to be careful not to overwrite running code if we write to it
// Safety check // Safety check
if (code_size > VM_MEMORY_SIZE) { if (code_size > VM_MEMORY_SIZE) {
@ -489,13 +484,7 @@ int vm_exec(const uint8_t *code, int code_size) {
while (pc < code_size) { while (pc < code_size) {
uint8_t op = memory[pc++]; uint8_t op = memory[pc++];
// DEBUGGING
/*
cmd_write("PC:"); cmd_write_int(pc-1);
cmd_write(" OP:"); cmd_write_int(op);
cmd_write(" SP:"); cmd_write_int(sp);
cmd_write("\n");
*/
switch (op) { switch (op) {
case OP_HALT: case OP_HALT: