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