diff --git a/source/Cosmos.Core/BaseIOGroups.cs b/source/Cosmos.Core/BaseIOGroups.cs index 23b989644..d4d4ecd93 100644 --- a/source/Cosmos.Core/BaseIOGroups.cs +++ b/source/Cosmos.Core/BaseIOGroups.cs @@ -43,6 +43,6 @@ namespace Cosmos.Core { /// /// VBE. /// - public readonly IOGroup.VBE VBE = new IOGroup.VBE(); + public readonly IOGroup.VBEIOGroup VBE = new IOGroup.VBEIOGroup(); } } diff --git a/source/Cosmos.Core/Bootstrap.cs b/source/Cosmos.Core/Bootstrap.cs index 09fd9a5e1..270d62146 100644 --- a/source/Cosmos.Core/Bootstrap.cs +++ b/source/Cosmos.Core/Bootstrap.cs @@ -1,6 +1,6 @@ namespace Cosmos.Core { - public static class Bootstrap + public unsafe static class Bootstrap { // See note in Global - these are a "hack" for now so // we dont force static init of Global, and it "pulls" these later till @@ -9,6 +9,11 @@ // Has to be static for now, ZeroFill gets called before the Init. static public readonly CPU CPU = new CPU(); + public static Multiboot.Header* header; + + public static VBE.ModeInfo* modeinfo; + public static VBE.ControllerInfo* controllerinfo; + // 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 @@ -32,6 +37,11 @@ */ CPU.InitFloat(); + header = (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(); } diff --git a/source/Cosmos.Core/IOGroup/VBE.cs b/source/Cosmos.Core/IOGroup/VBE.cs index 6e973d3c6..17ed31685 100644 --- a/source/Cosmos.Core/IOGroup/VBE.cs +++ b/source/Cosmos.Core/IOGroup/VBE.cs @@ -10,7 +10,7 @@ namespace Cosmos.Core.IOGroup /// /// VBE class. /// - public class VBE : IOGroup + public class VBEIOGroup : IOGroup { /// /// Index IOPort. @@ -27,7 +27,7 @@ namespace Cosmos.Core.IOGroup /// /// Frame buffer memory block. /// - public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1920 * 1200 * 4); + public MemoryBlock LinearFrameBuffer; //public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1024 * 768 * 4); } } diff --git a/source/Cosmos.Core/Multiboot.cs b/source/Cosmos.Core/Multiboot.cs new file mode 100644 index 000000000..c09760707 --- /dev/null +++ b/source/Cosmos.Core/Multiboot.cs @@ -0,0 +1,199 @@ +using IL2CPU.API.Attribs; +using System; +using System.Runtime.InteropServices; + +namespace Cosmos.Core +{ + /// + /// Used for Multiboot parsing + /// + public class Multiboot + { + /// /// + /// Get Multiboot address. Plugged. + /// + /// The Multiboot Address + [PlugMethod(PlugRequired = true)] + public static uint GetMBIAddress() => throw null; + + [StructLayout(LayoutKind.Explicit, Size = 88)] + public unsafe struct Header + { + [FieldOffset(0)] + public uint Flags; + [FieldOffset(4)] + public uint mem_lower; + [FieldOffset(8)] + public uint mem_upper; + [FieldOffset(12)] + public uint boot_device; + [FieldOffset(16)] + public uint cmdline; + [FieldOffset(20)] + public uint mods_count; + [FieldOffset(24)] + public uint mods_addr; + [FieldOffset(28)] + public fixed uint syms[4]; + [FieldOffset(44)] + public uint memMapLength; + [FieldOffset(48)] + public uint memMapAddress; + [FieldOffset(52)] + public uint drivesLength; + [FieldOffset(56)] + public uint drivesAddress; + [FieldOffset(60)] + public uint configTable; + [FieldOffset(68)] + public uint apmTable; + [FieldOffset(72)] + public uint vbeControlInfo; + [FieldOffset(76)] + public uint vbeModeInfo; + [FieldOffset(80)] + public uint vbeMode; + [FieldOffset(82)] + public uint vbeInterfaceSeg; + [FieldOffset(84)] + public uint vbeInterfaceOff; + [FieldOffset(86)] + public uint vbeInterfaceLength; + } + } + + public unsafe static class VBE + { + + static uint VBEINFO_PRESENT = (1 << 11); + + /// /// + /// Check in Multiboot if VBE is available + /// + /// True if is available, false if not + public static bool IsAvailable() + { + if ((Bootstrap.header->Flags & VBEINFO_PRESENT) == 0) + { + return false; + } + else + { + return true; + } + } + + /// /// + /// Get VBE Modeinfo structure + /// + public static ModeInfo getModeInfo() + { + return *Bootstrap.modeinfo; + } + + /// /// + /// Get the linear frame buffer address from VBE ModeInfo structure + /// + /// the offset in an uint + public static uint getLfbOffset() + { + return Bootstrap.modeinfo->framebuffer; + } + + [StructLayout(LayoutKind.Explicit, Size = 36)] + public struct ControllerInfo + { + [FieldOffset(0)] + public uint vbeSignature; + [FieldOffset(4)] + public ushort vbeVersion; + [FieldOffset(6)] + public uint oemStringPtr; + [FieldOffset(10)] + public uint capabilities; + [FieldOffset(14)] + public uint videoModePtr; + [FieldOffset(18)] + public ushort totalmemory; + [FieldOffset(20)] + public ushort oemSoftwareRev; + [FieldOffset(24)] + public uint oemVendorNamePtr; + [FieldOffset(28)] + public uint oemProductNamePtr; + [FieldOffset(32)] + public uint oemProductRevPtr; + } + + [StructLayout(LayoutKind.Explicit, Size = 256)] + public struct ModeInfo + { + [FieldOffset(0)] + public ushort attributes; // deprecated, only bit 7 should be of interest to you, and it indicates the mode supports a linear frame buffer. + [FieldOffset(2)] + public byte window_a; // deprecated + [FieldOffset(3)] + public byte window_b; // deprecated + [FieldOffset(4)] + public ushort granularity; // deprecated; used while calculating bank numbers + [FieldOffset(6)] + public ushort window_size; + [FieldOffset(8)] + public ushort segment_a; + [FieldOffset(10)] + public ushort segment_b; + [FieldOffset(12)] + public uint win_func_ptr; // deprecated; used to switch banks from protected mode without returning to real mode + [FieldOffset(16)] + public ushort pitch; // number of bytes per horizontal line + [FieldOffset(18)] + public ushort width; // width in pixels + [FieldOffset(20)] + public ushort height; // height in pixels + [FieldOffset(22)] + public byte w_char; // unused... + [FieldOffset(23)] + public byte y_char; // ... + [FieldOffset(24)] + public byte planes; + [FieldOffset(25)] + public byte bpp; // bits per pixel in this mode + [FieldOffset(26)] + public byte banks; // deprecated; total number of banks in this mode + [FieldOffset(27)] + public byte memory_model; + [FieldOffset(28)] + public byte bank_size; // deprecated; size of a bank, almost always 64 KB but may be 16 KB... + [FieldOffset(29)] + public byte image_pages; + [FieldOffset(30)] + public byte reserved0; + [FieldOffset(31)] + public byte red_mask; + [FieldOffset(32)] + public byte red_position; + [FieldOffset(33)] + public byte green_mask; + [FieldOffset(34)] + public byte green_position; + [FieldOffset(35)] + public byte blue_mask; + [FieldOffset(36)] + public byte blue_position; + [FieldOffset(37)] + public byte reserved_mask; + [FieldOffset(38)] + public byte reserved_position; + [FieldOffset(39)] + public byte direct_color_attributes; + [FieldOffset(40)] + public uint framebuffer; // physical address of the linear frame buffer; write here to draw to the screen + [FieldOffset(44)] + public uint off_screen_mem_off; + [FieldOffset(48)] + public ushort off_screen_mem_size; // size of memory in the framebuffer but not being displayed on the screen + [FieldOffset(50)] + public fixed byte reserved1[206]; + } + } +} diff --git a/source/Cosmos.Core_Asm/Multiboot/MultibootAsm.cs b/source/Cosmos.Core_Asm/Multiboot/MultibootAsm.cs new file mode 100644 index 000000000..f77597cf4 --- /dev/null +++ b/source/Cosmos.Core_Asm/Multiboot/MultibootAsm.cs @@ -0,0 +1,14 @@ +using XSharp.Assembler; +using XSharp; +using CPUx86 = XSharp.Assembler.x86; + +namespace Cosmos.Core_Asm +{ + public class MultibootAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + new CPUx86.Push { DestinationRef = ElementReference.New("MultiBootInfo_Structure"), DestinationIsIndirect = true }; + } + } +} diff --git a/source/Cosmos.Core_Asm/MultibootImpl.cs b/source/Cosmos.Core_Asm/MultibootImpl.cs new file mode 100644 index 000000000..d3c9226ac --- /dev/null +++ b/source/Cosmos.Core_Asm/MultibootImpl.cs @@ -0,0 +1,12 @@ +using Cosmos.Core; +using IL2CPU.API.Attribs; + +namespace Cosmos.Core_Asm +{ + [Plug(Target = typeof(Multiboot))] + public class MultibootImpl + { + [PlugMethod(Assembler = typeof(MultibootAsm))] + public static uint GetMBIAddress() => throw null; + } +} diff --git a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs index 658316ef7..5cb63e93d 100644 --- a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs +++ b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs @@ -12,7 +12,7 @@ namespace Cosmos.HAL.Drivers public class VBEDriver { - private static readonly VBE IO = Core.Global.BaseIOGroups.VBE; + private static readonly VBEIOGroup IO = Core.Global.BaseIOGroups.VBE; ManagedMemoryBlock lastbuffer; /// @@ -76,10 +76,19 @@ namespace Cosmos.HAL.Drivers /// BPP (color depth). public VBEDriver(ushort xres, ushort yres, ushort bpp) { - Global.mDebugger.SendInternal($"Creating VBEDriver with Mode {xres}*{yres}@{bpp}"); - //IO.LinearFrameBuffer = new MemoryBlock(0xE0000000, (uint)xres * yres * (uint)(bpp / 8)); - lastbuffer = new ManagedMemoryBlock(1920 * 1200 * 4); - VBESet(xres, yres, bpp); + if (VBE.IsAvailable()) + { + Global.mDebugger.SendInternal($"Creating VBE VESA driver with Mode {xres}*{yres}@{bpp}"); + IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); + lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); + } + else + { + Global.mDebugger.SendInternal($"Creating VBE BGA driver with Mode {xres}*{yres}@{bpp}"); + IO.LinearFrameBuffer = new MemoryBlock(0xE0000000, 1920 * 1200 * 4); + lastbuffer = new ManagedMemoryBlock(1920 * 1200 * 4); + VBESet(xres, yres, bpp); + } } /// diff --git a/source/Cosmos.System2/Graphics/FullScreenCanvas.cs b/source/Cosmos.System2/Graphics/FullScreenCanvas.cs index 4beffad0c..2395c13d6 100644 --- a/source/Cosmos.System2/Graphics/FullScreenCanvas.cs +++ b/source/Cosmos.System2/Graphics/FullScreenCanvas.cs @@ -66,7 +66,7 @@ namespace Cosmos.System.Graphics { return new SVGAIICanvas(); } - else if (BGAExists() || PCI.GetDevice((VendorID)0x80EE, (DeviceID)0xBEEF) != null) + else if (BGAExists() || PCI.GetDevice((VendorID)0x80EE, (DeviceID)0xBEEF) != null || Core.VBE.IsAvailable()) { return new VBECanvas(); } @@ -88,7 +88,7 @@ namespace Cosmos.System.Graphics { return new SVGAIICanvas(mode); } - else if (BGAExists() || PCI.GetDevice((VendorID)0x80EE, (DeviceID)0xBEEF) != null) + else if (BGAExists() || PCI.GetDevice((VendorID)0x80EE, (DeviceID)0xBEEF) != null || Core.VBE.IsAvailable()) { return new VBECanvas(mode); } diff --git a/source/Cosmos.System2/Graphics/VBECanvas.cs b/source/Cosmos.System2/Graphics/VBECanvas.cs index a38d5a735..1cd9bc5a5 100644 --- a/source/Cosmos.System2/Graphics/VBECanvas.cs +++ b/source/Cosmos.System2/Graphics/VBECanvas.cs @@ -44,6 +44,13 @@ namespace Cosmos.System.Graphics { Global.mDebugger.SendInternal($"Creating new VBEScreen() with mode {aMode.Columns}x{aMode.Rows}x{(uint)aMode.ColorDepth}"); + if (Core.VBE.IsAvailable()) + { + Core.VBE.ModeInfo ModeInfo = Core.VBE.getModeInfo(); + aMode = new Mode(ModeInfo.width, ModeInfo.height, (ColorDepth)ModeInfo.bpp); + Global.mDebugger.SendInternal($"Detected VBE VESA with {aMode.Columns}x{aMode.Rows}x{(uint)aMode.ColorDepth}"); + } + ThrowIfModeIsNotValid(aMode); _VBEDriver = new VBEDriver((ushort)aMode.Columns, (ushort)aMode.Rows, (ushort)aMode.ColorDepth); @@ -122,6 +129,7 @@ namespace Cosmos.System.Graphics new Mode(1024, 768, ColorDepth.ColorDepth32), /* The so called HD-Ready resolution */ new Mode(1280, 720, ColorDepth.ColorDepth32), + new Mode(1280, 768, ColorDepth.ColorDepth32), new Mode(1280, 1024, ColorDepth.ColorDepth32), /* A lot of HD-Ready screen uses this instead of 1280x720 */ new Mode(1366, 768, ColorDepth.ColorDepth32),