-
Notifications
You must be signed in to change notification settings - Fork 0
/
Gdt.h
139 lines (117 loc) · 5.04 KB
/
Gdt.h
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#if !defined(__GDT_H)
#define __GDT_H
/*
* The desc_table, stnd_desc and gate_desc macros piece together a descriptor
* table.
*
* Example usage:
*
* desc_table(GDT, 2) {
* stnd_desc(0, 0, 0),
* stnd_desc(0, 0xfffff, (D_CODE + D_READ + D_BIG + D_BIG_LIM))
* };
*
* gate_desc(offset, selector, control) ;For gate descriptors
* stnd_desc(base, limit, control) ;For all other descriptors
*
* base is the full 32 bit base address of the segment
* limit is one less than the segment length in 1 or 4K byte units
* control the sum of all the "D_" equates which apply (for call gates, you
* also add the "parameter dword count" to flags).
*
* desc_table(symbol, size) ;Start a descriptor table
*
* symbol is the C symbol that is used for this descriptor table
* size is the amount of descriptors defined in this table
*
* The descriptor table can be accessed in the code through the symbol [symbol],
* which is defined as an array of DT_entry unions. Every DT_entry union can
* contain either a normal descriptor, gate descriptor, or some other value
* which is 64 bits in size (this could be used to store custom info in the
* dummy descriptor of the GDT, for instance.)
*
* The dummy value can be inserted like this:
*
* desc_table(GDT, 2) {
* {dummy: 0x1234567890123456},
* ...
* };
*/
/*dfjkdfls*/
/*
* Each descriptor should have exactly one of next 8 codes to define the
* type of descriptor
*/
#define D_LDT 0x200 /* LDT segment */
#define D_TASK 0x500 /* Task gate */
#define D_TSS 0x900 /* TSS */
#define D_CALL 0x0C00 /* 386 call gate */
#define D_INT 0x0E00 /* 386 interrupt gate */
#define D_TRAP 0x0F00 /* 386 trap gate */
#define D_DATA 0x1000 /* Data segment */
#define D_CODE 0x1800 /* Code segment */
/*
* Descriptors may include the following as appropriate:
*/
#define D_DPL3 0x6000 /* DPL3 or mask for DPL */
#define D_DPL2 0x4000 /* DPL2 or mask for DPL */
#define D_DPL1 0x2000 /* DPL1 or mask for DPL */
#define D_PRESENT 0x8000 /* Present */
#define D_NOT_PRESENT 0x8000 /* Not Present */
/* Note, the PRESENT bit is set by default */
/* Include NOT_PRESENT to turn it off */
/* Do not specify D_PRESENT */
/*
* Segment descriptors (not gates) may include:
*/
#define D_ACC 0x100 /* Accessed (Data or Code) */
#define D_WRITE 0x200 /* Writable (Data segments only) */
#define D_READ 0x200 /* Readable (Code segments only) */
#define D_BUSY 0x200 /* Busy (TSS only) */
#define D_EXDOWN 0x400 /* Expand down (Data segments only) */
#define D_CONFORM 0x400 /* Conforming (Code segments only) */
#define D_BIG 0x40 /* Default to 32 bit mode */
#define D_BIG_LIM 0x80 /* Limit is in 4K units */
/*
* Now we define the structures for descriptors and gates:
*/
struct x86_desc {
unsigned short limit_low; /* limit 0..15 */
unsigned short base_low; /* base 0..15 */
unsigned char base_med; /* base 16..23 */
unsigned char access; /* access byte */
unsigned int limit_high:4; /* limit 16..19 */
unsigned int granularity:4; /* granularity */
unsigned char base_high; /* base 24..31 */
} __attribute__ ((packed));
struct x86_gate {
unsigned short offset_low; /* offset 0..15 */
unsigned short selector; /* selector */
unsigned short access; /* access flags */
unsigned short offset_high; /* offset 16..31 */
} __attribute__ ((packed));
/*
* Descriptor tables are basically arrays of either standard or gate
* descriptors; The exception is the first descriptor, which is a
* 'dummy' and can be filled with anything without crashing the machine.
*
* We define the union DT_entry as a general type of entry in a descriptor
* table; It can contain a normal descriptor, a gate descriptor, or any
* 64-bit number (for defining the dummy entries, if neccessary.)
*/
inline void InitGDT();
union DT_entry {
struct x86_desc desc; /* Normal descriptor */
struct x86_gate gate; /* Gate descriptor */
unsigned long long dummy; /* Any other info */
};
/*
* Now we perform the macro magic of the day.
*/
#define desc_table(name,length) union DT_entry name[length] =
#define stnd_desc(base, limit, control) {desc: {(limit & 0xffff), (base & 0xffff), ((base >> 16) & 0xff), \
((control+D_PRESENT) >> 8), (limit >> 16), \
((control & 0xff) >> 4), (base >> 24)}}
#define gate_desc(offset, selector, control) {gate: {(offset & 0xffff), selector, \
(control+D_PRESENT), (offset >> 16) }}
#endif