From 50efcc13fe960798cc77b7c02665f98da3a1b3a9 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Thu, 15 May 2025 04:22:55 -0700 Subject: [PATCH] minor additions to the kernel heap and adding acpi --- kernel/acpi.c | 53 +++++++++++++++++++++++++++++++++++++++++++ kernel/acpi.h | 47 ++++++++++++++++++++++++++++++++++++++ kernel/elf.c | 50 +++++++++++++++++++++++++++++++++++++++++ kernel/elf.h | 52 ++++++++++++++++++++++++++++++++++++++++++ kernel/heap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-- kernel/heap.h | 3 +++ kernel/kmain.c | 19 ++++++++++++---- 7 files changed, 279 insertions(+), 6 deletions(-) create mode 100644 kernel/acpi.c create mode 100644 kernel/acpi.h diff --git a/kernel/acpi.c b/kernel/acpi.c new file mode 100644 index 0000000..06698d8 --- /dev/null +++ b/kernel/acpi.c @@ -0,0 +1,53 @@ +#include "acpi.h" +#include +#include +#include +#include + +// Function to find the RSDP (Root System Description Pointer) +acpi_rsdp_t* acpi_find_rsdp() { + // Search memory from 0x000E0000 to 0x00100000 (BIOS) + for (uint32_t addr = 0x000E0000; addr < 0x00100000; addr += 16) { + acpi_rsdp_t* rsdp = (acpi_rsdp_t*)addr; + if (memcmp(rsdp->signature, "RSD PTR ", 8) == 0) { + uint8_t checksum = 0; + for (int i = 0; i < sizeof(acpi_rsdp_t); i++) { + checksum += ((uint8_t*)rsdp)[i]; + } + if (checksum == 0) { + return rsdp; // Valid RSDP found + } + } + } + return NULL; // RSDP not found +} + +// Function to get the RSDT or XSDT based on the RSDP revision +void* acpi_get_rsdt_or_xsdt(acpi_rsdp_t* rsdp) { + if (rsdp->revision >= 2) { + return (void*)rsdp->xsdt_addr; // ACPI 2.0+ uses XSDT + } else { + return (void*)rsdp->rsdt_addr; // ACPI 1.0 uses RSDT + } +} + +// Function to find the FADT table within the RSDT or XSDT +acpi_fadt_t* acpi_find_fadt(void* rsdt_or_xsdt) { + acpi_rsdt_t* rsdt = (acpi_rsdt_t*)rsdt_or_xsdt; + uint32_t num_tables = (rsdt->length - sizeof(acpi_rsdt_t)) / sizeof(uint32_t); + + for (uint32_t i = 0; i < num_tables; i++) { + uint32_t table_addr = rsdt->tables[i]; + acpi_fadt_t* fadt = (acpi_fadt_t*)table_addr; + if (fadt->signature == 0x50434146) { // "FACP" in ASCII + uint8_t checksum = 0; + for (int j = 0; j < fadt->length; j++) { + checksum += ((uint8_t*)fadt)[j]; + } + if (checksum == 0) { + return fadt; // Valid FADT found + } + } + } + return NULL; // FADT not found +} diff --git a/kernel/acpi.h b/kernel/acpi.h new file mode 100644 index 0000000..189ab79 --- /dev/null +++ b/kernel/acpi.h @@ -0,0 +1,47 @@ +#ifndef ACPI_H +#define ACPI_H + +#include + +// ACPI base address (replace with actual value) +#define ACPI_BASE 0xE0000000 + +#ifndef NULL +#define NULL ((void*)0) +#endif + +// ACPI RSDP Structure (Root System Description Pointer) +typedef struct { + uint8_t signature[8]; // Should be "RSD PTR " + uint8_t checksum; // Checksum for the RSDP structure + uint8_t oem_id[6]; // OEM ID string + uint8_t revision; // ACPI revision + uint32_t rsdt_addr; // 32-bit RSDT address (ACPI 1.0) + uint32_t xsdt_addr; // 64-bit XSDT address (ACPI 2.0+) +} __attribute__((packed)) acpi_rsdp_t; + +// ACPI RSDT Structure (Root System Description Table) +typedef struct { + uint32_t signature; // Should be "RSDT" + uint32_t length; // Length of the table + uint8_t revision; // Revision of the RSDT table + uint8_t checksum; // Checksum for the RSDT table + uint32_t tables[]; // Array of pointers to other tables (RSDT/XSDT entries) +} __attribute__((packed)) acpi_rsdt_t; + +// ACPI FADT Structure (Fixed ACPI Description Table) +typedef struct { + uint32_t signature; // Should be "FACP" + uint32_t length; // Length of the table + uint8_t revision; // Revision of the FADT table + uint8_t checksum; // Checksum for the FADT table + uint32_t pm_tmr_address; // Power Management Timer Address + // ... other FADT fields +} __attribute__((packed)) acpi_fadt_t; + +// Function prototypes +acpi_rsdp_t* acpi_find_rsdp(); +void* acpi_get_rsdt_or_xsdt(acpi_rsdp_t* rsdp); +acpi_fadt_t* acpi_find_fadt(void* rsdt_or_xsdt); + +#endif /* ACPI_H */ diff --git a/kernel/elf.c b/kernel/elf.c index e69de29..66d54d0 100644 --- a/kernel/elf.c +++ b/kernel/elf.c @@ -0,0 +1,50 @@ +#include "elf.h" +#include +#include + +// This assumes that the elf is ELF32 and little-endian Intel X86 architecture. + +// Check if a binary is a valid ELF executable. +int elf_validate(const void* data) { + const Elf32_Ehdr* header = (const Elf32_Ehdr*)data; + + if (*(uint32_t*)header->e_ident != ELF_MAGIC) + return 0; + + if (header->e_type != ET_EXEC && header->e_type != ET_DYN) + return 0; + + if (header->e_machine != EM_386) + return 0; + + return 1; +} + +// Load an ELF executable into memory. +int elf_load(const void* data, void (*load_segment)(uint32_t vaddr, const void* src, uint32_t size)) { + const Elf32_Ehdr* header = (const Elf32_Ehdr*)data; + const Elf32_Phdr* ph = (const Elf32_Phdr*)((uint8_t*)data + header->e_phoff); + + for (int i = 0; i < header->e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) + continue; + + const void* src = (uint8_t*)data + ph[i].p_offset; + uint32_t vaddr = ph[i].p_vaddr; + uint32_t filesz = ph[i].p_filesz; + uint32_t memsz = ph[i].p_memsz; + + // Copy data segment + load_segment(vaddr, src, filesz); + + // Zero remaining BSS (if any) + if (memsz > filesz) { + uint8_t* bss_start = (uint8_t*)(vaddr + filesz); + for (uint32_t j = 0; j < memsz - filesz; j++) { + bss_start[j] = 0; + } + } + } + + return header->e_entry; +} diff --git a/kernel/elf.h b/kernel/elf.h index e69de29..9ba9ca0 100644 --- a/kernel/elf.h +++ b/kernel/elf.h @@ -0,0 +1,52 @@ +#ifndef ELF_H +#define ELF_H + +#include + +#define ELF_MAGIC 0x464C457F // "\x7FELF" in little-endian + +// ELF Types +#define ET_EXEC 2 +#define ET_DYN 3 + +// ELF Machine +#define EM_386 3 + +// ELF Ident indexes +#define EI_NIDENT 16 + +// Program header types +#define PT_NULL 0 +#define PT_LOAD 1 + +// ELF Header (32-bit) +typedef struct { + uint8_t e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; // Entry point + uint32_t e_phoff; // Program header table offset + uint32_t e_shoff; // Section header table offset + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} __attribute__((packed)) Elf32_Ehdr; + +// Program Header (32-bit) +typedef struct { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} __attribute__((packed)) Elf32_Phdr; + +#endif // ELF_H diff --git a/kernel/heap.c b/kernel/heap.c index 9a2fdfe..81afa7e 100644 --- a/kernel/heap.c +++ b/kernel/heap.c @@ -1,6 +1,63 @@ #include "heap.h" +#include + +typedef struct heap_block { + size_t size; + struct heap_block *next; + int is_free; +} heap_block_t; + +static heap_block_t *free_list = NULL; +static void *heap_start_ptr = NULL; +static void *heap_end_ptr = NULL; + +void heap_init(void *heap_start, void *heap_end) { + heap_start_ptr = heap_start; + heap_end_ptr = heap_end; + + free_list = (heap_block_t *)heap_start; + free_list->size = (uintptr_t)heap_end - (uintptr_t)heap_start - sizeof(heap_block_t); + free_list->next = NULL; + free_list->is_free = 1; +} void *heap_alloc(size_t size) { - // Heap allocation code - return NULL; + heap_block_t *current = free_list; + + while (current != NULL) { + if (current->is_free && current->size >= size) { + // If it's a large block, split it + if (current->size > size + sizeof(heap_block_t)) { + heap_block_t *new_block = (heap_block_t *)((uintptr_t)current + sizeof(heap_block_t) + size); + new_block->size = current->size - size - sizeof(heap_block_t); + new_block->next = current->next; + new_block->is_free = 1; + + current->next = new_block; + current->size = size; + } + + current->is_free = 0; + return (void *)((uintptr_t)current + sizeof(heap_block_t)); + } + + current = current->next; + } + + return NULL; // Out of memory +} + +void heap_free(void *ptr) { + if (ptr == NULL) return; + + heap_block_t *block = (heap_block_t *)((uintptr_t)ptr - sizeof(heap_block_t)); + block->is_free = 1; + + // Coalesce with next block + if (block->next && block->next->is_free) { + block->size += block->next->size + sizeof(heap_block_t); + block->next = block->next->next; + } + + // TODO: Coalesce with previous block for better compaction } diff --git a/kernel/heap.h b/kernel/heap.h index 6100172..e8b22c0 100644 --- a/kernel/heap.h +++ b/kernel/heap.h @@ -3,6 +3,9 @@ #include +void heap_init(void *heap_start, void *heap_end); + void *heap_alloc(size_t size); +void heap_free(void *ptr); #endif // HEAP_H diff --git a/kernel/kmain.c b/kernel/kmain.c index 4e8517b..07d0cd5 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -7,6 +7,7 @@ #include "paging.h" #include "memmap.h" #include "gdt.h" +#include "cpu.h" #define LPT1 0x378 @@ -22,6 +23,10 @@ void kmain(void) { serial_init(); serial_write("Serial port initialized.\n"); + terminal_write("Identifying CPU...\n"); + identify_cpu(); + serial_write("CPU identification complete.\n"); + lpt_write('L'); // Send 'L' to LPT1 to test terminal_write("Initializing GDT...\n"); @@ -53,11 +58,17 @@ void kmain(void) { serial_write("Memory map retrieved.\n"); terminal_write("Memory Regions:\n"); + + char buf[32]; for (uint32_t i = 0; i < mmap_size; i++) { - terminal_write(" - Region: "); - // You would format and print base/length/type here - // (e.g., with a basic itoa and print_hex helper) - serial_write("Memory region entry\n"); + terminal_write(" - Base: "); + print_hex((uint32_t)(mmap[i].base_addr & 0xFFFFFFFF)); // Lower 32 bits + terminal_write(", Length: "); + print_hex((uint32_t)(mmap[i].length & 0xFFFFFFFF)); // Lower 32 bits + terminal_write(", Type: "); + itoa(mmap[i].type, buf, 10); + terminal_write(buf); + terminal_write("\n"); } terminal_write("System initialized. Halting.\n");