Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

108 changed files with 1486 additions and 4339 deletions

View File

@ -1,4 +1,4 @@
ColumnLimit: 120
ColumnLimit: 80
IndentWidth: 4
UseTab: ForIndentation
TabWidth: 4

View File

@ -1,34 +0,0 @@
---
name: Отчет об ошибке
about: " Создайте отчет, который поможет нам улучшить проект"
title: ''
labels: bug
assignees: 0Nera
---
**Опишите ошибку**
Четкое и лаконичное описание того, в чем заключается ошибка.
**Шаги воспроизведения**
Проделанные шаги:
1. Собрал ядро
2. Поменялись обои в гостинной
**Ожидаемое поведение**
Четкое и лаконичное описание того, что вы ожидали увидеть.
**Фото и видео**
Если применимо, добавьте скриншоты, которые помогут объяснить вашу проблему.
**Среда**
Опишите среду сборки и запуска
- ОС: (Windows 10 + WSL2, Astra linux, ALT Linux, Ubuntu 22)
- Компилятор: (gcc, clang, пересобранный gcc)
- Версия компилятора: 11.0.2
- Версия ядра: 1.2.78
**Дополнительно**
Добавьте сюда любою другую информацию, касательно проблемы.

View File

@ -13,13 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: install depends
run: |
sudo apt update
sudo apt upgrade
sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
run: sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
- name: install limine
run: |
git clone https://git.synapseos.ru/Aren/limine.git --branch=v5.x-branch-binary --depth=1
@ -38,4 +35,4 @@ jobs:
run: ls -la iso_root
- name: check bin
run: ls -la bin
run: ls -la bin

View File

@ -1,80 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '28 15 * * 1'
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ 'ubuntu-latest' }}
timeout-minutes: ${{ 360 }}
permissions:
# required for all workflows
security-events: write
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
language: [ 'c-cpp', 'python' ]
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- run: |
echo "Run, Build Application using script"
sudo apt update
sudo apt upgrade
sudo apt install clang-format python3 unzip git qemu-system-x86 qemu-system-gui gdisk dos2unix xorriso
sudo apt install libc6
chmod +x build.sh
./build.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -1,75 +0,0 @@
name: release
on:
workflow_dispatch:
inputs:
test_label:
required: true
type: string
jobs:
x86_64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: install depends
run: sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
- name: install limine
run: |
git clone https://git.synapseos.ru/Aren/limine.git --branch=v5.x-branch-binary --depth=1
cd limine && make && cd ..
- name: build
run: |
dos2unix *.sh
chmod +x build.sh
./build.sh
- name: save
run: |
mkdir -p ${{ github.workspace }}/rel
cp ${{ github.workspace }}/kernel.elf ${{ github.workspace }}/rel/
cp ${{ github.workspace }}/bmosp.hdd ${{ github.workspace }}/rel/
cp ${{ github.workspace }}/bmosp.iso ${{ github.workspace }}/rel/
cp ${{ github.workspace }}/LICENSE ${{ github.workspace }}/rel/
- uses: actions/upload-artifact@v3
with:
name: bmosp.hdd
path: ${{ github.workspace }}/bmosp.hdd
- uses: actions/upload-artifact@v3
with:
name: bmosp.iso
path: ${{ github.workspace }}/bmosp.iso
- uses: actions/upload-artifact@v3
with:
name: kernel.elf
path: ${{ github.workspace }}/kernel.elf
- name: check
run: |
echo ${{ github.workspace }}/rel/
ls -la ${{ github.workspace }}/rel/
- name: release
uses: softprops/action-gh-release@v0.1.15
with:
name: ${{ inputs.test_label }}
tag_name: autobuild
draft: true
files: |
${{ github.workspace }}/rel/kernel.elf
${{ github.workspace }}/rel/bmosp.hdd
${{ github.workspace }}/rel/bmosp.iso
${{ github.workspace }}/rel/LICENSE
body: |
${{ inputs.test_label }}
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
Мы не несем ответственности за нанесенный ущерб.

5
.gitignore vendored
View File

@ -6,12 +6,7 @@ ovmf/
iso_root/
output/
sdk/
_sdk/
*.so
*.o
*.ko
*.elf
*.zip
*.log
*.lck
configs/media/*

42
.vscode/settings.json vendored
View File

@ -1,28 +1,18 @@
{
"C_Cpp.errorSquiggles": "disabled",
"files.eol": "\n",
"files.associations": {
"array": "cpp",
"bitset": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"complex": "cpp",
"string": "cpp",
"limine.h": "c",
"tool.h": "c",
"sys.h": "c",
"arch.h": "c",
"fb.h": "c",
"system.h": "c",
"mod.h": "c",
"modstd.h": "c",
"stdbool.h": "c",
"stdint.h": "c",
"types.h": "c",
"random": "c",
"6x8_slim_font.h": "c",
"log.h": "c",
"mem.h": "c",
"lock.h": "c"
}
"C_Cpp.errorSquiggles": "disabled",
"files.associations": {
"array": "cpp",
"bitset": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"complex": "cpp",
"string": "cpp",
"limine.h": "c",
"tool.h": "c",
"sys.h": "c",
"arch.h": "c",
"fb.h": "c",
"system.h": "c",
"mod.h": "c"
}
}

View File

@ -1,6 +1,6 @@
# Системные вызовы
## alloc(size_t size)
## mem_alloc(size_t size)
Выделение блока памяти размером `size`.
Вовзращает адрес на блок памяти или 0 в случае ошибки.
@ -10,7 +10,7 @@
- `-1 не хватает ОЗУ`;
- `-2 неправильный размер блока`.
## free(uintptr_t mem)
## mem_free(uintptr_t mem)
Освобождение блока памяти `mem`.
Вовзращает 0 в случае успеха или -1 в случае ошибки.
@ -19,7 +19,7 @@
- `-1 блок не найден`.
## alloc_framebuffer()
## sys_alloc_framebuffer()
Выделяет память под буфер кадра для отображения графического интерфейса.
Возвращает указатель на структуру `framebuffer_t` или 0, если произошла ошибка.
@ -28,15 +28,7 @@
- `-1 не удалось выделить память для буфера кадра`.
## log_printf(char *str, ...)
Форматированный вывод строки на экран используя функцию ядра log_printf.
### Будет удалено в ближайших обновлениях
- Для вывода используйте любой графический или псевдографический модуль
## free_framebuffer(framebuffer_t *frame)
## sys_free_framebuffer(framebuffer_t *frame)
Освобождает ранее выделенную память `frame` для буфера кадра. Возвращает 0 в случае успеха или -1, если произошла ошибка.
@ -44,23 +36,23 @@
- `-1 ошибка при освобождении памяти для буфера кадра`.
## exit(int code)
## sys_exit(int code)
Завершает выполнение текущего потока с кодом `code`.
## get_error()
## sys_get_error()
Получает код ошибки последней операции. Возвращает целочисленное значение, представляющее код ошибки.
## get_info()
## sys_get_info()
Получает информацию о текущей системе. Возвращает структуру `sys_info_t` содержащую информацию о системе.
## get_module(char *module_id)
## sys_get_module(uid_t module_id)
Получает информацию о модуле `module_id`. Возвращает структуру `module_info_t` содержащую информацию о модуле.
Получает информацию о модуле `module_id`. Возвращает структуру, содержащую информацию о модуле.
## new_thread(func_t func)
## sys_new_thread(func_t func)
Создает новый поток выполнения для функции `func`. Возвращает идентификатор созданного потока или 0 в случае ошибки.
@ -68,7 +60,7 @@
- `-1 ошибка при создании потока`.
## delete_thread(uid_t thread_id)
## sys_delete_thread(uid_t thread_id)
Удаляет указанный поток выполнения `thread_id`. Возвращает 0 в случае успеха или -1 в случае ошибки.
@ -77,11 +69,11 @@
- `-1 поток не найден`.
<!--
## get_time()
## sys_get_time()
Получает текущее время системы в формате timestamp. Возвращает целое число, представляющее количество секунд с начала эпохи.
## set_alarm(time_t time, func_t func)
## sys_set_alarm(time_t time, func_t func)
Устанавливает сигнал будильника на время time. При наступлении указанного времени будет вызвана функция func.

View File

@ -6,20 +6,16 @@
Автор идеи, главный разработчик
* <aren@synapseos.ru>
* <https://t.me/nera00>
* <https://vk.com/0nera>
* <https://github.com/0nera>
* <https://0nera.ru>
* aren@synapseos.ru
* https://t.me/nera00
* https://vk.com/0nera
* https://github.com/0nera
* https://0nera.ru
## Основные участники
* __Тут могло быть ваше имя__
__Тут могло быть ваше имя__
## Другие участники
### Долганов Илья Владимирович
* <https://vk.com/xkrulex>
* <https://t.me/amakesla>
* <dolganov.19@mail.ru>
__Тут могло быть ваше имя__

View File

@ -1,19 +1,9 @@
# Сборка из исходного кода
## Установка SDK
Перед сборкой рекомендуем установить готовый пакет SDK вместе с libc6
```bash
sudo apt update
sudo apt install unzip
./scripts/get_sdk.sh
```
## Ubuntu 18.04+
```bash
sudo apt install clang-format python3 git qemu-system-x86 qemu-system-gui gdisk dos2unix xorriso libc6 gcc make curl mtools
sudo apt install clang-format python3 git qemu-system-x86 gdisk dos2unix xorriso
git clone https://git.synapseos.ru/Aren/BMOSP.git
cd BMOSP/
chmod +x build.sh
@ -26,23 +16,36 @@ 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 mtools
sudo apt install clang-format python3.7 git qemu-system-x86 gdisk dos2unix xorriso
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 xorriso
git clone https://git.synapseos.ru/Aren/BMOSP.git
cd BMOSP/
chmod +x build.sh
./build.sh
```
## Запуск
## Qemu
Стандартная конфигурация загрузки с HDD под x86_64(AMD64) UEFI
Стандартная конфигурация загрузки с HDD
```bash
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd
```
Стандартная конфигурация загрузки с ISO образа под x86_64(AMD64) UEFI
Стандартная конфигурация загрузки с ISO образа
```bash
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -cdrom bmosp.iso -boot d --no-reboot
@ -58,4 +61,4 @@ chmod +x run.sh
## Предупреждение
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
Мы не несем ответственности за нанесенный ущерб.
Мы не несем ответственности за нанесенный ущерб.

View File

@ -1,13 +0,0 @@
# Приглашаем к сотрудничеству
Мы ищем талантливых специалистов, обладающих опытом разработки на C/C++, включая умение работать с ассемблером для x86_64, а также экспертов в области документирования.
Если у вас есть опыт разработки на C/C++ для архитектуры x86_64, вы можете присоединиться к проекту и внести свой вклад следующими способами:
1. Вы можете помочь улучшить производительность и эффективность существующего кода, а также добавить новые функциональные возможности.
2. Вы можете принять участие в процессе тестирования, находя и исправляя ошибки в коде.
3. Вы можете анализировать и просматривать код, написанный другими участниками, и предлагать способы его улучшения.
Если вы специалист в области документации или готовы написать статьи или обучающие материалы по данному проекту, то ваш вклад может быть следующим:
1. Создание документации: разработайте документацию по архитектуре проекта, опишите его API, создайте руководства для пользователей.
2. Создание обучающих материалов: напишите статьи, снимите видеоуроки, создайте презентации для обучения ваших менее опытных коллег.

14
HISTORY.md Normal file
View File

@ -0,0 +1,14 @@
# История разработки
## 25.10.2023
Создание проекта
## 12.10.2023
Смена вектора и названия проекта МСООС (минимальная студенческая обучающая операционная система) -> БМПОС (базовая модульная платформа операционных систем)
## 21.10.2023
- Выпуск релиза 0.1.231
- Перевод кодовой базы с C++ на язык C

View File

@ -1,18 +1,15 @@
# БМПОС: Базовая Модульная Платформа Операционных Систем
[![CI сборка](https://github.com/0Nera/BMOSP/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/0Nera/BMOSP/actions/workflows/build.yml)
[![CodeQL](https://github.com/0Nera/BMOSP/actions/workflows/codeql.yml/badge.svg?branch=master)](https://github.com/0Nera/BMOSP/actions/workflows/codeql.yml)
[![Github pages сайт](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment/badge.svg?branch=pages)](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment)
---
БМПОС - Базовая Модульная Платформа Операционных Систем для платформы x86_64 (BIOS/UEFI). Это отечественное программное обеспечение, созданное при поддержке Синапс ОС на языке программирования C.
БМПОС не является операционной системой. Это платформа для изучения.
Философия БМПОС - "всё есть модуль".
![Скриншот вывода ядра в эмуляторе Qemu](https://git.synapseos.ru/Aren/BMOSP/raw/branch/pages/assets/0_0.2.0.png)
![Скриншот вывода ядра в эмуляторе Qemu](https://0nera.github.io/BMOSP/assets/0_0.1.367.png)
## Список задач
@ -20,7 +17,7 @@
## Партнеры
- Синапс ОС
- ООО **"НПО ТЕ-ОН"**
## Помощь проекту
@ -28,7 +25,7 @@
### Доработка кодовой базы
Если вы владеете C/C++, ассемблером GAS, то вы можете доработать ядро проекта или написать свой пользовательский модуль.
Если вы владеете C/C++, ассемблерами GAS или FASM, то вы можете доработать ядро проекта или написать свой пользовательский модуль.
Для добавления своего модуля используйте инструкцию `modules/README.md`.
@ -45,11 +42,11 @@
- Номер карты: 2200 7009 4662 4201
- Номер счета: 40817810400099892231
- БИК: 044525974
- Банк-получатель: АО «Т-Банк»
- Банк-получатель: АО «Тинькофф Банк»
## Сборка и запуск
Перенесено в файл `docs/BUILD.md`
Перенесено в файл `BUILD.md`
## Предупреждение

View File

@ -1,16 +0,0 @@
# Безопасность
## Поддерживаемые версии
| Версия | Поддержка |
| ------- | ------------------ |
| 0.1.98x | :white_check_mark: |
| < 0.1.9xx | :x: |
## Сообщение об уязвимости (ошибке)
Если вы нашли уязвимость или ошибку вы можете сообщить нам об этом используя один из предоставленных методов:
- На почту <aren@synapseos.ru>
- Используя раздел Issues
- В телеграм-чате <https://t.me/bmosp>

27
TODO.md
View File

@ -6,17 +6,17 @@
- [x] Менеджер памяти
- [x] Менеджер видеопамяти
- [X] Менеджер потоков
- [X] Загрузчик модулей
- [X] Буфер ввода-вывода
- [ ] Менеджер потоков
- [x] Загрузчик модулей
- [ ] Буферы ввода-вывода
Модули:
- [X] Оболочка ввода-вывода
- [ ] Оболочка ввода-вывода
Драйвера:
- [X] PS/2 (Клавиатура)
- [ ] PS/2 (Клавиатура)
- [ ] SATA (AHCI) (Чтение)
- [ ] EXT2
@ -37,13 +37,13 @@
Примеры:
- [X] Пример модуля
- [X] Пример драйвера
- [ ] Пример драйвера
- [ ] Пример программы-модуля
- [X] Пример модуля ввода-вывода
- [ ] Пример модуля ввода-вывода
Общая работа:
- [X] Ядро
- [ ] Ядро
- [ ] Модули
- [ ] Драйвера
- [ ] Документация
@ -53,13 +53,6 @@
### Второстепенные задачи
Общее:
- [ ] Разделение менеджера памяти
- [ ] Страничная адресация
- [ ] Поддержка ПО в пространстве пользователя
- [ ] Переход на make
Модули:
- [ ] Отладчик
@ -67,14 +60,10 @@
- [ ] Lua
- [ ] SQLite
- [ ] Криптограф
- [ ] Сетевой стек (ARP, IP, TCP, UDP, HTTP)
- [ ] DOOM
- [ ] IRC
Драйвера:
- [ ] PS/2 (Мышь)
- [ ] AMD PCnet
- [ ] SATA (AHCI) (Запись)
- [ ] SIMD (SSE, SSE2, SSE3, SSE4, AVX) - отдельный драйвер для инициализации SIMD инструкций

BIN
boot.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

BIN
boot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -1,26 +1,12 @@
#!/bin/sh
dos2unix *.sh
cd modlib/lib/
dos2unix build.sh
chmod +x build.sh
./build.sh
cd ../..
cd modules/
mkdir -p bin
dos2unix */*.sh
chmod +x */build.sh
for dir in */; do
if [ $dir != "bin/" ]; then
cd $dir
./build.sh
cd ..
fi
done
#cd helloworld/ && chmod +x build.sh && ./build.sh && cd ..
#cd music/ && chmod +x build.sh && ./build.sh && cd ..
cd simd/ && chmod +x build.sh && ./build.sh && cd ..
cd cpubench/ && chmod +x build.sh && ./build.sh && cd ..
cd pci/ && chmod +x build.sh && ./build.sh && cd ..
cd pci_data/ && chmod +x build.sh && ./build.sh && cd ..
cd ..
python3 scripts/pbuild.py
python3 pbuild.py

View File

@ -2,40 +2,31 @@ GRAPHICS=yes
TIMEOUT=5
DEFAULT_ENTRY=0
INTERFACE_BRANDING=git.synapseos.ru/Aren/bmosp
INTERFACE_RESOLUTION=1280x720
BACKGROUND_STYLE=stretched
TERM_WALLPAPER=boot:///mod/boot.jpg
BACKGROUND_PATH=boot:///boot.tga
TERM_WALLPAPER=boot:///boot.jpg
#TERM_FONT=boot:///CYRILL2.F16
#TERM_FONT_SIZE=8x16
:BMOSP (KASLR off)
#RESOLUTION=640x480
#RESOLUTION=1024x768
RESOLUTION=1280x720
PROTOCOL=limine
KASLR=no
KERNEL_PATH=boot:///kernel.elf
#RESOLUTION=640x480
#RESOLUTION=1024x768
RESOLUTION=1280x720
PROTOCOL=limine
KASLR=no
KERNEL_PATH=boot:///kernel.elf
MODULE_PATH=boot:///mod/pci_vendors.txt
MODULE_CMDLINE=[PCI][DATA][VENDORS]
MODULE_PATH=boot:///boot.tga
MODULE_CMDLINE=[BOOTIMG]
MODULE_PATH=boot:///mod/simd.ko
MODULE_CMDLINE=[MOD]simd.ko
MODULE_PATH=boot:///mod/simd.ko
MODULE_CMDLINE=[MOD]simd.ko
MODULE_PATH=boot:///mod/pci_data.ko
MODULE_CMDLINE=[MOD]pci_data.ko
MODULE_PATH=boot:///mod/cpubench.ko
MODULE_CMDLINE=[MOD]cpubench.ko
MODULE_PATH=boot:///mod/pci.ko
MODULE_CMDLINE=[MOD]pci.ko
MODULE_PATH=boot:///mod/pci_data.ko
MODULE_CMDLINE=[MOD]pci_data.ko
MODULE_PATH=boot:///mod/ps2.ko
MODULE_CMDLINE=[MOD]ps2.ko
MODULE_PATH=boot:///mod/cpubench.ko
MODULE_CMDLINE=[MOD]cpubench.ko
MODULE_PATH=boot:///mod/hello.ko
MODULE_CMDLINE=[MOD]hello.ko
MODULE_PATH=boot:///mod/ios.ko
MODULE_CMDLINE=[MOD][IO]ios.ko
MODULE_PATH=boot:///mod/pci.ko
MODULE_CMDLINE=[MOD]pci.ko

View File

@ -9,56 +9,55 @@ ENTRY(_start)
/* разрешения MMU */
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Динамический PHDR для учёта перерасположений */
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Динамический PHDR для учёта перерасположений */
}
SECTIONS
{
/* Мы хотим быть размещены в верхних 2 ГБ адресного пространства, для оптимизации */
/* и потому что это предписывает спецификация Limine. */
/* Любой адрес в этом регионе подойдет, но часто выбирают 0xffffffff80000000, так как это */
/* начало региона. */
. = 0xffffffff80000000;
/* Мы хотим быть размещены в верхних 2 ГБ адресного пространства, для оптимизации */
/* и потому что это предписывает спецификация Limine. */
/* Любой адрес в этом регионе подойдет, но часто выбирают 0xffffffff80000000, так как это */
/* начало региона. */
. = 0xffffffff80000000;
.text : {
*(.text .text.*)
} :text
.text : {
*(.text .text.*)
} :text
/* Переходим на следующую страницу памяти для .rodata */
. += CONSTANT(MAXPAGESIZE);
/* Переходим на следующую страницу памяти для .rodata */
. += CONSTANT(MAXPAGESIZE);
.rodata : {
*(.rodata .rodata.*)
} :rodata
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Переходим на следующую страницу памяти для .data */
. += CONSTANT(MAXPAGESIZE);
/* Переходим на следующую страницу памяти для .data */
. += CONSTANT(MAXPAGESIZE);
.data : {
*(.data .data.*)
} :data
.data : {
*(.data .data.*)
} :data
/* Динамический раздел для перерасположений, как в собственном PHDR, так и внутри раздела data */
.dynamic : {
*(.dynamic)
} :data :dynamic
/* Динамический раздел для перерасположений, как в собственном PHDR, так и внутри раздела data */
.dynamic : {
*(.dynamic)
} :data :dynamic
/* Примечание: .bss должен быть последней вещью, отображаемой в раздел data, иначе много */
/* ненужных нулей будет записано в бинарный файл. */
/* Если вам, например, нужны .init_array и .fini_array, они должны быть размещены */
/* выше этого. */
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
/* Примечание: .bss должен быть последней вещью, отображаемой в раздел data, иначе много */
/* ненужных нулей будет записано в бинарный файл. */
/* Если вам, например, нужны .init_array и .fini_array, они должны быть размещены */
/* выше этого. */
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
/* Игнорируем разделы .note.* и .eh_frame, так как они могут вызывать проблемы на некоторых хостах. */
/DISCARD/ : {
*(.comment)
*(.eh_frame)
*(.note .note.*)
}
/* Игнорируем разделы .note.* и .eh_frame, так как они могут вызывать проблемы на некоторых хостах. */
/DISCARD/ : {
*(.eh_frame)
*(.note .note.*)
}
}

0
scripts/deploy_to_sdc.sh → deploy_to_sdc.sh Normal file → Executable file
View File

View File

@ -1,8 +1,8 @@
// Название шрифта 6x8 Slim
// Автор шрифта Riva
// Название шрифта 6x8 Slim
// Автор шрифта Riva
// Дата и время генерации 06.06.2023 19:38:19
// Сгенерировано matrixFont v1.1.0.52
// Кодовая страница 1251 (ANSI - кириллица)
// Сгенерировано matrixFont v1.1.0.52
// Кодовая страница 1251 (ANSI - кириллица)
// https://gitlab.com/riva-lab/matrixFont
#ifndef FONT_6X8_SLIM_H
@ -21,7 +21,8 @@
#define FONT_6X8_SLIM_CHAR_WIDTH 6
#define FONT_6X8_SLIM_CHAR_HEIGHT 8
#define FONT_6X8_SLIM_FONT_TYPE (FONT_TYPE_MONOSPACED)
#define FONT_6X8_SLIM_ARRAY_LENGTH (FONT_6X8_SLIM_LENGTH * FONT_6X8_SLIM_CHAR_HEIGHT)
#define FONT_6X8_SLIM_ARRAY_LENGTH \
(FONT_6X8_SLIM_LENGTH * FONT_6X8_SLIM_CHAR_HEIGHT)
static const unsigned char font_6x8_slim[FONT_6X8_SLIM_ARRAY_LENGTH] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 32 < >

View File

@ -10,76 +10,16 @@
#ifndef ARCH_H
#define ARCH_H
#include <lock.h>
#include <stdint.h>
#include <sys.h>
#define STACK_SIZE 16 * 1024 // 16 килобайт на стек
typedef struct task {
uint64_t rax, rbx, rcx, rdx;
uint64_t rsi, rdi, rsp, rbp;
uint64_t cr3;
uint64_t cpu_time;
uint64_t cpu_time_expired;
uint64_t id;
char *id_str;
void *stack;
struct task *last;
struct task *next;
} __attribute__((packed)) task_t;
struct frame {
uint64_t rbp;
uint64_t rbx;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t int_number;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*int_entry_t)(struct frame *state);
extern lock_t task_lock;
extern uint64_t task_f_init;
extern task_t *current_task;
void arch_init( );
void task_init( );
void task_after_init( );
void task_switch( );
uint64_t task_new_thread(void (*func)(void *), char *name);
void task_del_current( );
void task_del(uint64_t id);
void cpu_init( );
void pic_init( );
void pit_init( );
void gdt_init( );
void idt_init( );
void idt_set_int(uint8_t vector, int_entry_t handler);
void idt_set_int(uint8_t vector, void *int_handler);
uint64_t arch_get_tick_b( );
uint64_t arch_get_tick_l( );
uint64_t arch_get_tick( );
void com_write_byte(uint8_t byte);
void com_write_bytes(char *c, uint64_t n);
time_t rtc_get_time( );
static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
@ -91,21 +31,4 @@ static inline uint8_t inb(uint16_t port) {
return ret;
}
static inline void outw(uint16_t port, uint16_t val) {
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint16_t inw(uint16_t port) {
uint16_t ret;
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void io_wait( ) {
outb(0x80, 0);
}
#define GET_TICK_BIG arch_get_tick_b( )
#define GET_TICK_lOW arch_get_tick_l( )
#endif // arch.h

View File

@ -10,7 +10,6 @@
#ifndef FB_H
#define FB_H
#include <6x8_slim_font.h>
#include <arch.h>
#include <stdarg.h>
#include <stddef.h>
@ -27,21 +26,22 @@ enum colors {
DARK_GREEN = 0x013220,
};
extern int fb_init_status;
extern uint32_t *fb_addr;
extern uint64_t width;
extern uint64_t height;
#define GET_TICK_BIG arch_get_tick_b( )
#define GET_TICK_lOW arch_get_tick_l( )
#define SCREEN_WIDTH width
#define SCREEN_HEIGHT height
#define SCREEN_BUFFER fb_addr
#define LOG(...) \
fb_printf("[%u]%s() (%s:%d) ", GET_TICK_BIG, __func__, __FILE__, \
__LINE__); \
fb_printf(__VA_ARGS__)
void fb_set_text_color(uint32_t color);
uint32_t fb_get_text_color( );
void fb_init( );
void fb_print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf);
void log_printf(char *str, ...);
void log_printf_at(size_t x, size_t y, char *str, ...);
void fb_print_bits(size_t x, size_t y, uint8_t num);
void fb_printf(char *str, ...);
void fb_printf_at(size_t x, size_t y, char *str, ...);
#endif // fb.h

View File

@ -1,26 +0,0 @@
/**
* io_buf.h
* Заголовок с определениями функций буфера ввода-вывода
*
* Данный заголовочный файл содержит определения которые используются для
* использования буфера ввода-вывода
*
*/
#ifndef IO_BUF_H
#define IO_BUF_H
#include <stdint.h>
typedef struct {
uint8_t *buffer;
uint64_t position;
uint64_t max_size;
} io_buf_t;
io_buf_t *io_buf_create(uint64_t max_size);
void io_buf_destroy(io_buf_t *buffer);
void io_buf_write(io_buf_t *buffer, uint8_t *data, uint64_t length);
uint8_t *io_buf_read(io_buf_t *buffer);
#endif // io_buf.h

View File

@ -14,21 +14,16 @@
typedef struct {
int lock;
const char *func;
int line;
const char* file;
} lock_t;
#define LOCK(lock) \
lock.line = __LINE__; \
lock_acquire(lock);
#define LOCK_INIT \
(lock_t) { \
0, __FILE__, __LINE__ \
#define LOCK_INIT \
(lock_t) { \
0, __FILE__ \
}
int lock_swap(lock_t lock);
void lock_acquire(lock_t lock);
void lock_release(lock_t lock);
int lock_swap(lock_t* lock);
void lock_acquire(lock_t* lock);
void lock_release(lock_t* lock);
#endif // lock.h

View File

@ -1,33 +0,0 @@
/**
* log.h
* Заголовок с функциями отладки
*
* Данный заголовочный файл содержит определения которые используются для работы
* с системным отладчиком
*
*/
#ifndef LOG_H
#define LOG_H
#include <6x8_slim_font.h>
#include <arch.h>
#include <fb.h>
#include <lock.h>
#include <mem.h>
#include <stdint.h>
#include <tool.h>
void log_init( );
void log_init_mem( );
void log_printf(char *str, ...);
#ifndef NO_DEBUG
#define LOG(...) \
log_printf("[%6u]%12s() (%18s:%3u) ", GET_TICK_BIG, __func__, __FILE__, __LINE__); \
log_printf(__VA_ARGS__)
#else
#define LOG(...)
#endif
#endif // log.h

View File

@ -17,7 +17,6 @@
#define HHDM_OFFSET (hhdm_request.response->offset)
void mem_dump_memory( );
void mem_get_stat( );
void mem_init( );
void *mem_alloc(size_t size);
void mem_add_block(void *addr, size_t size);

View File

@ -7,109 +7,35 @@
*
*/
#include <log.h>
#include <stddef.h>
#include <stdint.h>
#include <sys.h>
#ifndef MOD_H
#define MOD_H
#define EI_MAG0 0
#define ELFMAG0 0x7f
#define EI_MAG1 1
#define ELFMAG1 'E'
#define EI_MAG2 2
#define ELFMAG2 'L'
#define EI_MAG3 3
#define ELFMAG3 'F'
#define SHT_SYMTAB 2
typedef uint64_t elf64_addr_t; // Адрес
typedef uint64_t elf64_offset_t; // Смещение
typedef uint64_t elf64_xword_t; // Целочисленное длинное слово без знака
typedef uint64_t elf64_sxword_t; // Целочисленное длинное слово с знаком
typedef uint32_t elf64_word_t; // Целочисленное слово без знака
typedef uint32_t elf64_sword_t; // Целочисленное слово с знаком
typedef uint16_t elf64_half_t; // Среднее целое число без знака
typedef uint8_t elf64_small_t; // Малое целое число без знака
// Максимальное количество модулей 16. Позже перепишем на динамический массив,
// сейчас для прототипа это не так важно
#define MOD_MAX 16
// Структуры соответствующие ELF заголовкам
typedef struct {
elf64_small_t e_ident[16]; // Идентификация ELF
elf64_half_t e_type; // Тип объектного файла
elf64_half_t e_machine; // Тип компьютера
elf64_word_t e_version; // Версия объектного файла
elf64_addr_t e_entry; // Адрес точки входа
elf64_offset_t e_phoff; // Смещение заголовка программы
elf64_offset_t e_shoff; // Смещение заголовка раздела
elf64_word_t e_flags; // Флаги, зависящие от процессора
elf64_half_t e_ehsize; // Размер заголовка ELF
elf64_half_t e_phentsize; // Размер записи заголовка программы
elf64_half_t e_phnum; // Количество записей в заголовке программы
elf64_half_t e_shentsize; // Размер записи в заголовке раздела
elf64_half_t e_shnum; // Количество записей в заголовке раздела
elf64_half_t e_shstrndx; // Строковый табличный индекс названия раздела
unsigned char e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf64_header_t;
typedef struct {
elf64_word_t sh_name; // Название раздела
elf64_word_t sh_type; // Тип раздела
elf64_xword_t sh_flags; // Атрибуты раздела
elf64_addr_t sh_addr; // Виртуальный адрес в памяти
elf64_offset_t sh_offset; // Смещение в файле
elf64_xword_t sh_size; // Размер раздела
elf64_word_t sh_link; // Ссылка на другой раздел
elf64_word_t sh_info; // Дополнительная информация
elf64_xword_t sh_addralign; // Граница выравнивания адреса
elf64_xword_t sh_entsize; // Размер записей, если в разделе есть таблица
} elf64_section_header_t;
typedef struct {
elf64_addr_t r_offset; // Адрес ссылки
elf64_xword_t r_info; // Индекс символа и тип перемещения
} elf64_rel_t;
typedef struct {
elf64_addr_t r_offset; // Адрес ссылки
elf64_xword_t r_info; // Индекс символа и тип перемещения
elf64_sxword_t r_addend; // Постоянная часть выражения
} elf64_rela_t;
typedef struct {
elf64_word_t p_type; // Тип сегмента
elf64_word_t p_flags; // Атрибуты сегмента
elf64_offset_t p_offset; // Смещение в файле
elf64_addr_t p_vaddr; // Виртуальный адрес в памяти
elf64_addr_t p_paddr; // Зарезервирован
elf64_xword_t p_filesz; // Размер сегмента в файле
elf64_xword_t p_memsz; // Размер сегмента в памяти
elf64_xword_t p_align; // Выравнивание сегмента
} elf64_phdr_t;
typedef struct {
elf64_word_t st_name; // Название символа
elf64_small_t st_info; // Тип и атрибуты привязки
elf64_small_t st_other; // Зарезервировано
elf64_half_t st_shndx; // Индекс таблицы разделов
elf64_addr_t st_value; // Значение символа
elf64_xword_t st_size; // Размер объекта (например, общий)
} elf64_sym_t;
typedef struct {
elf64_sxword_t d_tag; // Тип динамического элемента
union {
elf64_xword_t d_val; // Значение динамического элемента
elf64_addr_t d_ptr; // Указатель динамического элемента
} d_un;
} elf64_dyn_t;
void mod_init( );
void mod_after_init( );
void mod_list_show( );
module_info_t *mod_find(char *tag);
module_info_t *mod_list_get(uint64_t *count);
void *elf_entry(void *module_bin);
void *elf_parse(elf64_header_t *head);
#endif // mod.h

View File

@ -30,6 +30,16 @@ typedef struct {
void *addr;
} module_func_t;
typedef struct {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
} module_info_t;
typedef struct {
int reserved;
} func_t;
@ -42,45 +52,27 @@ typedef struct {
} uid_t;
typedef struct {
uint8_t year;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hours;
uint8_t minutes;
uint8_t second;
} time_t;
typedef struct {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
uint8_t irq; // Номер прерывания
void *irq_handler; // Адрес обработчика прерываний
void *(*get_func)(uint64_t id);
void (*after_init)( );
} __attribute__((packed)) module_info_t;
typedef struct {
uint64_t offset;
void (*log_printf)(char *str, ...); // Временная функция
framebuffer_t (*alloc_framebuffer)( );
module_info_t *info;
void (*fb_printf)(char *str, ...); // Временная функция
framebuffer_t *(*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void *(*alloc)(uint64_t size);
void (*free)(void *ptr);
void (*exit)(int code);
int (*get_error)( );
sys_info_t *(*get_info)( );
module_info_t *(*get_module)(char *module_id);
module_info_t *(*mod_list_get)(uint64_t *count);
uint64_t (*new_thread)(void (*func)(void *), char *name);
void (*delete_thread)( );
uint64_t (*new_thread)(uint64_t func);
int (*delete_thread)(uint64_t thread_id);
time_t (*get_time)( );
} __attribute__((packed)) env_t;
} env_t;
env_t *sys_install(env_t *module);
env_t sys_install(env_t module);
#endif // sys.h

View File

@ -13,21 +13,21 @@
#include <stdarg.h>
#include <stdint.h>
#define UNUSED(x) (void)(x)
#define abs(x) ((x) < 0 ? -(x) : (x))
#define assert(check) \
do { \
if (!(check)) { \
LOG("\nassert() ошибка в %s() (%s:%d)\n", __func__, __FILE__, __LINE__); \
for (;;) asm volatile("hlt"); \
} \
#define assert(check) \
do { \
if (!(check)) { \
fb_printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
__FILE__, __LINE__); \
for (;;) asm volatile("hlt"); \
} \
} while (0)
#define ALIGN_UP(NUM, ALIGN) (((NUM) + ALIGN - 1) & ~(ALIGN - 1))
#define ALIGN_DOWN(NUM, ALIGN) ((NUM) & ~(ALIGN - 1))
#define CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
#define CONTAINER_OF(PTR, TYPE, MEMBER) \
((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
@ -42,9 +42,7 @@ static inline void pause( ) {
void tool_memcpy(void *dest, void *src, uint64_t n);
void *tool_memset(void *ptr, uint8_t n, uint64_t size);
uint64_t tool_strlen(const char *str);
void tool_strcpy(char *dest, char *src);
uint64_t tool_starts_with(const char *str, const char *prefix);
uint64_t tool_str_contains(const char *str, const char *substr);
void tool_format(void (*putc)(char c), const char *format_string, va_list args);
#endif // tool.h

View File

@ -1,3 +1,3 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_BUILD 58
#define VERSION_MINOR 1
#define VERSION_BUILD 505

47
kernel/arch/arch.c Normal file
View File

@ -0,0 +1,47 @@
/**
* arch.c
* Инициализация архитектуры
*
* Настройка архитектурнозависимых функций
*
*/
#include <arch.h>
static uint64_t kernel_start_ticks = 0;
static uint64_t kernel_ticks = 0;
uint64_t rdtsc( ) {
unsigned int lo, hi;
asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((uint64_t)hi << 32) | lo;
}
uint64_t arch_get_tick( ) {
if (kernel_start_ticks == 0) {
kernel_start_ticks = rdtsc( );
return 0;
}
kernel_ticks = rdtsc( ) - kernel_start_ticks;
return kernel_ticks;
}
uint64_t arch_get_tick_b( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick / 1000000;
}
uint64_t arch_get_tick_l( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick % 1000000;
}
void arch_init( ) {
gdt_init( );
idt_init( );
cpu_init( );
}

View File

@ -8,22 +8,25 @@
*/
#include <fb.h>
#include <log.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
static bool acpi_msrs_support = false;
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
}
static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
}
static void __attribute__((unused)) msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
static void __attribute__((unused))
msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
}
@ -61,24 +64,6 @@ 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,7 +71,8 @@ static void brandname( ) {
uint32_t manufacturer[4];
char manufacturer_string[13];
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2], &manufacturer[1]);
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2],
&manufacturer[1]);
tool_memcpy(manufacturer_string, manufacturer, 12);
brand_string[48] = 0;
@ -104,17 +90,29 @@ static void brandname( ) {
}
if (manufacturer[0] == 0x68747541) { do_amd( ); }
if (manufacturer[0] == 0x756E6547) { do_intel( ); }
}
void cpu_idle( ) {
if (acpi_msrs_support) {
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
get_cpu_temperature_intel( ));
}
}
void cpu_init( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(1, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) {
asm volatile("finit");
LOG("FPU(x87) поддерживается!\n");
}
if ((edx >> 22) & 1) {
acpi_msrs_support = true;
LOG("Встроенный терморегулятор MSRS для ACPI\n");
LOG("Температура: %d (в QEMU/KVM всегда 0)\n", get_cpu_temperature_intel( ));
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
get_cpu_temperature_intel( ));
}
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
@ -130,7 +128,9 @@ void cpu_init( ) {
"поддерживается!\n");
}
if ((edx >> 10) & 1) { LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n"); }
if ((edx >> 10) & 1) {
LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
}
if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); }
if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); }
@ -138,8 +138,12 @@ void cpu_init( ) {
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); }
if ((edx >> 4) & 1) { LOG("Аппаратный терморегулятор (HTC) поддерживается!\n"); }
if ((edx >> 5) & 1) { LOG("Программный терморегулятор (STC) поддерживается!\n"); }
if ((edx >> 4) & 1) {
LOG("Аппаратный терморегулятор (HTC) поддерживается!\n");
}
if ((edx >> 5) & 1) {
LOG("Программный терморегулятор (STC) поддерживается!\n");
}
brandname( );
}

66
kernel/arch/gdt.c Normal file
View File

@ -0,0 +1,66 @@
/**
* gdt.c
* Функции таблицы глобальных дескрипторов
*
* Настройка таблицы глобальных дескрипторов для управления сегментами памяти
*
*/
#include <arch.h>
#include <fb.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
typedef struct __attribute__((packed)) {
uint16_t limit;
uint16_t base_16;
uint8_t base_middle_16;
uint8_t access;
uint8_t granularity;
uint8_t base_hight_8;
} gdt_entry_t;
typedef struct __attribute__((packed)) {
uint16_t limit;
uint64_t base;
} gdt_reg_t;
gdt_entry_t gdt[11];
gdt_reg_t gdtr;
extern void load_gdt(uint64_t gdtr);
void gdt_load( ) {
gdtr.limit = (sizeof(gdt) - 1);
gdtr.base = (uint64_t)&gdt;
load_gdt((uint64_t)&gdtr);
}
void set_gdt_entry(gdt_entry_t *entry, uint16_t limit, uint64_t base,
uint8_t access, uint8_t granularity) {
entry->limit = limit;
entry->base_16 = base & 0xFFFF;
entry->base_middle_16 = (base >> 16) & 0xFF;
entry->base_hight_8 = (base >> 24) & 0xFF;
entry->access = access;
entry->granularity = granularity;
}
void gdt_init( ) {
set_gdt_entry(&gdt[0], 0, 0, 0, 0);
set_gdt_entry(&gdt[1], 0xFFFF, 0, 0x9A, 0);
set_gdt_entry(&gdt[2], 0xFFFF, 0, 0x92, 0);
set_gdt_entry(&gdt[3], 0xFFFF, 0, 0x9A, 0xCF);
set_gdt_entry(&gdt[4], 0xFFFF, 0, 0x92, 0xCF);
set_gdt_entry(&gdt[5], 0, 0, 0x9A, 0x20);
set_gdt_entry(&gdt[6], 0, 0, 0x92, 0);
set_gdt_entry(&gdt[7], 0, 0, 0xFA, 0x20);
set_gdt_entry(&gdt[8], 0, 0, 0xF2, 0);
set_gdt_entry(&gdt[9], 104, 0, 0x89, 0);
set_gdt_entry(&gdt[10], 0, 0, 0, 0);
gdt_load( );
LOG("GDT инициализирован\n");
}

120
kernel/arch/idt.c Normal file
View File

@ -0,0 +1,120 @@
/**
* idt.c
* Инициализация обработчика прерываний
*
* Настройка обработчика прерываний и системных исключений
*
*/
#include "idt.h"
#include <arch.h>
#include <fb.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
static struct idt_desc IDT[IDT_SIZE] __attribute__((aligned(16)));
struct idt_ptr IDT_POINT = { .limit = sizeof(IDT) - 1, .base = (uint64_t)IDT };
const char *exception_names[] = { "Деление на ноль",
"Отладка",
"NMI",
"Точка останова",
"Переполнение",
"Выход за границы",
"Недопустимая операция",
"Устройство недоступно",
"Двойное исключение",
NO_NAME,
"Недопустимый TSS",
"Сегмент не присутствует",
"Ошибка сегмента стека",
"Общая защитная ошибка",
"Ошибка страницы",
NO_NAME,
"x87 исключение",
"Проверка выравнивания",
"Ошибка машины",
"SIMD исключение",
"Виртуализация",
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
"Безопасность" };
void exception_handler(struct frame state) {
LOG("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n", exception_names[state.int_number]);
uintptr_t rsp = state.rsp;
const uintptr_t stack_bottom = rsp & ~((uintptr_t)4096 - 1);
const uintptr_t stack_top = stack_bottom + 4096;
LOG(" RAX=%x RBX=%x\n"
" RCX=%x RDX=%x\n"
" RSI=%x RDI=%x\n"
" RBP=%x RSP=%x\n"
" R08=%x R09=%x\n"
" R10=%x R11=%x\n"
" R12=%x R13=%x\n"
" R14=%x R15=%x\n"
" RIP=%x RFLAGS=%x\n"
" CS=%x SS=%x\n"
" ERR=%x INT=%u",
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi,
state.rbp, state.rsp, state.r8, state.r9, state.r10, state.r11,
state.r12, state.r13, state.r14, state.r15, state.rip, state.rflags,
state.cs, state.ss, state.err, state.int_number);
LOG("stack_top = %x\n", stack_top);
asm volatile("cli; hlt");
}
static void idt_desc_setup(struct idt_desc *desc, unsigned sel, uintptr_t offs,
unsigned flags) {
desc->offs0 = offs & 0xfffful;
desc->offs1 = (offs >> 16) & 0xfffful;
desc->offs2 = (offs >> 32) & 0xfffffffful;
desc->sel = sel;
desc->flags = flags;
desc->_reserved = 0;
}
static void idt_load( ) {
struct idt_ptr *ptr = &IDT_POINT;
asm volatile("lidt %0" : : "m"(*ptr));
}
void idt_set_int(uint8_t vector, void *int_handler) {
idt_desc_setup(&IDT[vector], KERNEL_CS, (uintptr_t)int_handler,
IDT_INTERRUPT_FLAGS);
idt_load( );
}
void idt_init( ) {
asm volatile("sti");
for (int i = 0; i != IDT_EXCEPTIONS; ++i) {
const uintptr_t handler = (uintptr_t)isr_stubs[i];
idt_desc_setup(&IDT[i], KERNEL_CS, handler, IDT_EXCEPTION_FLAGS);
}
for (int i = IDT_EXCEPTIONS; i != IDT_SIZE; ++i) {
const uintptr_t handler = (uintptr_t)isr_stubs[i];
idt_desc_setup(&IDT[i], KERNEL_CS, handler, IDT_INTERRUPT_FLAGS);
}
idt_desc_setup(&IDT[255], KERNEL_CS, (uintptr_t)isr_stubs[255],
IDT_SPURIOUS_FLAGS);
idt_load( );
LOG("IDT инициализирован\n");
}

72
kernel/arch/idt.h Normal file
View File

@ -0,0 +1,72 @@
#include <stdint.h>
#define NO_NAME "Не задано название"
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
#define IDT_SIZE 256
#define IDT_EXCEPTIONS 32
#define IDT_DPL(x) (((unsigned)(x)&0x3u) << 13)
#define IDT_KERNEL IDT_DPL(0)
#define IDT_TYPE(x) (((unsigned)(x)&0xfu) << 8)
#define IDT_INT_GATE IDT_TYPE(0xeu)
#define IDT_TRP_FATE IDT_TYPE(0xfu)
#define IDT_PRESENT (1u << 15)
#define IDT_EXCEPTION_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
#define IDT_INTERRUPT_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
#define IDT_SPURIOUS_FLAGS (IDT_KERNEL | IDT_INT_GATE | IDT_PRESENT)
struct frame {
uint64_t rbp;
uint64_t rbx;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t int_number;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*exception_handler_t)(void);
typedef void (*interrupt_handler_t)(void);
struct idt_desc {
uint16_t offs0;
uint16_t sel;
uint16_t flags;
uint16_t offs1;
uint32_t offs2;
uint32_t _reserved;
} __attribute__((packed));
struct idt_ptr {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
struct int_desc {
interrupt_handler_t handler;
int busy;
};
typedef void (*int_entry_t)(void);
extern int_entry_t isr_stubs[];

View File

@ -1,10 +1,9 @@
.text
.code64
.global isr_stubs
.extern isr_generic
.extern exception_handler
common:
.align 16
subq $120, %rsp
movq %rbp, 0(%rsp)
movq %rbx, 8(%rsp)
@ -23,7 +22,7 @@ common:
movq %rdi, 112(%rsp)
cld
movq %rsp, %rdi
call isr_generic
call exception_handler
movq 0(%rsp), %rbp
movq 8(%rsp), %rbx
movq 16(%rsp), %r15
@ -41,6 +40,7 @@ common:
movq 112(%rsp), %rdi
addq $136, %rsp
iretq
.align 16
entry0:
pushq $0
pushq $0

15
kernel/arch/load_gdt.s Normal file
View File

@ -0,0 +1,15 @@
.global load_gdt
load_gdt:
cli
lgdt (%rdi)
movw $0x30, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
pop %rdi
mov $0x28, %rax
push %rax
push %rdi
retfq

View File

@ -7,19 +7,26 @@
*/
#include <arch.h>
#include <log.h>
#include <fb.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
static uint64_t count = 0;
static void isr_generic( ) {
LOG("\nТик! %u", count++);
}
void pit_set_interval(int hz) {
int divisor = 1193180 / hz; // Вычисляем делитель
outb(0x43, 0x34); // Устанавливаем байт команды 0x34
outb(0x43, 0x36); // Устанавливаем байт команды 0x36
outb(0x40, divisor & 0xFF); // Устанавливаем младший байт делителя
outb(0x40, divisor >> 8); // Устанавливаем старший байт делителя
outb(0x40, divisor >> 8); // Устанавливаем старший байт делителя
}
void pit_init( ) {
LOG("PIT установлен\n");
pit_set_interval(1);
idt_set_int(32, isr_generic);
pit_set_interval(100);
asm volatile("sti");
}

View File

@ -1,116 +0,0 @@
/**
* arch.c
* Инициализация архитектуры
*
* Настройка архитектурнозависимых функций
*
*/
#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);
void paging_init( );
uint64_t rdtsc( ) {
unsigned int lo, hi;
asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((uint64_t)hi << 32) | lo;
}
uint64_t arch_get_tick( ) {
if (kernel_start_ticks == 0) {
kernel_start_ticks = rdtsc( );
return 0;
}
kernel_ticks = rdtsc( ) - kernel_start_ticks;
return kernel_ticks;
}
uint64_t arch_get_tick_b( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick / 1000000;
}
uint64_t arch_get_tick_l( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick % 1000000;
}
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( );
paging_init( );
}

View File

@ -1,23 +0,0 @@
/**
* com.c
* последовательный порт
*
* Функционал получения и записи информации в последовательный порт
*
*/
#include <arch.h>
static inline int com_is_transmit_empty(uint16_t com) {
return inb(com + 5) & 0x20;
}
void com_write_byte(uint8_t byte) {
while (!com_is_transmit_empty(0x3F8)) {}
outb(0x3F8, byte);
}
void com_write_bytes(char *c, uint64_t n) {
for (uint64_t i = 0; i < n; i++) { com_write_byte(c[i]); }
}

View File

@ -1,126 +0,0 @@
/**
* idt.c
* Инициализация обработчика прерываний
*
* Настройка обработчика прерываний и системных исключений
*
*/
#include "idt.h"
#include <arch.h>
#include <fb.h>
#include <log.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
extern task_t *current_task;
struct stack_frame {
struct stack_frame *rbp;
uint64_t rip;
} __attribute__((packed));
typedef struct stack_frame stack_frame_t;
static inline void idt_load( ) {
asm volatile("lidt %0" : : "m"(idtr));
}
static void encode_idt_entry(uint8_t vector, void *handler, uint8_t flags) {
uint64_t ptr = (uint64_t)handler;
idt[vector].offset_16 = (uint16_t)ptr;
idt[vector].selector = 0x28;
idt[vector].ist = 0;
idt[vector].flags = flags;
idt[vector].offset_middle_16 = (uint16_t)(ptr >> 16);
idt[vector].offset_high_32 = (uint32_t)(ptr >> 32);
idt[vector].reserved = 0;
}
static void exception_handler(struct frame state) {
LOG("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n", exception_names[state.int_number]);
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
LOG("\tRAX=%x RBX=%x\n"
"\tRCX=%x RDX=%x\n"
"\tRSI=%x RDI=%x\n"
"\tRBP=%x RSP=%x\n"
"\tR08=%x R09=%x\n"
"\tR10=%x R11=%x\n"
"\tR12=%x R13=%x\n"
"\tR14=%x R15=%x\n"
"\tRIP=%x RFLAGS=%x\n"
"\tCS=%x SS=%x\n"
"\tERR=%x INT=%u\n",
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi, state.rbp, state.rsp, state.r8, state.r9,
state.r10, state.r11, state.r12, state.r13, state.r14, state.r15, state.rip, state.rflags, state.cs, state.ss,
state.err, state.int_number);
LOG("\tCR3=%x\n", cr3);
mem_dump_memory( );
LOG("Поток вызвавший исключение: %u, [%s]\n", current_task->id, current_task->id_str);
task_t *t = current_task->next;
while (t && t != current_task) {
LOG("\tID: %u, [%s]\n", t->id, t->id_str);
t = t->next;
}
stack_frame_t *stk;
stk = (stack_frame_t *)state.rbp;
LOG("Трассировка стека:\n");
for (uint64_t i = 0; stk && i < 4; i++) {
LOG(" 0x%x\n", stk->rip);
stk = stk->rbp;
}
asm volatile("cli");
asm volatile("hlt");
}
void isr_generic(struct frame state) {
if (state.int_number > 255) { return; }
// if (state.int_number != 32) { LOG("Обработка прерывания %u\n", state.int_number); }
if (state.int_number < 32) {
exception_handler(state);
} else {
if (isr[state.int_number]) { isr[state.int_number](&state); }
if (state.int_number >= 39) { outb(0xA0, 0x20); }
outb(0x20, 0x20);
}
}
void idt_init( ) {
asm volatile("cli");
idtr = (idt_ptr_t){ .limit = sizeof(idt) - 1, .base = (uint64_t)idt };
tool_memset(isr, 0, 256 * sizeof(int_entry_t));
for (uint64_t i = 0; i < 256; i++) {
if (i < 32) {
encode_idt_entry(i, isr_stubs[i], 0x8E);
isr[i] = (void *)exception_handler;
} else {
encode_idt_entry(i, isr_stubs[i], 0x8F);
isr[i] = (void *)isr_generic;
}
}
idt_load( );
LOG("IDT инициализирован\n");
}
void idt_set_int(uint8_t vector, int_entry_t handler) {
isr[vector] = handler;
idt_load( );
}

View File

@ -1,61 +0,0 @@
#include <arch.h>
#include <stdint.h>
#define NO_NAME "Не задано название"
#define KERNEL_CODE_SEG 0x08 // Сегмент кода
#define KERNEL_DATA_SEG 0x10 // Сегмент данных
#define IDT_SIZE 256 // Количество обработчиков прерываний
#define IDT_EXCEPTIONS 32
typedef struct __attribute__((packed)) {
uint16_t limit;
uint64_t base;
} idt_ptr_t;
typedef struct __attribute__((packed)) {
uint16_t offset_16;
uint16_t selector;
uint8_t ist;
uint8_t flags;
uint16_t offset_middle_16;
uint32_t offset_high_32;
uint32_t reserved;
} idt_gate_t;
static idt_gate_t idt[256];
int_entry_t isr[256];
extern void *isr_stubs[];
static idt_ptr_t idtr;
const char *exception_names[] = { "Деление на ноль",
"Отладка",
"NMI",
"Точка останова",
"Переполнение",
"Выход за границы",
"Недопустимая операция",
"Устройство недоступно",
"Двойное исключение",
NO_NAME,
"Недопустимый TSS",
"Сегмент не присутствует",
"Ошибка сегмента стека",
"Общая защитная ошибка",
"Ошибка страницы",
NO_NAME,
"x87 исключение",
"Проверка выравнивания",
"Ошибка машины",
"SIMD исключение",
"Виртуализация",
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
NO_NAME,
"Безопасность" };

View File

@ -1,15 +0,0 @@
.global load_gdt
load_gdt:
cli
lgdt (%rdi) # Загружаем GDT
movw $0x30, %ax # Обновляем GDT
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
pop %rdi
mov $0x28, %rax
push %rax
push %rdi
retfq

View File

@ -1,58 +0,0 @@
/**
* paging.c
* Страничная адресация
*
* Функционал для работы со страницами памяти
*
*/
#include <arch.h>
#include <log.h>
typedef struct {
uint64_t present : 1;
uint64_t rw : 1;
uint64_t user : 1;
uint64_t pwt : 1;
uint64_t pcd : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
uint64_t pat : 1;
uint64_t global : 1;
uint64_t ignored : 3;
uint64_t addr : 40;
uint64_t reserved : 11;
uint64_t no_execute : 1;
} page_table_entry_t;
// Получение адреса CR3
static inline uint64_t get_cr3( ) {
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
// Вывод флагов
void print_flags(page_table_entry_t entry) {
LOG("\tФлаги: [%c%c%c%c%c%c%c]\n", entry.present ? 'P' : '-', entry.rw ? 'W' : 'R', entry.user ? 'U' : '-',
entry.pwt ? 'T' : '-', entry.pcd ? 'D' : '-', entry.accessed ? 'A' : '-', entry.no_execute ? 'X' : 'E');
}
// Вывод структуры таблицы страниц, начиная с CR3
void print_page_structure(uint64_t cr3) {
page_table_entry_t* pml4 = (page_table_entry_t*)(cr3 & ~0xFFF); // Получаем адрес PML4
LOG("PML4 Address: 0x%x\n", pml4);
for (uint64_t i = 0; i < 512; i++) {
if (pml4[i].present) {
LOG("PML4[%d] - present\n", i);
print_flags(pml4[i]);
LOG("Адрес: 0x%x\n", pml4[i].addr);
}
}
}
void paging_init( ) {
LOG("Paging...\n");
print_page_structure(get_cr3( ));
}

View File

@ -1,28 +0,0 @@
/**
* pic.c
* Программируемый контроллер прерываний
*
* Настройка PIC (Программируемый контроллер прерываний)
*
*/
#include <arch.h>
#include <log.h>
void pic_init( ) {
outb(0x20, 0x11);
outb(0xA0, 0x11);
io_wait( );
outb(0x21, 0x20);
outb(0xA1, 0x28);
io_wait( );
outb(0x21, 0x04);
outb(0xA1, 0x02);
io_wait( );
outb(0x21, 0x01);
outb(0xA1, 0x01);
io_wait( );
outb(0x21, 0x00);
outb(0xA1, 0x00);
LOG("Программируемый контроллер прерываний инициализирован\n");
}

View File

@ -1,82 +0,0 @@
/**
* rtc.c
* Часы реального времени
*
* Функции даты и времени с точностью до секунды
*
*/
#include <lock.h>
#include <log.h>
#include <stdint.h>
#include <sys.h>
#include <tool.h>
#define CMOS_ADDR_PORT 0x70
#define CMOS_DATA_PORT 0x71
static int century_register = 0;
static uint8_t century = 20;
static inline uint8_t read_cmos(uint8_t addr) {
outb(CMOS_ADDR_PORT, addr);
return inb(CMOS_DATA_PORT);
}
static inline int get_update_in_progress_flag( ) {
outb(CMOS_ADDR_PORT, 0x0A);
return (inb(CMOS_DATA_PORT) & 0x80);
}
time_t rtc_get_time( ) {
uint8_t last_second, last_minute, last_hour, last_day, last_month, last_year;
time_t rtc_time;
while (get_update_in_progress_flag( ))
;
rtc_time.second = read_cmos(0x00);
rtc_time.minutes = read_cmos(0x02);
rtc_time.hours = read_cmos(0x04);
rtc_time.day = read_cmos(0x07);
rtc_time.month = read_cmos(0x08);
rtc_time.year = read_cmos(0x09);
if (century_register != 0) { rtc_time.year += century * 100; }
do {
last_second = rtc_time.second;
last_minute = rtc_time.minutes;
last_hour = rtc_time.hours;
last_day = rtc_time.day;
last_month = rtc_time.month;
last_year = rtc_time.year;
while (get_update_in_progress_flag( ))
;
rtc_time.second = read_cmos(0x00);
rtc_time.minutes = read_cmos(0x02);
rtc_time.hours = read_cmos(0x04);
rtc_time.day = read_cmos(0x07);
rtc_time.month = read_cmos(0x08);
rtc_time.year = read_cmos(0x09);
if (century_register != 0) { rtc_time.year += century * 100; }
} while ((last_second != rtc_time.second) || (last_minute != rtc_time.minutes) || (last_hour != rtc_time.hours) ||
(last_day != rtc_time.day) || (last_month != rtc_time.month) || (last_year != rtc_time.year));
uint8_t reg_b = read_cmos(0x0B);
// Преобразуем BCD значения в бинарные, если необходимо
if (!(reg_b & 0x04)) {
rtc_time.second = (rtc_time.second & 0x0F) + ((rtc_time.second / 16) * 10);
rtc_time.minutes = (rtc_time.minutes & 0x0F) + ((rtc_time.minutes / 16) * 10);
rtc_time.hours = ((rtc_time.hours & 0x0F) + (((rtc_time.hours & 0x70) / 16) * 10)) | (rtc_time.hours & 0x80);
rtc_time.day = (rtc_time.day & 0x0F) + ((rtc_time.day / 16) * 10);
rtc_time.month = (rtc_time.month & 0x0F) + ((rtc_time.month / 16) * 10);
rtc_time.year = (rtc_time.year & 0x0F) + ((rtc_time.year / 16) * 10);
}
return rtc_time;
}

View File

@ -1,171 +0,0 @@
/**
* task.c
* Управление потоками
*
* Данный файл содержит функции для создания и удаления потоков.
*
*/
#include <arch.h>
#include <fb.h>
#include <log.h>
#include <mem.h>
static volatile uint64_t next_thread_id = 0;
static task_t *last_task = NULL;
static task_t *kernel_task = NULL;
task_t *current_task = NULL;
uint32_t *test_buf = NULL;
extern uint64_t full_init;
uint64_t task_f_init = 0;
lock_t task_lock;
void task_switch_asm(task_t *, task_t *);
void task_switch( ) {
asm volatile("cli");
task_t *next = current_task->next;
task_t *last = current_task;
if (current_task->cpu_time_expired) {
current_task->cpu_time_expired--;
outb(0x20, 0x20);
task_switch_asm(current_task, current_task);
return;
}
current_task->cpu_time_expired = current_task->cpu_time;
current_task = next;
// LOG("Смена потоков %u->%u\n", last->id, next->id);
outb(0x20, 0x20);
task_switch_asm(last, next);
}
uint64_t task_new_thread(void (*func)(void *), char *name) {
LOG("Выделение потока\n");
uint64_t cr3;
uint64_t *stack = mem_alloc(STACK_SIZE);
task_t *new_task = mem_alloc(sizeof(task_t));
asm volatile("mov %%cr3, %0" : "=r"(cr3));
tool_memset(stack, 0, STACK_SIZE);
tool_memset(new_task, 0, sizeof(task_t));
new_task->stack = stack;
uint64_t stack_top = STACK_SIZE;
stack[--stack_top] = (uint64_t)stack;
stack[--stack_top] = (uint64_t)func;
stack[--stack_top] = (uint64_t)0;
new_task->rsp = (uint64_t)new_task->stack + sizeof(uint64_t) * stack_top;
new_task->cpu_time = 500;
new_task->cpu_time_expired = new_task->cpu_time;
new_task->id = next_thread_id++;
new_task->id_str = name;
new_task->cr3 = cr3;
new_task->last = current_task;
new_task->next = current_task->next;
current_task->next->last = new_task;
current_task->next = new_task;
LOG("Создан новый поток с ID: %u\n", new_task->id);
if (full_init == 0) { current_task = new_task; }
return new_task->id;
}
void task_del(uint64_t id) {
task_t *task = current_task;
// Поиск задачи по ID
while (task->id != id) {
task = task->next;
// Если вернулись к начальной задаче, значит задачи с данным ID не существует
if (task == current_task) {
LOG("Задача с ID %u не существует\n", id);
return;
}
}
LOG("Удаление потока ID: %u, %s\n", current_task->id, current_task->id_str);
task_t *prev = task->last;
task_t *next = task->next;
prev->next = next;
next->last = prev;
mem_free(task->stack);
mem_free(task);
if (task == current_task) {
current_task = next;
if (full_init) { task_switch( ); }
}
}
void task_del_current( ) {
LOG("Удаление потока ID: %u, %s\n", current_task->id, current_task->id_str);
task_t *prev = current_task->last;
task_t *next = current_task->next;
prev->next = next;
next->last = prev;
mem_free(current_task->stack);
mem_free(current_task);
current_task = next;
if (full_init) { task_switch( ); }
}
void task_after_init( ) {
if (full_init) {
current_task = kernel_task;
kernel_task->id_str = "[KERNEL]";
}
}
void task_init( ) {
asm volatile("cli");
idt_set_int(32, task_switch);
uint64_t rsp;
uint64_t cr3;
LOG("Создание потока ядра\n");
asm volatile("mov %%rsp, %0" : "=r"(rsp));
asm volatile("mov %%cr3, %0" : "=r"(cr3));
LOG("Настройка потока ядра\n");
// mem_dump_memory( );
task_t *new_task = mem_alloc(sizeof(task_t));
LOG("%x\n", new_task);
kernel_task = new_task;
tool_memset(kernel_task, 0, sizeof(task_t));
kernel_task->id = next_thread_id++;
kernel_task->id_str = "kernel_early";
kernel_task->rsp = rsp;
kernel_task->cr3 = cr3;
kernel_task->cpu_time = 100;
kernel_task->cpu_time_expired = kernel_task->cpu_time;
current_task = kernel_task;
current_task->last = current_task;
current_task->next = current_task;
last_task = kernel_task;
LOG("Потоки инициализированы\n");
}

View File

@ -1,27 +0,0 @@
.global task_switch_asm
task_switch_asm:
pushfq
movq %rax, (%rdi)
movq %rbx, 8(%rdi)
movq %rcx, 16(%rdi)
movq %rdx, 24(%rdi)
movq %rsi, 32(%rdi)
movq %rdi, 40(%rdi)
movq %rsp, 48(%rdi)
movq %rbp, 56(%rdi)
movq %cr3, %rax
movq %rax, 64(%rdi)
movq 64(%rsi), %rax
movq %rax, %cr3
movq 56(%rsi), %rbp
movq 48(%rsi), %rsp
movq 40(%rsi), %rdi
movq 24(%rsi), %rdx
movq 16(%rsi), %rcx
movq 8(%rsi), %rbx
movq (%rsi), %rax
movq 32(%rsi), %rsi
popfq
sti
retq

View File

@ -1,116 +0,0 @@
/**
* elf.c
* Функции работы с ELF64
*
* Инструменты для парсинга и анализа ELF файлов
*
*/
#include <mod.h>
#include <stdint.h>
elf64_header_t *elf64_get_header(void *data) {
return (elf64_header_t *)(data);
}
static inline elf64_section_header_t *elf64_sheader(elf64_header_t *hdr) {
return (elf64_section_header_t *)((elf64_addr_t)hdr + hdr->e_shoff);
}
static inline elf64_section_header_t *elf64_section(elf64_header_t *hdr, elf64_offset_t idx) {
return &elf64_sheader(hdr)[idx];
}
static inline char *elf64_str_table(elf64_header_t *hdr) {
if (hdr->e_shstrndx == 0x0) return NULL;
return (char *)hdr + elf64_section(hdr, hdr->e_shstrndx)->sh_offset;
}
static inline char *elf64_lookup_string(elf64_header_t *hdr, elf64_offset_t offset) {
char *strtab = elf64_str_table(hdr);
if (strtab == NULL) return NULL;
return strtab + offset;
}
static elf64_sym_t *elf64_get_symval(elf64_header_t *hdr, elf64_offset_t table, elf64_offset_t idx) {
if (table == 0 || idx == 0) return 0;
elf64_section_header_t *symtab = elf64_section(hdr, table);
uint32_t symtab_entries = symtab->sh_size / symtab->sh_entsize;
if (idx >= symtab_entries) {
LOG("Индекс символа вне допустимых пределов (%u:%u).\n", table, idx);
return NULL;
}
uintptr_t symaddr = (uint64_t)hdr + symtab->sh_offset;
return (elf64_sym_t *)&((elf64_sym_t *)symaddr)[idx];
}
unsigned long elf64_hash(unsigned char *name) {
unsigned long h = 0, g;
// Вычисление хэша
while (*name) {
h = (h << 4) + *name++;
// Проверка на overflow
if (g = h & 0xf0000000) h ^= g >> 24;
// Ограничение хэша
h &= 0xffffffff;
}
return h;
}
// Получение адреса точки входа
void *elf_entry(void *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, тип = %u\n", (uint64_t)elf_header->e_entry, elf_header->e_type);
if (elf_header->e_type != 2) {
LOG("\t\tОшибка! Модуль неправильно собран!\n");
for (;;) { asm volatile("pause"); }
}
elf_parse((elf64_header_t *)module_bin);
// Возвращаем указатель на точку входа
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
}
void *elf_parse(elf64_header_t *head) {
elf64_section_header_t *symtab = NULL;
if (head->e_ident[0] != ELFMAG0 || head->e_ident[1] != ELFMAG1 || head->e_ident[2] != ELFMAG2 ||
head->e_ident[3] != ELFMAG3) {
LOG("Ошибка: Неправильный формат!\n");
return -1;
}
LOG("Точка входа: 0x%x\n", head->e_entry);
elf64_section_header_t *symtab_section = NULL;
char *string_table = NULL;
for (int i = 0; i < head->e_shnum; i++) {
elf64_section_header_t *shdr = elf64_section(head, i);
if (shdr->sh_type == SHT_SYMTAB) {
symtab_section = shdr;
elf64_section_header_t *strtab_section = elf64_section(head, shdr->sh_link);
string_table = (char *)head + strtab_section->sh_offset;
break;
}
}
if (symtab_section && string_table) {
LOG("\nТаблица символов:\n");
LOG("%s %s %s %s\n", "Индекс", "Значение", "Размер", "Наименование");
int num_symbols = symtab_section->sh_size / symtab_section->sh_entsize;
for (int i = 0; i < num_symbols; i++) {
elf64_sym_t *sym = elf64_get_symval(head, symtab_section - elf64_sheader(head), i);
if (sym) { LOG("%6u %8x %6x %s\n", i, sym->st_value, sym->st_size, string_table + sym->st_name); }
}
} else {
LOG("Таблица символов не найдена!\n");
}
return (void *)0;
}

View File

@ -10,20 +10,20 @@
#include <6x8_slim_font.h>
#include <fb.h>
#include <limine.h>
#include <log.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <tool.h>
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0, .response = (struct limine_framebuffer_response *)0
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0,
.response = (struct limine_framebuffer_response *)0
};
static struct limine_framebuffer_response *framebuffer_response;
static struct limine_framebuffer *boot_framebuffer;
int fb_init_status = 0;
uint32_t *fb_addr;
uint32_t text_color = GREEN;
uint32_t background = DARK_GREEN;
@ -31,18 +31,19 @@ uint64_t width;
uint64_t height;
uint64_t pitch;
uint16_t bpp;
uint64_t pos_x = 0;
uint64_t pos_y = 0;
uint64_t pos_x = 4;
uint64_t pos_y = 4;
void fb_set_text_color(uint32_t color) {
text_color = color;
}
// Настройка прослойки графики ядра
void fb_init( ) {
framebuffer_response = framebuffer_request.response;
if (framebuffer_response == NULL) { return; }
if (framebuffer_response->framebuffer_count < 1) { return; }
fb_init_status = framebuffer_response->framebuffer_count;
if (framebuffer_response == NULL) { asm volatile("hlt"); }
boot_framebuffer = framebuffer_response->framebuffers[0];
fb_addr = (uint32_t *)boot_framebuffer->address;
@ -57,18 +58,24 @@ void fb_init( ) {
if (framebuffer_response->framebuffer_count == 1) { return; }
LOG("Инициализация дополнительных: %u мониторов\n", framebuffer_response->framebuffer_count);
LOG("Инициализация дополнительных: %u мониторов\n",
framebuffer_response->framebuffer_count);
for (uint64_t i = 1; i < framebuffer_response->framebuffer_count; i++) {
struct limine_framebuffer *framebuffer = framebuffer_response->framebuffers[i];
struct limine_framebuffer *framebuffer =
framebuffer_response->framebuffers[i];
uint32_t *framebuffer_addr = (uint32_t *)framebuffer->address;
LOG("[%u]->0x%x %ux%u\n", i, framebuffer->address, framebuffer->width, framebuffer->height);
for (uint64_t ij = 0; ij < width * height; ij++) { framebuffer_addr[ij] = background; }
LOG("[%u]->0x%x %ux%u\n", i, framebuffer->address, framebuffer->width,
framebuffer->height);
for (uint64_t ij = 0; ij < width * height; ij++) {
framebuffer_addr[ij] = background;
}
}
}
// Отрисовка буффера по координатам (полезно для картинок)
void fb_print_buf(uint64_t x, uint64_t y, uint64_t h, uint64_t w, uint32_t *buf) {
void fb_print_buf(uint64_t x, uint64_t y, uint64_t h, uint64_t w,
uint32_t *buf) {
for (uint64_t j = 0; j < h; j++) {
for (uint64_t i = 0; i < w; i++) {
uint64_t where = (i + x) + (j + y) * width;
@ -77,20 +84,92 @@ void fb_print_buf(uint64_t x, uint64_t y, uint64_t h, uint64_t w, uint32_t *buf)
}
}
void fb_print_bits(size_t x, size_t y, uint8_t num) {
static inline void print_bits(size_t x, size_t y, uint8_t num) {
for (size_t i = 0; i <= 7; i++) {
if ((num >> i) & 1) { SCREEN_BUFFER[x + i + y * SCREEN_WIDTH] = text_color; }
if ((num >> i) & 1) {
SCREEN_BUFFER[x + i + y * SCREEN_WIDTH] = text_color;
}
}
}
// Получение кода символа в таблице
static inline uint32_t analyze(char glyth) {
return ((uint8_t)glyth - 32) * 8;
}
// Вывод символа по координатам
static void print_char(int x, int y, char glyth) {
for (uint64_t i = 0; i < FONT_6X8_SLIM_CHAR_HEIGHT; i++) {
print_bits(x, y + i, font_6x8_slim[analyze(glyth) + i]);
}
}
void scroll_fb( ) {
size_t last_line_index = (SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH;
size_t last_line_index =
(SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH;
for (uint64_t y = 0; y < SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT); y++) {
for (uint64_t x = 0; x < SCREEN_WIDTH; x++) {
SCREEN_BUFFER[x + y * SCREEN_WIDTH] = SCREEN_BUFFER[x + (y + (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH];
SCREEN_BUFFER[x + y * SCREEN_WIDTH] =
SCREEN_BUFFER[x +
(y + (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH];
}
}
for (uint64_t i = last_line_index; i < SCREEN_HEIGHT * SCREEN_WIDTH; i++) { SCREEN_BUFFER[i] = background; }
for (uint64_t i = last_line_index; i < SCREEN_HEIGHT * SCREEN_WIDTH; i++) {
SCREEN_BUFFER[i] = background;
}
}
// Вывод одного символа
static void fb_putchar(char c) {
if (c == '\t') {
pos_x += FONT_6X8_SLIM_CHAR_WIDTH * 4;
} else if (c == '\n') {
// Новая строка
pos_x = 4;
pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
} else {
if (pos_x >= SCREEN_WIDTH) {
pos_x = 4;
pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
}
if (pos_y >= SCREEN_HEIGHT - FONT_6X8_SLIM_CHAR_HEIGHT) {
scroll_fb( );
pos_y -= FONT_6X8_SLIM_CHAR_HEIGHT;
}
print_char(pos_x, pos_y, c);
pos_x += FONT_6X8_SLIM_CHAR_WIDTH;
}
}
// Вывод текстового сообщения
void fb_printf(char *str, ...) {
va_list args;
va_start(args, str);
tool_format(&fb_putchar, str, args);
va_end(args);
}
// Вывод текстового сообщения по координатам
void fb_printf_at(uint64_t x, uint64_t y, char *str, ...) {
va_list args;
va_start(args, str);
// Сохраняем текущие значения pos_x и pos_y
uint64_t prev_x = pos_x;
uint64_t prev_y = pos_y;
// Устанавливаем новые значения координат вывода
pos_x = x;
pos_y = y;
// Выводим строку
tool_format(&fb_putchar, str, args);
// Восстанавливаем предыдущие значения pos_x и pos_y
pos_x = prev_x;
pos_y = prev_y;
va_end(args);
}

View File

@ -1,47 +0,0 @@
/**
* io_buf.c
* Функции буфера ввода-вывода
*
* Функционал буфера ввода-вывода
*
*/
#include <io_buf.h>
#include <log.h>
#include <mem.h>
#include <stdint.h>
#include <tool.h>
io_buf_t *io_buf_create(uint64_t max_size) {
io_buf_t *buffer = mem_alloc(sizeof(io_buf_t));
buffer->buffer = mem_alloc(max_size * sizeof(uint8_t));
buffer->position = 0;
buffer->max_size = max_size;
return buffer;
}
void io_buf_destroy(io_buf_t *buffer) {
mem_free(buffer->buffer);
mem_free(buffer);
}
void io_buf_write(io_buf_t *buffer, uint8_t *data, uint64_t length) {
if (buffer->position + length > buffer->max_size) {
LOG("Переполнение буффера\n");
return;
}
tool_memcpy(buffer->buffer + buffer->position, data, length);
buffer->position += length;
}
uint8_t *io_buf_read(io_buf_t *buffer) {
uint8_t *data = mem_alloc((buffer->position + 1) * sizeof(uint8_t));
tool_memcpy(data, buffer->buffer, buffer->position);
data[buffer->position] = '\0';
buffer->position = 0;
tool_memset(buffer->buffer, 0, buffer->max_size);
return data;
}

View File

@ -8,36 +8,31 @@
#include <fb.h>
#include <lock.h>
#include <log.h>
#include <stdint.h>
#include <tool.h>
// Если не заблокировано - блокируем
int lock_swap(lock_t lock) {
if (lock.lock) { return 0; }
lock.lock = 1;
return 1;
int lock_swap(lock_t *lock) {
return __sync_bool_compare_and_swap(&lock->lock, 0, 1);
}
// Запрос блокировки ресурса
void lock_acquire(lock_t lock) {
void lock_acquire(lock_t *lock) {
uint64_t count = 0;
for (;;) {
if (lock_swap(lock)) { break; }
count++;
if (count > 10000) {
LOG("%s:%u блокировка зависла", lock.func, lock.line);
if (count > 1000000) {
LOG("%s блокировка зависла", lock->file);
assert(0);
}
asm volatile("pause");
if (task_f_init) { task_switch( ); }
}
}
// Запрос разблокировки ресурса
void lock_release(lock_t lock) {
if (lock.lock) { lock.lock = 0; }
void lock_release(lock_t *lock) {
__sync_bool_compare_and_swap(&lock->lock, 1, 0);
}

View File

@ -1,136 +0,0 @@
/**
* log.c
* Функции отладки
*
* Функционал отладки
*
*/
#include <arch.h>
#include <fb.h>
#include <lock.h>
#include <log.h>
#include <mem.h>
#include <stdint.h>
#include <tool.h>
static char start_buffer[1024];
static char *log_buffer;
static uint64_t fb_pos_x = 4;
static uint64_t fb_pos_y = 0;
static uint64_t buf_pos = 0;
static uint64_t buf_max = 1024;
static lock_t log_lock = LOCK_INIT;
#define FONT_WIDTH 6 + 1
#define FONT_HEIGHT 8 + 1
void redraw_screen( );
// Получение кода символа в таблице
static inline uint32_t analyze(char glyth) {
return ((uint8_t)glyth - 32) * 8;
}
// Вывод символа по координатам
static void print_char(uint64_t x, uint64_t y, char glyth) {
for (uint64_t i = 0; i < FONT_6X8_SLIM_CHAR_HEIGHT; i++) {
fb_print_bits(x, y + i, font_6x8_slim[analyze(glyth) + i]);
}
}
void log_dump_buffer( ) {
for (uint64_t i = 0; i < buf_pos; i++) { com_write_byte(log_buffer[i]); }
}
static void log_fb_putchar(char c) {
if (c == '\0' || fb_init_status < 1) { return; }
if (c == '\t') {
fb_pos_x += FONT_6X8_SLIM_CHAR_WIDTH * 4;
} else if (c == '\n') {
fb_pos_x = 4;
fb_pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
} else {
if (fb_pos_x >= SCREEN_WIDTH) {
fb_pos_x = 4;
fb_pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
}
if (fb_pos_y + FONT_6X8_SLIM_CHAR_HEIGHT >= SCREEN_HEIGHT) {
// Дошли до нижнего края экрана
while (log_buffer[0] != '\n') {
for (uint64_t i = 0; i < buf_max - 1; i++) { log_buffer[i] = log_buffer[i + 1]; }
buf_pos--;
}
for (uint64_t i = 0; i < buf_max - 1; i++) { log_buffer[i] = log_buffer[i + 1]; }
buf_pos--;
redraw_screen( );
return;
}
print_char(fb_pos_x, fb_pos_y, c);
fb_pos_x += FONT_6X8_SLIM_CHAR_WIDTH;
}
}
void redraw_screen( ) {
// Перерисовка экрана
for (uint64_t i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) { SCREEN_BUFFER[i] = DARK_GREEN; }
fb_pos_x = 4;
fb_pos_y = 0;
for (uint64_t i = 0; i < buf_pos; i++) { log_fb_putchar(log_buffer[i]); }
}
void log_putchar(char c) {
log_buffer[buf_pos] = c;
com_write_byte(c);
log_buffer[buf_pos] = c;
if (buf_pos + 1 == buf_max) {
// Смещение буфера на 1 символ влево
for (uint64_t i = 0; i < buf_max - 1; i++) { log_buffer[i] = log_buffer[i + 1]; }
if (fb_init_status < 1) { return; }
redraw_screen( );
} else {
buf_pos++;
if (fb_init_status < 1) { return; }
log_fb_putchar(c);
}
}
// Вывод текстового сообщения
void log_printf(char *str, ...) {
LOCK(log_lock);
va_list args;
va_start(args, str);
tool_format(&log_putchar, str, args);
lock_release(log_lock);
va_end(args);
}
void log_init_mem( ) {
LOCK(log_lock);
if (fb_init_status < 1) {
LOG("Нет доступных фреймбуфферов для вывода\n");
return;
}
LOG("Полная инициализация отладчика занимает %u килобайт озу\n",
(((SCREEN_WIDTH - 4) / FONT_WIDTH) * (SCREEN_HEIGHT / FONT_HEIGHT)) / 1024);
log_buffer = mem_alloc(((SCREEN_WIDTH - 4) / FONT_WIDTH) * (SCREEN_HEIGHT / FONT_HEIGHT));
tool_memcpy(log_buffer, start_buffer, buf_max);
buf_max = ((SCREEN_WIDTH - 4) / FONT_WIDTH) * (SCREEN_HEIGHT / FONT_HEIGHT);
LOG("Размер буффера: %u символов\n", buf_max);
redraw_screen( );
lock_release(log_lock);
}
void log_init( ) {
log_buffer = (char *)&start_buffer;
}

186
kernel/main/main.c Normal file
View File

@ -0,0 +1,186 @@
/**
* main.c
* Точка входа окончания загрузки
*
* Функции эффектов после полной инициализации ядра
*
*/
#include <fb.h>
#include <mem.h>
#include <tool.h>
#define TGA_ERR( ) LOG("Ошибка декодирования TGA на строчке: %u\n", __LINE__);
extern void *bootpng_ptr;
extern uint64_t bootpng_size;
typedef struct {
unsigned char magic1; // должно быть нулевым
unsigned char colormap; // должно быть нулевым
unsigned char encoding; // должно быть 2
unsigned short cmaporig, cmaplen; // должны быть нулевыми
unsigned char cmapent; // должно быть нулевым
unsigned short x; // должно быть нулевым
unsigned short y; // высота изображения
unsigned short h; // высота изображения
unsigned short w; // ширина изображения
unsigned char bpp; // должно быть 32
unsigned char pixeltype; // должно быть 40
} __attribute__((packed)) tga_header_t;
unsigned int *tga_parse(unsigned char *ptr, int size) {
unsigned int *data;
int i, j, k, x, y, w = (ptr[13] << 8) + ptr[12],
h = (ptr[15] << 8) + ptr[14],
o = (ptr[11] << 8) + ptr[10];
int m = ((ptr[1] ? (ptr[7] >> 3) * ptr[5] : 0) + 18);
if (w < 1 || h < 1) return NULL;
data = (unsigned int *)mem_alloc((w * h + 2) * sizeof(unsigned int));
if (!data) {
LOG("Ошибка декодирования TGA на строчке: %u, %x, %u kb\n", __LINE__,
data, ((w * h + 2) * sizeof(unsigned int)) / 1024);
return NULL;
}
switch (ptr[2]) {
case 1:
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 ||
(ptr[7] != 24 && ptr[7] != 32)) {
TGA_ERR( );
mem_free(data);
return NULL;
}
for (y = i = 0; y < h; y++) {
k = ((!o ? h - y - 1 : y) * w);
for (x = 0; x < w; x++) {
j = ptr[m + k++] * (ptr[7] >> 3) + 18;
data[2 + i++] = ((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) |
(ptr[j + 2] << 16) | (ptr[j + 1] << 8) |
ptr[j];
}
}
break;
case 2:
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 ||
(ptr[16] != 24 && ptr[16] != 32)) {
TGA_ERR( );
mem_free(data);
return NULL;
}
for (y = i = 0; y < h; y++) {
j = ((!o ? h - y - 1 : y) * w * (ptr[16] >> 3));
for (x = 0; x < w; x++) {
data[2 + i++] =
((ptr[16] == 32 ? ptr[j + 3] : 0xFF) << 24) |
(ptr[j + 2] << 16) | (ptr[j + 1] << 8) | ptr[j];
j += ptr[16] >> 3;
}
}
break;
case 9:
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 ||
(ptr[7] != 24 && ptr[7] != 32)) {
TGA_ERR( );
mem_free(data);
return NULL;
}
y = i = 0;
for (x = 0; x < w * h && m < size;) {
k = ptr[m++];
if (k > 127) {
k -= 127;
x += k;
j = ptr[m++] * (ptr[7] >> 3) + 18;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] =
((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) |
(ptr[j + 2] << 16) | (ptr[j + 1] << 8) | ptr[j];
}
} else {
k++;
x += k;
while (k--) {
j = ptr[m++] * (ptr[7] >> 3) + 18;
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] =
((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) |
(ptr[j + 2] << 16) | (ptr[j + 1] << 8) | ptr[j];
}
}
}
break;
case 10:
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 ||
(ptr[16] != 24 && ptr[16] != 32)) {
TGA_ERR( );
mem_free(data);
return NULL;
}
y = i = 0;
for (x = 0; x < w * h && m < size;) {
k = ptr[m++];
if (k > 127) {
k -= 127;
x += k;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] =
((ptr[16] == 32 ? ptr[m + 3] : 0xFF) << 24) |
(ptr[m + 2] << 16) | (ptr[m + 1] << 8) | ptr[m];
}
m += ptr[16] >> 3;
} else {
k++;
x += k;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] =
((ptr[16] == 32 ? ptr[m + 3] : 0xFF) << 24) |
(ptr[m + 2] << 16) | (ptr[m + 1] << 8) | ptr[m];
m += ptr[16] >> 3;
}
}
}
break;
default: {
TGA_ERR( );
mem_free(data);
return NULL;
}
}
data[0] = w;
data[1] = h;
return data;
}
void main( ) {
for (uint64_t i = 512; i > 1; i--) { pause( ); }
LOG("Загрузка завершена! 1\n");
unsigned int *res = tga_parse((uint8_t *)bootpng_ptr, bootpng_size);
LOG("Загрузка завершена! 2 %x\n", res);
tga_header_t *head = (tga_header_t *)bootpng_ptr;
if (res != NULL) {
LOG("Размер экрана загрузки: %ux%u \n", res[0], res[1]);
}
LOG("Размер экрана загрузки: %ux%u \n", head->h, head->w);
mem_dump_memory( );
fb_print_buf(0, 0, head->w, head->h, (uint32_t *)(res + 2));
}

View File

@ -9,23 +9,25 @@
#include <fb.h>
#include <limine.h>
#include <lock.h>
#include <log.h>
#include <mem.h>
#include <stdbool.h>
#include <tool.h>
static volatile struct limine_memmap_request memmap_request = { .id = LIMINE_MEMMAP_REQUEST,
.revision = 0,
.response = (struct limine_memmap_response *)0 };
static volatile struct limine_hhdm_request hhdm_request = { .id = LIMINE_HHDM_REQUEST,
.revision = 0,
.response = (struct limine_hhdm_response *)0 };
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0,
.response = (struct limine_memmap_response *)0
};
static volatile struct limine_hhdm_request hhdm_request = {
.id = LIMINE_HHDM_REQUEST,
.revision = 0,
.response = (struct limine_hhdm_response *)0
};
struct mem_entry {
struct mem_entry *next;
bool free;
uint64_t task_id;
uint64_t size;
size_t size;
uint8_t data[0];
};
@ -48,12 +50,11 @@ static uint64_t highest = 0;
// Количество записей в карте памяти
static uint64_t mmmap_count = 0;
extern task_t *current_task;
extern uint64_t full_init;
static const char memory_types[8][82] = { "Доступно", "Зарезервировано", "ACPI, можно освободить",
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
"Ядро и модули", "Буфер кадра" };
static const char memory_types[8][82] = {
"Доступно", "Зарезервировано", "ACPI, можно освободить",
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
"Ядро и модули", "Буфер кадра"
};
static struct limine_memmap_response *memmap_response;
@ -63,37 +64,13 @@ void mem_dump_memory( ) {
mem_entry_t *curr = first_node;
while (curr) {
if (curr->next) {
LOG("->0x%x | %u мегабайт | %s | 0x%x | поток %u\n", &curr->data, (curr->size) / 1024 / 1024,
curr->free ? memory_types[0] : memory_types[1], curr->next, curr->task_id);
} else {
LOG("->0x%x | %u мегабайт | %s | поток %u | Это последний блок\n", &curr->data, (curr->size) / 1024 / 1024,
curr->free ? memory_types[0] : memory_types[1], curr->task_id);
}
LOG("->0x%x | %u.%u kb | %s | 0x%x\n", &curr->data, (curr->size) / 1024,
(curr->size) % 1024, curr->free ? memory_types[0] : memory_types[1],
curr->next);
curr = curr->next;
}
}
void mem_get_stat( ) {
size_t free_mem = 0;
size_t used_mem = 0;
struct mem_entry *current_entry = first_node;
while (current_entry) {
if (current_entry->free) {
free_mem += current_entry->size;
} else {
used_mem += current_entry->size;
}
current_entry = current_entry->next;
}
LOG("Свободно: %u мегабайт\n", free_mem / 1024 / 1024);
LOG("Занято: %u мегабайт\n", used_mem / 1024 / 1024);
}
void mem_check_dynamic_memory( ) {
mem_entry_t *curr = first_node;
uint64_t free_mem = 0;
@ -157,12 +134,7 @@ static void merge_blocks(mem_entry_t *start) {
mem_entry_t *block = start;
while (block->next && block->next->free) {
block->size += block->next->size + sizeof(mem_entry_t);
if (block->next->next) {
block->next = block->next->next;
continue;
}
block->next = NULL;
block->next = block->next->next;
}
}
@ -205,44 +177,39 @@ static void *alloc_align(size_t size, size_t alignment) {
mem_entry_t *curr = first_node;
while (curr) {
if (curr->free && curr->size >= (alignment + sizeof(mem_entry_t) + size)) {
if (curr->free) {
void *addr = curr->data + alignment - 1;
addr -= (uintptr_t)addr % alignment + sizeof(mem_entry_t);
mem_entry_t *second = (mem_entry_t *)addr;
if (curr->size >= (second->data - curr->data + size)) {
mem_entry_t *third = (mem_entry_t *)(second->data + size);
mem_entry_t *third = (mem_entry_t *)(second->data + size);
tool_memset(third, 0, sizeof(mem_entry_t));
third->size = curr->size - (third->data - curr->data);
third->next = curr->next;
third->free = 1;
third->size = curr->size - (third->data - curr->data);
third->next = curr->next;
third->free = 1;
second->size = size;
second->next = third;
second->free = 0;
second->size = size;
second->next = third;
second->free = 0;
second->task_id = 0;
if (curr != second) {
curr->next = second;
curr->size = (uintptr_t)second - (uintptr_t)curr->data;
curr->free = 1;
}
if (task_f_init) { second->task_id = current_task->id; }
if (curr != second) {
curr->next = second;
curr->size = (uintptr_t)second - (uintptr_t)curr->data;
curr->free = 1;
return second->data;
}
return second->data;
}
curr = curr->next;
}
return NULL;
}
void *mem_alloc(size_t size) {
mem_check_dynamic_memory( );
void *data = alloc_align(size, 1);
return data;
return alloc_align(size, 1);
}
void mem_free(void *addr) {
@ -251,7 +218,6 @@ void mem_free(void *addr) {
if (curr->data == addr) {
curr->free = 1;
merge_blocks(prev ? prev : curr);
mem_merge_all_blocks( );
return;
}
prev = curr;
@ -290,12 +256,13 @@ void mem_init( ) {
for (uint64_t i = 0; i < mmmap_count; i++) {
available += mmaps[i]->length;
// LOG("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1, mmaps[i]->base, mmaps[i]->length,
// memory_types[mmaps[i]->type]);
// LOG("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
// mmaps[i]->base, mmaps[i]->length, memory_types[mmaps[i]->type]);
if (mmaps[i]->type == LIMINE_MEMMAP_FRAMEBUFFER) {
LOG("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
"килобайт\n",
mmaps[i]->length / 1024 / 1024, (mmaps[i]->length / 1024) % 1024);
mmaps[i]->length / 1024 / 1024,
(mmaps[i]->length / 1024) % 1024);
}
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
@ -323,27 +290,30 @@ void mem_init( ) {
// Освобождаем все доступные фреймы памяти
for (uint64_t i = 0; i < mmmap_count; i++) {
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) { bitmap_limit++; }
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
bitmap_limit++;
}
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) { mem_frame_free((void *)mmaps[i]->base + t, 1); }
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
mem_frame_free((void *)mmaps[i]->base + t, 1);
}
}
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
LOG("Размер битовой карты: %u\n", bitmap_size);
alloc_init(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
LOG("%u мегабайт выделено в динамичную память\n", (256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
// Выделяем по 4 мегабайта в аллокатор динамичной памяти
for (uint64_t i = 0; i < 32; i += 8) { mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE); }
alloc_init(mem_frame_alloc(1), BLOCK_SIZE);
LOG("%u мегабайт выделено в динамичную память\n",
(256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
for (uint64_t i = 256 * 16; i > 0; i -= BLOCK_SIZE) {
mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
}
mem_merge_all_blocks( );
mem_dump_memory( );
LOG("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n", (bitmap_available * BLOCK_SIZE) / 1024 / 1024,
available / 1024 / 1024);
LOG("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
(bitmap_available * BLOCK_SIZE) / 1024 / 1024, available / 1024 / 1024);
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
LOG("Проверка менеджера памяти\n");
}

View File

@ -9,18 +9,19 @@
#include <fb.h>
#include <limine.h>
#include <log.h>
#include <mod.h>
#include <sys.h>
#include <tool.h>
static volatile struct limine_module_request module_request = { .id = LIMINE_MODULE_REQUEST,
.revision = 0,
.response = (struct limine_module_response *)0 };
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0,
.response = (struct limine_module_response *)0
};
static struct limine_module_response *module_response;
uint64_t modules_count = 0;
module_info_t *module_list = NULL;
module_info_t module_list[MOD_MAX];
static char *graphics_module_message = "Графический модуль-объект";
static char *other_module_message = "Неизвестный тип модуля";
@ -29,69 +30,47 @@ static env_t main_env;
void *bootpng_ptr;
uint64_t bootpng_size;
// Вывод списка модулей в отладчик
static void *elf_entry(elf64_header_t *module_bin) {
// Приводим заголовок ELF файла к типу elf64_header_t
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
// Возвращаем указатель на точку входа
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
}
void mod_list_show( ) {
for (uint64_t i = 0; i < modules_count; i++) {
LOG("Имя: %s\n", module_list[i].name);
LOG("Описание модуля: %s\n", module_list[i].message);
LOG("Тип модуля: %u\n", module_list[i].type);
LOG("Код ошибки модуля: %u\n", module_list[i].err_code);
if (module_list[i].data_size) {
LOG("Размер данных: %u\n", module_list[i].data_size);
LOG("Адрес данных: 0x%x\n", module_list[i].data);
}
fb_printf("Имя: %s\n", module_list[i].name);
fb_printf("Описание модуля: %s\n", module_list[i].message);
fb_printf("Тип модуля: %u\n", module_list[i].type);
fb_printf("Код ошибки модуля: %u\n", module_list[i].err_code);
fb_printf("Размер данных: %u\n", module_list[i].data_size);
fb_printf("Адрес данных: 0x%x\n", module_list[i].data);
}
}
// Запуск модулей имеющих дополнительную точку входа
void mod_after_init( ) {
for (uint64_t i = 0; i < modules_count; i++) {
if (module_list[i].after_init != 0) {
LOG("%s.after_init( );\n", module_list[i].name);
task_new_thread(module_list[i].after_init, module_list[i].name);
}
}
}
// Запуск модулей имеющих дополнительную точку входа
module_info_t *mod_list_get(uint64_t *count) {
*count = modules_count;
return module_list;
}
// Поиск модуля по тегу
module_info_t *mod_find(char *tag) {
for (uint64_t i = 0; i < modules_count; i++) {
if (tool_str_contains(module_list[i].name, tag)) { return &module_list[i]; }
if (!tool_starts_with(module_list[i].name, tag)) {
return &module_list[i];
}
}
return (module_info_t *)NULL;
}
void mod_init( ) {
module_response = module_request.response;
uint64_t module_count = module_response->module_count;
struct limine_file *module_ptr = (struct limine_file *)0;
if (module_count > 0) {
module_list = (module_info_t *)mem_alloc(module_count * sizeof(module_info_t));
if (module_list == NULL) {
LOG("Ошибка выделения памяти для массива module_list\n");
return;
}
LOG("module_list = 0x%x\n", module_list);
}
for (uint64_t i = 0; i < module_count; i++) {
module_ptr = module_response->modules[i];
LOG("[%u] %s [%s] 0x%x Размер: %u\n", i, module_ptr->path, module_ptr->cmdline, module_ptr->address,
module_ptr->size);
LOG("[%d] %s [%s] 0x%x Размер: %u\n", i, module_ptr->path,
module_ptr->cmdline, module_ptr->address, module_ptr->size);
if (modules_count >= module_count) {
LOG("Модуль не обработан. Максимум %u модулей!\n", module_count);
if (modules_count >= MOD_MAX) {
LOG("Модуль не обработан. Максимум %u модулей!\n", MOD_MAX);
break;
}
@ -110,100 +89,35 @@ void mod_init( ) {
}
if (!tool_starts_with(module_ptr->cmdline, "[MOD]")) {
module_list[modules_count].data_size = module_ptr->size;
module_list[modules_count].data = module_ptr->address;
module_list[modules_count].type = 255; // Неизвестный тип модуля
modules_count++;
continue;
}
module_info_t (*module_init)(env_t *env) = (module_info_t(*)(env_t * env)) elf_entry(module_ptr->address);
module_info_t (*module_init)(env_t * env) =
(module_info_t(*)(env_t * env))
elf_entry((elf64_header_t *)module_ptr->address);
// LOG("\t->Точка входа: 0x%x\n", module_init);
LOG("\t->Точка входа: 0x%x\n", module_init);
main_env.offset = (uint64_t)module_ptr->address;
main_env.info = (module_info_t *)0;
sys_install(&main_env);
sys_install(main_env);
uint64_t id = task_new_thread((void *)1, module_list[i].name);
main_env.fb_printf = &fb_printf;
module_info_t ret = module_init(&main_env);
LOG("\t->%s\n", ret.message);
task_del(id);
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;
if (module_list[modules_count].after_init) {
task_new_thread(module_list[modules_count].after_init, module_list[modules_count].name);
}
if (ret.irq != 0) {
if (ret.irq_handler != 0) {
LOG("Установлен обработчик прерывания [%u] по адресу 0x%x в модуле %s\n", ret.irq, ret.irq_handler,
ret.name);
idt_set_int(ret.irq, ret.irq_handler);
}
if (ret.data_size != 0) {
module_list[modules_count].data =
(&(ret.data) + (uint64_t)module_ptr->address);
}
modules_count++;
}
LOG("Модулей обработано: %u\n", modules_count);
}
// Добавление модуля
void mod_add(module_info_t module) {
if (modules_count == 0) {
module_list = (module_info_t *)mem_alloc(sizeof(module_info_t));
if (module_list == NULL) {
LOG("Ошибка выделения памяти для массива module_list\n");
return;
}
} else {
module_info_t *new_module_list =
(module_info_t *)mem_realloc(module_list, (modules_count + 1) * sizeof(module_info_t));
if (new_module_list == NULL) {
LOG("Ошибка выделения памяти для массива module_list\n");
return;
}
module_list = new_module_list;
}
module_list[modules_count] = module;
modules_count++;
}
// Удаление модуля
void mod_del(module_info_t *module) {
if (modules_count == 0) {
LOG("Модуль не найден\n");
return;
}
for (uint64_t i = 0; i < modules_count; i++) {
if (&module_list[i] == module) {
for (uint64_t j = i; j < modules_count - 1; j++) { module_list[j] = module_list[j + 1]; }
modules_count--;
module_list = (module_info_t *)mem_realloc(module_list, modules_count * sizeof(module_info_t));
if (module_list == NULL) {
LOG("Ошибка выделения памяти для массива module_list\n");
return;
}
LOG("Модуль удален\n");
return;
}
}
LOG("Модуль не найден\n");
}

View File

@ -8,44 +8,43 @@
*/
#include <arch.h>
#include <fb.h>
#include <limine.h>
#include <log.h>
#include <mem.h>
#include <mod.h>
#include <tool.h>
#include <version.h>
uint64_t full_init = 0;
// Точка входа
void _start( ) {
asm volatile("cli");
log_init( );
mem_init( );
fb_init( );
log_init_mem( );
arch_init( );
pit_init( );
task_init( );
task_f_init = 1;
mod_init( );
mem_init( );
fb_set_text_color(0x00FF00);
LOG("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
"версии %u.%u.%u %s***\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, KERNEL_GIT_TAG);
"версии %u.%u.%u ***\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
LOG("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
fb_set_text_color(0x00D000);
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);
mod_init( );
// pit_init( );
full_init = 1;
task_after_init( );
mod_list_show( );
fb_set_text_color(0x00FF00);
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
asm volatile("sti");
fb_set_text_color(0x00D000);
for (;;) { asm volatile("hlt"); }
while (1) {
uint64_t byte = inb(0x60);
if (byte == 0x1) {
LOG("Exit!\n");
return;
}
}
}

View File

@ -6,27 +6,16 @@
*/
#include <fb.h>
#include <log.h>
#include <mem.h>
#include <mod.h>
#include <stdint.h>
#include <sys.h>
module_info_t *current_module;
extern uint32_t *fb_addr;
extern uint32_t text_color;
extern uint32_t background;
extern uint64_t width;
extern uint64_t height;
extern uint64_t pitch;
extern uint16_t bpp;
void sys_init( ) {}
static framebuffer_t sys_alloc_framebuffer( ) {
return (framebuffer_t){
.address = fb_addr, .width = width, .height = height, .pitch = pitch, .bpp = bpp, .reserved = 0
};
static framebuffer_t *sys_alloc_framebuffer( ) {
return (framebuffer_t *)0;
}
static void sys_free_framebuffer(framebuffer_t *frame) {
@ -49,20 +38,29 @@ static module_info_t *sys_get_module(char *module_id) {
return (module_info_t *)mod_find(module_id);
}
env_t *sys_install(env_t *module) {
module->log_printf = &log_printf;
module->alloc_framebuffer = &sys_alloc_framebuffer;
module->free_framebuffer = &sys_free_framebuffer;
module->alloc = &mem_alloc;
module->free = &mem_free;
module->exit = &sys_exit;
module->get_error = &sys_get_error;
module->get_info = &sys_get_info;
module->get_module = &sys_get_module;
module->mod_list_get = &mod_list_get;
module->new_thread = &task_new_thread;
module->delete_thread = &task_del_current;
module->get_time = &rtc_get_time;
static uint64_t sys_new_thread(uint64_t func) {
return func;
}
static int sys_delete_thread(uint64_t thread_id) {
return thread_id;
}
static time_t sys_get_time( ) {
return (time_t){ .year = 2023, .month = 10, .day = 31, .second = 1 };
}
env_t sys_install(env_t module) {
module.fb_printf = &fb_printf;
module.alloc_framebuffer = &sys_alloc_framebuffer;
module.free_framebuffer = &sys_free_framebuffer;
module.exit = &sys_exit;
module.get_error = &sys_get_error;
module.get_info = &sys_get_info;
module.get_module = &sys_get_module;
module.new_thread = &sys_new_thread;
module.delete_thread = &sys_delete_thread;
module.get_time = &sys_get_time;
return module;
}

17
kernel/task.c Normal file
View File

@ -0,0 +1,17 @@
/**
* task.c
* Управление потоками
*
* Данный файл содержит функции для создания и удаления потоков.
*
*/
void task_init( ) {}
void task_new_thread( ) {
return;
}
void task_delete_thread( ) {
return;
}

View File

@ -32,27 +32,6 @@ uint64_t tool_strlen(const char *str) {
return length;
}
void tool_strcpy(char *dest, char *src) {
uint64_t i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
void tool_strcat(char *str1, const char *str2) {
while (*str1 != '\0') { str1++; }
while (*str2 != '\0') {
*str1 = *str2;
str1++;
str2++;
}
*str1 = '\0';
}
uint64_t tool_starts_with(const char *str, const char *prefix) {
uint64_t str_len = tool_strlen(str);
uint64_t prefix_len = tool_strlen(prefix);
@ -66,24 +45,6 @@ uint64_t tool_starts_with(const char *str, const char *prefix) {
return 1;
}
uint64_t tool_str_contains(const char *str, const char *substr) {
uint64_t str_len = tool_strlen(str);
uint64_t substr_len = tool_strlen(substr);
if (substr_len > str_len) { return 0; }
for (uint64_t i = 0; i <= str_len - substr_len; i++) {
uint64_t j;
for (j = 0; j < substr_len; j++) {
if (str[i + j] != substr[j]) { break; }
}
if (j == substr_len) { return 1; }
}
return 0;
}
// Функция для переворачивания строки
void tool_reverse_str(char *str) {
int len = 0;
@ -117,7 +78,10 @@ void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
int64_t remainder = i % base;
// Преобразовываем остаток в символ и добавляем его в строку
buf[index++] =
(remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; // Если остаток > 9, добавляем заглавную букву А
(remainder > 9)
? (remainder - 10) + 'A'
: remainder +
'0'; // Если остаток > 9, добавляем заглавную букву А
i /= base;
} while (i > 0);
@ -140,7 +104,10 @@ void tool_uint_to_str(uint64_t i, uint8_t base, char *buf) {
uint64_t remainder = i % base;
// Преобразовываем остаток в символ и добавляем его в строку
buf[index++] =
(remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; // Если остаток > 9, добавляем заглавную букву А
(remainder > 9)
? (remainder - 10) + 'A'
: remainder +
'0'; // Если остаток > 9, добавляем заглавную букву А
i /= base;
} while (i > 0);
@ -151,67 +118,18 @@ void tool_uint_to_str(uint64_t i, uint8_t base, char *buf) {
tool_reverse_str(buf);
}
void tool_uint_to_wstr(uint64_t i, uint8_t base, char *buf, uint64_t width) {
uint64_t index = 0;
// Деление с остатком для преобразования числа в нужную систему счисления
do {
uint64_t remainder = i % base;
// Преобразовываем остаток в символ и добавляем его в строку
buf[index++] =
(remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; // Если остаток > 9, добавляем заглавную букву А
i /= base;
} while (i > 0);
while (index < width) {
buf[index++] = ' '; // Добавляем пробелы слева до заданной ширины
}
// Добавляем нулевой символ в конец строки, чтобы завершить ее
buf[index] = '\0';
// Переворачиваем строку, чтобы цифры были в правильном порядке
tool_reverse_str(buf);
}
int is_digit(char c) {
if (c >= '0' && c <= '9') { return 1; }
return 0;
}
int64_t char_to_digit(char c) {
if (is_digit(c)) { return (int64_t)(c - '0'); }
return -1;
}
uint64_t tool_uint_pow(uint64_t d, uint64_t n) {
uint64_t result = 1;
for (uint64_t i = 0; i < n; i++) { result *= d; }
return result;
}
// Функция для форматированного вывода
void tool_format(void (*putc)(char c), const char *format_string, va_list args) {
void tool_format(void (*putc)(char c), const char *format_string,
va_list args) {
while (*format_string != '\0') {
if (*format_string == '%') {
char buf[48];
uint64_t point = 0;
char *arg_s;
const char *arg_s;
int64_t arg_d = 0;
uint64_t arg_u = 0;
int64_t width = 0;
format_string++;
while (is_digit(*format_string)) {
arg_u += char_to_digit(*format_string);
if (is_digit(*(format_string + 1))) { arg_u *= 10; }
format_string++;
}
width = arg_u;
if (*format_string == '\0') {
break; // Неожиданный конец строки формата
}
@ -220,19 +138,12 @@ void tool_format(void (*putc)(char c), const char *format_string, va_list args)
case '%': putc('%'); break;
case 'c': putc(va_arg(args, int)); break;
case 's':
arg_s = va_arg(args, char *);
if (width) { width -= tool_strlen(arg_s); }
arg_s = va_arg(args, const char *);
// Вывод каждого символа строки
while (*arg_s != '\0') {
putc(*arg_s);
arg_s++;
}
while (width > 0) {
putc(' ');
width--;
}
break;
case 'd':
arg_d = va_arg(args, int64_t);
@ -241,10 +152,11 @@ void tool_format(void (*putc)(char c), const char *format_string, va_list args)
putc(buf[point]);
point++;
}
break;
case 'u':
arg_u = va_arg(args, uint64_t);
tool_uint_to_wstr(arg_u, 10, buf, width);
tool_uint_to_str(arg_u, 10, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
@ -252,7 +164,15 @@ void tool_format(void (*putc)(char c), const char *format_string, va_list args)
break;
case 'x':
arg_u = va_arg(args, uint64_t);
tool_uint_to_wstr(arg_u, 16, buf, width);
tool_uint_to_str(arg_u, 16, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
}
break;
case 'l':
arg_u = va_arg(args, uint64_t);
tool_uint_to_str(arg_u, 16, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;

View File

@ -1 +0,0 @@
libmod.a

View File

@ -1,11 +0,0 @@
#/bin/sh
CC=${CC:-gcc}
AR=${AR:-ar}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
mkdir -p bin
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c system.c -o bin/system.o
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c tool.c -o bin/tool.o
$AR -rcs ../../modlib/lib/libmod.a ../../modlib/lib/bin/system.o ../../modlib/lib/bin/tool.o
ranlib ../../modlib/lib/libmod.a

View File

@ -1,60 +0,0 @@
/**
* system.c
* Системные вызовы модулей
*
* Основные функции для работы с функцияи системы
*
*/
#include <modstd.h>
#include <system.h>
void *(*alloc)(uint64_t size);
void (*free)(void *ptr);
void (*log_printf)(char *str, ...);
module_info_t *(*get_module)(char *module_id);
module_info_t *(*mod_list_get)(uint64_t *count);
framebuffer_t (*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void (*exit)(int code);
int (*get_error)( );
sys_info_t *(*get_info)( );
uint64_t (*new_thread)(void (*func)(void *), char *name);
void (*delete_thread)( );
time_t (*get_time)( );
uint64_t offset;
void init_env(env_t *loader_env) {
offset = loader_env->offset;
log_printf = loader_env->log_printf;
alloc = loader_env->alloc;
free = loader_env->free;
get_module = loader_env->get_module;
mod_list_get = loader_env->mod_list_get;
alloc_framebuffer = loader_env->alloc_framebuffer;
free_framebuffer = loader_env->free_framebuffer;
exit = loader_env->exit;
get_error = loader_env->get_error;
get_info = loader_env->get_info;
new_thread = loader_env->new_thread;
delete_thread = loader_env->delete_thread;
get_time = loader_env->get_time;
}
void *realloc(void *addr, size_t size) {
if (size == 0) {
free(addr);
return NULL;
}
if (addr == NULL) { return alloc(size); }
void *new_addr = alloc(size);
if (new_addr == NULL) { return NULL; }
memcpy(new_addr, addr, size);
free(addr);
return new_addr;
}

View File

@ -1,259 +0,0 @@
/**
* tool.c
* Дополнительные функции
*
* Вспомогательные функции для работы с данными
*
*/
#include <modstd.h>
#include <system.h>
uint64_t strlen(char *str) {
uint64_t length = 0;
while (*str) {
length++;
str++;
}
return length;
}
void strcpy(char *dest, char *src) {
size_t i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0'; // добавляем завершающий нулевой символ
}
size_t strspn(char *str, char *accept) {
size_t count = 0;
char *ptr = str;
char *acc;
while (*ptr) {
acc = accept;
while (*acc) {
if (*ptr == *acc) {
count++;
break;
}
acc++;
}
if (*acc == '\0') break;
ptr++;
}
return count;
}
size_t strcspn(char *str, char *reject) {
size_t count = 0;
char *ptr = str;
char *r;
while (*ptr) {
r = reject;
while (*r) {
if (*ptr == *r) { return count; }
r++;
}
count++;
ptr++;
}
return count;
}
char *strtok(char *str, char *delim) {
char *token = NULL;
char *next_token = NULL;
if (str != NULL) {
token = str;
} else {
token = next_token;
}
if (token == NULL) { return NULL; }
token += strspn(token, delim);
if (*token == '\0') {
next_token = NULL;
return NULL;
}
next_token = token + strcspn(token, delim);
if (*next_token != '\0') {
*next_token = '\0';
next_token++;
} else {
next_token = NULL;
}
return token;
}
size_t strtol(char *str, char **endptr, int64_t base) {
size_t num = 0;
int64_t sign = 1;
// Пропускаем пробелы в начале строки
while (*str == ' ') { str++; }
// Проверяем знак числа
if (*str == '-') {
sign = -1;
str++;
} else if (*str == '+') {
str++;
}
// Проверяем основание системы счисления
if (base == 0) {
// Автоопределение основания
if (*str == '0') {
str++;
if (*str == 'x' || *str == 'X') {
base = 16; // Шестнадцатеричная система счисления
str++;
} else {
base = 8; // Восьмеричная система счисления
}
} else {
base = 10; // Десятичная система счисления
}
}
// Преобразование строки в число
while (*str != '\0') {
int64_t digit;
if (*str >= '0' && *str <= '9') {
digit = *str - '0';
} else if (*str >= 'A' && *str <= 'Z') {
digit = *str - 'A' + 10;
} else if (*str >= 'a' && *str <= 'z') {
digit = *str - 'a' + 10;
} else {
break; // Некорректный символ - прерываем преобразование
}
if (digit >= base) {
break; // Некорректная цифра - прерываем преобразование
}
num = num * base + digit;
str++;
}
if (endptr != NULL) {
//*endptr = (char *)str; // Указатель на символ, следующий за числом
}
return num * sign;
}
char *strchr(char *str, char c) {
// пройти по каждому символу строки
while (*str != '\0') {
// если символ найден, вернуть указатель на него
if (*str == c) { return (char *)str; }
str++; // переход к следующему символу
}
// символ не найден, вернуть NULL
return NULL;
}
int strcmp(char *s1, char *s2) {
while (*s1 == *s2) {
if (*s1 == '\0') { return 0; }
s1++;
s2++;
}
return *s1 - *s2;
}
char *trstr(char *str, char sym) {
size_t left, size = strlen(str);
for (left = 0x00U; left < size; left++)
if (str[left] == sym) break;
size++;
left++;
if (left < size)
size -= left;
else
left = 0x00U;
return str + left;
}
char *strdup(char *str) {
size_t len = strlen(str) + 1;
char *dup = alloc(len);
if (dup != NULL) { memcpy(dup, str, len); }
return dup;
}
size_t count_chars(char *str, char c) {
size_t count = 0;
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
if (str[i] == c) { count++; }
}
return count;
}
uint64_t str_contains(char *str, char *substr) {
uint64_t str_len = strlen(str);
uint64_t substr_len = strlen(substr);
if (substr_len > str_len) { return 0; }
for (uint64_t i = 0; i <= str_len - substr_len; i++) {
uint64_t j;
for (j = 0; j < substr_len; j++) {
if (str[i + j] != substr[j]) { break; }
}
if (j == substr_len) { return 1; }
}
return 0;
}
void memcpy(void *dest, void *src, size_t n) {
char *d = (char *)dest;
char *s = (char *)src;
for (size_t i = 0; i < n; i++) { d[i] = s[i]; }
}
void *memset(void *ptr, uint8_t n, size_t size) {
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < size; i++) { p[i] = n; }
return ptr;
}
void *memmove(void *dest, void *src, size_t n) {
char *d = (char *)dest;
char *s = (char *)src;
if (d > s) {
// копирование с конца массива, чтобы предотвратить перекрытие
for (size_t i = n; i > 0; --i) { d[i - 1] = s[i - 1]; }
} else if (d < s) {
// копирование с начала массива
for (size_t i = 0; i < n; ++i) { d[i] = s[i]; }
}
return dest;
}

View File

@ -1,30 +0,0 @@
/**
* modstd.h
* Стандартная библиотека для модулей
*
* Заголовочный файл содержащий определения стандартной библиотеки модулей
*
*/
#include <types.h>
#ifndef MODSTD_H
#define MODSTD_H
uint64_t strlen(char *str);
void strcpy(char *dest, char *src);
size_t strspn(char *str, char *accept);
size_t strcspn(char *str, char *reject);
char *strtok(char *str, char *delim);
size_t strtol(char *str, char **endptr, int64_t base);
char *strchr(char *str, char c);
int strcmp(char *s1, char *s2);
char *trstr(char *str, char sym);
char *strdup(char *str);
size_t count_chars(char *str, char c);
uint64_t str_contains(char *str, char *substr);
void memcpy(void *dest, void *src, size_t n);
void *memset(void *ptr, uint8_t n, size_t size);
void *memmove(void *dest, void *src, size_t n);
#endif // modstd.h

View File

@ -9,55 +9,76 @@
#ifndef SYSTEM_H
#define SYSTEM_H
#include <modstd.h>
#include <types.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef long long int64_t;
extern void *(*alloc)(uint64_t size);
extern void (*free)(void *ptr);
extern void (*log_printf)(char *str, ...);
extern module_info_t *(*get_module)(char *module_id);
extern module_info_t *(*mod_list_get)(uint64_t *count);
extern framebuffer_t (*alloc_framebuffer)( );
extern void (*free_framebuffer)(framebuffer_t *frame);
extern void (*exit)(int code);
extern int (*get_error)( );
extern sys_info_t *(*get_info)( );
extern uint64_t (*new_thread)(void (*func)(void *), char *name);
extern void (*delete_thread)( );
extern time_t (*get_time)( );
extern uint64_t offset;
typedef struct {
int reserved;
} framebuffer_t;
void init_env(env_t *loader_env);
void *realloc(void *addr, size_t size);
typedef struct {
int reserved;
} sys_info_t;
static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
typedef struct {
char *name;
void *addr;
} module_func_t;
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
typedef struct {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
} module_info_t;
static inline void outw(uint16_t port, uint16_t val) {
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
}
typedef struct {
int reserved;
} func_t;
static inline uint16_t inw(uint16_t port) {
uint16_t ret;
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
typedef struct {
uint8_t a[4];
uint8_t b[4];
uint8_t c[4];
uint8_t d[4];
} uid_t;
static inline uint32_t inl(uint16_t port) {
uint32_t data;
asm volatile("inl %1, %0" : "=a"(data) : "Nd"(port));
return data;
}
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t second;
} time_t;
static inline void outl(uint16_t port, uint32_t data) {
asm volatile("outl %0, %1" : : "a"(data), "Nd"(port));
typedef struct {
uint64_t offset;
module_info_t *info;
void (*fb_printf)(char *str, ...); // Временная функция
framebuffer_t *(*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void (*exit)(int code);
void (*get_error)( );
sys_info_t *(*get_info)( );
module_info_t *(*get_module)(char *module_id);
uint64_t (*new_thread)(uint64_t func);
int (*delete_thread)(uint64_t thread_id);
time_t (*get_time)( );
} env_t;
extern module_info_t static_info;
static void (*fb_printf)(char *str, ...);
static uint64_t offset;
static inline void init_env(env_t *loader_env) {
offset = loader_env->offset;
loader_env->info = (module_info_t *)&static_info + offset;
fb_printf = loader_env->fb_printf;
}
#endif // system.h

View File

@ -1,125 +0,0 @@
/**
* types.h
* Системные вызовы
*
* Заголовочный файл содержащий заготовку для работы с системными вызовами
*
*/
#ifndef TYPES_H
#define TYPES_H
#define NULL ((void *)0)
#define bool _Bool
#define false 0
#define true 1
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef uint64_t size_t;
typedef struct {
uint32_t *address;
uint64_t width;
uint64_t height;
uint64_t pitch;
uint16_t bpp;
int reserved;
} framebuffer_t;
typedef struct {
int reserved;
} sys_info_t;
typedef struct {
char *name;
void *addr;
} module_func_t;
typedef struct {
int reserved;
} func_t;
typedef struct {
uint8_t a[4];
uint8_t b[4];
uint8_t c[4];
uint8_t d[4];
} uid_t;
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hours;
uint8_t minutes;
uint8_t second;
} time_t;
struct frame {
uint64_t rbp;
uint64_t rbx;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t int_number;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*int_entry_t)(struct frame *state);
typedef struct {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
uint8_t irq;
int_entry_t irq_handler;
void *(*get_func)(uint64_t id);
void (*after_init)( );
} __attribute__((packed)) module_info_t;
typedef struct {
uint64_t offset;
void (*log_printf)(char *str, ...); // Временная функция
framebuffer_t (*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void *(*alloc)(uint64_t size);
void (*free)(void *ptr);
void (*exit)(int code);
int (*get_error)( );
sys_info_t *(*get_info)( );
module_info_t *(*get_module)(char *module_id);
module_info_t *(*mod_list_get)(uint64_t *count);
uint64_t (*new_thread)(void (*func)(void *), char *name);
void (*delete_thread)( );
time_t (*get_time)( );
} __attribute__((packed)) env_t;
#endif // types.h

13
modules/cpubench/build.sh Executable file → Normal file
View File

@ -1,16 +1,7 @@
#/bin/sh
echo "Название: CPUBENCH"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o cpubench.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld cpubench.o -L../../modlib/lib/ -lmod -o cpubench.ko
gcc -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o cpubench.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib cpubench.o -o cpubench.ko
cp cpubench.ko ../bin/
echo "Сборка завершена, файл: cpubench.ko"

View File

@ -2,90 +2,59 @@
static char fxsave_region[512] __attribute__((aligned(16)));
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
}
static inline void L1_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
log_printf("L1 кэш недоступен\n");
fb_printf("L1 кэш недоступен\n");
return;
}
log_printf("L1: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", ecx & 0xFF, (ecx >> 12) & 0x07,
(ecx >> 16) & 0xFFff);
fb_printf(
"L1: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
ecx & 0xff, (ecx >> 12) & 0x07, (ecx >> 16) & 0xffff);
}
static inline void L2_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
log_printf("L2 кэш недоступен\n");
fb_printf("L2 кэш недоступен\n");
return;
}
log_printf("L2: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", ecx & 0xFF, (ecx >> 12) & 0x0F,
(ecx >> 16) & 0xFFFF);
fb_printf(
"L2: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
ecx & 0xff, (ecx >> 12) & 0x0F, (ecx >> 16) & 0xFFFF);
}
static inline void L3_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
log_printf("L3 кэш недоступен\n");
fb_printf("L3 кэш недоступен\n");
return;
}
log_printf("L3: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", edx & 0xFF, (edx >> 12) & 0x0F,
(edx >> 16) & 0xFFFF);
fb_printf(
"L3: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
edx & 0xff, (edx >> 12) & 0x0F, (edx >> 16) & 0xFFFF);
}
static void cpu_info( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x8000001E, &eax, &ebx, &ecx, &edx);
uint32_t apic_id = eax;
uint8_t compute_unit_id = ebx & 0xFF;
uint8_t cores_per_compute_unit = ((ebx >> 8) & 3) + 1;
uint8_t node_id = ecx & 0xFF;
uint8_t nodes_per_processor = ((ecx >> 8) & 3) + 1;
log_printf("Топология процессора:\n");
log_printf(" Идентификатор APIC: %u\n", apic_id);
log_printf(" Идентификатор вычислительной единицы: %u\n", compute_unit_id);
log_printf(" Ядра на вычислительную единицу: %u\n", cores_per_compute_unit);
log_printf(" Идентификатор узла: %u\n", node_id);
log_printf(" Узлы на процессор: %u\n", nodes_per_processor);
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
uint32_t eax, ebx, ecx, edx;
module_info_t init(env_t *env) {
init_env(env);
cpuid(1, &eax, &ebx, &ecx, &edx);
if (ecx & (1 << 31)) {
log_printf("Запуск на эмуляторе\n");
} else {
log_printf("Запуск на физическом процессоре\n");
}
L1_cache_size( );
L2_cache_size( );
L3_cache_size( );
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
if (eax >= 0x8000001E) { cpu_info( ); }
return (module_info_t){ .name = (char *)"CPUBENCH",
.message = (char *)"Дополнительная информация о процессоре",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 };
return (module_info_t){
.name = (char *)"CPUBENCH",
.message = (char *)"Дополнительная информация о процессоре",
.err_code = 0,
};
}

View File

@ -1,17 +1,7 @@
#/bin/sh
echo "Название: Hello world"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o hello.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld hello.o -L../../modlib/lib/ -lmod -o hello.ko
gcc -mcmodel=large -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o hello.o
gcc -mcmodel=large -Wl,--entry=init -fPIC -shared -nostdlib hello.o -o hello.ko
cp hello.ko ../bin/
echo "Сборка завершена, файл: hello.ko"

View File

@ -1,80 +1,14 @@
#include <system.h>
static const char name[] = "[APP]Привет мир!";
static const char name[] = "Привет мир!";
static const char message[] = "Привет из модуля!";
static const char logo[] = "\n\n"
"\t ,:;;;;:, \n"
"\t :++******++: \n"
"\t ;****+;;+****; \n"
"\t :****;, ,;****, \n"
"\t :****: :****: \n"
"\t ,;****+;;+****; \n"
"\t ,;+********+: \n"
"\t ,:;****;:, \n"
"\t :****, \n"
"\t :****, \n"
"\t :****, \n"
"\t :****, \n"
"\t ,:;****;:,, \n"
"\t :*********+;:, \n"
"\t :++;;+++****+;, \n"
"\t ,:;****+: \n"
"\t ,, ,,::,, :+****: \n"
"\t ,++;;, ,;+****+;, ,+***+, \n"
"\t ;****: ;********; :****: \n"
"\t ;****, ;********+ :****: \n"
"\t ,****; ,;+*****;, ,+***+, \n"
"\t ;****;, ,::::, ,+****; \n"
"\t ,:;+*****+;,, ,,;+*****+;:, \n"
"\t ,:;+****++*****+;;;;;++****+++****+;:, \n"
"\t ,,,::,,, ,:;+****+;:, :;+***********++;, ,:;+****+;:,,:;;;;;;:,, \n"
"\t ,:+++****++;:,,:;+****+;:, ,,:;;;;;;;::, ,:;+****++*********+:, \n"
"\t ,;+****++++****++****+;:, ,:;+****+;;;;+****+, \n"
"\t ,+***+;:,,,,:;+****+;:, :****;, :+***+,\n"
"\t ;***+: :+***; ;***+, :****:\n"
"\t,+***; ;***+, ;****: ,;***+,\n"
"\t +***+, ,+***+ ,+***+;:,,,:+****: \n"
"\t :+***+:, ,:+***+: ,;+***********+: \n"
"\t :+****++;;++****+, ,:;+++++++;:, \n"
"\t ,:++********++:, ,,,,, \n"
"\t ,::;;;;::, "
"\n\n";
static const char logo_synapseos[] = "\n\n"
"\t\t :::::::: ::: ::: :::: ::: ::: ::::::::: "
" :::::::: :::::::::: :::::::: ::::::::\n"
"\t\t :+: :+: :+: :+: :+:+: :+: :+: :+: :+: :+: "
" :+: :+: :+: :+: :+: :+: :+:\n"
"\t\t +:+ +:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ +:+ "
" +:+ +:+ +:+ +:+ +:+\n"
"\t\t +#++:++#++ +#++: +#+ +:+ +#+ +#++:++#++: +#++:++#+ "
" +#++:++#++ +#++:++# +#+ +:+ +#++:++#++\n"
"\t\t +#+ +#+ +#+ +#+#+# +#+ +#+ +#+ "
" +#+ +#+ +#+ +#+ +#+\n"
"\t\t#+# #+# #+# #+# #+#+# #+# #+# #+# "
"#+# #+# #+# #+# #+# #+# #+#\n"
"\t\t######## ### ### #### ### ### ### "
"######## ########## ######## ########\n"
"\n\t\t\t\tМы вернулись!\n\n";
static int app_main( ) {
log_printf("[%s]\n", message);
return 2 + 2;
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
module_info_t init(env_t *env) {
init_env(env);
log_printf("[%s]\n", message);
log_printf("%s\n", logo);
log_printf("%s\n", logo_synapseos);
return (module_info_t){ .name = (char *)&name,
.message = (char *)&message,
.type = 0,
.data_size = 0,
.data = (void *)&app_main,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 };
fb_printf("[%s]\n", message);
return (module_info_t){
.name = (char *)&name,
.message = (char *)&message,
.err_code = 2023,
};
}

View File

@ -1,17 +0,0 @@
#/bin/sh
echo "Название: IMFS"
echo "Лицензия: CC BY-NC 4.0"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o imfs.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld imfs.o -L../../modlib/lib/ -lmod -o imfs.ko
cp imfs.ko ../bin/
echo "Сборка завершена, файл: imfs.ko"

View File

@ -1,170 +0,0 @@
#include <system.h>
#define MAX_FILE_NAME_LEN 256
#define MAX_FILE_TYPE_LEN 16
typedef unsigned char folder_type_t;
typedef struct file_t {
char *data;
size_t size;
char name[MAX_FILE_NAME_LEN];
char type[MAX_FILE_TYPE_LEN];
struct file_t *next;
} file_t;
typedef struct folder_t {
char name[MAX_FILE_NAME_LEN];
struct folder_t *parent;
struct folder_t *child;
struct folder_t *next;
file_t *files;
} folder_t;
folder_t *root_folder = NULL;
folder_t *cache_f = NULL;
folder_t *docs_f = NULL;
folder_t *media_f = NULL;
folder_t *mod_f = NULL;
folder_t *create_folder(char *name, folder_t *parent) {
folder_t *folder = alloc(sizeof(folder_t));
strcpy(folder->name, name);
folder->parent = parent;
folder->child = NULL;
folder->next = NULL;
folder->files = NULL;
if (parent == NULL) {
root_folder = folder;
} else {
if (parent->child == NULL) {
parent->child = folder;
} else {
folder_t *current_folder = parent->child;
while (current_folder->next != NULL) { current_folder = current_folder->next; }
current_folder->next = folder;
}
}
return folder;
}
file_t *create_file(char *name, char *type, folder_t *parent) {
file_t *file = alloc(sizeof(file_t));
file->data = NULL;
file->size = 0;
strcpy(file->name, name);
strcpy(file->type, type);
file->next = NULL;
if (parent->files == NULL) {
parent->files = file;
} else {
file_t *current_file = parent->files;
while (current_file->next != NULL) { current_file = current_file->next; }
current_file->next = file;
}
return file;
}
void write_file(file_t *file, void *data, size_t size) {
file->data = realloc(file->data, file->size + size);
memcpy(file->data + file->size, data, size);
file->size += size;
}
file_t *add_file(char *name, char *type, folder_t *folder, void *data, size_t size) {
file_t *file = create_file(name, type, folder);
write_file(file, data, size);
return file;
}
void read_file(file_t *file, char *buffer, size_t size) {
memcpy(buffer, file->data, size);
}
void delete_file(file_t *file) {
if (file->data != NULL) { free(file->data); }
if (file != NULL) { free(file); }
}
void delete_folder(folder_t *folder) {
if (folder == NULL) { return; }
while (folder->files != NULL) {
file_t *file = folder->files;
folder->files = file->next;
delete_file(file);
}
while (folder->child != NULL) {
folder_t *child_folder = folder->child;
folder->child = child_folder->next;
delete_folder(child_folder);
}
if (folder->parent == NULL) {
root_folder = NULL;
} else {
folder_t *parent_folder = folder->parent;
if (parent_folder->child == folder) {
parent_folder->child = folder->next;
} else {
folder_t *current_folder = parent_folder->child;
while (current_folder->next != folder) { current_folder = current_folder->next; }
current_folder->next = folder->next;
}
}
free(folder);
}
void print_folder_contents(folder_t *folder, size_t depth) {
for (size_t i = 0; i < depth; i++) { log_printf("\t"); }
log_printf("- %s/\n", folder->name);
file_t *file = folder->files;
while (file != NULL) {
for (size_t i = 0; i < depth + 1; i++) { log_printf("\t"); }
log_printf("- %8s %4s | %8u килобайт\n", file->name, file->type, (file->size + 1024) / 1024);
file = file->next;
}
folder_t *child_folder = folder->child;
while (child_folder != NULL) {
print_folder_contents(child_folder, depth + 1);
child_folder = child_folder->next;
}
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
create_folder("", NULL);
cache_f = create_folder("cache", root_folder);
docs_f = create_folder("docs", root_folder);
media_f = create_folder("media", root_folder);
mod_f = create_folder("mod", root_folder);
file_t *readme = create_file("readme", "txt", root_folder);
write_file(readme, "БМПОС 2023-2024", 21);
return (module_info_t){
.name = (char *)"[FS][IMFS]",
.message = (char *)"IMFS (in memory filesystem) - файловая система работающая исключительно в ОЗУ.",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0
};
}

View File

@ -1,17 +0,0 @@
#/bin/sh
echo "Название: IOS"
echo "Лицензия: CC BY-NC 4.0"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o ios.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld ios.o -L../../modlib/lib/ -lmod -o ios.ko
cp ios.ko ../bin/
echo "Сборка завершена, файл: ios.ko"

View File

@ -1,115 +0,0 @@
#include <system.h>
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) {
log_printf("Клавиатура не найдена!\n");
delete_thread( );
for (;;) { asm volatile("hlt"); }
}
getc = kbd_mod->get_func(2);
while (1) {
log_printf("Доступные программы:\n");
for (uint64_t i = 0; i < app_count; i++) { log_printf(" %2u. %s\n", i, app_list[i].name); }
log_printf(" %2u. Выход\n", app_count + 1);
log_printf("[IOS]>");
char c = '\0';
do { c = getc( ); } while (!is_digit(c));
log_printf(" %c\n", c);
int select = char_to_digit(c);
if (select == app_count + 1) {
log_printf("Выход\n");
delete_thread( );
for (;;) { asm volatile("hlt"); }
}
if (select > app_count - 1) {
log_printf("Ошибка! %u не входит в список\n");
continue;
}
log_printf("Запуск %s...\n", app_list[select].name);
int (*app)( ) = (int (*)( ))app_list[select].data;
int ret = (*app)( );
log_printf("\nПриложение %s завершилось с кодом: %d\n", app_list[select].name, ret);
}
}
static void main( ) {
log_printf("IOS (input-output shell) - оболочка ввода-вывода\n");
mod_count = alloc(sizeof(uint64_t));
mod_list = mod_list_get(mod_count);
app_list = alloc((*mod_count) * sizeof(module_info_t));
if (app_list == NULL) {
log_printf("Ошибка выделения памяти для app_list!\n");
delete_thread( );
for (;;) { asm volatile("hlt"); }
}
app_count = 0;
for (uint64_t i = 0; i < *mod_count; i++) {
if (str_contains(mod_list[i].name, "[APP]")) {
// log_printf("%u. %s\n", app_count, mod_list[i].name);
app_list[app_count] = mod_list[i];
app_count++;
}
}
free(mod_count);
if (app_count < 1) {
log_printf("Модулей-программ не обнаружено!\n");
free(app_list);
delete_thread( );
} else {
app_list = realloc(app_list, app_count * sizeof(module_info_t));
ios_main( );
for (;;) { asm volatile("hlt"); }
}
for (;;) { asm volatile("hlt"); }
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
return (module_info_t){ .name = (char *)"[IOS]",
.message = (char *)"IOS (input-output shell) - оболочка ввода-вывода.",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = main };
}

View File

@ -1,37 +0,0 @@
ENTRY(init)
SECTIONS
{
. = 0x1000;
start = .;
.text BLOCK(4K) : ALIGN(4K) {
code = .;
*(.minit)
*(.text)
}
.rodata BLOCK(4K) : ALIGN(4K) {
*(.rodata)
}
.data BLOCK(4K) : ALIGN(4K) {
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K) {
*(COMMON)
*(.bss)
}
.eh_frame BLOCK(4K) : ALIGN(4K) {
*(.eh_frame)
}
end = .;
/DISCARD/ : {
*(.comment)
*(.note.gnu.build-id)
}
}

View File

@ -1,9 +0,0 @@
[
{
"info": "Официальный репозиторий модулей",
"git": "https://git.synapseos.ru/Aren/BMOSP_repo.git",
"list": [
"https://git.synapseos.ru/Aren/BMOSP_repo/raw/branch/master/list.json"
]
}
]

7
modules/music/build.sh Executable file
View File

@ -0,0 +1,7 @@
#/bin/sh
echo "Название: Мелодия из тетриса"
echo "Лицензия: Публичное достояние"
gcc -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o music.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib music.o -o music.ko
cp music.ko ../bin/
echo "Сборка завершена, файл: music.ko"

65
modules/music/main.c Normal file
View File

@ -0,0 +1,65 @@
#include <system.h>
static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void usleep(uint64_t ticks) {
for (uint64_t i = 0; i < ticks * 100; i++) { asm volatile("pause"); }
}
static inline void play_sound(unsigned int frequency) {
uint32_t div;
uint8_t tmp;
// Устанавливаем частоту таймера
div = 1193180 / frequency;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)(div));
outb(0x42, (uint8_t)(div >> 8));
// Воспроизводим мелодию
tmp = inb(0x61);
if (tmp != (tmp | 3)) { outb(0x61, tmp | 3); }
}
static void nosound( ) {
uint8_t tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
}
module_info_t init(env_t *env) {
init_env(env);
fb_printf("Программа инициализирована!\n");
return (module_info_t){
.name = (char *)"Мелодия",
.message = (char *)"Надеюсь скоро тут будет тетрис!",
.err_code = 404,
};
// Массив с нотами
unsigned int tetris_notes[] = { 0 };
// Расчет количества нот в мелодии
uint64_t num_notes = sizeof(tetris_notes) / sizeof(tetris_notes[0]);
// Начальное значение для подсчета времени
int note_duration = 1000000; // 1 секунда
// Зацикленное воспроизведение мелодии в течение минуты
for (uint64_t i = 0; i < num_notes; i++) {
// Воспроизведение ноты с заданным временем
play_sound(tetris_notes[i]);
usleep(note_duration);
// Уменьшение времени для следующей ноты
note_duration -= note_duration / 24; // Уменьшение на 1/24 каждый раз
}
}

20
modules/pci/build.sh Executable file → Normal file
View File

@ -1,23 +1,7 @@
#/bin/sh
echo "Название: PCI"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o pci.o
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c pci_data.c -o pci_data.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld pci.o -L../../modlib/lib/ -lmod -o pci.ko
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld pci_data.o -L../../modlib/lib/ -lmod -o pci_data.ko
gcc -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o pci.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib pci.o -o pci.ko
cp pci.ko ../bin/
cp pci_data.ko ../bin/
cp pci_vendors.txt ../bin/
echo "Сборка завершена, файл: pci.ko"

View File

@ -5,72 +5,54 @@ typedef struct {
uint16_t id;
} vendor_t;
static vendor_t **vendor_list;
static uint64_t num_vendors;
static char *find_vendor(uint16_t id) {
for (uint64_t i = 0; i < num_vendors; i++) {
if (vendor_list[i]->id == id) { return vendor_list[i]->name; }
}
return "Нет в базе";
static inline uint32_t inl(uint16_t port) {
uint32_t data;
asm volatile("inl %1, %0" : "=a"(data) : "Nd"(port));
return data;
}
static inline uint16_t pci_read_word(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset) {
static inline void outl(uint16_t port, uint32_t data) {
asm volatile("outl %0, %1" : : "a"(data), "Nd"(port));
}
static inline uint16_t pci_read_word(uint16_t bus, uint16_t slot, uint16_t func,
uint16_t offset) {
uint64_t address;
uint64_t lbus = (uint64_t)bus;
uint64_t lslot = (uint64_t)slot;
uint64_t lfunc = (uint64_t)func;
uint16_t tmp = 0;
address = (uint64_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) | ((uint32_t)0x80000000));
address = (uint64_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) |
(offset & 0xFC) | ((uint32_t)0x80000000));
outl(0xCF8, address);
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
return (tmp);
}
static inline uint16_t get_vendor_id(uint16_t bus, uint16_t slot, uint16_t function) {
uint32_t r0 = pci_read_word(bus, slot, function, 0);
static inline uint16_t get_vendor_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0);
return r0;
}
static inline uint16_t get_device_id(uint16_t bus, uint16_t slot, uint16_t function) {
uint32_t r0 = pci_read_word(bus, slot, function, 2);
static inline uint16_t get_device_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 2);
return r0;
}
static inline uint16_t get_class_id(uint16_t bus, uint16_t slot, uint16_t function) {
uint32_t r0 = pci_read_word(bus, slot, function, 0xA);
static inline uint16_t get_class_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
return (r0 & ~0x00FF) >> 8;
}
static inline uint16_t get_sub_class_id(uint16_t bus, uint16_t slot, uint16_t function) {
uint32_t r0 = pci_read_word(bus, slot, function, 0xA);
static inline uint16_t get_sub_class_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
return (r0 & ~0xFF00);
}
static char *get_class_name(uint16_t number) {
switch (number) {
case 0x0: return "Неклассифицирован";
case 0x1: return "Контроллер устройства хранения";
case 0x2: return "Контроллер сети";
case 0x3: return "Контроллер дисплея";
case 0x4: return "Мультимедийный контроллер";
case 0x5: return "Контроллер памяти";
case 0x6: return "Мост";
case 0x7: return "Простой коммуникационный контроллер";
case 0x8: return "Периферийное устройство базовой системы";
case 0x9: return "Устройство ввода";
case 0xA: return "Док-станция";
case 0xB: return "Процессор";
case 0xC: return "Контроллер последовательной шины";
case 0xD: return "Беспроводной контроллер";
case 0xE: return "Интеллектуальный контроллер ввода/вывода";
case 0xF: return "Контроллер спутниковой связи";
case 0x10: return "Контроллер шифрования/дешифрования";
case 0x11: return "Контроллер сбора данных и обработки сигналов";
default: return "Неизвестный";
}
}
static inline void scan( ) {
uint64_t devices = 0;
for (uint32_t bus = 0; bus < 256; bus++) {
@ -83,61 +65,21 @@ static inline void scan( ) {
uint16_t device_id = get_device_id(bus, slot, function);
uint16_t class_id = get_class_id(bus, slot, function);
uint16_t status = pci_read_word(bus, slot, function, 0x6);
/*
uint32_t mem_addr_0 = pci_read_word(bus, slot, function, 0x1C);
uint32_t mem_addr_1 = pci_read_word(bus, slot, function, 0x24);
uint32_t mem_lim_0 = pci_read_word(bus, slot, function, 0x20);
uint32_t mem_lim_1 = pci_read_word(bus, slot, function, 0x28);
uint32_t io_addr_0 = pci_read_word(bus, slot, function, 0x2C);
uint32_t io_addr_1 = pci_read_word(bus, slot, function, 0x34);
uint32_t io_lim_0 = pci_read_word(bus, slot, function, 0x30);
uint32_t io_lim_1 = pci_read_word(bus, slot, function, 0x38);
*/
fb_printf("[%u] vendor: 0x%x, device: 0x%x, class: %u\n",
devices, vendor, device_id, class_id);
char *name = find_vendor(vendor);
log_printf("[%4u] %4x [%10s], устройство: %x, %u.%u.%u | ", devices, vendor, name, device_id, bus, slot,
function);
log_printf("%32s", get_class_name(class_id));
/*
log_printf(" | %8x : %8x", mem_addr_0, mem_lim_0);
log_printf(" | %8x : %8x", mem_addr_1, mem_lim_1);
log_printf(" | %8x : %8x", io_addr_0, io_lim_0);
log_printf(" | %8x : %8x", io_addr_1, io_lim_1);
*/
log_printf(" | %4x\n", status);
devices++;
}
}
}
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
module_info_t init(env_t *env) {
init_env(env);
module_info_t *pci_data = get_module("[PCI][ADAPTER]");
if (pci_data == NULL) {
log_printf("Адаптер PCI данных не найден!\n");
num_vendors = 0;
} else {
num_vendors = pci_data->data_size - 1;
log_printf("Записей в базе PCI: %u\n", pci_data->data_size);
vendor_list = (vendor_t **)pci_data->data;
}
scan( );
return (module_info_t){ .name = (char *)"[PCI]",
.message = (char *)"PCI драйвер",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 };
return (module_info_t){
.name = (char *)"[PCI]",
.message = (char *)"PCI драйвер",
.err_code = 0,
};
}

View File

@ -1,85 +0,0 @@
#include <system.h>
typedef struct {
char *name;
uint16_t id;
} vendor_t;
static vendor_t **parse_file(char *str, uint64_t num_vendors, uint64_t size) {
vendor_t **vendor_list = (vendor_t **)alloc(num_vendors * sizeof(vendor_t *));
if (vendor_list == NULL) { return NULL; }
for (uint64_t i = 0; i < num_vendors; i++) { vendor_list[i] = (vendor_t *)alloc(sizeof(vendor_t)); }
uint64_t i = 0;
char *line = alloc(strlen(str) + 1);
char *temp = alloc(strlen(str) + 1);
if (line == NULL) { return NULL; }
if (temp == NULL) { return NULL; }
strcpy(line, str);
while (line != NULL && i < num_vendors) {
temp = realloc(temp, strlen(line) + 1);
strcpy(temp, line);
char *name = trstr(temp, ';');
char *id_str = strtok(temp, ";");
name = strtok(name, "\n");
name[strlen(name) - 1] = '\0';
if (id_str != NULL && name != NULL) {
vendor_list[i]->id = strtol(id_str, NULL, 16);
vendor_list[i]->name = name;
i++;
}
temp = trstr(line, '\n');
strcpy(line, temp);
}
if (i != num_vendors) {
for (uint64_t j = 0; j < i; j++) { free(vendor_list[j]->name); }
free(vendor_list);
free(line);
free(temp);
return NULL;
}
free(line);
free(temp);
return vendor_list;
}
static void print_vendors(uint64_t num_vendors, vendor_t **vendor_list) {
for (uint64_t i = 0; i < num_vendors; i++) {
vendor_t *vendor = vendor_list[i];
log_printf("ID: 0x%x, Name: %s\n", vendor->id, vendor->name);
}
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
module_info_t *pci_data = get_module("[PCI][DATA][VENDORS]");
if (pci_data == NULL) { log_printf("База PCI не найдена!\n"); }
uint64_t num_vendors = count_chars(pci_data->data, ';');
log_printf("Количество вендоров: %u\n", num_vendors);
vendor_t **vendor_list = parse_file(pci_data->data, num_vendors, pci_data->data_size);
// print_vendors(num_vendors, vendor_list);
return (module_info_t){ .name = (char *)"[PCI][ADAPTER]",
.message = (char *)"PCI данные",
.type = 0,
.data_size = num_vendors,
.data = vendor_list,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 };
}

View File

@ -1,26 +0,0 @@
1002;AMD
1022;AMD
106B;Apple Inc.
10DE;NVIDIA
10EC;Realtek
10FA;Truevision
1234;Technical
1274;Ensoniq
1344;Micron
1462;MSI
15AD;VMware
1AF4;Red Hat
1B36;Red Hat
1D6B;Linux Foundation
1FFF;MCST
2646;Kingston Technology
5143;Qualcomm
8086;Intel
80EE;VirtualBox
8800;5553535
BEEF;Tasty and point
8966;SynapseOS
C0A9;Micron/Crucial
CAFE;TR&D
DADA;Are you mentally healthy?
DEAD;Page Fault inc.

View File

@ -0,0 +1,7 @@
#/bin/sh
echo "Название: список устройств и производителей для PCI"
echo "Лицензия: Публичное достояние"
gcc -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o pci_data.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib pci_data.o -o pci_data.ko
cp pci_data.ko ../bin/
echo "Сборка завершена, файл: pci_data.ko"

18
modules/pci_data/main.c Normal file
View File

@ -0,0 +1,18 @@
#include <system.h>
typedef struct {
char *name;
uint16_t id;
} vendor_t;
vendor_t vendor_list[] = { { "Intel", 0x8086 },
{ "AMD", 0x1002 },
{ "AMD", 0x1002 } };
module_info_t init(env_t *env) {
init_env(env);
return (module_info_t){ .name = (char *)"[PCI][DATA]",
.message = (char *)"PCI данные",
.data_size = 3,
.data = &vendor_list };
}

View File

@ -1,19 +0,0 @@
#/bin/sh
echo "Название: PS/2"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o ps2.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld ps2.o -L../../modlib/lib/ -lmod -o ps2.ko
cp ps2.ko ../bin/
echo "Сборка завершена, файл: ps2.ko"

View File

@ -1,165 +0,0 @@
#include "special.h"
static char en_chars_lower[] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 19 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter */
0, /* Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
'm', ',', '.', '/', 0, /* Right shift */
'*', 0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 */
0, /* F2 */
0, /* F3 */
0, /* F4 */
0, /* F5 */
0, /* F6 */
0, /* F7 */
0, /* F8 */
0, /* F9 */
0, /* F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home */
0, /* Up Arrow */
0, /* Page Up */
'-', 0, /* Left Arrow */
0, 0, /* Right Arrow */
'+', 0, /* 79 - End */
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert */
0, /* Delete */
0, 0, 0, 0, /* F11 */
0, /* F12 */
0, /* NULL */
};
static char en_chars_shifted[] = {
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
'(', ')', '_', '+', '\b', /* Backspace */
'\t', /* Tab */
'Q', 'W', 'E', 'R', /* 19 */
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter */
0, /* 29 - Control */
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
'"', '~', 0, /* Left shift */
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */
'M', '<', '>', '?', 0, /* Right shift */
'*', 0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 */
0, /* F2 */
0, /* F3 */
0, /* F4 */
0, /* F5 */
0, /* F6 */
0, /* F7 */
0, /* F8 */
0, /* F9 */
0, /* F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home */
0, /* Up Arrow */
0, /* Page Up */
'-', 0, /* Left Arrow */
0, 0, /* Right Arrow */
'+', 0, /* 79 - End */
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert */
0, /* Delete */
0, 0, 0, 0, /* F11 */
0, /* F12 */
0, /* NULL */
};
static char ru_chars_lower[] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'й', 'ц', 'у', 'к', /* 19 */
'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ', '\n', /* Enter */
0, /* Control */
'ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', /* 39 */
'э', 'ё', 0, /* Left shift */
'\\', 'я', 'ч', 'с', 'м', 'и', 'т', /* 49 */
'ь', 'б', 'ю', '.', 0, /* Right shift */
'*', 0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 */
0, /* F2 */
0, /* F3 */
0, /* F4 */
0, /* F5 */
0, /* F6 */
0, /* F7 */
0, /* F8 */
0, /* F9 */
0, /* F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home */
0, /* Up Arrow */
0, /* Page Up */
'-', 0, /* Left Arrow */
0, 0, /* Right Arrow */
'+', 0, /* 79 - End */
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert */
0, /* Delete */
0, 0, 0, 0, /* F11 */
0, /* F12 */
0, /* NULL */
};
static char ru_chars_shifted[] = {
0, 27, '!', '\"', '', ';', '%', ':', '?', '*', /* 9 */
'(', ')', '_', '+', '\b', /* Backspace */
'\t', /* Tab */
'Й', 'Ц', 'У', 'К', /* 19 */
'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ', '\n', /* Enter */
0, /* 29 - Control */
'Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', /* 39 */
'Э', 'Ё', 0, /* Left shift */
'\\', 'Я', 'Ч', 'С', 'М', 'И', 'Т', /* 49 */
'Ь', 'Б', 'Ю', ',', 0, /* Right shift */
'*', 0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 */
0, /* F2 */
0, /* F3 */
0, /* F4 */
0, /* F5 */
0, /* F6 */
0, /* F7 */
0, /* F8 */
0, /* F9 */
0, /* F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home */
0, /* Up Arrow */
0, /* Page Up */
'-', 0, /* Left Arrow */
0, 0, /* Right Arrow */
'+', 0, /* 79 - End */
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert */
0, /* Delete */
0, 0, 0, 0, /* F11 */
0, /* F12 */
0, /* NULL */
};

View File

@ -1,164 +0,0 @@
#include "keymap.h"
#include <system.h>
static uint8_t current_state;
static bool kbd_free = false;
static int ru = 1;
static char c_char = '\0';
static key_event_t keyboard_buffer;
static void virt_exit( ) {
outw(0x604, 0x2000);
outw(0x4004, 0x3400);
outw(0x600, 0x34);
}
static void wait_irq( ) {
while (!kbd_free) { asm volatile("pause"); }
kbd_free = false;
}
static char getkey( ) {
wait_irq( );
return c_char;
}
static char getc( ) {
__repeat:
wait_irq( );
if (c_char >= '0' && c_char <= '9') { return c_char; }
if (c_char >= 'A' && c_char <= 'Z') { return c_char; }
if (c_char >= 'a' && c_char <= 'z') { return c_char; }
if (c_char >= 'А' && c_char <= 'Я') { return c_char; }
if (c_char >= 'а' && c_char <= 'я') { return c_char; }
goto __repeat;
}
static void *__get_func(uint64_t func) {
switch (func) {
case 0: return wait_irq;
case 1: return getkey;
case 2: return getc;
default: return NULL;
}
}
static void after_interrupt( ) {
uint8_t status = inb(0x61) | 1;
outb(0x61, status);
}
static int is_shift(uint8_t scancode) {
switch (scancode) {
case 0x2A: // Левый SHIFT
case 0x36: // Правый SHIFT
return 1;
default: // Другой символ
return 0;
}
}
static int is_ctrl(uint8_t scancode) {
switch (scancode) {
case 0x1D: // Левый или правый CTRL
return 1;
default: // Другой символ
return 0;
}
}
static void handler( ) {
while (!(inb(0x64) & 1)) { asm volatile("pause"); }
uint8_t scancode = inb(0x60);
char c = '\0';
switch (scancode) {
case 0x01:
log_printf("ВЫХОД\n");
virt_exit( );
break; // Клавиша "ESCAPE"
case 0x4F: // Клавиша "END"
log_printf("END?\n");
break;
default: break;
}
if (scancode == 0xE0) {
current_state = PREFIX_STATE;
after_interrupt( );
return;
}
if (scancode < 0) {
after_interrupt( );
return;
}
if (scancode == 0xAA || scancode == 0xB6) { // Отпущена клавиша SHIFT
keyboard_buffer.shift_pressed = 0;
after_interrupt( );
return;
}
if (scancode == 0x9D) { // Отпущена клавиша CTRL
keyboard_buffer.ctrl_pressed = 0;
after_interrupt( );
return;
}
if (is_shift(scancode)) { // Нажата клавиша SHIFT
keyboard_buffer.shift_pressed = 1;
after_interrupt( );
return;
}
if (is_ctrl(scancode)) { // Нажата клавиша CTRL
keyboard_buffer.ctrl_pressed = 1;
after_interrupt( );
return;
}
if (current_state == PREFIX_STATE) { current_state = NORMAL_STATE; }
if (ru) {
if (keyboard_buffer.shift_pressed && !keyboard_buffer.ctrl_pressed) {
c = ru_chars_shifted[scancode];
} else {
c = ru_chars_lower[scancode];
}
} else {
if (keyboard_buffer.shift_pressed && !keyboard_buffer.ctrl_pressed) {
c = en_chars_shifted[scancode];
} else {
c = en_chars_lower[scancode];
}
}
c_char = c;
kbd_free = true;
after_interrupt( );
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
current_state = NORMAL_STATE;
keyboard_buffer.ctrl_pressed = 0;
keyboard_buffer.shift_pressed = 0;
return (module_info_t){ .name = (char *)"[KEYBOARD]",
.message = (char *)"PS/2 драйвер",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 33,
.irq_handler = &handler,
.get_func = __get_func };
}

View File

@ -1,18 +0,0 @@
#include <system.h>
#define MAX_KEY_BUFFER_SIZE 1
#define NORMAL_STATE 0
#define PREFIX_STATE 1
typedef struct {
uint8_t code;
bool ctrl_pressed;
bool alt_pressed;
bool shift_pressed;
bool sys_menu_pressed;
} key_event_t;
typedef struct {
uint8_t code;
uint8_t c;
} keyboard_char_t;

14
modules/simd/build.sh Executable file → Normal file
View File

@ -1,17 +1,7 @@
#/bin/sh
echo "Название: SIMD"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o simd.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld simd.o -L../../modlib/lib/ -lmod -o simd.ko
gcc -I../../modlib -O0 -finput-charset=UTF-8 -fexec-charset=cp1251 -c -fPIC -nostdlib main.c -o simd.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib simd.o -o simd.ko
cp simd.ko ../bin/
echo "Сборка завершена, файл: simd.ko"

View File

@ -2,42 +2,34 @@
static char fxsave_region[512] __attribute__((aligned(16)));
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
module_info_t init(env_t *env) {
init_env(env);
uint32_t eax, ebx, ecx, edx;
cpuid(1, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) {
asm volatile("finit");
log_printf("FPU(x87) поддерживается!\n");
}
if ((edx >> 23) & 1) { log_printf("MMX поддерживается!\n"); }
if ((edx >> 23) & 1) { env->fb_printf("MMX поддерживается!\n"); }
if ((edx >> 25) & 1) {
log_printf("SSE2 поддерживается!\n");
log_printf("Адрес региона fxsave 0x%x\n", &fxsave_region);
env->fb_printf("SSE2 поддерживается!\n");
env->fb_printf("Адрес региона fxsave 0x%x\n", &fxsave_region);
asm volatile(" fxsave %0 " ::"m"(fxsave_region));
uint32_t sse_version = (ecx >> 25) & 0x7;
log_printf("SSE%u включен\n", sse_version);
env->fb_printf("SSE%u включен\n", sse_version);
}
if ((ecx >> 28) & 1) { log_printf("AVX поддерживается!\n"); }
if ((ecx >> 28) & 1) { env->fb_printf("AVX поддерживается!\n"); }
return (module_info_t){ .name = (char *)"SIMD",
.message = (char *)"SIMD инструкции",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 };
return (module_info_t){
.name = (char *)"SIMD",
.message = (char *)"SIMD инструкции",
.err_code = 0,
};
}

View File

@ -1,19 +0,0 @@
#/bin/sh
echo "Название: TGA"
echo "Лицензия: Публичное достояние"
CC=${CC:-gcc}
ARCH_FLAGS="-fno-stack-protector -ffreestanding -O0 -g -fPIC -static -nostdlib "
if [ -d "../../sdk" ]; then
CC="../../sdk/bin/x86_64-elf-gcc"
fi
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o tga.o
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld tga.o -L../../modlib/lib/ -lmod -o tga.ko
cp boot.jpg ../bin/
cp boot.tga ../bin/
cp tga.ko ../bin/
echo "Сборка завершена, файл: tga.ko"

View File

@ -1,189 +0,0 @@
#include <system.h>
#define TGA_ERR( ) log_printf("Ошибка декодирования TGA на строчке: %u\n", __LINE__);
typedef struct {
unsigned char magic1; // должно быть нулевым
unsigned char colormap; // должно быть нулевым
unsigned char encoding; // должно быть 2
unsigned short cmaporig, cmaplen; // должны быть нулевыми
unsigned char cmapent; // должно быть нулевым
unsigned short x; // должно быть нулевым
unsigned short y; // высота изображения
unsigned short h; // высота изображения
unsigned short w; // ширина изображения
unsigned char bpp; // должно быть 32
unsigned char pixeltype; // должно быть 40
} __attribute__((packed)) tga_header_t;
static unsigned int *tga_parse(unsigned char *ptr, int size) {
unsigned int *data;
int i, j, k, x, y, w = (ptr[13] << 8) + ptr[12], h = (ptr[15] << 8) + ptr[14], o = (ptr[11] << 8) + ptr[10];
int m = ((ptr[1] ? (ptr[7] >> 3) * ptr[5] : 0) + 18);
if (w < 1 || h < 1) return NULL;
data = (unsigned int *)alloc((w * h + 2) * sizeof(unsigned int));
if (!data) { return NULL; }
memset(data, 0, (w * h + 2) * sizeof(unsigned int));
switch (ptr[2]) {
case 1:
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 || (ptr[7] != 24 && ptr[7] != 32)) {
TGA_ERR( );
free(data);
return NULL;
}
for (y = i = 0; y < h; y++) {
k = ((!o ? h - y - 1 : y) * w);
for (x = 0; x < w; x++) {
j = ptr[m + k++] * (ptr[7] >> 3) + 18;
data[2 + i++] =
((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) | (ptr[j + 2] << 16) | (ptr[j + 1] << 8) | ptr[j];
}
}
break;
case 2:
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 || (ptr[16] != 24 && ptr[16] != 32)) {
TGA_ERR( );
free(data);
return NULL;
}
for (y = i = 0; y < h; y++) {
j = ((!o ? h - y - 1 : y) * w * (ptr[16] >> 3));
for (x = 0; x < w; x++) {
data[2 + i++] =
((ptr[16] == 32 ? ptr[j + 3] : 0xFF) << 24) | (ptr[j + 2] << 16) | (ptr[j + 1] << 8) | ptr[j];
j += ptr[16] >> 3;
}
}
break;
case 9:
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 || (ptr[7] != 24 && ptr[7] != 32)) {
TGA_ERR( );
free(data);
return NULL;
}
y = i = 0;
for (x = 0; x < w * h && m < size;) {
k = ptr[m++];
if (k > 127) {
k -= 127;
x += k;
j = ptr[m++] * (ptr[7] >> 3) + 18;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] = ((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) | (ptr[j + 2] << 16) |
(ptr[j + 1] << 8) | ptr[j];
}
} else {
k++;
x += k;
while (k--) {
j = ptr[m++] * (ptr[7] >> 3) + 18;
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] = ((ptr[7] == 32 ? ptr[j + 3] : 0xFF) << 24) | (ptr[j + 2] << 16) |
(ptr[j + 1] << 8) | ptr[j];
}
}
}
break;
case 10:
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 || (ptr[16] != 24 && ptr[16] != 32)) {
TGA_ERR( );
free(data);
return NULL;
}
y = i = 0;
for (x = 0; x < w * h && m < size;) {
k = ptr[m++];
if (k > 127) {
k -= 127;
x += k;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] = ((ptr[16] == 32 ? ptr[m + 3] : 0xFF) << 24) | (ptr[m + 2] << 16) |
(ptr[m + 1] << 8) | ptr[m];
}
m += ptr[16] >> 3;
} else {
k++;
x += k;
while (k--) {
if (!(i % w)) {
i = ((!o ? h - y - 1 : y) * w);
y++;
}
data[2 + i++] = ((ptr[16] == 32 ? ptr[m + 3] : 0xFF) << 24) | (ptr[m + 2] << 16) |
(ptr[m + 1] << 8) | ptr[m];
m += ptr[16] >> 3;
}
}
}
break;
default: {
TGA_ERR( );
free(data);
return NULL;
}
}
data[0] = w;
data[1] = h;
return data;
}
static void *handler(uint64_t func) {
switch (func) {
case 0: return tga_parse;
default: return NULL;
}
}
module_info_t __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
module_info_t *boot_tga = get_module("[BOOTIMG]");
if (boot_tga != NULL) {
#if 0
framebuffer_t screen = alloc_framebuffer( );
uint32_t *screen_buf = screen.address;
uint32_t *img = tga_parse(boot_tga->data, boot_tga->data_size);
uint32_t width = img[0];
uint32_t height = img[1];
uint32_t *img_data = (uint32_t *)img + 2;
for (uint32_t w = 0; w < width; w++) {
for (uint32_t h = 0; h < height; h++) {
if (*img_data == 0x013220) {
*img_data++;
continue;
}
screen_buf[w * height + h] = *img_data++;
}
}
#endif
}
return (module_info_t){ .name = (char *)"[MEDIA][TGA]",
.message = (char *)"Отрисовка TGA изображений",
.type = 0,
.data_size = 0,
.data = (void *)0,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = handler };
}

173
pbuild.py Normal file
View File

@ -0,0 +1,173 @@
import os
import shutil
import subprocess
import time
from multiprocessing import Pool
ARCH_FLAGS = "-m64 -march=x86-64 -mabi=sysv -mno-red-zone -mcmodel=kernel -MMD -MP"
WARN_FLAGS = "-Wall -Wextra -nostdlib "
STANDART_FLAGS = "-std=gnu11"
PROTECT_FLAGS = "-O0 -pipe -ffreestanding -fno-stack-protector -fno-lto -fno-stack-check -fno-PIC -fno-PIE"
CHARSET_FLAGS = "-finput-charset=UTF-8 -fexec-charset=cp1251"
LIBS_FLAGS = "-Ilimine -Iinclude"
def version_build():
with open("include/version.h", "r") as file:
lines = file.readlines()
major = 0
minor = 0
build = 0
with open("include/version.h", "w") as file:
for line in lines:
if line.startswith("#define VERSION_BUILD"):
parts = line.split()
build = int(parts[2]) + 1
if build > 999:
build = 0
minor += 1
file.write(f"#define VERSION_MINOR {minor}\n")
file.write(f"#define VERSION_BUILD {build}\n")
elif line.startswith("#define VERSION_MAJOR"):
parts = line.split()
major = int(parts[2])
file.write(line)
elif line.startswith("#define VERSION_MINOR"):
parts = line.split()
minor = int(parts[2])
file.write(line)
else:
file.write(line)
return [major, minor, build]
def sort_strings(strings):
return sorted(strings, key=lambda x: not x.endswith('.s.o'))
def find_files(directory, extensions):
file_list = []
for root, dirs, files in os.walk(directory):
for file in files:
if any(file.endswith(extension) for extension in extensions):
file_list.append(os.path.join(root, file))
return file_list
def compile(file: str):
CC = "gcc"
output_file = file.replace('/', '_')
obj_file = f"bin/{output_file}.o"
cmd = f"{CC} {WARN_FLAGS} {PROTECT_FLAGS} {ARCH_FLAGS} {CHARSET_FLAGS} {LIBS_FLAGS} -c {file} -o {obj_file}"
print(cmd)
os.system(cmd)
return obj_file
def compile_all():
file_list = find_files("kernel/", [".s", ".cpp", ".c"])
file_list += find_files("kernel/*/*", [".s", ".cpp", ".c"])
with Pool() as pool:
results = pool.map(compile, file_list)
while not all(results):
print(results)
time.sleep(1)
print(results)
cmd = f"ld -nostdlib -static -m elf_x86_64 -z max-page-size=0x1000 -T configs/linker.ld -o kernel.elf {' '.join(sort_strings(results))}"
print(cmd)
os.system(cmd)
def check_limine():
if not os.path.isdir("limine"):
subprocess.run(["git", "clone", "https://git.synapseos.ru/Aren/limine.git", "--branch=v5.x-branch-binary", "--depth=1"])
else:
os.chdir("limine")
subprocess.run(["git", "pull"])
os.chdir("..")
os.chdir("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:
linux_distro = platform.linux_distribution()[0]
if linux_distro.lower() in ['debian', 'ubuntu']:
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")
os.system(f"sgdisk {IMAGE_NAME}.hdd -n 1:2048 -t 1:ef00")
os.system(f"./limine/limine bios-install {IMAGE_NAME}.hdd")
os.system(f"mformat -i {IMAGE_NAME}.hdd@@1M")
os.system(f"mmd -i {IMAGE_NAME}.hdd@@1M ::/mod ::/EFI ::/EFI/BOOT")
os.system(f"mcopy -i {IMAGE_NAME}.hdd@@1M kernel.elf configs/limine.cfg limine/limine-bios.sys ::/")
os.system(f"mcopy -i {IMAGE_NAME}.hdd@@1M modules/bin/*.ko ::/mod")
os.system(f"mcopy -i {IMAGE_NAME}.hdd@@1M limine/BOOTX64.EFI limine/BOOTIA32.EFI ::/EFI/BOOT")
os.system(f"mcopy -i {IMAGE_NAME}.hdd@@1M boot.jpg boot.tga ::/")
os.system(f"./limine/limine bios-install {IMAGE_NAME}.hdd")
def create_iso(IMAGE_NAME):
os.system(f"rm -f {IMAGE_NAME}.iso")
os.system(f"rm -rf iso_root")
os.system(f"mkdir -p iso_root")
os.system(f"cp -v kernel.elf boot.jpg boot.tga configs/limine.cfg limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/")
os.system(f"mkdir -p iso_root/EFI/BOOT")
shutil.copytree("modules/bin", "iso_root/mod")
os.system(f"cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/")
os.system(f"cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/")
os.system(f"xorriso -as mkisofs -b limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label iso_root -o {IMAGE_NAME}.iso")
os.system(f"./limine/limine bios-install {IMAGE_NAME}.iso")
if __name__ == "__main__":
os.system("""find . \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) -print0 | xargs -0 clang-format -i -style=file""")
subprocess.run(["rm", "-rf", "bin"])
subprocess.run(["mkdir", "-p", "bin"])
if not os.path.isdir("ovmf"):
subprocess.run(["mkdir", "-p", "ovmf"])
os.chdir("ovmf")
subprocess.run(["curl", "-Lo", "OVMF.fd", "https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd"])
os.chdir("..")
if not os.path.isdir("limine"):
check_limine()
check_tools()
major, minor, build = version_build()
compile_all()
create_iso("bmosp")
create_hdd("bmosp")
print(f"Не забудьте сохранить изменения! Номер сборки: {major}.{minor}.{build}")

9
run.sh
View File

@ -1,12 +1,5 @@
#!/bin/sh
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 \
-rtc base=localtime,clock=host \
--no-reboot -no-shutdown \
-net nic,model=pcnet # AMD PCnet Am79C970
#qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -hda bmosp.hdd --no-reboot
qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -hda bmosp.hdd --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -cdrom bmosp.iso -boot d --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd -d int --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu host -m 1G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd

6
scripts/build_sdk.sh Executable file → Normal file
View File

@ -8,9 +8,9 @@ echo "Updating..."
sudo apt-get update
sudo apt-get -y install build-essential g++ make bison flex texinfo libgmp-dev libmpc-dev libmpfr-dev libisl-dev
if [ ! -d "gcc-12.3.0" ]; then
echo "Installing gcc..."
wget https://ftp.gnu.org/gnu/gcc/gcc-12.3.0/gcc-12.3.0.tar.xz
tar -xf gcc-12.3.0.tar.xz
echo "Installing gcc..."
wget https://ftp.gnu.org/gnu/gcc/gcc-12.3.0/gcc-12.3.0.tar.xz
tar -xf gcc-12.3.0.tar.xz
fi
cd gcc-12.3.0/
echo "Configure..."

Some files were not shown because too many files have changed in this diff Show More