Added CPU.GetMemoryMap

Fixed GetMBIAddress Plug
Cleaned up code
This commit is contained in:
Quajak 2020-10-19 00:35:42 +02:00
parent 25639bc279
commit 8996b1f8a3
6 changed files with 153 additions and 29 deletions

View file

@ -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()}");

View file

@ -1,4 +1,7 @@
namespace Cosmos.Core
using Cosmos.Debug.Kernel;
using XSharp;
namespace Cosmos.Core
{
/// <summary>
/// Bootstrap class. Used to invoke pre-boot methods.
@ -22,7 +25,7 @@
/// <summary>
/// Multiboot header pointer.
/// </summary>
public static Multiboot.Header* header;
public static Multiboot.Header* MultibootHeader;
/// <summary>
/// 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;
}
}
}

View file

@ -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;
}
/// <summary>
/// Get CPU vendor name.
/// </summary>
@ -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();
}
/// <summary>
/// Check if can read CPU ID. Plugged.
/// </summary>
@ -341,5 +340,107 @@ namespace Cosmos.Core
/// <returns>ulong value.</returns>
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
internal static ulong ReadFromModelSpecificRegister() => throw new NotImplementedException();
/// <summary>
/// Checks if Multiboot returned a memory map
/// </summary>
/// <returns></returns>
public static unsafe bool MemoryMapExists()
{
return (Bootstrap.MultibootHeader->Flags & 1 << 6) == 64;
}
/// <summary>
/// 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 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
{
/// <summary>
/// Base Address of the memory region
/// </summary>
public ulong Address;
/// <summary>
/// Length in bytes of the region
/// </summary>
public ulong Length;
/// <summary>
/// Type of RAM in region. 1 is available. 3 is for ACPI. All other is unavailable
/// </summary>
public uint Type;
}
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct RawMemoryMap
{
/// <summary>
/// Size of this entry
/// </summary>
[FieldOffset(0)]
public uint Size;
/// <summary>
/// Low 32 bits of the base address
/// </summary>
[FieldOffset(4)]
public uint LowBaseAddr;
/// <summary>
/// High 32 bits of the base address
/// </summary>
[FieldOffset(8)]
public uint HighBaseAddr;
/// <summary>
/// Low 32 bits of the length of memory block in bytes
/// </summary>
[FieldOffset(12)]
public uint LowLength;
/// <summary>
/// High 32 bits of the length of memory block in bytes
/// </summary>
[FieldOffset(16)]
public uint HighLength;
/// <summary>
/// Type of memory area, 1 if usable RAM, everything else unusable.
/// </summary>
[FieldOffset(20)]
public uint Type;
}
}

View file

@ -8,6 +8,7 @@ namespace Cosmos.Core
/// </summary>
public unsafe class MemoryOperations
{
#region Fill
/// <summary>
/// Fill memory block. Plugged.
/// </summary>
@ -183,6 +184,23 @@ namespace Cosmos.Core
}
}
/// <summary>
/// Fill source to destination.
/// </summary>
/// <param name="dest">Destination.</param>
/// <param name="src">Source.</param>
[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
/// <summary>
/// Copy source to destination.
/// plugged.
@ -329,19 +347,6 @@ namespace Cosmos.Core
}
}
/// <summary>
/// Fill source to destination.
/// </summary>
/// <param name="dest">Destination.</param>
/// <param name="src">Source.</param>
[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
}
}

View file

@ -139,7 +139,7 @@ namespace Cosmos.Core
/// <returns>True if is available, false if not</returns>
public static bool IsAvailable()
{
if ((Bootstrap.header->Flags & VBEINFO_PRESENT) == 0)
if ((Bootstrap.MultibootHeader->Flags & VBEINFO_PRESENT) == 0)
{
return false;
}

View file

@ -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);
}
}
}