@@ -1,6 +1,7 @@
11#include "gdt.h"
22#include "gdt_structures.h"
33#include <std/memory.h>
4+#include <stdbool.h>
4556// TSS definition modified from http://www.jamesmolloy.co.uk/tutorial_html/10.-User%20Mode.html
67typedef struct tss_entry {
@@ -46,6 +47,25 @@ typedef struct gdt_def2 {
4647uint8_t base_high; // The last 8 bits of the base.
4748} __attribute__((packed)) gdt_def2_t;
484950+typedef struct gdt_def3 {
51+uint16_t limit_low;
52+uint16_t base_low;
53+uint8_t base_middle;
54+bool accessed:1;
55+bool readable:1;
56+bool conforming:1;
57+bool is_code:1;
58+bool belongs_to_os:1;
59+uint8_t dpl:2;
60+bool present:1;
61+uint8_t limit_high:4;
62+bool available:1;
63+bool long_mode:1;
64+bool default_operand_size:1;
65+bool granularity:1;
66+uint8_t base_high;
67+} __attribute__((packed)) gdt_def3_t;
68+4969static void gdt_set_gate(void* gdt_entries_ptr, int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
5070gdt_def2_t* gdt_entries = gdt_entries_ptr;
5171gdt_entries[num].base_low = (base & 0xFFFF);
@@ -84,11 +104,17 @@ static void tss_init(void* gdt_base, uint16_t gdt_offset, uint16_t ss0, uint32_t
84104}
8510586106static void gdt_write_descriptor(gdt_entry_t* entry, uint32_t base, uint32_t limit, uint16_t flag) {
107+uint32_t tmp = limit & 0x000F0000;
108+tmp |= (flag);
109+printf("tmp 0x%08x\n", tmp);
110+87111//write the high 32 bit word
88112//set limit bits 19:16
89113entry->high_word = limit & 0x000F0000;
90114//set type, p, dpl, s, g, d/b, l and avl fields
91-entry->high_word |= (flag << 8) & 0x00F0FF00;
115+//entry->high_word |= (flag << 8) & 0x00F0FF00;
116+entry->high_word |= flag;
117+printf("tm2 0x%08x\n", entry->high_word);
92118//set base bits 23:16
93119entry->high_word |= (base >> 16) & 0x000000FF;
94120//set base bits 31:24
@@ -101,22 +127,158 @@ static void gdt_write_descriptor(gdt_entry_t* entry, uint32_t base, uint32_t lim
101127entry->low_word |= limit & 0x0000FFFF;
102128}
103129130+typedef struct __attribute__((packed)) {
131+uint16_t limit_low; /*!< The low word of the limit */
132+uint16_t base_low; /*!< The low word of the base */
133+134+uint8_t base_middle; /*!< The low byte of the upper word of the base */
135+uint8_t access; /*!< The access flags for the entry */
136+uint8_t limit_high; /*!< The high byte of the limit. Also contains the flags */
137+uint8_t base_high; /*!< The high byte of the upper word of the base */
138+} gdt_entry2_t;
139+140+void gdt_set_entry(gdt_entry2_t* entry, uint32_t limit, uint32_t base, uint8_t access, uint8_t flags) {
141+// Set up the limit stuff
142+entry->limit_low = (uint16_t)(limit & 0xFFFF);
143+entry->limit_high = (uint8_t)((limit & 0xF0000) >> 16);
144+145+// Set up the base
146+entry->base_low = (uint16_t)(base & 0xFFFF);
147+entry->base_middle = (uint8_t)((base & 0xFF0000) >> 16);
148+entry->base_high = (uint8_t)((base & 0xFF000000) >> 24);
149+150+// Set up any flags
151+entry->limit_high |= (uint8_t)(flags);
152+entry->access = access;
153+}
154+155+void gdt_set_flat_entry(gdt_entry2_t* entry, uint8_t access, uint8_t flags) {
156+gdt_set_entry(entry, 0xFFFFF, 0, access, flags);
157+}
158+159+void gdt_activate(gdt_pointer_t* table);
160+104161void gdt_init() {
105-static gdt_entry_t gdt_entries[16] = {0};
106-static gdt_descriptor_t gdt_descriptor = {0};
162+//assert(sizeof(gdt_def3_t) == 8, "Must be exactly 8 bytes!");
163+printf("sizeof(gdt_def3_t) = %d\n", sizeof(gdt_def3_t));
164+static gdt_entry_t gdt_entries[16] = {0};
165+static gdt_pointer_t table = {0};
107166108-gdt_descriptor.table_base = (uint32_t)&gdt_entries;
109-gdt_descriptor.table_size = sizeof(gdt_entries) - 1;
167+table.table_base = (uint32_t)&gdt_entries;
168+table.table_size = sizeof(gdt_entries) - 1;
110169111170gdt_write_descriptor(&gdt_entries[0], 0, 0, 0);
171+gdt_def3_t cs_kernel_long = {
172+ .limit_low = 0xFFFF,
173+ .base_low = 0x0,
174+ .base_middle = 0x0,
175+ .accessed = 0,
176+ .readable = 1,
177+ .conforming = 0, // todo 0
178+ .is_code = 1,
179+ .belongs_to_os = 1,
180+ .dpl = 0,
181+ .present = 1,
182+ .limit_high = 0xF,
183+ .available = 0, // todo 0
184+ .long_mode = 1,
185+ .default_operand_size = 0, // must be 0
186+ .granularity = 1,
187+ .base_high = 0
188+ };
189+memcpy(&gdt_entries[1], &cs_kernel_long, sizeof(cs_kernel_long));
190+191+gdt_def3_t ds_kernel_long = {
192+ .limit_low = 0xFFFF,
193+ .base_low = 0x0,
194+ .base_middle = 0x0,
195+ .accessed = 0,
196+ .readable = 1,
197+ .conforming = 0, // todo 0 // For data segment this means expand down
198+ .is_code = 0,
199+ .belongs_to_os = 1,
200+ .dpl = 0,
201+ .present = 1,
202+ .limit_high = 0xF,
203+ .available = 0, // todo 0
204+ .long_mode = 1,
205+ .default_operand_size = 0, // must be 0
206+ .granularity = 1,
207+ .base_high = 0
208+ };
209+memcpy(&gdt_entries[2], &ds_kernel_long, sizeof(ds_kernel_long));
210+211+/*
212+Orig
213+ES =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
214+CS =0038 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
215+SS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
216+DS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
217+FS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
218+GS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
219+LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
220+TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
221+GDT= 000000000104a960 0000007f
222+223+ES =0010 0000000000000000 ffffffff 00bf9700 DPL=0 DS [EWA]
224+CS =0008 0000000000000000 ffffffff 00bf9e00 DPL=0 CS64 [CR-]
225+SS =0010 0000000000000000 ffffffff 00bf9700 DPL=0 DS [EWA]
226+DS =0010 0000000000000000 ffffffff 00bf9700 DPL=0 DS [EWA]
227+FS =0010 0000000000000000 ffffffff 00bf9700 DPL=0 DS [EWA]
228+GS =0010 0000000000000000 ffffffff 00bf9700 DPL=0 DS [EWA]
229+LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
230+TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
231+GDT= 000000000104a960 0000007f
232+233+ES =0010 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
234+CS =0008 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
235+SS =0010 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
236+DS =0010 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
237+FS =0010 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
238+GS =0010 0000000000000000 ffffffff 00af9300 DPL=0 DS [-WA]
239+LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
240+TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
241+GDT= 000000000104a960 0000007f
242+*/
243+/*
112244 gdt_write_descriptor(&gdt_entries[1], 0x00000000, 0x000FFFFF, (GDT_CODE_PL0));
113245 gdt_write_descriptor(&gdt_entries[2], 0x00000000, 0x000FFFFF, (GDT_DATA_PL0));
114246 gdt_write_descriptor(&gdt_entries[3], 0x00000000, 0x000FFFFF, (GDT_CODE_PL3));
115247 gdt_write_descriptor(&gdt_entries[4], 0x00000000, 0x000FFFFF, (GDT_DATA_PL3));
248+ */
249+250+//gdt_write_descriptor(&gdt_entries[1], 0x0, 0x000FFFFF, (GDT_CODE_R0_x64));
251+/*
252+ uint32_t flags = 0;
253+ flags |= (1 << 9); // Readable
254+ flags |= (1 << 11); // Always 1
255+ flags |= (1 << 12); // 0 = system, 1 = user. Select 1 for code/data segments
256+ flags |= (0 << 13); // Ring level (DPL)
257+ flags |= (1 << 15); // Present
258+ flags |= (1 << 21); // Long mode
259+ flags |= (0 << 22); // Default operand size; must be cleared in long mode
260+ flags |= (1 << 23); // Granularity: 4KB
261+ gdt_write_descriptor(&gdt_entries[1], 0x0, 0x000FFFFF, flags);
262+263+ flags &= ~(1 << 11); // Always 0
264+ flags &= ~(1 << 10); // Always 0
265+ flags |= (1 << 9); // Always 0
266+ gdt_write_descriptor(&gdt_entries[2], 0x0, 0x000FFFFF, flags);
267+ */
116268117-tss_init(gdt_entries, 5, 0x10, 0x00);
269+//gdt_write_descriptor(&gdt_entries[2], 0x0, 0x0FFFFFFF, (GDT_DATA_R0_x64));
270+//tss_init(gdt_entries, 5, 0x10, 0x00);
118271119-gdt_activate((uint32_t)&gdt_descriptor);
272+printf("Set GDT to %d 0x%x\n", &table, &table);
273+gdt_activate(&table);
274+//printf("Done load, do jmp\n");
275+//gdt_load_cs(SEGMENT_INDEX(1) | SEGMENT_RPL_KERNEL);
276+gdt_load_cs(0x08);
277+//gdt_load_ds(SEGMENT_INDEX(2) | SEGMENT_RPL_KERNEL);
278+gdt_load_ds(0x10);
279+ asm("cli");
280+ asm("hlt");
281+printf("Done!\n");
120282tss_activate();
121283}
122284