VST Operating System
1.0 Stable
Сердце нашей операционки на C++
Загрузка...
Поиск...
Не найдено
kernel.cpp
См. документацию.
1
6
7
#include <stddef.h>
8
#include <stdint.h>
9
16
static
inline
void
outb
(uint16_t port, uint8_t val)
17
{
18
asm
volatile
(
"outb %0, %1"
: :
"a"
(val),
"Nd"
(port));
19
}
20
27
static
inline
uint8_t
inb
(uint16_t port)
28
{
29
uint8_t ret;
30
asm
volatile
(
"inb %1, %0"
:
"=a"
(ret) :
"Nd"
(port));
31
return
ret;
32
}
33
38
static
inline
void
io_wait
(
void
)
39
{
40
outb
(0x80, 0);
41
}
42
49
size_t
strlen
(
const
char
*str)
50
{
51
size_t
len = 0;
52
while
(str[len])
53
len++;
54
return
len;
55
}
56
62
bool
strcmp
(
const
char
*s1,
const
char
*s2)
63
{
64
while
(*s1 && (*s1 == *s2))
65
{
66
s1++;
67
s2++;
68
}
69
return
*s1 == *s2;
70
}
71
78
void
memset
(
void
*dest,
char
val,
size_t
count)
79
{
80
char
*temp = (
char
*)dest;
81
for
(; count != 0; count--)
82
*temp++ = val;
83
}
84
89
enum
vga_color
90
{
91
VGA_COLOR_BLACK
= 0,
92
VGA_COLOR_BLUE
= 1,
93
VGA_COLOR_GREEN
= 2,
94
VGA_COLOR_CYAN
= 3,
95
VGA_COLOR_RED
= 4,
96
VGA_COLOR_MAGENTA
= 5,
97
VGA_COLOR_BROWN
= 6,
98
VGA_COLOR_LIGHT_GREY
= 7,
99
VGA_COLOR_DARK_GREY
= 8,
100
VGA_COLOR_LIGHT_BLUE
= 9,
101
VGA_COLOR_LIGHT_GREEN
= 10,
102
VGA_COLOR_LIGHT_CYAN
= 11,
103
VGA_COLOR_LIGHT_RED
= 12,
104
VGA_COLOR_LIGHT_MAGENTA
= 13,
105
VGA_COLOR_LIGHT_BROWN
= 14,
106
VGA_COLOR_WHITE
= 15,
107
};
108
110
static
const
size_t
VGA_WIDTH
= 80;
112
static
const
size_t
VGA_HEIGHT
= 25;
116
uint16_t *
const
VGA_MEMORY
= (uint16_t *)0xB8000;
117
119
size_t
terminal_row
;
121
size_t
terminal_column
;
123
uint8_t
terminal_color
;
125
uint16_t *
terminal_buffer
;
126
130
void
terminal_initialize
(
void
)
131
{
132
terminal_row
= 0;
133
terminal_column
= 0;
134
terminal_color
=
VGA_COLOR_LIGHT_GREY
| (
VGA_COLOR_BLACK
<< 4);
135
terminal_buffer
=
VGA_MEMORY
;
136
for
(
size_t
y = 0; y <
VGA_HEIGHT
; y++)
137
{
138
for
(
size_t
x = 0; x <
VGA_WIDTH
; x++)
139
{
140
const
size_t
index = y *
VGA_WIDTH
+ x;
141
// забиваем всё пробелами
142
terminal_buffer
[index] = (uint16_t)
' '
| (uint16_t)
terminal_color
<< 8;
143
}
144
}
145
}
146
151
void
terminal_scroll
()
152
{
153
for
(
size_t
y = 0; y <
VGA_HEIGHT
- 1; y++)
154
{
155
for
(
size_t
x = 0; x <
VGA_WIDTH
; x++)
156
{
157
terminal_buffer
[y *
VGA_WIDTH
+ x] =
terminal_buffer
[(y + 1) *
VGA_WIDTH
+ x];
158
}
159
}
160
// последнюю строчку чистим
161
for
(
size_t
x = 0; x <
VGA_WIDTH
; x++)
162
{
163
terminal_buffer
[(
VGA_HEIGHT
- 1) *
VGA_WIDTH
+ x] = (uint16_t)
' '
| (uint16_t)
terminal_color
<< 8;
164
}
165
terminal_row
=
VGA_HEIGHT
- 1;
166
}
167
171
void
terminal_putentryat
(
char
c, uint8_t color,
size_t
x,
size_t
y)
172
{
173
const
size_t
index = y *
VGA_WIDTH
+ x;
174
terminal_buffer
[index] = (uint16_t)c | (uint16_t)color << 8;
175
}
176
181
void
terminal_putchar
(
char
c)
182
{
183
if
(c ==
'\n'
)
// если встретили энтер, прыгаем на новую строку
184
{
185
terminal_column
= 0;
186
if
(++
terminal_row
==
VGA_HEIGHT
)
187
terminal_scroll
();
188
return
;
189
}
190
191
// рисуем символ
192
terminal_putentryat
(c,
terminal_color
,
terminal_column
,
terminal_row
);
193
194
// двигаем координату вправо
195
if
(++
terminal_column
==
VGA_WIDTH
)
196
{
197
terminal_column
= 0;
198
if
(++
terminal_row
==
VGA_HEIGHT
)
199
terminal_scroll
();
200
}
201
205
uint16_t pos =
terminal_row
*
VGA_WIDTH
+
terminal_column
;
206
outb
(0x3D4, 0x0F);
207
outb
(0x3D5, (uint8_t)(pos & 0xFF));
208
outb
(0x3D4, 0x0E);
209
outb
(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
210
}
211
215
void
terminal_write
(
const
char
*data)
216
{
217
for
(
size_t
i = 0; i <
strlen
(data); i++)
218
terminal_putchar
(data[i]);
219
}
220
224
void
terminal_writeln
(
const
char
*data)
225
{
226
terminal_write
(data);
227
terminal_putchar
(
'\n'
);
228
}
229
234
void
terminal_backspace
()
235
{
236
if
(
terminal_column
== 0 &&
terminal_row
> 0)
237
{
238
terminal_row
--;
239
terminal_column
=
VGA_WIDTH
;
240
}
241
if
(
terminal_column
> 0)
242
{
243
terminal_column
--;
244
terminal_putentryat
(
' '
,
terminal_color
,
terminal_column
,
terminal_row
);
245
246
// не забываем вернуть мигающий курсор назад
247
uint16_t pos =
terminal_row
*
VGA_WIDTH
+
terminal_column
;
248
outb
(0x3D4, 0x0F);
249
outb
(0x3D5, (uint8_t)(pos & 0xFF));
250
outb
(0x3D4, 0x0E);
251
outb
(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
252
}
253
}
254
259
char
kbd_US
[128] = {
260
0, 27,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'0'
,
'-'
,
'='
,
'\b'
,
261
'\t'
,
'q'
,
'w'
,
'e'
,
'r'
,
't'
,
'y'
,
'u'
,
'i'
,
'o'
,
'p'
,
'['
,
']'
,
'\n'
,
262
0,
'a'
,
's'
,
'd'
,
'f'
,
'g'
,
'h'
,
'j'
,
'k'
,
'l'
,
';'
,
'\''
,
'`'
, 0,
263
'\\'
,
'z'
,
'x'
,
'c'
,
'v'
,
'b'
,
'n'
,
'm'
,
','
,
'.'
,
'/'
, 0,
'*'
, 0,
' '
,
264
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'-'
, 0, 0, 0,
'+'
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
265
270
void
cmd_reboot
()
271
{
272
uint8_t temp;
273
asm
volatile
(
"cli"
);
// вырубаем прерывания, чтобы ничего не мешало
274
do
275
{
276
temp =
inb
(0x64);
// ждем, пока контроллер освободится
277
if
(temp & 1)
278
inb
(0x60);
279
}
while
(temp & 2);
280
outb
(0x64, 0xFE);
// шлем команду на ресет
281
asm
volatile
(
"hlt"
);
282
}
283
288
void
cmd_poweroff
()
289
{
290
outb
(0x604, 0x2000);
291
outb
(0xB004, 0x2000);
292
terminal_writeln
(
"ACPI Shutdown not available via Ports."
);
293
terminal_writeln
(
"Please turn off power manually."
);
294
asm
volatile
(
"hlt"
);
295
}
296
301
void
cmd_led
(
int
status)
302
{
303
while
((
inb
(0x64) & 2) != 0)
304
;
305
outb
(0x60, 0xED);
// говорим, что сейчас будем менять состояние диодов
306
307
while
((
inb
(0x64) & 2) != 0)
308
;
309
if
(status == 1)
310
outb
(0x60, 0x07);
// зажечь всё
311
else
312
outb
(0x60, 0x00);
// погасить всё
313
}
314
316
char
cmd_buffer
[128];
318
int
cmd_len
= 0;
319
324
void
execute_command
()
325
{
326
terminal_writeln
(
""
);
327
if
(
cmd_len
== 0)
328
return
;
329
330
// проверяем, что там ввел пользователь
331
if
(
strcmp
(
cmd_buffer
,
"about"
))
332
{
333
terminal_color
=
VGA_COLOR_LIGHT_CYAN
;
334
terminal_writeln
(
"-------------------------"
);
335
terminal_writeln
(
" VST Operating System Stable"
);
336
terminal_writeln
(
" FOR LEARNING ONLY"
);
337
terminal_writeln
(
"-------------------------"
);
338
terminal_color
=
VGA_COLOR_LIGHT_GREY
;
339
}
340
else
if
(
strcmp
(
cmd_buffer
,
"cat"
))
341
{
342
terminal_color
=
VGA_COLOR_LIGHT_GREEN
;
343
terminal_writeln
(
" /\\_/\\ "
);
344
terminal_writeln
(
" ( o.o ) "
);
345
terminal_writeln
(
" > ^ < "
);
346
terminal_writeln
(
" / ^ \\ "
);
347
terminal_color
=
VGA_COLOR_LIGHT_GREY
;
348
}
349
else
if
(
strcmp
(
cmd_buffer
,
"help"
))
350
{
351
terminal_writeln
(
"Available commands:"
);
352
terminal_writeln
(
" about - OS info"
);
353
terminal_writeln
(
" ascii - Show art"
);
354
terminal_writeln
(
" clear - Clear screen"
);
355
terminal_writeln
(
" led 1 - Turn ON keyboard LEDs"
);
356
terminal_writeln
(
" led 0 - Turn OFF keyboard LEDs"
);
357
terminal_writeln
(
" reboot - Restart system"
);
358
terminal_writeln
(
" power 0 - Shutdown (QEMU)"
);
359
}
360
else
if
(
strcmp
(
cmd_buffer
,
"reboot"
))
361
{
362
terminal_writeln
(
"Rebooting..."
);
363
cmd_reboot
();
364
}
365
else
if
(
strcmp
(
cmd_buffer
,
"power 0"
))
366
{
367
terminal_writeln
(
"Shutting down..."
);
368
cmd_poweroff
();
369
}
370
else
if
(
strcmp
(
cmd_buffer
,
"led 1"
))
371
{
372
cmd_led
(1);
373
terminal_writeln
(
"LEDs ON"
);
374
}
375
else
if
(
strcmp
(
cmd_buffer
,
"led 0"
))
376
{
377
cmd_led
(0);
378
terminal_writeln
(
"LEDs OFF"
);
379
}
380
else
if
(
strcmp
(
cmd_buffer
,
"clear"
))
381
{
382
terminal_initialize
();
383
}
384
else
385
{
386
terminal_color
=
VGA_COLOR_LIGHT_RED
;
387
terminal_write
(
"Unknown command: "
);
388
terminal_writeln
(
cmd_buffer
);
389
terminal_color
=
VGA_COLOR_LIGHT_GREY
;
390
}
391
392
// после выполнения чистим буфер для новой команды
393
for
(
int
i = 0; i < 128; i++)
394
cmd_buffer
[i] = 0;
395
cmd_len
= 0;
396
terminal_write
(
"> "
);
397
}
398
403
extern
"C"
void
kernel_main
(
void
)
404
{
405
// стартуем экран
406
terminal_initialize
();
407
408
// приветствие
409
terminal_color
=
VGA_COLOR_WHITE
;
410
terminal_writeln
(
"VST Operating System"
);
411
terminal_writeln
(
"Type 'help' for commands."
);
412
terminal_writeln
(
"------------------------------"
);
413
terminal_color
=
VGA_COLOR_LIGHT_GREY
;
414
terminal_write
(
"> "
);
415
416
// основной цикл, тут и живет система
417
while
(1)
418
{
419
// опрашиваем порт клавиатуры на нажатие чего либо
420
if
(
inb
(0x64) & 1)
421
{
422
uint8_t scancode =
inb
(0x60);
423
424
// если старший бит 1, значит клавишу отпустили, нам это пока не интересно
425
if
(scancode & 0x80)
426
{
427
}
428
else
429
{
430
// получаем символ из нашей таблицы
431
char
c =
kbd_US
[scancode];
432
433
if
(c ==
'\n'
)
// нажали энтер - выполняем
434
{
435
execute_command
();
436
}
437
else
if
(c ==
'\b'
)
// нажали бакспейс - стираем
438
{
439
if
(
cmd_len
> 0)
440
{
441
terminal_backspace
();
442
cmd_buffer
[--
cmd_len
] = 0;
443
}
444
}
445
else
if
(c > 0)
// обычная буква - пишем в буфер и на экран
446
{
447
if
(
cmd_len
< 79)
448
{
449
terminal_putchar
(c);
450
cmd_buffer
[
cmd_len
++] = c;
451
cmd_buffer
[
cmd_len
] = 0;
452
}
453
}
454
}
455
}
456
}
457
}
strlen
size_t strlen(const char *str)
Считаем длину строки
Определения
kernel.cpp:49
terminal_color
uint8_t terminal_color
Текущий цвет текста
Определения
kernel.cpp:123
inb
static uint8_t inb(uint16_t port)
Забирает байт из порта
Определения
kernel.cpp:27
terminal_putchar
void terminal_putchar(char c)
Основная функция печати символа
Определения
kernel.cpp:181
VGA_MEMORY
uint16_t *const VGA_MEMORY
Волшебный адрес VGA_MEMORY.
Определения
kernel.cpp:116
memset
void memset(void *dest, char val, size_t count)
Просто забиваем кусок памяти нужным символом
Определения
kernel.cpp:78
strcmp
bool strcmp(const char *s1, const char *s2)
Сравниваем две строки
Определения
kernel.cpp:62
terminal_writeln
void terminal_writeln(const char *data)
Печать строки с переходом на новую
Определения
kernel.cpp:224
cmd_buffer
char cmd_buffer[128]
Буфер, куда мы записываем то, что печатает юзер, пока он не нажмет энтер
Определения
kernel.cpp:316
execute_command
void execute_command()
Наш обработчик команд
Определения
kernel.cpp:324
cmd_reboot
void cmd_reboot()
Жесткий метод перезагрузки
Определения
kernel.cpp:270
terminal_buffer
uint16_t * terminal_buffer
Указатель на буфер экрана
Определения
kernel.cpp:125
io_wait
static void io_wait(void)
Маленькая задержка
Определения
kernel.cpp:38
terminal_column
size_t terminal_column
Текущий столбец курсора
Определения
kernel.cpp:121
kernel_main
void kernel_main(void)
Точка входа в ядро
Определения
kernel.cpp:403
terminal_putentryat
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
Вспомогательная штука, чтобы положить символ в конкретную точку экрана
Определения
kernel.cpp:171
terminal_row
size_t terminal_row
Текущая строка курсора
Определения
kernel.cpp:119
VGA_WIDTH
static const size_t VGA_WIDTH
Ширина текстового экрана (почти везде по дефолту 80).
Определения
kernel.cpp:110
terminal_scroll
void terminal_scroll()
Скроллинг экрана
Определения
kernel.cpp:151
VGA_HEIGHT
static const size_t VGA_HEIGHT
Высота текстового экрана (почти везде по дефолту 25).
Определения
kernel.cpp:112
terminal_write
void terminal_write(const char *data)
Просто печатаем строку целиком
Определения
kernel.cpp:215
outb
static void outb(uint16_t port, uint8_t val)
Это наши "руки" для работы с портами
Определения
kernel.cpp:16
cmd_poweroff
void cmd_poweroff()
Попытка выключить комп
Определения
kernel.cpp:288
vga_color
vga_color
Таблица цветов для VGA.
Определения
kernel.cpp:90
VGA_COLOR_BLACK
@ VGA_COLOR_BLACK
Определения
kernel.cpp:91
VGA_COLOR_GREEN
@ VGA_COLOR_GREEN
Определения
kernel.cpp:93
VGA_COLOR_LIGHT_GREY
@ VGA_COLOR_LIGHT_GREY
Определения
kernel.cpp:98
VGA_COLOR_LIGHT_MAGENTA
@ VGA_COLOR_LIGHT_MAGENTA
Определения
kernel.cpp:104
VGA_COLOR_LIGHT_GREEN
@ VGA_COLOR_LIGHT_GREEN
Определения
kernel.cpp:101
VGA_COLOR_BLUE
@ VGA_COLOR_BLUE
Определения
kernel.cpp:92
VGA_COLOR_MAGENTA
@ VGA_COLOR_MAGENTA
Определения
kernel.cpp:96
VGA_COLOR_RED
@ VGA_COLOR_RED
Определения
kernel.cpp:95
VGA_COLOR_LIGHT_BROWN
@ VGA_COLOR_LIGHT_BROWN
Определения
kernel.cpp:105
VGA_COLOR_BROWN
@ VGA_COLOR_BROWN
Определения
kernel.cpp:97
VGA_COLOR_WHITE
@ VGA_COLOR_WHITE
Определения
kernel.cpp:106
VGA_COLOR_LIGHT_CYAN
@ VGA_COLOR_LIGHT_CYAN
Определения
kernel.cpp:102
VGA_COLOR_LIGHT_BLUE
@ VGA_COLOR_LIGHT_BLUE
Определения
kernel.cpp:100
VGA_COLOR_LIGHT_RED
@ VGA_COLOR_LIGHT_RED
Определения
kernel.cpp:103
VGA_COLOR_CYAN
@ VGA_COLOR_CYAN
Определения
kernel.cpp:94
VGA_COLOR_DARK_GREY
@ VGA_COLOR_DARK_GREY
Определения
kernel.cpp:99
terminal_initialize
void terminal_initialize(void)
Чистим экран при запуске и ставим курсор в начало
Определения
kernel.cpp:130
kbd_US
char kbd_US[128]
Карта клавиш
Определения
kernel.cpp:259
terminal_backspace
void terminal_backspace()
Стираем последний символ
Определения
kernel.cpp:234
cmd_led
void cmd_led(int status)
Управление лампочками на клаве
Определения
kernel.cpp:301
cmd_len
int cmd_len
Длина текущей введенной команды
Определения
kernel.cpp:318
kernel.cpp
Создано системой
1.15.0