-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkernel.c
More file actions
175 lines (139 loc) · 3.89 KB
/
kernel.c
File metadata and controls
175 lines (139 loc) · 3.89 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
/************/
/* kernel.c */
/************/
#include "./keyboard_map.h"
#include "./utils.h"
#define VIDEO_LINES 25
#define VIDEO_COLUMNS_IN_LINE 80
#define VIDEO_ELEMENT_SIZE_BYTE 2
#define VIDEO_SCREENSIZE_BYTE (VIDEO_ELEMENT_SIZE_BYTE * \
VIDEO_COLUMNS_IN_LINE * \
VIDEO_LINES)
#define PORT_KEYBOARD_DATA 0x60
#define PORT_KEYBOARD_STATUS 0x64
#define IDT_SIZE 256
#define INTERRUPT_GATE 0x8E
#define KERNEL_CODE_SEGMENT_OFFSET 0x08
#define ENTER_KEY_CODE 0x1C
/* external data */
/* extern UCHAR keyboard_map[128]; */
/* external funtions */
extern void keyboard_handler(void);
extern char read_port(USHORT port);
extern void write_port(USHORT port, UCHAR data);
extern void load_idt(ULONG *idt_ptr);
struct IDT_entry {
USHORT offset_lowerbits;
USHORT selector;
UCHAR zero;
UCHAR type_attr;
USHORT offset_higherbits;
};
struct IDT_entry IDT[IDT_SIZE];
volatile char *vidptr = (char*) 0xb8000; // video memory begins at 0xb8000
UINT current_loc = 0; // cursor location
void idt_init(void)
{
ULONG keyboard_address;
ULONG idt_address;
ULONG idt_ptr[2];
/* populate IDT's entry of keyboard's interrupt */
keyboard_address = (ULONG) keyboard_handler;
IDT[0x21].offset_lowerbits = keyboard_address & 0xFFFF;
IDT[0x21].selector = KERNEL_CODE_SEGMENT_OFFSET;
IDT[0x21].zero = 0;
IDT[0x21].type_attr = INTERRUPT_GATE;
IDT[0x21].offset_higherbits = (keyboard_address & 0xFFFF0000) >> 16;
/*************************/
/* Ports */
/* PIC1 PIC2 */
/* Command 0x20 0xA0 */
/* Data 0x21 0xA1 */
/*************************/
/* ICW1 - begin initalization */
write_port(0x20, 0x11);
write_port(0xA0, 0x11);
/******************************************************/
/* In x86 protected mode, we have to remap the PICs */
/* beyond 0x20 because Intel decided to designate the */
/* first 32 interrupts as reserved for cpu exceptions */
/******************************************************/
/* ICW2 - remap offset address of IDT */
write_port(0x21, 0x20);
write_port(0xA1, 0x28);
/* ICW3 - setup cascading */
write_port(0x21, 0x00);
write_port(0xA1, 0x00);
/* ICW4 - environment info */
write_port(0x21, 0x01);
write_port(0xA1, 0x01);
/* Done initializaing */
/* mask interrupts */
write_port(0x21, 0xFF);
write_port(0xA1, 0xFF);
/* fill the IDT descriptor */
idt_address = (ULONG) IDT;
/* pointer = size + offset */
idt_ptr[0] = (sizeof(struct IDT_entry) * IDT_SIZE) + ((idt_address & 0xFFFF) << 16);
idt_ptr[1] = idt_address >> 16;
load_idt(idt_ptr);
}
void kb_init(void)
{
/* 0xFD enables IRQ1 only (the keyboard) */
write_port(0x21, 0xFD);
}
void kprint(const char str[])
{
for (UINT i = 0; str[i] != '\0'; i++) {
vidptr[current_loc++] = str[i]; // set foreground to str[i] glyph
vidptr[current_loc++] = 0x07; // set background to black
}
}
void kprint_newline(void)
{
UINT line_size = VIDEO_ELEMENT_SIZE_BYTE * VIDEO_COLUMNS_IN_LINE;
current_loc += line_size - current_loc % line_size;
}
void clear_screen(void)
{
UINT i = 0;
while (i < VIDEO_SCREENSIZE_BYTE) {
vidptr[i++] = ' ';
vidptr[i++] = 0x07;
}
}
void keyboard_handler_main(void)
{
UCHAR status;
char keycode;
/* write EOI */
write_port(0x20, 0x20);
status = read_port(PORT_KEYBOARD_STATUS);
/* LSB of status will be set if buffer isn't empty */
if (status & 0x01) {
keycode = read_port(PORT_KEYBOARD_DATA);
if (keycode < 0)
return ;
if (keycode == ENTER_KEY_CODE) {
kprint_newline();
return ;
}
vidptr[current_loc++] = keyboard_map[(UCHAR) keycode];
/* vidptr[current_loc++] = 'a'; */
vidptr[current_loc++] = 0x07;
}
}
void kmain(void)
{
const char *str = "got gud";
clear_screen();
kprint(str);
kprint_newline();
kprint_newline();
idt_init();
kb_init();
for(;;);
/* TODO: dump whole memory using gdb and compare */
return ;
}