Fixed GDT creation and address retrieval.

This commit is contained in:
neviyn 2017-11-09 23:21:49 +00:00
parent 8b129ea6d8
commit f279852501

View File

@ -1,25 +1,33 @@
import serial
type type
GDTEntry{.packed.} = object GDTEntry{.packed.} = object
limit_low: uint16 limit_low: uint16
base_low: uint16 base_low: uint16
base_middle: uint8 base_middle: uint8
access: uint8 access: uint8
granularity: uint8 flags_and_limit_mid: uint8
base_high: uint8 base_high: uint8
GDTPointer{.packed.} = ptr 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 = ptr array[0..2, GDTEntry] GDTEntries = array[0..2, GDTEntry]
AccessByte = uint8
Flags = uint8
var var
gdt: GDTEntries gdt: GDTEntries
gp: GDTPointer gp: GDTPointer
gpAddr: uint32
let gpAddr = cast[uint32](addr(gp))
{.push stackTrace:off.} {.push stackTrace:off.}
proc gdtFlush(){.asmNoStackFrame, inline.} = proc gdtFlush(){.inline.} =
gpAddr = cast[uint32](gp.addr)
serial.write("GDPointer Address: ")
serial.write(gpAddr)
serial.newLine()
asm """ asm """
cli
lgdt [`gpAddr`] lgdt [`gpAddr`]
mov %ax, 0x10 mov %ax, 0x10
mov %ds, %ax mov %ds, %ax
@ -30,7 +38,7 @@ proc gdtFlush(){.asmNoStackFrame, inline.} =
""" """
{.pop.} {.pop.}
proc gdtSetGate(num: int, base: uint16, limit: uint32, access: uint8, granularity: uint8) = 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[num].base_low = (base and 0xFFFF)
gdt[num].base_middle = (base shr 16) and 0xFF gdt[num].base_middle = (base shr 16) and 0xFF
@ -38,23 +46,36 @@ proc gdtSetGate(num: int, base: uint16, limit: uint32, access: uint8, granularit
# Setup the descriptor limits # Setup the descriptor limits
gdt[num].limit_low = (limit and 0xFFFF) gdt[num].limit_low = (limit and 0xFFFF)
gdt[num].granularity = ((limit shr 16) and 0x0F) gdt[num].flags_and_limit_mid = ((limit shr 16) and 0x0F) or flags
# Finally, set up the granularity and access flags
gdt[num].granularity = gdt[num].granularity or (granularity and 0xF0)
gdt[num].access = access gdt[num].access = access
proc gdtInstall*() = proc createAccessByte(priv: range[0..3], directionConform: bool, readWrite: bool): AccessByte =
gp.limit = uint16(sizeof(GDTEntry) * 3) - 1; result = 0b10011000'u8 # Present and executable bit
gp.base = cast[uint32](addr(gdt)); result = result or (uint8(priv) shl 5)
if directionConform:
result = result or 0b00000100'u8
if readWrite:
result = result or 0b00000010'u8
proc createFlags(granularity: bool, size: bool): Flags =
if granularity:
result = result or 0b10000000'u8
if size:
result = result or 0b01000000'u8
proc gdtInstall*() =
gp.limit = uint16(sizeof(GDTEntry) * gdt.len) - 1;
gp.base = cast[uint32](gdt.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);
# The second entry is our Code Segment # The second entry is our Code Segment
gdtSetGate(1, 0'u16, 0xFFFFFFFF'u32, 0x9A'u8, 0xCF'u8); gdtSetGate(1, 0'u16, 0xFFFFFFFF'u32, createAccessByte(0, false, true), createFlags(true, true));
# The third entry is our Data Segment # The third entry is our Data Segment
gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, 0x92'u8, 0xCF'u8); gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, createAccessByte(0, false, true), createFlags(true, true));
serial.write("Flushing GDT.\L")
gdtFlush(); gdtFlush();