├── 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 |
--------------------------------------------------------------------------------