From 5afd174af15cc24aa844c71bd32fb18eb2a57742 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:03:52 +0000 Subject: [PATCH 1/5] Initial plan From c81d08c2a8a1c99d5f672e27a7f8f72ed59e1543 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:07:55 +0000 Subject: [PATCH 2/5] Add support for 64GB of RAM - Update BITMAP_SIZE from 32768 to 2097152 bytes (2MB bitmap) - Update totalPages calculation to support 64GB (16M pages) - Update documentation to reflect 64GB memory support - Memory manager now supports any amount up to 64GB Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- docs/IMPLEMENTATION_SUMMARY.md | 2 +- docs/KERNEL_REFERENCE.md | 2 +- kernel/include/kernel/memory.h | 10 +++++----- kernel/src/memory.cpp | 9 +++++---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md index c355d8b..b5a16da 100644 --- a/docs/IMPLEMENTATION_SUMMARY.md +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -35,7 +35,7 @@ - Bitmap-based physical page allocator - Bump allocator for kernel heap (1MB) - Memory utilities (memset, memcpy, memcmp) - - Support for up to 128MB RAM + - Support for up to 64GB RAM #### PCI Bus Support - Files: `kernel/src/pci.c`, `kernel/include/kernel/pci.h` diff --git a/docs/KERNEL_REFERENCE.md b/docs/KERNEL_REFERENCE.md index eeeb527..3b966e6 100644 --- a/docs/KERNEL_REFERENCE.md +++ b/docs/KERNEL_REFERENCE.md @@ -158,7 +158,7 @@ if (gpu) { - **No Console Module**: As requested, no console.c/h files are created - **Minimal Design**: Only essential features for QT6 Hello World - **Bump Allocator**: Current heap doesn't support freeing (upgrade later if needed) -- **Physical Memory**: Simple bitmap allocator (32768 pages max in current impl) +- **Physical Memory**: Simple bitmap allocator (supports up to 64GB with 2MB bitmap) - **PCI Scan**: Scans all 256 buses, 32 devices per bus - **Timer**: Uses PIT in rate generator mode diff --git a/kernel/include/kernel/memory.h b/kernel/include/kernel/memory.h index 209760c..551ba33 100644 --- a/kernel/include/kernel/memory.h +++ b/kernel/include/kernel/memory.h @@ -18,8 +18,8 @@ * - 0 = page is free and available for allocation * - 1 = page is in use * - * The bitmap supports up to 128MB of physical memory (32768 bytes * 8 bits/byte - * * 4KB per page = 128MB). Memory is assumed to start at physical address 0x01000000 + * The bitmap supports up to 64GB of physical memory (2097152 bytes * 8 bits/byte + * * 4KB per page = 64GB). Memory is assumed to start at physical address 0x01000000 * (16MB) to avoid conflicts with legacy hardware and the kernel itself. * * This is a very simple allocator suitable for a minimal kernel. It does not: @@ -29,7 +29,7 @@ */ class PhysicalMemoryManager { private: - uint8_t pageBitmap[32768]; ///< Bitmap tracking page allocation (128MB / 4KB pages) + uint8_t pageBitmap[2097152]; ///< Bitmap tracking page allocation (64GB / 4KB pages = 16M pages = 2MB bitmap) uint64_t totalPages; ///< Total number of pages managed uint64_t usedPages; ///< Number of pages currently allocated @@ -39,8 +39,8 @@ public: /** * @brief Initialize the physical memory manager with boot information - * @param bootInfo Boot information from bootloader (currently unused, assumes 128MB) - * @note Currently hardcoded to manage 128MB starting at 16MB physical address + * @param bootInfo Boot information from bootloader (currently unused, assumes up to 64GB) + * @note Currently hardcoded to manage up to 64GB starting at 16MB physical address */ void init(BootInfo* bootInfo); diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index de8aa27..8010cc9 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -10,7 +10,7 @@ #include "kernel/memory.h" // Physical memory bitmap constants -#define BITMAP_SIZE 32768 // Supports up to 128MB with 4KB pages +#define BITMAP_SIZE 2097152 // Supports up to 64GB with 4KB pages (64GB / 4KB = 16M pages, 16M bits = 2MB bitmap) /* PhysicalMemoryManager class implementation */ @@ -28,7 +28,7 @@ PhysicalMemoryManager::PhysicalMemoryManager() * @brief Initialize the physical memory manager * * Currently uses a simplified approach: - * - Assumes 128MB of usable RAM starting at physical address 16MB (0x01000000) + * - Assumes up to 64GB of usable RAM starting at physical address 16MB (0x01000000) * - Clears the entire page bitmap to mark all pages as free * - TODO: Parse the UEFI memory map from bootInfo to properly detect available memory * @@ -41,8 +41,9 @@ PhysicalMemoryManager::PhysicalMemoryManager() void PhysicalMemoryManager::init(BootInfo* bootInfo) { (void)bootInfo; // TODO: Parse UEFI memory map - // For now, assume 128MB of usable memory starting at 16MB - totalPages = (128 * 1024 * 1024) / PAGE_SIZE; + // For now, assume 64GB of usable memory starting at 16MB + // This supports any amount up to 64GB + totalPages = (64ULL * 1024 * 1024 * 1024) / PAGE_SIZE; // Clear bitmap for (uint64_t i = 0; i < BITMAP_SIZE; i++) { From 0093b101383c2606d0be4d430c90589f4ee65051 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:09:23 +0000 Subject: [PATCH 3/5] Add bounds checking to prevent buffer overflow in bitmap access - Add safety check in allocPage() before accessing pageBitmap - Add safety check in freePage() before accessing pageBitmap - Prevents potential buffer overflow when bitmap size limits are reached Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- kernel/src/memory.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 8010cc9..50d3c11 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -74,6 +74,11 @@ void* PhysicalMemoryManager::allocPage() { uint64_t byte = i / 8; uint64_t bit = i % 8; + // Bounds check to prevent buffer overflow + if (byte >= BITMAP_SIZE) { + break; + } + if (!(pageBitmap[byte] & (1 << bit))) { // Mark as used pageBitmap[byte] |= (1 << bit); @@ -111,6 +116,11 @@ void PhysicalMemoryManager::freePage(void* page) { uint64_t byte = pageIdx / 8; uint64_t bit = pageIdx % 8; + // Bounds check to prevent buffer overflow + if (byte >= BITMAP_SIZE) { + return; + } + // Mark as free pageBitmap[byte] &= ~(1 << bit); usedPages--; From 4051edd19834290b0b0e028205c46645fa37a6fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:20:46 +0000 Subject: [PATCH 4/5] Parse UEFI memory map to detect actual available RAM - Implement proper memory detection by parsing UEFI memory map - Mark only usable memory regions as free (EfiConventionalMemory, Boot/Loader services) - Initialize bitmap with all pages marked as used, then free only available regions - Calculate totalPages based on highest usable address from memory map - Add 128MB fallback if memory map is unavailable - Now works correctly with any RAM amount from 0 to 64GB Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- docs/IMPLEMENTATION_SUMMARY.md | 4 +- docs/KERNEL_REFERENCE.md | 2 +- kernel/include/kernel/memory.h | 5 +- kernel/src/memory.cpp | 118 +++++++++++++++++++++++++++++---- 4 files changed, 110 insertions(+), 19 deletions(-) diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md index b5a16da..66e25c6 100644 --- a/docs/IMPLEMENTATION_SUMMARY.md +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -32,10 +32,10 @@ - Files: `kernel/src/memory.c`, `kernel/include/kernel/memory.h` - Functionality: Physical memory and kernel heap management - Features: - - Bitmap-based physical page allocator + - Bitmap-based physical page allocator with UEFI memory map parsing - Bump allocator for kernel heap (1MB) - Memory utilities (memset, memcpy, memcmp) - - Support for up to 64GB RAM + - Support for up to 64GB RAM (automatically detects available memory) #### PCI Bus Support - Files: `kernel/src/pci.c`, `kernel/include/kernel/pci.h` diff --git a/docs/KERNEL_REFERENCE.md b/docs/KERNEL_REFERENCE.md index 3b966e6..5060d1e 100644 --- a/docs/KERNEL_REFERENCE.md +++ b/docs/KERNEL_REFERENCE.md @@ -158,7 +158,7 @@ if (gpu) { - **No Console Module**: As requested, no console.c/h files are created - **Minimal Design**: Only essential features for QT6 Hello World - **Bump Allocator**: Current heap doesn't support freeing (upgrade later if needed) -- **Physical Memory**: Simple bitmap allocator (supports up to 64GB with 2MB bitmap) +- **Physical Memory**: Bitmap allocator with UEFI memory map parsing (supports up to 64GB, auto-detects available RAM) - **PCI Scan**: Scans all 256 buses, 32 devices per bus - **Timer**: Uses PIT in rate generator mode diff --git a/kernel/include/kernel/memory.h b/kernel/include/kernel/memory.h index 551ba33..0c834ba 100644 --- a/kernel/include/kernel/memory.h +++ b/kernel/include/kernel/memory.h @@ -39,8 +39,9 @@ public: /** * @brief Initialize the physical memory manager with boot information - * @param bootInfo Boot information from bootloader (currently unused, assumes up to 64GB) - * @note Currently hardcoded to manage up to 64GB starting at 16MB physical address + * @param bootInfo Boot information from bootloader containing UEFI memory map + * @note Parses the UEFI memory map to detect actual available RAM (up to 64GB) + * @note Falls back to 128MB if memory map is unavailable */ void init(BootInfo* bootInfo); diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 50d3c11..1cdf1d1 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -27,30 +27,120 @@ PhysicalMemoryManager::PhysicalMemoryManager() /** * @brief Initialize the physical memory manager * - * Currently uses a simplified approach: - * - Assumes up to 64GB of usable RAM starting at physical address 16MB (0x01000000) - * - Clears the entire page bitmap to mark all pages as free - * - TODO: Parse the UEFI memory map from bootInfo to properly detect available memory + * Parses the UEFI memory map from the bootloader to detect available physical memory. + * Only considers memory regions that are usable: + * - EfiConventionalMemory (type 7): Free memory available for allocation + * - EfiBootServicesCode (type 3) and EfiBootServicesData (type 4): Reclaimable after boot + * - EfiLoaderCode (type 1) and EfiLoaderData (type 2): Reclaimable after boot * - * The 16MB starting address is chosen to avoid: + * Memory below 16MB (0x01000000) is avoided to prevent conflicts with: * - First 1MB: Legacy BIOS area, video memory, etc. * - 1MB-16MB: Kernel code, boot structures, and reserved areas * - * @param bootInfo Boot information structure (currently unused, TODO: parse memory map) + * @param bootInfo Boot information structure containing UEFI memory map */ void PhysicalMemoryManager::init(BootInfo* bootInfo) { - (void)bootInfo; // TODO: Parse UEFI memory map - - // For now, assume 64GB of usable memory starting at 16MB - // This supports any amount up to 64GB - totalPages = (64ULL * 1024 * 1024 * 1024) / PAGE_SIZE; - - // Clear bitmap + // Clear bitmap - mark all pages as used initially for (uint64_t i = 0; i < BITMAP_SIZE; i++) { - pageBitmap[i] = 0; + pageBitmap[i] = 0xFF; // All bits set = all pages marked as used } usedPages = 0; + totalPages = 0; + + // Define memory region base (16MB) to avoid low memory conflicts + const uint64_t MEMORY_BASE = 0x01000000UL; // 16MB + + // Parse UEFI memory map if available + if (bootInfo && bootInfo->memory_map && bootInfo->memory_map_size > 0) { + uint8_t* map = (uint8_t*)bootInfo->memory_map; + uint64_t descriptor_size = bootInfo->memory_map_descriptor_size; + uint64_t num_descriptors = bootInfo->memory_map_size / descriptor_size; + + // EFI Memory types we consider usable + const uint32_t EfiLoaderCode = 1; + const uint32_t EfiLoaderData = 2; + const uint32_t EfiBootServicesCode = 3; + const uint32_t EfiBootServicesData = 4; + const uint32_t EfiConventionalMemory = 7; + + uint64_t highest_usable_address = 0; + + // First pass: find highest usable address and mark free pages + for (uint64_t i = 0; i < num_descriptors; i++) { + // Cast to EFI_MEMORY_DESCRIPTOR structure + struct { + uint32_t Type; + uint64_t PhysicalStart; + uint64_t VirtualStart; + uint64_t NumberOfPages; + uint64_t Attribute; + }* desc = (decltype(desc))(map + i * descriptor_size); + + // Check if this is a usable memory type + bool is_usable = (desc->Type == EfiConventionalMemory || + desc->Type == EfiBootServicesCode || + desc->Type == EfiBootServicesData || + desc->Type == EfiLoaderCode || + desc->Type == EfiLoaderData); + + if (is_usable) { + uint64_t region_start = desc->PhysicalStart; + uint64_t region_size = desc->NumberOfPages * 4096; // EFI pages are 4KB + uint64_t region_end = region_start + region_size; + + // Only consider memory at or above MEMORY_BASE + if (region_end > MEMORY_BASE) { + uint64_t usable_start = (region_start < MEMORY_BASE) ? MEMORY_BASE : region_start; + uint64_t usable_end = region_end; + + // Track highest address + if (usable_end > highest_usable_address) { + highest_usable_address = usable_end; + } + + // Mark pages in this region as free in the bitmap + uint64_t start_page = (usable_start - MEMORY_BASE) / PAGE_SIZE; + uint64_t end_page = (usable_end - MEMORY_BASE) / PAGE_SIZE; + + for (uint64_t page = start_page; page < end_page; page++) { + uint64_t byte = page / 8; + uint64_t bit = page % 8; + + // Bounds check + if (byte >= BITMAP_SIZE) { + break; + } + + // Mark page as free (clear bit) + pageBitmap[byte] &= ~(1 << bit); + } + } + } + } + + // Calculate total pages based on highest usable address + if (highest_usable_address > MEMORY_BASE) { + totalPages = (highest_usable_address - MEMORY_BASE) / PAGE_SIZE; + + // Cap at bitmap capacity + uint64_t max_pages = BITMAP_SIZE * 8; + if (totalPages > max_pages) { + totalPages = max_pages; + } + } + } + + // Fallback: if no memory map or parsing failed, use safe defaults + if (totalPages == 0) { + // Assume 128MB as a conservative fallback + totalPages = (128 * 1024 * 1024) / PAGE_SIZE; + + // Mark all pages as free + for (uint64_t i = 0; i < BITMAP_SIZE; i++) { + pageBitmap[i] = 0; + } + } } /** From 90ccd7c4db4fa8ca723ae0f8c082c82dc29074c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:22:08 +0000 Subject: [PATCH 5/5] Address code review feedback - Define EFI_MEMORY_DESCRIPTOR struct for better code clarity - Use PAGE_SIZE constant instead of magic number 4096 - Add check in freePage() to prevent usedPages underflow Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- kernel/src/memory.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 1cdf1d1..3b46010 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -12,6 +12,15 @@ // Physical memory bitmap constants #define BITMAP_SIZE 2097152 // Supports up to 64GB with 4KB pages (64GB / 4KB = 16M pages, 16M bits = 2MB bitmap) +// EFI Memory Descriptor structure (from UEFI spec) +struct EFI_MEMORY_DESCRIPTOR { + uint32_t Type; + uint64_t PhysicalStart; + uint64_t VirtualStart; + uint64_t NumberOfPages; + uint64_t Attribute; +}; + /* PhysicalMemoryManager class implementation */ /** @@ -68,14 +77,7 @@ void PhysicalMemoryManager::init(BootInfo* bootInfo) { // First pass: find highest usable address and mark free pages for (uint64_t i = 0; i < num_descriptors; i++) { - // Cast to EFI_MEMORY_DESCRIPTOR structure - struct { - uint32_t Type; - uint64_t PhysicalStart; - uint64_t VirtualStart; - uint64_t NumberOfPages; - uint64_t Attribute; - }* desc = (decltype(desc))(map + i * descriptor_size); + EFI_MEMORY_DESCRIPTOR* desc = (EFI_MEMORY_DESCRIPTOR*)(map + i * descriptor_size); // Check if this is a usable memory type bool is_usable = (desc->Type == EfiConventionalMemory || @@ -86,7 +88,7 @@ void PhysicalMemoryManager::init(BootInfo* bootInfo) { if (is_usable) { uint64_t region_start = desc->PhysicalStart; - uint64_t region_size = desc->NumberOfPages * 4096; // EFI pages are 4KB + uint64_t region_size = desc->NumberOfPages * PAGE_SIZE; // EFI pages are 4KB uint64_t region_end = region_start + region_size; // Only consider memory at or above MEMORY_BASE @@ -211,6 +213,11 @@ void PhysicalMemoryManager::freePage(void* page) { return; } + // Check if page is already free to prevent underflow + if (!(pageBitmap[byte] & (1 << bit))) { + return; // Already free, nothing to do + } + // Mark as free pageBitmap[byte] &= ~(1 << bit); usedPages--;