2017-11-09 23:21:49 +00:00
|
|
|
import serial
|
|
|
|
|
2017-11-06 21:44:17 +00:00
|
|
|
type
|
|
|
|
GDTEntry{.packed.} = object
|
|
|
|
limit_low: uint16
|
|
|
|
base_low: uint16
|
|
|
|
base_middle: uint8
|
|
|
|
access: uint8
|
2017-11-09 23:21:49 +00:00
|
|
|
flags_and_limit_mid: uint8
|
2017-11-06 21:44:17 +00:00
|
|
|
base_high: uint8
|
2017-11-09 23:21:49 +00:00
|
|
|
GDTPointer{.packed.} = object
|
2017-11-06 21:44:17 +00:00
|
|
|
limit: uint16 # Size of GDT
|
|
|
|
base: uint32 # GDT memory location
|
2017-11-09 23:21:49 +00:00
|
|
|
AccessByte = uint8
|
|
|
|
Flags = uint8
|
2018-05-11 02:07:40 +01:00
|
|
|
GDTEntries{.packed.} = array[0..2, GDTEntry]
|
2017-11-21 19:20:05 +00:00
|
|
|
GDT{.packed.} = object
|
|
|
|
descriptor: GDTPointer
|
2018-05-11 02:07:40 +01:00
|
|
|
entries: GDTEntries
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2018-05-11 02:07:40 +01:00
|
|
|
var
|
|
|
|
address: uint32
|
|
|
|
gdt: GDT
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-21 19:20:05 +00:00
|
|
|
proc gdtFlush(){.inline,asmNoStackFrame.} =
|
2017-11-06 21:44:17 +00:00
|
|
|
asm """
|
2018-05-11 02:07:40 +01:00
|
|
|
lgdt (%%eax)
|
2018-04-28 01:03:53 +01:00
|
|
|
ret
|
2018-05-11 02:07:40 +01:00
|
|
|
::"a"(`address`)
|
2017-11-06 21:44:17 +00:00
|
|
|
"""
|
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
proc gdtSetGate(num: int, base: uint16, limit: uint32, access: AccessByte, flags: Flags) =
|
2017-11-06 21:44:17 +00:00
|
|
|
# Setup the descriptor base address
|
2018-04-17 19:28:25 +01:00
|
|
|
gdt.entries[num].base_low = uint16(base and 0xFFFF)
|
|
|
|
gdt.entries[num].base_middle = uint8((base shr 16) and 0xFF)
|
|
|
|
gdt.entries[num].base_high = uint8((base shr 24) and 0xFF)
|
2017-11-06 21:44:17 +00:00
|
|
|
|
|
|
|
# Setup the descriptor limits
|
2018-04-17 19:28:25 +01:00
|
|
|
gdt.entries[num].limit_low = uint16(limit and 0xFFFF)
|
|
|
|
gdt.entries[num].flags_and_limit_mid = uint8(((limit shr 16) and 0x0F) or flags)
|
2017-11-21 19:20:05 +00:00
|
|
|
gdt.entries[num].access = access
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
proc createAccessByte(priv: range[0..3], directionConform: bool, readWrite: bool): AccessByte =
|
|
|
|
result = 0b10011000'u8 # Present and executable bit
|
|
|
|
result = result or (uint8(priv) shl 5)
|
|
|
|
if directionConform:
|
|
|
|
result = result or 0b00000100'u8
|
|
|
|
if readWrite:
|
|
|
|
result = result or 0b00000010'u8
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
proc createFlags(granularity: bool, size: bool): Flags =
|
|
|
|
if granularity:
|
|
|
|
result = result or 0b10000000'u8
|
|
|
|
if size:
|
|
|
|
result = result or 0b01000000'u8
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
proc gdtInstall*() =
|
2018-04-28 01:03:53 +01:00
|
|
|
gdt.descriptor.limit = uint16(sizeof(gdt.entries)) - 1
|
2017-11-21 19:20:05 +00:00
|
|
|
gdt.descriptor.base = cast[uint32](gdt.entries.addr)
|
2018-04-28 01:03:53 +01:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
# NULL descriptor
|
|
|
|
gdtSetGate(0, 0, 0, 0, 0);
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
# The second entry is our Code Segment
|
2018-04-28 01:03:53 +01:00
|
|
|
gdtSetGate(1, 0'u16, 0xFFFFFFFF'u32, 0x9A, createFlags(true, true));
|
2017-11-06 21:44:17 +00:00
|
|
|
|
2017-11-09 23:21:49 +00:00
|
|
|
# The third entry is our Data Segment
|
2018-04-28 01:03:53 +01:00
|
|
|
gdtSetGate(2, 0'u16, 0xFFFFFFFF'u32, 0x92, createFlags(true, true));
|
|
|
|
|
|
|
|
#gdtSetGate(3, 0'u16, 0xFFFFFFFF'u32, 0xFA, createFlags(true, true));
|
|
|
|
|
|
|
|
#gdtSetGate(4, 0'u16, 0xFFFFFFFF'u32, 0xF2, createFlags(true, true));
|
2018-04-28 22:22:05 +01:00
|
|
|
serial.writeLine("Flushing GDT.")
|
2018-05-11 02:07:40 +01:00
|
|
|
address = cast[uint32](gdt.addr)
|
|
|
|
serial.write("GDT Address:")
|
|
|
|
serial.writeLine(address)
|
2017-11-21 19:20:05 +00:00
|
|
|
gdtFlush()
|