Skip to content

Commit

Permalink
WIP - BareMetal (#1079)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Jul 10, 2023
1 parent c902c55 commit affa1c3
Show file tree
Hide file tree
Showing 26 changed files with 583 additions and 161 deletions.
5 changes: 5 additions & 0 deletions Source/Mosa.DeviceDriver/ISA/ISABus.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using System.Collections.Generic;
using System.Diagnostics;
using Mosa.DeviceSystem;
using Mosa.Runtime;

Expand Down Expand Up @@ -29,13 +30,17 @@ public override void Start()

protected void StartISADevices()
{
Debug.WriteLine("ISABus:StartISADevices()");

// Start ISA Drivers
var drivers = DeviceService.GetDeviceDrivers(DeviceBusType.ISA);

foreach (var driver in drivers)
{
if (driver is ISADeviceDriverRegistryEntry)
{
Debug.WriteLine("ISA: ", driver.Name);

StartISADevice(driver as ISADeviceDriverRegistryEntry);
}
}
Expand Down
16 changes: 8 additions & 8 deletions Source/Mosa.DeviceDriver/Setup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ public static List<DeviceDriverRegistryEntry> GetDeviceDriverRegistryEntries()
{
return new List<DeviceDriverRegistryEntry>
{
new ISADeviceDriverRegistryEntry
{
Name = "ACPI",
Platforms = PlatformArchitecture.X86,
AutoLoad = true,
Factory = () => new ISA.ACPI()
},

new ISADeviceDriverRegistryEntry
{
Name = "StandardKeyboard",
Expand Down Expand Up @@ -246,6 +238,14 @@ public static List<DeviceDriverRegistryEntry> GetDeviceDriverRegistryEntries()
PCIFields = PCIField.VendorID | PCIField.DeviceID,
Factory = () => new PCI.VMware.VMwareSVGA2()
},

new ISADeviceDriverRegistryEntry
{
Name = "ACPI",
Platforms = PlatformArchitecture.X86,
AutoLoad = true,
Factory = () => new ISA.ACPI()
},
};
}
}
8 changes: 8 additions & 0 deletions Source/Mosa.DeviceDriver/X86System.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using System.Diagnostics;
using Mosa.DeviceDriver.ISA;
using Mosa.DeviceSystem;

Expand All @@ -22,15 +23,22 @@ public override void Probe()

public override void Start()
{
Debug.WriteLine("X86System:Start()");
CreateISABusDevices();

Device.Status = DeviceStatus.Online;

Debug.WriteLine("X86System:Start() [Exit]");
}

public override bool OnInterrupt() => true;

protected void CreateISABusDevices()
{
Debug.WriteLine("X86System:CreateISABusDevices()");

DeviceService.Initialize(new ISABus(), Device, true, null, null, null);

Debug.WriteLine("X86System:CreateISABusDevices() [Exit]");
}
}
21 changes: 19 additions & 2 deletions Source/Mosa.DeviceSystem/Service/DeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ public Device Initialize(DeviceDriverRegistryEntry deviceDriverRegistryEntry, De

public Device Initialize(BaseDeviceDriver deviceDriver, Device parent, bool autoStart = true, BaseDeviceConfiguration configuration = null, HardwareResources resources = null, DeviceDriverRegistryEntry deviceDriverRegistryEntry = null)
{
HAL.DebugWriteLine("DeviceService:Initialize()");

if (deviceDriverRegistryEntry != null)
{
HAL.DebugWrite($" > Driver: ");
HAL.DebugWriteLine(deviceDriverRegistryEntry.Name);
}

var device = new Device
{
DeviceDriver = deviceDriver,
Expand All @@ -120,6 +128,8 @@ public Device Initialize(BaseDeviceDriver deviceDriver, Device parent, bool auto
StartDevice(device);
}

HAL.DebugWriteLine("DeviceService:Initialize() [Exit]");

return device;
}

Expand All @@ -129,8 +139,13 @@ public Device Initialize(BaseDeviceDriver deviceDriver, Device parent, bool auto
/// <param name="device">The device.</param>
private void StartDevice(Device device)
{
//HAL.DebugWriteLine($"DeviceService:StartDevice():Enter = " + (device.Name ?? string.Empty));
//HAL.Pause();
HAL.DebugWriteLine("DeviceService:StartDevice()");

if (device.Name != null)
{
HAL.DebugWrite($" > Device: ");
HAL.DebugWriteLine(device.Name);
}

lock (_lock)
{
Expand All @@ -149,6 +164,8 @@ private void StartDevice(Device device)
if (device.Status == DeviceStatus.Initializing)
{
//HAL.DebugWriteLine("DeviceService:StartDevice():Initializing = " + (device.Name ?? string.Empty));
//Debug.WriteLine(" > Initializing: ", device.Name);

device.DeviceDriver.Initialize();
if (device.Status == DeviceStatus.Initializing)
{
Expand Down
9 changes: 5 additions & 4 deletions Source/Mosa.Kernel.BareMetal.x86/IDT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
using System.Runtime.InteropServices;
using Mosa.Runtime;
using Mosa.Runtime.x86;
using Mosa.Kernel.BareMetal;
using Mosa.Kernel.BareMetal.BootMemory;
using Mosa.Runtime.Plug;

namespace Mosa.Kernel.BareMetal.x86;

Expand Down Expand Up @@ -48,7 +48,7 @@ public static void Setup()
IDTTable = BootPageAllocator.AllocatePage();
Page.ClearPage(IDTTable);

Debug.WriteLineHex(" > Address: ", IDTTable.ToUInt64());
Debug.WriteLine(" > Address: ", new Hex(IDTTable));

IDTTable.Store16(IDTEntryOffset.TotalSize * 256 - 1);
IDTTable.Store32(2, IDTTable.ToUInt32() + 6);
Expand Down Expand Up @@ -2169,9 +2169,10 @@ private static void IRQ255()
/// Interrupts the handler.
/// </summary>
/// <param name="stackStatePointer">The stack state pointer.</param>
private static unsafe void ProcessInterrupt(uint stackStatePointer)
[Plug("Mosa.Runtime.Interrupt::Process")]
private static unsafe void ProcessInterrupt(Pointer stackStatePointer)
{
var stack = new IDTStackEntry(new Pointer(stackStatePointer));
var stack = new IDTStackEntry(stackStatePointer);

//Debug.WriteLine(" > IDQ: ", stack.Interrupt);

Expand Down
93 changes: 59 additions & 34 deletions Source/Mosa.Kernel.BareMetal.x86/PlatformPlug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,56 +34,81 @@ public static void EntryPoint()
[Plug("Mosa.Kernel.BareMetal.Platform::GetInitialGCMemoryPool")]
public static AddressRange GetInitialGCMemoryPool() => new AddressRange(InitialGCMemoryPoolAddress, InitialGCMemoryPoolSize);

[Plug("Mosa.Kernel.BareMetal.Platform::PageTableSetup")]
public static void PageTableSetup() => PageTable.Setup();
[Plug("Mosa.Kernel.BareMetal.Platform::ConsoleWrite")]
public static void ConsoleWrite(byte c) => VGAConsole.Write(c);

[Plug("Mosa.Kernel.BareMetal.Platform::PageTableInitialize")]
public static void PageTableInitialize() => PageTable.Initialize();
[Plug("Mosa.Kernel.BareMetal.Platform::DebugWrite")]
public static void DebugWrite(byte c) => SerialDebug.Write(c);

[Plug("Mosa.Kernel.BareMetal.Platform::PageTableEnable")]
public static void PageTableEnable() => PageTable.Enable();
public static class PageTablePlug
{
[Plug("Mosa.Kernel.BareMetal.Platform+PageTable::Setup")]
public static void Setup() => PageTable.Setup();

[Plug("Mosa.Kernel.BareMetal.Platform::MapVirtualAddressToPhysical")]
public static void MapVirtualAddressToPhysical(Pointer virtualAddress, Pointer physicalAddress, bool present = true) => PageTable.MapVirtualAddressToPhysical(virtualAddress, physicalAddress, present);
[Plug("Mosa.Kernel.BareMetal.Platform+PageTable::Initialize")]
public static void Initialize() => PageTable.Initialize();

[Plug("Mosa.Kernel.BareMetal.Platform::GetPhysicalAddressFromVirtual")]
public static Pointer GetPhysicalAddressFromVirtual(Pointer virtualAddress) => PageTable.GetPhysicalAddressFromVirtual(virtualAddress);
[Plug("Mosa.Kernel.BareMetal.Platform+PageTable::Enable")]
public static void Enable() => PageTable.Enable();

[Plug("Mosa.Kernel.BareMetal.Platform::ConsoleWrite")]
public static void ConsoleWrite(byte c) => VGAConsole.Write(c);
[Plug("Mosa.Kernel.BareMetal.Platform+PageTable::MapVirtualAddressToPhysical")]
public static void MapVirtualAddressToPhysical(Pointer virtualAddress, Pointer physicalAddress, bool present = true) => PageTable.MapVirtualAddressToPhysical(virtualAddress, physicalAddress, present);

[Plug("Mosa.Kernel.BareMetal.Platform::DebugWrite")]
public static void DebugWrite(byte c) => SerialDebug.Write(c);
[Plug("Mosa.Kernel.BareMetal.Platform+PageTable::GetPhysicalAddressFromVirtual")]
public static Pointer GetPhysicalAddressFromVirtual(Pointer virtualAddress) => PageTable.GetPhysicalAddressFromVirtual(virtualAddress);
}

[Plug("Mosa.Kernel.BareMetal.Platform::InterruptHandlerSetup")]
public static void InterruptHandlerSetup() => IDT.Setup();
public static class InterruptPlug
{
[Plug("Mosa.Kernel.BareMetal.Platform+Interrupt::Setup")]
public static void HandlerSetup() => IDT.Setup();

[Plug("Mosa.Kernel.BareMetal.Platform::InterruptHandlerSet")]
public static void InterruptHandlerSet(InterruptHandler handler) => IDT.SetInterruptHandler(handler);
[Plug("Mosa.Kernel.BareMetal.Platform+Interrupt::SetHandler")]
public static void SetHandler(InterruptHandler handler) => IDT.SetInterruptHandler(handler);

#region IO Port Operations
[Plug("Mosa.Kernel.BareMetal.Platform+Interrupt::Enable")]
public static void Enable() => Native.Sti();

[Plug("Mosa.Kernel.BareMetal.Platform::In8")]
public static byte In8(ushort address) => Native.In8(address);
[Plug("Mosa.Kernel.BareMetal.Platform+Interrupt::Disable")]
public static void Disable() => Native.Cli();
}

[Plug("Mosa.Kernel.BareMetal.Platform::In16")]
public static ushort In16(ushort address) => Native.In16(address);
public static class IOPlug
{
[Plug("Mosa.Kernel.BareMetal.Platform+IO::In8")]
public static byte In8(ushort address) => Native.In8(address);

[Plug("Mosa.Kernel.BareMetal.Platform::In32")]
public static uint In32(ushort address) => Native.In32(address);
[Plug("Mosa.Kernel.BareMetal.Platform+IO::In16")]
public static ushort In16(ushort address) => Native.In16(address);

[Plug("Mosa.Kernel.BareMetal.Platform::Out8")]
public static void Out8(ushort address, byte data) => Native.Out8(address, data);
[Plug("Mosa.Kernel.BareMetal.Platform+IO::In32")]
public static uint In32(ushort address) => Native.In32(address);

[Plug("Mosa.Kernel.BareMetal.Platform::Out16")]
public static void Out16(ushort address, ushort data) => Native.Out16(address, data);
[Plug("Mosa.Kernel.BareMetal.Platform+IO::Out8")]
public static void Out8(ushort address, byte data) => Native.Out8(address, data);

[Plug("Mosa.Kernel.BareMetal.Platform::Out32")]
public static void Out32(ushort address, uint data) => Native.Out32(address, data);
[Plug("Mosa.Kernel.BareMetal.Platform+IO::Out16")]
public static void Out16(ushort address, ushort data) => Native.Out16(address, data);

#endregion IO Port Operations
[Plug("Mosa.Kernel.BareMetal.Platform+IO::Out32")]
public static void Out32(ushort address, uint data) => Native.Out32(address, data);
}

public static void EnableInterrupts() => Native.Sti();
public static class Scheduler
{
[Plug("Mosa.Kernel.BareMetal.Platform+Scheduler::ThreadStart")]
public static void ThreadStart() => ThreadStart();

public static void DisableInterrupts() => Native.Cli();
[Plug("Mosa.Kernel.BareMetal.Platform+Scheduler::ThreadYield")]
public static void ThreadYield() => Scheduler.ThreadYield();

[Plug("Mosa.Kernel.BareMetal.Platform+Scheduler::SignalTermination")]
public static void SignalTermination() => Scheduler.SignalTermination();

[Plug("Mosa.Kernel.BareMetal.Platform+Scheduler::SwitchToThread")]
public static void SwitchToThread(Thread thread) => Scheduler.SwitchToThread(thread);

[Plug("Mosa.Kernel.BareMetal.Platform+Scheduler::SetupThreadStack")]
public static Pointer SetupThreadStack(Pointer stackTop, Pointer methodAddress, Pointer termAddress) => Scheduler.SetupThreadStack(stackTop, methodAddress, termAddress);
}
}
62 changes: 62 additions & 0 deletions Source/Mosa.Kernel.BareMetal.x86/Scheduler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using System.Runtime.CompilerServices;
using Mosa.Runtime;
using Mosa.Runtime.x86;

namespace Mosa.Kernel.BareMetal.x86;

public static class Scheduler
{
public const int ClockIRQ = 0x20;
public const int ThreadTerminationSignalIRQ = 254;

public static void Start()
{
Native.Int(ClockIRQ);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Yield()
{
Native.Hlt();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void SignalTermination()
{
Native.Int(ThreadTerminationSignalIRQ);
}

private static Pointer SetupThreadStack(Pointer stackTop, Pointer methodAddress, Pointer termAddress)
{
// Setup stack state
stackTop.Store32(-4, 0); // Zero Sentinel
stackTop.Store32(-8, termAddress.ToInt32()); // Address of method that will raise a interrupt signal to terminate thread

stackTop.Store32(-12, 0x00000202);// EFLAG
stackTop.Store32(-16, 0x08); // CS
stackTop.Store32(-20, methodAddress.ToInt32()); // EIP

stackTop.Store32(-24, 0); // ErrorCode - not used
stackTop.Store32(-28, 0); // Interrupt Number - not used

stackTop.Store32(-32, 0); // EAX
stackTop.Store32(-36, 0); // ECX
stackTop.Store32(-40, 0); // EDX
stackTop.Store32(-44, 0); // EBX
stackTop.Store32(-48, 0); // ESP (original) - not used
stackTop.Store32(-52, (stackTop - 8).ToInt32()); // EBP
stackTop.Store32(-56, 0); // ESI
stackTop.Store32(-60, 0); // EDI

return stackTop - 60;
}

private static void SwitchToThread(Thread thread)
{
PIC.SendEndOfInterrupt(ClockIRQ);

Native.InterruptReturn((uint)thread.StackStatePointer.ToInt32());
}
}
15 changes: 10 additions & 5 deletions Source/Mosa.Kernel.BareMetal/Boot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,18 @@ public static void EntryPoint()
DeviceSystem.Setup.Initialize(hardware, deviceService.ProcessInterrupt);
Console.WriteLine(ConsoleColor.BrightBlack, " [Completed]");

//Console.Write(ConsoleColor.BrightGreen, "> Registering device drivers...");
//deviceService.RegisterDeviceDriver(DeviceDriver.Setup.GetDeviceDriverRegistryEntries());
//Console.WriteLine(ConsoleColor.BrightBlack, " [Completed]");
Console.Write(ConsoleColor.BrightGreen, "> Registering device drivers...");
deviceService.RegisterDeviceDriver(DeviceDriver.Setup.GetDeviceDriverRegistryEntries());
Console.WriteLine(ConsoleColor.BrightBlack, " [Completed]");

Debug.WriteLine("[X86System]");

//Console.Write(ConsoleColor.BrightGreen, "> X86System...");
Console.Write(ConsoleColor.BrightGreen, "> X86System...");
//deviceService.Initialize(new X86System(), null);
//Console.WriteLine(ConsoleColor.BrightBlack, " [Completed]");
Console.WriteLine(ConsoleColor.BrightBlack, " [Completed]");

//Debug.WriteLine("Done");
//Debug.Kill();
}

[Plug("Mosa.Runtime.GC::AllocateMemory")]
Expand Down
6 changes: 3 additions & 3 deletions Source/Mosa.Kernel.BareMetal/BootMemory/BootMemoryMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private static void ImportMultibootV1MemoryMap()

AvailableMemory = new Pointer(Multiboot.MultibootV1.MemoryUpper * 1024);

Debug.WriteLineHex(" > Available Memory: ", AvailableMemory.ToInt64());
Debug.WriteLine(" > Available Memory: ", AvailableMemory.ToInt64());

var memoryMapEnd = Multiboot.MultibootV1.MemoryMapStart + Multiboot.MultibootV1.MemoryMapLength;

Expand Down Expand Up @@ -118,9 +118,9 @@ public static void Dump()
var entry = GetBootMemoryMapEntry(slot);

Debug.Write("Start: 0x");
Debug.WriteValueAsHex(entry.StartAddress.ToUInt64(), 8);
Debug.WriteValue(new Hex8(entry.StartAddress));
Debug.Write(" Size: 0x");
Debug.WriteValueAsHex(entry.Size, 8);
Debug.WriteValue(new Hex8(entry.Size));
Debug.Write(" Type: ");
Debug.WriteValue((byte)entry.Type);
Debug.WriteLine();
Expand Down

0 comments on commit affa1c3

Please sign in to comment.