private static void SetupMemoryMap() { var mbMapCount = Multiboot.MemoryMapCount; BootInfo->MemoryMapArray = (BootInfoMemory *)MallocBootInfoData((USize)(sizeof(MultiBootMemoryMap) * MemoryMapReserve)); for (uint i = 0; i < mbMapCount; i++) { BootInfo->MemoryMapArray[i].Start = Multiboot.GetMemoryMapBase(i); BootInfo->MemoryMapArray[i].Size = Multiboot.GetMemoryMapLength(i); var memType = BootInfoMemoryType.Reserved; var type = (BIOSMemoryMapType)Multiboot.GetMemoryMapType(i); var addressSpaceKind = AddressSpaceKind.Physical; var preMap = false; switch (type) { case BIOSMemoryMapType.Usable: memType = BootInfoMemoryType.SystemUsable; break; case BIOSMemoryMapType.Reserved: memType = BootInfoMemoryType.Reserved; break; case BIOSMemoryMapType.ACPI_Relaimable: memType = BootInfoMemoryType.ACPI_Relaimable; break; case BIOSMemoryMapType.ACPI_NVS_Memory: memType = BootInfoMemoryType.ACPI_NVS_Memory; break; case BIOSMemoryMapType.BadMemory: memType = BootInfoMemoryType.BadMemory; break; default: memType = BootInfoMemoryType.Unknown; break; } BootInfo->MemoryMapArray[i].Type = memType; BootInfo->MemoryMapArray[i].AddressSpaceKind = addressSpaceKind; BootInfo->MemoryMapArray[i].PreMap = preMap; } // It's possible, that the BIOS-Area (@640K) is not correctly setup by Multiboot. So add it here manually to be sure var idx = mbMapCount + 0; BootInfo->MemoryMapArray[idx].Start = 640 * 1024; BootInfo->MemoryMapArray[idx].Size = (1024 - 640) * 1024; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.CustomReserved; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; //TODO: Physical BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelElfSectionPhys; BootInfo->MemoryMapArray[idx].Size = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelElf; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Physical; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelBootInfo; BootInfo->MemoryMapArray[idx].Size = 0x1000; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeader; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = BootInfo->HeapStart; BootInfo->MemoryMapArray[idx].Size = 0x1000; //TODO: Recalculate after Setup all Infos BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeap; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; uint stackSize = 0x100000; // 1MB BootInfo->MemoryMapArray[idx].Start = Address.InitialStack - stackSize; BootInfo->MemoryMapArray[idx].Size = stackSize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialStack; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.GCInitialMemory; BootInfo->MemoryMapArray[idx].Size = Address.GCInitialMemorySize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialGCMemory; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelBssSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelTextSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelROdataSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelDataSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; // Avoiding the use of the first megabyte of RAM idx++; BootInfo->MemoryMapArray[idx].Start = 0x0; BootInfo->MemoryMapArray[idx].Size = Address.ReserveMemory; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelReserved; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = false; BootInfo->MemoryMapLength = idx + 1; }
public static void Main() { //Screen.BackgroundColor = ScreenColor.Green; //Screen.Color = ScreenColor.Red; //Screen.Clear(); //Screen.Goto(0, 0); //Screen.Write('A'); //Serial.SetupPort(Serial.COM1); //Serial.Write(Serial.COM1, "Hello"); BootMemory.Setup(); // Setup Kernel Log var kmsgHandler = new KernelMessageWriter(); KernelMessage.SetHandler(kmsgHandler); KernelMessage.WriteLine("<LOADER:CONSOLE:BEGIN>"); Assert.Setup(AssertError); PerformanceCounter.Setup(); // Parse Boot Informations Multiboot.Setup(); // Parse Kernel ELF section SetupOriginalKernelElf(); // Print all section of Kernel ELF (for information only) DumpElfInfo(); // Copy Section to a final destination SetupKernelSection(); // Collection informations we need to pass to the kernel BootInfo_.Setup(); // Setup Global Descriptor Table var map = BootMemory.AllocateMemoryMap(0x1000, BootInfoMemoryType.GDT, AddressSpaceKind.Both); BootInfo_.AddMap(map); GDT.Setup(map.Start); // Now we enable Paging. It's important that we do not cause a Page Fault Exception, // Because IDT is not setup yet, that could handle this kind of exception. PageTable.ConfigureType(BootInfo_.BootInfo->PageTableType); map = BootMemory.AllocateMemoryMap(PageTable.KernelTable.InitalMemoryAllocationSize, BootInfoMemoryType.PageTable, AddressSpaceKind.Both); BootInfo_.AddMap(map); PageTable.KernelTable.Setup(map.Start); MapMemory(); PageTable.KernelTable.EnablePaging(); // Because Kernel is compiled in virtual address space, we need to remap the pages MapKernelImage(); // Get Entry Point of Kernel uint kernelEntry = GetKernelStartAddr(); if (kernelEntry == 0) { KernelMessage.WriteLine("No kernel entry point found {0:X8}"); KernelMessage.WriteLine("Is the name of entry point correct?"); KernelMessage.WriteLine("Are symbols emitted?"); KernelMessage.WriteLine("System halt!"); while (true) { Native.Nop(); } } KernelMessage.WriteLine("Call Kernel Start at {0:X8}", kernelEntry); // Start Kernel. CallAddress(kernelEntry); // If we hit this code location, the Kernel Main method returned. // This would be a general fault. Normally, this code section will overwritten // by the kernel, so normally, it can never reach this code position. KernelMessage.WriteLine("Unexpected return from Kernel Start"); Debug.Break(); }