mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-24 12:35:31 +00:00
GDT work
This commit is contained in:
parent
beb587aea0
commit
967ca09a2c
2 changed files with 102 additions and 34 deletions
|
|
@ -48,6 +48,7 @@ namespace Cosmos.IL2CPU.X86
|
||||||
new Comment(this, "EBX=multiboot_info ");
|
new Comment(this, "EBX=multiboot_info ");
|
||||||
new Comment(this, "EAX=0x2BADB002 - check if it's really Multiboot loader ");
|
new Comment(this, "EAX=0x2BADB002 - check if it's really Multiboot loader ");
|
||||||
new Comment(this, " ;- copy mb info - some stuff for you ");
|
new Comment(this, " ;- copy mb info - some stuff for you ");
|
||||||
|
new Comment(this, "BEGIN - Multiboot Info");
|
||||||
//new Move { DestinationReg = Registers.ESI, SourceReg = Registers.EBX };
|
//new Move { DestinationReg = Registers.ESI, SourceReg = Registers.EBX };
|
||||||
//new Move { DestinationReg = Registers.EDI, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
|
//new Move { DestinationReg = Registers.EDI, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
|
||||||
//new Move { DestinationReg = Registers.ECX, SourceValue = 0x58 };
|
//new Move { DestinationReg = Registers.ECX, SourceValue = 0x58 };
|
||||||
|
|
@ -56,12 +57,7 @@ namespace Cosmos.IL2CPU.X86
|
||||||
//new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
|
//new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
|
||||||
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Structure"), DestinationIsIndirect = true, SourceReg = Registers.EBX };
|
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Structure"), DestinationIsIndirect = true, SourceReg = Registers.EBX };
|
||||||
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
||||||
new Move
|
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true };
|
||||||
{
|
|
||||||
DestinationReg = Registers.EAX,
|
|
||||||
SourceReg = Registers.EBX,
|
|
||||||
SourceIsIndirect = true
|
|
||||||
};
|
|
||||||
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
||||||
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
||||||
new Move
|
new Move
|
||||||
|
|
@ -76,6 +72,8 @@ namespace Cosmos.IL2CPU.X86
|
||||||
DestinationReg = Registers.ESP,
|
DestinationReg = Registers.ESP,
|
||||||
SourceRef = ElementReference.New("Kernel_Stack")
|
SourceRef = ElementReference.New("Kernel_Stack")
|
||||||
};
|
};
|
||||||
|
new Comment(this, "END - Multiboot Info");
|
||||||
|
|
||||||
#if LFB_1024_8
|
#if LFB_1024_8
|
||||||
new Comment("Set graphics fields");
|
new Comment("Set graphics fields");
|
||||||
new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure"), SourceIsIndirect = true };
|
new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure"), SourceIsIndirect = true };
|
||||||
|
|
@ -86,9 +84,8 @@ namespace Cosmos.IL2CPU.X86
|
||||||
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true, SourceDisplacement = 80 };
|
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true, SourceDisplacement = 80 };
|
||||||
new Move { DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeMode"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
new Move { DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeMode"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
||||||
#endif
|
#endif
|
||||||
new Comment(this, "some more startups todo");
|
|
||||||
|
|
||||||
// SSE init
|
new Comment(this, "BEGIN - SSE Init");
|
||||||
// CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
|
// CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
|
||||||
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
|
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
|
||||||
new Or { DestinationReg = Registers.EAX, SourceValue = 0x100 };
|
new Or { DestinationReg = Registers.EAX, SourceValue = 0x100 };
|
||||||
|
|
@ -104,7 +101,7 @@ namespace Cosmos.IL2CPU.X86
|
||||||
|
|
||||||
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
|
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
|
||||||
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
|
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
|
||||||
// END SSE INIT
|
new Comment(this, "END - SSE Init");
|
||||||
|
|
||||||
if (mComNumber > 0)
|
if (mComNumber > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -118,7 +115,7 @@ namespace Cosmos.IL2CPU.X86
|
||||||
// Jump to Kernel entry point
|
// Jump to Kernel entry point
|
||||||
new Call { DestinationLabel = EntryPointName };
|
new Call { DestinationLabel = EntryPointName };
|
||||||
|
|
||||||
// After Kernel is done, sit here and halt till next IRQ.
|
new Comment(this, "Kernel done - loop till next IRQ");
|
||||||
new Label(".loop");
|
new Label(".loop");
|
||||||
new ClrInterruptFlag();
|
new ClrInterruptFlag();
|
||||||
new Halt();
|
new Halt();
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,85 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Cosmos.Core.Plugs.Assemblers {
|
namespace Cosmos.Core.Plugs.Assemblers {
|
||||||
public class CreateGDT : AssemblerMethod {
|
public class CreateGDT : AssemblerMethod {
|
||||||
|
// http://wiki.osdev.org/Global_Descriptor_Table
|
||||||
|
// http://http://wiki.osdev.org/GDT_Tutorial
|
||||||
|
// http://www.osdever.net/bkerndev/Docs/gdt.htm
|
||||||
|
|
||||||
|
//TODO: Modify this to support the flags and access as individual input rather
|
||||||
|
// than requiring user to pass pre-calculated numbers.
|
||||||
|
protected byte[] Descriptor(UInt32 aBase, UInt32 aSize, bool aCode) {
|
||||||
|
// Limit is a confusing word. Is it the max physical address or size?
|
||||||
|
// In fact it is the size, and 286 docs actually refer to it as size
|
||||||
|
// rather than limit.
|
||||||
|
// It is also size - 1, else there would be no way to specify
|
||||||
|
// all of RAM, and a limit of 0 is invalid.
|
||||||
|
|
||||||
|
var xResult = new byte[8];
|
||||||
|
|
||||||
|
// Check the limit to make sure that it can be encoded
|
||||||
|
if ((aSize > 65536) && (aSize & 0x0FFF) != 0x0FFF) {
|
||||||
|
// If larger than 16 bit, must be an even page (4kb) size
|
||||||
|
throw new Exception("Invalid size in GDT descriptor.");
|
||||||
|
}
|
||||||
|
// Flags nibble
|
||||||
|
// 7: Granularity
|
||||||
|
// 0 = bytes
|
||||||
|
// 1 = 4kb pages
|
||||||
|
// 6: 1 = 32 bit mode
|
||||||
|
// 5: 0 - Reserved
|
||||||
|
// 4: 0 - Reserved
|
||||||
|
xResult[6] = 0x40;
|
||||||
|
if (aSize > 65536) {
|
||||||
|
// Set page sizing instead of byte sizing
|
||||||
|
aSize = aSize >> 12;
|
||||||
|
xResult[6] = (byte)(xResult[6] | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
xResult[0] = (byte)(aSize & 0xFF);
|
||||||
|
xResult[1] = (byte)((aSize >> 8) & 0xFF);
|
||||||
|
xResult[6] = (byte)(xResult[6] | ((aSize >> 16) & 0x0F));
|
||||||
|
|
||||||
|
xResult[2] = (byte)(aBase & 0xFF);
|
||||||
|
xResult[3] = (byte)((aBase >> 8) & 0xFF);
|
||||||
|
xResult[4] = (byte)((aBase >> 16) & 0xFF);
|
||||||
|
xResult[7] = (byte)((aBase >> 24) & 0xFF);
|
||||||
|
|
||||||
|
xResult[5] = (byte)(
|
||||||
|
// Bit 7: Present, must be 1
|
||||||
|
0x80 |
|
||||||
|
// Bit 6-5: Privilege, 0=kernel, 3=user
|
||||||
|
0x00 |
|
||||||
|
// Reserved, must be 1
|
||||||
|
0x10 |
|
||||||
|
// Bit 3: 1=Code, 0=Data
|
||||||
|
(aCode ? 0x08 : 0x00) |
|
||||||
|
// Bit 2: Direction/Conforming
|
||||||
|
0x00 |
|
||||||
|
// Bit 1: R/W Data (1=Writeable, 0=Read only) Code (1=Readable, 0=Not readable)
|
||||||
|
0x02 |
|
||||||
|
// Bit 0: Accessed - Set to 0. Updated by CPU later.
|
||||||
|
0x00
|
||||||
|
);
|
||||||
|
|
||||||
|
return xResult;
|
||||||
|
}
|
||||||
|
|
||||||
public override void AssembleNew(object aAssembler, object aMethodInfo) {
|
public override void AssembleNew(object aAssembler, object aMethodInfo) {
|
||||||
var xAssembler = (Assembler)aAssembler;
|
var xAsm = (Assembler)aAssembler;
|
||||||
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Contents"
|
|
||||||
, new byte[]
|
var xGDT = new List<byte>();
|
||||||
{0,0,0,0,0,0,0,0 // Null Segment
|
// Null Segment - Selector 0x00
|
||||||
, 0xFF, 0xFF, 0, 0, 0, 0x99, 0xCF, 0 // Code Segment
|
// Not used, but required by many emulators.
|
||||||
, 0xFF,0xFF,0,0,0,0x93,0xCF,0})); // Data Segment
|
xGDT.AddRange(new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
|
||||||
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Pointer", new ushort[] { 0x17, 0, 0 }));
|
// Code Segment
|
||||||
|
byte xCodeSelector = (byte)xGDT.Count;
|
||||||
|
xGDT.AddRange(Descriptor(0x00000000, 0xFFFFFFFF, true));
|
||||||
|
// Data Segment - Selector 0x0B
|
||||||
|
byte xDataSelector = (byte)xGDT.Count;
|
||||||
|
xGDT.AddRange(Descriptor(0x00000000, 0xFFFFFFFF, false));
|
||||||
|
xAsm.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Contents", xGDT.ToArray()));
|
||||||
|
|
||||||
|
xAsm.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Pointer", new ushort[] { 0x17, 0, 0 }));
|
||||||
|
|
||||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
|
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
|
||||||
new CPUx86.Move { DestinationRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Contents") };
|
new CPUx86.Move { DestinationRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Contents") };
|
||||||
|
|
@ -30,8 +101,8 @@ namespace Cosmos.Core.Plugs.Assemblers {
|
||||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.GS, SourceReg = CPUx86.Registers.AX };
|
new CPUx86.Move { DestinationReg = CPUx86.Registers.GS, SourceReg = CPUx86.Registers.AX };
|
||||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.SS, SourceReg = CPUx86.Registers.AX };
|
new CPUx86.Move { DestinationReg = CPUx86.Registers.SS, SourceReg = CPUx86.Registers.AX };
|
||||||
|
|
||||||
// Force reload of code segment
|
new CPUAll.Comment("Force reload of code segment");
|
||||||
new CPUx86.JumpToSegment { Segment = 8, DestinationLabel = "flush__GDT__table" };
|
new CPUx86.JumpToSegment { Segment = 0x08, DestinationLabel = "flush__GDT__table" };
|
||||||
new CPUAll.Label("flush__GDT__table");
|
new CPUAll.Label("flush__GDT__table");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue