From a90c7846d43acdcfe78b81e75b1ce80b569fe48e Mon Sep 17 00:00:00 2001 From: Atheria Date: Sat, 9 Aug 2025 13:30:34 +0700 Subject: [PATCH] It works --- arch/x86_64/interrupts/Interrupts.c | 15 +- drivers/Ide.c | 38 +- drivers/Ide.h | 4 - drivers/Serial.c | 12 + drivers/Serial.h | 2 + fs/FAT12.c | 46 ++- fs/Fs.c | 55 ++- fs/Fs.h | 2 +- fs/VFS.c | 128 +++++-- kernel/core/Kernel.c | 60 ++- kernel/etc/Editor.c | 561 +++++++++++----------------- kernel/etc/Shell.c | 65 +++- kernel/memory/KernelHeap.c | 4 +- kernel/memory/KernelHeap.h | 2 +- kernel/memory/VMem.c | 26 +- kernel/memory/VMem.h | 6 +- meson.build | 4 +- 17 files changed, 567 insertions(+), 463 deletions(-) diff --git a/arch/x86_64/interrupts/Interrupts.c b/arch/x86_64/interrupts/Interrupts.c index 9e83769..727bbad 100644 --- a/arch/x86_64/interrupts/Interrupts.c +++ b/arch/x86_64/interrupts/Interrupts.c @@ -5,7 +5,7 @@ #include "Keyboard.h" #include "Panic.h" #include "Process.h" - +#include "Serial.h" // The C-level interrupt handler, called from the assembly stub void InterruptHandler(Registers* regs) { ASSERT(regs != NULL); @@ -72,9 +72,22 @@ void InterruptHandler(Registers* regs) { uint64_t cr2; asm volatile("mov %%cr2, %0" : "=r"(cr2)); + // Serial logging for debugging + SerialWrite("\n[PAGEFAULT] CR2: 0x"); + SerialWriteHex(cr2); + SerialWrite(" RIP: 0x"); + SerialWriteHex(regs->rip); + SerialWrite(" RSP: 0x"); + SerialWriteHex(regs->rsp); + SerialWrite(" Error: 0x"); + SerialWriteHex(regs->error_code); + SerialWrite("\n"); + PrintKernelError(" TYPE: Page Fault (PF)\n"); PrintKernelError(" Faulting Address: "); PrintKernelHex(cr2); + PrintKernelError("\n RIP: "); + PrintKernelHex(regs->rip); PrintKernelError("\n Error Code: "); PrintKernelHex(regs->error_code); PrintKernelError("\n Details:\n"); diff --git a/drivers/Ide.c b/drivers/Ide.c index f586e52..60dd1b4 100644 --- a/drivers/Ide.c +++ b/drivers/Ide.c @@ -9,32 +9,35 @@ static volatile int ide_lock = 0; // Wait for drive to be ready (not busy) static int IdeWaitReady(uint16_t base_port) { - uint32_t timeout = 100000; // ~100ms timeout + uint32_t timeout = 500000; // Increased timeout for QEMU while (timeout--) { uint8_t status = inb(base_port + IDE_REG_STATUS); if (!(status & IDE_STATUS_BSY)) { - if (status & IDE_STATUS_ERR) { + if (status & IDE_STATUS_ERR) return IDE_ERROR_IO; - } - return IDE_OK; + return IDE_OK; // Don't require RDY bit } + // Small delay + for (volatile int i = 0; i < 100; i++); } return IDE_ERROR_TIMEOUT; } // Wait for data ready static int IdeWaitData(uint16_t base_port) { - uint32_t timeout = 100000; + uint32_t timeout = 500000; // Increased timeout while (timeout--) { uint8_t status = inb(base_port + IDE_REG_STATUS); - if (status & IDE_STATUS_DRQ) { + if (!(status & IDE_STATUS_BSY) && (status & IDE_STATUS_DRQ)) { return IDE_OK; } if (status & IDE_STATUS_ERR) { return IDE_ERROR_IO; } + // Small delay + for (volatile int i = 0; i < 100; i++); } return IDE_ERROR_TIMEOUT; } @@ -65,9 +68,12 @@ static int IdeIdentifyDrive(uint16_t base_port, uint8_t drive, uint16_t* buffer) // Send IDENTIFY command outb(base_port + IDE_REG_COMMAND, IDE_CMD_IDENTIFY); - // Check if drive exists + // Wait a bit after command + for (volatile int i = 0; i < 1000; i++); + + // Check if drive exists - be more lenient uint8_t status = inb(base_port + IDE_REG_STATUS); - if (status == 0) return IDE_ERROR_NO_DRIVE; + if (status == 0 || status == 0xFF) return IDE_ERROR_NO_DRIVE; result = IdeWaitData(base_port); if (result != IDE_OK) return result; @@ -146,15 +152,15 @@ int IdeReadSector(uint8_t drive, uint32_t lba, void* buffer) { return IDE_ERROR_NO_DRIVE; } - irq_flags_t flags = SpinLockIrqSave(&ide_lock); - + // Protect access to shared channels structure only + SpinLock(&ide_lock); uint16_t base_port = channels[channel].base_port; + SpinUnlock(&ide_lock); int result; // Select drive and set LBA result = IdeSelectDrive(base_port, drive_num, lba); if (result != IDE_OK) { - SpinUnlockIrqRestore(&ide_lock, flags); return result; } @@ -170,7 +176,6 @@ int IdeReadSector(uint8_t drive, uint32_t lba, void* buffer) { // Wait for data ready result = IdeWaitData(base_port); if (result != IDE_OK) { - SpinUnlockIrqRestore(&ide_lock, flags); return result; } @@ -180,7 +185,6 @@ int IdeReadSector(uint8_t drive, uint32_t lba, void* buffer) { buf16[i] = inw(base_port + IDE_REG_DATA); } - SpinUnlockIrqRestore(&ide_lock, flags); return IDE_OK; } @@ -194,15 +198,15 @@ int IdeWriteSector(uint8_t drive, uint32_t lba, const void* buffer) { return IDE_ERROR_NO_DRIVE; } - irq_flags_t flags = SpinLockIrqSave(&ide_lock); - + // Protect access to shared channels structure only + SpinLock(&ide_lock); uint16_t base_port = channels[channel].base_port; + SpinUnlock(&ide_lock); int result; // Select drive and set LBA result = IdeSelectDrive(base_port, drive_num, lba); if (result != IDE_OK) { - SpinUnlockIrqRestore(&ide_lock, flags); return result; } @@ -218,7 +222,6 @@ int IdeWriteSector(uint8_t drive, uint32_t lba, const void* buffer) { // Wait for data ready result = IdeWaitData(base_port); if (result != IDE_OK) { - SpinUnlockIrqRestore(&ide_lock, flags); return result; } @@ -230,7 +233,6 @@ int IdeWriteSector(uint8_t drive, uint32_t lba, const void* buffer) { // Wait for write completion result = IdeWaitReady(base_port); - SpinUnlockIrqRestore(&ide_lock, flags); return result; } diff --git a/drivers/Ide.h b/drivers/Ide.h index 91c7fd0..29cd34e 100644 --- a/drivers/Ide.h +++ b/drivers/Ide.h @@ -61,7 +61,3 @@ int IdeGetDriveInfo(uint8_t drive, char* model_out); void IDEPrimaryIRQH(void); void IDESecondaryIRQH(void); -// Internal Functions -static int IdeWaitReady(uint16_t base_port); -static int IdeSelectDrive(uint16_t base_port, uint8_t drive, uint32_t lba); -static int IdeIdentifyDrive(uint16_t base_port, uint8_t drive, uint16_t* buffer); \ No newline at end of file diff --git a/drivers/Serial.c b/drivers/Serial.c index c5f2500..2033526 100644 --- a/drivers/Serial.c +++ b/drivers/Serial.c @@ -32,4 +32,16 @@ void SerialWrite(const char* str) { for (int i = 0; str[i] != '\0'; i++) { SerialWriteChar(str[i]); } +} + +void SerialWriteHex(uint64_t value) { + const char hex[] = "0123456789ABCDEF"; + char buffer[17]; + buffer[16] = '\0'; + + for (int i = 15; i >= 0; i--) { + buffer[15-i] = hex[(value >> (i * 4)) & 0xF]; + } + + SerialWrite(buffer); } \ No newline at end of file diff --git a/drivers/Serial.h b/drivers/Serial.h index 2e95fc5..86fff3c 100644 --- a/drivers/Serial.h +++ b/drivers/Serial.h @@ -1,8 +1,10 @@ #ifndef VOIDFRAME_SERIAL_H #define VOIDFRAME_SERIAL_H +#include "stdint.h" void SerialInit(void); void SerialWriteChar(char c); void SerialWrite(const char* str); +void SerialWriteHex(uint64_t value); #endif // VOIDFRAME_SERIAL_H diff --git a/fs/FAT12.c b/fs/FAT12.c index 777376f..07db958 100644 --- a/fs/FAT12.c +++ b/fs/FAT12.c @@ -6,7 +6,7 @@ static Fat12Volume volume; static uint8_t* sector_buffer = NULL; -static int fat12_initialized = 0; +int fat12_initialized = 0; // Make global for VFS int Fat12Init(uint8_t drive) { if (fat12_initialized) { @@ -44,6 +44,8 @@ int Fat12Init(uint8_t drive) { uint32_t fat_size = volume.boot.sectors_per_fat * 512; volume.fat_table = KernelMemoryAlloc(fat_size); if (!volume.fat_table) { + KernelFree(sector_buffer); + sector_buffer = NULL; return -1; } @@ -51,6 +53,9 @@ int Fat12Init(uint8_t drive) { for (int i = 0; i < volume.boot.sectors_per_fat; i++) { if (IdeReadSector(drive, volume.fat_sector + i, volume.fat_table + (i * 512)) != IDE_OK) { KernelFree(volume.fat_table); + volume.fat_table = NULL; + KernelFree(sector_buffer); + sector_buffer = NULL; return -1; } } @@ -76,7 +81,7 @@ static uint16_t Fat12GetNextCluster(uint16_t cluster) { } int Fat12GetCluster(uint16_t cluster, uint8_t* buffer) { - if (cluster < 2 || cluster >= 0xFF8) return -1; + if (volume.boot.sectors_per_cluster == 0 || volume.boot.sectors_per_cluster > 8) return -1; uint32_t sector = volume.data_sector + ((cluster - 2) * volume.boot.sectors_per_cluster); @@ -90,13 +95,13 @@ int Fat12GetCluster(uint16_t cluster, uint8_t* buffer) { } int Fat12ListRoot(void) { - PrintKernel("[FAT12] Root directory contents:\n"); + PrintKernel("[SYSTEM] Root directory contents:\n"); uint32_t root_sectors = (volume.boot.root_entries * 32 + 511) / 512; for (uint32_t sector = 0; sector < root_sectors; sector++) { if (IdeReadSector(volume.drive, volume.root_sector + sector, sector_buffer) != IDE_OK) { - PrintKernelError("[FAT12] Failed to read root directory\n"); + PrintKernelError("[SYSTEM] Failed to read root directory\n"); return -1; } @@ -179,22 +184,39 @@ int Fat12ReadFile(const char* filename, void* buffer, uint32_t max_size) { // Found file, read it uint16_t cluster = entry->cluster_low; uint32_t bytes_read = 0; + uint32_t file_size = entry->file_size; uint8_t* buf_ptr = (uint8_t*)buffer; - - while (cluster < 0xFF8 && bytes_read < max_size) { - uint8_t cluster_buffer[512 * 8]; // Max cluster size + if (file_size == 0) { + return 0; + } + // Safety bound: max clusters we should traverse + uint32_t cluster_bytes = volume.boot.sectors_per_cluster * 512; + if (cluster_bytes == 0) return -1; + uint32_t max_clusters = (file_size + cluster_bytes - 1) / cluster_bytes; + uint32_t visited = 0; + + while (cluster < 0xFF8 && bytes_read < max_size && visited < max_clusters) { + uint8_t* cluster_buffer = KernelMemoryAlloc(cluster_bytes); + if (!cluster_buffer) return -1; + if (Fat12GetCluster(cluster, cluster_buffer) != 0) { + KernelFree(cluster_buffer); return -1; } - uint32_t cluster_size = volume.boot.sectors_per_cluster * 512; - uint32_t copy_size = (bytes_read + cluster_size > max_size) ? - (max_size - bytes_read) : cluster_size; - + + uint32_t cluster_size = cluster_bytes; + uint32_t remaining_in_file = (file_size > bytes_read) ? (file_size - bytes_read) : 0; + uint32_t copy_size = cluster_size; + if (copy_size > remaining_in_file) copy_size = remaining_in_file; + if (copy_size > (max_size - bytes_read)) copy_size = (max_size - bytes_read); + if (copy_size == 0) break; + FastMemcpy(buf_ptr + bytes_read, cluster_buffer, copy_size); bytes_read += copy_size; - + ++visited; cluster = Fat12GetNextCluster(cluster); + KernelFree(cluster_buffer); } return bytes_read; diff --git a/fs/Fs.c b/fs/Fs.c index 81e7277..1f762e4 100644 --- a/fs/Fs.c +++ b/fs/Fs.c @@ -3,6 +3,8 @@ #include "KernelHeap.h" #include "MemOps.h" #include "Process.h" +#include "StringOps.h" +#include "Serial.h" static FsNode* root_node = NULL; static FileHandle file_handles[MAX_OPEN_FILES]; @@ -72,7 +74,12 @@ FsNode* FsCreateNode(const char* name, FsNodeType type, FsNode* parent) { FsNode* node = AllocNode(); if (!node) return NULL; - FastMemcpy(node->name, name, MAX_FILENAME); + int len = 0; + while (name[len] && len < MAX_FILENAME - 1) { + node->name[len] = name[len]; + len++; + } + node->name[len] = '\0'; node->type = type; node->parent = parent; node->size = 0; @@ -93,9 +100,21 @@ FsNode* FsCreateNode(const char* name, FsNodeType type, FsNode* parent) { } FsNode* FsFind(const char* path) { - if (!path || !root_node) return NULL; + SerialWrite("[FS] FsFind called with path: "); + if (!path) { + SerialWrite("NULL\n"); + return NULL; + } + SerialWrite(path); + SerialWrite("\n"); + + if (!root_node) { + SerialWrite("[FS] root_node is NULL!\n"); + return NULL; + } if (path[0] == '/' && path[1] == '\0') { + SerialWrite("[FS] Returning root node\n"); return root_node; } @@ -112,9 +131,24 @@ FsNode* FsFind(const char* path) { if (name_idx == 0) continue; + SerialWrite("[FS] Looking for child: "); + SerialWrite(name_buf); + SerialWrite("\n"); + FsNode* child = current->children; while (child) { - if (FastMemcmp(child->name, name_buf, name_idx + 1) == 0) { + SerialWrite("[FS] Checking child at: 0x"); + SerialWriteHex((uint64_t)child); + SerialWrite(" name: "); + if (child->name) { + SerialWrite(child->name); + } else { + SerialWrite("NULL"); + } + SerialWrite("\n"); + + if (FastStrCmp(child->name, name_buf) == 0) { + SerialWrite("[FS] Found match!\n"); current = child; break; } @@ -150,9 +184,18 @@ int FsOpen(const char* path, FsOpenFlags flags) { if (last_slash == -1) return -1; - FastMemcpy(parent_path, path, last_slash + 1); + for (int i = 0; i <= last_slash; i++) { + parent_path[i] = path[i]; + } parent_path[last_slash + 1] = '\0'; - FastMemcpy(filename, path + last_slash + 1, MAX_FILENAME); + + int fn_len = 0; + const char* fn_start = path + last_slash + 1; + while (fn_start[fn_len] && fn_len < MAX_FILENAME - 1) { + filename[fn_len] = fn_start[fn_len]; + fn_len++; + } + filename[fn_len] = '\0'; FsNode* parent = FsFind(parent_path); if (!parent || parent->type != FS_DIRECTORY) return -1; @@ -338,7 +381,7 @@ int FsCreateDir(const char* path) { return FsMkdir(path); } -int FsWriteFile(const char* path, const void* buffer, uint32_t size) { +int FsWriteFile(const char* path, const void* buffer, size_t size) { int fd = FsOpen(path, FS_WRITE); if (fd < 0) return -1; int result = FsWrite(fd, buffer, size); diff --git a/fs/Fs.h b/fs/Fs.h index 11f90a5..82c4e74 100644 --- a/fs/Fs.h +++ b/fs/Fs.h @@ -61,6 +61,6 @@ FsNode* FsReaddir(const char* path); int FsListDir(const char* path); int FsCreateFile(const char* path); int FsCreateDir(const char* path); -int FsWriteFile(const char* path, const void* buffer, uint32_t size); +int FsWriteFile(const char* path, const void* buffer, size_t size); #endif \ No newline at end of file diff --git a/fs/VFS.c b/fs/VFS.c index 3fe85d5..c3418eb 100644 --- a/fs/VFS.c +++ b/fs/VFS.c @@ -5,6 +5,7 @@ #include "FsUtils.h" #include "MemOps.h" #include "StringOps.h" +#include "Serial.h" #define VFS_MAX_PATH_LEN 256 @@ -45,36 +46,44 @@ int VfsInit(void) { for (int i = 0; i < VFS_MAX_MOUNTS; i++) { mounts[i].active = 0; } - PrintKernel("[VFS] Mount table cleared\n"); + SerialWrite("[VFS] Mount table cleared\n"); // Mount RamFS as root - PrintKernel("[VFS] Mounting RamFS as root...\n"); + SerialWrite("[VFS] Mounting RamFS as root...\n"); int result = VfsMount("/", VFS_RAMFS, 0); - PrintKernel("[VFS] Root mount result: "); - PrintKernelInt(result); - PrintKernel("\n"); + if (result != 0) { + SerialWrite("[VFS] Failed to mount root\n"); + } + SerialWrite("[VFS] Root mounted"); - // Try to mount FAT12 on /disk - PrintKernel("[VFS] Attempting FAT12 mount...\n"); - int disk_result = VfsMount("/disk", VFS_FAT12, 0); - PrintKernel("[VFS] Disk mount result: "); - PrintKernelInt(disk_result); - PrintKernel("\n"); - PrintKernelSuccess("[VFS] FAT12 mounted at /disk\n"); + // Only mount FAT12 if it was successfully initialized + extern int fat12_initialized; + if (fat12_initialized) { + PrintKernel("[VFS] Attempting FAT12 mount...\n"); + int disk_result = VfsMount("/disk", VFS_FAT12, 0); - // Test mount table integrity - PrintKernel("[VFS] Testing mount table integrity:\n"); - for (int i = 0; i < VFS_MAX_MOUNTS; i++) { - if (mounts[i].active) { - PrintKernel("[VFS] Mount "); - PrintKernelInt(i); - PrintKernel(": '"); - PrintKernel(mounts[i].mount_point); - PrintKernel("' type="); - PrintKernelInt(mounts[i].type); - PrintKernel("\n"); + if (disk_result == 0) { + SerialWrite("[VFS] FAT12 mounted at /disk\n"); + } else { + SerialWrite("[VFS] FAT12 mount failed\n"); } + } else { + PrintKernel("[VFS] Skipping FAT12 mount - Already initialized\n"); } + + // // Test mount table integrity + // SerialWrite("[VFS] Testing mount table integrity:\n"); + // for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + // if (mounts[i].active) { + // SerialWrite("[VFS] Mount "); + // PrintKernelInt(i); + // PrintKernel(": '"); + // PrintKernel(mounts[i].mount_point); + // PrintKernel("' type="); + // PrintKernelInt(mounts[i].type); + // PrintKernel("\n"); + // } + // } PrintKernelSuccess("[VFS] Virtual File System initialized\n"); return 0; @@ -112,6 +121,8 @@ VfsMountStruct* VfsFindMount(const char* path) { } const char* VfsStripMount(const char* path, VfsMountStruct* mount) { + if (!path || !mount) return NULL; + int mount_len = FastStrlen(mount->mount_point, 64); if (mount_len == 1 && mount->mount_point[0] == '/') { return path; // Root mount @@ -124,23 +135,81 @@ const char* VfsStripMount(const char* path, VfsMountStruct* mount) { } int VfsReadFile(const char* path, void* buffer, uint32_t max_size) { + SerialWrite("[VFS] VfsReadFile called\n"); + if (!path || !buffer || max_size == 0) { + SerialWrite("[VFS] Invalid parameters\n"); + return -1; + } + + SerialWrite("[VFS] Finding mount for: "); + SerialWrite(path); + SerialWrite("\n"); + VfsMountStruct* mount = VfsFindMount(path); - if (!mount) return -1; + if (!mount) { + SerialWrite("[VFS] No mount found\n"); + return -1; + } + SerialWrite("[VFS] Mount found, stripping path\n"); const char* local_path = VfsStripMount(path, mount); + if (!local_path) { + SerialWrite("[VFS] Path strip failed\n"); + return -1; + } + + SerialWrite("[VFS] Mount type: "); + SerialWriteHex(mount->type); + SerialWrite("\n"); switch (mount->type) { case VFS_RAMFS: { - if (FastStrlen(local_path, 2) == 0) local_path = "/"; // normalize empty to root + SerialWrite("[VFS] RAMFS path, calling FsFind\n"); + if (FastStrlen(local_path, 2) == 0) local_path = "/"; + + SerialWrite("[VFS] About to call FsFind with: "); + SerialWrite(local_path); + SerialWrite("\n"); + FsNode* node = FsFind(local_path); - if (!node || node->type != FS_FILE) return -1; + SerialWrite("[VFS] FsFind returned\n"); + if (!node || node->type != FS_FILE) { + SerialWrite("[VFS] Node not found or not a file\n"); + return -1; + } + + // Handle empty files safely (node->data may be NULL when size == 0) + if (node->size == 0) { + SerialWrite("[VFS] Empty file, returning 0 bytes\n"); + return 0; + } + + // Guard against NULL data pointer + if (node->data == NULL) { + SerialWrite("[VFS] File data is NULL, returning 0 bytes\n"); + return 0; + } + + SerialWrite("[VFS] Copying data\n"); uint32_t copy_size = (node->size < max_size) ? node->size : max_size; + if (copy_size == 0) { + SerialWrite("[VFS] Nothing to copy (bounded to 0)\n"); + return 0; + } FastMemcpy(buffer, node->data, copy_size); + SerialWrite("[VFS] Copy complete\n"); return copy_size; } - case VFS_FAT12: + case VFS_FAT12: { + extern int fat12_initialized; + if (!fat12_initialized) { + PrintKernel("[VFS] FAT12 not initialized, cannot read\n"); + return -1; + } + PrintKernel("[VFS] Calling Fat12ReadFile\n"); return Fat12ReadFile(local_path, buffer, max_size); + } } return -1; @@ -171,11 +240,14 @@ int VfsListDir(const char* path) { } return result; } - case VFS_FAT12: + case VFS_FAT12: { + extern int fat12_initialized; + if (!fat12_initialized) return -1; if (FastStrCmp(local_path, "/") == 0 || FastStrlen(local_path, 256) == 0) { return Fat12ListRoot(); } return -1; + } } return -1; diff --git a/kernel/core/Kernel.c b/kernel/core/Kernel.c index 858cabf..6725a00 100644 --- a/kernel/core/Kernel.c +++ b/kernel/core/Kernel.c @@ -75,7 +75,14 @@ void BootstrapMapPage(uint64_t pml4_phys, uint64_t vaddr, uint64_t paddr, uint64 int pml4_idx = (vaddr >> 39) & 0x1FF; uint64_t pdpt_phys; if (!(pml4[pml4_idx] & PAGE_PRESENT)) { - pdpt_phys = (uint64_t)AllocPage(); + // allocate PDPT in identity-mapped region + pdpt_phys = 0; + for (int attempt = 0; attempt < 32; attempt++) { + void* candidate = AllocPage(); + if (!candidate) break; + if ((uint64_t)candidate < IDENTITY_MAP_SIZE) { pdpt_phys = (uint64_t)candidate; break; } + FreePage(candidate); + } if (!pdpt_phys) PANIC("BootstrapMapPage: Out of memory for PDPT"); if (pdpt_phys & 0xFFF) PANIC("PDPT not aligned"); FastZeroPage((void*)pdpt_phys); @@ -90,7 +97,14 @@ void BootstrapMapPage(uint64_t pml4_phys, uint64_t vaddr, uint64_t paddr, uint64 int pdpt_idx = (vaddr >> 30) & 0x1FF; uint64_t pd_phys; if (!(pdpt[pdpt_idx] & PAGE_PRESENT)) { - pd_phys = (uint64_t)AllocPage(); + // allocate PD in identity-mapped region + pd_phys = 0; + for (int attempt = 0; attempt < 32; attempt++) { + void* candidate = AllocPage(); + if (!candidate) break; + if ((uint64_t)candidate < IDENTITY_MAP_SIZE) { pd_phys = (uint64_t)candidate; break; } + FreePage(candidate); + } if (!pd_phys) PANIC("BootstrapMapPage: Out of memory for PD"); FastZeroPage((void*)pd_phys); pdpt[pdpt_idx] = pd_phys | PAGE_PRESENT | PAGE_WRITABLE; @@ -103,7 +117,14 @@ void BootstrapMapPage(uint64_t pml4_phys, uint64_t vaddr, uint64_t paddr, uint64 const int pd_idx = (vaddr >> 21) & 0x1FF; uint64_t pt_phys; if (!(pd[pd_idx] & PAGE_PRESENT)) { - pt_phys = (uint64_t)AllocPage(); + // allocate PT in identity-mapped region + pt_phys = 0; + for (int attempt = 0; attempt < 32; attempt++) { + void* candidate = AllocPage(); + if (!candidate) break; + if ((uint64_t)candidate < IDENTITY_MAP_SIZE) { pt_phys = (uint64_t)candidate; break; } + FreePage(candidate); + } if (!pt_phys) PANIC("BootstrapMapPage: Out of memory for PT"); FastZeroPage((void*)pt_phys); pd[pd_idx] = pt_phys | PAGE_PRESENT | PAGE_WRITABLE; @@ -236,15 +257,20 @@ static InitResultT CoreInit(void) { // Initialize IDE driver PrintKernel("[INFO] Initializing IDE driver...\n"); - IdeInit(); - PrintKernelSuccess("[SYSTEM] IDE driver initialized\n"); - - // Explicitly initialize FAT12 before VFS (explicit > auto-detect) - PrintKernel("[INFO] Initializing FAT12...\n"); - if (Fat12Init(0) == 0) { - PrintKernelSuccess("[SYSTEM] FAT12 Driver initialized\n"); + int ide_result = IdeInit(); + if (ide_result == IDE_OK) { + PrintKernelSuccess("[SYSTEM] IDE driver initialized\n"); + + // Explicitly initialize FAT12 before VFS (explicit > auto-detect) + PrintKernel("[INFO] Initializing FAT12...\n"); + if (Fat12Init(0) == 0) { + PrintKernelSuccess("[SYSTEM] FAT12 Driver initialized\n"); + } else { + PrintKernelWarning("[WARN] FAT12 initialization failed\n"); + } } else { - PrintKernelWarning("[WARN] FAT12 initialization failed\n"); + PrintKernelWarning("[WARN] IDE initialization failed - no drives detected\n"); + PrintKernelWarning("[WARN] Skipping FAT12 initialization\n"); } // Initialize ram filesystem @@ -286,9 +312,15 @@ void KernelMain(const uint32_t magic, const uint32_t info) { // Initialize physical memory manager first MemoryInit(g_multiboot_info_addr); - // Create new PML4 with memory validation - void* pml4_phys = AllocPage(); - if (!pml4_phys) PANIC("Failed to allocate PML4"); + // Create new PML4 with memory validation (ensure identity-mapped physical page) + void* pml4_phys = NULL; + for (int attempt = 0; attempt < 64; attempt++) { + void* candidate = AllocPage(); + if (!candidate) break; + if ((uint64_t)candidate < IDENTITY_MAP_SIZE) { pml4_phys = candidate; break; } + FreePage(candidate); + } + if (!pml4_phys) PANIC("Failed to allocate PML4 in identity-mapped memory"); FastZeroPage(pml4_phys); uint64_t pml4_addr = (uint64_t)pml4_phys; diff --git a/kernel/etc/Editor.c b/kernel/etc/Editor.c index bf8f99d..a529d73 100644 --- a/kernel/etc/Editor.c +++ b/kernel/etc/Editor.c @@ -1,413 +1,286 @@ #include "Editor.h" #include "Console.h" -#include "VFS.h" +#include "KernelHeap.h" #include "Keyboard.h" #include "MemOps.h" #include "Process.h" #include "StringOps.h" -#include "KernelHeap.h" +#include "VFS.h" -#define MAX_LINES 50 -#define MAX_LINE_LEN 80 -#define FILENAME_MAX_LEN 127 +#define MAX_BUFFER_SIZE 4096 -static char editor_buffer[MAX_LINES][MAX_LINE_LEN]; -static int current_line = 0; -static int current_col = 0; -static int total_lines = 1; -static char filename[FILENAME_MAX_LEN + 1]; -static int dirty = 0; // Track if file has unsaved changes -static int goto_mode = 0; // Track if we're in goto line mode -static char goto_buffer[10]; // Buffer for line number input -static int goto_pos = 0; // Position in goto buffer +static char* buffer = NULL; +static int buffer_size = 0; +static int cursor_pos = 0; +static char current_filename[128]; +static int dirty = 0; -// Helper function to get line length -static int get_line_length(int line) { - if (line < 0 || line >= MAX_LINES) return 0; - return FastStrlen(editor_buffer[line], MAX_LINE_LEN); +// Helpers to compute line/column information +static int EditorGetLineCount(void) { + int lines = 1; + for (int i = 0; i < buffer_size; i++) { + if (buffer[i] == '\n') lines++; + } + return lines; } -// Helper function to clamp cursor position -static void clamp_cursor(void) { - if (current_line < 0) current_line = 0; - if (current_line >= total_lines) current_line = total_lines - 1; - if (current_line >= MAX_LINES) current_line = MAX_LINES - 1; - - int line_len = get_line_length(current_line); - if (current_col > line_len) current_col = line_len; - if (current_col < 0) current_col = 0; - if (current_col >= MAX_LINE_LEN) current_col = MAX_LINE_LEN - 1; +static int EditorFindLineStart(int target_line) { + if (target_line <= 1) return 0; + int line = 1; + for (int i = 0; i < buffer_size; i++) { + if (buffer[i] == '\n') { + line++; + if (line == target_line) { + // Start is next character or end of buffer + return (i + 1 <= buffer_size) ? (i + 1) : buffer_size; + } + } + } + // If target_line is beyond existing lines, return end + return buffer_size; } -static void EditorRefresh(void) { - ClearScreen(); - PrintKernel("VoidFrame Editor - "); - PrintKernel(filename); - if (dirty) { - PrintKernel(" *"); +static void EditorGetCursorLineCol(int* out_line, int* out_col) { + int line = 1, col = 0; + for (int i = 0; i < buffer_size && i < cursor_pos; i++) { + if (buffer[i] == '\n') { line++; col = 0; } + else { col++; } } - PrintKernel(" (Ctrl+S=Save, Ctrl+Q=Quit, Ctrl+L=Goto Line)\n"); + if (out_line) *out_line = line; + if (out_col) *out_col = col; +} - if (goto_mode) { - PrintKernel("Go to line: "); - PrintKernel(goto_buffer); - PrintKernel("_\n"); - PrintKernel("(Enter to go, Esc to cancel)\n"); - PrintKernel("----------------------------------------\n"); - return; +static void EditorGotoLinePrompt(void) { + // Simple inline prompt at bottom + PrintKernel("\nGo to line: "); + char input[12]; + int len = 0; + while (1) { + while (!HasInput()) { Yield(); } + char c = GetChar(); + if (c == '\n' || c == '\r') { + break; + } else if ((c == '\b' || c == 127)) { + if (len > 0) { + len--; + PrintKernel("\b \b"); + } + } else if (c >= '0' && c <= '9') { + if (len < (int)sizeof(input) - 1) { + input[len++] = c; + char s[2] = { c, 0 }; + PrintKernel(s); + } + } } + input[len] = 0; + if (len == 0) return; + int target = 0; + for (int i = 0; i < len; i++) { target = target * 10 + (input[i] - '0'); } + if (target < 1) target = 1; + int pos = EditorFindLineStart(target); + if (pos < 0) pos = 0; + if (pos > buffer_size) pos = buffer_size; + cursor_pos = pos; +} +static void EditorRefresh(void) { + ClearScreen(); + PrintKernel("VoidFrame Editor - "); + PrintKernel(current_filename); + if (dirty) PrintKernel(" *"); + PrintKernel(" (Ctrl+S=Save, Ctrl+Q=Quit)\n"); PrintKernel("----------------------------------------\n"); - - // Display visible lines (simple scrolling) - int start_line = 0; - int display_lines = 20; // Adjust based on your screen size - - if (current_line >= display_lines) { - start_line = current_line - display_lines + 1; - } - - for (int i = start_line; i < start_line + display_lines && i < total_lines && i < MAX_LINES; i++) { - if (i == current_line) { - PrintKernel("> "); - } else { - PrintKernel(" "); + + // Print buffer content with line numbers and cursor + int current_line = 1; + int printed_any = 0; + // Print first line number + PrintKernelInt(current_line); + PrintKernel(" | "); + for (int i = 0; i < buffer_size; i++) { + if (i == cursor_pos) { PrintKernel("|"); } + char c[2] = { buffer[i], 0 }; + PrintKernel(c); + printed_any = 1; + if (buffer[i] == '\n' && i + 1 < buffer_size) { + current_line++; + PrintKernelInt(current_line); + PrintKernel(" | "); } - - // Print line number for reference - if (i < 9) PrintKernel(" "); - PrintKernelInt(i + 1); - PrintKernel(": "); - - PrintKernel(editor_buffer[i]); - PrintKernel("\n"); } - - PrintKernel("----------------------------------------\n"); - PrintKernel("Line "); - PrintKernelInt(current_line + 1); - PrintKernel("/"); - PrintKernelInt(total_lines); - PrintKernel(" Col "); - PrintKernelInt(current_col + 1); - if (dirty) { - PrintKernel(" [Modified]"); + if (!printed_any) { + // Empty buffer: just show cursor pipe after line number + if (cursor_pos == 0) PrintKernel("_"); + } else if (cursor_pos >= buffer_size) { + PrintKernel("_"); } + + PrintKernel("\n----------------------------------------\n"); + PrintKernel("Size: "); + PrintKernelInt(buffer_size); + int line, col; + EditorGetCursorLineCol(&line, &col); + PrintKernel(" Cursor: "); + PrintKernelInt(cursor_pos); + PrintKernel(" Line: "); + PrintKernelInt(line); + PrintKernel(" Col: "); + PrintKernelInt(col); PrintKernel("\n"); } -static int EditorSave(void) { - // Compute total length - int total_len = 0; - for (int i = 0; i < total_lines && i < MAX_LINES; i++) { - total_len += get_line_length(i); - if (i < total_lines - 1) total_len += 1; // newline - } - - char* buffer = (char*)KernelMemoryAlloc(total_len > 0 ? (size_t)total_len : 1); - if (!buffer) { - PrintKernel("\nError: Out of memory\n"); - return 0; - } - - int pos = 0; - for (int i = 0; i < total_lines && i < MAX_LINES; i++) { - int len = get_line_length(i); - if (len > 0) { - FastMemcpy(&buffer[pos], editor_buffer[i], len); - pos += len; - } - if (i < total_lines - 1) { - buffer[pos++] = '\n'; - } - } - - int written = VfsWriteFile(filename, buffer, (uint32_t)total_len); - KernelFree(buffer); - - if (written < 0 || written != total_len) { - PrintKernel("\nError: Write failed\n"); - return 0; +static void EditorSave(void) { + if (!buffer || buffer_size == 0) { + VfsWriteFile(current_filename, "", 0); + } else { + VfsWriteFile(current_filename, buffer, buffer_size); } - dirty = 0; - PrintKernel("\nFile saved successfully!\n"); - return 1; + PrintKernel("\nSaved!\n"); } static void EditorLoad(void) { - char buffer[4096]; - int bytes_read = VfsReadFile(filename, buffer, sizeof(buffer) - 1); - if (bytes_read <= 0) { - // New or empty file - FastMemset(editor_buffer, 0, sizeof(editor_buffer)); - total_lines = 1; - current_line = 0; - current_col = 0; - dirty = 0; + char* temp_buffer = (char*)KernelMemoryAlloc(MAX_BUFFER_SIZE); + if (!temp_buffer) { + buffer_size = 0; + cursor_pos = 0; return; } - if (bytes_read < (int)sizeof(buffer)) buffer[bytes_read] = '\0'; else buffer[sizeof(buffer)-1] = '\0'; - FastMemset(editor_buffer, 0, sizeof(editor_buffer)); - - int line = 0, col = 0; - for (int i = 0; i < bytes_read && line < MAX_LINES; i++) { - char ch = buffer[i]; - - if (ch == '\n') { - line++; - col = 0; - } else if (ch == '\r') { - continue; - } else if (ch >= 32 && ch <= 126) { - if (col < MAX_LINE_LEN - 1) { - editor_buffer[line][col++] = ch; - } - } - } - - total_lines = line + 1; - if (total_lines <= 0) total_lines = 1; - if (total_lines > MAX_LINES) total_lines = MAX_LINES; - - current_line = 0; - current_col = 0; - dirty = 0; - clamp_cursor(); -} - -// Convert string to integer (simple atoi) -static int str_to_int(const char* str) { - if (!str) return 0; - int result = 0; - int i = 0; - while (str[i] >= '0' && str[i] <= '9' && i < 10) { - result = result * 10 + (str[i] - '0'); - i++; - } - return result; -} - -// Handle goto line mode -static void handle_goto_mode(char c) { - if (c == 27) { // ESC - cancel goto - goto_mode = 0; - goto_pos = 0; - FastMemset(goto_buffer, 0, sizeof(goto_buffer)); - return; - } - - if (c == '\n' || c == '\r') { // Enter - execute goto - goto_buffer[goto_pos] = '\0'; - int target_line = str_to_int(goto_buffer); - - if (target_line > 0 && target_line <= total_lines) { - current_line = target_line - 1; // Convert to 0-based - current_col = 0; - clamp_cursor(); - } - - goto_mode = 0; - goto_pos = 0; - FastMemset(goto_buffer, 0, sizeof(goto_buffer)); + int bytes = VfsReadFile(current_filename, temp_buffer, MAX_BUFFER_SIZE - 1); + + if (bytes <= 0) { + KernelFree(temp_buffer); + buffer_size = 0; + cursor_pos = 0; return; } - - if (c == '\b' || c == 127) { // Backspace - if (goto_pos > 0) { - goto_pos--; - goto_buffer[goto_pos] = '\0'; - } + + if (buffer) KernelFree(buffer); + buffer = KernelMemoryAlloc(bytes); + if (!buffer) { + KernelFree(temp_buffer); return; } - - if (c >= '0' && c <= '9' && goto_pos < 9) { // Digit - goto_buffer[goto_pos] = c; - goto_pos++; - goto_buffer[goto_pos] = '\0'; - } + + FastMemcpy(buffer, temp_buffer, bytes); + KernelFree(temp_buffer); + buffer_size = bytes; + cursor_pos = 0; + dirty = 0; } -static void EditorInsertChar(const char c) { - if (current_col >= MAX_LINE_LEN - 1) return; - - // Shift characters right - for (int i = MAX_LINE_LEN - 2; i > current_col; i--) { - editor_buffer[current_line][i] = editor_buffer[current_line][i - 1]; +static void EditorInsertChar(char c) { + char* new_buffer = KernelMemoryAlloc(buffer_size + 1); + if (!new_buffer) return; + + // Copy before cursor + if (cursor_pos > 0) { + FastMemcpy(new_buffer, buffer, cursor_pos); } - - editor_buffer[current_line][current_col] = c; - current_col++; - // Ensure line is always null-terminated - editor_buffer[current_line][MAX_LINE_LEN - 1] = '\0'; + + // Insert character + new_buffer[cursor_pos] = c; + + // Copy after cursor + if (cursor_pos < buffer_size) { + FastMemcpy(new_buffer + cursor_pos + 1, buffer + cursor_pos, buffer_size - cursor_pos); + } + + if (buffer) KernelFree(buffer); + buffer = new_buffer; + buffer_size++; + cursor_pos++; dirty = 1; } static void EditorDeleteChar(void) { - if (current_col > 0) { - current_col--; - // Shift characters left - for (int i = current_col; i < MAX_LINE_LEN - 1; i++) { - editor_buffer[current_line][i] = editor_buffer[current_line][i + 1]; - } - // Ensure termination at end - editor_buffer[current_line][MAX_LINE_LEN - 1] = '\0'; - dirty = 1; - } else if (current_line > 0) { - // Join with previous line - int prev_len = get_line_length(current_line - 1); - - // Check if we can fit the current line - int curr_len = get_line_length(current_line); - if (prev_len + curr_len < MAX_LINE_LEN - 1) { - // Copy current line to end of previous line - int remaining_space = MAX_LINE_LEN - 1 - prev_len; - if (remaining_space > 0 && curr_len <= remaining_space) { - FastMemcpy(&editor_buffer[current_line - 1][prev_len], - editor_buffer[current_line], curr_len); - editor_buffer[current_line - 1][prev_len + curr_len] = '\0'; - } - // Move lines up - for (int i = current_line; i < total_lines - 1 && i < MAX_LINES - 1; i++) { - FastMemcpy(editor_buffer[i], editor_buffer[i + 1], MAX_LINE_LEN); - } - - // Clear last line - if (total_lines > 0 && total_lines <= MAX_LINES) { - FastMemset(editor_buffer[total_lines - 1], 0, MAX_LINE_LEN); - } - - current_line--; - current_col = prev_len; - total_lines--; - if (total_lines <= 0) total_lines = 1; - dirty = 1; + if (cursor_pos == 0 || buffer_size == 0) return; + + char* new_buffer = KernelMemoryAlloc(buffer_size - 1); + if (!new_buffer && buffer_size > 1) return; + + cursor_pos--; + + if (buffer_size == 1) { + KernelFree(buffer); + buffer = NULL; + buffer_size = 0; + } else { + // Copy before cursor + if (cursor_pos > 0) { + FastMemcpy(new_buffer, buffer, cursor_pos); } - } - clamp_cursor(); -} - -static void EditorNewLine(void) { - if (total_lines >= MAX_LINES) return; - - // Move lines down - for (int i = (total_lines < MAX_LINES ? total_lines : MAX_LINES - 1); i > current_line + 1; i--) { - FastMemcpy(editor_buffer[i], editor_buffer[i-1], MAX_LINE_LEN); - } - - // Split current line at cursor - if (current_line + 1 < MAX_LINES) { - FastMemset(editor_buffer[current_line + 1], 0, MAX_LINE_LEN); - - // Copy text after cursor to new line using FastMemcpy - int curr_len = get_line_length(current_line); - int copy_len = curr_len - current_col; - if (copy_len > 0) { - if (copy_len > MAX_LINE_LEN - 1) copy_len = MAX_LINE_LEN - 1; - FastMemcpy(editor_buffer[current_line + 1], - &editor_buffer[current_line][current_col], copy_len); - editor_buffer[current_line + 1][copy_len] = '\0'; + + // Copy after deleted char + if (cursor_pos < buffer_size - 1) { + FastMemcpy(new_buffer + cursor_pos, buffer + cursor_pos + 1, buffer_size - cursor_pos - 1); } - - // Truncate current line at cursor - editor_buffer[current_line][current_col] = '\0'; + + KernelFree(buffer); + buffer = new_buffer; + buffer_size--; } - - current_line++; - current_col = 0; - if (total_lines < MAX_LINES) total_lines++; + dirty = 1; - clamp_cursor(); } -void EditorOpen(const char* file) { - if (!file) return; - - // Safely copy filename using Fast string copy - FastStrCopy(filename, file, FILENAME_MAX_LEN + 1); - +void EditorOpen(const char* filename) { + if (!filename) return; + + FastStrCopy(current_filename, filename, 127); + + if (buffer) { + KernelFree(buffer); + buffer = NULL; + } + buffer_size = 0; + cursor_pos = 0; + dirty = 0; + EditorLoad(); - + while (1) { EditorRefresh(); - - // Wait for input + while (!HasInput()) { Yield(); } - + char c = GetChar(); - - // Handle goto line mode first - if (goto_mode) { - handle_goto_mode(c); - continue; - } - - // Handle control characters first - if (c == 19) { // Ctrl+S - Save + + if (c == 19) { // Ctrl+S EditorSave(); continue; } - - if (c == 17) { // Ctrl+Q - Quit + + if (c == 17) { // Ctrl+Q if (dirty) { - PrintKernel("\nFile has unsaved changes! Press Ctrl+Q again to quit without saving, or Ctrl+S to save.\n"); - // Wait for another key + PrintKernel("\nUnsaved changes! Press Ctrl+Q again to quit.\n"); while (!HasInput()) Yield(); - char confirm = GetChar(); - if (confirm != 17) { // Not Ctrl+Q again - continue; - } + if (GetChar() != 17) continue; } - PrintKernel("\nExiting editor...\n"); break; } - - if (c == 12) { // Ctrl+L - Goto line - goto_mode = 1; - goto_pos = 0; - FastMemset(goto_buffer, 0, sizeof(goto_buffer)); - continue; - } - - // Navigation - if (c == 23) { // Ctrl+W - Up - if (current_line > 0) { - current_line--; - } - } else if (c == 24) { // Ctrl+X - Down - if (current_line < total_lines - 1) { - current_line++; - } - } else if (c == 1) { // Ctrl+A - Left - if (current_col > 0) { - current_col--; - } else if (current_line > 0) { - current_line--; - current_col = get_line_length(current_line); - } - } else if (c == 4) { // Ctrl+D - Right - int line_len = get_line_length(current_line); - if (current_col < line_len) { - current_col++; - } else if (current_line < total_lines - 1) { - current_line++; - current_col = 0; - } - } - // Text editing - else if (c == '\n' || c == '\r') { - EditorNewLine(); - } else if (c == '\b' || c == 127) { // Backspace or DEL + + if (c == 1) { // Ctrl+A - cursor left + if (cursor_pos > 0) cursor_pos--; + } else if (c == 4) { // Ctrl+D - cursor right + if (cursor_pos < buffer_size) cursor_pos++; + } else if (c == '\b' || c == 127) { // Backspace EditorDeleteChar(); - } else if (c >= 32 && c <= 126) { - // Printable character + } else if (c >= 32 && c <= 126) { // Printable EditorInsertChar(c); + } else if (c == '\n' || c == '\r') { // Enter + EditorInsertChar('\n'); + } else if (c == 12) { // Ctrl+L: Go to line + EditorGotoLinePrompt(); } - - // Always clamp cursor after any operation - clamp_cursor(); + } + + if (buffer) { + KernelFree(buffer); + buffer = NULL; } } \ No newline at end of file diff --git a/kernel/etc/Shell.c b/kernel/etc/Shell.c index 5fc4e56..5c483ea 100644 --- a/kernel/etc/Shell.c +++ b/kernel/etc/Shell.c @@ -3,6 +3,7 @@ #include "Editor.h" #include "FAT12.h" #include "Ide.h" +#include "KernelHeap.h" #include "Keyboard.h" #include "MemOps.h" #include "Process.h" @@ -29,7 +30,11 @@ static char* GetArg(const char* cmd, int arg_num) { if (cmd[pos] == ' ') { if (word == arg_num) { arg_buf[buf_pos] = '\0'; - return buf_pos > 0 ? arg_buf : NULL; + if (buf_pos == 0) return NULL; + char* copy = KernelMemoryAlloc(buf_pos + 1); + if (!copy) return NULL; + FastMemcpy(copy, arg_buf, buf_pos + 1); + return copy; } // Skip multiple spaces while (cmd[pos] == ' ') pos++; @@ -46,7 +51,10 @@ static char* GetArg(const char* cmd, int arg_num) { // Handle last argument if (word == arg_num && buf_pos > 0) { arg_buf[buf_pos] = '\0'; - return arg_buf; + char* copy = KernelMemoryAlloc(buf_pos + 1); + if (!copy) return NULL; + FastMemcpy(copy, arg_buf, buf_pos + 1); + return copy; } return NULL; } @@ -122,8 +130,6 @@ static void ExecuteCommand(const char* cmd) { char new_path[256]; ResolvePath(dir, new_path, 256); - // Normalize: handle "." and ".." segments on RAMFS side using VFS existence check - // Simple check via VfsIsDir; if not a directory, do not change current_dir if (VfsIsDir(new_path)) { FastMemcpy(current_dir, new_path, 256); PrintKernel("[VFS] DIRECTORY SWITCHED TO "); @@ -134,6 +140,7 @@ static void ExecuteCommand(const char* cmd) { PrintKernel(new_path); PrintKernel("\n"); } + KernelFree(dir); } } else if (FastStrCmp(cmd_name, "pwd") == 0) { PrintKernel(current_dir); @@ -146,22 +153,32 @@ static void ExecuteCommand(const char* cmd) { char full_path[256]; ResolvePath(path, full_path, 256); VfsListDir(full_path); + KernelFree(path); } } else if (FastStrCmp(cmd_name, "cat") == 0) { char* file = GetArg(cmd, 1); - if (file) { + if (file) { char full_path[256]; ResolvePath(file, full_path, 256); - static uint8_t file_buffer[4096]; - int bytes = VfsReadFile(full_path, file_buffer, 4095); - if (bytes > 0) { - file_buffer[bytes] = 0; - PrintKernel((char*)file_buffer); - PrintKernel("\n"); + uint8_t* file_buffer = KernelMemoryAlloc(4096); + if (file_buffer) { + int bytes = VfsReadFile(full_path, file_buffer, 4095); + if (bytes >= 0) { + // Null-terminate and print if non-empty + file_buffer[(bytes < 4095) ? bytes : 4095] = 0; + if (bytes > 0) { + PrintKernel((char*)file_buffer); + } + PrintKernel("\n"); + } else { + PrintKernel("cat: file not found or read error\n"); + } + KernelFree(file_buffer); } else { - PrintKernel("cat: file not found or read error\n"); + PrintKernel("cat: out of memory\n"); } + KernelFree(file); } else { PrintKernel("Usage: cat \n"); } @@ -175,6 +192,7 @@ static void ExecuteCommand(const char* cmd) { } else { PrintKernel("Failed to create directory\n"); } + KernelFree(name); } else { PrintKernel("Usage: mkdir \n"); } @@ -188,6 +206,7 @@ static void ExecuteCommand(const char* cmd) { } else { PrintKernel("Failed to create file\n"); } + KernelFree(name); } else { PrintKernel("Usage: touch \n"); } @@ -201,6 +220,7 @@ static void ExecuteCommand(const char* cmd) { } else { PrintKernel("Failed to remove (file not found or directory not empty)\n"); } + KernelFree(name); } else { PrintKernel("Usage: rm \n"); } @@ -217,8 +237,12 @@ static void ExecuteCommand(const char* cmd) { } else { PrintKernel("Failed to write to file\n"); } + KernelFree(text); + KernelFree(file); } else { PrintKernel("Usage: echo \n"); + if (text) KernelFree(text); + if (file) KernelFree(file); } } else if (FastStrCmp(cmd_name, "edit") == 0) { char* file = GetArg(cmd, 1); @@ -226,6 +250,7 @@ static void ExecuteCommand(const char* cmd) { char full_path[256]; ResolvePath(file, full_path, 256); EditorOpen(full_path); + KernelFree(file); } else { PrintKernel("Usage: edit \n"); } @@ -250,11 +275,14 @@ static void ExecuteCommand(const char* cmd) { VfsListDir("/test"); PrintKernel("[VFS] Contents of /test/hello.txt:\n"); - static uint8_t file_buffer[256]; - int bytes = VfsReadFile("/test/hello.txt", file_buffer, 255); - if (bytes > 0) { - file_buffer[bytes] = 0; - PrintKernel((char*)file_buffer); + uint8_t* file_buffer = KernelMemoryAlloc(256); + if (file_buffer) { + int bytes = VfsReadFile("/test/hello.txt", file_buffer, 255); + if (bytes > 0) { + file_buffer[bytes] = 0; + PrintKernel((char*)file_buffer); + } + KernelFree(file_buffer); } PrintKernel("[VFS] Filesystem tests completed\n"); @@ -263,6 +291,8 @@ static void ExecuteCommand(const char* cmd) { PrintKernel(cmd_name); PrintKernel("\nType 'help' for commands\n"); } + + KernelFree(cmd_name); } void ShellInit(void) { @@ -271,7 +301,6 @@ void ShellInit(void) { void ShellProcess(void) { PrintKernelSuccess("VoidFrame Shell v0.0.1-beta\n"); - PrintKernelSuccess("VoidFrame Shell. Press ENTER to start shell\n"); // actually start already but on start the /> isnt there so yeah while (1) { if (HasInput()) { char c = GetChar(); diff --git a/kernel/memory/KernelHeap.c b/kernel/memory/KernelHeap.c index 19b7d7a..fa5fe3c 100644 --- a/kernel/memory/KernelHeap.c +++ b/kernel/memory/KernelHeap.c @@ -1,7 +1,5 @@ #include "KernelHeap.h" - #include "Console.h" -#include "Kernel.h" #include "MemOps.h" #include "Spinlock.h" #include "VMem.h" @@ -224,7 +222,7 @@ void* KernelMemoryAlloc(size_t size) { return BlockToUser(block); } -void* KernelCallocate(size_t num, size_t size) { +void* KernelAllocate(size_t num, size_t size) { // Check for overflow if (num && size > MAX_ALLOC_SIZE / num) { return NULL; diff --git a/kernel/memory/KernelHeap.h b/kernel/memory/KernelHeap.h index 7a25ebd..bc443b2 100644 --- a/kernel/memory/KernelHeap.h +++ b/kernel/memory/KernelHeap.h @@ -6,7 +6,7 @@ void KernelHeapInit(); void* KernelMemoryAlloc(size_t size); -void* KernelCallocate(size_t num, size_t size); +void* KernelAllocate(size_t num, size_t size); void* KernelReallocate(void* ptr, size_t size); void KernelFree(void* ptr); void PrintHeapStats(void); diff --git a/kernel/memory/VMem.c b/kernel/memory/VMem.c index d8c9261..c575cca 100644 --- a/kernel/memory/VMem.c +++ b/kernel/memory/VMem.c @@ -51,13 +51,10 @@ void VMemInit(void) { static uint64_t VMemGetPageTablePhys(uint64_t pml4_phys, uint64_t vaddr, int level, int create) { if (!is_valid_phys_addr(pml4_phys)) return 0; - // Access page table through identity mapping - uint64_t* table_virt; - if (pml4_phys < IDENTITY_MAP_SIZE) { - table_virt = (uint64_t*)pml4_phys; - } else { - table_virt = (uint64_t*)PHYS_TO_VIRT(pml4_phys); - } + // Access the table via identity map when available, otherwise via higher-half mapping + uint64_t* table_virt = (pml4_phys < IDENTITY_MAP_SIZE) + ? (uint64_t*)pml4_phys + : (uint64_t*)PHYS_TO_VIRT(pml4_phys); int shift = 39 - (level * 9); int index = (vaddr >> shift) & PT_INDEX_MASK; @@ -66,14 +63,25 @@ static uint64_t VMemGetPageTablePhys(uint64_t pml4_phys, uint64_t vaddr, int lev if (!(table_virt[index] & PAGE_PRESENT)) { if (!create) return 0; - void* new_table_phys = AllocPage(); + // Allocate page-table memory from identity-mapped low memory to ensure accessibility + void* new_table_phys = NULL; + for (int attempt = 0; attempt < 32; attempt++) { + void* candidate = AllocPage(); + if (!candidate) break; + if ((uint64_t)candidate < IDENTITY_MAP_SIZE) { + new_table_phys = candidate; + break; + } + // Not identity-mapped; return it to the pool and try again + FreePage(candidate); + } if (!new_table_phys) return 0; if (!is_valid_phys_addr((uint64_t)new_table_phys)) { FreePage(new_table_phys); return 0; } - // Zero the new table using identity mapping if possible + // Zero the new table using an address we can access if ((uint64_t)new_table_phys < IDENTITY_MAP_SIZE) { FastZeroPage(new_table_phys); } else { diff --git a/kernel/memory/VMem.h b/kernel/memory/VMem.h index 4ff1c9a..655bdf8 100644 --- a/kernel/memory/VMem.h +++ b/kernel/memory/VMem.h @@ -38,9 +38,9 @@ #define KERNEL_VIRTUAL_OFFSET 0xFFFFFFFF80000000ULL #define KERNEL_VIRTUAL_BASE KERNEL_VIRTUAL_OFFSET -// Heap space layout -#define VIRT_ADDR_SPACE_START 0xFFFF800000000000ULL // Heap start -#define VIRT_ADDR_SPACE_END 0xFFFFFFFF7FFFFFFFULL // Heap end (before kernel) +// Heap space layout - Non-overlapping canonical addresses +#define VIRT_ADDR_SPACE_START 0xFFFF800000000000ULL // Heap start (canonical) +#define VIRT_ADDR_SPACE_END 0xFFFFFFFF7FFFFFFFULL // End before kernel space #define KERNEL_SPACE_START KERNEL_VIRTUAL_BASE // Kernel starts here #define KERNEL_SPACE_END 0xFFFFFFFFFFFFFFFFULL // Kernel ends at top diff --git a/meson.build b/meson.build index ca93cf8..af7498d 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,8 @@ project('voidframe', 'c', nasm = find_program('nasm') grub_mkrescue = find_program('grub-mkrescue') +qemu_img = find_program('qemu-img', required : true) +mkfs_fat = find_program('mkfs.fat', required : true) # Source root src_root = './' @@ -150,7 +152,7 @@ iso = custom_target('VoidFrame.iso', # Run target run_target('run', - command : ['qemu-system-x86_64', '-cdrom', 'VoidFrame.iso', '-debugcon', 'stdio' , '-no-reboot','-no-shutdown','-m', '1G', '-drive', 'file=VoidFrameDisk.img,format=raw,if=ide', '-boot', 'd'] + command : ['qemu-system-x86_64', '-cdrom', 'VoidFrame.iso', '-serial', 'stdio' , '-no-reboot','-no-shutdown','-m', '1G', '-drive', 'file=VoidFrameDisk.img,format=raw,if=ide', '-boot', 'd'] ) run_target('img',