/// <summary> /// Returns a pointer size of largest continuous block of free ram /// DOES NOT ALLOCATE ANYTHING so it can be used before Memory Management is initalised /// </summary> /// <returns>The size of the largest block in bytes</returns> public static unsafe RawMemoryMapBlock *GetLargestMemoryBlock() { if (!Multiboot2.MemoryMapExists()) { return(null); } var baseMap = (RawMemoryMapBlock *)((uint *)Multiboot2.MemoryMap + (uint)16); var currentMap = baseMap; uint totalSize = Multiboot2.MemoryMap->Size - 16; uint entrySize = Multiboot2.MemoryMap->EntrySize; RawMemoryMapBlock *BestMap = null; int counter = 0; ulong bestSize = 0; while ((uint)currentMap < ((uint)baseMap + totalSize) && counter < 64) { currentMap = (RawMemoryMapBlock *)((uint)currentMap + entrySize); if (currentMap->Type == 1) { if (currentMap->Length > bestSize) { BestMap = currentMap; bestSize = currentMap->Length; } } } return(BestMap); }
/// Get the Memory Map Information from Multiboot /// </summary> /// <returns>Returns an array of MemoryMaps containing the Multiboot Memory Map information. The array may have empty values at the end.</returns> public static unsafe MemoryMapBlock[] GetMemoryMap() { if (!Multiboot2.MemoryMapExists()) { throw new Exception("No Memory Map was returned by Multiboot"); } var rawMap = new RawMemoryMapBlock[64]; var baseMap = (RawMemoryMapBlock *)((uint *)Multiboot2.MemoryMap + (uint)16); var currentMap = baseMap; uint totalSize = Multiboot2.MemoryMap->Size - 16; uint entrySize = Multiboot2.MemoryMap->EntrySize; int counter = 0; while ((uint)currentMap < ((uint)baseMap + totalSize) && counter < 64) { rawMap[counter++] = *currentMap; currentMap = (RawMemoryMapBlock *)((uint)currentMap + entrySize); } if (counter >= 64) { throw new Exception("Memory Map returned too many segments"); } var entireMap = new MemoryMapBlock[counter]; for (int i = 0; i < counter; i++) { var rawMemoryMap = rawMap[i]; entireMap[i] = new MemoryMapBlock { Address = rawMemoryMap.Address, Length = rawMemoryMap.Length, Type = rawMemoryMap.Type }; } return(entireMap); }
// Bootstrap is a class designed only to get the essentials done. // ie the stuff needed to "pre boot". Do only the very minimal here. // IDT, PIC, and Float // Note: This is changing a bit GDT (already) and IDT are moving to a real preboot area. /// <summary> /// Init the boot strap. Invoke pre-boot methods. /// </summary> public static void Init() { // Drag this stuff in to the compiler manually until we add the always include attrib Multiboot2.Init(); INTs.Dummy(); PIC = new PIC(); CPU.UpdateIDT(true); /* TODO check using CPUID that SSE2 is supported */ CPU.InitSSE(); /* * We liked to use SSE for all floating point operation and end to mix SSE / x87 in Cosmos code * but sadly in x86 this resulte impossible as Intel not implemented some needed instruction (for example conversion * for long to double) so - in some rare cases - x87 continue to be used. I hope passing to the x32 or x64 IA will solve * definively this problem. */ CPU.InitFloat(); }
// Amount of RAM in MB's. // needs to be static, as Heap needs it before we can instantiate objects /// <summary> /// Get amount of RAM in MB's. /// </summary> public static uint GetAmountOfRAM() { return(Multiboot2.GetMemUpper() / 1024); }