832 lines
20 KiB
C++
832 lines
20 KiB
C++
/*
|
||
as --32 -o bootsect.o bootsect.asm
|
||
ld -Ttext 0x7c00 --oformat binary -m elf_i386 -o bootsect.bin bootsect.o
|
||
g++ -ffreestanding -m32 -o kernel.o -c kernel.cpp
|
||
ld --oformat binary -Ttext 0x10000 -o kernel.bin --entry=kmain -m elf_i386 kernel.o
|
||
qemu -fda bootsect.bin -fdb kernel.bin
|
||
*/
|
||
|
||
__asm("jmp kmain");
|
||
|
||
#define NWORD 456
|
||
#define CLR 0x02
|
||
#define VIDEO_BUF_PTR (0xb8000)
|
||
#define IDT_TYPE_INTR (0x0E)
|
||
#define IDT_TYPE_TRAP (0x0F)
|
||
#define PIC1_PORT (0x20)
|
||
#define CURSOR_PORT (0x3D4)
|
||
#define VIDEO_WIDTH (80)
|
||
#define GDT_CS (0x8)
|
||
|
||
char avb_letter[27] = { 0 };
|
||
int avb_letter_cnt[26] = { 0 };
|
||
int rand = 0x12000;
|
||
const char* empty_str = " ";
|
||
int str_num = 0;
|
||
int offset = 0;
|
||
unsigned int ticks = 0;
|
||
char time_os_loaded[15] = { 0 };
|
||
unsigned short mem_h = 0;
|
||
unsigned short mem_l = 0;
|
||
|
||
char strlen(const char *str)
|
||
{
|
||
const char *s;
|
||
|
||
for (s = str; *s; ++s)
|
||
;
|
||
return (s - str);
|
||
}
|
||
|
||
char strncmp(char *s1, char* s2, int len)
|
||
{
|
||
int i = 0;
|
||
while (*s1 && *s2 && i < len)
|
||
{
|
||
if (*s1 != *s2)
|
||
{
|
||
return (*s1 - *s2);
|
||
}
|
||
s1++;
|
||
s2++;
|
||
i++;
|
||
}
|
||
if (i == len)
|
||
{
|
||
s1--;
|
||
s2--;
|
||
}
|
||
return (*s1 - *s2);
|
||
}
|
||
|
||
unsigned int kbd_scan[44] = {
|
||
0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x39, 0x0d, 0x0c, 0x35, 0x1c, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0e, 0x2a, 0xAA };
|
||
char alphabet[32] = "abcdefghijklmnopqrstuvwxyz +-/*";
|
||
bool is_shift_pressed = false;
|
||
|
||
char command[41] = { 0 };
|
||
|
||
//OBRABOTKA PRERIVANIY KLAVIATURY
|
||
//////////////////////////////////////////////////////////////////
|
||
static inline unsigned char inb(unsigned short port)
|
||
{
|
||
unsigned char data;
|
||
asm volatile ("inb %w1, %b0": "=a" (data) : "Nd" (port));
|
||
return data;
|
||
}
|
||
|
||
static inline void outb(unsigned short port, unsigned char data)
|
||
{
|
||
asm volatile ("outb %b0, %w1" : : "a" (data), "Nd" (port));
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
|
||
|
||
static inline void outw(unsigned short port, unsigned short data)
|
||
{
|
||
asm volatile ("outw %w0, %w1" : : "a" (data), "Nd" (port));
|
||
}
|
||
|
||
|
||
void get_cpu_vendor_id(char *vendor_id) {
|
||
unsigned int eax, ebx, ecx, edx;
|
||
// Выполняем инструкцию CPUID с EAX = 0 для получения Vendor ID
|
||
eax = 0;
|
||
asm volatile (
|
||
"cpuid"
|
||
: "=b"(ebx), "=d"(edx), "=c"(ecx), "=a"(eax) // Выходные операнды
|
||
: "a"(eax) // Входной операнд, EAX = 0
|
||
);
|
||
|
||
// Копируем Vendor ID в строку
|
||
*((unsigned int *)&vendor_id[0]) = ebx;
|
||
*((unsigned int *)&vendor_id[4]) = edx;
|
||
*((unsigned int *)&vendor_id[8]) = ecx;
|
||
// Добавляем нуль-терминатор
|
||
vendor_id[12] = '\0';
|
||
}
|
||
|
||
//MOVE CURSORE TO POSITION
|
||
///////////////////////////////////////////////////////////////////////
|
||
void cursor_moveto(unsigned int strnum, unsigned int pos)
|
||
{
|
||
unsigned short new_pos = (strnum * VIDEO_WIDTH) + pos;
|
||
outb(CURSOR_PORT, 0x0F);
|
||
outb(CURSOR_PORT + 1, (unsigned char)(new_pos & 0xFF));
|
||
outb(CURSOR_PORT, 0x0E);
|
||
outb(CURSOR_PORT + 1, (unsigned char)((new_pos >> 8) & 0xFF));
|
||
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
|
||
// Функция для получения времени
|
||
unsigned char get_time(unsigned char reg) {
|
||
|
||
outb(0x70, reg); // Записываем интересующий регистр в порт 0x70
|
||
return inb(0x71); // Читаем текущее значение из порта 0x71
|
||
|
||
}
|
||
|
||
|
||
void curtime(char* buffer, unsigned int buffer_size) {
|
||
unsigned char seconds = get_time(0); // Читаем секунды
|
||
unsigned char minutes = get_time(2); // Читаем минуты
|
||
unsigned char hours = get_time(4); // Читаем часы
|
||
// Преобразуем BCD в десятичный формат
|
||
seconds = (seconds & 0x0F) + ((seconds >> 4) * 10);
|
||
minutes = (minutes & 0x0F) + ((minutes >> 4) * 10);
|
||
hours = ((hours & 0x0F) + ((hours >> 4) * 10) + 3) % 24;
|
||
// Формируем строку времени
|
||
char* ptr = buffer;
|
||
// Чаcы
|
||
*ptr++ = (hours / 10) + '0';
|
||
*ptr++ = (hours % 10) + '0';
|
||
*ptr++ = ':';
|
||
// Минуты
|
||
*ptr++ = (minutes / 10) + '0';
|
||
*ptr++ = (minutes % 10) + '0';
|
||
*ptr++ = ':';
|
||
// Секунды
|
||
*ptr++ = (seconds / 10) + '0';
|
||
*ptr++ = (seconds % 10) + '0';
|
||
// Завершаем строку
|
||
*ptr++ = '\0';
|
||
}
|
||
|
||
|
||
//
|
||
void clear() {
|
||
|
||
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||
// Очищаем весь видеобуфер
|
||
for (unsigned int i = 0; i < 80 * 25; i++) {
|
||
video_buf[i * 2] = (unsigned char)' '; // Установка пробела
|
||
}
|
||
|
||
// Сбрасываем курсор на начало
|
||
str_num = 0;
|
||
offset = 0;
|
||
cursor_moveto(str_num, offset);
|
||
}
|
||
|
||
|
||
void get_str(char* ptr, int strnum)
|
||
{
|
||
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||
video_buf += 80 * 2 * strnum;
|
||
|
||
for (int i = 0; i < 40; i++, video_buf += 2)
|
||
{
|
||
ptr[i] = *video_buf;
|
||
}
|
||
}
|
||
|
||
void print_str(const char* ptr, unsigned int strnum);
|
||
|
||
void skip()
|
||
{
|
||
if (str_num != 25)
|
||
return;
|
||
char temp[41] = { 0 };
|
||
for (int i = 0; i < 24; i++)
|
||
{
|
||
get_str(temp, i + 1);
|
||
print_str(temp, i);
|
||
}
|
||
print_str(empty_str, 24);
|
||
str_num = 24;
|
||
}
|
||
|
||
void print_str(const char* ptr, unsigned int strnum)
|
||
{
|
||
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||
video_buf += 80 * 2 * strnum;
|
||
|
||
while (*ptr)
|
||
{
|
||
|
||
video_buf[0] = (unsigned char)*ptr;
|
||
video_buf[1] = CLR;
|
||
video_buf += 2;
|
||
ptr++;
|
||
}
|
||
|
||
str_num++; offset = 0;
|
||
skip();
|
||
cursor_moveto(str_num, offset);
|
||
}
|
||
|
||
void print_char(char chr)
|
||
{
|
||
unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
|
||
video_buf += 80 * 2 * str_num + offset * 2;
|
||
|
||
video_buf[0] = (unsigned char)chr;
|
||
video_buf[1] = CLR;
|
||
|
||
offset++;
|
||
cursor_moveto(str_num, offset);
|
||
}
|
||
//SHUTDOWN
|
||
////////////////////////////////////////////
|
||
void
|
||
shutdown_power_off (void)
|
||
{
|
||
const char s[] = "Shutdown";
|
||
const char *p;
|
||
|
||
str_num++;
|
||
offset = 0;
|
||
skip();
|
||
print_str("Powering off...", str_num);
|
||
outw (0xB004, 0x2000);
|
||
outw (0x604, 0x2000);
|
||
|
||
for (p = s; *p != '\0'; p++)
|
||
outb (0x8900, *p);
|
||
|
||
asm("cli");
|
||
asm("hlt");
|
||
}
|
||
///////////////////////////////////////////////
|
||
|
||
struct idt_entry
|
||
{
|
||
unsigned short base_lo;
|
||
unsigned short segm_sel;
|
||
unsigned char always0;
|
||
unsigned char flags;
|
||
unsigned short base_hi;
|
||
} __attribute__((packed));
|
||
|
||
|
||
struct idt_ptr
|
||
{
|
||
unsigned short limit;
|
||
unsigned int base;
|
||
} __attribute__((packed));
|
||
|
||
|
||
////////////////////////////////////////////////////
|
||
|
||
|
||
// Функция для преобразования ticks в строку
|
||
|
||
void uint_to_string(unsigned int num, char* str_ticks)
|
||
{
|
||
if (num == 0) {
|
||
str_ticks[0] = '0';
|
||
str_ticks[1] = '\0'; // Завершаем строку
|
||
return;
|
||
}
|
||
|
||
char buffer[9 + 1]; // +1 для завершающего нуля
|
||
int i = 0;
|
||
|
||
// Заполнение буфера цифрами в обратном порядке
|
||
while (num > 0) {
|
||
buffer[i++] = '0' + (num % 10); // Получаем последнюю цифру
|
||
num /= 10; // Убираем последнюю цифру
|
||
}
|
||
|
||
// Обратный порядок в строке
|
||
for (int j = 0; j < i; j++) {
|
||
str_ticks[j] = buffer[i - 1 - j];
|
||
}
|
||
str_ticks[i] = '\0'; // Завершаем строку
|
||
}
|
||
///////////////////////////////////////////////////
|
||
|
||
void parseTime(char* timeStr, int* hours, int* minutes, int* seconds) {
|
||
*hours = (timeStr[0] - '0') * 10 + (timeStr[1] - '0');
|
||
*minutes = (timeStr[3] - '0') * 10 + (timeStr[4] - '0');
|
||
*seconds = (timeStr[6] - '0') * 10 + (timeStr[7] - '0');
|
||
}
|
||
|
||
void formatUptime(int totalSeconds, char* buffer) {
|
||
int hours = totalSeconds / 3600;
|
||
int minutes = (totalSeconds % 3600) / 60;
|
||
int seconds = totalSeconds % 60;
|
||
|
||
char* ptr = buffer;
|
||
|
||
// Форматируем часы
|
||
if (hours > 0) {
|
||
// Преобразуем часы в строку
|
||
if (hours >= 10) {
|
||
*ptr++ = (hours / 10) + '0';
|
||
*ptr++ = (hours % 10) + '0';
|
||
}
|
||
else {
|
||
*ptr++ = hours + '0';
|
||
}
|
||
|
||
*ptr++ = ' '; // Пробел после часов
|
||
|
||
// Добавляем "hour" или "hours"
|
||
if (hours == 1) {
|
||
*ptr++ = 'h';
|
||
*ptr++ = 'o';
|
||
*ptr++ = 'u';
|
||
*ptr++ = 'r';
|
||
}
|
||
else {
|
||
*ptr++ = 'h';
|
||
*ptr++ = 'o';
|
||
*ptr++ = 'u';
|
||
*ptr++ = 'r';
|
||
*ptr++ = 's';
|
||
}
|
||
|
||
// Проверяем, нужны ли запятые
|
||
if (minutes > 0 || seconds > 0) {
|
||
*ptr++ = ',';
|
||
*ptr++ = ' ';
|
||
}
|
||
}
|
||
|
||
// Форматируем минуты
|
||
if (minutes > 0) {
|
||
// Преобразуем минуты в строку
|
||
if (minutes >= 10) {
|
||
*ptr++ = (minutes / 10) + '0';
|
||
*ptr++ = (minutes % 10) + '0';
|
||
}
|
||
else {
|
||
*ptr++ = minutes + '0';
|
||
}
|
||
|
||
*ptr++ = ' '; // Пробел после минут
|
||
|
||
// Добавляем "minute" или "minutes"
|
||
if (minutes == 1) {
|
||
*ptr++ = 'm';
|
||
*ptr++ = 'i';
|
||
*ptr++ = 'n';
|
||
*ptr++ = 'u';
|
||
*ptr++ = 't';
|
||
*ptr++ = 'e';
|
||
}
|
||
else {
|
||
*ptr++ = 'm';
|
||
*ptr++ = 'i';
|
||
*ptr++ = 'n';
|
||
*ptr++ = 'u';
|
||
*ptr++ = 't';
|
||
*ptr++ = 'e';
|
||
*ptr++ = 's';
|
||
}
|
||
|
||
// Проверяем, нужны ли запятые
|
||
if (seconds > 0) {
|
||
*ptr++ = ',';
|
||
*ptr++ = ' ';
|
||
}
|
||
}
|
||
|
||
// Форматируем секунды
|
||
if (seconds >= 10) {
|
||
*ptr++ = (seconds / 10) + '0';
|
||
*ptr++ = (seconds % 10) + '0';
|
||
}
|
||
else {
|
||
*ptr++ = seconds + '0';
|
||
}
|
||
|
||
*ptr++ = ' '; // Пробел после секунд
|
||
|
||
// Добавляем "second" или "seconds"
|
||
if (seconds == 1) {
|
||
*ptr++ = 's';
|
||
*ptr++ = 'e';
|
||
*ptr++ = 'c';
|
||
*ptr++ = 'o';
|
||
*ptr++ = 'n';
|
||
*ptr++ = 'd';
|
||
}
|
||
else {
|
||
*ptr++ = 's';
|
||
*ptr++ = 'e';
|
||
*ptr++ = 'c';
|
||
*ptr++ = 'o';
|
||
*ptr++ = 'n';
|
||
*ptr++ = 'd';
|
||
*ptr++ = 's';
|
||
}
|
||
|
||
*ptr = '\0'; // Завершаем строку
|
||
}
|
||
|
||
|
||
int calculateUptime(char* bootTime, char* currentTime, char* uptimeStr) {
|
||
int bootHours, bootMinutes, bootSeconds;
|
||
int currentHours, currentMinutes, currentSeconds;
|
||
|
||
parseTime(bootTime, &bootHours, &bootMinutes, &bootSeconds);
|
||
parseTime(currentTime, ¤tHours, ¤tMinutes, ¤tSeconds);
|
||
|
||
// Преобразуем всё в секунды
|
||
int bootTotalSeconds = bootHours * 3600 + bootMinutes * 60 + bootSeconds;
|
||
int currentTotalSeconds = currentHours * 3600 + currentMinutes * 60 + currentSeconds;
|
||
|
||
// Вычисляем общее время работы системы
|
||
int uptimeTotalSeconds = currentTotalSeconds - bootTotalSeconds;
|
||
|
||
// Если текущее время меньше времени включения (например, переход через полночь)
|
||
if (uptimeTotalSeconds < 0) {
|
||
uptimeTotalSeconds += 24 * 3600; // Добавляем 24 часа в секундах
|
||
}
|
||
|
||
formatUptime(uptimeTotalSeconds, uptimeStr);
|
||
return uptimeTotalSeconds;
|
||
}
|
||
|
||
///////////////////////////////////////////////////
|
||
|
||
void meminfo_command()
|
||
{
|
||
unsigned int size = mem_h * 64 + mem_l;
|
||
char buffer[20];
|
||
uint_to_string(size, buffer);
|
||
print_str(buffer, str_num);
|
||
print_str("Kilobytes", str_num);
|
||
}
|
||
|
||
|
||
//VYPOLNENIYE COMMAND
|
||
////////////////////////////////////////////////////
|
||
void cmd_exec() {
|
||
int command_switch = 0;
|
||
|
||
if ('\0' == strncmp(command, "info", 4))
|
||
{
|
||
command_switch = 1;
|
||
}
|
||
else if ('\0' == strncmp(command, "help", 4))
|
||
{
|
||
command_switch = 2;
|
||
}
|
||
else if ('\0' == strncmp(command, "clear ", 5))
|
||
{
|
||
command_switch = 3;
|
||
}
|
||
else if ('\0' == strncmp(command, "curtime", 7))
|
||
{
|
||
command_switch = 4;
|
||
}
|
||
else if ('\0' == strncmp(command, "shutdown", 8))
|
||
{
|
||
command_switch = 5;
|
||
}
|
||
else if ('\0' == strncmp(command, "cpuid", 5))
|
||
{
|
||
command_switch = 6;
|
||
}
|
||
else if ('\0' == strncmp(command, "ticks", 5))
|
||
{
|
||
command_switch = 7;
|
||
}
|
||
else if ('\0' == strncmp(command, "loadtime", 8))
|
||
{
|
||
command_switch = 8;
|
||
}
|
||
else if ('\0' == strncmp(command, "uptime", 6))
|
||
{
|
||
command_switch = 9;
|
||
}
|
||
else if ('\0' == strncmp(command, "meminfo", 7))
|
||
{
|
||
command_switch = 10;
|
||
}
|
||
else
|
||
{
|
||
command_switch = 0;
|
||
}
|
||
|
||
switch (command_switch) {
|
||
case 1:
|
||
{
|
||
print_str("Made by ...", str_num);
|
||
print_str("...", str_num);
|
||
print_str("with: GNU Assembler, GCC, Intel syntax", str_num);
|
||
break;
|
||
}
|
||
case 2:
|
||
{
|
||
print_str("+ info - System information", str_num);
|
||
print_str("+ help - List of supported commands", str_num);
|
||
print_str("+ clear - Clear command history", str_num);
|
||
print_str("+ ticks - ticks number since the start", str_num);
|
||
print_str("+ loadtime - The time the OS was booted", str_num);
|
||
print_str("+ curtime - Current time", str_num);
|
||
print_str("+ uptime - Uptime in a readable format", str_num);
|
||
print_str("+ meminfo - Inf about available memory", str_num);
|
||
print_str("+ cpuid - Specifies the processor model", str_num);
|
||
print_str("+ shutdown - Computer shutdown", str_num);
|
||
break;
|
||
}
|
||
case 3:
|
||
{
|
||
clear();
|
||
break;
|
||
}
|
||
case 4:
|
||
{
|
||
char time_str[50]; // Буфер для строки времени
|
||
curtime(time_str, sizeof(time_str));
|
||
print_str(time_str, str_num);
|
||
break;
|
||
}
|
||
case 5:
|
||
{
|
||
shutdown_power_off();
|
||
break;
|
||
}
|
||
case 6:
|
||
{
|
||
char vendor_id[13];
|
||
get_cpu_vendor_id(vendor_id);
|
||
print_str(vendor_id, str_num);
|
||
break;
|
||
}
|
||
case 7:
|
||
{
|
||
char str_ticks[10];
|
||
uint_to_string(ticks, str_ticks);
|
||
print_str(str_ticks, str_num);
|
||
break;
|
||
}
|
||
case 8:
|
||
{
|
||
print_str(time_os_loaded, str_num);
|
||
break;
|
||
}
|
||
case 9:
|
||
{
|
||
char currentTime[50]; // Буфер для строки времени
|
||
curtime(currentTime, sizeof(currentTime));
|
||
char uptimeStr[100]; // Буфер для строки uptime
|
||
calculateUptime(time_os_loaded, currentTime, uptimeStr);
|
||
print_str(uptimeStr, str_num);
|
||
break;
|
||
}
|
||
case 10:
|
||
{
|
||
meminfo_command();
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
print_str("wrong input", str_num);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
//NAZHATIE KLAVISH
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
void on_key(unsigned int scan_code)
|
||
{
|
||
int i;
|
||
for (i = 0; i < 43; i++)
|
||
{
|
||
if (scan_code == kbd_scan[i])
|
||
break;
|
||
}
|
||
if (i == 43)
|
||
return;
|
||
if (i >= 0 && i <= 25)
|
||
{
|
||
if (is_shift_pressed == true)
|
||
{
|
||
command[offset] = alphabet[i] - (char)0x20;
|
||
print_char(alphabet[i] - (char)0x20);
|
||
}
|
||
else
|
||
{
|
||
command[offset] = alphabet[i];
|
||
print_char(alphabet[i]);
|
||
}
|
||
}
|
||
else if (i >= 26 && i <= 29)
|
||
{
|
||
command[offset] = alphabet[i];
|
||
print_char(alphabet[i]);
|
||
}
|
||
|
||
else if (i == 30)
|
||
{
|
||
str_num++;
|
||
skip();
|
||
offset = 0;
|
||
cursor_moveto(str_num, offset);
|
||
cmd_exec();
|
||
for (int i = 0; i < 41; i++)
|
||
command[i] = '\0';
|
||
str_num++;
|
||
skip();
|
||
offset = 0;
|
||
cursor_moveto(str_num, offset);
|
||
}
|
||
|
||
else if (i >= 31 && i <= 40)
|
||
{
|
||
if (is_shift_pressed)
|
||
{
|
||
command[offset] = '*';
|
||
print_char('*');
|
||
}
|
||
else
|
||
{
|
||
char num = (char)((kbd_scan[i] - 1) % 10 + '0');
|
||
command[offset] = num - '0';
|
||
print_char(num);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (offset == 0)
|
||
return;
|
||
offset--;
|
||
command[offset] = '\0';
|
||
print_char(' ');
|
||
offset--;
|
||
cursor_moveto(str_num, offset);
|
||
}
|
||
}
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
|
||
//SCHITIVANIE POSTUPAYSHEGO SIMVOLA
|
||
//////////////////////////////////////////////////////////
|
||
void process_shift(unsigned int scan_code)
|
||
{
|
||
if (scan_code == kbd_scan[42])
|
||
{
|
||
is_shift_pressed = true;
|
||
}
|
||
else if (scan_code == kbd_scan[43])
|
||
{
|
||
is_shift_pressed = false;
|
||
}
|
||
else if (scan_code < 128 || scan_code == 0x135)
|
||
{
|
||
on_key(scan_code);
|
||
}
|
||
}
|
||
void keyb_process_keys()
|
||
{
|
||
if (inb(0x64) & 0x01)
|
||
{
|
||
unsigned int scan_code;
|
||
scan_code = (unsigned int)inb(0x60) & 0x1FF;
|
||
|
||
if (offset == 40 && scan_code != kbd_scan[30])
|
||
{
|
||
return;
|
||
}
|
||
|
||
process_shift(scan_code);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
//OBRABOTCHIK PRERIVANIY
|
||
////////////////////////////////////////////////////////////////////
|
||
void keyb_handler()
|
||
{
|
||
asm("pusha");
|
||
keyb_process_keys();
|
||
outb(PIC1_PORT, 0x20);
|
||
asm("popa; leave; iret");
|
||
}
|
||
/////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Обработчик тиков
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
|
||
void timer_handler()
|
||
{
|
||
asm("pusha");
|
||
ticks++; // Инкрементируем счетчик тиков
|
||
outb(PIC1_PORT, 0x20); // Посылаем сигнал завершения прерывания
|
||
asm("popa; leave; iret");
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
|
||
//PROCEDURA OBRABOTCHIK PRERIVANIY
|
||
/////////////////////////////////////////////////////////////////////
|
||
|
||
struct idt_entry g_idt[256];
|
||
struct idt_ptr g_idtp;
|
||
void default_interrupt_handler()
|
||
{
|
||
asm("pusha");
|
||
asm("popa; leave; iret");
|
||
}
|
||
|
||
typedef void(*interrupt_handler)();
|
||
void interrupt_reg_handler(int num, unsigned short segm_sel, unsigned short
|
||
flags, interrupt_handler hndlr)
|
||
{
|
||
unsigned int hndlr_addr = (unsigned int)hndlr;
|
||
|
||
g_idt[num].base_lo = (unsigned short)(hndlr_addr & 0xFFFF);
|
||
g_idt[num].segm_sel = segm_sel;
|
||
g_idt[num].always0 = 0;
|
||
g_idt[num].flags = flags;
|
||
g_idt[num].base_hi = (unsigned short)(hndlr_addr >> 16);
|
||
}
|
||
|
||
void keyb_init()
|
||
{
|
||
interrupt_reg_handler(0x09, GDT_CS, 0x80 | IDT_TYPE_INTR, keyb_handler);
|
||
outb(PIC1_PORT + 1, 0xFF ^ 0x02);
|
||
|
||
}
|
||
|
||
void timer_init()
|
||
{
|
||
// Регистрация обработчика прерывания
|
||
interrupt_reg_handler(8, GDT_CS, 0x80 | IDT_TYPE_INTR, timer_handler);
|
||
// segm_sel=0x8, P=1, DPL=0, Type=Intr
|
||
|
||
// Разрешение только прерываний клавиатуры от контроллера 8259
|
||
outb(PIC1_PORT + 1, 0xFF ^ 0x01); // 0xFF - все прерывания, 0x02 - бит IRQ1 (клавиатура)
|
||
// Разрешены будут только прерывания, чьи биты установлены в 0
|
||
}
|
||
|
||
|
||
void interrupt_init()
|
||
{
|
||
int i;
|
||
int idt_count = sizeof(g_idt) / sizeof(g_idt[0]);
|
||
|
||
for (i = 0; i < idt_count; i++)
|
||
interrupt_reg_handler(i, GDT_CS, 0x80 | IDT_TYPE_INTR,
|
||
default_interrupt_handler);
|
||
}
|
||
|
||
void interrupt_start()
|
||
{
|
||
int idt_count = sizeof(g_idt) / sizeof(g_idt[0]);
|
||
|
||
g_idtp.base = (unsigned int)(&g_idt[0]);
|
||
g_idtp.limit = (sizeof(struct idt_entry) * idt_count) - 1;
|
||
|
||
asm("lidt %0" : : "m" (g_idtp));
|
||
}
|
||
|
||
void interrupt_enable()
|
||
{
|
||
asm("sti");
|
||
}
|
||
|
||
void interrupt_disable()
|
||
{
|
||
asm("cli");
|
||
}
|
||
|
||
extern "C" int kmain()
|
||
{
|
||
interrupt_init();
|
||
timer_init();
|
||
interrupt_disable();
|
||
keyb_init();
|
||
interrupt_start();
|
||
interrupt_enable();
|
||
cursor_moveto(str_num, offset);
|
||
|
||
curtime(time_os_loaded, sizeof(time_os_loaded));
|
||
|
||
char m1, m2;
|
||
m1 = (*(char*)(0x3400));
|
||
m2 = (*(char*)(0x3420));
|
||
mem_l = (unsigned short)m1;
|
||
mem_h = (unsigned short)m2;
|
||
|
||
const char* hello = ".:: WELCOME TO INFO_OS ::.";
|
||
print_str(hello , str_num);
|
||
while (1)
|
||
{
|
||
outb(PIC1_PORT + 1, 0xFF ^ 0x02);
|
||
outb(PIC1_PORT + 1, 0xFF ^ 0x01);
|
||
asm("hlt");
|
||
}
|
||
|
||
return 0;
|
||
}
|