Fixes for memory. Lots of work left.

Mainly, we need to be able to locate the kernel executable physically in memory.
This commit is contained in:
Curle 2020-11-28 16:43:43 +00:00
parent 4468cee2e7
commit 2b1d6cca5f
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
5 changed files with 82 additions and 10 deletions

View File

@ -14,7 +14,8 @@ extern "C" {
#define BOOT_MAGIC "BOOT" #define BOOT_MAGIC "BOOT"
/* minimum protocol level: /* 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 #define PROTOCOL_MINIMAL 0
/* static protocol level: /* static protocol level:
* kernel name parsed from environment, static kernel memory addresses */ * kernel name parsed from environment, static kernel memory addresses */
@ -27,6 +28,7 @@ extern "C" {
/* loader types, just informational */ /* loader types, just informational */
#define LOADER_BIOS (0<<2) #define LOADER_BIOS (0<<2)
/* unless we get to a weird stage, these should never be used. */
#define LOADER_UEFI (1<<2) #define LOADER_UEFI (1<<2)
#define LOADER_RPI (2<<2) #define LOADER_RPI (2<<2)
@ -106,6 +108,31 @@ typedef struct {
} __attribute__((packed)) bootinfo; } __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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -28,6 +28,7 @@ extern bootinfo bootldr;
extern unsigned char* environment; extern unsigned char* environment;
extern uint8_t fb; extern uint8_t fb;
extern volatile unsigned char _binary_font_psf_start; extern volatile unsigned char _binary_font_psf_start;
extern volatile size_t* _kernel_text_start;
extern address_space_t KernelAddressSpace; extern address_space_t KernelAddressSpace;

View File

@ -8,6 +8,8 @@
*** Chroma *** *** Chroma ***
***********************/ ***********************/
size_t KernelLocation;
/************************************************ /************************************************
* C O N S T A N T S A N D M A C R O S * 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_RESERVED 0x8
#define ERR_INST 0x10 #define ERR_INST 0x10
#define ELF64MAGIC 0x7F454c46
/* /*
* The way we boot, using BOOTBOOT, and the static hard drive images, means * 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_REGION 0xFFFFFFFFFC000000ull // Cannot move!
#define FB_PHYSICAL 0x00000000E0000000ull // Physical location of the Framebuffer #define FB_PHYSICAL 0x00000000E0000000ull // Physical location of the Framebuffer
#define KERNEL_REGION 0xFFFFFFFFFFE00000ull // -2MiB, from bootloader #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 #define USER_REGION 0x00007FFFFFFFFFFFull // Not needed yet, but we're higher half so we might as well be thorough

View File

@ -20,9 +20,48 @@ address_space_t KernelAddressSpace;
int Main(void) { int Main(void) {
KernelAddressSpace = (address_space_t) {0}; KernelAddressSpace = (address_space_t) {0};
KernelLocation = 0x112600;
SerialPrintf("\r\n[ boot] Booting Chroma..\r\n"); 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] 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)); SerialPrintf("[ boot] The bootloader has put the paging tables at 0x%p.\r\n", ReadControlRegister(3));

View File

@ -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_rodata_start;
extern size_t _kernel_data_start; extern size_t _kernel_data_start;
@ -138,10 +138,10 @@ void InitPaging() {
SerialPrintf("[ Mem] Identity mapping higher half complete.\n"); 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; 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) { for(size_t Address = 0; Address < AlignUpwards(LargestAddress, PAGE_SIZE); Address += PAGE_SIZE) {
MapVirtualMemory(&KernelAddressSpace, (size_t*)(((char*)Address) + DIRECT_REGION), Address, MAP_WRITE); 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 //TODO: Disallow execution of rodata and data, and bootldr/environment
for(void* Address = CAST(void*, KERNEL_REGION); 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)) { 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*, KERNEL_REGION + 0x12000); // Higher half of kernel
Address = CAST(void*, CAST(char*, Address) + PAGE_SIZE)) { Address = CAST(void*, CAST(char*, Address) + PAGE_SIZE)) {
MapVirtualMemory(&KernelAddressSpace, Address, (CAST(size_t, Address) - KERNEL_REGION) + KERNEL_PHYSICAL_2, MAP_EXEC); MapVirtualMemory(&KernelAddressSpace, Address, (CAST(size_t, Address) - KERNEL_REGION) + KERNEL_PHYSICAL_2, MAP_EXEC);
} }*/
for(void* Address = CAST(void*, FB_REGION); for(void* Address = CAST(void*, FB_REGION);
Address < CAST(void*, 0x200000); // TODO: Turn this into a calculation with bootldr.fb_size 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] 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); //ASSERT(Allocator != NULL);
} }