├── src ├── drivers │ ├── ata │ │ ├── Makefile │ │ ├── ata.h │ │ └── ata.c │ ├── drivers.h │ ├── driver_list.h │ ├── keyboard │ │ ├── keyboard_handler.asm │ │ ├── Makefile │ │ ├── keyboard.h │ │ └── keyboard.c │ ├── devices.h │ ├── pci │ │ ├── Makefile │ │ ├── pci.h │ │ └── pci.c │ ├── display │ │ ├── Makefile │ │ ├── display.h │ │ └── display.c │ ├── driver_list.c │ ├── Makefile │ ├── drivers.c │ └── devices.c ├── libs │ ├── io.c │ ├── ata.c │ ├── time.c │ ├── io.h │ ├── ata.h │ ├── time.h │ ├── memory.h │ ├── memory.c │ ├── driver.h │ ├── string.h │ ├── asm.h │ ├── asm.asm │ ├── device.h │ ├── device.c │ └── string.c ├── kernel │ ├── gdt.h │ ├── timer.h │ ├── timer_handler.asm │ ├── kernel.h │ ├── IDT_PIC.h │ ├── timer.c │ ├── gdt.asm │ ├── kernel.c │ └── IDT_PIC.c ├── api │ ├── api_handler.asm │ ├── kernel_functions.h │ ├── api.h │ ├── kernel_functions.c │ ├── general_functions.h │ ├── userspace_if.h │ ├── api.c │ ├── userspace_if.c │ └── general_functions.c └── linker.ld ├── docs ├── programs │ └── README.md ├── api │ ├── api.pdf │ ├── README.md │ ├── syscalls.md │ ├── internal_api.md │ ├── add_api_function.md │ └── syscall_functions.md ├── os_arch.pdf ├── os_boot.pdf ├── notes │ ├── ata2.pdf │ ├── 92130pm.pdf │ ├── pciide.pdf │ ├── io_ports_table.png │ └── ata.md ├── drivers │ ├── driver_connect.pdf │ ├── driver_functionality.pdf │ ├── driver_functionality.md │ ├── README.md │ ├── function_specification.md │ ├── development.md │ ├── driver_connect.drawio │ └── driver_work.drawio ├── README.md └── os_boot.drawio ├── .gitignore ├── iso └── boot │ └── grub │ └── grub.cfg ├── CHANGELOG.md ├── programs ├── libs │ ├── io.h │ ├── syscall.S │ ├── syscall.h │ ├── io.c │ └── device.h ├── program_base.c ├── program_linker.ld ├── uptime │ └── uptime.c ├── colorama │ └── colorama.c ├── terminal │ └── terminal.c └── term2 │ └── term2.c ├── README.md └── Makefile /src/drivers/ata/Makefile: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/libs/io.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | 3 | -------------------------------------------------------------------------------- /docs/programs/README.md: -------------------------------------------------------------------------------- 1 | # Программы 2 | -------------------------------------------------------------------------------- /src/libs/ata.c: -------------------------------------------------------------------------------- 1 | #include "ata.h" 2 | 3 | -------------------------------------------------------------------------------- /src/libs/time.c: -------------------------------------------------------------------------------- 1 | #include "time.h" 2 | 3 | -------------------------------------------------------------------------------- /docs/api/api.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/api/api.pdf -------------------------------------------------------------------------------- /docs/os_arch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/os_arch.pdf -------------------------------------------------------------------------------- /docs/os_boot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/os_boot.pdf -------------------------------------------------------------------------------- /docs/notes/ata2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/notes/ata2.pdf -------------------------------------------------------------------------------- /src/libs/io.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_IO 2 | #define INCL_LIB_IO 3 | 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /docs/notes/92130pm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/notes/92130pm.pdf -------------------------------------------------------------------------------- /docs/notes/pciide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/notes/pciide.pdf -------------------------------------------------------------------------------- /src/libs/ata.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_ATA 2 | #define INCL_LIB_ATA 3 | 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/libs/time.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_TIME 2 | #define INCL_LIB_TIME 3 | 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | output/ 2 | *.elf 3 | **.kate-swp 4 | **.drawio.bkp 5 | **.drawio.dtmp 6 | **.log 7 | -------------------------------------------------------------------------------- /docs/notes/io_ports_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/notes/io_ports_table.png -------------------------------------------------------------------------------- /docs/drivers/driver_connect.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/drivers/driver_connect.pdf -------------------------------------------------------------------------------- /docs/drivers/driver_functionality.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igmunv/kosmos/HEAD/docs/drivers/driver_functionality.pdf -------------------------------------------------------------------------------- /src/kernel/gdt.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_GDT 2 | #define INCL_GDT 3 | 4 | // ASM-functions 5 | extern void gdt_init(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/drivers/drivers.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_DRIVERS 2 | #define INCL_DRIVER_DRIVERS 3 | 4 | void driver_manager(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set default=0 2 | set timeout=1 3 | 4 | menuentry "My OS" { 5 | multiboot /boot/kernel.elf 6 | boot 7 | } 8 | -------------------------------------------------------------------------------- /src/libs/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_MEMORY 2 | #define INCL_LIB_MEMORY 3 | 4 | int memcpy(void* dst, void* src, int size); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/kernel/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_PIT 2 | #define INCL_DRIVER_PIT 3 | 4 | extern unsigned int TICKS; 5 | 6 | void timer_init(); 7 | void tick_handler(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/drivers/ata/ata.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_ATA 2 | #define INCL_DRIVER_ATA 3 | 4 | extern struct dev_info; 5 | extern void* ata_funcs[]; 6 | 7 | int ata_init(struct dev_info* device); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /docs/drivers/driver_functionality.md: -------------------------------------------------------------------------------- 1 | # Работа драйверов 2 | 3 | ## Порядок работы 4 | 5 | ### Инициатор 6 | 7 | Использовать функции драйвера возможно через [API](api/) компонентам ядра, а также программам из user-space 8 | -------------------------------------------------------------------------------- /src/drivers/driver_list.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_LIST 2 | #define INCL_DRIVER_LIST 3 | 4 | #include "../libs/driver.h" 5 | 6 | extern struct driver_info drivers[]; 7 | extern const unsigned int driver_count; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/kernel/timer_handler.asm: -------------------------------------------------------------------------------- 1 | global asm_tick_handler 2 | 3 | ; C-handlers 4 | extern tick_handler 5 | 6 | section .text 7 | 8 | ; PIT interrupt handler 9 | asm_tick_handler: 10 | pusha 11 | call tick_handler ; C-handler 12 | popa 13 | iretd 14 | 15 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Документация 2 | 3 | ### 🌳 Структура документации 4 | 5 | - [API](api/) - работа и использование API ядра 6 | - [Drivers](drivers/) - работа драйверов 7 | - [OS Architecture](os_arch.pdf/) - архитектура ядра 8 | - [OS Boot](os_boot.pdf/) - запуск и инициализация ядра 9 | -------------------------------------------------------------------------------- /src/libs/memory.c: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | 3 | int memcpy(void* dst, void* src, int size){ 4 | 5 | for (int i = 0; i < size; i++){ 6 | 7 | char* src_byte = src+i; 8 | char* dst_byte = dst+i; 9 | *dst_byte = *src_byte; 10 | 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.1.2 4 | 5 | *В процессе...* 6 | 7 | ### Added 8 | 9 | ### Changed 10 | 11 | ### Fixed 12 | 13 | ## 0.1.1 14 | 15 | ### Added 16 | - Поиск устройств 17 | - Менеджер драйверов 18 | 19 | ### Changed 20 | - Новая архитектура 21 | 22 | ### Fixed 23 | -------------------------------------------------------------------------------- /src/drivers/keyboard/keyboard_handler.asm: -------------------------------------------------------------------------------- 1 | global asm_keyboard_handler 2 | 3 | ; C-handlers 4 | extern keyboard_handler 5 | 6 | section .text 7 | 8 | ; Keyboard interrupt handler 9 | asm_keyboard_handler: 10 | pusha 11 | call keyboard_handler ; C-handler 12 | popa 13 | iretd 14 | -------------------------------------------------------------------------------- /src/drivers/devices.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_DEVICES 2 | #define INCL_DRIVER_DEVICES 3 | 4 | #include "../libs/device.h" 5 | 6 | extern struct dev_info DEVICES_INFO[256]; 7 | extern unsigned int DEVICE_COUNT; 8 | 9 | void device_registration(); 10 | 11 | int device_manager(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/kernel/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL 2 | #define KERNEL 3 | 4 | extern unsigned int EXECUTE_PROGRAM; 5 | 6 | extern void _syscall(unsigned int syscall_number, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5); 7 | 8 | void kmain(void); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /programs/libs/io.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_IO 2 | #define INCL_LIB_IO 3 | 4 | 5 | void print_text(unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bckg_color, unsigned int device_index); 6 | 7 | void print(unsigned char* text); 8 | 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/drivers/pci/Makefile: -------------------------------------------------------------------------------- 1 | DRIVER_NAME = pci 2 | OBJ_DIR = ../../../output/drivers/$(DRIVER_NAME) 3 | 4 | CC = i386-elf-gcc 5 | CFLAGS = -w -ffreestanding -m32 -fno-pie -nostdlib 6 | 7 | NSM = nasm 8 | NSMFLAGS = -f elf32 9 | 10 | all: 11 | mkdir -p $(OBJ_DIR) 12 | $(CC) $(CFLAGS) -c pci.c -o $(OBJ_DIR)/pci.o 13 | -------------------------------------------------------------------------------- /src/drivers/display/Makefile: -------------------------------------------------------------------------------- 1 | DRIVER_NAME = display 2 | OBJ_DIR = ../../../output/drivers/$(DRIVER_NAME) 3 | 4 | CC = i386-elf-gcc 5 | CFLAGS = -w -ffreestanding -m32 -fno-pie -nostdlib 6 | 7 | NSM = nasm 8 | NSMFLAGS = -f elf32 9 | 10 | all: 11 | mkdir -p $(OBJ_DIR) 12 | $(CC) $(CFLAGS) -c display.c -o $(OBJ_DIR)/display.o 13 | -------------------------------------------------------------------------------- /programs/libs/syscall.S: -------------------------------------------------------------------------------- 1 | global _syscall 2 | 3 | section .text 4 | 5 | _syscall: 6 | push ebp 7 | mov ebp, esp 8 | 9 | mov eax, [ebp+8] ; syscall number 10 | mov ebx, [ebp+12] ; arg1 11 | mov ecx, [ebp+16] ; arg2 12 | mov edx, [ebp+20] ; arg3 13 | mov esi, [ebp+24] ; arg4 14 | mov edi, [ebp+28] ; arg5 15 | 16 | int 0x22 17 | 18 | pop ebp 19 | ret 20 | -------------------------------------------------------------------------------- /src/drivers/keyboard/Makefile: -------------------------------------------------------------------------------- 1 | DRIVER_NAME = keyboard 2 | OBJ_DIR = ../../../output/drivers/$(DRIVER_NAME) 3 | 4 | CC = i386-elf-gcc 5 | CFLAGS = -w -ffreestanding -m32 -fno-pie -nostdlib 6 | 7 | NSM = nasm 8 | NSMFLAGS = -f elf32 9 | 10 | all: 11 | mkdir -p $(OBJ_DIR) 12 | $(CC) $(CFLAGS) -c keyboard.c -o $(OBJ_DIR)/keyboard.o 13 | $(NSM) $(NSMFLAGS) keyboard_handler.asm -o $(OBJ_DIR)/keyboard_handler.o 14 | -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | # API 2 | 3 | - [Системные вызовы для user-space](syscalls.md) - API для программ 4 | - [Внутренние функции для kernel-space](internal_api.md) - внутренний API для компонентов ядра 5 | - [Добавление новых функций API](add_api_function.md) - добавления новых функций API для user-space и kernel-space 6 | - [Схема работы API](api.pdf) - схема работы API, продемонстрированно назначение [исходных файлов](../../src/api/) 7 | -------------------------------------------------------------------------------- /src/kernel/IDT_PIC.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_IDT_PIC 2 | #define INCL_IDT_PIC 3 | 4 | // Тип: указатель 5 | typedef void (*intr_handler)(); 6 | 7 | void interrupt_enable(); 8 | void interrupt_disable(); 9 | void PIC_remap(); 10 | void IDT_reg_handler(int number, unsigned short segm_sel, unsigned short flags, intr_handler handler); 11 | void IDT_load(); 12 | void PIC_set_mask(unsigned char master, unsigned char slave); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/api/api_handler.asm: -------------------------------------------------------------------------------- 1 | global api_asm_handler 2 | 3 | ; C-обработчик прерываний 4 | extern api_handler 5 | 6 | section .text 7 | 8 | ; Обработчик API прерываний 9 | api_asm_handler: 10 | pusha 11 | call api_handler ; C-handler 12 | mov [esp + 0], eax ; ret EAX 13 | mov [esp + 12], ebx ; ret EBX 14 | mov [esp + 4], ecx ; ret ECX 15 | mov [esp + 8], edx ; ret EDX 16 | popa 17 | iretd 18 | -------------------------------------------------------------------------------- /docs/drivers/README.md: -------------------------------------------------------------------------------- 1 | # Драйвера 2 | 3 | - [Driver Functionality](driver_functionality.md) - работа драйверов 4 | - [Driver Functionality Scheme](driver_functionality.pdf) - схема работы драйверов 5 | - [Driver Development](development.md) - разработка драйверов 6 | - [Driver Function Specification](function_specification.md) - спецификация дополнительных функций драйверов 7 | - [Connecting Drivers](driver_connect.pdf) - как происходит подключение драйверов при компиляции 8 | -------------------------------------------------------------------------------- /src/api/kernel_functions.h: -------------------------------------------------------------------------------- 1 | // Функции API только для kernel space 2 | 3 | #ifndef INCL_API_KF 4 | #define INCL_API_KF 5 | 6 | typedef void (*intr_handler)(); 7 | 8 | void _int_reg_handler(int number, unsigned short segm_sel, unsigned short flags, intr_handler handler); 9 | 10 | // value: 0 - включает, 1 - выключает 11 | void _pic_update_mask(unsigned char mst_sl, unsigned char bit, unsigned char value); 12 | 13 | void _intr_enable(); 14 | 15 | void _intr_disable(); 16 | 17 | 18 | #include "general_functions.h" 19 | #include "../drivers/pci/pci.h" 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/drivers/keyboard/keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_KEYBOARD 2 | #define INCL_DRIVER_KEYBOARD 3 | 4 | #include "../../libs/device.h" 5 | 6 | extern void* keyboard_funcs[]; 7 | void* keyboard_get_buffer(struct dev_info* device); 8 | unsigned int keyboard_get_buffer_ptr(struct dev_info* device); 9 | unsigned char keyboard_get_shift_pressed(struct dev_info* device); 10 | unsigned char keyboard_get_ctrl_pressed(struct dev_info* device); 11 | unsigned char keyboard_get_alt_pressed(struct dev_info* device); 12 | int keyboard_init(struct dev_info* device); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/api/api.h: -------------------------------------------------------------------------------- 1 | // userspace API handler 2 | 3 | #ifndef INCL_API 4 | #define INCL_API 5 | 6 | 7 | // Структура предназначенная для хранения регистров 8 | struct registers_struct { 9 | unsigned int eax; 10 | unsigned int ebx; 11 | unsigned int ecx; 12 | unsigned int edx; 13 | unsigned int esi; 14 | unsigned int edi; 15 | }; 16 | 17 | 18 | // Обработчик прерываний на ASM 19 | extern void api_asm_handler(void); 20 | 21 | // Обработчик прерываний на C 22 | void api_handler(); 23 | 24 | // Инициализация: обработчик прерывания 25 | void api_init(); 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /programs/program_base.c: -------------------------------------------------------------------------------- 1 | // Header: start 2 | volatile unsigned char _start_header[16] __attribute__((section(".start_header"))) = {'_','_','_','I','A','M','P','R','O','G','R','A','M','_','_','_'}; 3 | // Header: info 4 | volatile unsigned char _info_header[20] __attribute__((section(".info_header"))) = "terminal"; 5 | // Header: end 6 | volatile unsigned char _end_header[16] __attribute__((section(".end_header"))) = {'_','_','_','E','N','D','P','R','O','G','R','A','M','_','_','_'}; 7 | 8 | 9 | // Entry point 10 | void _start(void) __attribute__((section(".text.start"))); 11 | void _start(){ 12 | // Your code 13 | } 14 | -------------------------------------------------------------------------------- /programs/libs/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_SYSCALL 2 | #define INCL_LIB_SYSCALL 3 | 4 | #define SYS_PRINT_TEXT 0x0 5 | #define SYS_NEW_LINE 0x1 6 | #define SYS_CURSOR_UPDATE 0x2 7 | #define SYS_CLEAR_DISPLAY 0x3 8 | #define SYS_GET_CURRENT_SYMB 0x4 9 | #define SYS_DEL_CURRENT_SYMB 0x5 10 | #define SYS_GET_DISP_CURSOR_POS_X 0x106 11 | #define SYS_GET_DISP_CURSOR_POS_Y 0x107 12 | #define SYS_SET_DISP_CURSOR_POS_X 0x200 13 | #define SYS_SET_DISP_CURSOR_POS_Y 0x201 14 | 15 | 16 | extern unsigned int _syscall(unsigned int syscall_number, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5); 17 | 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /programs/program_linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | 6 | /* Заголовок начала программы */ 7 | . = 0x100000; 8 | .start_header : { 9 | *(.start_header) 10 | } 11 | .info_header : ALIGN(1) { 12 | *(.info_header) 13 | } 14 | 15 | .text : { 16 | *(.text.start) 17 | *(.text) 18 | } 19 | .rodata : { 20 | *(.rodata*) 21 | } 22 | 23 | .data : { 24 | *(.data) 25 | } 26 | 27 | .bss : { 28 | *(.bss) 29 | *(COMMON) 30 | } 31 | 32 | /* Заголовок конца программы */ 33 | .end_header : { 34 | *(.end_header) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/api/kernel_functions.c: -------------------------------------------------------------------------------- 1 | // Функции API только для kernel space 2 | 3 | #include "kernel_functions.h" 4 | #include "../kernel/IDT_PIC.h" 5 | 6 | void _int_reg_handler(int number, unsigned short segm_sel, unsigned short flags, intr_handler handler){ 7 | interrupt_disable(); 8 | IDT_reg_handler(number, segm_sel, flags, handler); 9 | IDT_load(); 10 | interrupt_enable(); 11 | } 12 | 13 | void _pic_update_mask(unsigned char mst_sl, unsigned char bit, unsigned char value){ 14 | PIC_update_mask(mst_sl, bit, value); 15 | } 16 | 17 | void _intr_enable(){ 18 | interrupt_enable(); 19 | } 20 | 21 | void _intr_disable(){ 22 | interrupt_disable(); 23 | } 24 | -------------------------------------------------------------------------------- /src/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(kmain) 2 | 3 | SECTIONS 4 | { 5 | 6 | /* Для GRUB */ 7 | .multiboot :{ 8 | *(.multiboot) 9 | } 10 | 11 | /* Основной код и данные ОС */ 12 | . = 0x10000; 13 | .text : { 14 | *(.text) 15 | } 16 | 17 | .rodata : { 18 | *(.rodata*) 19 | } 20 | 21 | .data : { 22 | *(.data) 23 | } 24 | 25 | .bss : { 26 | *(.bss) 27 | *(COMMON) 28 | } 29 | 30 | . = 0x30000; 31 | .file_system : { 32 | *(.file_system) 33 | } 34 | 35 | 36 | /* 37 | 38 | .rodata (Read-Only Data) - константы, строки и любые данные, которые НЕ ИЗМЕНЯЮТСЯ во время работы программы. 39 | .data (Initialized Data) - переменные, которым присвоено начальное значение. 40 | .bss (Uninitialized Data) - переменные без начального значение (не инициализированные или инициализированные нулём). 41 | 42 | */ 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/libs/driver.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_DRIVER 2 | #define INCL_LIB_DRIVER 3 | 4 | #define DRIVER_FUNC_COUNT 16 5 | 6 | 7 | struct driver_info { 8 | unsigned char name[16]; 9 | unsigned char filename[16]; 10 | 11 | unsigned char classcode; 12 | unsigned char subclass; 13 | 14 | void* init; 15 | void** funcs; 16 | 17 | }; 18 | 19 | 20 | enum dfunctype_virt_display_vgatext{ 21 | PRINT_TEXT, 22 | NEW_LINE, 23 | CURSOR_UPDATE, 24 | CLEAR_DISPLAY, 25 | GET_CURRENT_SYMBOL, 26 | DELETE_CURRENT_SYMBOL, 27 | GET_CURSOR_POS_X, 28 | GET_CURSOR_POS_Y, 29 | SET_CURSOR_POS_X, 30 | SET_CURSOR_POS_Y, 31 | }; 32 | 33 | enum dfunctype_virt_ps2_keyb{ 34 | GET_KEYBOARD_BUFFER, 35 | GET_KEYBOARD_BUFFER_PTR, 36 | GET_KEYBOARD_SHIFT_PRD, 37 | GET_KEYBOARD_CTRL_PRD, 38 | GET_KEYBOARD_ALT_PRD 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/drivers/driver_list.c: -------------------------------------------------------------------------------- 1 | 2 | #include "driver_list.h" 3 | #include "../libs/device.h" 4 | #include "../libs/driver.h" 5 | 6 | // - - Includes drivers - - 7 | #include "ata/ata.h" 8 | #include "display/display.h" 9 | #include "keyboard/keyboard.h" 10 | 11 | // - - Driver list - - 12 | #define DRIVER_LIST \ 13 | X(keyboard_driver, "keyboard.c", VIRT_KEYBOARD_CONTROLLER, VIRT_KEYBOARD_LDEV, keyboard_init, keyboard_funcs) \ 14 | X(display_driver, "display.c", VIRT_DISPLAY_CONTROLLER, VIRT_DISPLAY_VGATEXT, display_init, display_funcs) 15 | 16 | // - - TemplateM - - 17 | #define X(name, filename, classcode, subclass, init, funcs) { #name, filename, classcode, subclass, init, funcs }, 18 | 19 | struct driver_info drivers[] = { 20 | DRIVER_LIST 21 | }; 22 | 23 | 24 | #undef X 25 | 26 | #define X(name, filename, classcode, subclass, init, funcs) +1 27 | const unsigned int driver_count = 0 DRIVER_LIST; 28 | 29 | #undef X 30 | -------------------------------------------------------------------------------- /programs/uptime/uptime.c: -------------------------------------------------------------------------------- 1 | #include "../../libs/shared_memory.h" 2 | #include "../../libs/asm.h" 3 | #include "../../libs/string.h" 4 | #include "../../libs/io.h" 5 | #include "../../libs/time.h" 6 | 7 | // Header: start 8 | volatile unsigned char _start_header[16] __attribute__((section(".start_header"))) = {'_','_','_','I','A','M','P','R','O','G','R','A','M','_','_','_'}; 9 | // Header: info 10 | volatile unsigned char _info_header[20] __attribute__((section(".info_header"))) = "uptime"; 11 | // Header: end 12 | volatile unsigned char _end_header[16] __attribute__((section(".end_header"))) = {'_','_','_','E','N','D','P','R','O','G','R','A','M','_','_','_'}; 13 | 14 | 15 | int _start(void) __attribute__((section(".text.start"))); 16 | int _start(void){ 17 | 18 | long uptime_second = (TICKS) / 1000; 19 | unsigned char uptime_second_str[50]; 20 | itos(uptime_second, &uptime_second_str); 21 | print(uptime_second_str); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /src/drivers/Makefile: -------------------------------------------------------------------------------- 1 | # Собираем все драйверы верхнего уровня 2 | DRIVERS_SRC := $(wildcard *.c) $(wildcard *.asm) 3 | DRIVERS_OBJ := $(DRIVERS_SRC:.c=.o) 4 | DRIVERS_OBJ := $(DRIVERS_OBJ:.asm=.o) 5 | 6 | # Находим директории драйверов 7 | DRIVER_DIRS := $(filter-out .,$(wildcard */)) 8 | 9 | # Путь куда 10 | DRIVER_OUTPUT = ../../output/drivers/ 11 | 12 | CC = i386-elf-gcc 13 | CFLAGS = -w -ffreestanding -m32 -fno-pie -nostdlib 14 | 15 | NS = nasm 16 | NSFLAGS = -f elf32 17 | 18 | all: $(DRIVERS_OBJ) drivers 19 | 20 | # Сборка файлов в текущей папке 21 | %.o: %.c 22 | mkdir -p $(DRIVER_OUTPUT) 23 | $(CC) $(CFLAGS) -c $< -o $(DRIVER_OUTPUT)$@ 24 | 25 | %.o: %.asm 26 | mkdir -p $(DRIVER_OUTPUT) 27 | $(NS) $(NSFLAGS) $< -o $(DRIVER_OUTPUT)$@ 28 | 29 | # Сборка драйверов в подпапках 30 | drivers: 31 | @for dir in $(DRIVER_DIRS); do \ 32 | if [ -f $$dir/Makefile ] || [ -f $$dir/makefile ]; then \ 33 | echo "==> Building driver in $$dir"; \ 34 | $(MAKE) -C $$dir; \ 35 | else \ 36 | echo "==> Skipping $$dir (no Makefile)"; \ 37 | fi; \ 38 | done 39 | -------------------------------------------------------------------------------- /src/drivers/display/display.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_DISPLAY 2 | #define INCL_DRIVER_DISPLAY 3 | 4 | extern struct dev_info; 5 | extern void* display_funcs[]; 6 | 7 | void display_cursor_update(struct dev_info* device); 8 | 9 | void display_new_line(struct dev_info* device); 10 | 11 | void display_print_text(struct dev_info* device, unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bkgr_color); 12 | 13 | void display_clear(struct dev_info*); 14 | 15 | unsigned char display_get_current_symbol(struct dev_info* device, short offset); 16 | 17 | void display_delete_current_symbol(struct dev_info* device, short offset); 18 | 19 | unsigned char display_get_display_cursor_pos_x(struct dev_info* device); 20 | 21 | unsigned char display_get_display_cursor_pos_y(struct dev_info* device); 22 | 23 | void display_set_display_cursor_pos_x(struct dev_info* device, unsigned char x); 24 | 25 | void display_set_display_cursor_pos_y(struct dev_info* device, unsigned char y); 26 | 27 | int display_init(struct dev_info* device); 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/kernel/timer.c: -------------------------------------------------------------------------------- 1 | #define PIT_CMD 0x43 2 | #define PIT_CH0 0x40 3 | #define PIT_INPUT_FREQ 1193182UL 4 | 5 | #include "timer.h" 6 | #include "../api/kernel_functions.h" 7 | 8 | extern void asm_tick_handler(); 9 | 10 | unsigned int TICKS = 0; 11 | 12 | // Инициализация таймера PIT 13 | void PIT_init(unsigned int freq_hz) { 14 | 15 | // Выставляем заданную в freq_hz частоту (количество тиков в секунду) 16 | 17 | unsigned int divisor = (unsigned int)(PIT_INPUT_FREQ / freq_hz); // 1193182 / freq 18 | unsigned char lo = divisor & 0xFF; 19 | unsigned char hi = (divisor >> 8) & 0xFF; 20 | 21 | // Mode 3 (square wave), access lobyte/hibyte, channel 0 22 | outb(PIT_CMD, 0x36); 23 | 24 | // write divisor low then high 25 | outb(PIT_CH0, lo); 26 | outb(PIT_CH0, hi); 27 | } 28 | 29 | // Обработчик прерывания PIT 30 | void tick_handler(){ 31 | TICKS++; 32 | outb(0x20, 0x20); 33 | } 34 | 35 | void timer_init(){ 36 | PIT_init(1000); 37 | _intr_disable(); 38 | _pic_update_mask(0, 0, 0); 39 | _int_reg_handler(32, 0x08, 0x80 | 0x0E, asm_tick_handler); 40 | _intr_enable(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /programs/colorama/colorama.c: -------------------------------------------------------------------------------- 1 | #include "../../libs/io.h" 2 | #include "../../libs/time.h" 3 | #include "../../libs/shared_memory.h" 4 | 5 | // Header: start 6 | volatile unsigned char _start_header[16] __attribute__((section(".start_header"))) = {'_','_','_','I','A','M','P','R','O','G','R','A','M','_','_','_'}; 7 | // Header: info 8 | volatile unsigned char _info_header[20] __attribute__((section(".info_header"))) = "colorama"; 9 | // Header: end 10 | volatile unsigned char _end_header[16] __attribute__((section(".end_header"))) = {'_','_','_','E','N','D','P','R','O','G','R','A','M','_','_','_'}; 11 | 12 | 13 | // Entry point 14 | void _start(void) __attribute__((section(".text.start"))); 15 | void _start(){ 16 | 17 | int color = 0; 18 | int bcolor = 7; 19 | for (int i = 33; i <= 126; i++){ 20 | char text[2]; 21 | text[0] = (unsigned char)i; 22 | text[1] = '\0'; 23 | io_printx(text, DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, color, bcolor); 24 | color = (color+1)%14; 25 | bcolor = (bcolor+1)%14; 26 | sleep(50); 27 | } 28 | io_printx("\n", DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, 0, 0); 29 | color = (color+1)%14; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/kernel/gdt.asm: -------------------------------------------------------------------------------- 1 | global gdt_init 2 | 3 | section .data 4 | 5 | ; Структура gdt: 6 | ; 0: NULL 7 | ; 1: Кодовый сегмент (привилегии 0) 8 | ; 2: Данные (привилегии 0) 9 | 10 | gdt: 11 | ; Нулевой дескриптор (не используется): Index = 0 12 | dd 0x00000000 13 | dd 0x00000000 14 | ; Сегмент кода (для привилегий 0, 32-битный): Index = 1 15 | dd 0x0000FFFF 16 | dd 0x00CF9A00 17 | ; Сегмент данных (для привилегий 0, 32-битный): Index = 2 18 | dd 0x0000FFFF 19 | dd 0x00CF9200 20 | 21 | 22 | gdt_info: 23 | dw gdt_info - gdt - 1 ; Размер GDT (должен быть на 1 меньше) 24 | dd gdt ; Адрес GDT (32-битный) 25 | 26 | 27 | section .text 28 | 29 | 30 | gdt_init: 31 | lgdt [gdt_info] ; Загружаем GDT 32 | 33 | ; Перезагружаем сегментные регистры 34 | mov ax, 0x10 ; Селектор сегмента данных (просто математика: 2 << 3 = 0x10 - 2 это индекс) 35 | mov ds, ax 36 | mov es, ax 37 | mov fs, ax 38 | mov gs, ax 39 | mov ss, ax 40 | 41 | ; Делаем дальний прыжок для обновления CS 42 | jmp 0x08:.reload_cs ; 0x08 - селектор кода (просто математика: 1 << 3 = 0x08 - 1 это индекс) 43 | 44 | 45 | .reload_cs: 46 | ret 47 | -------------------------------------------------------------------------------- /src/libs/string.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_STRING 2 | #define INCL_LIB_STRING 3 | 4 | 5 | // Разделенный байт на: Младшие 4 бита и Старшие 4 бита 6 | struct byte_split_struct{ 7 | char low; 8 | char high; 9 | }; 10 | 11 | 12 | // Перевернуть строку 13 | void string_turn_over(unsigned char* string, short size, unsigned char* result); 14 | 15 | // Int to string. Число в строку 16 | int itos(long i, unsigned char* ret); 17 | 18 | // Проверка строки на то, является ли она числом 19 | char is_digit(char* string); 20 | 21 | // Получить размер строки 22 | int strlen(char* string); 23 | 24 | // Сравнение строк. Если одинаковые то 1, если разные то 0 25 | char is_str_equally(unsigned char* str1, unsigned char* str2); 26 | 27 | // String to int. Строку в число 28 | int stoi(char* string, int* result); 29 | 30 | // Byte to hex. Байт в HEX строку (16-чный вид, строка) 31 | void btox(char byte, struct byte_split_struct* result); 32 | 33 | // Pointer to hex. Адрес в HEX строку (16-чный вид, строка) 34 | void ptox(void* ptr, unsigned char* result); 35 | 36 | // Возвращает символ ASCII по таблице исходя из скан-кода клавиши 37 | char scancode_to_ascii(unsigned char scancode, unsigned char shift_state); 38 | 39 | // Является ли сканкод символом 40 | int is_symbol_scancode(unsigned char scancode); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/kernel/kernel.c: -------------------------------------------------------------------------------- 1 | // GRUB header 2 | __attribute__((section(".multiboot"))) 3 | const unsigned int multiboot_header[] = { 4 | 0x1BADB002, 5 | 0, 6 | -(0x1BADB002) 7 | }; 8 | 9 | #include "kernel.h" 10 | #include "timer.h" 11 | 12 | // Kernel 13 | #include "gdt.h" 14 | #include "IDT_PIC.h" 15 | 16 | // api 17 | #include "../api/api.h" 18 | #include "../api/kernel_functions.h" 19 | 20 | #include "../libs/device.h" 21 | 22 | 23 | #include "../libs/asm.h" 24 | 25 | 26 | unsigned int EXECUTE_PROGRAM = 0; 27 | 28 | // Loop 29 | __attribute__((section(".kernel_loop"))) void kernel_loop(void) { 30 | while(1) 31 | { 32 | if (EXECUTE_PROGRAM == 0){ 33 | 34 | } 35 | 36 | else{ 37 | 38 | EXECUTE_PROGRAM = 0; 39 | } 40 | } 41 | } 42 | 43 | 44 | void test(){ 45 | struct dev_info* devs = (struct dev_info*)_get_device_info(); 46 | for (unsigned int dev = 0; dev < _get_device_count(); dev++){ 47 | if (devs[dev].classcode == VIRT_DISPLAY_CONTROLLER && devs[dev].subclass == VIRT_DISPLAY_VGATEXT){ 48 | 49 | unsigned char* text = "test"; 50 | unsigned int size = 4; 51 | _print_text(text, size, 15, 2, 7, 0, dev); 52 | 53 | } 54 | } 55 | } 56 | 57 | // Main 58 | void kmain(void){ 59 | 60 | // GDT table init 61 | gdt_init(); 62 | 63 | // Remap interrupts 64 | PIC_remap(); 65 | 66 | // Init PIT, timers 67 | timer_init(); 68 | 69 | // Init API 70 | api_init(); 71 | 72 | device_manager(); 73 | 74 | driver_manager(); 75 | 76 | // test(); 77 | 78 | // Endless loop 79 | kernel_loop(); 80 | } 81 | -------------------------------------------------------------------------------- /programs/libs/io.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | #include "syscall.h" 3 | #include "device.h" 4 | 5 | 6 | unsigned int get_default_output_device(){ 7 | struct dev_info* devs = (struct dev_info*)_syscall(0x10A, 0, 0, 0, 0, 0); 8 | unsigned int dev_count = _syscall(0x109, 0, 0, 0, 0, 0); 9 | for (unsigned int dev = 0; dev < dev_count; dev++){ 10 | if (devs[dev].classcode == VIRT_DISPLAY_CONTROLLER && devs[dev].subclass == VIRT_DISPLAY_VGATEXT){ 11 | return dev; 12 | } 13 | } 14 | } 15 | 16 | void print_text(unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bckg_color, unsigned int device_index){ 17 | _syscall( 18 | SYS_PRINT_TEXT, 19 | text, 20 | size, 21 | (unsigned int)((x & 0xff) | ((y & 0xff) << 8)), 22 | (unsigned int)((font_color & 0xff) | ((bckg_color & 0xff) << 8)), 23 | device_index); 24 | } 25 | 26 | void print(unsigned char* text){ 27 | // принимает строку с `\0` в конце 28 | unsigned int size; 29 | for (unsigned int i = 0; i < 2000; i++){ 30 | if (text[i] == '\0'){ 31 | size = i; 32 | break; 33 | } 34 | } 35 | if (size > 0){ 36 | 37 | unsigned int device_index = get_default_output_device(); 38 | unsigned char x = _syscall(SYS_GET_DISP_CURSOR_POS_X, device_index, 0, 0, 0, 0); 39 | unsigned char y = _syscall(SYS_GET_DISP_CURSOR_POS_Y, device_index, 0, 0, 0, 0); 40 | 41 | print_text(text, size, x, y, 7, 0, device_index); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KOSM OS 2 | **K**inetic **O**pen **S**tructure **M**inimal **O**peration **S**ystem — *динамичная, открытая, структурированная, минималистичная операционная система, написанная на C + ASM* 3 | 4 | **Текущая версия:** `0.1.1` 5 | 6 | **[🕒 Список изменений](CHANGELOG.md)** 7 | 8 | **📄 [Документация](docs/README.md)** 9 | 10 | ## ⚡️ Основные возможности 11 | - Загрузчик GRUB 12 | - Счётчик тиков 13 | - Регистрация и обработка прерываний 14 | - API через системные вызовы 15 | - Удобное добавление драйверов 16 | - Драйвер PCI 17 | - Поиск и идентификация устройств 18 | - Поиск подходящего драйвера для устройства 19 | 20 | ## 🌳 Структура проекта 21 | - [src/](src/) - 22 | здесь хранится исходный код ОС 23 | - [src/api/](src/api/) - 24 | API 25 | - [src/drivers/](src/drivers/) - 26 | драйвера 27 | - [src/kernel/](src/kernel/) - 28 | точка входа, инструменты ядра 29 | - [src/libs/](src/libs/) - 30 | вспомогательные библиотеки 31 | 32 | - [programs/](programs/) - 33 | исходный код программ ОС 34 | 35 | - [docs/](docs/) - 36 | документация 37 | 38 | - [iso/](iso/) - 39 | здесь хранится конфигурация для загрузчика GRUB 40 | 41 | ## 🚀 Как запустить ОС 42 | 1. Установка зависимостей: `make nasm xorriso qemu-system` 43 | 2. Скачивание компилятора: [i386-elf-7.5.0-Linux-x86_64.tar.xz](https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz) 44 | 3. Распаковка скачанного архива: `tar -xf toolchain/dists/i386-elf*.tar.xz` 45 | 4. Добавить путь до распакованного компилятора в PATH: `export PATH=$PATH:<ПУТЬ_ДО_КОМПИЛЯТОРА>/i386-elf*/bin/` 46 | 5. Перезайти в сессию 47 | 6. Компиляция ядра и запуск: `make` (в корне проекта) 48 | -------------------------------------------------------------------------------- /src/api/general_functions.h: -------------------------------------------------------------------------------- 1 | // Общие функции API 2 | 3 | #ifndef INCL_API_GENFUNC 4 | #define INCL_API_GENFUNC 5 | 6 | void _print_text(unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bkgr_color, unsigned int device_index); 7 | 8 | void _new_line(unsigned int device_index); 9 | 10 | void _cursor_update(unsigned int device_index); 11 | 12 | void _clear_display(unsigned int device_index); 13 | 14 | unsigned char _get_current_symbol(unsigned int offset, unsigned int device_index); 15 | 16 | unsigned char _delete_current_symbol(unsigned int offset, unsigned int device_index); 17 | 18 | unsigned char _get_display_cursor_pos_x(unsigned int device_index); 19 | 20 | unsigned char _get_display_cursor_pos_y(unsigned int device_index); 21 | 22 | void _set_display_cursor_pos_x(unsigned char x, unsigned int device_index); 23 | 24 | void _set_display_cursor_pos_y(unsigned char y, unsigned int device_index); 25 | 26 | unsigned char _read_sector(unsigned int device_index, unsigned int lba, void* dst); 27 | 28 | unsigned char _write_sector(unsigned int device_index, unsigned int lba, void* src); 29 | 30 | void _execute_program(unsigned int program); 31 | 32 | unsigned int _get_execute_program(); 33 | 34 | void* _get_keyboard_buffer(unsigned int device_index); 35 | 36 | unsigned int _get_keyboard_buffer_ptr(unsigned int device_index); 37 | 38 | unsigned char _get_keyboard_shift_pressed(unsigned int device_index); 39 | 40 | unsigned char _get_keyboard_ctrl_pressed(unsigned int device_index); 41 | 42 | unsigned char _get_keyboard_alt_pressed(unsigned int device_index); 43 | 44 | unsigned int _get_ticks(); 45 | 46 | unsigned int _get_device_count(); 47 | 48 | void* _get_device_info(); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/drivers/pci/pci.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_DRIVER_PCI 2 | #define INCL_DRIVER_PCI 3 | 4 | #define CONFIG_ADDRESS 0xCF8 5 | #define CONFIG_DATA 0xCFC 6 | 7 | 8 | struct pci_command_register { 9 | char io_space; 10 | char memory_space; 11 | char bus_master; 12 | char special_cycles; 13 | char mem_wr_and_inv_en; 14 | char vga_pal_sn; 15 | char par_err_resp; 16 | char serr_enable; 17 | char fast_bk_to_bk_en; 18 | char int_disable; 19 | }; 20 | 21 | struct pci_status_register { 22 | char int_status; 23 | char capb_list; 24 | char _66mhz_cap; 25 | char fast_bk_to_bk_cap; 26 | char mast_dt_par_err; 27 | char devsel_timing; 28 | char sign_targ_abort; 29 | char received_targ_abort; 30 | char received_mast_abort; 31 | char sign_sys_err; 32 | char detect_par_err; 33 | }; 34 | 35 | struct pci_common_header{ 36 | unsigned short vendor_id; 37 | unsigned short device_id; 38 | unsigned short command; 39 | unsigned short status; 40 | unsigned char revision_id; 41 | unsigned char prog_if; 42 | unsigned char subclass; 43 | unsigned char classcode; 44 | unsigned char cache_line_size; 45 | unsigned char latency_timer; 46 | unsigned char mf; 47 | unsigned char header_type; 48 | unsigned char bist; 49 | }; 50 | 51 | struct pci_header_0{ 52 | struct pci_common_header common_header; 53 | unsigned int bar0; 54 | unsigned int bar1; 55 | unsigned int bar2; 56 | unsigned int bar3; 57 | unsigned int bar4; 58 | unsigned int bar5; 59 | }; 60 | 61 | 62 | unsigned short pci_config_read_word(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset); 63 | 64 | unsigned int pci_config_read_dword(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset); 65 | 66 | void pci_config_write_word(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset, unsigned short word); 67 | 68 | struct pci_command_register pci_config_get_command(unsigned int bus, unsigned int dev, unsigned int func); 69 | 70 | struct pci_status_register pci_config_get_status(unsigned int bus, unsigned int dev, unsigned int func); 71 | 72 | void pci_config_set_command(unsigned int bus, unsigned int dev, unsigned int func, struct pci_command_register cmd); 73 | 74 | void pci_find_devices(); 75 | 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/api/userspace_if.h: -------------------------------------------------------------------------------- 1 | // Интерфейс API функций для userspace 2 | 3 | #ifndef INCL_API_USIF 4 | #define INCL_API_USIF 5 | 6 | void sys_print_text(struct registers_struct* args, struct registers_struct* result); 7 | 8 | void sys_new_line(struct registers_struct* args, struct registers_struct* result); 9 | 10 | void sys_cursor_update(struct registers_struct* args, struct registers_struct* result); 11 | 12 | void sys_clear_display(struct registers_struct* args, struct registers_struct* result); 13 | 14 | void sys_get_current_symbol(struct registers_struct* args, struct registers_struct* result); 15 | 16 | void sys_delete_current_symbol(struct registers_struct* args, struct registers_struct* result); 17 | 18 | void sys_read_sector(struct registers_struct* args, struct registers_struct* result); 19 | 20 | void sys_write_sector(struct registers_struct* args, struct registers_struct* result); 21 | 22 | void sys_execute_program(struct registers_struct* args, struct registers_struct* result); 23 | 24 | void sys_get_execute_program(struct registers_struct* args, struct registers_struct* result); 25 | 26 | void sys_get_keyboard_buffer(struct registers_struct* args, struct registers_struct* result); 27 | 28 | void sys_get_keyboard_buffer_ptr(struct registers_struct* args, struct registers_struct* result); 29 | 30 | void sys_get_keyboard_shift_pressed(struct registers_struct* args, struct registers_struct* result); 31 | 32 | void sys_get_keyboard_ctrl_pressed(struct registers_struct* args, struct registers_struct* result); 33 | 34 | void sys_get_keyboard_alt_pressed(struct registers_struct* args, struct registers_struct* result); 35 | 36 | void sys_get_display_cursor_pos_x(struct registers_struct* args, struct registers_struct* result); 37 | 38 | void sys_get_display_cursor_pos_y(struct registers_struct* args, struct registers_struct* result); 39 | 40 | void sys_get_ticks(struct registers_struct* args, struct registers_struct* result); 41 | 42 | void sys_get_device_count(struct registers_struct* args, struct registers_struct* result); 43 | 44 | void sys_get_device_info(struct registers_struct* args, struct registers_struct* result); 45 | 46 | void sys_set_display_cursor_pos_x(struct registers_struct* args, struct registers_struct* result); 47 | 48 | void sys_set_display_cursor_pos_y(struct registers_struct* args, struct registers_struct* result); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /docs/drivers/function_specification.md: -------------------------------------------------------------------------------- 1 | # Спецификация дополнительных функций драйверов 2 | 3 | 4 | ## Display 5 | 6 | 7 | #### 0 - вывод текста 8 | 9 | ``` 10 | void print_text(struct dev_info* device, unsigned char*, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char) 11 | ``` 12 | 13 | #### 1 - новая строка 14 | 15 | ``` 16 | void new_line(struct dev_info* device) 17 | ``` 18 | 19 | #### 2 - обновить курсор 20 | 21 | ``` 22 | void cursor_update(struct dev_info* device) 23 | ``` 24 | 25 | #### 3 - очистить дисплей 26 | 27 | ``` 28 | void clear_display(struct dev_info* device) 29 | ``` 30 | 31 | #### 4 - получить текущий символ (можно со смещением) 32 | 33 | ``` 34 | unsigned char get_current_symbol(struct dev_info* device, unsigned int) 35 | ``` 36 | 37 | #### 5 - удалить текущий символ (можно со смещением) 38 | 39 | ``` 40 | unsigned char delete_current_symbol(struct dev_info* device, unsigned int) 41 | ``` 42 | 43 | #### 6 - получить значение координаты X 44 | 45 | ``` 46 | unsigned char get_display_cursor_pos_x(struct dev_info* device) 47 | ``` 48 | 49 | #### 7 - получить значение координаты Y 50 | 51 | ``` 52 | unsigned char get_display_cursor_pos_y(struct dev_info* device) 53 | ``` 54 | 55 | #### 8 - установить значение координаты X 56 | 57 | ``` 58 | void set_display_cursor_pos_x(struct dev_info* device, unsigned char) 59 | ``` 60 | 61 | #### 9 - установить значение координаты Y 62 | 63 | ``` 64 | void set_display_cursor_pos_y(struct dev_info* device, unsigned char) 65 | ``` 66 | 67 | 68 | 69 | ## Keyboard 70 | 71 | 72 | #### 0 - получить адрес буфера клавиатуры 73 | 74 | ``` 75 | void* get_keyboard_buffer(struct dev_info* device) 76 | ``` 77 | 78 | #### 1 - получить индекс (текущее положение) буфера клавиатуры 79 | 80 | ``` 81 | unsigned int get_keyboard_buffer_ptr(struct dev_info* device) 82 | ``` 83 | 84 | #### 2 - получить флаг: нажата ли клавиша shift 85 | 86 | ``` 87 | unsigned char get_keyboard_shift_pressed(struct dev_info* device) 88 | ``` 89 | 90 | #### 3 - получить флаг: нажата ли клавиша ctrl 91 | 92 | ``` 93 | unsigned char get_keyboard_ctrl_pressed(struct dev_info* device) 94 | ``` 95 | 96 | #### 4 - получить флаг: нажата ли клавиша alt 97 | 98 | ``` 99 | unsigned char get_keyboard_alt_pressed(struct dev_info* device) 100 | ``` 101 | -------------------------------------------------------------------------------- /src/drivers/drivers.c: -------------------------------------------------------------------------------- 1 | 2 | #include "drivers.h" 3 | #include "devices.h" 4 | #include "../libs/device.h" 5 | #include "../libs/driver.h" 6 | 7 | #include "driver_list.h" 8 | 9 | #define MAX_DRIVER_COUNT 32 10 | 11 | struct driver_info DRIVERS[MAX_DRIVER_COUNT]; 12 | unsigned int DRIVER_COUNT; 13 | 14 | 15 | // Регистрация драйвера для конкретного устройства 16 | void driver_registration(struct driver_info* driver, struct dev_info* device){ 17 | device->driver = driver; 18 | } 19 | 20 | 21 | // Функция должна найти драйвера, и записать их в DRIVERS 22 | void drivers_find(){ 23 | 24 | // пока что берет просто из статического списка drivers, 25 | // который собирается при компиляции 26 | DRIVER_COUNT = driver_count; 27 | for(int i = 0; i < DRIVER_COUNT; i++){ 28 | DRIVERS[i] = drivers[i]; 29 | } 30 | 31 | } 32 | 33 | 34 | // получает подходящий драйвер для устройства. сразу проверяет через init 35 | int driver_get(struct dev_info* device, struct driver_info** result){ 36 | // 37 | /* 38 | Драйвер просто инициализирует устройство, делает прерывания, и всё! 39 | дальше уже он просто типо ждёт: 40 | когда будет прерывание 41 | либо когда юзер-space сделает syscall в ядро, а ядро уже вызовет драйвер 42 | **он просто реагирует!** 43 | */ 44 | 45 | for (unsigned int driver_index = 0; driver_index < DRIVER_COUNT; driver_index++){ 46 | struct driver_info* driver = &DRIVERS[driver_index]; 47 | if ((driver->classcode == device->classcode) && (driver->subclass == device->subclass)){ 48 | 49 | int (*init)(struct dev_info*) = (int (*)(struct dev_info*))(driver->init); 50 | int init_result = init(device); 51 | 52 | if (init_result == 1){ 53 | *result = driver; 54 | return 0; 55 | } 56 | 57 | } 58 | } 59 | 60 | return -1; 61 | 62 | } 63 | 64 | 65 | void driver_manager(){ 66 | 67 | drivers_find(); 68 | 69 | for (unsigned int device_index = 0; device_index < DEVICE_COUNT; device_index++){ 70 | 71 | struct dev_info* device = &DEVICES_INFO[device_index]; 72 | 73 | if (device->driver == 0){ 74 | struct driver_info* driver; 75 | int dr_get_result = driver_get(device, &driver); 76 | if (dr_get_result == 0) 77 | driver_registration(driver, device); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/libs/asm.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_ASM 2 | #define INCL_LIB_ASM 3 | 4 | #define cpu_pause() __asm__ __volatile__("pause" ::: "memory") 5 | 6 | // Полезные ASM функции 7 | extern void outb (unsigned short port, unsigned char byte); 8 | extern void outw(unsigned short port, unsigned short value); 9 | extern void outl(unsigned short port, unsigned int value); 10 | 11 | extern unsigned char inb (unsigned short port); 12 | extern unsigned short inw (unsigned short port); 13 | extern unsigned int inl (unsigned short port); 14 | 15 | extern void in_out_wait(void); 16 | 17 | // Write in 8-bit registers 18 | extern void in_ah(unsigned char byte); 19 | extern void in_al(unsigned char byte); 20 | extern void in_bh(unsigned char byte); 21 | extern void in_bl(unsigned char byte); 22 | extern void in_ch(unsigned char byte); 23 | extern void in_cl(unsigned char byte); 24 | extern void in_dh(unsigned char byte); 25 | extern void in_dl(unsigned char byte); 26 | 27 | // Write in 16-bit registers 28 | extern void in_ax(short word); 29 | extern void in_bx(short word); 30 | extern void in_cx(short word); 31 | extern void in_dx(short word); 32 | extern void in_si(short word); 33 | 34 | // Write in 32-bit registers 35 | extern void in_eax(unsigned int dword); 36 | extern void in_ebx(unsigned int dword); 37 | extern void in_ecx(unsigned int dword); 38 | extern void in_edx(unsigned int dword); 39 | extern void in_esi(unsigned int dword); 40 | extern void in_edi(unsigned int dword); 41 | 42 | // Read from 8-bit registers 43 | extern unsigned char get_ah(); 44 | extern unsigned char get_al(); 45 | extern unsigned char get_bh(); 46 | extern unsigned char get_bl(); 47 | extern unsigned char get_ch(); 48 | extern unsigned char get_cl(); 49 | extern unsigned char get_dh(); 50 | extern unsigned char get_dl(); 51 | 52 | // Read from 16-bit registers 53 | extern unsigned short get_ax(); 54 | extern unsigned short get_bx(); 55 | extern unsigned short get_cx(); 56 | extern unsigned short get_dx(); 57 | extern unsigned short get_si(); 58 | 59 | // Read from 32-bit registers 60 | extern int get_ebx(); 61 | extern int get_edx(); 62 | extern int get_esi(); 63 | 64 | // Clear 8-bit registers 65 | extern void clear_ah(); 66 | extern void clear_al(); 67 | extern void clear_bh(); 68 | extern void clear_bl(); 69 | extern void clear_ch(); 70 | extern void clear_cl(); 71 | extern void clear_dh(); 72 | extern void clear_dl(); 73 | 74 | // Clear 16-bit registers 75 | extern void clear_ax(); 76 | extern void clear_bx(); 77 | extern void clear_cx(); 78 | extern void clear_dx(); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | LIB_DIRS := $(wildcard src/libs/*.c) 4 | OBJS := $(shell mkdir -p output; find output -name '*.o') 5 | 6 | CC = i386-elf-gcc 7 | CFLAGS = -w -ffreestanding -m32 -fno-pie -nostdlib 8 | 9 | NS = nasm 10 | NSFLAGS = -f elf32 11 | 12 | LIBS_C := $(shell find src/libs -type f -name '*.c') 13 | LIBS_S := $(shell find src/libs -type f -name '*.asm') 14 | KERNEL_C := $(shell find src/kernel -name *.c) 15 | KERNEL_S := $(shell find src/kernel -name *.asm) 16 | API_C := $(shell find src/api -name *.c) 17 | API_S := $(shell find src/api -name *.asm) 18 | 19 | 20 | define build-rule 21 | for src in $(1); do \ 22 | obj=$$(echo $$src | sed 's|$(2)|$(3)|' | sed 's|$(4)$$|$(5)|'); \ 23 | echo "Building $$src -> $$obj"; \ 24 | mkdir -p $$(dirname $$obj); \ 25 | if echo $$src | grep -q "\.c$$"; then \ 26 | $(6) $(7) -c $$src -o $$obj; \ 27 | else \ 28 | $(6) $(7) $$src -o $$obj; \ 29 | fi; \ 30 | done 31 | endef 32 | 33 | 34 | all: 35 | $(MAKE) build 36 | $(MAKE) make_iso 37 | $(MAKE) make_disk 38 | $(MAKE) run 39 | 40 | 41 | 42 | drivers: 43 | $(MAKE) -C ./src/drivers/ 44 | 45 | 46 | libs: 47 | mkdir -p output/libs 48 | $(call build-rule,$(LIBS_C),src/libs,output/libs,.c,.o,$(CC),$(CFLAGS)) 49 | $(call build-rule,$(LIBS_S),src/libs,output/libs,.asm,.o,$(NS),$(NSFLAGS)) 50 | 51 | 52 | kernel: 53 | mkdir -p output/kernel/ 54 | $(call build-rule,$(KERNEL_C),src/kernel,output/kernel,.c,.o,$(CC),$(CFLAGS)) 55 | $(call build-rule,$(KERNEL_S),src/kernel,output/kernel,.asm,.o,$(NS),$(NSFLAGS)) 56 | 57 | $(MAKE) k_api 58 | 59 | 60 | k_api: 61 | mkdir -p output/api/ 62 | $(call build-rule,$(API_C),src/api,output/api,.c,.o,$(CC),$(CFLAGS)) 63 | $(call build-rule,$(API_S),src/api,output/api,.asm,.o,$(NS),$(NSFLAGS)) 64 | 65 | 66 | link: 67 | i386-elf-ld -m elf_i386 -T src/linker.ld --oformat elf32-i386 -o output/kernel.elf $(OBJS) 68 | 69 | 70 | clean: 71 | rm -rf output/ 72 | 73 | 74 | build: 75 | echo "\n --- --- clean --- --- \n" 76 | $(MAKE) clean 77 | echo "\n --- --- drivers --- --- \n" 78 | $(MAKE) drivers 79 | echo "\n --- --- libs --- --- \n" 80 | $(MAKE) libs 81 | echo "\n --- --- kernel --- --- \n" 82 | $(MAKE) kernel 83 | echo "\n --- --- link --- --- \n" 84 | $(MAKE) link 85 | 86 | 87 | make_iso: 88 | # Make ISO 89 | cp output/kernel.elf iso/boot/ 90 | grub-mkrescue -o output/os.iso ./iso/ 91 | 92 | make_disk: 93 | # Make hard disk 94 | dd if=/dev/zero of=output/disk.img bs=512 count=20480 95 | 96 | run: 97 | qemu-system-i386 -no-reboot -no-shutdown -monitor stdio \ 98 | -drive file=output/disk.img,format=raw,if=ide,index=0,media=disk \ 99 | -drive file=output/os.iso,format=raw,if=ide,index=1,media=cdrom \ 100 | -d int,cpu_reset -D qemu.log 101 | -------------------------------------------------------------------------------- /docs/drivers/development.md: -------------------------------------------------------------------------------- 1 | # Разработка драйверов 2 | 3 | Драйвера находятся по пути [src/drivers/](../../src/drivers/) 4 | 5 | У каждого драйвера должна быть своя директория 6 | 7 | Сборка драйвера - это индивидуальный процесс поэтому необходимо локально создать Makefile и собрать драйвер в объектный файл по пути `output/drivers/` 8 | 9 | ### Функция Init 10 | — это функция, запускаемая менеджером драйверов при регистрации драйвера. Менеджер драйверов передаёт адрес структуры устройства, драйвер должен определить: сможет ли он обслуживать данное устройство. Если может, то функция возвращает `1`, если же драйвер не подходит, то функция должна вернуть `0`. 11 | Сигнатура функции init: 12 | ``` 13 | int init(struct dev_info*); 14 | ``` 15 | 16 | > Название не может совпадать с другими функциями ядра 17 | 18 | > Функция init должна быть определена в header файле, подключаемый в `src/drivers/driver_list.c` 19 | 20 | ### Дополнительные функции 21 | — это функции драйверов, которые должны быть реализованы в зависимости от [спецификации ядра](function_specification.md). 22 | > Пример: драйвер клавиатуры должен в обязательном порядке реализовать функцию для получения адреса буффера клавиатуры 23 | 24 | Адреса этих функций должны быть в массиве, который затем используется для [регистрации драйвера](#registration). Порядок определяется [спецификацией](function_specification.md) 25 | 26 | Первый аргумент каждой дополнительной функции - это адрес на структуру устройства 27 | 28 | > Название массива должно быть уникальным 29 | 30 | > Массив с адресами функций должен быть определён в header файле, подключаемый в `src/drivers/driver_list.c` 31 | 32 | ## Registration 33 | 34 | Чтобы ядро увидело ваш драйвер, необходимо зарегестрировать его перед компиляцией 35 | 36 | Для этого в файле [src/drivers/driver_list.c](../../src/drivers/driver_list.c) необходимо подключить заголовочный файл вашего драйвера в секции `Includes drivers`, а также в секции `Driver list` добавить в макрос DRIVER_LIST определение в формате: 37 | ``` 38 | X(НАЗВАНИЕ_ДРАЙВЕРА, "ФАЙЛ_ДРАЙВЕРА", КЛАСС_УСТРОЙСТВ, ПОДКЛАСС_УСТРОЙСТВ, ФУНКЦИЯ_ИНИЦИАЛИЗАЦИИ, МАССИВ_ФУНКЦИЙ) 39 | ``` 40 | 41 | - `НАЗВАНИЕ_ДРАЙВЕРА` - это название которое будет отображаться в системе 42 | 43 | - `ФАЙЛ_ДРАЙВЕРА` - не обязательная часть, можно указать что угодно, но обязательно в кавычках 44 | 45 | - `КЛАСС_УСТРОЙСТВ` - класс устройств для которых предназначен драйвер 46 | 47 | - `ПОДКЛАСС_УСТРОЙСТВ` - подкласс устройств для которых предназначен драйвер 48 | 49 | - `ФУНКЦИЯ_ИНИЦИАЛИЗАЦИИ` - адрес функции инициализации. Можно просто указать название функции 50 | 51 | - `МАССИВ_ФУНКЦИЙ` - адрес на массив дополнительных функций 52 | 53 | 54 | ## Kernel API 55 | 56 | Есть возможность использовать API функции ядра. Для этого необходимо подключить заголовочный файл [src/api/kernel_functions.h](../../src/api/kernel_functions.h) 57 | 58 | Доступные функции расписаны в [документации API](../api/internal_api.md) 59 | 60 | -------------------------------------------------------------------------------- /docs/api/syscalls.md: -------------------------------------------------------------------------------- 1 | # Системные вызовы 2 | 3 | ## Детали 4 | 5 | Системный вызов выполняется посредством генерации программного прерывания `0x22` 6 | 7 | Следующие регистры используются для передачи аргументов: 8 | 9 | | Register | Description | 10 | | :-------------: | :------------- | 11 | | `EAX` | Номер системного вызова | 12 | | `EBX` | 1-й аргумент | 13 | | `ECX` | 2-й аргумент | 14 | | `EDX` | 3-й аргумент | 15 | | `ESI` | 4-й аргумент | 16 | | `EDI` | 5-й аргумент | 17 | | `EAX` | Возвращаемое значение | 18 | 19 | ## Таблица системных вызовов 20 | 21 | | Number | Name | Description | 22 | | :-------------: | :------------- | :------------- | 23 | | `0x0` | [print_text](syscall_functions.md#print_text) | Вывод текста | 24 | | `0x1` | [new_line](syscall_functions.md#new_line) | Переход на следующую строку | 25 | | `0x2` | [cursor_update](syscall_functions.md#cursor_update) | Обновить курсор | 26 | | `0x3` | [clear_display](syscall_functions.md#clear_display) | Очистить дисплей | 27 | | `0x4` | [get_current_symbol](syscall_functions.md#get_current_symbol) | Получить текущий символ | 28 | | `0x5` | [delete_current_symbol](syscall_functions.md#delete_current_symbol) | Удалить текущий символ | 29 | | `0x10` | [read_sector](syscall_functions.md#read_sector) | Читать определённый сектор диска | 30 | | `0x11` | [write_sector](syscall_functions.md#write_sector) | Записать в определённый сектор диска | 31 | | `0x50` | [execute_program](syscall_functions.md#execute_program) | Указать следующую программу для исполнения | 32 | | `0x100` | [get_execute_program](syscall_functions.md#get_execute_program) | Получить следующую программу для исполнения | 33 | | `0x101` | [get_keyboard_buffer](syscall_functions.md#get_keyboard_buffer) | Получить адрес буффера клавиатуры | 34 | | `0x102` | [get_keyboard_buffer_ptr](syscall_functions.md#get_keyboard_buffer_ptr) | Получить текущий индекс (текущее положение) буфера клавиатуры | 35 | | `0x103` | [get_keyboard_shift_pressed](syscall_functions.md#get_keyboard_shift_pressed) | Получить флаг: нажата ли клавиша Shift | 36 | | `0x104` | [get_keyboard_ctrl_pressed](syscall_functions.md#get_keyboard_ctrl_pressed) | Получить флаг: нажата ли клавиша Ctrl | 37 | | `0x105` | [get_keyboard_alt_pressed](syscall_functions.md#get_keyboard_alt_pressed) | Получить флаг: нажата ли клавиша Alt | 38 | | `0x106` | [get_display_cursor_pos_x](syscall_functions.md#get_display_cursor_pos_x) | Получить позицию курсора по координате X | 39 | | `0x107` | [get_display_cursor_pos_y](syscall_functions.md#get_display_cursor_pos_y) | Получить позицию курсора по координате Y | 40 | | `0x108` | [get_ticks](syscall_functions.md#get_ticks) | Получить количество тиков с момента запуска системы | 41 | | `0x109` | [get_device_count](syscall_functions.md#get_device_count) | Получить количество устройств | 42 | | `0x10A` | [get_device_info](syscall_functions.md#get_device_info) | Получить адрес массива структур устройств | 43 | | `0x200` | [set_display_cursor_pos_x](syscall_functions.md#set_display_cursor_pos_x) | Задать положение координаты X | 44 | | `0x201` | [set_display_cursor_pos_y](syscall_functions.md#set_display_cursor_pos_y) | Задать положение координаты Y | 45 | 46 | -------------------------------------------------------------------------------- /src/drivers/keyboard/keyboard.c: -------------------------------------------------------------------------------- 1 | #define KEYBOARD_BUFFER_SIZE 16 2 | 3 | #define KEYBOARD_SHIFT_SCANCODE 42 4 | #define KEYBOARD_CTRL_SCANCODE 29 5 | #define KEYBOARD_ALT_SCANCODE 56 6 | 7 | #include "keyboard.h" 8 | #include "../drivers.h" 9 | #include "../../api/kernel_functions.h" 10 | #include "../../libs/asm.h" 11 | #include "../../libs/device.h" 12 | 13 | // ASM keyboard handler 14 | extern void asm_keyboard_handler(); 15 | 16 | void* keyboard_funcs[] = { 17 | keyboard_get_buffer, 18 | keyboard_get_buffer_ptr, 19 | keyboard_get_shift_pressed, 20 | keyboard_get_ctrl_pressed, 21 | keyboard_get_alt_pressed 22 | }; 23 | 24 | unsigned char KEYBOARD_SHIFT_PRESSED = 0; 25 | unsigned char KEYBOARD_CTRL_PRESSED = 0; 26 | unsigned char KEYBOARD_ALT_PRESSED = 0; 27 | 28 | unsigned char KEYBOARD_BUFFER[KEYBOARD_BUFFER_SIZE]; 29 | unsigned int KEYBOARD_BUFFER_PTR; 30 | 31 | // Добавление сканн-кода в буфер клавиатуры (для последующего использования программами) 32 | void keyboard_scancode_add_in_buffer(unsigned char scancode){ 33 | KEYBOARD_BUFFER[KEYBOARD_BUFFER_PTR] = scancode; 34 | KEYBOARD_BUFFER_PTR = (KEYBOARD_BUFFER_PTR+1) % KEYBOARD_BUFFER_SIZE; 35 | } 36 | 37 | 38 | // Возвращает скан-код нажатой клавиши 39 | unsigned char keyboard_get_scancode(){ 40 | unsigned char keyboard_state = inb(0x64); 41 | if ((keyboard_state & 0b00000001) == 0b00000001) return inb(0x60); 42 | else return 0; 43 | } 44 | 45 | 46 | // Проверка на то, специальный ли символ (SHIFT, CTRL, ALT - спец. символы) 47 | char keyboard_is_special_key(unsigned char scancode){ 48 | switch (scancode){ 49 | case KEYBOARD_SHIFT_SCANCODE: return 1; 50 | case KEYBOARD_CTRL_SCANCODE: return 1; 51 | case KEYBOARD_ALT_SCANCODE: return 1; 52 | default: return 0; 53 | } 54 | } 55 | 56 | 57 | // Обработчик специальных клавиш (выставляет флаги) 58 | char keyboard_special_key_handler(unsigned char scancode, char state){ 59 | if ((scancode) == KEYBOARD_SHIFT_SCANCODE){ 60 | KEYBOARD_SHIFT_PRESSED = state; 61 | } 62 | else if ((scancode) == KEYBOARD_CTRL_SCANCODE){ 63 | KEYBOARD_CTRL_PRESSED = state; 64 | } 65 | else if ((scancode) == KEYBOARD_ALT_SCANCODE){ 66 | KEYBOARD_ALT_PRESSED = state; 67 | } 68 | } 69 | 70 | 71 | // Обрабатывает нажатие клавиши (прерывание) 72 | void keyboard_handler(){ 73 | 74 | unsigned char scancode = keyboard_get_scancode(); 75 | 76 | if ((scancode & 0b10000000) == 0b10000000){ 77 | // released 78 | char is_special_key = keyboard_is_special_key(scancode & 0b01111111); 79 | if (is_special_key) keyboard_special_key_handler(scancode & 0b01111111, 0); 80 | 81 | } 82 | else{ 83 | // pressed 84 | char is_special_key = keyboard_is_special_key(scancode & 0b01111111); 85 | if (is_special_key) keyboard_special_key_handler(scancode & 0b01111111, 1); 86 | else keyboard_scancode_add_in_buffer(scancode); 87 | } 88 | outb(0x20, 0x20); 89 | } 90 | 91 | void* keyboard_get_buffer(struct dev_info* device){ 92 | return KEYBOARD_BUFFER; 93 | } 94 | 95 | unsigned int keyboard_get_buffer_ptr(struct dev_info* device){ 96 | return KEYBOARD_BUFFER_PTR; 97 | } 98 | 99 | unsigned char keyboard_get_shift_pressed(struct dev_info* device){ 100 | return KEYBOARD_SHIFT_PRESSED; 101 | } 102 | 103 | unsigned char keyboard_get_ctrl_pressed(struct dev_info* device){ 104 | return KEYBOARD_CTRL_PRESSED; 105 | } 106 | 107 | unsigned char keyboard_get_alt_pressed(struct dev_info* device){ 108 | return KEYBOARD_ALT_PRESSED; 109 | } 110 | 111 | int keyboard_init(struct dev_info* device){ 112 | 113 | if (device->revision_id == 89){ 114 | return 0; 115 | } 116 | 117 | _intr_disable(); 118 | _pic_update_mask(0, 1, 0); 119 | _int_reg_handler(33, 0x08, 0x80 | 0x0E, asm_keyboard_handler); 120 | _intr_enable(); 121 | 122 | return 1; 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/api/api.c: -------------------------------------------------------------------------------- 1 | // userspace API handler 2 | 3 | #include "api.h" 4 | #include "userspace_if.h" 5 | #include "kernel_functions.h" 6 | 7 | 8 | void api_handler(){ 9 | 10 | // 11 | // Получение аргументов из регистров 12 | // 13 | 14 | struct registers_struct args; 15 | 16 | asm volatile( 17 | "movl %%eax, %0\n" 18 | "movl %%ebx, %1\n" 19 | "movl %%ecx, %2\n" 20 | "movl %%edx, %3\n" 21 | "movl %%esi, %4\n" 22 | "movl %%edi, %5\n" 23 | : "=a"(args.eax), 24 | "=b"(args.ebx), 25 | "=c"(args.ecx), 26 | "=d"(args.edx), 27 | "=S"(args.esi), 28 | "=D"(args.edi) 29 | : 30 | : "memory" 31 | ); 32 | 33 | unsigned int syscall_number = args.eax; // Получаем номер системного вызова 34 | 35 | // 36 | // Вызов определённой функции исходя по номеру системного вызова 37 | // 38 | 39 | struct registers_struct result; // Здесь будет храниться результат 40 | 41 | switch(syscall_number){ 42 | 43 | case 0x0: 44 | sys_print_text(&args, &result); 45 | break; 46 | 47 | case 0x1: 48 | sys_new_line(&args, &result); 49 | break; 50 | 51 | case 0x2: 52 | sys_cursor_update(&args, &result); 53 | break; 54 | 55 | case 0x3: 56 | sys_clear_display(&args, &result); 57 | break; 58 | 59 | case 0x4: 60 | sys_get_current_symbol(&args, &result); 61 | break; 62 | 63 | case 0x5: 64 | sys_delete_current_symbol(&args, &result); 65 | break; 66 | 67 | case 0x10: 68 | sys_read_sector(&args, &result); 69 | break; 70 | 71 | case 0x11: 72 | sys_write_sector(&args, &result); 73 | break; 74 | 75 | case 0x50: 76 | sys_execute_program(&args, &result); 77 | break; 78 | 79 | case 0x100: 80 | sys_get_execute_program(&args, &result); 81 | break; 82 | 83 | case 0x101: 84 | sys_get_keyboard_buffer(&args, &result); 85 | break; 86 | 87 | case 0x102: 88 | sys_get_keyboard_buffer_ptr(&args, &result); 89 | break; 90 | 91 | case 0x103: 92 | sys_get_keyboard_shift_pressed(&args, &result); 93 | break; 94 | 95 | case 0x104: 96 | sys_get_keyboard_ctrl_pressed(&args, &result); 97 | break; 98 | 99 | case 0x105: 100 | sys_get_keyboard_alt_pressed(&args, &result); 101 | break; 102 | 103 | case 0x106: 104 | sys_get_display_cursor_pos_x(&args, &result); 105 | break; 106 | 107 | case 0x107: 108 | sys_get_display_cursor_pos_y(&args, &result); 109 | break; 110 | 111 | case 0x108: 112 | sys_get_ticks(&args, &result); 113 | break; 114 | 115 | case 0x109: 116 | sys_get_device_count(&args, &result); 117 | break; 118 | 119 | case 0x10A: 120 | sys_get_device_info(&args, &result); 121 | break; 122 | 123 | } 124 | 125 | outb(0x20, 0x20); // Обработали прерывание (системный вызов) 126 | 127 | // 128 | // Записываем результат в регистры 129 | // 130 | 131 | asm volatile( 132 | "movl %0, %%eax\n" 133 | "movl %1, %%ebx\n" 134 | "movl %2, %%ecx\n" 135 | "movl %3, %%edx\n" 136 | "movl %4, %%esi\n" 137 | "movl %5, %%edi\n" 138 | : 139 | : "a"(result.eax), 140 | "b"(result.ebx), 141 | "c"(result.ecx), 142 | "d"(result.edx), 143 | "S"(result.esi), 144 | "D"(result.edi) 145 | : "memory" 146 | ); 147 | 148 | } 149 | 150 | // Регистрация API прерываний 151 | void api_registration_functions(){ 152 | // Не забывай: IRQ всегда делает только маленькую и быструю работу 153 | _int_reg_handler(0x22, 0x08, 0x80 | 0x0E, api_asm_handler); 154 | } 155 | 156 | 157 | // Инициализация API 158 | void api_init(){ 159 | api_registration_functions(); 160 | } 161 | -------------------------------------------------------------------------------- /docs/notes/ata.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | | Регистр | Порт (базовый) | Примечание | 5 | | ---------------- | -------------- | ----------------------------------------- | 6 | | Data | 0x1F0 | 16 бит | 7 | | Error / Features | 0x1F1 | чтение/запись | 8 | | Sector Count | 0x1F2 | количество секторов для команды | 9 | | LBA Low | 0x1F3 | младший байт LBA | 10 | | LBA Mid | 0x1F4 | средний байт LBA | 11 | | LBA High | 0x1F5 | старший байт LBA | 12 | | Drive/Head | 0x1F6 | выбор диска, бит 6 = 1 для LBA, 0 для CHS | 13 | | Status / Command | 0x1F7 | чтение статуса / запись команды | 14 | 15 | 16 | команды 17 | 18 | | Команда | Код | Что делает | Регистры | 19 | | ---------------------- | ---- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | 20 | | IDENTIFY DEVICE | 0xEC | Возвращает данные о диске (модель, серийник, размер, поддержка LBA/DMA) | 0x1F0 (Data), 0x1F6 (выбор диска), 0x1F7 (команда) | 21 | | READ SECTORS | 0x20 | Читает один или несколько секторов | 0x1F0 (Data), 0x1F2 (кол-во секторов), 0x1F3..0x1F5 (LBA), 0x1F6 (диск), 0x1F7 (команда) | 22 | | WRITE SECTORS | 0x30 | Записывает один или несколько секторов | 0x1F0 (Data), 0x1F2 (кол-во секторов), 0x1F3..0x1F5 (LBA), 0x1F6 (диск), 0x1F7 (команда) | 23 | | READ MULTIPLE | 0xC4 | Чтение нескольких секторов за раз | 0x1F0 (Data), 0x1F2 (кол-во секторов), 0x1F3..0x1F5 (LBA), 0x1F6 (диск), 0x1F7 (команда) | 24 | | WRITE MULTIPLE | 0xC5 | Запись нескольких секторов за раз | 0x1F0 (Data), 0x1F2 (кол-во секторов), 0x1F3..0x1F5 (LBA), 0x1F6 (диск), 0x1F7 (команда) | 25 | | SET FEATURES | 0xEF | Настройка функций диска (PIO/DMA, кеш) | 0x1F1 (Features), 0x1F7 (команда) | 26 | | PACKET COMMAND (ATAPI) | 0xA0 | Работа с CD/DVD через пакет | 0x1F0 (Data), 0x1F7 (команда) | 27 | 28 | 29 | 30 | Если к шине не подключены диски до в байте состояния будет 0xFF 31 | 32 | 33 | Биты ответа Status Register 0x1F7 34 | 35 | | Бит | Символ | Назначение | 36 | | --- | -------- | ---------------------------------------------------------------------------------------------------------------------------- | 37 | | 0 | **ERR** | **Error** — если установлен, последняя операция завершилась с ошибкой. Для детальной ошибки читают `0x1F1` (Error Register). | 38 | | 1 | **IDX** | **Index** — устаревший, почти никогда не используется (только для старых MFM/RLL дисков). | 39 | | 2 | **CORR** | **Corrected data** — показывает, что данные были исправлены аппаратно (ECC). Используется редко. | 40 | | 3 | **DRQ** | **Data Request** — диск готов передавать/принимать данные (read/write). Важно для всех операций чтения/записи. | 41 | | 4 | **SRV** | **Overlapped Mode Service Request** — используется для “overlapped” режима (редко). | 42 | | 5 | **DF** | **Device Fault** — устройство выдало внутреннюю ошибку. Если установлен, операция прервана. | 43 | | 6 | **RDY** | **Device Ready** — диск готов к командам. Если сброшен, диск не готов. | 44 | | 7 | **BSY** | **Busy** — диск занят, не принимать новые команды. Пока бит = 1, все команды игнорируются. | 45 | -------------------------------------------------------------------------------- /docs/api/internal_api.md: -------------------------------------------------------------------------------- 1 | # Внутренний API для компонентов ядра 2 | 3 | ## Детали 4 | 5 | Чтобы использовать API нужно подключить заголовочный файл [src/api/kernel_functions.h](../../src/api/kernel_functions.h) 6 | 7 | Обратите внимание: перед именами API-функций в коде всегда используется символ `_` (в документации он опущен) 8 | 9 | 10 | ## Таблица функций 11 | 12 | | Name | Description | 13 | | :------------------------------------------------------------------------------------: | :------------------------------------------ | 14 | | [print_text](internal_functions.md#print_text) | Вывод текста | 15 | | [new_line](internal_functions.md#new_line) | Переход на следующую строку | 16 | | [cursor_update](internal_functions.md#cursor_update) | Обновить курсор | 17 | | [clear_display](internal_functions.md#clear_display) | Очистить дисплей | 18 | | [get_current_symbol](internal_functions.md#get_current_symbol) | Получить текущий символ | 19 | | [delete_current_symbol](internal_functions.md#delete_current_symbol) | Удалить текущий символ | 20 | | [read_sector](internal_functions.md#read_sector) | Читать определённый сектор диска | 21 | | [write_sector](internal_functions.md#write_sector) | Записать в определённый сектор диска | 22 | | [execute_program](internal_functions.md#execute_program) | Указать следующую программу для исполнения | 23 | | [get_execute_program](internal_functions.md#get_execute_program) | Получить следующую программу для исполнения | 24 | | [get_keyboard_buffer](internal_functions.md#get_keyboard_buffer) | Получить адрес буфера клавиатуры | 25 | | [get_keyboard_buffer_ptr](internal_functions.md#get_keyboard_buffer_ptr) | Получить текущий индекс буфера клавиатуры | 26 | | [get_keyboard_shift_pressed](internal_functions.md#get_keyboard_shift_pressed) | Флаг: нажата ли клавиша Shift | 27 | | [get_keyboard_ctrl_pressed](internal_functions.md#get_keyboard_ctrl_pressed) | Флаг: нажата ли клавиша Ctrl | 28 | | [get_keyboard_alt_pressed](internal_functions.md#get_keyboard_alt_pressed) | Флаг: нажата ли клавиша Alt | 29 | | [get_display_cursor_pos_x](internal_functions.md#get_display_cursor_pos_x) | Позиция курсора по X | 30 | | [get_display_cursor_pos_y](internal_functions.md#get_display_cursor_pos_y) | Позиция курсора по Y | 31 | | [get_ticks](internal_functions.md#get_ticks) | Количество тиков с момента запуска | 32 | | [get_device_count](internal_functions.md#get_device_count) | Количество устройств | 33 | | [get_device_info](internal_functions.md#get_device_info) | Адрес массива структур устройств | 34 | | [set_display_cursor_pos_x](internal_functions.md#set_display_cursor_pos_x) | Задать положение X | 35 | | [set_display_cursor_pos_y](internal_functions.md#set_display_cursor_pos_y) | Задать положение Y | 36 | | [int_reg_handler](internal_functions.md#int_reg_handler) | Зарегестрировать обработчик для прерывания | 37 | | [pic_update_mask](internal_functions.md#pic_update_mask) | Обновить маску PCI | 38 | | [intr_enable](internal_functions.md#intr_enable) | Включить/разрешить прерывания | 39 | | [intr_disable](internal_functions.md#intr_disable) | Выключить/запретить прерывания | 40 | | [pci_config_read_word](internal_functions.md#pci_config_read_word) | PCI Config Read Word | 41 | | [pci_config_read_dword](internal_functions.md#pci_config_read_dword) | PCI Config Read Double Word | 42 | | [pci_config_write_word](internal_functions.md#pci_config_write_word) | PCI Config Write Word | 43 | | [pci_config_get_command](internal_functions.md#pci_config_get_command) | PCI Config Get Command | 44 | | [pci_config_get_status](internal_functions.md#pci_config_get_status) | PCI Config Get Status | 45 | | [pci_config_set_command](internal_functions.md#pci_config_set_command) | PCI Config Set Command | 46 | -------------------------------------------------------------------------------- /src/api/userspace_if.c: -------------------------------------------------------------------------------- 1 | // Интерфейс API функций для userspace 2 | 3 | #include "api.h" 4 | #include "userspace_if.h" 5 | #include "general_functions.h" 6 | 7 | 8 | void sys_print_text(struct registers_struct* args, struct registers_struct* result){ 9 | 10 | _print_text( 11 | args->ebx, 12 | args->ecx, 13 | ((args->edx) & 0xFF), 14 | ((args->edx >> 8) & 0xFF), 15 | ((args->esi) & 0xFF), 16 | ((args->esi >> 8) & 0xFF), 17 | args->edi 18 | ); 19 | 20 | } 21 | 22 | void sys_new_line(struct registers_struct* args, struct registers_struct* result){ 23 | _new_line(args->ebx); 24 | } 25 | 26 | void sys_cursor_update(struct registers_struct* args, struct registers_struct* result){ 27 | _cursor_update(args->ebx); 28 | } 29 | 30 | void sys_clear_display(struct registers_struct* args, struct registers_struct* result){ 31 | _clear_display(args->ebx); 32 | } 33 | 34 | void sys_get_current_symbol(struct registers_struct* args, struct registers_struct* result){ 35 | unsigned char symbol = _get_current_symbol(args->ebx, args->edx); 36 | result->eax = (unsigned int)symbol; 37 | } 38 | 39 | void sys_delete_current_symbol(struct registers_struct* args, struct registers_struct* result){ 40 | unsigned char symbol = _delete_current_symbol(args->ebx, args->edx); 41 | result->eax = (unsigned int)symbol; 42 | } 43 | 44 | void sys_read_sector(struct registers_struct* args, struct registers_struct* result){ 45 | unsigned char state = _read_sector(args->ebx, args->ecx, args->edx); 46 | result->eax = (unsigned int)state; 47 | } 48 | 49 | void sys_write_sector(struct registers_struct* args, struct registers_struct* result){ 50 | unsigned char state = _write_sector(args->ebx, args->ecx, args->edx); 51 | result->eax = (unsigned int)state; 52 | } 53 | 54 | void sys_execute_program(struct registers_struct* args, struct registers_struct* result){ 55 | _execute_program(args->ebx); 56 | } 57 | 58 | void sys_get_execute_program(struct registers_struct* args, struct registers_struct* result){ 59 | unsigned int program = _get_execute_program(); 60 | result->eax = (unsigned int)program; 61 | } 62 | 63 | void sys_get_keyboard_buffer(struct registers_struct* args, struct registers_struct* result){ 64 | void* buffer = _get_keyboard_buffer(args->ebx); 65 | result->eax = (unsigned int)buffer; 66 | } 67 | 68 | void sys_get_keyboard_buffer_ptr(struct registers_struct* args, struct registers_struct* result){ 69 | unsigned int buffer_ptr = _get_keyboard_buffer_ptr(args->ebx); 70 | result->eax = buffer_ptr; 71 | } 72 | 73 | void sys_get_keyboard_shift_pressed(struct registers_struct* args, struct registers_struct* result){ 74 | unsigned char flag = _get_keyboard_shift_pressed(args->ebx); 75 | result->eax = (unsigned int)flag; 76 | } 77 | 78 | void sys_get_keyboard_ctrl_pressed(struct registers_struct* args, struct registers_struct* result){ 79 | unsigned char flag = _get_keyboard_ctrl_pressed(args->ebx); 80 | result->eax = (unsigned int)flag; 81 | } 82 | 83 | void sys_get_keyboard_alt_pressed(struct registers_struct* args, struct registers_struct* result){ 84 | unsigned char flag = _get_keyboard_alt_pressed(args->ebx); 85 | result->eax = (unsigned int)flag; 86 | } 87 | 88 | void sys_get_display_cursor_pos_x(struct registers_struct* args, struct registers_struct* result){ 89 | unsigned int x = _get_display_cursor_pos_x(result->ebx); 90 | result->eax = x; 91 | } 92 | 93 | void sys_get_display_cursor_pos_y(struct registers_struct* args, struct registers_struct* result){ 94 | unsigned int y = _get_display_cursor_pos_y(result->ebx); 95 | result->eax = y; 96 | } 97 | 98 | void sys_get_ticks(struct registers_struct* args, struct registers_struct* result){ 99 | unsigned int ticks = _get_ticks(); 100 | result->eax = ticks; 101 | } 102 | 103 | void sys_get_device_count(struct registers_struct* args, struct registers_struct* result){ 104 | unsigned int count = _get_device_count(); 105 | result->eax = count; 106 | } 107 | 108 | void sys_get_device_info(struct registers_struct* args, struct registers_struct* result){ 109 | void* devices = _get_device_info(); 110 | result->eax = (unsigned int)devices; 111 | } 112 | 113 | void sys_set_display_cursor_pos_x(struct registers_struct* args, struct registers_struct* result){ 114 | _set_display_cursor_pos_x(result->ebx, result->ecx); 115 | } 116 | 117 | void sys_set_display_cursor_pos_y(struct registers_struct* args, struct registers_struct* result){ 118 | _set_display_cursor_pos_x(result->ebx, result->ecx); 119 | } 120 | -------------------------------------------------------------------------------- /src/libs/asm.asm: -------------------------------------------------------------------------------- 1 | global outb, outw, outl, inb, inw, inl, in_out_wait 2 | 3 | global in_ah, in_al, in_bh, in_bl, in_ch, in_cl, in_dh, in_dl 4 | global in_ax, in_bx, in_cx, in_dx, in_si 5 | global in_eax, in_ebx, in_ecx, in_edx, in_esi, in_edi 6 | 7 | global get_ah, get_al, get_bh, get_bl, get_ch, get_cl, get_dh, get_dl 8 | global get_ax, get_bx, get_cx, get_dx, get_si 9 | global get_ebx, get_edx, get_esi 10 | 11 | global clear_ah, clear_al, clear_bh, clear_bl, clear_ch, clear_cl, clear_dh, clear_dl 12 | global clear_ax, clear_bx, clear_cx, clear_dx 13 | 14 | section .text 15 | 16 | 17 | outb: 18 | push ebp 19 | mov ebp, esp 20 | ; [ebp+8] = port (16-bit) 21 | ; [ebp+12] = byte (8-bit) 22 | mov dx, WORD [ebp+8] 23 | mov al, BYTE [ebp+12] 24 | out dx, al 25 | pop ebp 26 | ret 27 | 28 | outw: 29 | push ebp 30 | mov ebp, esp 31 | mov dx, WORD [ebp+8] 32 | mov ax, WORD [ebp+12] 33 | out dx, ax 34 | pop ebp 35 | ret 36 | 37 | outl: 38 | push ebp 39 | mov ebp, esp 40 | mov dx, WORD [ebp+8] 41 | mov eax, DWORD [ebp+12] 42 | out dx, eax 43 | pop ebp 44 | ret 45 | 46 | inb: 47 | push ebp 48 | mov ebp, esp 49 | mov dx, WORD [ebp+8] 50 | xor eax, eax 51 | in al, dx 52 | pop ebp 53 | ret 54 | 55 | inw: 56 | push ebp 57 | mov ebp, esp 58 | mov dx, WORD [ebp+8] 59 | xor eax, eax 60 | in ax, dx 61 | pop ebp 62 | ret 63 | 64 | inl: 65 | push ebp 66 | mov ebp, esp 67 | mov dx, WORD [ebp+8] 68 | xor eax, eax 69 | in eax, dx 70 | pop ebp 71 | ret 72 | 73 | in_out_wait: 74 | mov dx, 0x80 75 | mov ax, 0 76 | out dx, ax 77 | 78 | 79 | 80 | ; Write 8-bit registers 81 | 82 | in_ah: 83 | mov ah, [esp+4] 84 | ret 85 | 86 | in_al: 87 | mov al, [esp+4] 88 | ret 89 | 90 | in_bh: 91 | mov bh, [esp+4] 92 | ret 93 | 94 | in_bl: 95 | mov bl, [esp+4] 96 | ret 97 | 98 | in_ch: 99 | mov ch, [esp+4] 100 | ret 101 | 102 | in_cl: 103 | mov cl, [esp+4] 104 | ret 105 | 106 | in_dh: 107 | mov dh, [esp+4] 108 | ret 109 | 110 | in_dl: 111 | mov dl, [esp+4] 112 | ret 113 | 114 | ; Write 16-bit registers 115 | 116 | in_ax: 117 | mov ax, [esp+4] 118 | ret 119 | 120 | in_bx: 121 | mov bx, [esp+4] 122 | ret 123 | 124 | in_cx: 125 | mov cx, [esp+4] 126 | ret 127 | 128 | in_dx: 129 | mov dx, [esp+4] 130 | ret 131 | 132 | in_si: 133 | mov si, [esp+4] 134 | ret 135 | 136 | ; Write 32-bit registers 137 | 138 | in_eax: 139 | mov eax, [esp+4] 140 | ret 141 | 142 | in_ebx: 143 | mov ebx, [esp+4] 144 | ret 145 | 146 | in_ecx: 147 | mov ecx, [esp+4] 148 | ret 149 | 150 | in_edx: 151 | mov edx, [esp+4] 152 | ret 153 | 154 | in_esi: 155 | mov esi, [esp+4] 156 | ret 157 | 158 | in_edi: 159 | mov edi, [esp+4] 160 | ret 161 | 162 | ; Read 8-bit registers 163 | 164 | get_ah: 165 | movzx eax, ah 166 | ret 167 | 168 | get_al: 169 | movzx eax, al 170 | ret 171 | 172 | get_bh: 173 | movzx eax, bh 174 | ret 175 | 176 | get_bl: 177 | movzx eax, bl 178 | ret 179 | 180 | get_ch: 181 | movzx eax, ch 182 | ret 183 | 184 | get_cl: 185 | movzx eax, cl 186 | ret 187 | 188 | get_dh: 189 | movzx eax, dh 190 | ret 191 | 192 | get_dl: 193 | movzx eax, dl 194 | ret 195 | 196 | ; Read 16-bit registers 197 | 198 | get_ax: 199 | movzx eax, ax 200 | ret 201 | 202 | get_bx: 203 | movzx eax, bx 204 | ret 205 | 206 | get_cx: 207 | movzx eax, cx 208 | ret 209 | 210 | get_dx: 211 | movzx eax, dx 212 | ret 213 | 214 | get_si: 215 | movzx eax, si 216 | ret 217 | 218 | ; Read 32-bit registers 219 | 220 | get_ebx: 221 | mov eax, ebx 222 | ret 223 | 224 | get_edx: 225 | mov eax, edx 226 | ret 227 | 228 | get_esi: 229 | mov eax, esi 230 | ret 231 | 232 | ; Clear 8-bit registers 233 | 234 | clear_ah: 235 | xor ah, ah 236 | ret 237 | 238 | clear_al: 239 | xor al, al 240 | ret 241 | 242 | clear_bh: 243 | xor bh, bh 244 | ret 245 | 246 | clear_bl: 247 | xor bl, bl 248 | ret 249 | 250 | clear_ch: 251 | xor ch, ch 252 | ret 253 | 254 | clear_cl: 255 | xor cl, cl 256 | ret 257 | 258 | clear_dh: 259 | xor dh, dh 260 | ret 261 | 262 | clear_dl: 263 | xor dl, dl 264 | ret 265 | 266 | ; Clear 16-bit registers 267 | 268 | clear_ax: 269 | xor ax, ax 270 | ret 271 | 272 | clear_bx: 273 | xor bx, bx 274 | ret 275 | 276 | clear_cx: 277 | xor cx, cx 278 | ret 279 | 280 | clear_dx: 281 | xor dx, dx 282 | ret 283 | -------------------------------------------------------------------------------- /src/drivers/display/display.c: -------------------------------------------------------------------------------- 1 | #define VIDEO_BUFFER_PTR (0xb8000) 2 | 3 | #include "display.h" 4 | #include "../../libs/device.h" 5 | 6 | void* display_funcs[] = { 7 | display_print_text, 8 | display_new_line, 9 | display_cursor_update, 10 | display_clear, 11 | display_get_current_symbol, 12 | display_delete_current_symbol, 13 | display_get_display_cursor_pos_x, 14 | display_get_display_cursor_pos_y, 15 | display_set_display_cursor_pos_x, 16 | display_set_display_cursor_pos_y 17 | }; 18 | 19 | // Нижний лимит по y 20 | const char display_limit_x_bottom = 79; 21 | const char display_limit_y_bottom = 24; 22 | 23 | unsigned char DISPLAY_CURSOR_POS_X; 24 | unsigned char DISPLAY_CURSOR_POS_Y; 25 | 26 | 27 | // Обновить курсор 28 | void display_cursor_update(struct dev_info* device){ 29 | int display_cursor_location = DISPLAY_CURSOR_POS_Y * 80 + DISPLAY_CURSOR_POS_X; 30 | outb(0x3D4, 14); 31 | outb(0x3D5, display_cursor_location >> 8); 32 | outb(0x3D4, 15); 33 | outb(0x3D5, display_cursor_location); 34 | } 35 | 36 | 37 | // Переход на новую (следующую) строку 38 | void display_new_line(struct dev_info* device){ 39 | if (DISPLAY_CURSOR_POS_Y >= display_limit_y_bottom){ 40 | DISPLAY_CURSOR_POS_Y = 0; 41 | display_clear(device); 42 | } 43 | else DISPLAY_CURSOR_POS_Y++; 44 | 45 | DISPLAY_CURSOR_POS_X = 0; 46 | display_cursor_update(device); 47 | } 48 | 49 | 50 | // Вывести символ на экран 51 | void display_print_symbol(unsigned char symbol, unsigned short x, unsigned short y, char font_color, char bkgr_color){ 52 | unsigned char* video_mem = (unsigned char*)VIDEO_BUFFER_PTR; 53 | video_mem += (80 * y + x) * 2; 54 | video_mem[0] = symbol; 55 | video_mem[1] = font_color; 56 | bkgr_color = bkgr_color << 4; 57 | video_mem[1] = video_mem[1] | bkgr_color; 58 | video_mem += 2; 59 | } 60 | 61 | 62 | // Вывести текст на экран 63 | void display_print_text(struct dev_info* device, unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bkgr_color){ 64 | 65 | DISPLAY_CURSOR_POS_X = x; 66 | DISPLAY_CURSOR_POS_Y = y; 67 | 68 | for (int i = 0; i < size; i++){ 69 | display_print_symbol(text[i], DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, font_color, bkgr_color); 70 | 71 | if ((x + 1) > display_limit_x_bottom){ 72 | DISPLAY_CURSOR_POS_Y++; 73 | DISPLAY_CURSOR_POS_X = 0; 74 | } 75 | else{ 76 | DISPLAY_CURSOR_POS_X++; 77 | } 78 | 79 | } 80 | 81 | } 82 | 83 | 84 | // Очистить весь экран 85 | void display_clear(struct dev_info* device){ 86 | unsigned char* video_mem = (unsigned char*)VIDEO_BUFFER_PTR; 87 | for (unsigned short y = 0; y < 25; y++){ 88 | for (unsigned short x = 0; x < 80; x++){ 89 | video_mem[0] = 0; 90 | video_mem[1] = 7; 91 | video_mem += 2; 92 | } 93 | } 94 | 95 | DISPLAY_CURSOR_POS_X = 0; 96 | DISPLAY_CURSOR_POS_Y = 0; 97 | display_cursor_update(device); 98 | } 99 | 100 | 101 | // Получить текущий символ (можно со смещением) 102 | unsigned char display_get_current_symbol(struct dev_info* device, short offset){ 103 | unsigned char* video_mem = (unsigned char*)VIDEO_BUFFER_PTR; 104 | video_mem += (80 * (DISPLAY_CURSOR_POS_Y) + (DISPLAY_CURSOR_POS_X)) * 2; 105 | video_mem += 2 * offset; 106 | return video_mem[0]; 107 | } 108 | 109 | 110 | // Удалить текущий символ (можно со смещением) 111 | void display_delete_current_symbol(struct dev_info* device, short offset){ 112 | unsigned char* video_mem = (unsigned char*)VIDEO_BUFFER_PTR; 113 | video_mem += (80 * (DISPLAY_CURSOR_POS_Y) + (DISPLAY_CURSOR_POS_X)) * 2; 114 | video_mem += 2 * offset; 115 | video_mem[0] = 0; 116 | video_mem[1] = 7; 117 | 118 | if (DISPLAY_CURSOR_POS_X == 0){ 119 | if (DISPLAY_CURSOR_POS_Y > 0){ 120 | DISPLAY_CURSOR_POS_Y--; 121 | DISPLAY_CURSOR_POS_X = 79; 122 | display_cursor_update(device); 123 | } 124 | } 125 | else{ 126 | DISPLAY_CURSOR_POS_X--; 127 | display_cursor_update(device); 128 | } 129 | } 130 | 131 | unsigned char display_get_display_cursor_pos_x(struct dev_info* device){ 132 | return DISPLAY_CURSOR_POS_X; 133 | } 134 | 135 | unsigned char display_get_display_cursor_pos_y(struct dev_info* device){ 136 | return DISPLAY_CURSOR_POS_Y; 137 | } 138 | 139 | void display_set_display_cursor_pos_x(struct dev_info* device, unsigned char x){ 140 | DISPLAY_CURSOR_POS_X = x; 141 | } 142 | 143 | void display_set_display_cursor_pos_y(struct dev_info* device, unsigned char y){ 144 | DISPLAY_CURSOR_POS_Y = y; 145 | } 146 | 147 | int display_init(struct dev_info* device){ 148 | display_clear(device); 149 | return 1; 150 | } 151 | -------------------------------------------------------------------------------- /src/kernel/IDT_PIC.c: -------------------------------------------------------------------------------- 1 | #include "IDT_PIC.h" 2 | #include "../libs/asm.h" 3 | 4 | // Главная структура: хранит обработчик для конкретного прерывания 5 | struct IDT_row 6 | { 7 | unsigned short low_bits; 8 | unsigned short segm_sel; 9 | unsigned char always0; 10 | unsigned char flags; 11 | unsigned short high_bits; 12 | } __attribute__((packed)); 13 | 14 | // Указатель на главную структуру 15 | struct IDT_ptr 16 | { 17 | unsigned short limit; 18 | unsigned int base; 19 | } __attribute__((packed)); 20 | 21 | // Инициализация структур 22 | struct IDT_row IDT_table[256]; 23 | struct IDT_ptr IDT_desc; 24 | 25 | 26 | unsigned char IRQ_MASTER_MASK = 0xff; 27 | unsigned char IRQ_SLAVE_MASK = 0xff; 28 | 29 | // Регистрация прерывания 30 | void IDT_reg_handler(int number, unsigned short segm_sel, unsigned short flags, intr_handler handler) 31 | { 32 | unsigned int handler_addr = (unsigned int) handler; 33 | IDT_table[number].low_bits = (unsigned short) (handler_addr & 0xFFFF); 34 | IDT_table[number].segm_sel = segm_sel; 35 | IDT_table[number].always0 = 0; 36 | IDT_table[number].flags = flags; 37 | IDT_table[number].high_bits = (unsigned short) (handler_addr >> 16); 38 | } 39 | 40 | 41 | // Загрузка таблицы прерываний 42 | void IDT_load() 43 | { 44 | int IDT_row_count = sizeof(IDT_table) / sizeof(IDT_table[0]); 45 | IDT_desc.base = (unsigned int)(&IDT_table[0]); 46 | IDT_desc.limit = (sizeof(struct IDT_row) * IDT_row_count) - 1; 47 | asm("lidt %0" : : "m" (IDT_desc)); 48 | } 49 | 50 | 51 | // Разрешить/включить прерывания 52 | void interrupt_enable() 53 | { 54 | asm("sti"); 55 | } 56 | 57 | 58 | // Запретить/выключить прерывания 59 | void interrupt_disable() 60 | { 61 | asm("cli"); 62 | } 63 | 64 | 65 | void PIC_set_mask(unsigned char master, unsigned char slave){ 66 | outb(0x21, master); 67 | outb(0xA1, slave); 68 | } 69 | 70 | 71 | // mst_sl - master или slave - 0: master - 1: slave 72 | // bit - какой бит 73 | // value - значение бита: 0 - 0, 1 - 1 74 | // Меняет бит в маске на 0 или 1 75 | void PIC_update_mask(unsigned char mst_sl, unsigned char bit, unsigned char value) { 76 | if (mst_sl == 0) { 77 | // Master 78 | if (value) 79 | IRQ_MASTER_MASK |= (1 << bit); // ставим 1 - выключаем 80 | else 81 | IRQ_MASTER_MASK &= ~(1 << bit); // ставим 0 - разрешаем 82 | } else if (mst_sl == 1) { 83 | // Slave 84 | if (value) 85 | IRQ_SLAVE_MASK |= (1 << bit); // ставим 1 - выключаем 86 | else 87 | IRQ_SLAVE_MASK &= ~(1 << bit); // ставим 0 - разрешаем 88 | } 89 | 90 | PIC_set_mask(IRQ_MASTER_MASK, IRQ_SLAVE_MASK); 91 | } 92 | 93 | 94 | // Инициализация PIC для того, чтобы наши прерывания не пересекались с прерываниями процессора 95 | void PIC_remap(){ 96 | 97 | interrupt_disable(); 98 | 99 | // IRQ - аппратная линия, по которому устройство может отправить прерывание 100 | 101 | // Master - управляет первой групой IRQ (0-7) 102 | // Slave - дополнительный, соединяется с Master по IRQ2 и обрабатывает вторую группу IRQ (8-15) 103 | 104 | // ICW - (Initialization Command Words) - управляющие команды, определяющие в каком режиме работать, куда кидать вектор прерывания, как связаны Master и Slave 105 | // Каждая ICW посылается через порты: 0x20/0x21 (master) и 0xA0/0xA1 (slave). 106 | 107 | 108 | // ICW1: начинаем инициализацию 109 | // 0x11 = 00010001b 110 | // бит 4 (1) - начинаем инициализацию 111 | // бит 0 (1) - будет ICW4, жди ICW4: 112 | outb(0x20, 0x11); in_out_wait(); // Master 113 | outb(0xA0, 0x11); in_out_wait(); // Slave 114 | 115 | 116 | // ICW2: задаём базовые адреа вектора прерываний. Самое важное 117 | // PIC выдает CPU номера векторов (0-15) 118 | // нужно сказать с какого номера начинать: 119 | // Master: 0x20 (т.е IRQ0 = 0x20, IRQ1 = 0x21...): 120 | outb(0x21, 0x20); in_out_wait(); 121 | // Slave: 0x28 (т.е IRQ8 = 0x28, IRQ15 = 0x2F...): 122 | outb(0xA1, 0x28); in_out_wait(); 123 | 124 | 125 | // ICW3: как master и slave соединены 126 | // Master: У меня есть Slave на линии IRQ2 (0x04 = 00000100. Т.е бит 2 (1) = IRQ2): 127 | outb(0x21, 0x04); in_out_wait(); 128 | // Slave: Я подключен к мастеру через IRQ2 (0x02 - номер линии - IRQ2): 129 | outb(0xA1, 0x02); in_out_wait(); 130 | 131 | // ICW4: режим работы 132 | // Итого: работай в обычном 8086-совместимом режиме 133 | // Бит 0 = 1 - 8086/88 mode (совеременные CPU): 134 | outb(0x21, 0x01); in_out_wait(); 135 | // Бит 4 = 0 - не использовать "special fully nested mode": 136 | outb(0xA1, 0x01); in_out_wait(); 137 | 138 | 139 | // Master: разрешаем только прерывания PIT (IRQ0) и клавиатуры (IRQ1) 140 | // Расшифровка (11111100): 141 | // бит 7 — IRQ7 (1 → выключен) 142 | // бит 6 — IRQ6 (1 → выключен) 143 | // бит 5 — IRQ5 (1 → выключен) 144 | // бит 4 — IRQ4 (1 → выключен) 145 | // бит 3 — IRQ3 (1 → выключен) 146 | // бит 2 — IRQ2 (1 → выключен) 147 | // бит 1 — IRQ1 (0 → включен) 148 | // бит 0 — IRQ0 (0 → включен) 149 | PIC_set_mask(0b11111111, 0xFF); 150 | // Slave: всё выключено 151 | // Расшифровка (1111111): 152 | // бит 0-7 — IRQ8-IRQ15 (1 - выключен) 153 | 154 | interrupt_enable(); 155 | 156 | } 157 | -------------------------------------------------------------------------------- /src/drivers/ata/ata.c: -------------------------------------------------------------------------------- 1 | #define ATA_BASE 0x1F0 2 | 3 | #include "ata.h" 4 | #include "../../libs/device.h" 5 | 6 | 7 | void* ata_funcs[] = { 8 | 9 | }; 10 | 11 | 12 | // стандартная задержка для ATA 13 | void ata_delay(){ 14 | inb(ATA_BASE + 7); 15 | inb(ATA_BASE + 7); 16 | inb(ATA_BASE + 7); 17 | inb(ATA_BASE + 7); 18 | } 19 | 20 | // Ожидание готовности принятия или отдачи данных и проверяет Занято ли устройство 21 | int ata_wait_ready() { 22 | int timeout = 1000000; 23 | while (timeout-- > 0) { 24 | unsigned char status = inb(ATA_BASE + 7); 25 | 26 | if ((status & 0b10000000) == 0) { // BSY=0 27 | // в QEMU не работают 28 | // if (status & 0x01) return -1; // ERR 29 | // if (status & 0x20) return -1; // Device Fault 30 | // if (status & 0b00001000) return 0; // DRQ 31 | return 0; 32 | } 33 | in_out_wait(); 34 | 35 | } 36 | return -1; // Timeout 37 | } 38 | 39 | int ata_get_err(){ 40 | unsigned char status = inb(ATA_BASE + 7); 41 | if (status & 0x01) return -1; // ERR 42 | if (status & 0x20) return -1; // DF 43 | else return 0; // ok 44 | } 45 | 46 | // Читаем данные с диска 47 | // Читаем 512 байт (один сектор) 48 | void ata_read(unsigned short* buffer){ 49 | for (int i = 0; i < 256; i++) { 50 | unsigned short word = inw(ATA_BASE); 51 | buffer[i] = word; 52 | } 53 | } 54 | 55 | // Записываем данные на диск 56 | // Записываем 512 байт (один сектор) 57 | void ata_write(unsigned short* src){ 58 | for (int i = 0; i < 256; i++) { 59 | unsigned short word = src[i]; 60 | outw(ATA_BASE, word); 61 | } 62 | } 63 | 64 | 65 | // Есть ли диск 66 | // 0 - ok, -1 - not found 67 | int ata_driver_find_master_disks(){ 68 | 69 | // Проверяем подключен ли вообще диск 70 | 71 | outb(ATA_BASE + 6, 0xA0); // Выбираем диск (Master) 72 | outb(ATA_BASE + 2, 0); 73 | outb(ATA_BASE + 3, 0); 74 | outb(ATA_BASE + 4, 0); 75 | outb(ATA_BASE + 5, 0); 76 | ata_delay(); 77 | unsigned char status = inb(ATA_BASE + 7); // Читаем подключено ли 78 | if (status == 0xFF || status == 0x00){ 79 | return -1; // нет 80 | } 81 | 82 | // Если подключено то ждем пока диск ответит 83 | int is_timeout = ata_wait_ready(); 84 | if (is_timeout == -1){ 85 | return -1; // timeout 86 | } 87 | 88 | // IDENTIFY command 89 | outb(ATA_BASE + 7, 0xEC); 90 | 91 | ata_delay(); 92 | 93 | // Get status 94 | status = inb(ATA_BASE + 7); 95 | 96 | if (status == 0){ 97 | return -1; // не существует 98 | } 99 | 100 | 101 | // В QEMU не работает 102 | // unsigned char lbamid = inb(ATA_BASE + 4); 103 | // unsigned char lbahi = inb(ATA_BASE + 5); 104 | // if (lbamid == 0 && lbahi == 0){ 105 | // return -1; // не является ATA диском 106 | // } 107 | 108 | 109 | if (ata_wait_ready() == -1){ 110 | return -1; 111 | } 112 | else{ 113 | // Читаем IDENTIFY 114 | unsigned short ident_buffer[256]; 115 | ata_read(ident_buffer); 116 | 117 | // Модель диска 118 | char model[41]; 119 | 120 | // Чтение модели из регистров 27-46 121 | for (int i = 27; i <= 46; i++) { 122 | model[(i-1)*2] = ident_buffer[i] & 0x00ff; // Младший байт из регистра 123 | model[(i-1)*2 + 1] = (ident_buffer[i] >> 8) & 0x00ff; // Старший байт из регистра 124 | } 125 | 126 | // Завершаем строку нулевым символом 127 | model[40] = '\0'; 128 | 129 | // Количество секторов на диске 130 | unsigned int sector_count = (unsigned int)(ident_buffer[60] & 0x0000FFFF) | (unsigned int)((ident_buffer[61] << 16) & 0xFFFF0000); 131 | 132 | // диск, модель, размер модели, кол-во секторов, is_master, тип диска ATA 133 | device_reg(1, model, 41, sector_count, 1, 1); 134 | 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | 141 | // Чтение определенного секотра 142 | // lba - номер сектора 143 | // buffer - буффер 144 | int ata_driver_read_sector(unsigned int lba, unsigned char* buffer) { 145 | 146 | // Проверяем и ждем готовность диска 147 | if (ata_wait_ready() < 0) return -1; 148 | 149 | // Выбираем диск Master + LBA (старший байт) 150 | outb(ATA_BASE + 6, 0xE0 | ((lba >> 24) & 0x0F)); 151 | 152 | // Параметры 153 | outb(ATA_BASE + 2, 1); // кол-во секторов: 1 154 | outb(ATA_BASE + 3, lba & 0xFF); // LBA 0-7 155 | outb(ATA_BASE + 4, (lba >> 8) & 0xFF); // LBA 8-15 156 | outb(ATA_BASE + 5, (lba >> 16) & 0xFF); // LBA 16-23 157 | 158 | // Команда чтения 159 | outb(ATA_BASE + 7, 0x20); 160 | 161 | // Проверяем и ждем готовность диска 162 | if (ata_wait_ready() < 0) return -1; 163 | 164 | // Читаем 512 байт (один сектор) 165 | unsigned short temp[256]; 166 | ata_read(temp); 167 | 168 | // переводим из массива short 169 | for (int i = 0; i < 256; i++) { 170 | buffer[i*2] = temp[i] & 0xFF; // младший байт 171 | buffer[i*2 + 1] = (temp[i] >> 8) & 0xFF; // старший байт 172 | } 173 | 174 | // Возвращаем статус ошибки: 0 ок, -1 ошибка 175 | return ata_get_err(); 176 | } 177 | 178 | int ata_driver_write_sector(unsigned int lba, unsigned char* src){ 179 | // Проверяем и ждем готовность диска 180 | if (ata_wait_ready() < 0) return -1; 181 | 182 | // Выбираем диск Master + LBA (старший байт) 183 | outb(ATA_BASE + 6, 0xE0 | ((lba >> 24) & 0x0F)); 184 | 185 | // Параметры 186 | outb(ATA_BASE + 2, 1); // кол-во секторов: 1 187 | outb(ATA_BASE + 3, lba & 0xFF); // LBA 0-7 188 | outb(ATA_BASE + 4, (lba >> 8) & 0xFF); // LBA 8-15 189 | outb(ATA_BASE + 5, (lba >> 16) & 0xFF); // LBA 16-23 190 | 191 | // Команда записи 192 | outb(ATA_BASE + 7, 0x30); 193 | 194 | // Проверяем и ждем готовность диска 195 | if (ata_wait_ready() < 0) return -1; 196 | 197 | // переводим в массив short 198 | unsigned short temp[256]; 199 | for (int i = 0; i < 256; i++) { 200 | temp[i] = src[i*2] | (src[i*2 + 1] << 8); // младший байт | старший байт 201 | } 202 | 203 | // Записываем 512 байт (один сектор) 204 | ata_write(temp); 205 | 206 | // Проверяем и ждем готовность диска 207 | if (ata_wait_ready() < 0) return -1; 208 | 209 | // Возвращаем статус ошибки: 0 ок, -1 ошибка 210 | return ata_get_err(); 211 | } 212 | 213 | 214 | int ata_init(struct dev_info* device){ 215 | 216 | } 217 | -------------------------------------------------------------------------------- /programs/terminal/terminal.c: -------------------------------------------------------------------------------- 1 | #define TERMINAL_BUFFER_SIZE 1024 2 | #define KEYBOARD_BUFFER_SIZE 16 3 | 4 | #include "../libs/shared_memory.h" 5 | #include "../libs/asm.c" 6 | #include "../libs/string.c" 7 | #include "../libs/io.c" 8 | #include "../libs/time.c" 9 | #include "../libs/programs.c" 10 | 11 | // Header: start 12 | volatile unsigned char _start_header[16] __attribute__((section(".start_header"))) = {'_','_','_','I','A','M','P','R','O','G','R','A','M','_','_','_'}; 13 | // Header: info 14 | volatile unsigned char _info_header[20] __attribute__((section(".info_header"))) = "terminal"; 15 | // Header: end 16 | volatile unsigned char _end_header[16] __attribute__((section(".end_header"))) = {'_','_','_','E','N','D','P','R','O','G','R','A','M','_','_','_'}; 17 | 18 | // Local memory 19 | volatile unsigned char keyboard_buffer_tail; 20 | volatile unsigned char terminal_buffer[TERMINAL_BUFFER_SIZE+1]; 21 | volatile unsigned short terminal_ptr = 0; 22 | 23 | char limit_y_top = 0; 24 | 25 | char terminal_default_font_color = 7; 26 | char terminal_default_bckd_color = 0; 27 | 28 | 29 | void terminal_buffer_clear(){ 30 | terminal_buffer[TERMINAL_BUFFER_SIZE+1] = '\0'; 31 | for(unsigned short i = 0; i < TERMINAL_BUFFER_SIZE; i++){ 32 | terminal_buffer[i] = '\0'; 33 | } 34 | terminal_ptr = 0; 35 | } 36 | 37 | 38 | 39 | 40 | 41 | void terminal_command_handler(){ 42 | 43 | // Commands 44 | unsigned char cmd_help[5] = "help"; 45 | unsigned char cmd_list[5] = "list"; 46 | unsigned char cmd_clear[6] = "clear"; 47 | unsigned char cmd_uptime[7] = "uptime"; 48 | unsigned char cmd_poweroff[9] = "poweroff"; 49 | 50 | // Data for commands 51 | char* cmd_help_text = "Available commands:\n| [NUMBER] - run program\n| list - view programs\n| clear - clear display\n| poweroff - shutdown system"; 52 | 53 | // Clear 54 | if (is_str_equally(&cmd_clear, strlen(&cmd_clear), &terminal_buffer)){ 55 | io_clear(); 56 | } 57 | 58 | // Number - Run program 59 | else if (is_digit(&terminal_buffer)){ 60 | int prog_num; 61 | stoi(&terminal_buffer, &prog_num); 62 | program_run(prog_num); 63 | } 64 | 65 | // Other commands 66 | else{ 67 | 68 | // Help 69 | if (is_str_equally(&cmd_help, strlen(&cmd_help), &terminal_buffer)){ 70 | print(cmd_help_text); 71 | } 72 | 73 | // List 74 | else if (is_str_equally(&cmd_list, strlen(&cmd_list), &terminal_buffer)){ 75 | print("All programs in disk:"); 76 | for (int i = 1; i < PROGLOADER_PROGRAM_COUNT; i++){ 77 | 78 | char num[3] = {0,0,0}; 79 | itos(i, &num); 80 | print(num); 81 | DISPLAY_CURSOR_POS_Y--; 82 | DISPLAY_CURSOR_POS_X++; 83 | DISPLAY_CURSOR_POS_X++; 84 | DISPLAY_CURSOR_POS_X++; 85 | DISPLAY_CURSOR_POS_X++; 86 | print(((struct program_info*)PROGLOADER_PROGRAMS)[i].name); 87 | } 88 | } 89 | 90 | // Poweroff 91 | else if (is_str_equally(&cmd_poweroff, strlen(&cmd_poweroff), &terminal_buffer)){ 92 | outw(0x604, 0x2000); 93 | } 94 | 95 | else { 96 | 97 | // Chech name programs and run 98 | for (int i = 1; i < PROGLOADER_PROGRAM_COUNT; i++){ 99 | if (is_str_equally(((struct program_info*)PROGLOADER_PROGRAMS)[i].name, strlen(((struct program_info*)PROGLOADER_PROGRAMS)[i].name), &terminal_buffer)){ 100 | program_run(i); 101 | } 102 | } 103 | 104 | // Unknow command 105 | print("Command not found!"); 106 | } 107 | 108 | limit_y_top = DISPLAY_CURSOR_POS_Y; 109 | 110 | } 111 | } 112 | 113 | void terminal_enter_key_handler(){ 114 | limit_y_top = DISPLAY_CURSOR_POS_Y; 115 | terminal_buffer[terminal_ptr] = '\0'; 116 | terminal_ptr = (terminal_ptr+1) % TERMINAL_BUFFER_SIZE; 117 | io_new_line(); 118 | if (terminal_ptr > 1) terminal_command_handler(); 119 | terminal_buffer_clear(); 120 | } 121 | 122 | void terminal_backspace_key_handler(){ 123 | while (1){ 124 | if (DISPLAY_CURSOR_POS_X == 0 && DISPLAY_CURSOR_POS_Y - 1 == limit_y_top) break; 125 | else{ 126 | io_delete_current_symbol(-1); 127 | terminal_ptr--; 128 | terminal_buffer[terminal_ptr] = '\0'; 129 | unsigned char symbol = io_get_current_symbol(-1); 130 | if ((DISPLAY_CURSOR_POS_Y > 0 || (DISPLAY_CURSOR_POS_Y == 0 && DISPLAY_CURSOR_POS_X > 0)) && symbol == '\0' && DISPLAY_CURSOR_POS_X != 0) continue; 131 | else break; 132 | } 133 | } 134 | } 135 | 136 | void terminal_other_key_handler(unsigned char scancode){ 137 | unsigned char symbol = scancode_to_ascii(scancode, KEYBOARD_SHIFT_PRESSED); 138 | if (symbol != '\0'){ 139 | terminal_buffer[terminal_ptr] = symbol; 140 | terminal_ptr = (terminal_ptr+1) % TERMINAL_BUFFER_SIZE; 141 | io_printx_symbol(symbol, DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, terminal_default_font_color, terminal_default_bckd_color); 142 | io_cursor_update(); 143 | } 144 | } 145 | 146 | void cursor(){ 147 | io_printx_symbol('>', DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, terminal_default_font_color, terminal_default_bckd_color); 148 | io_printx_symbol(' ', DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, terminal_default_font_color, terminal_default_bckd_color); 149 | io_cursor_update(); 150 | } 151 | 152 | void terminal_scancode_handler(unsigned char scancode){ 153 | 154 | // Enter 155 | if (scancode == 28){ 156 | terminal_enter_key_handler(); 157 | cursor(); 158 | } 159 | 160 | // BackSpace 161 | else if (scancode == 14){ 162 | terminal_backspace_key_handler(); 163 | } 164 | 165 | // Other 166 | else{ 167 | terminal_other_key_handler(scancode); 168 | } 169 | 170 | } 171 | 172 | void terminal_keyboard_listen(){ 173 | keyboard_buffer_tail = KEYBOARD_BUFFER_PTR; 174 | while (1){ 175 | if (keyboard_buffer_tail != KEYBOARD_BUFFER_PTR){ 176 | unsigned char scancode; 177 | scancode = KEYBOARD_BUFFER[keyboard_buffer_tail]; 178 | terminal_scancode_handler(scancode); 179 | keyboard_buffer_tail = (keyboard_buffer_tail+1) % KEYBOARD_BUFFER_SIZE; 180 | } 181 | sleep(10); 182 | } 183 | } 184 | 185 | void terminal_init(){ 186 | // io_clear(); 187 | terminal_buffer_clear(); 188 | cursor(); 189 | io_cursor_update(); 190 | terminal_keyboard_listen(); 191 | } 192 | 193 | void _start(void) __attribute__((section(".text.start"))); 194 | void _start(){ 195 | terminal_init(); 196 | } 197 | -------------------------------------------------------------------------------- /programs/term2/term2.c: -------------------------------------------------------------------------------- 1 | // Header: start 2 | volatile unsigned char _start_header[16] __attribute__((section(".start_header"))) = {'_','_','_','I','A','M','P','R','O','G','R','A','M','_','_','_'}; 3 | // Header: info 4 | volatile unsigned char _info_header[20] __attribute__((section(".info_header"))) = "term2"; 5 | // Header: end 6 | volatile unsigned char _end_header[16] __attribute__((section(".end_header"))) = {'_','_','_','E','N','D','P','R','O','G','R','A','M','_','_','_'}; 7 | 8 | #define TERM_BUFFER_SIZE 1024 9 | #define KEYBOARD_BUFFER_SIZE 16 10 | 11 | #include "../../libs/asm.h" 12 | #include "../../libs/shared_memory.h" 13 | #include "../../libs/string.h" 14 | #include "../../libs/io.h" 15 | #include "../../libs/programs.h" 16 | 17 | 18 | volatile unsigned char keyboard_buffer_tail = 0; 19 | volatile unsigned char term_buffer[TERM_BUFFER_SIZE]; 20 | volatile unsigned char term_buffer_ptr = 0; 21 | 22 | volatile char term_default_font_color = 7; 23 | volatile char term_default_bckd_color = 0; 24 | 25 | volatile char term_prompt_font_color = 2; 26 | volatile char term_prompt_bckd_color = 0; 27 | 28 | // Лимит для backspace: до лимита не подняться 29 | volatile unsigned char term_pos_x_limit = 0; 30 | volatile unsigned char term_pos_y_limit = 0; 31 | 32 | // Commands 33 | unsigned char cmd_help[5] = "help"; 34 | unsigned char cmd_progs[6] = "progs"; 35 | unsigned char cmd_progsload[10] = "progsload"; 36 | unsigned char cmd_clear[6] = "clear"; 37 | unsigned char cmd_poweroff[9] = "poweroff"; 38 | 39 | // Data for commands 40 | unsigned char* cmd_help_text = "Available commands:\n| [PROGRAM NAME] - run program\n| progs - view programs\n| progsload - load programs from disk\n| clear - clear display\n| poweroff - shutdown system"; 41 | 42 | 43 | // Чистим буффер терминала 44 | void term_buffer_clear(){ 45 | term_buffer[TERM_BUFFER_SIZE] = '\0'; 46 | for(int i = 0; i < TERM_BUFFER_SIZE; i++){ 47 | term_buffer[i] = '\0'; 48 | } 49 | term_buffer_ptr = 0; 50 | } 51 | 52 | // Prompt - приглашение командой строки 53 | void term_prompt(){ 54 | io_printx("> ", DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, term_prompt_font_color, term_prompt_bckd_color); 55 | term_pos_x_limit = DISPLAY_CURSOR_POS_X; 56 | term_pos_y_limit = DISPLAY_CURSOR_POS_Y; 57 | } 58 | 59 | // Обработчик команд 60 | void term_command_handler(){ 61 | // Clear 62 | if (is_str_equally(&cmd_clear, &term_buffer)){ 63 | io_clear(); 64 | } 65 | 66 | // Help 67 | else if (is_str_equally(&cmd_help, &term_buffer)){ 68 | print(cmd_help_text); 69 | } 70 | 71 | // Progs 72 | else if (is_str_equally(&cmd_progs, &term_buffer)){ 73 | print("All programs in disk:"); 74 | for (int i = 1; i < PROGLOADER_PROGRAM_COUNT; i++){ 75 | io_printx(" - ", DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, term_default_font_color, term_default_bckd_color); 76 | print(PROGLOADER_PROGRAMS[i].name); 77 | } 78 | } 79 | 80 | // ProgsLoad 81 | else if (is_str_equally(&cmd_progsload, &term_buffer)){ 82 | print("Load programs from disk..."); 83 | programs_load(); 84 | print("Completed!"); 85 | } 86 | 87 | // Poweroff 88 | else if (is_str_equally(&cmd_poweroff, &term_buffer)){ 89 | 90 | } 91 | 92 | // Other 93 | else{ 94 | 95 | // Chech name programs and run 96 | for (int i = 1; i < PROGLOADER_PROGRAM_COUNT; i++){ 97 | if (is_str_equally(PROGLOADER_PROGRAMS[i].name, &term_buffer)){ 98 | program_run(i); 99 | return; 100 | } 101 | } 102 | 103 | // Unknow command 104 | print("Command not found!"); 105 | 106 | } 107 | } 108 | 109 | // Обработчик Enter 110 | void term_enter_key_handler(){ 111 | // Заканчиваем строку 112 | term_buffer[term_buffer_ptr] = '\0'; 113 | term_buffer_ptr = (term_buffer_ptr+1) % TERM_BUFFER_SIZE; 114 | // Новая линия для вывода команды 115 | io_new_line(); 116 | // Обрабатываем введенную команду 117 | if (term_buffer_ptr > 0) term_command_handler(); 118 | // Сброс буфера 119 | term_buffer_clear(); 120 | // Prompt 121 | if (EXECUTE_PROGRAM == 0){ 122 | term_prompt(); 123 | } 124 | } 125 | 126 | // Обработчик BackSpace 127 | void term_backspace_key_handler(){ 128 | if ((DISPLAY_CURSOR_POS_X > term_pos_x_limit && DISPLAY_CURSOR_POS_Y == term_pos_y_limit) || DISPLAY_CURSOR_POS_Y > term_pos_y_limit){ 129 | io_delete_current_symbol(-1); 130 | term_buffer_ptr--; 131 | term_buffer[term_buffer_ptr] = '\0'; 132 | } 133 | } 134 | 135 | // Обработчик символов 136 | void term_symbol_key_handler(unsigned char scancode){ 137 | unsigned char symbol = scancode_to_ascii(scancode, KEYBOARD_SHIFT_PRESSED); 138 | if (symbol != '\0'){ 139 | 140 | term_buffer[term_buffer_ptr] = symbol; 141 | term_buffer_ptr = (term_buffer_ptr+1) % TERM_BUFFER_SIZE; 142 | 143 | io_printx_symbol(symbol, DISPLAY_CURSOR_POS_X, DISPLAY_CURSOR_POS_Y, term_default_font_color, term_default_bckd_color); 144 | 145 | io_cursor_update(); 146 | 147 | } 148 | } 149 | 150 | // Общий обработчик всех сканкодов 151 | void term_scancode_handler(unsigned char scancode){ 152 | 153 | // Enter 154 | if (scancode == 28){ 155 | term_enter_key_handler(); 156 | } 157 | 158 | // Backspace 159 | else if (scancode == 14){ 160 | term_backspace_key_handler(); 161 | } 162 | 163 | // Symbols 164 | else if (is_symbol_scancode(scancode)){ 165 | term_symbol_key_handler(scancode); 166 | } 167 | } 168 | 169 | // Слушаем клавиатуру (буффер клавиатуры) 170 | void term_keyboard_listen(){ 171 | 172 | // Обновляем хвост на текущий указатель на эллемент буфера клавиатуры 173 | keyboard_buffer_tail = KEYBOARD_BUFFER_PTR; 174 | 175 | while(1){ 176 | 177 | // Если появилась программа на исполнение 178 | if (EXECUTE_PROGRAM > 0){ 179 | return; 180 | } 181 | 182 | // Нажата клавиша 183 | if (keyboard_buffer_tail != KEYBOARD_BUFFER_PTR){ 184 | unsigned char scancode = KEYBOARD_BUFFER[keyboard_buffer_tail]; // Получаем сканкод 185 | term_scancode_handler(scancode); // Обрабатываем сканкод 186 | keyboard_buffer_tail = (keyboard_buffer_tail+1) % KEYBOARD_BUFFER_SIZE; // Обновляем хвост, т.е делаем +1 187 | } 188 | 189 | // Спим чтобы не лагало 190 | sleep(10); 191 | } 192 | } 193 | 194 | // Инициализация терминала 195 | void term_init(){ 196 | term_buffer_clear(); 197 | term_prompt(); 198 | term_keyboard_listen(); 199 | } 200 | 201 | 202 | // Entry point 203 | void _start(void) __attribute__((section(".text.start"))); 204 | void _start(){ 205 | term_init(); 206 | } 207 | -------------------------------------------------------------------------------- /programs/libs/device.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_DEVICE 2 | #define INCL_LIB_DEVICE 3 | 4 | #define MAX_DEVICE_COUNT 256 5 | 6 | // Информация о устройстве 7 | struct dev_info{ 8 | 9 | unsigned char is_pci_dev; // 0 or 1 10 | unsigned char is_virt_dev; // 0 or 1 11 | 12 | unsigned int bus; 13 | unsigned int dev; 14 | unsigned int func; 15 | 16 | unsigned short vendor_id; 17 | unsigned short device_id; 18 | 19 | unsigned short command; 20 | unsigned short status; 21 | 22 | unsigned char revision_id; 23 | unsigned char prog_if; 24 | 25 | unsigned char subclass; 26 | unsigned char classcode; 27 | 28 | unsigned char cache_line_size; 29 | unsigned char latency_timer; 30 | 31 | unsigned char mf; 32 | unsigned char header_type; 33 | 34 | unsigned char bist; 35 | 36 | unsigned int bar0; 37 | unsigned int bar1; 38 | unsigned int bar2; 39 | unsigned int bar3; 40 | unsigned int bar4; 41 | unsigned int bar5; 42 | 43 | struct driver_info* driver; 44 | 45 | }; 46 | 47 | 48 | enum virt_class_codes{ 49 | VIRT_DISPLAY_CONTROLLER = 0x20, 50 | VIRT_KEYBOARD_CONTROLLER = 0x21, 51 | }; 52 | 53 | enum virt_display_subclass{ 54 | VIRT_DISPLAY_VGATEXT = 0x0, 55 | }; 56 | 57 | enum virt_keyboard_subclass{ 58 | VIRT_KEYBOARD_LDEV = 0x0, 59 | }; 60 | 61 | 62 | enum class_codes{ 63 | UNCLASSIFIED = 0x0, 64 | STORAGE_CONTROLLER = 0x1, 65 | NETWORK_CONTROLLER = 0x2, 66 | DISPLAY_CONTROLLER = 0x3, 67 | MULTIMEDIA_CONTROLLER = 0x4, 68 | MEMORY_CONTROLLER = 0x5, 69 | BRIDGE = 0x6, 70 | SIMPLE_COMMUNICATION_CONTROLLER = 0x7, 71 | BASE_SYSTEM_PERIPHERAL = 0x8, 72 | INPUT_DEVICE_CONTROLLER = 0x9, 73 | DOCKING_STATION = 0xA, 74 | PROCESSOR = 0xB, 75 | SERIAL_BUS_CONTROLLER = 0xC, 76 | WIRELESS_CONTROLLER = 0xD, 77 | INTELLIGENT_CONTROLLER = 0xE, 78 | SATELLITE_COMMUNICATION_CONTROLLER = 0xF, 79 | ENCRYPTION_CONTROLLER = 0x10, 80 | SIGNAL_PROCESSING_CONTROLLER = 0x11, 81 | PROCESSING_ACCELERATOR = 0x12, 82 | NON_ESSENTIAL_INSTRUMENTATION = 0x13, 83 | 84 | RESERVED_BEGIN = 0x14, 85 | RESERVED_END = 0x3F, 86 | CO_PROCESSOR = 0x40, 87 | _0xFE_RESERVED = 0xFE, 88 | UNASSIGNED_CLASS = 0xFF 89 | }; 90 | 91 | enum storage_subclass { 92 | STORAGE_SCSI_BUS_CONTROLLER = 0x00, 93 | STORAGE_IDE_CONTROLLER = 0x01, 94 | STORAGE_FLOPPY_DISK_CONTROLLER = 0x02, 95 | STORAGE_IPI_BUS_CONTROLLER = 0x03, 96 | STORAGE_RAID_CONTROLLER = 0x04, 97 | STORAGE_ATA_CONTROLLER = 0x05, 98 | STORAGE_SERIAL_ATA_CONTROLLER = 0x06, 99 | STORAGE_SERIAL_ATTACHED_SCSI = 0x07, 100 | STORAGE_NON_VOLATILE_MEMORY = 0x08, 101 | STORAGE_OTHER = 0x80, 102 | }; 103 | 104 | enum network_subclass { 105 | NETWORK_ETHERNET_CONTROLLER = 0x0, 106 | NETWORK_TOKEN_RING_CONTROLLER = 0x1, 107 | NETWORK_FDDI_CONTROLLER = 0x2, 108 | NETWORK_ATM_CONTROLLER = 0x3, 109 | NETWORK_ISDN_CONTROLLER = 0x4, 110 | NETWORK_WORLDFIP_CONTROLLER = 0x5, 111 | NETWORK_PICMG_MC_CONTROLLER = 0x6, 112 | NETWORK_INFINIBAND_CONTROLLER = 0x7, 113 | NETWORK_FABRIC_CONTROLLER = 0x8, 114 | NETWORK_OTHER = 0x80, 115 | }; 116 | 117 | enum display_subclass { 118 | DISPLAY_VGA_COMPATIBLE = 0x00, 119 | DISPLAY_XGA = 0x01, 120 | DISPLAY_3D = 0x02, 121 | DISPLAY_OTHER = 0x80 122 | }; 123 | 124 | enum multimedia_subclass { 125 | MULTIMEDIA_VIDEO = 0x00, 126 | MULTIMEDIA_AUDIO = 0x01, 127 | MULTIMEDIA_TELEPHONY = 0x02, 128 | MULTIMEDIA_AUDIO_DEVICE = 0x03, 129 | MULTIMEDIA_OTHER = 0x80 130 | }; 131 | 132 | enum memory_subclass { 133 | MEMORY_RAM = 0x00, 134 | MEMORY_FLASH = 0x01, 135 | MEMORY_OTHER = 0x80 136 | }; 137 | 138 | enum bridge_subclass { 139 | BRIDGE_HOST = 0x00, 140 | BRIDGE_ISA = 0x01, 141 | BRIDGE_EISA = 0x02, 142 | BRIDGE_MCA = 0x03, 143 | BRIDGE_PCI_TO_PCI = 0x04, 144 | BRIDGE_PCMCIA = 0x05, 145 | BRIDGE_NUBUS = 0x06, 146 | BRIDGE_CARDBUS = 0x07, 147 | BRIDGE_RACEWAY = 0x08, 148 | BRIDGE_PCI_TO_PCI1 = 0x09, 149 | BRIDGE_INFINIBAND_TO_PCI = 0x0A, 150 | BRIDGE_OTHER = 0x80 151 | }; 152 | 153 | enum scomm_subclass { 154 | SCOMM_SERIAL = 0x00, 155 | SCOMM_PARALLEL = 0x01, 156 | SCOMM_MULTI_SERIAL = 0x02, 157 | SCOMM_MODEM = 0x03, 158 | SCOMM_GPIB = 0x04, 159 | SCOMM_SMART_CARD = 0x05, 160 | SCOMM_OTHER = 0x80 161 | }; 162 | 163 | enum base_sys_peripheral_subclass { 164 | BSP_PIC = 0x00, 165 | BSP_DMA = 0x01, 166 | BSP_TIMER = 0x02, 167 | BSP_RTC = 0x03, 168 | BSP_PCI_HOTPLUG = 0x04, 169 | BSP_SD_HOST = 0x05, 170 | BSP_IOMMU = 0x06, 171 | BSP_OTHER = 0x80 172 | }; 173 | 174 | enum input_device_subclass { 175 | INPUT_KEYBOARD = 0x00, 176 | INPUT_DIGITIZER = 0x01, 177 | INPUT_MOUSE = 0x02, 178 | INPUT_SCANNER = 0x03, 179 | INPUT_GAMEPORT = 0x04, 180 | INPUT_OTHER = 0x80 181 | }; 182 | 183 | enum docking_station_subclass { 184 | OCK_GENERIC = 0x00, 185 | DOCK_OTHER = 0x80 186 | }; 187 | 188 | enum processor_subclass { 189 | PROC_386 = 0x00, 190 | PROC_486 = 0x01, 191 | PROC_PENTIUM = 0x02, 192 | PROC_PENTIUM_PRO = 0x03, 193 | PROC_ALPHA = 0x10, 194 | PROC_POWERPC = 0x20, 195 | PROC_MIPS = 0x30, 196 | PROC_CO_PROCESSOR = 0x40, 197 | PROC_OTHER = 0x80 198 | }; 199 | 200 | enum serbus_subclass { 201 | SERBUS_FIREWIRE = 0x00, 202 | SERBUS_ACCESS = 0x01, 203 | SERBUS_SSA = 0x02, 204 | SERBUS_USB = 0x03, 205 | SERBUS_FIBRE_CHANNEL = 0x04, 206 | SERBUS_SMBUS = 0x05, 207 | SERBUS_INFINIBAND = 0x06, 208 | SERBUS_IPMI = 0x07, 209 | SERBUS_SERCOS = 0x08, 210 | SERBUS_CANBUS = 0x09, 211 | SERBUS_OTHER = 0x80 212 | }; 213 | 214 | enum wireless_subclass { 215 | WIRELESS_IRDA = 0x00, 216 | WIRELESS_CONSUMER_IR = 0x01, 217 | WIRELESS_RF = 0x10, 218 | WIRELESS_BLUETOOTH = 0x11, 219 | WIRELESS_BROADBAND = 0x12, 220 | WIRELESS_ETHERNET_A = 0x20, 221 | WIRELESS_ETHERNET_B = 0x21, 222 | WIRELESS_OTHER = 0x80 223 | }; 224 | 225 | enum intelligent_subclass { 226 | INTELLIGENT_I20 = 0x00 227 | }; 228 | 229 | enum satcomm_subclass { 230 | SATCOMM_TV = 0x01, 231 | SATCOMM_AUDIO = 0x02, 232 | SATCOMM_VOICE = 0x03, 233 | SATCOMM_DATA = 0x04 234 | }; 235 | 236 | enum encryption_subclass { 237 | ENCRYPTION_NET_COMP = 0x00, 238 | ENCRYPTION_ENTERTAIN = 0x10, 239 | ENCRYPTION_OTHER = 0x80 240 | }; 241 | 242 | enum signproccs_subclass { 243 | SIGPROC_DPIO_MODULES = 0x00, 244 | SIGPROC_PERF_COUNTERS = 0x01, 245 | SIGPROC_COMM_SYNC = 0x10, 246 | SIGPROC_SIG_PROC_MGMT = 0x20, 247 | SIGPROC_OTHER = 0x80 248 | }; 249 | 250 | #endif 251 | -------------------------------------------------------------------------------- /src/api/general_functions.c: -------------------------------------------------------------------------------- 1 | // Общие функции API 2 | 3 | #include "general_functions.h" 4 | 5 | #include "../libs/device.h" 6 | #include "../libs/driver.h" 7 | 8 | #include "../kernel/kernel.h" 9 | #include "../kernel/timer.h" 10 | #include "../drivers/devices.h" 11 | #include "../drivers/drivers.h" 12 | 13 | void _print_text(unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bkgr_color, unsigned int device_index){ 14 | 15 | struct dev_info* devices = _get_device_info(); 16 | struct dev_info* device = &devices[device_index]; 17 | 18 | void (*driver_print_text)(struct dev_info*, unsigned char*, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char) = (void (*)(struct dev_info*, unsigned char*, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char))(device->driver->funcs[PRINT_TEXT]); 19 | 20 | driver_print_text(device, text, size, x, y, font_color, bkgr_color); 21 | 22 | } 23 | 24 | void _new_line(unsigned int device_index){ 25 | 26 | struct dev_info* devices = _get_device_info(); 27 | struct dev_info* device = &devices[device_index]; 28 | 29 | void (*driver_new_line)(struct dev_info*) = (void (*)(struct dev_info*))(device->driver->funcs[NEW_LINE]); 30 | 31 | driver_new_line(device); 32 | 33 | } 34 | 35 | void _cursor_update(unsigned int device_index){ 36 | 37 | struct dev_info* devices = _get_device_info(); 38 | struct dev_info* device = &devices[device_index]; 39 | 40 | void (*driver_cursor_update)(struct dev_info*) = (void (*)(struct dev_info*))(device->driver->funcs[CURSOR_UPDATE]); 41 | 42 | driver_cursor_update(device); 43 | 44 | } 45 | 46 | void _clear_display(unsigned int device_index){ 47 | 48 | struct dev_info* devices = _get_device_info(); 49 | struct dev_info* device = &devices[device_index]; 50 | 51 | void (*driver_clear_display)(struct dev_info*) = (void (*)(struct dev_info*))(device->driver->funcs[CLEAR_DISPLAY]); 52 | 53 | driver_clear_display(device); 54 | 55 | } 56 | 57 | unsigned char _get_current_symbol(unsigned int offset, unsigned int device_index){ 58 | 59 | struct dev_info* devices = _get_device_info(); 60 | struct dev_info* device = &devices[device_index]; 61 | 62 | unsigned char (*driver_get_current_symbol)(struct dev_info*, unsigned int) = (unsigned char (*)(struct dev_info*, unsigned int))(device->driver->funcs[GET_CURRENT_SYMBOL]); 63 | 64 | unsigned char symbol = driver_get_current_symbol(device, offset); 65 | return symbol; 66 | 67 | } 68 | 69 | unsigned char _delete_current_symbol(unsigned int offset, unsigned int device_index){ 70 | 71 | struct dev_info* devices = _get_device_info(); 72 | struct dev_info* device = &devices[device_index]; 73 | 74 | unsigned char (*driver_delete_current_symbol)(struct dev_info*, unsigned int) = (unsigned char (*)(struct dev_info*, unsigned int))(device->driver->funcs[DELETE_CURRENT_SYMBOL]); 75 | 76 | unsigned char symbol = driver_delete_current_symbol(device, offset); 77 | return symbol; 78 | 79 | } 80 | 81 | unsigned char _get_display_cursor_pos_x(unsigned int device_index){ 82 | struct dev_info* devices = _get_device_info(); 83 | struct dev_info* device = &devices[device_index]; 84 | 85 | unsigned char (*driver_get_display_cursor_pos_x)(struct dev_info*) = (unsigned char (*)(struct dev_info*))(device->driver->funcs[GET_CURSOR_POS_X]); 86 | 87 | unsigned char symbol = driver_get_display_cursor_pos_x(device); 88 | return symbol; 89 | } 90 | 91 | unsigned char _get_display_cursor_pos_y(unsigned int device_index){ 92 | struct dev_info* devices = _get_device_info(); 93 | struct dev_info* device = &devices[device_index]; 94 | 95 | unsigned char (*driver_get_display_cursor_pos_y)(struct dev_info*) = (unsigned char (*)(struct dev_info*))(device->driver->funcs[GET_CURSOR_POS_Y]); 96 | 97 | unsigned char symbol = driver_get_display_cursor_pos_y(device); 98 | return symbol; 99 | } 100 | 101 | void _set_display_cursor_pos_x(unsigned char x, unsigned int device_index){ 102 | struct dev_info* devices = _get_device_info(); 103 | struct dev_info* device = &devices[device_index]; 104 | 105 | unsigned char (*driver_set_display_cursor_pos_x)(struct dev_info*, unsigned char) = (unsigned char (*)(struct dev_info*, unsigned char))(device->driver->funcs[SET_CURSOR_POS_X]); 106 | 107 | driver_set_display_cursor_pos_x(device, x); 108 | } 109 | 110 | void _set_display_cursor_pos_y(unsigned char y, unsigned int device_index){ 111 | struct dev_info* devices = _get_device_info(); 112 | struct dev_info* device = &devices[device_index]; 113 | 114 | unsigned char (*driver_set_display_cursor_pos_y)(struct dev_info*, unsigned char) = (unsigned char (*)(struct dev_info*, unsigned char))(device->driver->funcs[SET_CURSOR_POS_Y]); 115 | 116 | driver_set_display_cursor_pos_y(device, y); 117 | } 118 | 119 | unsigned char _read_sector(unsigned int device_index, unsigned int lba, void* dst){ 120 | 121 | } 122 | 123 | unsigned char _write_sector(unsigned int device_index, unsigned int lba, void* src){ 124 | 125 | } 126 | 127 | void _execute_program(unsigned int program){ 128 | EXECUTE_PROGRAM = program; 129 | } 130 | 131 | unsigned int _get_execute_program(){ 132 | return EXECUTE_PROGRAM; 133 | } 134 | 135 | void* _get_keyboard_buffer(unsigned int device_index){ 136 | struct dev_info* devices = _get_device_info(); 137 | struct dev_info* device = &devices[device_index]; 138 | void* (*get_keyboard_buffer)(struct dev_info*) = (void* (*)(struct dev_info*))(device->driver->funcs[GET_KEYBOARD_BUFFER]); 139 | return get_keyboard_buffer(device); 140 | } 141 | 142 | unsigned int _get_keyboard_buffer_ptr(unsigned int device_index){ 143 | struct dev_info* devices = _get_device_info(); 144 | struct dev_info* device = &devices[device_index]; 145 | unsigned int (*get_keyboard_buffer_ptr)(struct dev_info*) = (unsigned int (*)(struct dev_info*))(device->driver->funcs[GET_KEYBOARD_BUFFER_PTR]); 146 | return get_keyboard_buffer_ptr(device); 147 | } 148 | 149 | unsigned char _get_keyboard_shift_pressed(unsigned int device_index){ 150 | struct dev_info* devices = _get_device_info(); 151 | struct dev_info* device = &devices[device_index]; 152 | unsigned int (*get_keyboard_shift_pressed)(struct dev_info*) = (unsigned int (*)(struct dev_info*))(device->driver->funcs[GET_KEYBOARD_SHIFT_PRD]); 153 | return get_keyboard_shift_pressed(device); 154 | } 155 | 156 | unsigned char _get_keyboard_ctrl_pressed(unsigned int device_index){ 157 | struct dev_info* devices = _get_device_info(); 158 | struct dev_info* device = &devices[device_index]; 159 | unsigned int (*get_keyboard_shift_pressed)(struct dev_info*) = (unsigned int (*)(struct dev_info*))(device->driver->funcs[GET_KEYBOARD_CTRL_PRD]); 160 | return get_keyboard_shift_pressed(device); 161 | } 162 | 163 | unsigned char _get_keyboard_alt_pressed(unsigned int device_index){ 164 | struct dev_info* devices = _get_device_info(); 165 | struct dev_info* device = &devices[device_index]; 166 | unsigned int (*get_keyboard_alt_pressed)(struct dev_info*) = (unsigned int (*)(struct dev_info*))(device->driver->funcs[GET_KEYBOARD_ALT_PRD]); 167 | return get_keyboard_alt_pressed(device); 168 | } 169 | 170 | 171 | 172 | unsigned int _get_ticks(){ 173 | return TICKS; 174 | } 175 | 176 | unsigned int _get_device_count(){ 177 | return DEVICE_COUNT; 178 | } 179 | 180 | 181 | 182 | void* _get_device_info(){ 183 | return &DEVICES_INFO; 184 | } 185 | -------------------------------------------------------------------------------- /src/libs/device.h: -------------------------------------------------------------------------------- 1 | #ifndef INCL_LIB_DEVICE 2 | #define INCL_LIB_DEVICE 3 | 4 | #define MAX_DEVICE_COUNT 256 5 | 6 | // Информация о устройстве 7 | struct dev_info{ 8 | 9 | unsigned char is_pci_dev; // 0 or 1 10 | unsigned char is_virt_dev; // 0 or 1 11 | unsigned char is_leg_dev; // 0 or 1 12 | 13 | unsigned int bus; 14 | unsigned int dev; 15 | unsigned int func; 16 | 17 | unsigned short vendor_id; 18 | unsigned short device_id; 19 | 20 | unsigned short command; 21 | unsigned short status; 22 | 23 | unsigned char revision_id; 24 | unsigned char prog_if; 25 | 26 | unsigned char subclass; 27 | unsigned char classcode; 28 | 29 | unsigned char cache_line_size; 30 | unsigned char latency_timer; 31 | 32 | unsigned char mf; 33 | unsigned char header_type; 34 | 35 | unsigned char bist; 36 | 37 | unsigned int bar0; 38 | unsigned int bar1; 39 | unsigned int bar2; 40 | unsigned int bar3; 41 | unsigned int bar4; 42 | unsigned int bar5; 43 | 44 | struct driver_info* driver; 45 | 46 | }; 47 | 48 | 49 | struct class_map{ 50 | unsigned int code; 51 | unsigned char* name; 52 | }; 53 | 54 | struct subclass_map{ 55 | unsigned int classcode; 56 | unsigned int subclass; 57 | unsigned char* name; 58 | }; 59 | 60 | extern struct class_map pci_class_names[]; 61 | 62 | extern struct subclass_map* pci_subclass_names[]; 63 | 64 | 65 | enum virt_class_codes{ 66 | VIRT_DISPLAY_CONTROLLER = 0x20, 67 | VIRT_KEYBOARD_CONTROLLER = 0x21, 68 | }; 69 | 70 | enum virt_display_subclass{ 71 | VIRT_DISPLAY_VGATEXT = 0x0, 72 | }; 73 | 74 | enum virt_keyboard_subclass{ 75 | VIRT_KEYBOARD_LDEV = 0x0, 76 | }; 77 | 78 | 79 | enum class_codes{ 80 | UNCLASSIFIED = 0x0, 81 | STORAGE_CONTROLLER = 0x1, 82 | NETWORK_CONTROLLER = 0x2, 83 | DISPLAY_CONTROLLER = 0x3, 84 | MULTIMEDIA_CONTROLLER = 0x4, 85 | MEMORY_CONTROLLER = 0x5, 86 | BRIDGE = 0x6, 87 | SIMPLE_COMMUNICATION_CONTROLLER = 0x7, 88 | BASE_SYSTEM_PERIPHERAL = 0x8, 89 | INPUT_DEVICE_CONTROLLER = 0x9, 90 | DOCKING_STATION = 0xA, 91 | PROCESSOR = 0xB, 92 | SERIAL_BUS_CONTROLLER = 0xC, 93 | WIRELESS_CONTROLLER = 0xD, 94 | INTELLIGENT_CONTROLLER = 0xE, 95 | SATELLITE_COMMUNICATION_CONTROLLER = 0xF, 96 | ENCRYPTION_CONTROLLER = 0x10, 97 | SIGNAL_PROCESSING_CONTROLLER = 0x11, 98 | PROCESSING_ACCELERATOR = 0x12, 99 | NON_ESSENTIAL_INSTRUMENTATION = 0x13, 100 | 101 | RESERVED_BEGIN = 0x14, 102 | RESERVED_END = 0x3F, 103 | CO_PROCESSOR = 0x40, 104 | _0xFE_RESERVED = 0xFE, 105 | UNASSIGNED_CLASS = 0xFF 106 | }; 107 | 108 | enum storage_subclass { 109 | STORAGE_SCSI_BUS_CONTROLLER = 0x00, 110 | STORAGE_IDE_CONTROLLER = 0x01, 111 | STORAGE_FLOPPY_DISK_CONTROLLER = 0x02, 112 | STORAGE_IPI_BUS_CONTROLLER = 0x03, 113 | STORAGE_RAID_CONTROLLER = 0x04, 114 | STORAGE_ATA_CONTROLLER = 0x05, 115 | STORAGE_SERIAL_ATA_CONTROLLER = 0x06, 116 | STORAGE_SERIAL_ATTACHED_SCSI = 0x07, 117 | STORAGE_NON_VOLATILE_MEMORY = 0x08, 118 | STORAGE_OTHER = 0x80, 119 | }; 120 | 121 | enum network_subclass { 122 | NETWORK_ETHERNET_CONTROLLER = 0x0, 123 | NETWORK_TOKEN_RING_CONTROLLER = 0x1, 124 | NETWORK_FDDI_CONTROLLER = 0x2, 125 | NETWORK_ATM_CONTROLLER = 0x3, 126 | NETWORK_ISDN_CONTROLLER = 0x4, 127 | NETWORK_WORLDFIP_CONTROLLER = 0x5, 128 | NETWORK_PICMG_MC_CONTROLLER = 0x6, 129 | NETWORK_INFINIBAND_CONTROLLER = 0x7, 130 | NETWORK_FABRIC_CONTROLLER = 0x8, 131 | NETWORK_OTHER = 0x80, 132 | }; 133 | 134 | enum display_subclass { 135 | DISPLAY_VGA_COMPATIBLE = 0x00, 136 | DISPLAY_XGA = 0x01, 137 | DISPLAY_3D = 0x02, 138 | DISPLAY_OTHER = 0x80 139 | }; 140 | 141 | enum multimedia_subclass { 142 | MULTIMEDIA_VIDEO = 0x00, 143 | MULTIMEDIA_AUDIO = 0x01, 144 | MULTIMEDIA_TELEPHONY = 0x02, 145 | MULTIMEDIA_AUDIO_DEVICE = 0x03, 146 | MULTIMEDIA_OTHER = 0x80 147 | }; 148 | 149 | enum memory_subclass { 150 | MEMORY_RAM = 0x00, 151 | MEMORY_FLASH = 0x01, 152 | MEMORY_OTHER = 0x80 153 | }; 154 | 155 | enum bridge_subclass { 156 | BRIDGE_HOST = 0x00, 157 | BRIDGE_ISA = 0x01, 158 | BRIDGE_EISA = 0x02, 159 | BRIDGE_MCA = 0x03, 160 | BRIDGE_PCI_TO_PCI = 0x04, 161 | BRIDGE_PCMCIA = 0x05, 162 | BRIDGE_NUBUS = 0x06, 163 | BRIDGE_CARDBUS = 0x07, 164 | BRIDGE_RACEWAY = 0x08, 165 | BRIDGE_PCI_TO_PCI1 = 0x09, 166 | BRIDGE_INFINIBAND_TO_PCI = 0x0A, 167 | BRIDGE_OTHER = 0x80 168 | }; 169 | 170 | enum scomm_subclass { 171 | SCOMM_SERIAL = 0x00, 172 | SCOMM_PARALLEL = 0x01, 173 | SCOMM_MULTI_SERIAL = 0x02, 174 | SCOMM_MODEM = 0x03, 175 | SCOMM_GPIB = 0x04, 176 | SCOMM_SMART_CARD = 0x05, 177 | SCOMM_OTHER = 0x80 178 | }; 179 | 180 | enum base_sys_peripheral_subclass { 181 | BSP_PIC = 0x00, 182 | BSP_DMA = 0x01, 183 | BSP_TIMER = 0x02, 184 | BSP_RTC = 0x03, 185 | BSP_PCI_HOTPLUG = 0x04, 186 | BSP_SD_HOST = 0x05, 187 | BSP_IOMMU = 0x06, 188 | BSP_OTHER = 0x80 189 | }; 190 | 191 | enum input_device_subclass { 192 | INPUT_KEYBOARD = 0x00, 193 | INPUT_DIGITIZER = 0x01, 194 | INPUT_MOUSE = 0x02, 195 | INPUT_SCANNER = 0x03, 196 | INPUT_GAMEPORT = 0x04, 197 | INPUT_OTHER = 0x80 198 | }; 199 | 200 | enum docking_station_subclass { 201 | DOCK_GENERIC = 0x00, 202 | DOCK_OTHER = 0x80 203 | }; 204 | 205 | enum processor_subclass { 206 | PROC_386 = 0x00, 207 | PROC_486 = 0x01, 208 | PROC_PENTIUM = 0x02, 209 | PROC_PENTIUM_PRO = 0x03, 210 | PROC_ALPHA = 0x10, 211 | PROC_POWERPC = 0x20, 212 | PROC_MIPS = 0x30, 213 | PROC_CO_PROCESSOR = 0x40, 214 | PROC_OTHER = 0x80 215 | }; 216 | 217 | enum serbus_subclass { 218 | SERBUS_FIREWIRE = 0x00, 219 | SERBUS_ACCESS = 0x01, 220 | SERBUS_SSA = 0x02, 221 | SERBUS_USB = 0x03, 222 | SERBUS_FIBRE_CHANNEL = 0x04, 223 | SERBUS_SMBUS = 0x05, 224 | SERBUS_INFINIBAND = 0x06, 225 | SERBUS_IPMI = 0x07, 226 | SERBUS_SERCOS = 0x08, 227 | SERBUS_CANBUS = 0x09, 228 | SERBUS_OTHER = 0x80 229 | }; 230 | 231 | enum wireless_subclass { 232 | WIRELESS_IRDA = 0x00, 233 | WIRELESS_CONSUMER_IR = 0x01, 234 | WIRELESS_RF = 0x10, 235 | WIRELESS_BLUETOOTH = 0x11, 236 | WIRELESS_BROADBAND = 0x12, 237 | WIRELESS_ETHERNET_A = 0x20, 238 | WIRELESS_ETHERNET_B = 0x21, 239 | WIRELESS_OTHER = 0x80 240 | }; 241 | 242 | enum intelligent_subclass { 243 | INTELLIGENT_I20 = 0x00 244 | }; 245 | 246 | enum satcomm_subclass { 247 | SATCOMM_TV = 0x01, 248 | SATCOMM_AUDIO = 0x02, 249 | SATCOMM_VOICE = 0x03, 250 | SATCOMM_DATA = 0x04 251 | }; 252 | 253 | enum encryption_subclass { 254 | ENCRYPTION_NET_COMP = 0x00, 255 | ENCRYPTION_ENTERTAIN = 0x10, 256 | ENCRYPTION_OTHER = 0x80 257 | }; 258 | 259 | enum signproccs_subclass { 260 | SIGPROC_DPIO_MODULES = 0x00, 261 | SIGPROC_PERF_COUNTERS = 0x01, 262 | SIGPROC_COMM_SYNC = 0x10, 263 | SIGPROC_SIG_PROC_MGMT = 0x20, 264 | SIGPROC_OTHER = 0x80 265 | }; 266 | 267 | #endif 268 | -------------------------------------------------------------------------------- /docs/drivers/driver_connect.drawio: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/drivers/devices.c: -------------------------------------------------------------------------------- 1 | #include "devices.h" 2 | #include "../libs/device.h" 3 | #include "../libs/string.h" 4 | #include "pci/pci.h" 5 | 6 | #include "drivers.h" 7 | 8 | 9 | struct dev_info DEVICES_INFO[256]; 10 | unsigned int DEVICE_COUNT; 11 | 12 | 13 | void device_log(struct dev_info* device) { 14 | unsigned int dev = 0; 15 | 16 | unsigned char x = _get_display_cursor_pos_x(dev); 17 | unsigned char y = _get_display_cursor_pos_y(dev); 18 | 19 | unsigned char type_fcolor = 2; 20 | unsigned char tire_fcolor = 7; 21 | unsigned char class_fcolor = 7; 22 | unsigned char subclass_fcolor = 7; 23 | 24 | // Тип устройства 25 | if (device->is_pci_dev == 1) { 26 | 27 | _print_text("pci", 3, x, y, type_fcolor, 0, dev); 28 | 29 | x = _get_display_cursor_pos_x(dev); 30 | y = _get_display_cursor_pos_y(dev); 31 | 32 | _print_text(": ", 2, x, y, tire_fcolor, 0, dev); 33 | 34 | unsigned char bus_string[3]; 35 | int bus_string_size = itos(device->bus, bus_string); 36 | if (bus_string_size == 1){ 37 | x = _get_display_cursor_pos_x(dev); 38 | y = _get_display_cursor_pos_y(dev); 39 | _print_text("0", 1, x, y, tire_fcolor, 0, dev); 40 | } 41 | x = _get_display_cursor_pos_x(dev); 42 | y = _get_display_cursor_pos_y(dev); 43 | _print_text(bus_string, bus_string_size, x, y, tire_fcolor, 0, dev); 44 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(":", 1, x, y, tire_fcolor, 0, dev); 45 | 46 | unsigned char dev_string[3]; 47 | int dev_string_size = itos(device->dev, dev_string); 48 | if (dev_string_size == 1){ 49 | x = _get_display_cursor_pos_x(dev); 50 | y = _get_display_cursor_pos_y(dev); 51 | _print_text("0", 1, x, y, tire_fcolor, 0, dev); 52 | } 53 | x = _get_display_cursor_pos_x(dev); 54 | y = _get_display_cursor_pos_y(dev); 55 | _print_text(dev_string, dev_string_size, x, y, tire_fcolor, 0, dev); 56 | 57 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(".", 1, x, y, tire_fcolor, 0, dev); 58 | 59 | unsigned char func_string[3]; 60 | int func_string_size = itos(device->func, func_string); 61 | if (bus_string_size == 1){ 62 | x = _get_display_cursor_pos_x(dev); 63 | y = _get_display_cursor_pos_y(dev); 64 | _print_text("0", 1, x, y, tire_fcolor, 0, dev); 65 | } 66 | x = _get_display_cursor_pos_x(dev); 67 | y = _get_display_cursor_pos_y(dev); 68 | _print_text(func_string, func_string_size, x, y, tire_fcolor, 0, dev); 69 | 70 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(" ", 1, x, y, tire_fcolor, 0, dev); 71 | 72 | 73 | unsigned int pci_class_num = 0; 74 | unsigned int print_flag = 0; 75 | 76 | for (;;){ 77 | 78 | if (pci_class_names[pci_class_num].name == 0) break; 79 | if (pci_class_names[pci_class_num].code == device->classcode){ 80 | x = _get_display_cursor_pos_x(dev); 81 | y = _get_display_cursor_pos_y(dev); 82 | unsigned int size = strlen(pci_class_names[pci_class_num].name); 83 | _print_text(pci_class_names[pci_class_num].name, size, x, y, class_fcolor, 0, dev); 84 | print_flag = 1; 85 | } 86 | 87 | x = _get_display_cursor_pos_x(dev); 88 | y = _get_display_cursor_pos_y(dev); 89 | 90 | pci_class_num++; 91 | } 92 | 93 | // Класс не найден 94 | if (print_flag == 0){ 95 | x = _get_display_cursor_pos_x(dev); 96 | y = _get_display_cursor_pos_y(dev); 97 | _print_text("UNKNOWN", 7, x, y, class_fcolor, 0, dev); 98 | } 99 | 100 | x = _get_display_cursor_pos_x(dev); 101 | y = _get_display_cursor_pos_y(dev); 102 | 103 | _print_text(" ", 1, x, y, tire_fcolor, 0, dev); 104 | 105 | unsigned int pci_subclass_m_num = 0; 106 | for (;;){ 107 | 108 | struct subclass_map* subclass_m = pci_subclass_names[pci_subclass_m_num]; 109 | 110 | // Конец масива 111 | if (pci_subclass_names[pci_subclass_m_num] == 0) break; 112 | 113 | unsigned int pci_subclass_num = 0; 114 | for (;;){ 115 | 116 | // Конец массива 117 | if (subclass_m[pci_subclass_num].name == 0) break; 118 | 119 | if (device->classcode == subclass_m[pci_subclass_num].classcode && device->subclass == subclass_m[pci_subclass_num].subclass){ 120 | x = _get_display_cursor_pos_x(dev); 121 | y = _get_display_cursor_pos_y(dev); 122 | unsigned int size = strlen(subclass_m[pci_subclass_num].name); 123 | _print_text(subclass_m[pci_subclass_num].name, size, x, y, subclass_fcolor, 0, dev); 124 | } 125 | 126 | pci_subclass_num++; 127 | } 128 | 129 | pci_subclass_m_num++; 130 | } 131 | 132 | } else if (device->is_leg_dev == 1) { 133 | _print_text("legacy", 6, x, y, type_fcolor, 0, dev); 134 | } else if (device->is_virt_dev == 1) { 135 | _print_text("virt", 4, x, y, type_fcolor, 0, dev); 136 | } 137 | 138 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(" (", 2, x, y, tire_fcolor, 0, dev); 139 | 140 | unsigned char vendorid_string[5]; 141 | int vendorid_string_size = itos(device->vendor_id, vendorid_string); 142 | x = _get_display_cursor_pos_x(dev); 143 | y = _get_display_cursor_pos_y(dev); 144 | _print_text(vendorid_string, vendorid_string_size, x, y, tire_fcolor, 0, dev); 145 | 146 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(", ", 2, x, y, tire_fcolor, 0, dev); 147 | 148 | unsigned char deviceid_string[5]; 149 | int deviceid_string_size = itos(device->device_id, deviceid_string); 150 | x = _get_display_cursor_pos_x(dev); 151 | y = _get_display_cursor_pos_y(dev); 152 | _print_text(deviceid_string, deviceid_string_size, x, y, tire_fcolor, 0, dev); 153 | 154 | x = _get_display_cursor_pos_x(dev); y = _get_display_cursor_pos_y(dev); _print_text(")", 1, x, y, tire_fcolor, 0, dev); 155 | 156 | _new_line(dev); 157 | } 158 | 159 | 160 | 161 | void device_registration(struct dev_info* device){ 162 | DEVICES_INFO[DEVICE_COUNT] = *device; 163 | DEVICE_COUNT++; 164 | if( 165 | DEVICE_COUNT == 1 && 166 | DEVICES_INFO[0].classcode == VIRT_DISPLAY_CONTROLLER && 167 | DEVICES_INFO[0].subclass == VIRT_DISPLAY_VGATEXT 168 | ) driver_manager(); // устройство дисплей => сразу же ищем ему драйвер (для логов) 169 | if ( 170 | DEVICE_COUNT > 0 && 171 | DEVICES_INFO[0].classcode == VIRT_DISPLAY_CONTROLLER && 172 | DEVICES_INFO[0].subclass == VIRT_DISPLAY_VGATEXT 173 | ) device_log(device); // если есть устройство дисплей, то выводим логи 174 | } 175 | 176 | 177 | //виртуальные устройства 178 | void devices_virt(){ 179 | 180 | // display vga text mode 181 | struct dev_info dev_display; 182 | dev_display.is_pci_dev = 0; 183 | dev_display.is_virt_dev = 1; 184 | dev_display.is_leg_dev = 0; 185 | 186 | dev_display.classcode = VIRT_DISPLAY_CONTROLLER; 187 | dev_display.subclass = VIRT_DISPLAY_VGATEXT; 188 | dev_display.vendor_id = 0; 189 | dev_display.device_id = 0; 190 | 191 | dev_display.driver = 0; 192 | 193 | device_registration(&dev_display); 194 | 195 | } 196 | 197 | 198 | void devices_legacy_find(){ 199 | 200 | // keyboard 201 | struct dev_info dev_keyb; 202 | dev_keyb.is_pci_dev = 0; 203 | dev_keyb.is_virt_dev = 0; 204 | dev_keyb.is_leg_dev = 1; 205 | 206 | dev_keyb.classcode = VIRT_KEYBOARD_CONTROLLER; 207 | dev_keyb.subclass = VIRT_KEYBOARD_LDEV; 208 | dev_keyb.vendor_id = 0; 209 | dev_keyb.device_id = 0; 210 | 211 | dev_keyb.driver = 0; 212 | 213 | device_registration(&dev_keyb); 214 | 215 | } 216 | 217 | 218 | int device_manager(){ 219 | 220 | unsigned int old_device_count = DEVICE_COUNT; 221 | 222 | devices_virt(); 223 | devices_legacy_find(); 224 | pci_find_devices(); 225 | 226 | // Возвращает то, сколько нашёл устройств 227 | return (DEVICE_COUNT-old_device_count); 228 | } 229 | -------------------------------------------------------------------------------- /docs/os_boot.drawio: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /docs/api/add_api_function.md: -------------------------------------------------------------------------------- 1 | # Добавление новых функций API 2 | 3 | Добавление новых функций в API может понадобится при модернизации ядра или разработке драйвера для устройства, которое не было предусмотрено создателем ядра. 4 | 5 | ## Структура файлов с исходным кодом API 6 | 7 | Здесь можно посмотреть назначение файлов с исходным кодом API ядра. Это важно, ведь для изменения API необходимо понимать куда вносить изменения. 8 | 9 | Файлы с исходным кодом API ядра находятся по пути [`src/api/`](../../src/api/) 10 | 11 | [Схема демонстрирующая назначение исходных файлов API](api.pdf) 12 | 13 | ### [api.c](../../src/api/api.c) / [api.h](../../src/api/api.h) 14 | Предназначены для приёма системных вызовов из user-space. Вызывает внутреннюю функцию-интерфейс ядра исходя из номера системного вызова. Внутренние функции-интерфейсы для user-space находятся в файлах `userspace_if.c` / `userspace_if.h` 15 | 16 | ### [userspace_if.c](../../src/api/userspace_if.c) / [userspace_if.h](../../src/api/userspace_if.h) 17 | Файлы содержат функции-интерфейсы для userspace. Эти принимают: 18 | - Адрес структуры, которая содержит значения регистров, то есть аргументы 19 | - Адрес структуры, которая содержит результат, который затем будет записан в регистры 20 | 21 | Сигнатура структуры: 22 | ``` c 23 | // Структура предназначенная для хранения регистров 24 | struct registers_struct { 25 | unsigned int eax; 26 | unsigned int ebx; 27 | unsigned int ecx; 28 | unsigned int edx; 29 | unsigned int esi; 30 | unsigned int edi; 31 | }; 32 | ``` 33 | 34 | Сигнатура функции-интерфейса: 35 | ``` c 36 | void sys_example_func(struct registers_struct* args, struct registers_struct* result); 37 | ``` 38 | 39 | Функция-интерфейс вызывает внутреннюю функцию ядра, передавая ей аргументы не в структуре, а уже как полноценные аргументы. После возврата внутренняя функция ядра может вернуть значение (*зависит от спецификации*), оно должно быть записно в определённый *спецификацией* регистр по адресу структуры в result 40 | 41 | Рассмотрим пример: 42 | 43 | Существует внутренняя функция ядра: 44 | 45 | ``` c 46 | int _example_func(int arg1, void* arg2, char* arg3); // Возвращает число 47 | ``` 48 | 49 | Вот как она будет вызываться в функции-интерфейсе: 50 | 51 | ``` c 52 | void sys_example_func(struct registers_struct* args, struct registers_struct* result){ 53 | int arg1 = (int)args->ebx; // Число 54 | void* arg2 = (void*)args->ecx; // Адрес 55 | char* arg3 = (char*)args->edx; // Адрес на массив символов 56 | int func_result = _example_func(arg1, arg2, arg3); // Вызываем функцию, передаём ей аргументы, получаем значение 57 | result->ebx = func_result; // Записываем результат в регистр ebx 58 | } 59 | ``` 60 | 61 | ### [general_functions.c](../../src/api/general_functions.c) / [general_functions.h](../../src/api/general_functions.h) 62 | 63 | Эти файлы содержат **общие** функции ядра, т.е предназначенные и для user-space и для компонентов ядра. 64 | 65 | ### [kernel_functions.c](../../src/api/kernel_functions.c) / [kernel_functions.h](../../src/api/kernel_functions.h) 66 | 67 | Эти файлы содержат функции ядра только **для компонентов ядра**. 68 | 69 | ## Добавление функции 70 | 71 | Для начала нужно определиться: функция должна быть доступна **только для компонентов ядра (kernel-space)** или **должна быть общей (kernel-space и user-space)** 72 | 73 | ### Только для компонентов ядра (kernel-space) 74 | 75 | Краткий план действий: 76 | 1. реализуем функцию в файлах `kernel_functions.c` и `kernel_functions.h` 77 | 78 | > Желательно перед названием функции ставить символ `_` 79 | 80 | ### Общая (kernel-space и user-space) 81 | 82 | Краткий план действий: 83 | 1. придумываем спецификацию для системного вызова 84 | 2. реализуем функцию в файлах `general_functions.c` и `general_functions.h` 85 | 3. добавляем функцию-интерфейс в файлы `userspace_if.c` и `userspace_if.h` 86 | 4. добавляем обработчик системного вызова по его номеру 87 | 88 | В качестве примера возьмём функцию `_print_text`, которая выводит текст. 89 | 90 | #### 1. Спецификация для системного вызова 91 | 92 | Необходимо продумать как программы будут вызывать системный вызов: какие регистры необходимо использовать для передачи аргументов, какой номер системного вызова будет использоваться. 93 | 94 | Основная спецификация системных вызовов [находится здесь](syscalls.md#детали) - для аргументов необходимо использовать те регистры, которые приведены в ней. 95 | 96 | Номер системного вызова должен быть уникальным, и не совпадать с уже существующими номерами. Номера существующих системных функций можно посмотреть [в таблице](syscalls.md#таблица-системных-вызовов) 97 | 98 | Пример: 99 | 100 | Функция `_print_text` имеет номер системного вызова `0x0`. 101 | 102 | Регистр `ebx` используется для передачи адреса строки, `ecx` - количество байт для вывода, `dl` - координата X, `dh` - координата Y, `si` - цвет символов, `edi` - индекс устройства. 103 | 104 | Спецификацию `_print_text` можно найти [здесь](syscall_functions.md#print_text) 105 | 106 | #### 2. Реализация функции в `general_functions.c/h` 107 | 108 | Здесь реализовывается функция, которая должна принимать аргументы, и может вызываться как из kernel-space так и из user-space (через системные вызовы). 109 | 110 | Желательно, чтобы имя функции начиналось с символа `_`. 111 | 112 | Пример: 113 | 114 | Функция `_print_text` имеет следующую реализацию: 115 | ``` c 116 | void _print_text(unsigned char* text, unsigned int size, unsigned char x, unsigned char y, unsigned char font_color, unsigned char bkgr_color, unsigned int device_index){ 117 | 118 | struct dev_info* devices = _get_device_info(); // Получение адреса массива устройств 119 | struct dev_info* device = &devices[device_index]; // Получение конкретного устройства по его индексу, который передаётся в аргументах 120 | 121 | // Здесь происходит получение драйвера устройства. 122 | // Дальше получаем функцию драйвера PRINT_TEXT - данная функция расположена по индексу 0 (но здесь используется объект enum). 123 | void (*driver_print_text)(struct dev_info*, unsigned char*, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char) = (void (*)(struct dev_info*, unsigned char*, unsigned int, unsigned char, unsigned char, unsigned char, unsigned char))(device->driver->funcs[PRINT_TEXT]); 124 | 125 | // Вызываем полученную функцию и передаем аргументы. 126 | driver_print_text(device, text, size, x, y, font_color, bkgr_color); 127 | 128 | // Обратите внимание: расположение функций драйверов в массиве, а также принимаемые аргументы - определены в спецификации драйверов 129 | } 130 | ``` 131 | 132 | #### 3. Реализация функции-интерфейса в `userspace_if.c/h` 133 | 134 | Смысл функции-интерфейса: принять регистры, правильно передать аргументы (по спецификации функции), вернуть результат в регистрах 135 | 136 | Функция-интерфейс должна принимать два аргумента: 137 | ``` c 138 | void sys_example_func(struct registers_struct* args, struct registers_struct* result); 139 | ``` 140 | 141 | Структура выглядит следующим образом: 142 | ``` c 143 | // Структура предназначенная для хранения регистров 144 | struct registers_struct { 145 | unsigned int eax; 146 | unsigned int ebx; 147 | unsigned int ecx; 148 | unsigned int edx; 149 | unsigned int esi; 150 | unsigned int edi; 151 | }; 152 | ``` 153 | 154 | Функция-интерфейс должна правильно передать значения регистров из структуры в аргументы функции (по спецификации функции): 155 | ``` c 156 | void sys_example_func(struct registers_struct* args, struct registers_struct* result){ 157 | int arg1 = (int)args->ebx; // Число 158 | void* arg2 = (void*)args->ecx; // Адрес 159 | char* arg3 = (char*)args->edx; // Адрес на массив символов 160 | int func_result = _example_func(arg1, arg2, arg3); // Вызываем функцию, передаём ей аргументы, получаем значение 161 | result->ebx = func_result; // Записываем результат в регистр ebx 162 | } 163 | ``` 164 | 165 | А также должна записать результат функции в структуру по адресу из `result` 166 | 167 | Желательно, чтобы имя функции начиналось с `sys_`. 168 | 169 | Пример: 170 | 171 | Функция `_print_text` вызывается следующим образом: 172 | ``` c 173 | void sys_print_text(struct registers_struct* args, struct registers_struct* result){ 174 | _print_text( 175 | args->ebx, 176 | args->ecx, 177 | ((args->edx) & 0xFF), 178 | ((args->edx >> 8) & 0xFF), 179 | ((args->esi) & 0xFF), 180 | ((args->esi >> 8) & 0xFF), 181 | args->edi 182 | ); 183 | } 184 | ``` 185 | Обратите внимание на то, что соблюдается [спецификация аргументов](syscall_functions.md#print_text) 186 | 187 | #### 4. Обработчик системного вызова по его номеру 188 | 189 | В файле `api.c` необходимо в секции `Вызов определённой функции исходя по номеру системного вызова` в конструкцию `switch-case` добавить еще одно условие в таком виде: 190 | ``` c 191 | case НОМЕР_СИСТЕМНОГО_ВЫЗОВА: 192 | sys_НАЗВАНИЕ_ФУНКЦИИ(&args, &result); 193 | break; 194 | ``` 195 | 196 | Пример: 197 | 198 | Функция `_print_text` вызывается следующим образом: 199 | 200 | ``` c 201 | case 0x0: 202 | sys_print_text(&args, &result); 203 | break; 204 | ``` 205 | -------------------------------------------------------------------------------- /docs/api/syscall_functions.md: -------------------------------------------------------------------------------- 1 | # Функции системных вызовов 2 | 3 | ## Display 4 | 5 | ### print_text 6 | 7 | **Номер системного вызова:** `0x0` 8 | 9 | **Описание:** Вывод текста 10 | 11 | **Аргументы:** 12 | | Register | Description | 13 | | :-------------: | :------------- | 14 | | `EBX` | Адрес строки | 15 | | `ECX` | Количество байт | 16 | | `DL` | X | 17 | | `DH` | Y | 18 | | `SI` | Цвета символов: младший байт — цвет текста, старший байт — цвет фона | 19 | | `EDI` | Индекс устройства вывода | 20 | 21 | **Возвращает:** None 22 | 23 | --- 24 | 25 | ### new_line 26 | 27 | **Номер системного вызова:** `0x1` 28 | 29 | **Описание:** Переход на следующую строку (y += 1) 30 | 31 | **Аргументы:** 32 | | Register | Description | 33 | | :-------------: | :------------- | 34 | | `EBX` | Индекс устройства | 35 | 36 | **Возвращает:** None 37 | 38 | --- 39 | 40 | ### cursor_update 41 | 42 | **Номер системного вызова:** `0x2` 43 | 44 | **Описание:** Обновить курсор. Перемещает курсор на текущие координаты x и y 45 | 46 | **Аргументы:** 47 | | Register | Description | 48 | | :-------------: | :------------- | 49 | | `EBX` | Индекс устройства | 50 | 51 | **Возвращает:** None 52 | 53 | --- 54 | 55 | ### clear_display 56 | 57 | **Номер системного вызова:** `0x3` 58 | 59 | **Описание:** Очистить дисплей 60 | 61 | **Аргументы:** 62 | | Register | Description | 63 | | :-------------: | :------------- | 64 | | `EBX` | Индекс устройства | 65 | 66 | **Возвращает:** None 67 | 68 | --- 69 | 70 | ### get_current_symbol 71 | 72 | **Номер системного вызова:** `0x4` 73 | 74 | **Описание:** Получить текущий символ на экране. Получает символ, на который указывают координаты x и y. Можно задать смещение 75 | 76 | **Аргументы:** 77 | | Register | Description | 78 | | :-------------: | :------------- | 79 | | `EBX` | Смещение относительно текущей позиции | 80 | | `EDX` | Индекс устройства | 81 | 82 | **Возвращает:** 83 | | Register | Description | 84 | | :-------------: | :------------- | 85 | | `EAX` | Символ | 86 | 87 | --- 88 | 89 | ### delete_current_symbol 90 | 91 | **Номер системного вызова:** `0x5` 92 | 93 | **Описание:** Удалить текущий символ на экране. Удаляет символ, на который указывают координаты x и y. Можно задать смещение 94 | 95 | **Аргументы:** 96 | | Register | Description | 97 | | :-------------: | :------------- | 98 | | `EBX` | Смещение относительно текущей позиции | 99 | | `EDX` | Индекс устройства | 100 | 101 | **Возвращает:** 102 | | Register | Description | 103 | | :-------------: | :------------- | 104 | | `EAX` | Удалённый символ | 105 | 106 | --- 107 | 108 | ### set_display_cursor_pos_x 109 | 110 | **Номер системного вызова:** `0x200` 111 | 112 | **Описание:** Установить позицию курсора по координате X 113 | 114 | **Аргументы:** 115 | | Register | Description | 116 | | :-------------: | :------------- | 117 | | `EBX` | Значение координаты | 118 | | `ECX` | Индекс устройства | 119 | 120 | **Возвращает:** None 121 | 122 | --- 123 | 124 | ### set_display_cursor_pos_y 125 | 126 | **Номер системного вызова:** `0x201` 127 | 128 | **Описание:** Установить позицию курсора по координате Y 129 | 130 | **Аргументы:** 131 | | Register | Description | 132 | | :-------------: | :------------- | 133 | | `EBX` | Значение координаты | 134 | | `ECX` | Индекс устройства | 135 | 136 | **Возвращает:** None 137 | 138 | --- 139 | 140 | ### get_display_cursor_pos_x 141 | 142 | **Номер системного вызова:** `0x106` 143 | 144 | **Описание:** Получить позицию курсора по координате X 145 | 146 | **Аргументы:** 147 | | Register | Description | 148 | | :-------------: | :------------- | 149 | | `EBX` | Индекс устройства | 150 | 151 | **Возвращает:** 152 | | Register | Description | 153 | | :-------------: | :------------- | 154 | | `EAX` | Позиция курсора по X | 155 | 156 | --- 157 | 158 | ### get_display_cursor_pos_y 159 | 160 | **Номер системного вызова:** `0x107` 161 | 162 | **Описание:** Получить позицию курсора по координате Y 163 | 164 | **Аргументы:** 165 | | Register | Description | 166 | | :-------------: | :------------- | 167 | | `EBX` | Индекс устройства | 168 | 169 | **Возвращает:** 170 | | Register | Description | 171 | | :-------------: | :------------- | 172 | | `EAX` | Позиция курсора по Y | 173 | 174 | --- 175 | 176 | ## Storage 177 | 178 | ### read_sector 179 | 180 | **Номер системного вызова:** `0x10` 181 | 182 | **Описание:** Читать определённый сектор с диска 183 | 184 | **Аргументы:** 185 | | Register | Description | 186 | | :-------------: | :------------- | 187 | | `EBX` | Идентификатор диска | 188 | | `ECX` | Номер сектора | 189 | | `EDX` | Адрес куда читать (размер 512 байт) | 190 | 191 | **Возвращает:** 192 | | Register | Description | 193 | | :-------------: | :------------- | 194 | | `EAX` | 0 - успешно, -1 - неудача | 195 | 196 | --- 197 | 198 | ### write_sector 199 | 200 | **Номер системного вызова:** `0x11` 201 | 202 | **Описание:** Записать в определённый сектор диска 203 | 204 | **Аргументы:** 205 | | Register | Description | 206 | | :-------------: | :------------- | 207 | | `EBX` | Идентификатор диска | 208 | | `ECX` | Номер сектора | 209 | | `EDX` | Адрес откуда читать (размер 512 байт) | 210 | 211 | **Возвращает:** 212 | | Register | Description | 213 | | :-------------: | :------------- | 214 | | `EAX` | 0 - успешно, -1 - неудача | 215 | 216 | --- 217 | 218 | ## Scheduler 219 | 220 | ### execute_program 221 | 222 | **Номер системного вызова:** `0x50` 223 | 224 | **Описание:** Указать номер следующей программы для исполнения 225 | 226 | **Аргументы:** 227 | | Register | Description | 228 | | :-------------: | :------------- | 229 | | `EBX` | Номер программы | 230 | 231 | **Возвращает:** None 232 | 233 | --- 234 | 235 | ### get_execute_program 236 | 237 | **Номер системного вызова:** `0x100` 238 | 239 | **Описание:** Получить номер следующей программы для исполнения 240 | 241 | **Аргументы:** None 242 | 243 | **Возвращает:** 244 | | Register | Description | 245 | | :-------------: | :------------- | 246 | | `EAX` | Номер программы | 247 | 248 | --- 249 | 250 | ## Keyboard 251 | 252 | ### get_keyboard_buffer 253 | 254 | **Номер системного вызова:** `0x101` 255 | 256 | **Описание:** Получить адрес буффера клавиатуры 257 | 258 | **Аргументы:** 259 | | Register | Description | 260 | | :-------------: | :------------- | 261 | | `EBX` | Индекс устройства | 262 | 263 | **Возвращает:** 264 | | Register | Description | 265 | | :-------------: | :------------- | 266 | | `EAX` | Адрес буффера клавиатуры | 267 | 268 | --- 269 | 270 | ### get_keyboard_buffer_ptr 271 | 272 | **Номер системного вызова:** `0x102` 273 | 274 | **Описание:** Получить текущий индекс (текущее положение) буфера клавиатуры 275 | 276 | **Аргументы:** 277 | | Register | Description | 278 | | :-------------: | :------------- | 279 | | `EBX` | Индекс устройства | 280 | 281 | **Возвращает:** 282 | | Register | Description | 283 | | :-------------: | :------------- | 284 | | `EAX` | Текущий индекс буфера клавиатуры | 285 | 286 | --- 287 | 288 | ### get_keyboard_shift_pressed 289 | 290 | **Номер системного вызова:** `0x103` 291 | 292 | **Описание:** Получить флаг: нажата ли клавиша Shift 293 | 294 | **Аргументы:** 295 | | Register | Description | 296 | | :-------------: | :------------- | 297 | | `EBX` | Индекс устройства | 298 | 299 | **Возвращает:** 300 | | Register | Description | 301 | | :-------------: | :------------- | 302 | | `EAX` | 0 - не нажата, 1 - нажата | 303 | 304 | --- 305 | 306 | ### get_keyboard_ctrl_pressed 307 | 308 | **Номер системного вызова:** `0x104` 309 | 310 | **Описание:** Получить флаг: нажата ли клавиша Ctrl 311 | 312 | **Аргументы:** 313 | | Register | Description | 314 | | :-------------: | :------------- | 315 | | `EBX` | Индекс устройства | 316 | 317 | **Возвращает:** 318 | | Register | Description | 319 | | :-------------: | :------------- | 320 | | `EAX` | 0 - не нажата, 1 - нажата | 321 | 322 | --- 323 | 324 | ### get_keyboard_alt_pressed 325 | 326 | **Номер системного вызова:** `0x105` 327 | 328 | **Описание:** Получить флаг: нажата ли клавиша Alt 329 | 330 | **Аргументы:** 331 | | Register | Description | 332 | | :-------------: | :------------- | 333 | | `EBX` | Индекс устройства | 334 | 335 | **Возвращает:** 336 | | Register | Description | 337 | | :-------------: | :------------- | 338 | | `EAX` | 0 - не нажата, 1 - нажата | 339 | 340 | --- 341 | 342 | ## Other 343 | 344 | ### get_ticks 345 | 346 | **Номер системного вызова:** `0x108` 347 | 348 | **Описание:** Получить количество тиков с момента запуска системы 349 | 350 | **Аргументы:** None 351 | 352 | **Возвращает:** 353 | | Register | Description | 354 | | :-------------: | :------------- | 355 | | `EAX` | Количество тиков | 356 | 357 | --- 358 | 359 | ### get_device_count 360 | 361 | **Номер системного вызова:** `0x109` 362 | 363 | **Описание:** Получить количество устройств 364 | 365 | **Аргументы:** None 366 | 367 | **Возвращает:** 368 | | Register | Description | 369 | | :-------------: | :------------- | 370 | | `EAX` | Количество устройств | 371 | 372 | --- 373 | 374 | ### get_device_info 375 | 376 | **Номер системного вызова:** `0x10A` 377 | 378 | **Описание:** Получить адрес массива с устройствами 379 | 380 | **Аргументы:** None 381 | 382 | **Возвращает:** 383 | | Register | Description | 384 | | :-------------: | :------------- | 385 | | `EAX` | Адрес массива | 386 | 387 | --- 388 | 389 | 390 | -------------------------------------------------------------------------------- /docs/drivers/driver_work.drawio: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/drivers/pci/pci.c: -------------------------------------------------------------------------------- 1 | #include "pci.h" 2 | #include "../devices.h" 3 | #include "../../libs/asm.h" 4 | #include "../../libs/device.h" 5 | 6 | unsigned short pci_config_read_word(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset){ 7 | 8 | unsigned int address = 0; 9 | // bus, device, function, offset, enable bit 10 | address = (unsigned int)((bus << 16) | (dev << 11) | (func << 8) | (offset & 0b11111100) | ((unsigned int)0x80000000)); 11 | outl(CONFIG_ADDRESS, address); 12 | unsigned short result = (unsigned short)((inl(CONFIG_DATA) >> ((offset & 0b00000010) * 8)) & 0xFFFF); 13 | return result; 14 | 15 | } 16 | 17 | 18 | unsigned int pci_config_read_dword(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset){ 19 | 20 | unsigned int address = 0; 21 | // bus, device, function, offset, enable bit 22 | address = (unsigned int)((bus << 16) | (dev << 11) | (func << 8) | (offset & 0b11111100) | ((unsigned int)0x80000000)); 23 | outl(CONFIG_ADDRESS, address); 24 | return inl(CONFIG_DATA); 25 | 26 | } 27 | 28 | 29 | void pci_config_write_word(unsigned int bus, unsigned int dev, unsigned int func, unsigned char offset, unsigned short word){ 30 | unsigned int address = 0; 31 | // bus, device, function, offset, enable bit 32 | address = (unsigned int)((bus << 16) | (dev << 11) | (func << 8) | (offset & 0b11111100) | ((unsigned int)0x80000000)); 33 | outl(CONFIG_ADDRESS, address); 34 | 35 | // дальше изменяем полученное, и отправляем обратно 36 | 37 | // Эта проверка определяет в какой половине 32-битного регистра находятся нужные 16 бит 38 | // так как в одних 32 битах, может быть 2 значения по 16 бит, к примеру command и status 39 | if ((offset & 0b00000010) == 0b00000010){ // проверяем один бит 40 | unsigned int tmp = inl(CONFIG_DATA) & 0x0000FFFF; 41 | tmp |= ((unsigned int)word << 16); 42 | outl(CONFIG_DATA, tmp); 43 | } 44 | else{ 45 | unsigned int tmp = inl(CONFIG_DATA) & 0xFFFF0000; 46 | tmp |= (unsigned int)word; 47 | outl(CONFIG_DATA, tmp); 48 | } 49 | 50 | } 51 | 52 | 53 | struct pci_common_header pci_config_get_common_header(unsigned int bus, unsigned int dev, unsigned int func){ 54 | 55 | struct pci_common_header header; 56 | 57 | unsigned int vendor_device = pci_config_read_dword(bus, dev, func, 0x0); 58 | unsigned int command_status = pci_config_read_dword(bus, dev, func, 0x4); 59 | unsigned int rev_prog_sclass_class = pci_config_read_dword(bus, dev, func, 0x8); 60 | unsigned int cls_lt_headt_bist = pci_config_read_dword(bus, dev, func, 0xC); 61 | 62 | unsigned short vendor_id = vendor_device & 0x0000FFFF; 63 | unsigned short device_id = (vendor_device >> 16) & 0x0000FFFF; 64 | 65 | unsigned short command = command_status & 0x0000FFFF; 66 | unsigned short status = (command_status >> 16) & 0x0000FFFF; 67 | 68 | unsigned char revision_id = rev_prog_sclass_class & 0x000000FF; 69 | unsigned char prog_if = (rev_prog_sclass_class >> 8) & 0x000000FF; 70 | unsigned char subclass = (rev_prog_sclass_class >> 16) & 0x000000FF; 71 | unsigned char class_code = (rev_prog_sclass_class >> 24) & 0x000000FF; 72 | 73 | unsigned char cache_line_size = cls_lt_headt_bist & 0x000000FF; 74 | unsigned char latency_timer = (cls_lt_headt_bist >> 8) & 0x000000FF; 75 | 76 | unsigned char mf = (((cls_lt_headt_bist >> 16) & 0x000000FF) & 0b10000000) >> 7; 77 | unsigned char header_type = ((cls_lt_headt_bist >> 16) & 0x000000FF) & 0b01111111; 78 | 79 | unsigned char bist = (cls_lt_headt_bist >> 24) & 0x000000FF; 80 | 81 | header.vendor_id = vendor_id; 82 | header.device_id = device_id; 83 | header.command = command; 84 | header.status = status; 85 | header.revision_id = revision_id; 86 | header.prog_if = prog_if; 87 | header.subclass = subclass; 88 | header.classcode = class_code; 89 | header.cache_line_size = cache_line_size; 90 | header.latency_timer = latency_timer; 91 | header.mf = mf; 92 | header.header_type = header_type; 93 | header.bist = bist; 94 | 95 | return header; 96 | 97 | } 98 | 99 | 100 | struct pci_header_0 pci_config_get_header_0(unsigned int bus, unsigned int dev, unsigned int func){ 101 | struct pci_common_header common_header = pci_config_get_common_header(bus, dev, func); 102 | struct pci_header_0 result; 103 | result.common_header = common_header; 104 | result.bar0 = pci_config_read_dword(bus, dev, func, 0x10); 105 | result.bar1 = pci_config_read_dword(bus, dev, func, 0x14); 106 | result.bar2 = pci_config_read_dword(bus, dev, func, 0x18); 107 | result.bar3 = pci_config_read_dword(bus, dev, func, 0x1C); 108 | result.bar4 = pci_config_read_dword(bus, dev, func, 0x20); 109 | result.bar5 = pci_config_read_dword(bus, dev, func, 0x24); 110 | return result; 111 | } 112 | 113 | 114 | struct pci_command_register pci_config_get_command(unsigned int bus, unsigned int dev, unsigned int func){ 115 | unsigned short command = pci_config_read_word(bus, dev, func, 0x4); 116 | 117 | struct pci_command_register result; 118 | 119 | result.io_space = (command & 0b00000001); 120 | result.memory_space = (command & 0b00000010) >> 1; 121 | result.bus_master = (command & 0b00000100) >> 2; 122 | result.special_cycles = (command & 0b00001000) >> 3; 123 | result.mem_wr_and_inv_en = (command & 0b00010000) >> 4; 124 | result.vga_pal_sn = (command & 0b00100000) >> 5; 125 | result.par_err_resp = (command & 0b01000000) >> 6; 126 | result.serr_enable = (command & 0b0000000100000000) >> 8; 127 | result.fast_bk_to_bk_en = (command & 0b0000001000000000) >> 9; 128 | result.int_disable = (command & 0b0000010000000000) >> 10; 129 | 130 | return result; 131 | } 132 | 133 | 134 | struct pci_status_register pci_config_get_status(unsigned int bus, unsigned int dev, unsigned int func){ 135 | unsigned short status = pci_config_read_word(bus, dev, func, 0x6); 136 | 137 | struct pci_status_register result; 138 | 139 | result.int_status = (status & 0b00001000) >> 3; 140 | result.capb_list = (status & 0b00010000) >> 4; 141 | result._66mhz_cap = (status & 0b00100000) >> 5; 142 | result.fast_bk_to_bk_cap = (status & 0b10000000) >> 7; 143 | result.mast_dt_par_err = (status & 0b0000000100000000) >> 8; 144 | result.devsel_timing = (status & 0b0000011000000000) >> 9; 145 | result.sign_targ_abort = (status & 0b0000100000000000) >> 11; 146 | result.received_targ_abort = (status & 0b0001000000000000) >> 12; 147 | result.received_mast_abort = (status & 0b0010000000000000) >> 13; 148 | result.sign_sys_err = (status & 0b0100000000000000) >> 14; 149 | result.detect_par_err = (status & 0b1000000000000000) >> 15; 150 | 151 | return result; 152 | } 153 | 154 | 155 | void pci_config_set_command(unsigned int bus, unsigned int dev, unsigned int func, struct pci_command_register cmd){ 156 | unsigned short cmd_binary = 0; 157 | 158 | cmd_binary |= (cmd.io_space & 0x1) << 0; 159 | cmd_binary |= (cmd.memory_space & 0x1) << 1; 160 | cmd_binary |= (cmd.bus_master & 0x1) << 2; 161 | cmd_binary |= (cmd.special_cycles & 0x1) << 3; 162 | cmd_binary |= (cmd.mem_wr_and_inv_en & 0x1) << 4; 163 | cmd_binary |= (cmd.vga_pal_sn & 0x1) << 5; 164 | cmd_binary |= (cmd.par_err_resp & 0x1) << 6; 165 | cmd_binary |= (cmd.serr_enable & 0x1) << 8; 166 | cmd_binary |= (cmd.fast_bk_to_bk_en & 0x1) << 9; 167 | cmd_binary |= (cmd.int_disable & 0x1) << 10; 168 | 169 | pci_config_write_word(bus, dev, func, 0x4, cmd_binary); 170 | } 171 | 172 | 173 | void pci_device_registration(unsigned int bus, unsigned int dev, unsigned int func, struct pci_header_0 header){ 174 | 175 | struct dev_info device; 176 | 177 | device.is_pci_dev = 1; 178 | 179 | device.bus = bus; 180 | device.dev = dev; 181 | device.func = func; 182 | 183 | device.vendor_id = header.common_header.vendor_id; 184 | device.device_id = header.common_header.device_id; 185 | 186 | device.command = header.common_header.command; 187 | device.status = header.common_header.status; 188 | 189 | device.revision_id = header.common_header.revision_id; 190 | device.prog_if = header.common_header.prog_if; 191 | 192 | device.subclass = header.common_header.subclass; 193 | device.classcode = header.common_header.classcode; 194 | 195 | device.cache_line_size = header.common_header.cache_line_size; 196 | device.latency_timer = header.common_header.latency_timer; 197 | 198 | device.mf = header.common_header.mf; 199 | device.header_type = header.common_header.header_type; 200 | 201 | device.bist = header.common_header.bist; 202 | 203 | device.bar0 = header.bar0; 204 | device.bar1 = header.bar1; 205 | device.bar2 = header.bar2; 206 | device.bar3 = header.bar3; 207 | device.bar4 = header.bar4; 208 | device.bar5 = header.bar5; 209 | 210 | device.driver = 0; 211 | 212 | device_registration(&device); 213 | 214 | } 215 | 216 | 217 | void pci_find_devices(){ 218 | for (unsigned int bus = 0; bus < 256; bus++){ 219 | for (unsigned int dev = 0; dev < 32; dev++){ 220 | for (unsigned int func = 0; func < 8; func++){ 221 | 222 | struct pci_common_header common_header = pci_config_get_common_header(bus, dev, func); 223 | 224 | // Обрабатываем только устройства, без шин и т.д 225 | if (common_header.header_type != 0x0) continue; 226 | 227 | if (func == 0){ 228 | 229 | if (common_header.vendor_id == 0xFFFF) break; // Not found 230 | 231 | pci_device_registration(bus, dev, func, pci_config_get_header_0(bus, dev, func)); 232 | 233 | if (!common_header.mf) break; // Not multifunction 234 | 235 | } 236 | else{ 237 | 238 | if (common_header.vendor_id == 0xFFFF) continue; // Not found 239 | 240 | pci_device_registration(bus, dev, func, pci_config_get_header_0(bus, dev, func)); 241 | 242 | } 243 | 244 | } 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/libs/device.c: -------------------------------------------------------------------------------- 1 | #include "device.h" 2 | 3 | struct class_map pci_class_names[] = { 4 | {UNCLASSIFIED, "UNCLASSIFIED"}, 5 | {STORAGE_CONTROLLER, "STORAGE"}, 6 | {NETWORK_CONTROLLER, "NETWORK"}, 7 | {DISPLAY_CONTROLLER, "DISPLAY"}, 8 | {MULTIMEDIA_CONTROLLER, "MULTIMEDIA"}, 9 | {MEMORY_CONTROLLER, "MEMORY"}, 10 | {BRIDGE, "BRIDGE"}, 11 | {SIMPLE_COMMUNICATION_CONTROLLER, "SIMPLE_COMMUNICATION"}, 12 | {BASE_SYSTEM_PERIPHERAL, "BASE_SYSTEM_PERIPHERAL"}, 13 | {INPUT_DEVICE_CONTROLLER, "INPUT_DEVICE"}, 14 | {DOCKING_STATION, "DOCKING_STATION"}, 15 | {PROCESSOR, "PROCESSOR"}, 16 | {SERIAL_BUS_CONTROLLER, "SERIAL_BUS"}, 17 | {WIRELESS_CONTROLLER, "WIRELESS"}, 18 | {INTELLIGENT_CONTROLLER, "INTELLIGENT"}, 19 | {SATELLITE_COMMUNICATION_CONTROLLER, "SATELLITE_COMMUNICATION"}, 20 | {ENCRYPTION_CONTROLLER, "ENCRYPTION"}, 21 | {SIGNAL_PROCESSING_CONTROLLER, "SIGNAL_PROCESSING"}, 22 | {PROCESSING_ACCELERATOR, "PROCESSING_ACCELERATOR"}, 23 | {NON_ESSENTIAL_INSTRUMENTATION, "NON_ESSENTIAL_INSTRUMENTATION"}, 24 | {UNASSIGNED_CLASS, "UNASSIGNED_CLASS"}, 25 | {0, 0} // маркер конца 26 | }; 27 | 28 | 29 | struct subclass_map pci_subclass_storage_names[] = { 30 | {STORAGE_CONTROLLER, STORAGE_SCSI_BUS_CONTROLLER, "SCSI_BUS_CONTROLLER"}, 31 | {STORAGE_CONTROLLER, STORAGE_IDE_CONTROLLER, "IDE_CONTROLLER"}, 32 | {STORAGE_CONTROLLER, STORAGE_FLOPPY_DISK_CONTROLLER, "FLOPPY_DISK_CONTROLLER"}, 33 | {STORAGE_CONTROLLER, STORAGE_IPI_BUS_CONTROLLER, "IPI_BUS_CONTROLLER"}, 34 | {STORAGE_CONTROLLER, STORAGE_RAID_CONTROLLER, "RAID_CONTROLLER"}, 35 | {STORAGE_CONTROLLER, STORAGE_ATA_CONTROLLER, "ATA_CONTROLLER"}, 36 | {STORAGE_CONTROLLER, STORAGE_SERIAL_ATA_CONTROLLER, "SERIAL_ATA_CONTROLLER"}, 37 | {STORAGE_CONTROLLER, STORAGE_SERIAL_ATTACHED_SCSI, "SERIAL_ATTACHED_SCSI"}, 38 | {STORAGE_CONTROLLER, STORAGE_NON_VOLATILE_MEMORY, "NON_VOLATILE_MEMORY"}, 39 | {STORAGE_CONTROLLER, STORAGE_OTHER, "OTHER"}, 40 | {0, 0, 0} // маркер конца 41 | }; 42 | 43 | struct subclass_map pci_subclass_network_names[] = { 44 | {NETWORK_CONTROLLER, NETWORK_ETHERNET_CONTROLLER, "ETHERNET_CONTROLLER"}, 45 | {NETWORK_CONTROLLER, NETWORK_TOKEN_RING_CONTROLLER, "TOKEN_RING_CONTROLLER"}, 46 | {NETWORK_CONTROLLER, NETWORK_FDDI_CONTROLLER, "FDDI_CONTROLLER"}, 47 | {NETWORK_CONTROLLER, NETWORK_ATM_CONTROLLER, "ATM_CONTROLLER"}, 48 | {NETWORK_CONTROLLER, NETWORK_ISDN_CONTROLLER, "ISDN_CONTROLLER"}, 49 | {NETWORK_CONTROLLER, NETWORK_WORLDFIP_CONTROLLER, "WORLDFIP_CONTROLLER"}, 50 | {NETWORK_CONTROLLER, NETWORK_PICMG_MC_CONTROLLER, "PICMG_MC_CONTROLLER"}, 51 | {NETWORK_CONTROLLER, NETWORK_INFINIBAND_CONTROLLER, "INFINIBAND_CONTROLLER"}, 52 | {NETWORK_CONTROLLER, NETWORK_FABRIC_CONTROLLER, "FABRIC_CONTROLLER"}, 53 | {NETWORK_CONTROLLER, NETWORK_OTHER, "OTHER"}, 54 | {0, 0, 0} // маркер конца 55 | }; 56 | 57 | struct subclass_map pci_subclass_display_names[] = { 58 | {DISPLAY_CONTROLLER, DISPLAY_VGA_COMPATIBLE, "VGA_COMPATIBLE"}, 59 | {DISPLAY_CONTROLLER, DISPLAY_XGA, "XGA"}, 60 | {DISPLAY_CONTROLLER, DISPLAY_3D, "3D"}, 61 | {DISPLAY_CONTROLLER, DISPLAY_OTHER, "OTHER"}, 62 | {0, 0, 0} // маркер конца 63 | }; 64 | 65 | struct subclass_map pci_subclass_multimedia_names[] = { 66 | {MULTIMEDIA_CONTROLLER, MULTIMEDIA_VIDEO, "VIDEO"}, 67 | {MULTIMEDIA_CONTROLLER, MULTIMEDIA_AUDIO, "AUDIO"}, 68 | {MULTIMEDIA_CONTROLLER, MULTIMEDIA_TELEPHONY, "TELEPHONY"}, 69 | {MULTIMEDIA_CONTROLLER, MULTIMEDIA_AUDIO_DEVICE, "AUDIO_DEVICE"}, 70 | {MULTIMEDIA_CONTROLLER, MULTIMEDIA_AUDIO_DEVICE, "OTHER"}, 71 | {0, 0, 0} // маркер конца 72 | }; 73 | 74 | struct subclass_map pci_subclass_memory_names[] = { 75 | {MEMORY_CONTROLLER, MEMORY_RAM, "RAM"}, 76 | {MEMORY_CONTROLLER, MEMORY_FLASH, "FLASH"}, 77 | {MEMORY_CONTROLLER, MEMORY_OTHER, "OTHER"}, 78 | {0, 0, 0} // маркер конца 79 | }; 80 | 81 | struct subclass_map pci_subclass_bridge_names[] = { 82 | {BRIDGE, BRIDGE_HOST, "HOST"}, 83 | {BRIDGE, BRIDGE_ISA, "ISA"}, 84 | {BRIDGE, BRIDGE_EISA, "EISA"}, 85 | {BRIDGE, BRIDGE_MCA, "MCA"}, 86 | {BRIDGE, BRIDGE_PCI_TO_PCI, "PCI_TO_PCI"}, 87 | {BRIDGE, BRIDGE_PCMCIA, "PCMCIA"}, 88 | {BRIDGE, BRIDGE_NUBUS, "NUBUS"}, 89 | {BRIDGE, BRIDGE_CARDBUS, "CARDBUS"}, 90 | {BRIDGE, BRIDGE_RACEWAY, "RACEWAY"}, 91 | {BRIDGE, BRIDGE_PCI_TO_PCI1, "PCI_TO_PCI1"}, 92 | {BRIDGE, BRIDGE_INFINIBAND_TO_PCI, "INFINIBAND_TO_PCI"}, 93 | {BRIDGE, BRIDGE_OTHER, "OTHER"}, 94 | {0, 0, 0} // маркер конца 95 | }; 96 | 97 | struct subclass_map pci_subclass_scomm_names[] = { 98 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_SERIAL, "SERIAL"}, 99 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_PARALLEL, "PARALLEL"}, 100 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_MULTI_SERIAL, "MULTI_SERIAL"}, 101 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_MODEM, "MODEM"}, 102 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_GPIB, "GPIB"}, 103 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_SMART_CARD, "SMART_CARD"}, 104 | {SIMPLE_COMMUNICATION_CONTROLLER, SCOMM_OTHER, "OTHER"}, 105 | {0, 0, 0} // маркер конца 106 | }; 107 | 108 | struct subclass_map pci_subclass_sys_peripheral_names[] = { 109 | {BASE_SYSTEM_PERIPHERAL, BSP_PIC, "PIC"}, 110 | {BASE_SYSTEM_PERIPHERAL, BSP_DMA, "DMA"}, 111 | {BASE_SYSTEM_PERIPHERAL, BSP_TIMER, "TIMER"}, 112 | {BASE_SYSTEM_PERIPHERAL, BSP_RTC, "RTC"}, 113 | {BASE_SYSTEM_PERIPHERAL, BSP_PCI_HOTPLUG, "PCI_HOTPLUG"}, 114 | {BASE_SYSTEM_PERIPHERAL, BSP_SD_HOST, "SD_HOST"}, 115 | {BASE_SYSTEM_PERIPHERAL, BSP_IOMMU, "IOMMU"}, 116 | {BASE_SYSTEM_PERIPHERAL, BSP_OTHER, "OTHER"}, 117 | {0, 0, 0} // маркер конца 118 | }; 119 | 120 | struct subclass_map pci_subclass_input_device_names[] = { 121 | {INPUT_DEVICE_CONTROLLER, INPUT_KEYBOARD, "KEYBOARD"}, 122 | {INPUT_DEVICE_CONTROLLER, INPUT_DIGITIZER, "DIGITIZER"}, 123 | {INPUT_DEVICE_CONTROLLER, INPUT_MOUSE, "MOUSE"}, 124 | {INPUT_DEVICE_CONTROLLER, INPUT_SCANNER, "SCANNER"}, 125 | {INPUT_DEVICE_CONTROLLER, INPUT_GAMEPORT, "GAMEPORT"}, 126 | {INPUT_DEVICE_CONTROLLER, INPUT_OTHER, "OTHER"}, 127 | {0, 0, 0} // маркер конца 128 | }; 129 | 130 | struct subclass_map pci_subclass_docking_station_names[] = { 131 | {DOCKING_STATION, DOCK_GENERIC, "GENERIC"}, 132 | {DOCKING_STATION, DOCK_OTHER, "OTHER"}, 133 | {0, 0, 0} // маркер конца 134 | }; 135 | 136 | struct subclass_map pci_subclass_processor_names[] = { 137 | {PROCESSOR, PROC_386, "386"}, 138 | {PROCESSOR, PROC_486, "486"}, 139 | {PROCESSOR, PROC_PENTIUM, "PENTIUM"}, 140 | {PROCESSOR, PROC_PENTIUM_PRO, "PENTIUM_PRO"}, 141 | {PROCESSOR, PROC_ALPHA, "ALPHA"}, 142 | {PROCESSOR, PROC_POWERPC, "POWERPC"}, 143 | {PROCESSOR, PROC_MIPS, "MIPS"}, 144 | {PROCESSOR, PROC_CO_PROCESSOR, "CO_PROCESSOR"}, 145 | {PROCESSOR, PROC_OTHER, "OTHER"}, 146 | {0, 0, 0} // маркер конца 147 | }; 148 | 149 | struct subclass_map pci_subclass_serbus_names[] = { 150 | {SERIAL_BUS_CONTROLLER, SERBUS_FIREWIRE, "FIREWIRE"}, 151 | {SERIAL_BUS_CONTROLLER, SERBUS_ACCESS, "ACCESS"}, 152 | {SERIAL_BUS_CONTROLLER, SERBUS_SSA, "SSA"}, 153 | {SERIAL_BUS_CONTROLLER, SERBUS_USB, "USB"}, 154 | {SERIAL_BUS_CONTROLLER, SERBUS_FIBRE_CHANNEL, "FIBRE_CHANNEL"}, 155 | {SERIAL_BUS_CONTROLLER, SERBUS_SMBUS, "SMBUS"}, 156 | {SERIAL_BUS_CONTROLLER, SERBUS_INFINIBAND, "INFINIBAND"}, 157 | {SERIAL_BUS_CONTROLLER, SERBUS_IPMI, "IPMI"}, 158 | {SERIAL_BUS_CONTROLLER, SERBUS_SERCOS, "SERCOS"}, 159 | {SERIAL_BUS_CONTROLLER, SERBUS_CANBUS, "CANBUS"}, 160 | {SERIAL_BUS_CONTROLLER, SERBUS_OTHER, "OTHER"}, 161 | {0, 0, 0} // маркер конца 162 | }; 163 | 164 | struct subclass_map pci_subclass_wireless_names[] = { 165 | {WIRELESS_CONTROLLER, WIRELESS_IRDA, "IRDA"}, 166 | {WIRELESS_CONTROLLER, WIRELESS_CONSUMER_IR, "CONSUMER_IR"}, 167 | {WIRELESS_CONTROLLER, WIRELESS_RF, "RF"}, 168 | {WIRELESS_CONTROLLER, WIRELESS_BLUETOOTH, "BLUETOOTH"}, 169 | {WIRELESS_CONTROLLER, WIRELESS_BROADBAND, "BROADBAND"}, 170 | {WIRELESS_CONTROLLER, WIRELESS_ETHERNET_A, "ETHERNET_A"}, 171 | {WIRELESS_CONTROLLER, WIRELESS_ETHERNET_B, "ETHERNET_B"}, 172 | {WIRELESS_CONTROLLER, WIRELESS_OTHER, "OTHER"}, 173 | {0, 0, 0} // маркер конца 174 | }; 175 | 176 | struct subclass_map pci_subclass_intelligent_names[] = { 177 | {INTELLIGENT_CONTROLLER, INTELLIGENT_I20, "I20"}, 178 | {0, 0, 0} // маркер конца 179 | }; 180 | 181 | 182 | struct subclass_map pci_subclass_satcomm_names[] = { 183 | {SATELLITE_COMMUNICATION_CONTROLLER, SATCOMM_TV, "TV"}, 184 | {SATELLITE_COMMUNICATION_CONTROLLER, SATCOMM_AUDIO, "AUDIO"}, 185 | {SATELLITE_COMMUNICATION_CONTROLLER, SATCOMM_VOICE, "VOICE"}, 186 | {SATELLITE_COMMUNICATION_CONTROLLER, SATCOMM_DATA, "DATA"}, 187 | {0, 0, 0} // маркер конца 188 | }; 189 | 190 | struct subclass_map pci_subclass_encryption_names[] = { 191 | {ENCRYPTION_CONTROLLER, ENCRYPTION_NET_COMP, "NET_COMP"}, 192 | {ENCRYPTION_CONTROLLER, ENCRYPTION_ENTERTAIN, "ENTERTAIN"}, 193 | {ENCRYPTION_CONTROLLER, ENCRYPTION_OTHER, "OTHER"}, 194 | {0, 0, 0} // маркер конца 195 | }; 196 | 197 | struct subclass_map pci_subclass_signproccs_names[] = { 198 | {SIGNAL_PROCESSING_CONTROLLER, SIGPROC_DPIO_MODULES, "DPIO_MODULES"}, 199 | {SIGNAL_PROCESSING_CONTROLLER, SIGPROC_PERF_COUNTERS, "PERF_COUNTERS"}, 200 | {SIGNAL_PROCESSING_CONTROLLER, SIGPROC_COMM_SYNC, "COMM_SYNC"}, 201 | {SIGNAL_PROCESSING_CONTROLLER, SIGPROC_SIG_PROC_MGMT, "SIG_PROC_MGMT"}, 202 | {SIGNAL_PROCESSING_CONTROLLER, SIGPROC_OTHER, "OTHER"}, 203 | {0, 0, 0} // маркер конца 204 | }; 205 | 206 | struct subclass_map* pci_subclass_names[] = { 207 | pci_subclass_storage_names, 208 | pci_subclass_network_names, 209 | pci_subclass_display_names, 210 | pci_subclass_multimedia_names, 211 | pci_subclass_memory_names, 212 | pci_subclass_bridge_names, 213 | pci_subclass_scomm_names, 214 | pci_subclass_sys_peripheral_names, 215 | pci_subclass_input_device_names, 216 | pci_subclass_docking_station_names, 217 | pci_subclass_processor_names, 218 | pci_subclass_serbus_names, 219 | pci_subclass_wireless_names, 220 | pci_subclass_intelligent_names, 221 | pci_subclass_satcomm_names, 222 | pci_subclass_encryption_names, 223 | pci_subclass_signproccs_names, 224 | 225 | 0 // маркер конца 226 | }; 227 | -------------------------------------------------------------------------------- /src/libs/string.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | // Возвращает символ (цифру), соответствующий цифре 4 | unsigned char itos_table(char i){ 5 | switch (i){ 6 | case 0: return '0'; 7 | case 1: return '1'; 8 | case 2: return '2'; 9 | case 3: return '3'; 10 | case 4: return '4'; 11 | case 5: return '5'; 12 | case 6: return '6'; 13 | case 7: return '7'; 14 | case 8: return '8'; 15 | case 9: return '9'; 16 | default: return '\0'; 17 | } 18 | } 19 | 20 | 21 | // Перевернуть строку 22 | void string_turn_over(unsigned char* string, short size, unsigned char* result){ 23 | for (int i = 0; i < size; i++){ 24 | result[i] = string[size-i-1]; 25 | } 26 | result[size] = '\0'; 27 | } 28 | 29 | 30 | // Int to string. Число в строку 31 | int itos(long i, unsigned char* ret){ 32 | long j = i; 33 | unsigned char result[21]; 34 | 35 | if (i == 0){ 36 | ret[0] = '0'; 37 | ret[1] = '\0'; 38 | return 1; 39 | } 40 | 41 | char string[20]; 42 | int s_ptr = 0; 43 | 44 | if (i < 0) i = i * -1; 45 | 46 | while (i){ 47 | int p = (long)(i % 10); 48 | i = (long)(i / 10); 49 | unsigned char s = itos_table(p); 50 | 51 | string[s_ptr] = s; 52 | s_ptr++; 53 | } 54 | 55 | string_turn_over(&string, s_ptr, &result); 56 | 57 | if (j < 0){ 58 | ret[0] = '-'; 59 | 60 | for (int f = 0; f < s_ptr+1; f++){ 61 | ret[f+1] = result[f]; 62 | } 63 | ret[s_ptr+1] = '\0'; 64 | return s_ptr+1; 65 | } 66 | else{ 67 | for (int f = 0; f < s_ptr; f++){ 68 | ret[f] = result[f]; 69 | } 70 | ret[s_ptr] = '\0'; 71 | return s_ptr; 72 | } 73 | 74 | } 75 | 76 | 77 | // Проверка строки на то, является ли она числом 78 | char is_digit(char* string){ 79 | // пустая строка 80 | if(string[0] == '\0') return 0; 81 | // бегаем пока не конец строки 82 | for (int i = 0; string[i] != '\0'; i++){ 83 | char symbol = string[i]; 84 | // если вдруг отрицательное, то корректная проверка 85 | if (i == 0 && symbol == '-' && string[i+1] != '\0') continue; 86 | // проверка на то, входит ли символ в диапазон цифр 87 | if (symbol < '0' || symbol > '9'){ 88 | return 0; // not digit 89 | } 90 | } 91 | return 1; // is digit 92 | } 93 | 94 | 95 | // Получить размер строки 96 | int strlen(char* string){ 97 | int len = 0; 98 | for (int i = 0; string[i] != '\0'; i++){ 99 | len++; 100 | } 101 | return len; 102 | } 103 | 104 | 105 | // Сравнение строк. Если одинаковые то 1, если разные то 0 106 | char is_str_equally(unsigned char* str1, unsigned char* str2){ 107 | short str1_len = strlen(str1); 108 | for (short n = 0; n <= str1_len; n++){ 109 | unsigned char str1_sym = str1[n]; 110 | unsigned char str2_sym = str2[n]; 111 | unsigned char xor = str1_sym ^ str2_sym; 112 | if (xor != 0 ) return 0; 113 | } 114 | return 1; 115 | } 116 | 117 | 118 | // Возвращает число, соответствующее символу (цифре) 119 | char smtoi(char symbol){ 120 | switch (symbol){ 121 | case '0': return 0; 122 | case '1': return 1; 123 | case '2': return 2; 124 | case '3': return 3; 125 | case '4': return 4; 126 | case '5': return 5; 127 | case '6': return 6; 128 | case '7': return 7; 129 | case '8': return 8; 130 | case '9': return 9; 131 | default: return 0; 132 | } 133 | } 134 | 135 | 136 | // String to int. Строку в число 137 | int stoi(char* string, int* result){ 138 | if (!is_digit(string)){ 139 | return 0; 140 | } 141 | 142 | char minus = 0; 143 | if (string[0] == '-') minus = 1; 144 | 145 | int i_result = 0; 146 | int umn = 1; 147 | short len = strlen(string); 148 | for (int i = len-1; i >= minus; i--){ 149 | char symbol = string[i]; 150 | char digit = smtoi(symbol); 151 | i_result = (digit * umn) + i_result; 152 | umn *= 10; 153 | } 154 | if (minus) i_result *= -1; 155 | *result = i_result; 156 | return 1; 157 | } 158 | 159 | 160 | // Возвращает HEX строку, соответствующее числу 161 | char btox_table(char byte){ 162 | switch(byte){ 163 | case 0: return '0'; 164 | case 1: return '1'; 165 | case 2: return '2'; 166 | case 3: return '3'; 167 | case 4: return '4'; 168 | case 5: return '5'; 169 | case 6: return '6'; 170 | case 7: return '7'; 171 | case 8: return '8'; 172 | case 9: return '9'; 173 | case 10: return 'A'; 174 | case 11: return 'B'; 175 | case 12: return 'C'; 176 | case 13: return 'D'; 177 | case 14: return 'E'; 178 | case 15: return 'F'; 179 | default: return 0; 180 | } 181 | } 182 | 183 | 184 | // Byte to hex. Байт в HEX строку (16-чный вид, строка) 185 | void btox(char byte, struct byte_split_struct* result){ 186 | char low = byte & 0b00001111; 187 | char high = (byte >> 4) & 0b00001111; 188 | result->low = btox_table(low); 189 | result->high = btox_table(high); 190 | } 191 | 192 | 193 | // Pointer to hex. Адрес в HEX строку (16-чный вид, строка) 194 | void ptox(void* ptr, unsigned char* result){ 195 | char hp_num = 7; 196 | for (char i = 0; i < 4; i++){ 197 | 198 | struct byte_split_struct btox_result; 199 | long p = ptr; 200 | btox(p >> (i*8), &btox_result); 201 | 202 | result[hp_num] = btox_result.low; 203 | hp_num--; 204 | result[hp_num] = btox_result.high; 205 | hp_num--; 206 | 207 | } 208 | } 209 | 210 | 211 | // Возвращает символ ASCII по таблице исходя из скан-кода клавиши 212 | char scancode_to_ascii(unsigned char scancode, unsigned char shift_state){ 213 | 214 | if (shift_state){ 215 | 216 | // - - SHIFT - - 217 | 218 | switch (scancode){ 219 | 220 | // Numbers 221 | case 2: return '!'; 222 | case 3: return '@'; 223 | case 4: return '#'; 224 | case 5: return '$'; 225 | case 6: return '%'; 226 | case 7: return '^'; 227 | case 8: return '&'; 228 | case 9: return '*'; 229 | case 10: return '('; 230 | case 11: return ')'; 231 | 232 | // Letters 233 | case 16: return 'Q'; 234 | case 17: return 'W'; 235 | case 18: return 'E'; 236 | case 19: return 'R'; 237 | case 20: return 'T'; 238 | case 21: return 'Y'; 239 | case 22: return 'U'; 240 | case 23: return 'I'; 241 | case 24: return 'O'; 242 | case 25: return 'P'; 243 | 244 | case 30: return 'A'; 245 | case 31: return 'S'; 246 | case 32: return 'D'; 247 | case 33: return 'F'; 248 | case 34: return 'G'; 249 | case 35: return 'H'; 250 | case 36: return 'J'; 251 | case 37: return 'K'; 252 | case 38: return 'L'; 253 | 254 | case 44: return 'Z'; 255 | case 45: return 'X'; 256 | case 46: return 'C'; 257 | case 47: return 'V'; 258 | case 48: return 'B'; 259 | case 49: return 'N'; 260 | case 50: return 'M'; 261 | 262 | // Special symbols 263 | case 12: return '_'; 264 | case 13: return '+'; 265 | case 26: return '{'; 266 | case 27: return '}'; 267 | case 39: return ':'; 268 | case 40: return '"'; 269 | case 51: return '<'; 270 | case 52: return '>'; 271 | case 53: return '?'; 272 | 273 | // Special keys 274 | case 57: return ' '; // Space 275 | 276 | default: return '\0'; // If different, then 0 277 | } 278 | 279 | } 280 | else{ 281 | 282 | // - - WITHOUT SHIFT - - 283 | 284 | switch (scancode){ 285 | 286 | // Numbers 287 | case 2: return '1'; 288 | case 3: return '2'; 289 | case 4: return '3'; 290 | case 5: return '4'; 291 | case 6: return '5'; 292 | case 7: return '6'; 293 | case 8: return '7'; 294 | case 9: return '8'; 295 | case 10: return '9'; 296 | case 11: return '0'; 297 | 298 | // Letters 299 | case 16: return 'q'; 300 | case 17: return 'w'; 301 | case 18: return 'e'; 302 | case 19: return 'r'; 303 | case 20: return 't'; 304 | case 21: return 'y'; 305 | case 22: return 'u'; 306 | case 23: return 'i'; 307 | case 24: return 'o'; 308 | case 25: return 'p'; 309 | 310 | case 30: return 'a'; 311 | case 31: return 's'; 312 | case 32: return 'd'; 313 | case 33: return 'f'; 314 | case 34: return 'g'; 315 | case 35: return 'h'; 316 | case 36: return 'j'; 317 | case 37: return 'k'; 318 | case 38: return 'l'; 319 | 320 | case 44: return 'z'; 321 | case 45: return 'x'; 322 | case 46: return 'c'; 323 | case 47: return 'v'; 324 | case 48: return 'b'; 325 | case 49: return 'n'; 326 | case 50: return 'm'; 327 | 328 | // Special symbols 329 | case 12: return '-'; 330 | case 13: return '='; 331 | case 26: return '['; 332 | case 27: return ']'; 333 | case 39: return ';'; 334 | case 40: return '\''; 335 | case 51: return ','; 336 | case 52: return '.'; 337 | case 53: return '/'; 338 | 339 | // Special keys 340 | case 57: return ' '; // Space 341 | 342 | default: return '\0'; // If different, then 0 343 | } 344 | } 345 | } 346 | 347 | 348 | // Является ли сканкод символом 349 | int is_symbol_scancode(unsigned char scancode){ 350 | if ((scancode >= 2 && scancode <= 13) || (scancode >= 16 && scancode <= 27) || 351 | (scancode >= 30 && scancode <= 57)) return 1; 352 | else return 0; 353 | } 354 | --------------------------------------------------------------------------------