Merge pull request #1384 from CosmosOS/dev/multibootvbe

Multiboot VBE detection
This commit is contained in:
valentinbreiz 2020-07-06 22:01:28 +02:00 committed by GitHub
commit afff8d9e46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 263 additions and 11 deletions

View file

@ -43,6 +43,6 @@ namespace Cosmos.Core {
/// <summary> /// <summary>
/// VBE. /// VBE.
/// </summary> /// </summary>
public readonly IOGroup.VBE VBE = new IOGroup.VBE(); public readonly IOGroup.VBEIOGroup VBE = new IOGroup.VBEIOGroup();
} }
} }

View file

@ -1,6 +1,6 @@
namespace Cosmos.Core namespace Cosmos.Core
{ {
public static class Bootstrap public unsafe static class Bootstrap
{ {
// See note in Global - these are a "hack" for now so // See note in Global - these are a "hack" for now so
// we dont force static init of Global, and it "pulls" these later till // 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. // Has to be static for now, ZeroFill gets called before the Init.
static public readonly CPU CPU = new CPU(); 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. // Bootstrap is a class designed only to get the essentials done.
// ie the stuff needed to "pre boot". Do only the very minimal here. // ie the stuff needed to "pre boot". Do only the very minimal here.
// IDT, PIC, and Float // IDT, PIC, and Float
@ -32,6 +37,11 @@
*/ */
CPU.InitFloat(); 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.Initialize();
// Managed_Memory_System.ManagedMemory.SetUpMemoryArea(); // Managed_Memory_System.ManagedMemory.SetUpMemoryArea();
} }

View file

@ -10,7 +10,7 @@ namespace Cosmos.Core.IOGroup
/// <summary> /// <summary>
/// VBE class. /// VBE class.
/// </summary> /// </summary>
public class VBE : IOGroup public class VBEIOGroup : IOGroup
{ {
/// <summary> /// <summary>
/// Index IOPort. /// Index IOPort.
@ -27,7 +27,7 @@ namespace Cosmos.Core.IOGroup
/// <summary> /// <summary>
/// Frame buffer memory block. /// Frame buffer memory block.
/// </summary> /// </summary>
public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1920 * 1200 * 4); public MemoryBlock LinearFrameBuffer;
//public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1024 * 768 * 4); //public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1024 * 768 * 4);
} }
} }

View file

@ -0,0 +1,199 @@
using IL2CPU.API.Attribs;
using System;
using System.Runtime.InteropServices;
namespace Cosmos.Core
{
/// <summary>
/// Used for Multiboot parsing
/// </summary>
public class Multiboot
{
/// /// <summary>
/// Get Multiboot address. Plugged.
/// </summary>
/// <returns>The Multiboot Address</returns>
[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);
/// /// <summary>
/// Check in Multiboot if VBE is available
/// </summary>
/// <returns>True if is available, false if not</returns>
public static bool IsAvailable()
{
if ((Bootstrap.header->Flags & VBEINFO_PRESENT) == 0)
{
return false;
}
else
{
return true;
}
}
/// /// <summary>
/// Get VBE Modeinfo structure
/// </summary>
public static ModeInfo getModeInfo()
{
return *Bootstrap.modeinfo;
}
/// /// <summary>
/// Get the linear frame buffer address from VBE ModeInfo structure
/// </summary>
/// <returns>the offset in an uint</returns>
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];
}
}
}

View file

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

View file

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

View file

@ -12,7 +12,7 @@ namespace Cosmos.HAL.Drivers
public class VBEDriver public class VBEDriver
{ {
private static readonly VBE IO = Core.Global.BaseIOGroups.VBE; private static readonly VBEIOGroup IO = Core.Global.BaseIOGroups.VBE;
ManagedMemoryBlock lastbuffer; ManagedMemoryBlock lastbuffer;
/// <summary> /// <summary>
@ -76,10 +76,19 @@ namespace Cosmos.HAL.Drivers
/// <param name="bpp">BPP (color depth).</param> /// <param name="bpp">BPP (color depth).</param>
public VBEDriver(ushort xres, ushort yres, ushort bpp) public VBEDriver(ushort xres, ushort yres, ushort bpp)
{ {
Global.mDebugger.SendInternal($"Creating VBEDriver with Mode {xres}*{yres}@{bpp}"); if (VBE.IsAvailable())
//IO.LinearFrameBuffer = new MemoryBlock(0xE0000000, (uint)xres * yres * (uint)(bpp / 8)); {
lastbuffer = new ManagedMemoryBlock(1920 * 1200 * 4); Global.mDebugger.SendInternal($"Creating VBE VESA driver with Mode {xres}*{yres}@{bpp}");
VBESet(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);
}
} }
/// <summary> /// <summary>

View file

@ -66,7 +66,7 @@ namespace Cosmos.System.Graphics
{ {
return new SVGAIICanvas(); 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(); return new VBECanvas();
} }
@ -88,7 +88,7 @@ namespace Cosmos.System.Graphics
{ {
return new SVGAIICanvas(mode); 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); return new VBECanvas(mode);
} }

View file

@ -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}"); 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); ThrowIfModeIsNotValid(aMode);
_VBEDriver = new VBEDriver((ushort)aMode.Columns, (ushort)aMode.Rows, (ushort)aMode.ColorDepth); _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), new Mode(1024, 768, ColorDepth.ColorDepth32),
/* The so called HD-Ready resolution */ /* The so called HD-Ready resolution */
new Mode(1280, 720, ColorDepth.ColorDepth32), new Mode(1280, 720, ColorDepth.ColorDepth32),
new Mode(1280, 768, ColorDepth.ColorDepth32),
new Mode(1280, 1024, ColorDepth.ColorDepth32), new Mode(1280, 1024, ColorDepth.ColorDepth32),
/* A lot of HD-Ready screen uses this instead of 1280x720 */ /* A lot of HD-Ready screen uses this instead of 1280x720 */
new Mode(1366, 768, ColorDepth.ColorDepth32), new Mode(1366, 768, ColorDepth.ColorDepth32),