diff --git a/Tests/Kernels/ProcessorTests/Kernel.cs b/Tests/Kernels/ProcessorTests/Kernel.cs index 2320625f3..74b2c79cb 100644 --- a/Tests/Kernels/ProcessorTests/Kernel.cs +++ b/Tests/Kernels/ProcessorTests/Kernel.cs @@ -22,6 +22,8 @@ namespace ProcessorTests { try { + TestMultibootMemoryMap(); + TetsGetRam(); TestVendorNameIsNotBlank(); TestCycleCount(); TestCycleRateIsNotZero(); @@ -37,6 +39,22 @@ namespace ProcessorTests } } + public void TetsGetRam() + { + Assert.IsTrue(CPU.GetAmountOfRAM() > 0, "CPU.GetAmountOfRAM() returns a positive value: " + CPU.GetAmountOfRAM()); + } + + public void TestMultibootMemoryMap() + { + var memoryMap = CPU.GetMemoryMap(); + for (int i = 0; i < memoryMap.Length; i++) + { + mDebugger.Send($"Memory Map: {memoryMap[i].Address} " + + $"Length: {memoryMap[i].Length} Type: {memoryMap[i].Type}"); + } + Assert.IsTrue(memoryMap.Length != 0, "Memory Map is not empty! Length " + memoryMap.Length); + } + public void TestMultiboot() { Assert.IsTrue(Multiboot.GetMBIAddress() != 0, $"Multiboot.GetMBIAddress works {Multiboot.GetMBIAddress()}"); diff --git a/source/Cosmos.Core/Bootstrap.cs b/source/Cosmos.Core/Bootstrap.cs index b23955ace..81c1edf36 100644 --- a/source/Cosmos.Core/Bootstrap.cs +++ b/source/Cosmos.Core/Bootstrap.cs @@ -1,4 +1,7 @@ -namespace Cosmos.Core +using Cosmos.Debug.Kernel; +using XSharp; + +namespace Cosmos.Core { /// /// Bootstrap class. Used to invoke pre-boot methods. @@ -22,7 +25,7 @@ /// /// Multiboot header pointer. /// - public static Multiboot.Header* header; + public static Multiboot.Header* MultibootHeader; /// /// VBE mode info pointer. @@ -59,13 +62,10 @@ */ CPU.InitFloat(); - header = (Multiboot.Header*)Multiboot.GetMBIAddress(); + MultibootHeader = (Multiboot.Header*)Multiboot.GetMBIAddress(); - modeinfo = (Core.VBE.ModeInfo*)header->vbeModeInfo; - controllerinfo = (Core.VBE.ControllerInfo*)header->vbeControlInfo; - - // Managed_Memory_System.ManagedMemory.Initialize(); - // Managed_Memory_System.ManagedMemory.SetUpMemoryArea(); + modeinfo = (Core.VBE.ModeInfo*)MultibootHeader->vbeModeInfo; + controllerinfo = (Core.VBE.ControllerInfo*)MultibootHeader->vbeControlInfo; } } } diff --git a/source/Cosmos.Core/CPU.cs b/source/Cosmos.Core/CPU.cs index 26defb248..b2374d334 100644 --- a/source/Cosmos.Core/CPU.cs +++ b/source/Cosmos.Core/CPU.cs @@ -1,5 +1,7 @@ +#define COSMOSDEBUG using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using IL2CPU.API.Attribs; namespace Cosmos.Core @@ -110,8 +112,6 @@ namespace Cosmos.Core return xResult; } - - /// /// Get CPU vendor name. /// @@ -300,7 +300,8 @@ namespace Cosmos.Core if (!(rs == "")) { return rs; - } else + } + else { throw new NotSupportedException(); } @@ -308,8 +309,6 @@ namespace Cosmos.Core throw new NotSupportedException(); } - - /// /// Check if can read CPU ID. Plugged. /// @@ -341,5 +340,107 @@ namespace Cosmos.Core /// ulong value. /// Thrown on fatal error, contact support. internal static ulong ReadFromModelSpecificRegister() => throw new NotImplementedException(); + + /// + /// Checks if Multiboot returned a memory map + /// + /// + public static unsafe bool MemoryMapExists() + { + return (Bootstrap.MultibootHeader->Flags & 1 << 6) == 64; + } + + /// + /// Get the Memory Map Information from Multiboot + /// + /// Returns an array of MemoryMaps containing the Multiboot Memory Map information. The array may have empty values at the end. + public static unsafe MemoryMap[] GetMemoryMap() + { + if (!MemoryMapExists()) + { + throw new Exception("No Memory Map was returned by Multiboot"); + } + var rawMap = new RawMemoryMap[64]; + var currentMap = (RawMemoryMap*)Bootstrap.MultibootHeader->memMapAddress; + int counter = 0; + while ((uint)currentMap < (Bootstrap.MultibootHeader->memMapAddress + Bootstrap.MultibootHeader->memMapLength) && counter < 64) + { + rawMap[counter++] = *currentMap; + currentMap = (RawMemoryMap*)((uint*)currentMap + ((currentMap->Size + 4 )>> 2)); //The size is in bits, not bytes + if (currentMap->Size == 0) + { + break; + } + } + + if (counter >= 64) + { + throw new Exception("Memory Map returned too many segments"); + } + + var entireMap = new MemoryMap[counter]; + for (int i = 0; i < counter; i++) + { + var rawMemoryMap = rawMap[i]; + entireMap[i] = new MemoryMap + { + Address = (ulong)rawMemoryMap.HighBaseAddr << 32 | rawMemoryMap.LowBaseAddr, + Length = (ulong)rawMemoryMap.HighLength << 32 | rawMemoryMap.LowLength, + Type = rawMemoryMap.Type + }; + } + return entireMap; + } + } + + public class MemoryMap + { + /// + /// Base Address of the memory region + /// + public ulong Address; + /// + /// Length in bytes of the region + /// + public ulong Length; + /// + /// Type of RAM in region. 1 is available. 3 is for ACPI. All other is unavailable + /// + public uint Type; + } + + [StructLayout(LayoutKind.Explicit, Size = 24)] + public struct RawMemoryMap + { + /// + /// Size of this entry + /// + [FieldOffset(0)] + public uint Size; + /// + /// Low 32 bits of the base address + /// + [FieldOffset(4)] + public uint LowBaseAddr; + /// + /// High 32 bits of the base address + /// + [FieldOffset(8)] + public uint HighBaseAddr; + /// + /// Low 32 bits of the length of memory block in bytes + /// + [FieldOffset(12)] + public uint LowLength; + /// + /// High 32 bits of the length of memory block in bytes + /// + [FieldOffset(16)] + public uint HighLength; + /// + /// Type of memory area, 1 if usable RAM, everything else unusable. + /// + [FieldOffset(20)] + public uint Type; } } diff --git a/source/Cosmos.Core/MemoryOperations.cs b/source/Cosmos.Core/MemoryOperations.cs index 81c8be230..c66ce56ef 100644 --- a/source/Cosmos.Core/MemoryOperations.cs +++ b/source/Cosmos.Core/MemoryOperations.cs @@ -8,6 +8,7 @@ namespace Cosmos.Core /// public unsafe class MemoryOperations { + #region Fill /// /// Fill memory block. Plugged. /// @@ -183,6 +184,23 @@ namespace Cosmos.Core } } + /// + /// Fill source to destination. + /// + /// Destination. + /// Source. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void Fill(sbyte[] dest, sbyte[] src) + { + fixed (sbyte* destPtr = dest) + fixed (sbyte* srcPtr = src) + { + Copy(destPtr, srcPtr, dest.Length); + } + } + #endregion Fill + + #region Copy /// /// Copy source to destination. /// plugged. @@ -329,19 +347,6 @@ namespace Cosmos.Core } } - /// - /// Fill source to destination. - /// - /// Destination. - /// Source. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void Fill(sbyte[] dest, sbyte[] src) - { - fixed (sbyte* destPtr = dest) - fixed (sbyte* srcPtr = src) - { - Copy(destPtr, srcPtr, dest.Length); - } - } + #endregion Copy } } diff --git a/source/Cosmos.Core/Multiboot.cs b/source/Cosmos.Core/Multiboot.cs index 341de394e..99e41484d 100644 --- a/source/Cosmos.Core/Multiboot.cs +++ b/source/Cosmos.Core/Multiboot.cs @@ -139,7 +139,7 @@ namespace Cosmos.Core /// True if is available, false if not public static bool IsAvailable() { - if ((Bootstrap.header->Flags & VBEINFO_PRESENT) == 0) + if ((Bootstrap.MultibootHeader->Flags & VBEINFO_PRESENT) == 0) { return false; } diff --git a/source/Cosmos.Core_Asm/MultibootImpl.cs b/source/Cosmos.Core_Asm/MultibootImpl.cs index c2203981f..bd7153769 100644 --- a/source/Cosmos.Core_Asm/MultibootImpl.cs +++ b/source/Cosmos.Core_Asm/MultibootImpl.cs @@ -19,7 +19,7 @@ namespace Cosmos.Core_Asm { public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { - XS.Push("MultibootSignature"); + XS.Push("MultiBootInfo_Structure", isIndirect: true); } } }