-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkernel.c
More file actions
189 lines (153 loc) · 5.14 KB
/
kernel.c
File metadata and controls
189 lines (153 loc) · 5.14 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
typedef unsigned int u32int;
typedef int s32int;
typedef unsigned short u16int;
typedef short s16int;
typedef unsigned char u8int;
typedef char s8int;
// Write len copies of val into dest.
void memset(u8int *dest, u8int val, u32int len)
{
u8int *temp = (u8int *)dest;
for ( ; len != 0; len--) *temp++ = val;
}
// A struct describing an interrupt gate.
struct idt_entry_struct
{
u16int base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
u16int sel; // Kernel segment selector.
u8int always0; // This must always be zero.
u8int flags; // More flags. See documentation.
u16int base_hi; // The upper 16 bits of the address to jump to.
} __attribute__((packed));
typedef struct idt_entry_struct idt_entry_t;
// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct
{
u16int limit;
u32int base; // The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
typedef struct registers
{
u32int ds; // Data segment selector
u32int edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
u32int int_no, err_code; // Interrupt number and error code (if applicable)
u32int eip, cs, eflags, useresp, ss; // Pushed by the processor automatically.
} registers_t;
// These extern directives let us access the addresses of our ASM ISR handlers.
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10 ();
extern void isr11 ();
extern void isr12 ();
extern void isr13 ();
extern void isr14 ();
extern void isr15 ();
extern void isr16 ();
extern void isr17 ();
extern void isr18 ();
extern void isr19 ();
extern void isr20 ();
extern void isr21 ();
extern void isr22 ();
extern void isr23 ();
extern void isr24 ();
extern void isr25 ();
extern void isr26 ();
extern void isr27 ();
extern void isr28 ();
extern void isr29 ();
extern void isr30 ();
extern void isr31();
extern void idt_flush(u32int);
#include "console.c"
void isr_handler(registers_t regs)
{
print(0, 0, "recieved interrupt: ");
// print(1, 0, regs.int_no);
print_char(1, 0, 'a' + (regs.int_no % 10));
}
idt_entry_t idt_entries[256];
idt_ptr_t idt_ptr;
static void idt_set_gate(u8int num, u32int base, u16int sel, u8int flags)
{
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
// We must uncomment the OR below when we get to using user-mode.
// It sets the interrupt gate's privilege level to 3.
idt_entries[num].flags = flags /* | 0x60 */;
}
static void init_idt()
{
idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
idt_ptr.base = (u32int)&idt_entries;
memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
idt_set_gate( 0, (u32int)isr0 , 0x08, 0x8E);
idt_set_gate( 1, (u32int)isr1 , 0x08, 0x8E);
idt_set_gate( 2, (u32int)isr2 , 0x08, 0x8E);
idt_set_gate( 3, (u32int)isr3 , 0x08, 0x8E);
idt_set_gate( 4, (u32int)isr4 , 0x08, 0x8E);
idt_set_gate( 5, (u32int)isr5 , 0x08, 0x8E);
idt_set_gate( 6, (u32int)isr6 , 0x08, 0x8E);
idt_set_gate( 7, (u32int)isr7 , 0x08, 0x8E);
idt_set_gate( 8, (u32int)isr8 , 0x08, 0x8E);
idt_set_gate( 9, (u32int)isr9 , 0x08, 0x8E);
idt_set_gate(10, (u32int)isr10, 0x08, 0x8E);
idt_set_gate(11, (u32int)isr11, 0x08, 0x8E);
idt_set_gate(12, (u32int)isr12, 0x08, 0x8E);
idt_set_gate(13, (u32int)isr13, 0x08, 0x8E);
idt_set_gate(14, (u32int)isr14, 0x08, 0x8E);
idt_set_gate(15, (u32int)isr15, 0x08, 0x8E);
idt_set_gate(16, (u32int)isr16, 0x08, 0x8E);
idt_set_gate(17, (u32int)isr17, 0x08, 0x8E);
idt_set_gate(18, (u32int)isr18, 0x08, 0x8E);
idt_set_gate(19, (u32int)isr19, 0x08, 0x8E);
idt_set_gate(20, (u32int)isr20, 0x08, 0x8E);
idt_set_gate(21, (u32int)isr21, 0x08, 0x8E);
idt_set_gate(22, (u32int)isr22, 0x08, 0x8E);
idt_set_gate(23, (u32int)isr23, 0x08, 0x8E);
idt_set_gate(24, (u32int)isr24, 0x08, 0x8E);
idt_set_gate(25, (u32int)isr25, 0x08, 0x8E);
idt_set_gate(26, (u32int)isr26, 0x08, 0x8E);
idt_set_gate(27, (u32int)isr27, 0x08, 0x8E);
idt_set_gate(28, (u32int)isr28, 0x08, 0x8E);
idt_set_gate(29, (u32int)isr29, 0x08, 0x8E);
idt_set_gate(30, (u32int)isr30, 0x08, 0x8E);
idt_set_gate(31, (u32int)isr31, 0x08, 0x8E);
idt_flush((u32int)&idt_ptr);
}
void init_descriptor_tables()
{
// Initialise the global descriptor table.
//init_gdt();
// Initialise the interrupt descriptor table.
init_idt();
}
/*
* kernel.c
*/
void print(unsigned int x, unsigned int y, char *string);
void clear();
void kmain(void)
{
init_descriptor_tables();
clear();
char *str = "my first kernel";
print(0, 0, str);
print(10, 6, str);
print(20, 8, str);
//asm volatile ("int $0x3");
//asm volatile ("int $0x4");
return;
}