61 lines
1.5 KiB
Nim
61 lines
1.5 KiB
Nim
|
type
|
||
|
GDTEntry{.packed.} = object
|
||
|
limit_low: uint16
|
||
|
base_low: uint16
|
||
|
base_middle: uint8
|
||
|
access: uint8
|
||
|
granularity: uint8
|
||
|
base_high: uint8
|
||
|
GDTPointer{.packed.} = ptr object
|
||
|
limit: uint16 # Size of GDT
|
||
|
base: uint32 # GDT memory location
|
||
|
GDTEntries = ptr array[0..2, GDTEntry]
|
||
|
|
||
|
var
|
||
|
gdt: GDTEntries
|
||
|
gp: GDTPointer
|
||
|
|
||
|
let gpAddr = cast[uint32](addr(gp))
|
||
|
|
||
|
{.push stackTrace:off.}
|
||
|
proc gdtFlush(){.asmNoStackFrame, inline.} =
|
||
|
asm """
|
||
|
lgdt [`gpAddr`]
|
||
|
mov %ax, 0x10
|
||
|
mov %ds, %ax
|
||
|
mov %es, %ax
|
||
|
mov %fs, %ax
|
||
|
mov %gs, %ax
|
||
|
mov %ss, %ax
|
||
|
"""
|
||
|
{.pop.}
|
||
|
|
||
|
proc gdtSetGate(num: int, base: uint16, limit: uint32, access: uint8, granularity: uint8) =
|
||
|
# 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
|
||
|
|
||
|
# Setup the descriptor limits
|
||
|
gdt[num].limit_low = (limit and 0xFFFF)
|
||
|
gdt[num].granularity = ((limit shr 16) and 0x0F)
|
||
|
|
||
|
# Finally, set up the granularity and access flags
|
||
|
gdt[num].granularity = gdt[num].granularity or (granularity and 0xF0)
|
||
|
gdt[num].access = access
|
||
|
|
||
|
proc gdtInstall*() =
|
||
|
gp.limit = uint16(sizeof(GDTEntry) * 3) - 1;
|
||
|
gp.base = cast[uint32](addr(gdt));
|
||
|
|
||
|
# NULL descriptor
|
||
|
gdtSetGate(0, 0, 0, 0, 0);
|
||
|
|
||
|
# The second entry is our Code Segment
|
||
|
gdtSetGate(1, 0'u16, 0xFFFFFFFF'u32, 0x9A'u8, 0xCF'u8);
|
||
|
|
||
|
# The third entry is our Data Segment
|
||
|
gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, 0x92'u8, 0xCF'u8);
|
||
|
|
||
|
gdtFlush();
|