diff options
Diffstat (limited to 'src/gdt.c')
-rw-r--r-- | src/gdt.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/gdt.c b/src/gdt.c new file mode 100644 index 0000000..a9808aa --- /dev/null +++ b/src/gdt.c @@ -0,0 +1,36 @@ +#include "gdt.h" + +void encodeGDT(uint8_t* gdtEntry, struct GDT source) { + if ((source.limit > 65536) && ((source.limit & 0xFFF) == 0xFFF)) { + // Set the GDT to use paging + // To do this we need to make sure the limit is aligned to 4KiB + source.limit = source.limit >> 12; + // Granularity: 1 (use paging with 4KiB segments) + // Size: 1 (32 bit protected mode) + gdtEntry[6] = 0xC0; + } + else { + // Granularity: 0 (1 byte segments) + // Size: 1 + gdtEntry[6] = 0x40; + } + + // Here we are encoding the limit + + // Bits 0-15 encode the bottom 16 bits of the limit + gdtEntry[0] = source.limit & 0xFF; + gdtEntry[1] = (source.limit >> 8) & 0xFF; + // Bits 48-51 encode the last 4 bits of the limit + gdtEntry[6] |= (source.limit >> 16) & 0xF; + + // Bits 16-39 encode the bottom 24 bits of the base + gdtEntry[2] = source.base & 0xFF; + gdtEntry[3] = (source.base >> 8) & 0xFF; + gdtEntry[4] = (source.base >> 16) & 0xFF; + // Bits 56-64 encode the last byte of the base + gdtEntry[7] = (source.base >> 24) & 0xFF; + + // Bits 40-47 set the access byte, which is documented at https://wiki.osdev.org/GDT, + // where most of the ideas for this function are taken from shamelessly + gdtEntry[5] = source.type; +} |