From 2b1d6cca5f48f9e1d4959c6ab15a808e5a75a2c6 Mon Sep 17 00:00:00 2001 From: Curle Date: Sat, 28 Nov 2020 16:43:43 +0000 Subject: [PATCH] Fixes for memory. Lots of work left. Mainly, we need to be able to locate the kernel executable physically in memory. --- chroma/inc/kernel/boot/boot.h | 29 ++++++++++++++++++++++- chroma/inc/kernel/chroma.h | 1 + chroma/inc/kernel/system/memory.h | 6 +++-- chroma/kernel.c | 39 +++++++++++++++++++++++++++++++ chroma/system/memory/paging.c | 17 ++++++++------ 5 files changed, 82 insertions(+), 10 deletions(-) diff --git a/chroma/inc/kernel/boot/boot.h b/chroma/inc/kernel/boot/boot.h index 7c0f9e7..b012a80 100644 --- a/chroma/inc/kernel/boot/boot.h +++ b/chroma/inc/kernel/boot/boot.h @@ -14,7 +14,8 @@ extern "C" { #define BOOT_MAGIC "BOOT" /* minimum protocol level: - * hardcoded kernel name, static kernel memory addresses */ + * hardcoded kernel name, static kernel memory addresses + * this is the default */ #define PROTOCOL_MINIMAL 0 /* static protocol level: * kernel name parsed from environment, static kernel memory addresses */ @@ -27,6 +28,7 @@ extern "C" { /* loader types, just informational */ #define LOADER_BIOS (0<<2) +/* unless we get to a weird stage, these should never be used. */ #define LOADER_UEFI (1<<2) #define LOADER_RPI (2<<2) @@ -106,6 +108,31 @@ typedef struct { } __attribute__((packed)) bootinfo; +typedef struct { + uint32_t Magic; + uint8_t Class; + uint8_t Endianness; + uint8_t Version; + uint8_t ABI; + uint8_t ABIVersion; + uint8_t Unused[7]; + uint16_t Type; + uint16_t TargetArchitecture; + uint32_t ELFVersion; + size_t EntryPoint; + size_t ProgramHeadersTable; + size_t SectionHeadersTable; + uint32_t Flags; + uint16_t ELFHeaderSize; + uint16_t ProgramHeadersEntrySize; + uint16_t ProgramHeaderEntries; + uint16_t SectionHeadersEntrySize; + uint16_t SectionHeaderEntries; + uint16_t SectionHeaderNameEntry; + uint8_t End; +} __attribute__((packed)) ELF64Header_t; + + #ifdef __cplusplus } #endif diff --git a/chroma/inc/kernel/chroma.h b/chroma/inc/kernel/chroma.h index 8ec5f92..adef472 100644 --- a/chroma/inc/kernel/chroma.h +++ b/chroma/inc/kernel/chroma.h @@ -28,6 +28,7 @@ extern bootinfo bootldr; extern unsigned char* environment; extern uint8_t fb; extern volatile unsigned char _binary_font_psf_start; +extern volatile size_t* _kernel_text_start; extern address_space_t KernelAddressSpace; diff --git a/chroma/inc/kernel/system/memory.h b/chroma/inc/kernel/system/memory.h index 93a1669..418b80f 100644 --- a/chroma/inc/kernel/system/memory.h +++ b/chroma/inc/kernel/system/memory.h @@ -8,6 +8,8 @@ *** Chroma *** ***********************/ +size_t KernelLocation; + /************************************************ * C O N S T A N T S A N D M A C R O S @@ -52,6 +54,8 @@ #define ERR_RESERVED 0x8 #define ERR_INST 0x10 +#define ELF64MAGIC 0x7F454c46 + /* * The way we boot, using BOOTBOOT, and the static hard drive images, means @@ -104,8 +108,6 @@ #define FB_REGION 0xFFFFFFFFFC000000ull // Cannot move! #define FB_PHYSICAL 0x00000000E0000000ull // Physical location of the Framebuffer #define KERNEL_REGION 0xFFFFFFFFFFE00000ull // -2MiB, from bootloader -#define KERNEL_PHYSICAL 0x0000000000008000ull // Physical location of the kernel -#define KERNEL_PHYSICAL_2 0x000000000011C000ull // For some reason the kernel is split in half #define USER_REGION 0x00007FFFFFFFFFFFull // Not needed yet, but we're higher half so we might as well be thorough diff --git a/chroma/kernel.c b/chroma/kernel.c index 6e279d4..2d8d1f0 100644 --- a/chroma/kernel.c +++ b/chroma/kernel.c @@ -20,9 +20,48 @@ address_space_t KernelAddressSpace; int Main(void) { KernelAddressSpace = (address_space_t) {0}; + KernelLocation = 0x112600; SerialPrintf("\r\n[ boot] Booting Chroma..\r\n"); SerialPrintf("[ boot] Kernel loaded at 0x%p, ends at 0x%p, is %d bytes long.\r\n", KernelAddr, KernelEnd, KernelEnd - KernelAddr); + SerialPrintf("[ boot] Initrd is physically at 0x%p, and is %d bytes long.\r\n", bootldr.initrd_ptr, bootldr.initrd_size); + + SerialPrintf("[ boot] Searching for kernel... Constants start at 0x%p\r\n", &_kernel_text_start); + // We stop at the constants in the kernel, otherwise we'll read the constant ELF64MAGIC which is stored inside the kernel... + + size_t headerLoc = 0; + for(size_t i = KernelAddr; i < KernelEnd; i++) { + if(i < (size_t) (&_kernel_text_start) - KernelAddr) { + if(*((volatile uint32_t*)(i)) == ELF64MAGIC) { + SerialPrintf("[ boot] Matched kernel header at 0x%p.\r\n", i); + } + } + } + + int flag = 0; + + if(headerLoc) { + ELF64Header_t* PotentialKernelHeader = (ELF64Header_t*) &headerLoc; + SerialPrintf( + "[ boot] Considering ELF with:\r\n\tBitness %d\r\n\tEntry point 0x%p\r\n\tFile type %s : %d\r\n\tArchitecture %s : %d\r\n", + PotentialKernelHeader->Class == 2 ? 64 : 32, PotentialKernelHeader->EntryPoint, PotentialKernelHeader->Type == 0x02 ? "EXECUTABLE" : "OTHER", PotentialKernelHeader->Type, PotentialKernelHeader->TargetArchitecture == 0x3E ? "AMD64" : "OTHER", PotentialKernelHeader->TargetArchitecture); + if(PotentialKernelHeader->EntryPoint == KernelAddr) { + SerialPrintf("[ boot] Header at 0x%p matches kernel header.\r\n", headerLoc); + flag = 1; + } + + if(!flag) { + + for(size_t i = 0; i < 8; i++) { + SerialPrintf("[ boot] Header dump part %d: 0x%x\r\n", i, *((volatile uint32_t*)(headerLoc + i))); + } + } + } + + if(!flag) { + SerialPrintf("[ boot] Unable to find kernel in memory. Fatal error.\r\n"); + //for(;;) {} + } SerialPrintf("[ boot] The bootloader has put the paging tables at 0x%p.\r\n", ReadControlRegister(3)); diff --git a/chroma/system/memory/paging.c b/chroma/system/memory/paging.c index f21c079..f3abcfb 100644 --- a/chroma/system/memory/paging.c +++ b/chroma/system/memory/paging.c @@ -48,7 +48,7 @@ * */ -extern size_t _kernel_text_start; +//extern size_t _kernel_text_start; extern size_t _kernel_rodata_start; extern size_t _kernel_data_start; @@ -138,10 +138,10 @@ void InitPaging() { SerialPrintf("[ Mem] Identity mapping higher half complete.\n"); - MMapEnt* TopEntry = (MMapEnt*)(((&bootldr) + bootldr.size) - sizeof(MMapEnt)); + MMapEnt* TopEntry = (MMapEnt*)(((size_t) (&bootldr) + bootldr.size) - sizeof(MMapEnt)); size_t LargestAddress = TopEntry->ptr + TopEntry->size; - SerialPrintf("[ Mem] About to map lower memory into the Direct Region.\n"); + SerialPrintf("[ Mem] About to map lower memory into the Direct Region. Highest address = 0x%p\n", AlignUpwards(LargestAddress, PAGE_SIZE)); for(size_t Address = 0; Address < AlignUpwards(LargestAddress, PAGE_SIZE); Address += PAGE_SIZE) { MapVirtualMemory(&KernelAddressSpace, (size_t*)(((char*)Address) + DIRECT_REGION), Address, MAP_WRITE); } @@ -151,16 +151,16 @@ void InitPaging() { //TODO: Disallow execution of rodata and data, and bootldr/environment for(void* Address = CAST(void*, KERNEL_REGION); - Address < CAST(void*, KERNEL_REGION + 0x2000); // Lower half of Kernel + Address < CAST(void*, KERNEL_REGION + (KernelEnd - KernelAddr)); // Lower half of Kernel Address = CAST(void*, CAST(char*, Address) + PAGE_SIZE)) { - MapVirtualMemory(&KernelAddressSpace, Address, (CAST(size_t, Address) - KERNEL_REGION) + KERNEL_PHYSICAL, MAP_EXEC); + MapVirtualMemory(&KernelAddressSpace, Address, (CAST(size_t, Address) - KERNEL_REGION) + KernelLocation, MAP_EXEC); } - for(void* Address = CAST(void*, KERNEL_REGION + 0x2000); + /*for(void* Address = CAST(void*, KERNEL_REGION + 0x2000); Address < CAST(void*, KERNEL_REGION + 0x12000); // Higher half of kernel Address = CAST(void*, CAST(char*, Address) + PAGE_SIZE)) { MapVirtualMemory(&KernelAddressSpace, Address, (CAST(size_t, Address) - KERNEL_REGION) + KERNEL_PHYSICAL_2, MAP_EXEC); - } + }*/ for(void* Address = CAST(void*, FB_REGION); Address < CAST(void*, 0x200000); // TODO: Turn this into a calculation with bootldr.fb_size @@ -169,6 +169,9 @@ void InitPaging() { } SerialPrintf("[ Mem] Kernel mapped into pagetables. New PML4 at 0x%p\r\n", KernelAddressSpace.PML4); + SerialPrintf("[ Mem] About to move into our own pagetables.\r\n"); + WriteControlRegister(3, (size_t) KernelAddressSpace.PML4); + SerialPrintf("[ Mem] We survived!\r\n"); //ASSERT(Allocator != NULL); }