Skip to content

Conversation

assembler-0
Copy link
Owner

@assembler-0 assembler-0 commented Aug 9, 2025

Summary by CodeRabbit

  • New Features

    • Added support for VESA BIOS Extensions (VBE) graphics mode, including pixel drawing, shapes, lines, text rendering, and a splash screen.
    • Introduced new utilities for decimal and line-based serial input/output.
    • Provided absolute value helper functions for integers and doubles.
  • Improvements

    • Enhanced serial port driver with robust error handling, multi-port support, and non-blocking I/O.
    • Serial and graphics initialization now occurs earlier in the boot process with fallback serial port probing.
    • Added multiboot2 header tags to request framebuffer graphics mode and VBE information.
  • Bug Fixes

    • Corrected duplicate initialization in the programmable interrupt controller.
  • Chores

    • Updated build configuration to include new graphics driver and reorganized source file order.
  • Style

    • Minor whitespace and header cleanup in drivers.

Copy link

coderabbitai bot commented Aug 9, 2025

Walkthrough

This update introduces a VESA BIOS Extensions (VBE) graphics driver, including header and implementation files, and expands the serial driver with robust error handling, multi-port support, and new I/O utilities. The kernel is updated to initialize the serial and VBE drivers at startup, displaying a graphical splash if VBE is available. Supporting changes include new absolute value functions, build script updates, multiboot2 header enhancements for framebuffer and VBE info, and minor fixes in other drivers and assembly headers.

Changes

Cohort / File(s) Change Summary
VBE Graphics Driver Addition
drivers/VesaBIOSExtension.c, drivers/VesaBIOSExtension.h
Introduces a new VBE graphics driver with framebuffer parsing, pixel/primitive drawing, text rendering, splash screen, and graphics-to-text mode switching. Declares color macros and graphics API in the header.
Serial Driver Refactor & Extension
drivers/Serial.c, drivers/Serial.h
Refactors and extends the serial driver: adds multi-port support, error handling, status/query functions, read/write utilities, decimal output, and line input. Updates function signatures to return status codes.
Kernel Initialization Update
kernel/core/Kernel.c
Moves serial driver initialization to kernel entry, adds VBE initialization and splash logic, updates boot sequence to support graphics mode if available, and launches Setup process for splash display.
Multiboot2 Header Update
arch/x86_64/asm/pxs.asm
Adds framebuffer and VBE tags to multiboot2 header, requesting graphics mode and VBE info. Adjusts tag alignment and adds commented fallback header.
Build System Update
meson.build
Adds VBE driver to build, reorders source file list for compilation.
Utility Functions Addition
include/stdlib.h
Adds inline absolute value functions for integers and doubles.
Process Stack and Cleanup Update
kernel/process/Process.c
Modifies process stack setup to push ProcessExitStub as return address; changes stack deallocation to guarded virtual memory free.
Minor Driver Cleanups
drivers/Keyboard.c, drivers/Pic.c
Removes unused header from keyboard driver; eliminates redundant PIC write and cleans whitespace in PIC driver.

Sequence Diagram(s)

Kernel Startup with VBE and Serial Initialization

sequenceDiagram
    participant Bootloader
    participant KernelMain
    participant SerialDriver
    participant VBEDriver

    Bootloader->>KernelMain: Pass multiboot2 info
    KernelMain->>SerialDriver: SerialInit()
    SerialDriver-->>KernelMain: Status (success/fail)
    KernelMain->>VBEDriver: VBEInit(multiboot_info_addr)
    VBEDriver-->>KernelMain: Status (success/fail)
    alt VBE available
        KernelMain->>VBEDriver: VBEShowSplash()
        KernelMain->>VBEDriver: VBESwitchToTextMode()
    else
        KernelMain->>SerialDriver: SerialWrite("No graphics, text mode.")
    end
    KernelMain->>...: Continue system init
Loading

Serial Driver: Transmitting a Character

sequenceDiagram
    participant Caller
    participant SerialDriver

    Caller->>SerialDriver: SerialWriteChar(c)
    SerialDriver->>SerialDriver: Check initialized
    alt Not initialized
        SerialDriver-->>Caller: Error code
    else
        SerialDriver->>SerialDriver: Wait for transmit buffer empty (with timeout)
        alt Timeout
            SerialDriver-->>Caller: Error code
        else
            SerialDriver->>SerialDriver: Write char to port
            SerialDriver-->>Caller: Success
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Fixed + Security changes #19: Also modifies Process.c by changing process stack pointer setup and stack cleanup, overlapping with this PR's changes to process exit handling and stack deallocation.

Poem

A rabbit hopped onto a pixel screen,
With colors bright—red, blue, and green!
Serial ports now chatter with care,
While graphics bloom beyond compare.
From text to splash, the boot feels new,
And absolute values are hopping through!
🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Development

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (5)
arch/x86_64/asm/pxs.asm (1)

23-26: Optional: request-required flag

If the kernel truly needs VBE info, set bit 0 in ‘flags’ so the bootloader aborts gracefully when unavailable.

-    dw 0        ; flags
+    dw 1        ; flags – tag is required
drivers/VesaBIOSExtension.c (2)

170-205: Consider allowing force switch to text mode even if VBEInit failed

The early return on !vbe_initialized prevents forcing VGA text mode in scenarios where the bootloader left graphics mode but VBE init failed. A force path can be useful for recovery.

Option: add a VBESwitchToTextModeForce() or accept a flag.


141-151: Char rendering is a placeholder

Acknowledged. If this is intentional for the demo, add a TODO to wire in a tiny bitmap font (e.g., 8x8) to make text usable in graphics mode.

drivers/Serial.c (2)

103-122: Add CPU relax while polling; avoid hot spins on slow UARTs

Tight polling loops can unnecessarily hammer the pipeline. Insert a PAUSE to be kinder to SMT/OOO cores and reduce power, and optionally extend the timeout.

Apply this diff:

-    while (!SerialTransmitEmpty() && --timeout > 0);
+    while (!SerialTransmitEmpty() && --timeout > 0) {
+        __asm__ volatile("pause");
+    }
@@
-    while (!SerialTransmitEmpty() && --timeout > 0);
+    while (!SerialTransmitEmpty() && --timeout > 0) {
+        __asm__ volatile("pause");
+    }

181-208: SerialReadLine busy-waits; optionally yield/relax

The loop spins continuously if no data arrives. If feasible in your scheduling model, add pause/hlt (post-sti) or a small backoff to reduce CPU burn.

Example minimal change:

-        if (c < 0) continue; // No data, keep waiting
+        if (c < 0) { __asm__ volatile("pause"); continue; } // No data, keep waiting
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a39224 and 49ee11a.

📒 Files selected for processing (10)
  • arch/x86_64/asm/pxs.asm (1 hunks)
  • drivers/Keyboard.c (0 hunks)
  • drivers/Pic.c (2 hunks)
  • drivers/Serial.c (1 hunks)
  • drivers/Serial.h (1 hunks)
  • drivers/VesaBIOSExtension.c (1 hunks)
  • drivers/VesaBIOSExtension.h (1 hunks)
  • include/stdlib.h (1 hunks)
  • kernel/core/Kernel.c (2 hunks)
  • meson.build (1 hunks)
💤 Files with no reviewable changes (1)
  • drivers/Keyboard.c
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-16T01:04:23.790Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#47
File: kernel/core/Kernel.c:434-434
Timestamp: 2025-07-16T01:04:23.790Z
Learning: VMemAlloc() in VoidFrame kernel fails with error code -2 (VMEM_ERROR_INVALID_ADDR) due to virtual address space layout conflict where the heap start address (_bss_end + KERNEL_VIRTUAL_OFFSET + 1MB margin) exceeds VIRT_ADDR_SPACE_END (0xFFFFFFFF80000000ULL), causing VMemMap validation to fail.

Applied to files:

  • arch/x86_64/asm/pxs.asm
  • kernel/core/Kernel.c
  • drivers/VesaBIOSExtension.c
📚 Learning: 2025-08-09T04:47:56.871Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#53
File: kernel/core/Kernel.c:256-259
Timestamp: 2025-08-09T04:47:56.871Z
Learning: The VoidFrame kernel memory crash occurs when VIRT_ADDR_SPACE_START is set to 0xFFFF800000000000ULL instead of 0xFFFFFFFF80000000ULL, causing the heap to allocate 128TB away from where the kernel is mapped, resulting in page faults when accessing heap memory.

Applied to files:

  • kernel/core/Kernel.c
🧬 Code Graph Analysis (4)
drivers/VesaBIOSExtension.h (1)
drivers/VesaBIOSExtension.c (12)
  • VBEInit (32-75)
  • VBEPutPixel (77-84)
  • VBEGetPixel (86-93)
  • VBEFillScreen (95-103)
  • VBEDrawRect (105-113)
  • VBEDrawLine (115-139)
  • VBEDrawChar (141-151)
  • VBEDrawString (153-168)
  • VBEShowSplash (210-232)
  • VBEGetInfo (234-236)
  • VBEIsInitialized (238-240)
  • VBESwitchToTextMode (170-205)
drivers/Serial.c (1)
include/Io.h (2)
  • outb (6-8)
  • inb (10-14)
drivers/Serial.h (1)
drivers/Serial.c (10)
  • SerialInit (45-47)
  • SerialInitPort (49-91)
  • SerialTransmitEmpty (93-96)
  • SerialDataAvailable (98-101)
  • SerialWriteChar (103-122)
  • SerialReadChar (124-132)
  • SerialWrite (134-143)
  • SerialReadLine (182-208)
  • SerialWriteHex (145-157)
  • SerialWriteDec (159-179)
drivers/VesaBIOSExtension.c (3)
drivers/Serial.c (3)
  • SerialWrite (134-143)
  • SerialWriteHex (145-157)
  • SerialWriteDec (159-179)
include/stdlib.h (1)
  • ABSi (4-9)
include/Io.h (1)
  • outb (6-8)
🔇 Additional comments (5)
drivers/Pic.c (1)

15-15: No functional change detected — OK to ignore.

Also applies to: 53-53

meson.build (1)

82-98: Build-list re-ordering looks sane

Source list update correctly adds VesaBIOSExtension.c; no duplicate entries spotted.

kernel/core/Kernel.c (1)

26-26: Header inclusion OK

Including VesaBIOSExtension.h here is appropriate and isolates VBE usage to Kernel.c.

drivers/VesaBIOSExtension.h (1)

28-41: API surface looks good

Init, drawing, text mode switch, and info accessors are coherent for early boot usage.

drivers/Serial.c (1)

49-57: Scratch register probe is good

This is a simple, effective presence test before full init.

Comment on lines +30 to 33
// Number output
void SerialWriteHex(uint64_t value);
void SerialWriteDec(uint64_t value);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Return-type inconsistency hampers error handling

All other I/O functions now return int for status; SerialWriteHex / SerialWriteDec still return void, so callers cannot detect transmit time-outs or un-initialised port.

-void SerialWriteHex(uint64_t value);
-void SerialWriteDec(uint64_t value);
+int  SerialWriteHex(uint64_t value);
+int  SerialWriteDec(uint64_t value);

Propagate the return codes inside the implementations for uniform API.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Number output
void SerialWriteHex(uint64_t value);
void SerialWriteDec(uint64_t value);
// Number output
int SerialWriteHex(uint64_t value);
int SerialWriteDec(uint64_t value);
🤖 Prompt for AI Agents
In drivers/Serial.h at lines 30 to 33, change the return type of SerialWriteHex
and SerialWriteDec from void to int to match other I/O functions. Update their
implementations to return status codes indicating success or failure, such as
transmit time-outs or uninitialized port errors, so callers can handle errors
uniformly.

Comment on lines +32 to +75
int VBEInit(uint32_t multiboot_info_addr) {
SerialWrite("VBE: Parsing Multiboot2 info...\n");

// Skip the total size field (first 8 bytes)
uint8_t *tag_ptr = (uint8_t*)(multiboot_info_addr + 8);

while (1) {
multiboot_tag_t *tag = (multiboot_tag_t*)tag_ptr;

if (tag->type == 0) break; // End tag

if (tag->type == MULTIBOOT_TAG_FRAMEBUFFER) {
multiboot_tag_framebuffer_t *fb_tag = (multiboot_tag_framebuffer_t*)tag;

vbe_info.framebuffer = (uint32_t*)fb_tag->framebuffer_addr;
vbe_info.width = fb_tag->framebuffer_width;
vbe_info.height = fb_tag->framebuffer_height;
vbe_info.bpp = fb_tag->framebuffer_bpp;
vbe_info.pitch = fb_tag->framebuffer_pitch;

SerialWrite("VBE: Found framebuffer!\n");
SerialWrite(" Address: 0x");
SerialWriteHex(fb_tag->framebuffer_addr);
SerialWrite("\n Resolution: ");
SerialWriteDec(vbe_info.width);
SerialWrite("x");
SerialWriteDec(vbe_info.height);
SerialWrite("x");
SerialWriteDec(vbe_info.bpp);
SerialWrite("\n Pitch: ");
SerialWriteDec(vbe_info.pitch);
SerialWrite("\n");

vbe_initialized = 1;
return 0;
}

// Move to next tag (align to 8 bytes)
tag_ptr += ((tag->size + 7) & ~7);
}

SerialWrite("VBE: No framebuffer found in Multiboot info\n");
return -1;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bounded tag parsing; validate pixel format; store a volatile framebuffer

Tag walk should be bounded by total_size, and the driver must reject unsupported formats. Current code assumes 32bpp and will corrupt memory on 24bpp due to pitch/4 math.

Apply this diff:

 int VBEInit(uint32_t multiboot_info_addr) {
     SerialWrite("VBE: Parsing Multiboot2 info...\n");
 
-    // Skip the total size field (first 8 bytes)
-    uint8_t *tag_ptr = (uint8_t*)(multiboot_info_addr + 8);
+    // Multiboot2 header: [total_size(4)][reserved(4)] followed by tags
+    uint32_t total_size = *(uint32_t*)(uintptr_t)multiboot_info_addr;
+    uint8_t *tag_ptr = (uint8_t*)(uintptr_t)(multiboot_info_addr + 8);
+    uint8_t *tag_end = (uint8_t*)(uintptr_t)(multiboot_info_addr + total_size);
 
-    while (1) {
+    while (tag_ptr + sizeof(multiboot_tag_t) <= tag_end) {
         multiboot_tag_t *tag = (multiboot_tag_t*)tag_ptr;
 
-        if (tag->type == 0) break; // End tag
+        if (tag->type == 0) break; // End tag (size must be 8)
 
         if (tag->type == MULTIBOOT_TAG_FRAMEBUFFER) {
             multiboot_tag_framebuffer_t *fb_tag = (multiboot_tag_framebuffer_t*)tag;
 
-            vbe_info.framebuffer = (uint32_t*)fb_tag->framebuffer_addr;
+            if (fb_tag->framebuffer_bpp != 32) {
+                SerialWrite("VBE: Unsupported bpp (expect 32)\n");
+                return -2;
+            }
+            vbe_info.framebuffer = (volatile uint32_t*)(uintptr_t)fb_tag->framebuffer_addr;
             vbe_info.width = fb_tag->framebuffer_width;
             vbe_info.height = fb_tag->framebuffer_height;
             vbe_info.bpp = fb_tag->framebuffer_bpp;
             vbe_info.pitch = fb_tag->framebuffer_pitch;
 
             SerialWrite("VBE: Found framebuffer!\n");
             SerialWrite("  Address: 0x");
             SerialWriteHex(fb_tag->framebuffer_addr);
             SerialWrite("\n  Resolution: ");
             SerialWriteDec(vbe_info.width);
             SerialWrite("x");
             SerialWriteDec(vbe_info.height);
             SerialWrite("x");
             SerialWriteDec(vbe_info.bpp);
             SerialWrite("\n  Pitch: ");
             SerialWriteDec(vbe_info.pitch);
             SerialWrite("\n");
 
             vbe_initialized = 1;
             return 0;
         }
 
         // Move to next tag (align to 8 bytes)
-        tag_ptr += ((tag->size + 7) & ~7);
+        if (tag->size == 0) break; // Corrupt tag guard
+        tag_ptr += ((tag->size + 7) & ~7);
     }
 
     SerialWrite("VBE: No framebuffer found in Multiboot info\n");
     return -1;
 }
🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.c between lines 32 and 75, the tag parsing loop
lacks bounds checking against the total size of the multiboot info, risking
out-of-bounds reads. Also, the code assumes a 32bpp pixel format without
validating it, which can cause memory corruption on 24bpp formats due to
incorrect pitch calculations. To fix this, add a boundary check to ensure the
tag pointer does not exceed the total size field from the multiboot info header,
validate that the framebuffer pixel format is supported (e.g., 32bpp), and
declare the framebuffer pointer as volatile to prevent unwanted compiler
optimizations.

Comment on lines +77 to +85
void VBEPutPixel(uint32_t x, uint32_t y, uint32_t color) {
if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height) {
return;
}

uint32_t offset = y * (vbe_info.pitch / 4) + x;
vbe_info.framebuffer[offset] = color;
}

Copy link

@coderabbitai coderabbitai bot Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Pixel write/read assume 32bpp; guard and use stride in pixels

Current offset math divides pitch by 4 and writes 32 bits. Guard on bpp to avoid accidental over/under-writes.

Apply this diff:

 void VBEPutPixel(uint32_t x, uint32_t y, uint32_t color) {
-    if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height) {
+    if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height || vbe_info.bpp != 32) {
         return;
     }
 
-    uint32_t offset = y * (vbe_info.pitch / 4) + x;
-    vbe_info.framebuffer[offset] = color;
+    const uint32_t stride = vbe_info.pitch >> 2; // bytes->dwords
+    vbe_info.framebuffer[y * stride + x] = color;
 }
 
 uint32_t VBEGetPixel(uint32_t x, uint32_t y) {
-    if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height) {
+    if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height || vbe_info.bpp != 32) {
         return 0;
     }
 
-    uint32_t offset = y * (vbe_info.pitch / 4) + x;
-    return vbe_info.framebuffer[offset];
+    const uint32_t stride = vbe_info.pitch >> 2;
+    return vbe_info.framebuffer[y * stride + x];
 }

Also applies to: 86-93

🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.c around lines 77 to 85, the pixel write function
assumes a 32 bits per pixel (bpp) format by dividing the pitch by 4 and writing
32-bit colors without checking the actual bpp. To fix this, add a guard to
verify that the vbe_info.bpp is 32 before performing the write to avoid
accidental over- or under-writes. Also, use the pitch as stride in pixels
correctly without hardcoding division by 4. Apply the same fix to lines 86 to 93
where pixel read/write occurs.

Copy link
Owner Author

@assembler-0 assembler-0 Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also just asking will i able to go back the real mode service stage to switched to 0xb8000 after i change to long mode and enable all cpu memory protection 😇? also we have a critical issue, when a process returns, rather than terminating that process, it GPF the system.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for process termination, exit handling, and GPF handlers
echo "=== Searching for process exit/termination handling ==="
rg -A 5 "process.*exit|process.*terminate|ProcessExit|ProcessTerminate" --type c

echo -e "\n=== Searching for GPF handlers ==="
rg -A 10 "GPF|GeneralProtectionFault|general_protection" --type c

echo -e "\n=== Looking for process return/exit syscalls ==="
ast-grep --pattern 'exit($_) {
  $$$
}'

echo -e "\n=== Searching for process management code ==="
fd -e c -e h "Process|Task|Scheduler" --exec head -20 {}

echo -e "\n=== Checking syscall implementations for exit ==="
rg -A 10 "SYS_EXIT|sys_exit|syscall.*exit" --type c

Length of output: 5232


🏁 Script executed:

#!/bin/bash
# Find KillProcess and TerminateProcess implementations
echo "=== Searching for KillProcess implementation ==="
rg -A 20 "^[^/]*KillProcess\s*\(" --type c

echo -e "\n=== Searching for TerminateProcess implementation ==="
rg -A 20 "^[^/]*TerminateProcess\s*\(" --type c

echo -e "\n=== Looking for process entry point and return handling ==="
rg -A 10 "process.*entry|process.*return|ret.*process" --type c

echo -e "\n=== Checking how processes are created and their stack setup ==="
rg -A 15 "CreateProcess|SpawnProcess|process.*create" --type c | head -50

Length of output: 14421


🏁 Script executed:

#!/bin/bash
# Find stack allocation and setup
echo "=== Searching for process stack allocation ==="
rg -A 10 "stack.*alloc|AllocStack|process.*stack" --type c

echo -e "\n=== Looking at ProcessExitStub and how it's used ==="
rg -B 5 -A 10 "ProcessExitStub" --type c

echo -e "\n=== Checking CreateSecureProcess for stack setup ==="
rg -B 5 -A 30 "CreateSecureProcess" --type c | head -80

echo -e "\n=== Looking for process context setup ==="
ast-grep --pattern 'processes[$_].context.rsp = $_'

Length of output: 8037


🏁 Script executed:

#!/bin/bash
# Find where process context (especially RSP) is initialized
echo "=== Looking for context initialization ==="
rg -A 20 "processes\[.*\]\.context\." --type c

echo -e "\n=== Finding STACK_SIZE definition ==="
rg "define.*STACK_SIZE" --type c --type h

echo -e "\n=== Looking for stack pointer setup in assembly ==="
fd -e asm -e s | xargs grep -l "rsp" | head -5

echo -e "\n=== Check if there's a wrapper that sets return address ==="
rg -A 10 "push.*ProcessExitStub|call.*entry_point" --type c --type asm

Length of output: 2253


🏁 Script executed:

#!/bin/bash
# Find the complete CreateSecureProcess function to see rsp calculation
echo "=== Complete CreateSecureProcess function ==="
rg -B 10 "processes\[slot\]\.context\.rsp = rsp" --type c

echo -e "\n=== Looking for process wrapper or trampoline ==="
rg -A 5 -B 5 "trampoline|wrapper|process_start" --type c

echo -e "\n=== Check interrupt/syscall return path ==="
rg -A 10 "iretq|sysretq" --type asm

Length of output: 3005


@assembler-0, let me address both of your questions:

1. Returning to Real Mode from Long Mode

No, you cannot go back to real mode services once you're in long mode with memory protection enabled. The transition path would be: Long Mode → Protected Mode → Real Mode, which requires:

  • Disabling paging
  • Switching GDT
  • Clearing control registers
  • This is impractical and dangerous in a running OS

However, you don't need real mode to access text mode at 0xB8000! This is memory-mapped I/O that works perfectly from long mode. Your VBESwitchToTextMode() function already does this correctly by:

  • Writing VGA registers directly using port I/O
  • Clearing the text buffer at 0xB8000
  • No real mode needed!

2. Critical GPF Issue on Process Return

I found the problem! When a process is created, the stack pointer is set but no return address is pushed:

// In CreateSecureProcess:
uint64_t rsp = (uint64_t)stack + STACK_SIZE;
rsp &= ~0xF; // 16-byte alignment
processes[slot].context.rsp = rsp;
processes[slot].context.rip = (uint64_t)entry_point;  // Direct entry, no return!

When your process function returns, it tries to pop a non-existent return address → GPF!

Solution:

Push ProcessExitStub as the return address on the stack:

// In CreateSecureProcess, after allocating stack:
uint64_t rsp = (uint64_t)stack + STACK_SIZE;
rsp &= ~0xF; // 16-byte alignment

// Push ProcessExitStub as return address
rsp -= 8;
*(uint64_t*)rsp = (uint64_t)ProcessExitStub;

processes[slot].context.rsp = rsp;
processes[slot].context.rip = (uint64_t)entry_point;

This way, when a process returns, it will "return" to ProcessExitStub, which properly terminates the process instead of causing a GPF.

Would you like me to open an issue to track this critical process termination bug?


🧠 Learnings used
Learnt from: assembler-0
PR: assembler-0/VoidFrame#47
File: kernel/core/Kernel.c:434-434
Timestamp: 2025-07-16T01:04:23.790Z
Learning: VMemAlloc() in VoidFrame kernel fails with error code -2 (VMEM_ERROR_INVALID_ADDR) due to virtual address space layout conflict where the heap start address (_bss_end + KERNEL_VIRTUAL_OFFSET + 1MB margin) exceeds VIRT_ADDR_SPACE_END (0xFFFFFFFF80000000ULL), causing VMemMap validation to fail.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#53
File: kernel/core/Kernel.c:256-259
Timestamp: 2025-08-09T04:47:56.871Z
Learning: The VoidFrame kernel memory crash occurs when VIRT_ADDR_SPACE_START is set to 0xFFFF800000000000ULL instead of 0xFFFFFFFF80000000ULL, causing the heap to allocate 128TB away from where the kernel is mapped, resulting in page faults when accessing heap memory.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok ok, it works (the switch to 0xb800 doesnt work), but this [MEMORY] FreePage: Page index out of bounds: 4503565267632165, huh?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for FreePage implementation and the error message
echo "=== Searching for FreePage implementation ==="
rg -B 5 -A 15 "FreePage.*out of bounds|FreePage.*Page index" --type c

echo -e "\n=== Looking for FreePage function ==="
ast-grep --pattern 'FreePage($_) {
  $$$
}'

echo -e "\n=== Searching for any FreePage function ==="
rg -B 5 -A 20 "^[^/]*FreePage\s*\(" --type c

echo -e "\n=== Looking for memory page management structures ==="
rg -A 10 "PAGE_SIZE|page_index|PageIndex" --type c --type h | head -50

echo -e "\n=== Check VBESwitchToTextMode implementation ==="
rg -A 30 "VBESwitchToTextMode" drivers/VesaBIOSExtension.c

Length of output: 17121


🏁 Script executed:

#!/bin/bash
# Check how process stacks are allocated and freed
echo "=== Looking for process stack allocation ==="
rg -B 5 -A 10 "proc->stack.*=|processes\[.*\]\.stack.*=" --type c

echo -e "\n=== Check PAGE_SIZE definition ==="
rg "#define\s+PAGE_SIZE" --type h --type c

echo -e "\n=== Look for virtual to physical address conversion ==="
rg "VIRT_TO_PHYS|VirtToPhys|virtual.*physical" --type c --type h | head -20

echo -e "\n=== Check how KernelMemoryAlloc/Free work with addresses ==="
rg -A 10 "KernelMemoryFree" --type c | head -30

echo -e "\n=== Check text mode buffer access in kernel ==="
rg "0xB8000|text_buffer" --type c | head -20

Length of output: 3448


@assembler-0, I found both issues!

1. Memory Corruption - FreePage Error

The massive page index (4503565267632165 ≈ 0x10011E03AB00025) indicates a virtual address is being passed to FreePage which expects a physical address.

The problem is in process stack handling:

  • AllocPage() returns a physical address
  • But when setting up the process context, you use this as RSP (which needs to be virtual)
  • Later, FreePage(proc->stack) tries to free this address

The fix: Track both physical and virtual addresses for the stack:

// In CreateSecureProcess:
void* stack_phys = AllocPage();  // Physical address
if (!stack_phys) return -1;

// Convert to virtual for process use
uint64_t stack_virt = (uint64_t)stack_phys + KERNEL_VIRTUAL_OFFSET;
uint64_t rsp = stack_virt + STACK_SIZE;

// Store physical address for freeing
processes[slot].stack = stack_phys;  // Keep physical for FreePage
processes[slot].context.rsp = rsp;   // Use virtual for process

2. Text Mode Switch (0xB8000)

The issue is that 0xB8000 needs to be accessed as part of the identity-mapped region in virtual addressing mode:

// In VBESwitchToTextMode, change:
uint16_t* text_buffer = (uint16_t*)0xB8000;

// To (if in higher-half kernel):
uint16_t* text_buffer = (uint16_t*)(0xB8000 + KERNEL_VIRTUAL_OFFSET);
// OR if it's identity-mapped and accessible:
uint16_t* text_buffer = (uint16_t*)0xB8000;  // Should work if properly mapped

Actually, since 0xB8000 is in the first 1GB which you identity-map, it should work. The problem might be:

  1. VGA registers aren't being set correctly
  2. The framebuffer is still active and overriding text mode

Try adding this after setting VGA registers:

// Disable graphics mode completely
outb(0x3C0, 0x10); outb(0x3C0, 0x0C);  // Graphics mode off
outb(0x3CE, 0x05); outb(0x3CF, 0x00);  // Graphics mode register
outb(0x3CE, 0x06); outb(0x3CF, 0x0E);  // Memory map mode

The root cause is mixing physical and virtual addresses. Would you like me to create an issue to track these memory management fixes?


🧠 Learnings used
Learnt from: assembler-0
PR: assembler-0/VoidFrame#47
File: kernel/core/Kernel.c:434-434
Timestamp: 2025-07-16T01:04:23.790Z
Learning: VMemAlloc() in VoidFrame kernel fails with error code -2 (VMEM_ERROR_INVALID_ADDR) due to virtual address space layout conflict where the heap start address (_bss_end + KERNEL_VIRTUAL_OFFSET + 1MB margin) exceeds VIRT_ADDR_SPACE_END (0xFFFFFFFF80000000ULL), causing VMemMap validation to fail.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#53
File: kernel/core/Kernel.c:256-259
Timestamp: 2025-08-09T04:47:56.871Z
Learning: The VoidFrame kernel memory crash occurs when VIRT_ADDR_SPACE_START is set to 0xFFFF800000000000ULL instead of 0xFFFFFFFF80000000ULL, causing the heap to allocate 128TB away from where the kernel is mapped, resulting in page faults when accessing heap memory.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#57
File: kernel/memory/VMem.h:64-66
Timestamp: 2025-08-09T09:29:00.591Z
Learning: In the VoidFrame kernel, removing locks from KernelMemoryAlloc/KernelMemoryFree causes heap corruption where shell command strings (like "clear" = 0x61656C63) overwrite heap block magic values due to race conditions between allocation and free operations.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what? i tought the allocation process is like this
void* stack = VMemAllocWithGuards(STACK_SIZE);
if (UNLIKELY(!stack)) {
FreeSlotFast(slot);
SpinUnlockIrqRestore(&scheduler_lock, flags);
PANIC("CreateSecureProcess: Failed to allocate stack");
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the actual CreateSecureProcess implementation
echo "=== Complete CreateSecureProcess function ==="
rg -B 10 -A 50 "void\*\s+stack\s*=\s*VMemAllocWithGuards" --type c

echo -e "\n=== Find VMemAllocWithGuards implementation ==="
ast-grep --pattern 'VMemAllocWithGuards($_) {
  $$$
}'

echo -e "\n=== Search for VMemAllocWithGuards ==="
rg -B 5 -A 20 "VMemAllocWithGuards" --type c --type h

echo -e "\n=== Find where process stack is freed ==="
rg -B 5 -A 10 "FreePage.*stack|free.*process.*stack" --type c

echo -e "\n=== Check TerminateProcess implementation ==="
rg -B 5 -A 25 "^[^/]*TerminateProcess\s*\(" --type c

Length of output: 18355


🏁 Script executed:

#!/bin/bash
# Find VMemFreeWithGuards and VMemFree implementations
echo "=== Search for VMemFreeWithGuards ==="
rg -B 5 -A 20 "VMemFreeWithGuards" --type c --type h

echo -e "\n=== Search for VMemFree ==="
rg -B 5 -A 15 "^[^/]*VMemFree\s*\(" --type c

echo -e "\n=== Check what FreePage expects ==="
rg -B 5 -A 10 "^[^/]*FreePage\s*\(" --type c | head -40

Length of output: 11734


@assembler-0, you're absolutely right! I apologize for the confusion. I found the critical bug:

The Memory Bug

The issue is a mismatch between allocation and deallocation:

  1. Stack allocation: Uses VMemAllocWithGuards() which returns a virtual address
  2. Stack deallocation: Uses FreePage() which expects a physical address

In TerminateProcess:

if (proc->stack) {
    FreePage(proc->stack);  // ❌ WRONG! proc->stack is virtual, not physical!
    proc->stack = NULL;
}

This explains the huge page index (4503565267632165) - it's interpreting a virtual address as physical!

The Fix

Replace FreePage(proc->stack) with:

if (proc->stack) {
    VMemFreeWithGuards(proc->stack, STACK_SIZE);  // ✅ Correct!
    proc->stack = NULL;
}

VMemFreeWithGuards will:

  1. Check the guard pages for corruption
  2. Properly unmap the virtual memory
  3. Free the underlying physical pages

Text Mode Switch Issue

For the 0xB8000 not working, try accessing it directly without offset since it should be identity-mapped:

uint16_t* text_buffer = (uint16_t*)0xB8000;

If that still doesn't work, the VGA registers might not be switching modes properly. The framebuffer could still be active and overriding text mode.

Would you like me to create an issue to track this critical memory management bug where process stacks are being freed incorrectly?


✏️ Learnings added
Learnt from: assembler-0
PR: assembler-0/VoidFrame#58
File: drivers/VesaBIOSExtension.c:77-85
Timestamp: 2025-08-09T10:31:44.413Z
Learning: In VoidFrame kernel, process stacks are allocated using VMemAllocWithGuards() which returns virtual addresses, but TerminateProcess incorrectly uses FreePage() (which expects physical addresses) to free them, causing "Page index out of bounds" errors. The correct function to use is VMemFreeWithGuards(proc->stack, STACK_SIZE).

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: assembler-0
PR: assembler-0/VoidFrame#47
File: kernel/core/Kernel.c:434-434
Timestamp: 2025-07-16T01:04:23.790Z
Learning: VMemAlloc() in VoidFrame kernel fails with error code -2 (VMEM_ERROR_INVALID_ADDR) due to virtual address space layout conflict where the heap start address (_bss_end + KERNEL_VIRTUAL_OFFSET + 1MB margin) exceeds VIRT_ADDR_SPACE_END (0xFFFFFFFF80000000ULL), causing VMemMap validation to fail.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#57
File: kernel/memory/VMem.h:64-66
Timestamp: 2025-08-09T09:29:00.591Z
Learning: In the VoidFrame kernel, removing locks from KernelMemoryAlloc/KernelMemoryFree causes heap corruption where shell command strings (like "clear" = 0x61656C63) overwrite heap block magic values due to race conditions between allocation and free operations.

Learnt from: assembler-0
PR: assembler-0/VoidFrame#53
File: kernel/core/Kernel.c:256-259
Timestamp: 2025-08-09T04:47:56.871Z
Learning: The VoidFrame kernel memory crash occurs when VIRT_ADDR_SPACE_START is set to 0xFFFF800000000000ULL instead of 0xFFFFFFFF80000000ULL, causing the heap to allocate 128TB away from where the kernel is mapped, resulting in page faults when accessing heap memory.

Comment on lines +6 to +17
// Common colors (32-bit RGBA format)
#define VBE_COLOR_BLACK 0x00000000
#define VBE_COLOR_WHITE 0x00FFFFFF
#define VBE_COLOR_RED 0x00FF0000
#define VBE_COLOR_GREEN 0x0000FF00
#define VBE_COLOR_BLUE 0x000000FF
#define VBE_COLOR_YELLOW 0x00FFFF00
#define VBE_COLOR_CYAN 0x0000FFFF
#define VBE_COLOR_MAGENTA 0x00FF00FF
#define VBE_COLOR_GRAY 0x00808080
#define VBE_COLOR_DARK_GRAY 0x00404040

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Color constants assume 32-bit X8R8G8B8; document and/or derive from framebuffer format

These hard-coded 0x00RRGGBB values only display correctly if the framebuffer is 32bpp with the expected channel order. The VBE driver currently ignores the format fields from Multiboot2.

  • Document the assumption in a comment.
  • Or extend vbe_info_t with channel offsets/masks and provide a VBE_MAKE_RGB() helper derived from the Multiboot2 color info.
🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.h around lines 6 to 17, the color constants are
hard-coded assuming a 32-bit X8R8G8B8 framebuffer format, which may not match
the actual framebuffer format from Multiboot2. To fix this, add a comment
clearly documenting this assumption. Alternatively, extend the vbe_info_t
structure to include channel offsets and masks from the Multiboot2 framebuffer
info, and implement a VBE_MAKE_RGB() helper macro or function that constructs
color values dynamically based on these parameters instead of using fixed
constants.

Comment on lines 20 to 25
uint32_t *framebuffer; // Pointer to framebuffer
uint32_t width; // Screen width
uint32_t height; // Screen height
uint32_t pitch; // Bytes per scanline
uint32_t bpp; // Bits per pixel
} vbe_info_t;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make framebuffer pointer volatile; consider exposing get-info as const

Access is MMIO-like; mark the pointer volatile to prevent the compiler from eliding writes. Returning a const pointer from VBEGetInfo prevents accidental mutation of geometry.

Apply this diff:

-    uint32_t *framebuffer;  // Pointer to framebuffer
+    volatile uint32_t *framebuffer;  // Pointer to framebuffer

Optionally:

-vbe_info_t* VBEGetInfo(void);
+const vbe_info_t* VBEGetInfo(void);
🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.h around lines 20 to 25, the framebuffer pointer
should be marked volatile because it points to memory-mapped I/O and the
compiler must not optimize away reads or writes. Change the framebuffer
declaration to a volatile uint32_t pointer. Additionally, modify the VBEGetInfo
function to return a pointer to a const vbe_info_t structure to prevent
accidental modification of the VBE geometry information.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
drivers/Serial.h (1)

35-37: Return-type inconsistency for number-printing helpers
SerialWriteHex / SerialWriteDec still return void while every other public I/O routine now returns int for status. This was raised earlier; please align the signatures and propagate error codes.

kernel/core/Kernel.c (1)

370-381: Serial fallback logic implemented as recommended – LGTM

Kernel now retries COM2-4 when COM1 fails and logs the selected outcome. Good adoption of earlier feedback.

drivers/VesaBIOSExtension.c (1)

32-71: Tag-parsing still lacks bounds & bpp validation

The loop walks past the multiboot structure until it hits type 0 with no upper bound; a malformed tag size will over-read memory.
Also, you still accept any framebuffer_bpp but later compute pitch/4, assuming 32 bpp, and cast to non-volatile uint32_t*.
See prior review diff for a hardened version.

drivers/Serial.c (1)

140-153: Still no error propagation from Hex/Dec writers

SerialWriteHex/SerialWriteDec ignore failures from SerialWrite and expose no status to callers, unlike the rest of the API. Please convert them to int and bubble up errors for uniform handling.

🧹 Nitpick comments (3)
drivers/Serial.h (1)

6-16: Drop one set of duplicate COM port macros

Both COMx and SERIAL_COMx define the same port addresses, creating two authoritative sources that can diverge. Keep a single naming scheme (preferably SERIAL_COMx) and delete the other to avoid accidental mismatch.

kernel/core/Kernel.c (1)

357-360: Busy-wait delay wastes CPU cycles

for (volatile int i = 0; i < 100000000; i++); spins for hundreds of ms and still varies per clock speed. Prefer a calibrated PIT/APIC delay or at least insert pause in the loop to throttle power draw.

drivers/Serial.c (1)

176-203: SerialReadLine spins without back-off

When no character is ready the loop busy-waits indefinitely, burning CPU in early boot. Consider a small pause instruction or timeout/yield hook to make this polling friendlier.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49ee11a and e670d3b.

📒 Files selected for processing (8)
  • arch/x86_64/asm/pxs.asm (1 hunks)
  • drivers/Serial.c (1 hunks)
  • drivers/Serial.h (1 hunks)
  • drivers/VesaBIOSExtension.c (1 hunks)
  • drivers/VesaBIOSExtension.h (1 hunks)
  • include/stdlib.h (1 hunks)
  • kernel/core/Kernel.c (4 hunks)
  • kernel/process/Process.c (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • arch/x86_64/asm/pxs.asm
  • include/stdlib.h
  • drivers/VesaBIOSExtension.h
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-09T10:31:44.413Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#58
File: drivers/VesaBIOSExtension.c:77-85
Timestamp: 2025-08-09T10:31:44.413Z
Learning: In VoidFrame kernel, process stacks are allocated using VMemAllocWithGuards() which returns virtual addresses, but TerminateProcess incorrectly uses FreePage() (which expects physical addresses) to free them, causing "Page index out of bounds" errors. The correct function to use is VMemFreeWithGuards(proc->stack, STACK_SIZE).

Applied to files:

  • kernel/process/Process.c
  • kernel/core/Kernel.c
  • drivers/VesaBIOSExtension.c
📚 Learning: 2025-08-09T09:29:00.591Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#57
File: kernel/memory/VMem.h:64-66
Timestamp: 2025-08-09T09:29:00.591Z
Learning: In the VoidFrame kernel, removing locks from KernelMemoryAlloc/KernelMemoryFree causes heap corruption where shell command strings (like "clear" = 0x61656C63) overwrite heap block magic values due to race conditions between allocation and free operations.

Applied to files:

  • kernel/process/Process.c
  • drivers/VesaBIOSExtension.c
📚 Learning: 2025-07-16T01:04:23.790Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#47
File: kernel/core/Kernel.c:434-434
Timestamp: 2025-07-16T01:04:23.790Z
Learning: VMemAlloc() in VoidFrame kernel fails with error code -2 (VMEM_ERROR_INVALID_ADDR) due to virtual address space layout conflict where the heap start address (_bss_end + KERNEL_VIRTUAL_OFFSET + 1MB margin) exceeds VIRT_ADDR_SPACE_END (0xFFFFFFFF80000000ULL), causing VMemMap validation to fail.

Applied to files:

  • kernel/process/Process.c
  • kernel/core/Kernel.c
  • drivers/VesaBIOSExtension.c
📚 Learning: 2025-08-09T04:47:56.871Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#53
File: kernel/core/Kernel.c:256-259
Timestamp: 2025-08-09T04:47:56.871Z
Learning: The VoidFrame kernel memory crash occurs when VIRT_ADDR_SPACE_START is set to 0xFFFF800000000000ULL instead of 0xFFFFFFFF80000000ULL, causing the heap to allocate 128TB away from where the kernel is mapped, resulting in page faults when accessing heap memory.

Applied to files:

  • kernel/core/Kernel.c
  • drivers/VesaBIOSExtension.c
🔇 Additional comments (2)
kernel/process/Process.c (2)

982-985: Nice: safe return path added

Pushing ProcessExitStub ensures a clean process exit instead of a GPF – good fix. The 8-byte push preserves the expected “RSP % 16 == 8” alignment inside the entry routine, so no ABI issue.


1045-1045: Correct allocator pairing

Switching from FreePage to VMemFreeWithGuards matches the stack allocator and removes the “page index out of bounds” fault.

Comment on lines +77 to +93
void VBEPutPixel(uint32_t x, uint32_t y, uint32_t color) {
if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height) {
return;
}

uint32_t offset = y * (vbe_info.pitch / 4) + x;
vbe_info.framebuffer[offset] = color;
}

uint32_t VBEGetPixel(uint32_t x, uint32_t y) {
if (!vbe_initialized || x >= vbe_info.width || y >= vbe_info.height) {
return 0;
}

uint32_t offset = y * (vbe_info.pitch / 4) + x;
return vbe_info.framebuffer[offset];
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Undefined ABSi and 32-bpp assumption break build & correctness

ABSi is not defined/included and will not compile.
Offset calculation uses pitch / 4 and 32-bit writes—unsafe for 24 bpp modes. Guard on vbe_info.bpp == 32 (or add full format handling) before touching the framebuffer.

🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.c around lines 77 to 93, the code uses an undefined
identifier `ABSi` and assumes 32 bits per pixel by dividing pitch by 4, which
breaks compilation and correctness for other bpp modes. Remove or define `ABSi`
properly if needed, and add a guard to ensure the pixel operations only proceed
if vbe_info.bpp equals 32, or implement handling for other bpp formats before
accessing the framebuffer.

@assembler-0 assembler-0 merged commit d240517 into main Aug 9, 2025
1 check passed
This was referenced Aug 9, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 23, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 31, 2025
@coderabbitai coderabbitai bot mentioned this pull request Sep 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant