mirror of
https://github.com/0Nera/BMOSP.git
synced 2025-02-19 18:43:58 +03:00
Merge branch 'master' of https://git.synapseos.ru/Aren/BMOSP
This commit is contained in:
commit
e1e88ada09
2
TODO.md
2
TODO.md
@ -12,7 +12,7 @@
|
||||
|
||||
Модули:
|
||||
|
||||
- [ ] Оболочка ввода-вывода
|
||||
- [X] Оболочка ввода-вывода
|
||||
|
||||
Драйвера:
|
||||
|
||||
|
@ -19,9 +19,6 @@ TERM_WALLPAPER=boot:///mod/boot.jpg
|
||||
MODULE_PATH=boot:///mod/pci_vendors.txt
|
||||
MODULE_CMDLINE=[PCI][DATA][VENDORS]
|
||||
|
||||
MODULE_PATH=boot:///mod/boot.tga
|
||||
MODULE_CMDLINE=[BOOTIMG]
|
||||
|
||||
MODULE_PATH=boot:///mod/simd.ko
|
||||
MODULE_CMDLINE=[MOD]simd.ko
|
||||
|
||||
@ -37,12 +34,6 @@ TERM_WALLPAPER=boot:///mod/boot.jpg
|
||||
MODULE_PATH=boot:///mod/cpubench.ko
|
||||
MODULE_CMDLINE=[MOD]cpubench.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/tga.ko
|
||||
MODULE_CMDLINE=[MOD]tga.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/imfs.ko
|
||||
MODULE_CMDLINE=[MOD]imfs.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/hello.ko
|
||||
MODULE_CMDLINE=[MOD]hello.ko
|
||||
|
||||
|
@ -13,7 +13,7 @@ sudo apt install unzip
|
||||
## Ubuntu 18.04+
|
||||
|
||||
```bash
|
||||
sudo apt install clang-format python3 git qemu-system-x86 qemu-system-gui gdisk dos2unix xorriso libc6 gcc make curl
|
||||
sudo apt install clang-format python3 git qemu-system-x86 qemu-system-gui gdisk dos2unix xorriso libc6 gcc make curl mtools
|
||||
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
||||
cd BMOSP/
|
||||
chmod +x build.sh
|
||||
@ -26,23 +26,12 @@ chmod +x build.sh
|
||||
В qemu недоступен флаг `-cpu max`, просто уберите его при запуске
|
||||
|
||||
```bash
|
||||
sudo apt install clang-format python3.7 git qemu-system-x86 gdisk dos2unix xorriso libc6 gcc make curl
|
||||
sudo apt install clang-format python3.7 git qemu-system-x86 gdisk dos2unix xorriso libc6 gcc make curl mtools
|
||||
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
||||
cd BMOSP/
|
||||
python3.7 pbuild.py
|
||||
```
|
||||
|
||||
## ArchLinux
|
||||
|
||||
```bash
|
||||
yay -S clang-format
|
||||
sudo pacman -S python3 git qemu-system-x86 qemu-system-gui xorriso libc6 gcc make curl
|
||||
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
||||
cd BMOSP/
|
||||
chmod +x build.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
## Qemu
|
||||
|
@ -1,3 +1,3 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_BUILD 0
|
||||
#define VERSION_BUILD 52
|
||||
|
@ -7,9 +7,70 @@
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <log.h>
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} gdt_reg_t;
|
||||
|
||||
struct gdt_desc {
|
||||
uint16_t limit;
|
||||
uint16_t base_low;
|
||||
uint8_t base_mid;
|
||||
uint8_t access;
|
||||
uint8_t granularity;
|
||||
uint8_t base_hi;
|
||||
} __attribute__((packed));
|
||||
|
||||
static uint64_t kernel_start_ticks = 0;
|
||||
static uint64_t kernel_ticks = 0;
|
||||
static gdt_reg_t gdtr;
|
||||
static struct gdt_desc gdt_descs[] = { { 0 },
|
||||
|
||||
{ .limit = 0xffff,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10011011,
|
||||
.granularity = 0b00000000,
|
||||
.base_hi = 0x00 },
|
||||
|
||||
{ .limit = 0xffff,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10010011,
|
||||
.granularity = 0b00000000,
|
||||
.base_hi = 0x00 },
|
||||
|
||||
{ .limit = 0xffff,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10011011,
|
||||
.granularity = 0b11001111,
|
||||
.base_hi = 0x00 },
|
||||
|
||||
{ .limit = 0xffff,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10010011,
|
||||
.granularity = 0b11001111,
|
||||
.base_hi = 0x00 },
|
||||
|
||||
{ .limit = 0x0000,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10011011,
|
||||
.granularity = 0b00100000,
|
||||
.base_hi = 0x00 },
|
||||
|
||||
{ .limit = 0x0000,
|
||||
.base_low = 0x0000,
|
||||
.base_mid = 0x00,
|
||||
.access = 0b10010011,
|
||||
.granularity = 0b00000000,
|
||||
.base_hi = 0x00 } };
|
||||
|
||||
extern void load_gdt(uint64_t gdtr);
|
||||
|
||||
uint64_t rdtsc( ) {
|
||||
unsigned int lo, hi;
|
||||
@ -41,6 +102,12 @@ uint64_t arch_get_tick_l( ) {
|
||||
}
|
||||
|
||||
void arch_init( ) {
|
||||
LOG("Установка сегментов\n");
|
||||
gdtr.limit = (sizeof(gdt_descs) - 1);
|
||||
gdtr.base = (uint64_t)&gdt_descs;
|
||||
load_gdt((uint64_t)&gdtr);
|
||||
LOG("Установка сегментов успешна!\n");
|
||||
|
||||
pic_init( );
|
||||
idt_init( );
|
||||
cpu_init( );
|
||||
|
@ -61,6 +61,24 @@ static void do_amd( ) {
|
||||
LOG("cpu_family = [%u]\n", cpu_family);
|
||||
}
|
||||
|
||||
static void do_intel( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
uint32_t cpu_model;
|
||||
uint32_t cpu_family;
|
||||
uint32_t cpu_brand_id;
|
||||
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
cpu_brand_id = ebx;
|
||||
cpu_family = ((eax >> 8) & 0xFF) + ((eax >> 20) & 0xFF);
|
||||
cpu_model = ((eax >> 4) & 0xF) | ((eax >> 12) & 0xF0);
|
||||
|
||||
LOG("Используется процессор Intel\n");
|
||||
LOG("cpu_brand_id = [%u]\n", cpu_brand_id);
|
||||
LOG("cpu_family = [%u]\n", cpu_family);
|
||||
LOG("cpu_model = [%u]\n", cpu_model);
|
||||
}
|
||||
|
||||
static void brandname( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
char brand_string[49];
|
||||
@ -86,15 +104,13 @@ static void brandname( ) {
|
||||
}
|
||||
|
||||
if (manufacturer[0] == 0x68747541) { do_amd( ); }
|
||||
}
|
||||
|
||||
void cpu_idle( ) {
|
||||
if (acpi_msrs_support) { LOG("Температура: %d (в QEMU/KVM всегда 0)\n", get_cpu_temperature_intel( )); }
|
||||
if (manufacturer[0] == 0x756E6547) { do_intel( ); }
|
||||
}
|
||||
|
||||
void cpu_init( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 22) & 1) {
|
||||
acpi_msrs_support = true;
|
||||
LOG("Встроенный терморегулятор MSRS для ACPI\n");
|
||||
|
@ -1,8 +1,8 @@
|
||||
.global load_gdt
|
||||
load_gdt:
|
||||
cli
|
||||
lgdt (%rdi)
|
||||
movw $0x30, %ax
|
||||
lgdt (%rdi) # Загружаем GDT
|
||||
movw $0x30, %ax # Обновляем GDT
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
|
@ -334,10 +334,10 @@ void mem_init( ) {
|
||||
LOG("Размер битовой карты: %u\n", bitmap_size);
|
||||
|
||||
alloc_init(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
|
||||
LOG("%u мегабайт выделено в динамичную память\n", (256 * 32 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
||||
LOG("%u мегабайт выделено в динамичную память\n", (256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
||||
|
||||
// Выделяем по 4 мегабайта в аллокатор динамичной памяти
|
||||
for (uint64_t i = 0; i < 64; i += 8) { mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE); }
|
||||
for (uint64_t i = 0; i < 32; i += 8) { mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE); }
|
||||
|
||||
mem_merge_all_blocks( );
|
||||
mem_dump_memory( );
|
||||
|
@ -33,7 +33,7 @@ static void *elf_entry(elf64_header_t *module_bin) {
|
||||
// Приводим заголовок ELF файла к типу elf64_header_t
|
||||
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
|
||||
|
||||
// LOG("(uint64_t)elf_header->e_entry = 0x%x, type = %u\n", (uint64_t)elf_header->e_entry, elf_header->e_type);
|
||||
LOG("(uint64_t)elf_header->e_entry = 0x%x, тип = %u\n", (uint64_t)elf_header->e_entry, elf_header->e_type);
|
||||
|
||||
if (elf_header->e_type != 2) {
|
||||
LOG("\t\tОшибка! Модуль неправильно собран!\n");
|
||||
@ -92,6 +92,7 @@ void mod_init( ) {
|
||||
LOG("Ошибка выделения памяти для массива module_list\n");
|
||||
return;
|
||||
}
|
||||
LOG("module_list = 0x%x\n", module_list);
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < module_count; i++) {
|
||||
@ -146,6 +147,7 @@ void mod_init( ) {
|
||||
module_list[modules_count].name = ret.name;
|
||||
module_list[modules_count].message = ret.message;
|
||||
module_list[modules_count].data_size = ret.data_size;
|
||||
module_list[modules_count].data = ret.data;
|
||||
module_list[modules_count].get_func = ret.get_func;
|
||||
module_list[modules_count].after_init = ret.after_init;
|
||||
|
||||
@ -153,8 +155,6 @@ void mod_init( ) {
|
||||
task_new_thread(module_list[modules_count].after_init, module_list[modules_count].name);
|
||||
}
|
||||
|
||||
if (ret.data_size != 0) { module_list[modules_count].data = ret.data; }
|
||||
|
||||
if (ret.irq != 0) {
|
||||
if (ret.irq_handler != 0) {
|
||||
LOG("Установлен обработчик прерывания [%u] по адресу 0x%x в модуле %s\n", ret.irq, ret.irq_handler,
|
||||
|
@ -16,18 +16,6 @@
|
||||
#include <version.h>
|
||||
|
||||
uint64_t full_init = 0;
|
||||
uint64_t dum = 0;
|
||||
|
||||
void finally( ) {
|
||||
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
void dummy( ) {
|
||||
LOG("Поток %u\n", dum++);
|
||||
task_del_current( );
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
// Точка входа
|
||||
void _start( ) {
|
||||
@ -52,12 +40,11 @@ void _start( ) {
|
||||
time_t time = rtc_get_time( );
|
||||
LOG("Время: %u:%u.%u, %u.%u.%u\n", time.hours, time.minutes, time.second, time.day, time.month, time.year);
|
||||
|
||||
task_new_thread(finally, "fin");
|
||||
|
||||
full_init = 1;
|
||||
|
||||
task_after_init( );
|
||||
|
||||
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
|
||||
asm volatile("sti");
|
||||
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
|
@ -3,6 +3,11 @@
|
||||
static const char name[] = "[APP]Привет мир!";
|
||||
static const char message[] = "Привет из модуля!";
|
||||
|
||||
static int app_main( ) {
|
||||
fb_printf("[%s]\n", message);
|
||||
return 2 + 2;
|
||||
}
|
||||
|
||||
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
|
||||
init_env(env);
|
||||
fb_printf("[%s]\n", message);
|
||||
@ -10,7 +15,7 @@ module_info_t __attribute__((section(".minit"))) init(env_t *env) {
|
||||
.message = (char *)&message,
|
||||
.type = 0,
|
||||
.data_size = 0,
|
||||
.data = (void *)0,
|
||||
.data = (void *)&app_main,
|
||||
.err_code = 0,
|
||||
.module_id = 0,
|
||||
.irq = 0,
|
||||
|
@ -4,6 +4,61 @@ static module_info_t *mod_list = NULL;
|
||||
static uint64_t *mod_count = NULL;
|
||||
static uint64_t app_count = 0;
|
||||
static module_info_t *app_list = NULL;
|
||||
static char (*getc)( ) = NULL;
|
||||
|
||||
static inline int is_digit(char c) {
|
||||
if (c >= '0' && c <= '9') { return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t char_to_digit(char c) {
|
||||
if (is_digit(c)) { return (int64_t)(c - '0'); }
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ios_main( ) {
|
||||
module_info_t *kbd_mod = get_module("[KEYBOARD]");
|
||||
|
||||
if (kbd_mod == NULL) {
|
||||
fb_printf("Клавиатура не найдена!\n");
|
||||
delete_thread( );
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
getc = kbd_mod->get_func(2);
|
||||
|
||||
while (1) {
|
||||
fb_printf("Доступные программы:\n");
|
||||
for (uint64_t i = 0; i < app_count; i++) { fb_printf(" %2u. %s\n", i, app_list[i].name); }
|
||||
fb_printf(" %2u. Выход\n", app_count + 1);
|
||||
|
||||
fb_printf("[IOS]>");
|
||||
|
||||
char c = '\0';
|
||||
|
||||
do { c = getc( ); } while (!is_digit(c));
|
||||
|
||||
fb_printf(" %c\n", c);
|
||||
|
||||
int select = char_to_digit(c);
|
||||
|
||||
if (select == app_count + 1) {
|
||||
fb_printf("Выход\n");
|
||||
delete_thread( );
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
if (select > app_count - 1) {
|
||||
fb_printf("Ошибка! %u не входит в список\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
fb_printf("Запуск %s...\n", app_list[select].name);
|
||||
int (*app)( ) = (int (*)( ))app_list[select].data;
|
||||
int ret = (*app)( );
|
||||
fb_printf("\nПриложение %s завершилось с кодом: %d\n", app_list[select].name, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void main( ) {
|
||||
fb_printf("IOS (input-output shell) - оболочка ввода-вывода\n");
|
||||
@ -22,7 +77,7 @@ static void main( ) {
|
||||
|
||||
for (uint64_t i = 0; i < *mod_count; i++) {
|
||||
if (str_contains(mod_list[i].name, "[APP]")) {
|
||||
fb_printf("%u. %s\n", app_count, mod_list[i].name);
|
||||
// fb_printf("%u. %s\n", app_count, mod_list[i].name);
|
||||
app_list[app_count] = mod_list[i];
|
||||
app_count++;
|
||||
}
|
||||
@ -36,7 +91,7 @@ static void main( ) {
|
||||
delete_thread( );
|
||||
} else {
|
||||
app_list = realloc(app_list, app_count * sizeof(module_info_t));
|
||||
for (uint64_t i = 0; i < app_count; i++) { fb_printf("%2u.\t%s\n", app_list[i]); }
|
||||
ios_main( );
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
|
@ -7,17 +7,9 @@ static int ru = 1;
|
||||
static char c_char = '\0';
|
||||
static key_event_t keyboard_buffer;
|
||||
|
||||
void virt_exit( ) {
|
||||
fb_printf("Выход для Bochs\n");
|
||||
outw(0xB004, 0x2000);
|
||||
|
||||
fb_printf("Выход для Qemu\n");
|
||||
static void virt_exit( ) {
|
||||
outw(0x604, 0x2000);
|
||||
|
||||
fb_printf("Выход для Virtualbox\n");
|
||||
outw(0x4004, 0x3400);
|
||||
|
||||
fb_printf("Выход для облачного гипервизора\n");
|
||||
outw(0x600, 0x34);
|
||||
}
|
||||
|
||||
@ -80,8 +72,7 @@ static int is_ctrl(uint8_t scancode) {
|
||||
}
|
||||
}
|
||||
|
||||
void handler(struct frame *state) {
|
||||
(void)state;
|
||||
static void handler( ) {
|
||||
while (!(inb(0x64) & 1)) { asm volatile("pause"); }
|
||||
|
||||
uint8_t scancode = inb(0x60);
|
||||
@ -159,7 +150,6 @@ module_info_t __attribute__((section(".minit"))) init(env_t *env) {
|
||||
current_state = NORMAL_STATE;
|
||||
keyboard_buffer.ctrl_pressed = 0;
|
||||
keyboard_buffer.shift_pressed = 0;
|
||||
fb_printf("\t\t[%u][%c]\n", 27, 27);
|
||||
|
||||
return (module_info_t){ .name = (char *)"[KEYBOARD]",
|
||||
.message = (char *)"PS/2 драйвер",
|
||||
@ -169,6 +159,6 @@ module_info_t __attribute__((section(".minit"))) init(env_t *env) {
|
||||
.err_code = 0,
|
||||
.module_id = 0,
|
||||
.irq = 33,
|
||||
.irq_handler = handler,
|
||||
.irq_handler = &handler,
|
||||
.get_func = __get_func };
|
||||
}
|
2
run.sh
2
run.sh
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 \
|
||||
qemu-system-x86_64 -name "БМПОС" -cpu max -m 64M -smp 1 \
|
||||
-serial file:serial.log \
|
||||
-drive file=bmosp.hdd,if=none,id=sata_drive -device ahci \
|
||||
-device virtio-blk-pci,drive=sata_drive \
|
||||
|
@ -100,42 +100,6 @@ def check_limine():
|
||||
subprocess.run(["make"])
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
|
||||
def check_os():
|
||||
import platform
|
||||
using_distro = False
|
||||
try:
|
||||
import distro
|
||||
using_distro = True
|
||||
except ImportError:
|
||||
pass
|
||||
if using_distro:
|
||||
linux_distro = distro.like()
|
||||
else:
|
||||
try:
|
||||
linux_distro = platform.linux_distribution()[0]
|
||||
except Exception as E:
|
||||
return 1
|
||||
if linux_distro.lower() in ['debian', 'ubuntu', 'astra']:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def check_tools():
|
||||
required_tools = ["gcc", "g++", "xorriso", "make", "mtools", "curl"]
|
||||
missing_tools = []
|
||||
|
||||
for tool in required_tools:
|
||||
if shutil.which(tool) is None:
|
||||
missing_tools.append(tool)
|
||||
|
||||
if len(missing_tools) > 0:
|
||||
if check_os():
|
||||
subprocess.run(["sudo", "apt", "install"] + missing_tools)
|
||||
return
|
||||
subprocess.run(["sudo", "pacman", "-S"] + missing_tools)
|
||||
|
||||
|
||||
def create_hdd(IMAGE_NAME):
|
||||
os.system(f"rm -f {IMAGE_NAME}.hdd".format())
|
||||
os.system(f"dd if=/dev/zero bs=1M count=0 seek=4 of={IMAGE_NAME}.hdd")
|
||||
@ -191,10 +155,6 @@ if __name__ == "__main__":
|
||||
print("Установка Limine")
|
||||
check_limine()
|
||||
|
||||
print("Проверка зависимостей")
|
||||
|
||||
check_tools()
|
||||
|
||||
major, minor, build = version_build()
|
||||
|
||||
print("Сборка модульного ядра")
|
||||
|
Loading…
x
Reference in New Issue
Block a user