Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ CMakeLists.txt
*build*
target
.venv
*cache*
*cache*
.amazonq
22 changes: 20 additions & 2 deletions arch/x86_64/interrupts/Interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ asmlinkage void InterruptHandler(Registers* regs) {
// If we get here, it's a serious kernel fault
FaultContext ctx = {0};
AnalyzeFault(regs, &ctx);
PrintDetailedFaultInfo(&ctx, regs);RegistersDumpT dump = {0};
PrintDetailedFaultInfo(&ctx, regs);
RegistersDumpT dump = {0};
DumpRegisters(&dump);
// Override with fault context where applicable
dump.rip = regs->rip;
Expand All @@ -116,6 +117,15 @@ asmlinkage void InterruptHandler(Registers* regs) {
FaultContext ctx = {0};
AnalyzeFault(regs, &ctx);
PrintDetailedFaultInfo(&ctx, regs);
RegistersDumpT dump = {0};
DumpRegisters(&dump);
// Override with fault context where applicable
dump.rip = regs->rip;
dump.cs = regs->cs;
dump.rflags = regs->rflags;
dump.rsp = regs->rsp;
dump.ss = regs->ss;
PrintRegisters(&dump);
PanicFromInterrupt(ctx.fault_reason, regs);
break;
}
Expand All @@ -125,7 +135,15 @@ asmlinkage void InterruptHandler(Registers* regs) {
char int_str[20], rip_str[20];
itoa(regs->interrupt_number, int_str);
htoa(regs->rip, rip_str);

RegistersDumpT dump = {0};
DumpRegisters(&dump);
// Override with fault context where applicable
dump.rip = regs->rip;
dump.cs = regs->cs;
dump.rflags = regs->rflags;
dump.rsp = regs->rsp;
dump.ss = regs->ss;
PrintRegisters(&dump);
strcpy(panic_message, "Unhandled Exception #");
strcat(panic_message, int_str);
strcat(panic_message, " at ");
Expand Down
120 changes: 97 additions & 23 deletions drivers/Vesa.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,34 @@ void VBEFillScreen(uint32_t color) {
void VBEDrawRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color) {
if (!vbe_initialized) return;

for (uint32_t row = y; row < y + height && row < vbe_info.height; row++) {
for (uint32_t col = x; col < x + width && col < vbe_info.width; col++) {
VBEPutPixel(col, row, color);
if (x >= vbe_info.width || y >= vbe_info.height) return;

// Clip
if (width > vbe_info.width - x) width = vbe_info.width - x;
if (height > vbe_info.height - y) height = vbe_info.height - y;
if (width == 0 || height == 0) return;

uint32_t mapped = VBEMapColor(color);

uint8_t* fb = (uint8_t*)vbe_info.framebuffer;
uint32_t pitch = vbe_info.pitch;

// Pattern buffer: 1 KiB = 256 pixels
uint32_t pattern[256];
for (uint32_t i = 0; i < 256; i++) pattern[i] = mapped;

uint64_t row_bytes = (uint64_t)width * 4u;

for (uint32_t r = 0; r < height; r++) {
uint8_t* dst = fb + (uint64_t)(y + r) * pitch + (uint64_t)x * 4u;
uint64_t remaining = row_bytes;
while (remaining >= sizeof(pattern)) {
FastMemcpy(dst, pattern, sizeof(pattern));
dst += sizeof(pattern);
remaining -= sizeof(pattern);
}
if (remaining) {
FastMemcpy(dst, pattern, remaining);
}
}
}
Expand Down Expand Up @@ -187,21 +212,40 @@ void VBEDrawChar(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_
return; // Character out of bounds
}

// Clip early if entirely outside
if (x >= vbe_info.width || y >= vbe_info.height) return;

const unsigned char* glyph = console_font[(unsigned char)c];

// Pre-map colors
uint32_t fg = VBEMapColor(fg_color);
uint32_t bg = VBEMapColor(bg_color);

uint32_t max_w = vbe_info.width;
uint32_t max_h = vbe_info.height;

// Use the font dimensions from font.h
for (int row = 0; row < FONT_HEIGHT; row++) {
uint32_t py = y + (uint32_t)row;
if (py >= max_h) break; // Outside vertical bounds

// Calculate which byte contains this row's data
int byte_index = row * ((FONT_WIDTH + 7) / 8); // Number of bytes per row

// Start of the destination row in framebuffer
uint32_t* dst_row = (uint32_t*)((uint8_t*)vbe_info.framebuffer + (uint64_t)py * vbe_info.pitch) + x;

for (int col = 0; col < FONT_WIDTH; col++) {
int bit_position = 7 - (col % 8); // MSB first
uint32_t px = x + (uint32_t)col;
if (px >= max_w) break; // Outside horizontal bounds

if ((glyph[byte_index + (col / 8)] >> bit_position) & 1) {
VBEPutPixel(x + col, y + row, fg_color);
int bit_position = 7 - (col % 8); // MSB first
uint8_t glyph_byte = glyph[byte_index + (col / 8)];
if ((glyph_byte >> bit_position) & 1) {
dst_row[col] = fg;
} else {
// Always draw background to ensure proper clearing
VBEPutPixel(x + col, y + row, bg_color);
dst_row[col] = bg;
}
}
}
Expand Down Expand Up @@ -288,32 +332,62 @@ void VBEShowSplash(void) {
if (!vbe_initialized) return;

for (unsigned int i = 0; i < num_splash_images; i++) { // Loop
const uint32_t* image_data = (const uint32_t*)splash_images[i % num_splash_images];

const uint32_t* image_data = (const uint32_t*)splash_images[i];
uint8_t* fb = (uint8_t*)vbe_info.framebuffer;
// Copy entire scanlines at once instead of pixel-by-pixel
for (uint32_t y = 0; y < vbe_info.height; y++) {
for (uint32_t x = 0; x < vbe_info.width; x++) {
VBEPutPixel(x, y, image_data[y * vbe_info.width + x]);
// Calculate source and destination for this scanline
const uint32_t* src = &image_data[y * vbe_info.width];
uint8_t* dst = fb + (y * vbe_info.pitch);
// Fast path: only when framebuffer uses 8:8:8 at 16/8/0 (0x00RRGGBB)
int direct_compatible =
(vbe_info.red_mask_size == 8 && vbe_info.red_field_position == 16) &&
(vbe_info.green_mask_size == 8 && vbe_info.green_field_position == 8) &&
(vbe_info.blue_mask_size == 8 && vbe_info.blue_field_position == 0);
if (direct_compatible) {
FastMemcpy(dst, src, vbe_info.width * 4);
} else {
// Fallback: map each pixel
uint32_t* d32 = (uint32_t*)dst;
const uint32_t* s32 = src;
for (uint32_t x = 0; x < vbe_info.width; x++) {
// Assume source is 0x00RRGGBB
d32[x] = VBEMapColor(s32[x]);
}
}
}
}
delay(700000000);
}
#endif

#ifndef VF_CONFIG_EXCLUDE_EXTRA_OBJECTS
void VBEShowPanic(void) {
if (!vbe_initialized) return;
const uint32_t* image_data = (const uint32_t*)panic_images[0];
uint8_t* fb = (uint8_t*)vbe_info.framebuffer;

// Copy entire scanlines at once instead of pixel-by-pixel
for (uint32_t y = 0; y < vbe_info.height; y++) {
// Calculate source and destination for this scanline
const uint32_t* src = &image_data[y * vbe_info.width];
uint8_t* dst = fb + (y * vbe_info.pitch);

// Copy entire scanline (width * 4 bytes) using optimized memcpy
FastMemcpy(dst, src, vbe_info.width * 4);
for (unsigned int i = 0; i < num_panic_images; i++) { // Loop
const uint32_t* image_data = (const uint32_t*)panic_images[i];
uint8_t* fb = (uint8_t*)vbe_info.framebuffer;
// Copy entire scanlines at once instead of pixel-by-pixel
for (uint32_t y = 0; y < vbe_info.height; y++) {
// Calculate source and destination for this scanline
const uint32_t* src = &image_data[y * vbe_info.width];
uint8_t* dst = fb + (y * vbe_info.pitch);
// Fast path: only when framebuffer uses 8:8:8 at 16/8/0 (0x00RRGGBB)
int direct_compatible =
(vbe_info.red_mask_size == 8 && vbe_info.red_field_position == 16) &&
(vbe_info.green_mask_size == 8 && vbe_info.green_field_position == 8) &&
(vbe_info.blue_mask_size == 8 && vbe_info.blue_field_position == 0);
if (direct_compatible) {
FastMemcpy(dst, src, vbe_info.width * 4);
} else {
// Fallback: map each pixel
uint32_t* d32 = (uint32_t*)dst;
const uint32_t* s32 = src;
for (uint32_t x = 0; x < vbe_info.width; x++) {
// Assume source is 0x00RRGGBB
d32[x] = VBEMapColor(s32[x]);
}
}
}
}
}
#endif
Expand Down
8 changes: 4 additions & 4 deletions kernel/core/Kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,6 @@ asmlinkage void KernelMain(const uint32_t magic, const uint32_t info) {

console.buffer = (volatile uint16_t*)VGA_BUFFER_ADDR;

ClearScreen();
PrintKernelSuccess("System: VoidFrame Kernel - Version 0.0.2-development2 loaded\n");
PrintKernel("Magic: ");
PrintKernelHex(magic);
Expand All @@ -799,11 +798,9 @@ void KernelMainHigherHalf(void) {

// Initialize core systems
PXS2();
PrintKernelSuccess("System: Kernel initialization complete\n");
PrintKernelSuccess("System: Initializing interrupts...\n");

#ifdef VF_CONFIG_SNOOZE_ON_BOOT
ClearScreen();
ClearScreen();
Unsnooze();
#endif

Expand All @@ -813,6 +810,9 @@ void KernelMainHigherHalf(void) {
ExecuteCommand("post");
#endif

PrintKernelSuccess("System: Kernel initialization complete\n");
PrintKernelSuccess("System: Initializing interrupts...\n");

sti();

while (1) {
Expand Down
1 change: 0 additions & 1 deletion kernel/core/Panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ void __attribute__((noreturn)) KernelPanicHandler(const char* message, uint64_t
int use_vbe_graphics = VBEIsInitialized();

if (use_vbe_graphics) {
// Pure VBE graphics path - show panic image ONLY
#ifndef VF_CONFIG_EXCLUDE_EXTRA_OBJECTS
VBEShowPanic();
#endif
Expand Down
24 changes: 4 additions & 20 deletions kernel/etc/Console.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ static void ConsolePutcharAt(char c, uint32_t x, uint32_t y, uint8_t color) {

void ClearScreen(void) {
SpinLock(&lock);

if (use_vbe) {
VBEConsoleClear();
} else {
Expand Down Expand Up @@ -172,17 +171,13 @@ void ConsoleSetColor(uint8_t color) {
}
}

void SystemLog(const char * str) {
extern int IsVFSInitialized;
if (!IsVFSInitialized) return;
VfsWriteFile(SystemKernelLog, str, StringLength(str));
}

void PrintKernel(const char* str) {
if (!str) return;
if (snooze) goto serial;
if (snooze) {
SerialWrite(str);
return;
}
SpinLock(&lock);

if (use_vbe) {
VBEConsolePrint(str);
} else {
Expand All @@ -192,10 +187,8 @@ void PrintKernel(const char* str) {
}
console.color = original_color;
}
serial:
SpinUnlock(&lock);
SerialWrite(str);
SystemLog(str);
}

void PrintKernelChar(const char c) {
Expand Down Expand Up @@ -293,15 +286,6 @@ void PrintKernelSuccessF(const char* format, ...) {
PrintKernelSuccess(buffer);
}

void SystemLogF(const char * format, ... ) {
char buffer[1024];
va_list args;
va_start(args, format);
Format(buffer, sizeof(buffer), format, args);
va_end(args);
SystemLog(buffer);
}

void SerialWriteF(const char* format, ...) {
char buffer[1024];
va_list args;
Expand Down
25 changes: 23 additions & 2 deletions kernel/etc/Shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ static const HelpEntry system_cmds[] = {
{"perf", "Show performance stats"},
{"kill <pid>", "Terminate process"},
{"memstat", "Show memory statistics"},
{"lscpu", "List CPU features"}
{"lscpu", "List CPU features"},
{"snoozer <on/off>", "Snooze messages from PrintKernel"},
};

static const HelpEntry file_cmds[] = {
Expand Down Expand Up @@ -330,6 +331,8 @@ static void MemstatHandler(const char * args) {
PrintKernel("% fragmented, Used: ");
PrintKernelInt(stats.used_physical_bytes / (1024*1024));
PrintKernel("MB\n");
PrintVMemStats();
PrintHeapStats();
}

static void LsPCIHandler(const char * args) {
Expand Down Expand Up @@ -1181,8 +1184,25 @@ static void PingHandler(const char* args) {
KernelFree(ip_str);
}

static const ShellCommand commands[] = {
static void SnoozeHandler(const char* args) {
char* status = GetArg(args, 1);
if (!status) {
PrintKernel("Usage: snooze <on/off>\n");
return;
}
if (FastStrCmp(status, "on") == 0) {
Snooze();
} else if (FastStrCmp(status, "off") == 0) {
Unsnooze();
} else {
PrintKernel("Usage: snooze <on/off>\n");
KernelFree(status);
return;
}
KernelFree(status);
}

static const ShellCommand commands[] = {\
{"help", HelpHandler},
{"ps", PSHandler},
{"sched", SchedHandler},
Expand Down Expand Up @@ -1232,6 +1252,7 @@ static const ShellCommand commands[] = {
{"regdump", RegDumpHandler},
{"post", POSTHandler},
{"ping", PingHandler},
{"snooze", SnoozeHandler},
};

void ExecuteCommand(const char* cmd) {
Expand Down
1 change: 1 addition & 0 deletions kernel/sched/MLFQ.c
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,7 @@ void VFCompositorRequestInit(const char * str) {
PrintKernelError("System: VFCompositor disabled in this build\n");
return;
#endif
Snooze();
static uint32_t cached_vfc_pid = 0;
if (cached_vfc_pid) {
MLFQProcessControlBlock* p = MLFQGetCurrentProcessByPID(cached_vfc_pid);
Expand Down
5 changes: 1 addition & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ c_flags = [
'-fstack-protector-strong',
'-D_FORTIFY_SOURCE=2',
'-fvisibility=hidden',
'-Wall',
'-Wpedantic',
'-Wextra',
]

cpp_flags = c_flags + [
Expand Down Expand Up @@ -203,7 +200,7 @@ vf_config_flags = [
'-DVF_CONFIG_USE_ASTRA',
'-DVF_CONFIG_USE_CERBERUS',
# '-DVF_CONFIG_CERBERUS_VFS_LOGGING',
'-DVF_CONFIG_CERBERUS_THREAT_REPORTING',
# '-DVF_CONFIG_CERBERUS_THREAT_REPORTING',
'-DVF_CONFIG_CERBERUS_STACK_PROTECTION',
'-DVF_CONFIG_SCHED_MLFQ',
# '-DVF_CONFIG_PROCINFO_AUTO_CLEANUP',
Expand Down
Loading