-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsegments.c
109 lines (92 loc) · 3.34 KB
/
segments.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "segments.h"
#include "kernel_functions.h"
#define N_GDT_ENTRIES (8192)
#define N_LDT_ENTRIES (2)
void initial_gdt()
{
gdt_entry_t *p_gdt_entries = GDT_TABLE_START_ADDR;
p_gdt_entries[0].dwords[0] = 0x0;
p_gdt_entries[0].dwords[1] = 0x0;
p_gdt_entries[1].dwords[0] = 0x0000FFFF;
p_gdt_entries[1].dwords[1] = 0x00CF9A00;
p_gdt_entries[2].dwords[0] = 0x0000FFFF;
p_gdt_entries[2].dwords[1] = 0x00CF9200;
for (int i = 3; i < N_GDT_ENTRIES; i++)
{
p_gdt_entries[i].dwords[0] = 0x0;
p_gdt_entries[i].dwords[1] = 0x0;
}
gdtr_t gdtr;
gdtr.n_entries = (N_GDT_ENTRIES << 3) - 1;
gdtr.p_start_addr = GDT_TABLE_START_ADDR;
load_gdt(gdtr);
}
int install_tss_to_gdt(unsigned int slot, void *base_addr, unsigned int limit)
{
if (slot == 0 || slot >= N_GDT_ENTRIES)
_panic(); // Out of GDT boundary
gdt_entry_t *entry = ((gdt_entry_t *)GDT_TABLE_START_ADDR) + slot;
entry->fields.base_low_word = (unsigned int)base_addr & 0xFFFF;
entry->fields.base_mid_byte = ((unsigned int)base_addr >> 16) & 0xFF;
entry->fields.base_high_byte = ((unsigned int)base_addr >> 24) & 0xFF;
entry->fields.limit_low_word = (unsigned int)limit & 0xFFFF;
entry->fields.limit_high = ((unsigned int)limit >> 16) & 0xF;
entry->fields.access.access_byte = 0x89;
entry->fields.G = 0x0;
entry->fields.DB = 0x1;
return 0;
}
int install_ldt_to_gdt(size_t slot, void *base_addr, size_t limit) {
if (slot == 0 || slot >= N_GDT_ENTRIES)
_panic(); // Out of GDT boundary
gdt_entry_t *entry = ((gdt_entry_t *)GDT_TABLE_START_ADDR) + slot;
entry->fields.base_low_word = (size_t)base_addr & 0xFFFF;
entry->fields.base_mid_byte = ((size_t)base_addr >> 16) & 0xFF;
entry->fields.base_high_byte = ((size_t)base_addr >> 24) & 0xFF;
entry->fields.limit_low_word = (size_t)limit & 0xFFFF;
entry->fields.limit_high = ((size_t)limit >> 16) & 0xF;
entry->fields.access.S = 0;
entry->fields.access.ac = 0;
entry->fields.access.rw = 1;
entry->fields.access.dc = 0;
entry->fields.access.ex = 0;
entry->fields.access.DPL = 0x3;
entry->fields.access.P = 1;
entry->fields.G = 0x0;
entry->fields.DB = 0x1;
}
int uninstall_gdt_entry(size_t slot)
{
if (slot == 0 || slot >= N_GDT_ENTRIES)
_panic(); // Out of GDT boundary
gdt_entry_t *entry = ((gdt_entry_t *)GDT_TABLE_START_ADDR) + slot;
entry->fields.access.P = 0; // Simply set present bit to 0 to mark as unpresent
return 0;
}
int install_seg_to_ldt(void *ldt_addr, size_t slot, void *base_addr, size_t limit, uint8_t is_code) {
if (slot >= N_LDT_ENTRIES)
_panic();
ldt_entry_t * entry = ((ldt_entry_t *)ldt_addr + slot);
entry->fields.base_low_word = (size_t)base_addr & 0xFFFF;
entry->fields.base_mid_byte = ((size_t)base_addr >> 16) & 0xFF;
entry->fields.base_high_byte = ((size_t)base_addr >> 24) & 0xFF;
entry->fields.limit_low_word = (size_t)limit & 0xFFFF;
entry->fields.limit_high = ((size_t)limit >> 16) & 0xF;
entry->fields.access.S = 1;
entry->fields.DB = 1;
if (is_code) {
entry->fields.access.ac = 1;
entry->fields.access.rw = 1;
entry->fields.access.dc = 0;
entry->fields.access.ex = 1;
}
else {
entry->fields.access.ac = 1;
entry->fields.access.rw = 1;
entry->fields.access.dc = 0;
entry->fields.access.ex = 0;
}
entry->fields.access.DPL = 0x3;
entry->fields.access.P = 1;
entry->fields.G = 0x0;
}