GDT now installs correctly.

This commit is contained in:
neviyn 2017-11-21 19:20:05 +00:00
parent 5cefd5d2b8
commit 8d61080d8d

View File

@ -11,43 +11,41 @@ type
GDTPointer{.packed.} = object GDTPointer{.packed.} = object
limit: uint16 # Size of GDT limit: uint16 # Size of GDT
base: uint32 # GDT memory location base: uint32 # GDT memory location
GDTEntries = array[0..2, GDTEntry]
AccessByte = uint8 AccessByte = uint8
Flags = uint8 Flags = uint8
GDT{.packed.} = object
descriptor: GDTPointer
entries: array[0..2, GDTEntry]
var const
gdt: GDTEntries gdtAddress: uint32 = 0x00000800
gp: GDTPointer gdt = cast[ptr GDT](gdtAddress)
gpAddr: uint32
{.push stackTrace:off.} {.push stackTrace:off.}
proc gdtFlush(){.inline.} = proc gdtFlush(){.inline,asmNoStackFrame.} =
gpAddr = cast[uint32](gp.addr)
serial.write("GDPointer Address: ")
serial.write(gpAddr)
serial.newLine()
asm """ asm """
cli cli
lgdt [`gpAddr`] lgdtl [`0x00000800`]
mov %ax, 0x10 movw $0x10, %ax
mov %ds, %ax movw %ax, %ds
mov %es, %ax movw %ax, %es
mov %fs, %ax movw %ax, %fs
mov %gs, %ax movw %ax, %gs
mov %ss, %ax ljmp $0x08, $next
next:
""" """
{.pop.} {.pop.}
proc gdtSetGate(num: int, base: uint16, limit: uint32, access: AccessByte, flags: Flags) = proc gdtSetGate(num: int, base: uint16, limit: uint32, access: AccessByte, flags: Flags) =
# Setup the descriptor base address # Setup the descriptor base address
gdt[num].base_low = (base and 0xFFFF) gdt.entries[num].base_low = (base and 0xFFFF)
gdt[num].base_middle = (base shr 16) and 0xFF gdt.entries[num].base_middle = (base shr 16) and 0xFF
gdt[num].base_high = (base shr 24) and 0xFF gdt.entries[num].base_high = (base shr 24) and 0xFF
# Setup the descriptor limits # Setup the descriptor limits
gdt[num].limit_low = (limit and 0xFFFF) gdt.entries[num].limit_low = (limit and 0xFFFF)
gdt[num].flags_and_limit_mid = ((limit shr 16) and 0x0F) or flags gdt.entries[num].flags_and_limit_mid = ((limit shr 16) and 0x0F) or flags
gdt[num].access = access gdt.entries[num].access = access
proc createAccessByte(priv: range[0..3], directionConform: bool, readWrite: bool): AccessByte = proc createAccessByte(priv: range[0..3], directionConform: bool, readWrite: bool): AccessByte =
result = 0b10011000'u8 # Present and executable bit result = 0b10011000'u8 # Present and executable bit
@ -64,11 +62,8 @@ proc createFlags(granularity: bool, size: bool): Flags =
result = result or 0b01000000'u8 result = result or 0b01000000'u8
proc gdtInstall*() = proc gdtInstall*() =
gp.limit = uint16(sizeof(GDTEntry) * gdt.len) - 1; gdt.descriptor.limit = uint16(sizeof(GDTEntry) * gdt.entries.len) - 1;
gp.base = cast[uint32](gdt.addr) gdt.descriptor.base = cast[uint32](gdt.entries.addr)
serial.write("GDT Address: ")
serial.write(gp.base)
serial.newLine()
# NULL descriptor # NULL descriptor
gdtSetGate(0, 0, 0, 0, 0); gdtSetGate(0, 0, 0, 0, 0);
@ -78,4 +73,4 @@ proc gdtInstall*() =
# The third entry is our Data Segment # The third entry is our Data Segment
gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, createAccessByte(0, false, true), createFlags(true, true)); gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, createAccessByte(0, false, true), createFlags(true, true));
serial.write("Flushing GDT.\L") serial.write("Flushing GDT.\L")
gdtFlush(); gdtFlush()