-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathgdt.c
77 lines (63 loc) · 2.66 KB
/
gdt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "gdt.h"
#include "stdint.h"
// This structure contains the value of one GDT entry.
// We use the attribute 'packed' to tell GCC not to change
// any of the alignment in the structure.
struct gdt_entry_struct
{
uint16_t limit_low; // The lower 16 bits of the limit.
uint16_t base_low; // The lower 16 bits of the base.
uint8_t base_middle; // The next 8 bits of the base.
uint8_t access; // Access flags, determine what ring this segment can be used in.
uint8_t granularity; // low 4 bits are high 4 bits of limit
uint8_t base_high; // The last 8 bits of the base.
} __attribute__((packed));
typedef struct gdt_entry_struct gdt_entry_t;
struct gdt_ptr_struct
{
uint16_t limit; // The upper 16 bits of all selector limits.
uint32_t base; // The address of the first gdt_entry_t struct.
}
__attribute__((packed));
typedef struct gdt_ptr_struct gdt_ptr_t;
// Lets us access our ASM functions from our C code.
//extern void load_gdt(uint32_t);
extern void load_gdt(gdt_ptr_t * gdt_ptr);
// Internal function prototypes.
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);
gdt_entry_t gdt_entries[5];
gdt_ptr_t gdt_ptr;
//idt_entry_t idt_entries[256];
//idt_ptr_t idt_ptr;
void init_gdt()
{
gdt_ptr.limit = (sizeof(gdt_entry_t)*5) - 1;
gdt_ptr.base = (uint32_t)&gdt_entries;
/*
Pr Priv 1 Ex DC RW Ac
0x9A == 1001 1010 == 1 00 1 1 0 1 0
0x92 == 1001 0010 == 1 00 1 0 0 1 0
0xFA == 1111 1010 == 1 11 1 1 0 1 0
0xF2 == 1111 0010 == 1 11 1 0 0 1 0
We have page-granularity and 32-bit mode
G D 0 Av
0xCF == 1100 1111 == 1 1 0 0 ~
*/
gdt_set_gate(0,0,0,0,0); //Null segment
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); //Code segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Data segment
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User mode code segment
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User mode data segment
//terminal_writestring("Flushing GDT.\n");
load_gdt(&gdt_ptr);
}
static void gdt_set_gate(int32_t entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
{
gdt_entries[entry].base_low = (base & 0xFFFF);
gdt_entries[entry].base_middle = (base >> 16) & 0xFF;
gdt_entries[entry].base_high = (base >> 24) & 0xFF;
gdt_entries[entry].limit_low = (limit & 0xFFFF);
gdt_entries[entry].granularity = (limit >> 16) & 0x0F;
gdt_entries[entry].granularity |= gran & 0xF0;
gdt_entries[entry].access = access;
}