VST Operating System 1.0 Stable
Сердце нашей операционки на C++
Загрузка...
Поиск...
Не найдено
kernel.cpp
См. документацию.
1
6
7#include <stddef.h>
8#include <stdint.h>
9
16static inline void outb(uint16_t port, uint8_t val)
17{
18 asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
19}
20
27static 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
38static inline void io_wait(void)
39{
40 outb(0x80, 0);
41}
42
49size_t strlen(const char *str)
50{
51 size_t len = 0;
52 while (str[len])
53 len++;
54 return len;
55}
56
62bool 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
78void memset(void *dest, char val, size_t count)
79{
80 char *temp = (char *)dest;
81 for (; count != 0; count--)
82 *temp++ = val;
83}
84
108
110static const size_t VGA_WIDTH = 80;
112static const size_t VGA_HEIGHT = 25;
116uint16_t *const VGA_MEMORY = (uint16_t *)0xB8000;
117
126
131{
132 terminal_row = 0;
133 terminal_column = 0;
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
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 }
166}
167
171void 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
182{
183 if (c == '\n') // если встретили энтер, прыгаем на новую строку
184 {
185 terminal_column = 0;
186 if (++terminal_row == VGA_HEIGHT)
188 return;
189 }
190
191 // рисуем символ
193
194 // двигаем координату вправо
195 if (++terminal_column == VGA_WIDTH)
196 {
197 terminal_column = 0;
198 if (++terminal_row == VGA_HEIGHT)
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
215void terminal_write(const char *data)
216{
217 for (size_t i = 0; i < strlen(data); i++)
218 terminal_putchar(data[i]);
219}
220
224void terminal_writeln(const char *data)
225{
226 terminal_write(data);
227 terminal_putchar('\n');
228}
229
235{
236 if (terminal_column == 0 && terminal_row > 0)
237 {
238 terminal_row--;
240 }
241 if (terminal_column > 0)
242 {
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
259char 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
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
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
301void 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
316char cmd_buffer[128];
318int cmd_len = 0;
319
325{
327 if (cmd_len == 0)
328 return;
329
330 // проверяем, что там ввел пользователь
331 if (strcmp(cmd_buffer, "about"))
332 {
334 terminal_writeln("-------------------------");
335 terminal_writeln(" VST Operating System Stable");
336 terminal_writeln(" FOR LEARNING ONLY");
337 terminal_writeln("-------------------------");
339 }
340 else if (strcmp(cmd_buffer, "cat"))
341 {
343 terminal_writeln(" /\\_/\\ ");
344 terminal_writeln(" ( o.o ) ");
345 terminal_writeln(" > ^ < ");
346 terminal_writeln(" / ^ \\ ");
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 {
383 }
384 else
385 {
387 terminal_write("Unknown command: ");
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
403extern "C" void kernel_main(void)
404{
405 // стартуем экран
407
408 // приветствие
410 terminal_writeln("VST Operating System");
411 terminal_writeln("Type 'help' for commands.");
412 terminal_writeln("------------------------------");
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 {
436 }
437 else if (c == '\b') // нажали бакспейс - стираем
438 {
439 if (cmd_len > 0)
440 {
442 cmd_buffer[--cmd_len] = 0;
443 }
444 }
445 else if (c > 0) // обычная буква - пишем в буфер и на экран
446 {
447 if (cmd_len < 79)
448 {
450 cmd_buffer[cmd_len++] = c;
451 cmd_buffer[cmd_len] = 0;
452 }
453 }
454 }
455 }
456 }
457}
size_t strlen(const char *str)
Считаем длину строки
Определения kernel.cpp:49
uint8_t terminal_color
Текущий цвет текста
Определения kernel.cpp:123
static uint8_t inb(uint16_t port)
Забирает байт из порта
Определения kernel.cpp:27
void terminal_putchar(char c)
Основная функция печати символа
Определения kernel.cpp:181
uint16_t *const VGA_MEMORY
Волшебный адрес VGA_MEMORY.
Определения kernel.cpp:116
void memset(void *dest, char val, size_t count)
Просто забиваем кусок памяти нужным символом
Определения kernel.cpp:78
bool strcmp(const char *s1, const char *s2)
Сравниваем две строки
Определения kernel.cpp:62
void terminal_writeln(const char *data)
Печать строки с переходом на новую
Определения kernel.cpp:224
char cmd_buffer[128]
Буфер, куда мы записываем то, что печатает юзер, пока он не нажмет энтер
Определения kernel.cpp:316
void execute_command()
Наш обработчик команд
Определения kernel.cpp:324
void cmd_reboot()
Жесткий метод перезагрузки
Определения kernel.cpp:270
uint16_t * terminal_buffer
Указатель на буфер экрана
Определения kernel.cpp:125
static void io_wait(void)
Маленькая задержка
Определения kernel.cpp:38
size_t terminal_column
Текущий столбец курсора
Определения kernel.cpp:121
void kernel_main(void)
Точка входа в ядро
Определения kernel.cpp:403
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
Вспомогательная штука, чтобы положить символ в конкретную точку экрана
Определения kernel.cpp:171
size_t terminal_row
Текущая строка курсора
Определения kernel.cpp:119
static const size_t VGA_WIDTH
Ширина текстового экрана (почти везде по дефолту 80).
Определения kernel.cpp:110
void terminal_scroll()
Скроллинг экрана
Определения kernel.cpp:151
static const size_t VGA_HEIGHT
Высота текстового экрана (почти везде по дефолту 25).
Определения kernel.cpp:112
void terminal_write(const char *data)
Просто печатаем строку целиком
Определения kernel.cpp:215
static void outb(uint16_t port, uint8_t val)
Это наши "руки" для работы с портами
Определения kernel.cpp:16
void cmd_poweroff()
Попытка выключить комп
Определения kernel.cpp:288
vga_color
Таблица цветов для VGA.
Определения kernel.cpp:90
@ VGA_COLOR_BLACK
Определения kernel.cpp:91
@ VGA_COLOR_GREEN
Определения kernel.cpp:93
@ VGA_COLOR_LIGHT_GREY
Определения kernel.cpp:98
@ VGA_COLOR_LIGHT_MAGENTA
Определения kernel.cpp:104
@ VGA_COLOR_LIGHT_GREEN
Определения kernel.cpp:101
@ VGA_COLOR_BLUE
Определения kernel.cpp:92
@ VGA_COLOR_MAGENTA
Определения kernel.cpp:96
@ VGA_COLOR_RED
Определения kernel.cpp:95
@ VGA_COLOR_LIGHT_BROWN
Определения kernel.cpp:105
@ VGA_COLOR_BROWN
Определения kernel.cpp:97
@ VGA_COLOR_WHITE
Определения kernel.cpp:106
@ VGA_COLOR_LIGHT_CYAN
Определения kernel.cpp:102
@ VGA_COLOR_LIGHT_BLUE
Определения kernel.cpp:100
@ VGA_COLOR_LIGHT_RED
Определения kernel.cpp:103
@ VGA_COLOR_CYAN
Определения kernel.cpp:94
@ VGA_COLOR_DARK_GREY
Определения kernel.cpp:99
void terminal_initialize(void)
Чистим экран при запуске и ставим курсор в начало
Определения kernel.cpp:130
char kbd_US[128]
Карта клавиш
Определения kernel.cpp:259
void terminal_backspace()
Стираем последний символ
Определения kernel.cpp:234
void cmd_led(int status)
Управление лампочками на клаве
Определения kernel.cpp:301
int cmd_len
Длина текущей введенной команды
Определения kernel.cpp:318