mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +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, "EAX=0x2BADB002 - check if it's really Multiboot loader ");
|
||||
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.EDI, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
|
||||
//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 { DestinationRef = ElementReference.New("MultiBootInfo_Structure"), DestinationIsIndirect = true, SourceReg = Registers.EBX };
|
||||
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
||||
new Move
|
||||
{
|
||||
DestinationReg = Registers.EAX,
|
||||
SourceReg = Registers.EBX,
|
||||
SourceIsIndirect = true
|
||||
};
|
||||
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true };
|
||||
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
||||
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
|
||||
new Move
|
||||
|
|
@ -76,6 +72,8 @@ namespace Cosmos.IL2CPU.X86
|
|||
DestinationReg = Registers.ESP,
|
||||
SourceRef = ElementReference.New("Kernel_Stack")
|
||||
};
|
||||
new Comment(this, "END - Multiboot Info");
|
||||
|
||||
#if LFB_1024_8
|
||||
new Comment("Set graphics fields");
|
||||
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 { DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeMode"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
|
||||
#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
|
||||
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
|
||||
new Or { DestinationReg = Registers.EAX, SourceValue = 0x100 };
|
||||
|
|
@ -104,7 +101,7 @@ namespace Cosmos.IL2CPU.X86
|
|||
|
||||
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
|
||||
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
|
||||
// END SSE INIT
|
||||
new Comment(this, "END - SSE Init");
|
||||
|
||||
if (mComNumber > 0)
|
||||
{
|
||||
|
|
@ -118,7 +115,7 @@ namespace Cosmos.IL2CPU.X86
|
|||
// Jump to Kernel entry point
|
||||
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 ClrInterruptFlag();
|
||||
new Halt();
|
||||
|
|
|
|||
|
|
@ -6,33 +6,104 @@ using CPUx86 = Cosmos.Compiler.Assembler.X86;
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Cosmos.Core.Plugs.Assemblers {
|
||||
public class CreateGDT : AssemblerMethod {
|
||||
public override void AssembleNew(object aAssembler, object aMethodInfo) {
|
||||
var xAssembler = (Assembler)aAssembler;
|
||||
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Contents"
|
||||
, new byte[]
|
||||
{0,0,0,0,0,0,0,0 // Null Segment
|
||||
, 0xFF, 0xFF, 0, 0, 0, 0x99, 0xCF, 0 // Code Segment
|
||||
, 0xFF,0xFF,0,0,0,0x93,0xCF,0})); // Data Segment
|
||||
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Pointer", new ushort[] { 0x17, 0, 0 }));
|
||||
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
|
||||
|
||||
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") };
|
||||
//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.
|
||||
|
||||
new CPUAll.Label(".RegisterGDT");
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
|
||||
new CPUx86.Lgdt { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true };
|
||||
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));
|
||||
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceValue = 0x10 };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.DS, SourceReg = CPUx86.Registers.AX };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.ES, SourceReg = CPUx86.Registers.AX };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.FS, 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 };
|
||||
xResult[2] = (byte)(aBase & 0xFF);
|
||||
xResult[3] = (byte)((aBase >> 8) & 0xFF);
|
||||
xResult[4] = (byte)((aBase >> 16) & 0xFF);
|
||||
xResult[7] = (byte)((aBase >> 24) & 0xFF);
|
||||
|
||||
// Force reload of code segment
|
||||
new CPUx86.JumpToSegment { Segment = 8, DestinationLabel = "flush__GDT__table" };
|
||||
new CPUAll.Label("flush__GDT__table");
|
||||
}
|
||||
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) {
|
||||
var xAsm = (Assembler)aAssembler;
|
||||
|
||||
var xGDT = new List<byte>();
|
||||
// Null Segment - Selector 0x00
|
||||
// Not used, but required by many emulators.
|
||||
xGDT.AddRange(new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
|
||||
// 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 { DestinationRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Contents") };
|
||||
|
||||
new CPUAll.Label(".RegisterGDT");
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
|
||||
new CPUx86.Lgdt { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true };
|
||||
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceValue = 0x10 };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.DS, SourceReg = CPUx86.Registers.AX };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.ES, SourceReg = CPUx86.Registers.AX };
|
||||
new CPUx86.Move { DestinationReg = CPUx86.Registers.FS, 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 CPUAll.Comment("Force reload of code segment");
|
||||
new CPUx86.JumpToSegment { Segment = 0x08, DestinationLabel = "flush__GDT__table" };
|
||||
new CPUAll.Label("flush__GDT__table");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue