mirror of https://github.com/0Nera/BMOSP.git
Compare commits
No commits in common. "master" and "master" have entirely different histories.
|
@ -1,4 +1,4 @@
|
|||
ColumnLimit: 120
|
||||
ColumnLimit: 80
|
||||
IndentWidth: 4
|
||||
UseTab: ForIndentation
|
||||
TabWidth: 4
|
||||
|
|
|
@ -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
|
||||
|
||||
**Дополнительно**
|
||||
Добавьте сюда любою другую информацию, касательно проблемы.
|
|
@ -3,6 +3,8 @@ name: CI BUILD
|
|||
on:
|
||||
push:
|
||||
branches-ignore: [ "pages" ]
|
||||
pull_request:
|
||||
branches-ignore: [ "pages" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
@ -13,21 +15,17 @@ jobs:
|
|||
- 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/mirrors/limine.git --branch=v5.x-branch-binary --depth=1
|
||||
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 *.sh
|
||||
./build_mods.sh
|
||||
chmod +x build.sh
|
||||
./build.sh
|
||||
|
||||
- name: check root dir
|
||||
|
|
|
@ -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-ignore: [ "pages" ]
|
||||
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']
|
||||
# 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
|
||||
dos2unix *.sh
|
||||
chmod +x *.sh
|
||||
./build_mods.sh
|
||||
./build.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
|
@ -1,70 +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/mirrors/limine.git --branch=v5.x-branch-binary --depth=1
|
||||
cd limine && make && cd ..
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
dos2unix *.sh
|
||||
chmod +x *.sh
|
||||
./build_mods.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.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.iso
|
||||
${{ github.workspace }}/rel/LICENSE
|
||||
|
||||
body: |
|
||||
${{ inputs.test_label }}
|
||||
|
||||
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
|
||||
Мы не несем ответственности за нанесенный ущерб.
|
|
@ -5,12 +5,8 @@ limine/
|
|||
ovmf/
|
||||
iso_root/
|
||||
output/
|
||||
sdk*/
|
||||
sdk/
|
||||
*.so
|
||||
*.o
|
||||
*.ko
|
||||
*.elf
|
||||
*.zip
|
||||
*.log
|
||||
*.lck
|
||||
configs/media/*
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"files.eol": "\n",
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"bitset": "cpp",
|
||||
|
@ -14,15 +13,6 @@
|
|||
"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"
|
||||
"mod.h": "c"
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
18
AUTHORS.md
18
AUTHORS.md
|
@ -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>
|
||||
__Тут могло быть ваше имя__
|
||||
|
|
|
@ -1,23 +1,12 @@
|
|||
# Сборка из исходного кода
|
||||
|
||||
## Установка 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 *.sh
|
||||
./build_mods.sh
|
||||
chmod +x build.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
|
@ -27,11 +16,22 @@ chmod +x *.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/
|
||||
chmod +x *.sh
|
||||
./build_mods.sh
|
||||
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
|
||||
```
|
||||
|
||||
|
@ -39,13 +39,13 @@ chmod +x *.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
|
|
@ -1,13 +0,0 @@
|
|||
# Приглашаем к сотрудничеству
|
||||
|
||||
Мы ищем талантливых специалистов, обладающих опытом разработки на C/C++, включая умение работать с ассемблером для x86_64, а также экспертов в области документирования.
|
||||
Если у вас есть опыт разработки на C/C++ для архитектуры x86_64, вы можете присоединиться к проекту и внести свой вклад следующими способами:
|
||||
|
||||
1. Вы можете помочь улучшить производительность и эффективность существующего кода, а также добавить новые функциональные возможности.
|
||||
2. Вы можете принять участие в процессе тестирования, находя и исправляя ошибки в коде.
|
||||
3. Вы можете анализировать и просматривать код, написанный другими участниками, и предлагать способы его улучшения.
|
||||
|
||||
Если вы специалист в области документации или готовы написать статьи или обучающие материалы по данному проекту, то ваш вклад может быть следующим:
|
||||
|
||||
1. Создание документации: разработайте документацию по архитектуре проекта, опишите его API, создайте руководства для пользователей.
|
||||
2. Создание обучающих материалов: напишите статьи, снимите видеоуроки, создайте презентации для обучения ваших менее опытных коллег.
|
|
@ -0,0 +1,14 @@
|
|||
# История разработки
|
||||
|
||||
## 25.10.2023
|
||||
|
||||
Создание проекта
|
||||
|
||||
## 12.10.2023
|
||||
|
||||
Смена вектора и названия проекта МСООС (минимальная студенческая обучающая операционная система) -> БМПОС (базовая модульная платформа операционных систем)
|
||||
|
||||
## 21.10.2023
|
||||
|
||||
- Выпуск релиза 0.1.231
|
||||
- Перевод кодовой базы с C++ на язык C
|
13
README.md
13
README.md
|
@ -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`
|
||||
|
||||
## Предупреждение
|
||||
|
||||
|
|
16
SECURITY.md
16
SECURITY.md
|
@ -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
27
TODO.md
|
@ -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 инструкций
|
||||
|
||||
|
|
15
build.sh
15
build.sh
|
@ -1,5 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
dos2unix *.sh
|
||||
|
||||
python3 scripts/pbuild.py
|
||||
cd modules/
|
||||
mkdir -p bin
|
||||
dos2unix */*.sh
|
||||
#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 pbuild.py
|
|
@ -1,24 +0,0 @@
|
|||
#!/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 ..
|
|
@ -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=1280x720x32
|
||||
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/cpubench.ko
|
||||
MODULE_CMDLINE=[MOD]cpubench.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/pci_data.ko
|
||||
MODULE_CMDLINE=[MOD]pci_data.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/pci.ko
|
||||
MODULE_CMDLINE=[MOD]pci.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/doom.ko
|
||||
MODULE_CMDLINE=[MOD]doom.ko
|
||||
|
||||
MODULE_PATH=boot:///mod/ios.ko
|
||||
MODULE_CMDLINE=[MOD][IO]ios.ko
|
|
@ -57,7 +57,6 @@ SECTIONS
|
|||
|
||||
/* Игнорируем разделы .note.* и .eh_frame, так как они могут вызывать проблемы на некоторых хостах. */
|
||||
/DISCARD/ : {
|
||||
*(.comment)
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
|
|
|
@ -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 < >
|
||||
|
|
123
include/arch.h
123
include/arch.h
|
@ -10,78 +10,16 @@
|
|||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include <lock.h>
|
||||
#include <stdint.h>
|
||||
#include <sys.h>
|
||||
|
||||
#define STACK_SIZE 32 * 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;
|
||||
void *entry;
|
||||
uint64_t status; // 0 - на удаление 1 - работает
|
||||
|
||||
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 *arg);
|
||||
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(char 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));
|
||||
|
@ -93,61 +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);
|
||||
}
|
||||
|
||||
static inline void *hal_memset(void *s, char c, int64_t count) {
|
||||
int64_t d0, d1;
|
||||
asm volatile("rep\n\t"
|
||||
"stosb"
|
||||
: "=&c"(d0), "=&D"(d1)
|
||||
: "a"(c), "1"(s), "0"(count)
|
||||
: "memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline void *hal_memset_32(void *s, uint32_t c, int64_t count) {
|
||||
int64_t d0, d1;
|
||||
asm volatile("rep\n\t"
|
||||
"stosl"
|
||||
: "=&c"(d0), "=&D"(d1)
|
||||
: "a"(c), "1"(s), "0"(count)
|
||||
: "memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline void *hal_memcpy(void *dest, const void *src, int64_t count) {
|
||||
int64_t d0, d1;
|
||||
asm volatile("rep\n\t"
|
||||
"movsb"
|
||||
: "=&c"(d0), "=&D"(d1)
|
||||
: "S"(src), "0"(count), "1"(dest)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline void *hal_memcpy32(void *dest, const void *src, int64_t count) {
|
||||
int64_t d0, d1;
|
||||
asm volatile("rep\n\t"
|
||||
"movsl"
|
||||
: "=&c"(d0), "=&D"(d1)
|
||||
: "S"(src), "0"(count), "1"(dest)
|
||||
: "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define GET_TICK_BIG arch_get_tick_b( )
|
||||
#define GET_TICK_lOW arch_get_tick_l( )
|
||||
|
||||
#endif // arch.h
|
19
include/fb.h
19
include/fb.h
|
@ -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,22 +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;
|
||||
extern uint16_t bpp;
|
||||
#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
|
|
@ -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
|
|
@ -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__ \
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
129
include/mod.h
129
include/mod.h
|
@ -7,128 +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
|
||||
|
||||
#define STT_NOTYPE 0 // Тип символа не указан
|
||||
#define STT_OBJECT 1 // Символ является объектом данных
|
||||
#define STT_FUNC 2 // Символ является объектом кода
|
||||
#define STT_SECTION 3 // Символ связан с разделом
|
||||
#define STT_FILE 4 // Имя символа является именем файла
|
||||
#define STT_COMMON 5 // Символ является общим объектом данных
|
||||
#define STT_TLS 6 // Символ является объектом данных локального потока
|
||||
#define STT_NUM 7 // Количество определенных типов.
|
||||
#define STT_GNU_IFUNC 10 // Символ является объектом непрямого кода
|
||||
|
||||
#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4)
|
||||
#define ELF32_ST_TYPE(val) ((val)&0xf)
|
||||
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf))
|
||||
|
||||
#define ELF64_ST_BIND(val) ELF32_ST_BIND(val)
|
||||
#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val)
|
||||
#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO((bind), (type))
|
||||
|
||||
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 mod_update_info(env_t *ret);
|
||||
|
||||
void *elf_entry(void *module_bin);
|
||||
void *elf_parse(elf64_header_t *head);
|
||||
|
||||
#endif // mod.h
|
|
@ -10,7 +10,6 @@
|
|||
#ifndef SYS_H
|
||||
#define SYS_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
|
@ -31,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;
|
||||
|
@ -43,51 +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)( );
|
||||
void *env; // env_t
|
||||
} __attribute__((packed)) module_info_t;
|
||||
|
||||
typedef struct env_t_s {
|
||||
uint64_t offset;
|
||||
uint64_t id;
|
||||
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 *arg);
|
||||
void (*delete_thread)( );
|
||||
void (*task_switch)( );
|
||||
uint64_t (*new_thread)(uint64_t func);
|
||||
int (*delete_thread)(uint64_t thread_id);
|
||||
time_t (*get_time)( );
|
||||
void (*set_int)(uint8_t vector, void (*handler)(void *));
|
||||
void (*mod_update_info)(struct env_t_s *ret);
|
||||
module_info_t *ret;
|
||||
} __attribute__((packed)) env_t;
|
||||
} env_t;
|
||||
|
||||
env_t *sys_install(env_t *module);
|
||||
env_t sys_install(env_t module);
|
||||
|
||||
#endif // sys.h
|
|
@ -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__); \
|
||||
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)))
|
||||
|
@ -41,12 +41,8 @@ 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);
|
||||
void tool_memmove(void *dest, void *src, uint64_t n);
|
||||
uint64_t tool_strlen(const char *str);
|
||||
void tool_strcpy(char *dest, char *src);
|
||||
int tool_strcmp(const char *s1, const char *s2);
|
||||
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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_BUILD 257
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_BUILD 505
|
||||
|
|
|
@ -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( );
|
||||
}
|
|
@ -8,23 +8,25 @@
|
|||
*/
|
||||
|
||||
#include <fb.h>
|
||||
#include <log.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
static bool acpi_msrs_support = false;
|
||||
static char fxsave_region[512] __attribute__((aligned(16)));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -62,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];
|
||||
|
@ -87,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;
|
||||
|
@ -105,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);
|
||||
|
@ -131,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"); }
|
||||
|
@ -139,19 +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"); }
|
||||
|
||||
brandname( );
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 25) & 1) {
|
||||
LOG("SSE2 поддерживается!\n");
|
||||
fpu_initialize( );
|
||||
uint32_t sse_version = (ecx >> 25) & 0x7;
|
||||
LOG("SSE%u включен\n", sse_version);
|
||||
if ((edx >> 4) & 1) {
|
||||
LOG("Аппаратный терморегулятор (HTC) поддерживается!\n");
|
||||
}
|
||||
if ((edx >> 5) & 1) {
|
||||
LOG("Программный терморегулятор (STC) поддерживается!\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 28) & 1) { LOG("AVX поддерживается!\n"); }
|
||||
brandname( );
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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[];
|
|
@ -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
|
|
@ -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
|
|
@ -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); // Устанавливаем старший байт делителя
|
||||
}
|
||||
|
||||
void pit_init( ) {
|
||||
LOG("PIT установлен\n");
|
||||
pit_set_interval(1);
|
||||
idt_set_int(32, isr_generic);
|
||||
pit_set_interval(100);
|
||||
asm volatile("sti");
|
||||
}
|
|
@ -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( );
|
||||
}
|
|
@ -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(char 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]); }
|
||||
}
|
128
kernel/cpu/idt.c
128
kernel/cpu/idt.c
|
@ -1,128 +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;
|
||||
}
|
||||
|
||||
mod_list_show( );
|
||||
|
||||
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( );
|
||||
}
|
|
@ -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,
|
||||
"Безопасность" };
|
|
@ -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
|
|
@ -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( ));
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,157 +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, void *arg) {
|
||||
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;
|
||||
new_task->entry = func;
|
||||
new_task->status = 1;
|
||||
|
||||
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->rdi = (uint64_t)arg;
|
||||
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 (%s)\n", new_task->id, name);
|
||||
|
||||
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->status = 0;
|
||||
|
||||
for (;;) { task_switch( ); }
|
||||
}
|
||||
|
||||
void task_del_current( ) {
|
||||
LOG("Удаление потока ID: %u, %s\n", current_task->id, current_task->id_str);
|
||||
current_task->status = 0;
|
||||
|
||||
for (;;) { 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->status = 1;
|
||||
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");
|
||||
}
|
|
@ -1,47 +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
|
||||
|
||||
.global fpu_initialize
|
||||
fpu_initialize:
|
||||
clts
|
||||
mov %cr0, %rax
|
||||
and $0xFFFD, %ax
|
||||
or $0x10, %ax
|
||||
mov %rax, %cr0
|
||||
fninit
|
||||
mov %cr0, %rax
|
||||
and $0xfffb, %ax
|
||||
or $0x0002, %ax
|
||||
mov %rax, %cr0
|
||||
mov %cr4, %rax
|
||||
or $0x600, %rax
|
||||
mov %rax, %cr4
|
||||
pushq $0x1F80
|
||||
ldmxcsr (%rsp)
|
||||
addq $8, %rsp
|
||||
ret
|
165
kernel/elf.c
165
kernel/elf.c
|
@ -1,165 +0,0 @@
|
|||
/**
|
||||
* elf.c
|
||||
* Функции работы с ELF64
|
||||
*
|
||||
* Инструменты для парсинга и анализа ELF файлов
|
||||
*
|
||||
*/
|
||||
|
||||
#include <mod.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.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"); }
|
||||
}
|
||||
void *h = elf_parse((elf64_header_t *)module_bin);
|
||||
|
||||
if (h == NULL) { return NULL; }
|
||||
|
||||
// Возвращаем указатель на точку входа
|
||||
return (void *)((uint64_t)h + (uint64_t)module_bin);
|
||||
}
|
||||
|
||||
void import_test( ) {
|
||||
LOG("123");
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
#ifdef DEBUG_ELF
|
||||
LOG("\nТаблица символов:\n");
|
||||
LOG("%s %s %s %s\n", "Индекс", "Значение", "Размер", "Наименование");
|
||||
#endif
|
||||
|
||||
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) {
|
||||
#ifdef DEBUG_ELF
|
||||
LOG("%6u %8x %6x %18s ", i, sym->st_value, sym->st_size, string_table + sym->st_name);
|
||||
#endif
|
||||
switch (ELF64_ST_TYPE(sym->st_info)) {
|
||||
case STT_NOTYPE:
|
||||
|
||||
#ifdef DEBUG_ELF
|
||||
log_printf("без типа\n");
|
||||
#endif
|
||||
break;
|
||||
case STT_OBJECT:
|
||||
#ifdef DEBUG_ELF
|
||||
log_printf("объект данных\n");
|
||||
#endif
|
||||
if (!(string_table + sym->st_name)) { break; }
|
||||
// log_printf("%u\n", tool_strcmp(string_table + sym->st_name, "import_test"));
|
||||
if (tool_strcmp(string_table + sym->st_name, "import_test") == 0) {
|
||||
#ifdef DEBUG_ELF
|
||||
log_printf("0x%x\n", head + sym->st_value);
|
||||
#endif
|
||||
// void (*imp)( ) = (void *)head + sym->st_value;
|
||||
// imp = &import_test;
|
||||
}
|
||||
break;
|
||||
#ifdef DEBUG_ELF
|
||||
case STT_FUNC: log_printf("объект кода\n"); break;
|
||||
case STT_SECTION: log_printf("символ раздела\n"); break;
|
||||
case STT_FILE: log_printf("имя файла\n"); break;
|
||||
case STT_COMMON: log_printf("общий объект данных\n"); break;
|
||||
case STT_TLS: log_printf("объект данных локального потока\n"); break;
|
||||
case STT_NUM: log_printf("количество определенных типов\n"); break;
|
||||
case STT_GNU_IFUNC: log_printf("объект непрямого кода\n"); break;
|
||||
#endif
|
||||
default:
|
||||
#ifdef DEBUG_ELF
|
||||
log_printf("???\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG("Таблица символов не найдена!\n");
|
||||
}
|
||||
|
||||
return (void *)head->e_entry;
|
||||
}
|
126
kernel/fb.c
126
kernel/fb.c
|
@ -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;
|
||||
|
@ -53,23 +54,28 @@ void fb_init( ) {
|
|||
|
||||
for (uint64_t i = 0; i < width * height; i++) { fb_addr[i] = background; }
|
||||
|
||||
LOG("0x%x %ux%u\n", fb_addr, width, height);
|
||||
|
||||
if (framebuffer_response->framebuffer_count == 1) { return; }
|
||||
|
||||
#ifdef DEBUG_FB
|
||||
LOG("Инициализация дополнительных: %u мониторов\n", framebuffer_response->framebuffer_count);
|
||||
#endif
|
||||
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;
|
||||
#ifdef DEBUG_FB
|
||||
LOG("[%u]->0x%x %ux%u\n", i, framebuffer->address, framebuffer->width, framebuffer->height);
|
||||
#endif
|
||||
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;
|
||||
|
@ -78,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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
128
kernel/log.c
128
kernel/log.c
|
@ -1,128 +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) {
|
||||
uint32_t glyth_index = analyze(glyth);
|
||||
for (uint64_t i = 0; i < FONT_6X8_SLIM_CHAR_HEIGHT; i++) {
|
||||
fb_print_bits(x, y + i, font_6x8_slim[glyth_index + 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 == '\r') {
|
||||
log_buffer[--buf_pos] = 0;
|
||||
} else 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') { tool_memmove(log_buffer, log_buffer + 1, --buf_pos); }
|
||||
tool_memmove(log_buffer, log_buffer + 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( ) {
|
||||
// Перерисовка экрана
|
||||
hal_memset_32(SCREEN_BUFFER, DARK_GREEN, SCREEN_WIDTH * SCREEN_HEIGHT);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
LOG("%ux%u %u\n", width, height, bpp);
|
||||
redraw_screen( );
|
||||
lock_release(log_lock);
|
||||
}
|
||||
|
||||
void log_init( ) {
|
||||
log_buffer = (char *)&start_buffer;
|
||||
}
|
|
@ -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));
|
||||
}
|
119
kernel/mem.c
119
kernel/mem.c
|
@ -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,
|
||||
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,
|
||||
.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 };
|
||||
.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, можно освободить",
|
||||
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,
|
||||
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,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,13 +177,12 @@ 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);
|
||||
tool_memset(third, 0, sizeof(mem_entry_t));
|
||||
|
||||
third->size = curr->size - (third->data - curr->data);
|
||||
third->next = curr->next;
|
||||
|
@ -220,9 +191,6 @@ static void *alloc_align(size_t size, size_t alignment) {
|
|||
second->size = size;
|
||||
second->next = third;
|
||||
second->free = 0;
|
||||
second->task_id = 0;
|
||||
|
||||
if (task_f_init) { second->task_id = current_task->id; }
|
||||
|
||||
if (curr != second) {
|
||||
curr->next = second;
|
||||
|
@ -232,17 +200,16 @@ static void *alloc_align(size_t size, size_t alignment) {
|
|||
|
||||
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;
|
||||
|
@ -284,21 +250,19 @@ void mem_init( ) {
|
|||
mmmap_count = memmap_response->entry_count;
|
||||
struct limine_memmap_entry **mmaps = memmap_response->entries;
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
LOG("Записей в карте памяти: %u\n", memmap_response->entry_count);
|
||||
#endif
|
||||
|
||||
// Обработка каждой записи в карте памяти
|
||||
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) {
|
||||
#ifdef DEBUG_MEM
|
||||
LOG("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
|
||||
"килобайт\n",
|
||||
mmaps[i]->length / 1024 / 1024, (mmaps[i]->length / 1024) % 1024);
|
||||
#endif
|
||||
mmaps[i]->length / 1024 / 1024,
|
||||
(mmaps[i]->length / 1024) % 1024);
|
||||
}
|
||||
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
||||
|
||||
|
@ -326,33 +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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||
LOG("Размер битовой карты: %u\n", bitmap_size);
|
||||
#endif
|
||||
|
||||
alloc_init(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
|
||||
#ifdef DEBUG_MEM
|
||||
LOG("%u мегабайт выделено в динамичную память\n", (256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
// Выделяем по 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( );
|
||||
#ifdef DEBUG_MEM
|
||||
|
||||
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);
|
||||
#endif
|
||||
LOG("Проверка менеджера памяти\n");
|
||||
}
|
168
kernel/mod.c
168
kernel/mod.c
|
@ -9,82 +9,68 @@
|
|||
|
||||
#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,
|
||||
static volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_module_response *)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 = "Неизвестный тип модуля";
|
||||
|
||||
static env_t *main_env = NULL;
|
||||
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( ) {
|
||||
LOG("Список модулей:\n");
|
||||
for (uint64_t i = 0; i < modules_count; i++) {
|
||||
LOG("Имя: %s | ID: %u \n", module_list[i].name ? module_list[i].name : "(NULL)", i);
|
||||
LOG("Описание модуля: %s\n", module_list[i].message ? module_list[i].message : "(NULL)");
|
||||
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 ? module_list[i].data : 0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Запуск модулей имеющих дополнительную точку входа
|
||||
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 (module_list[i].name) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -103,99 +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);
|
||||
|
||||
if (module_init == NULL) {
|
||||
LOG("Модуль %s неисправен\n", module_ptr->cmdline);
|
||||
continue;
|
||||
}
|
||||
LOG("\t->Точка входа: 0x%x\n", module_init);
|
||||
|
||||
main_env.offset = (uint64_t)module_ptr->address;
|
||||
main_env.info = (module_info_t *)0;
|
||||
|
||||
// LOG("\t->Точка входа: 0x%x\n", module_init);
|
||||
main_env = (env_t *)mem_alloc(sizeof(env_t));
|
||||
tool_memset(main_env, 0, sizeof(env_t));
|
||||
main_env->offset = (uint64_t)module_ptr->address;
|
||||
main_env->id = modules_count;
|
||||
sys_install(main_env);
|
||||
|
||||
task_new_thread((void (*)(void *))module_init, module_list[i].name, main_env);
|
||||
module_list[modules_count].env = (void *)main_env;
|
||||
module_list[modules_count].name = 0;
|
||||
module_list[modules_count].message = 0;
|
||||
module_list[modules_count].data_size = 0;
|
||||
module_list[modules_count].data = 0;
|
||||
module_list[modules_count].get_func = 0;
|
||||
module_list[modules_count].after_init = 0;
|
||||
main_env.fb_printf = &fb_printf;
|
||||
|
||||
module_info_t ret = module_init(&main_env);
|
||||
|
||||
module_list[modules_count].message = ret.message;
|
||||
module_list[modules_count].data_size = ret.data_size;
|
||||
|
||||
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_update_info(env_t *env) {
|
||||
module_list[env->id].name = env->ret->name;
|
||||
module_list[env->id].message = env->ret->message;
|
||||
module_list[env->id].data_size = env->ret->data_size;
|
||||
module_list[env->id].data = env->ret->data;
|
||||
module_list[env->id].get_func = env->ret->get_func;
|
||||
module_list[env->id].after_init = env->ret->after_init;
|
||||
module_list[env->id].irq = env->ret->irq;
|
||||
module_list[env->id].irq_handler = env->ret->irq_handler;
|
||||
}
|
||||
|
||||
// Добавление модуля
|
||||
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");
|
||||
}
|
|
@ -8,62 +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( );
|
||||
mem_get_stat( );
|
||||
mod_list_show( );
|
||||
|
||||
fb_set_text_color(0x00FF00);
|
||||
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
|
||||
asm volatile("sti");
|
||||
for (;;) {
|
||||
task_t *task = current_task;
|
||||
do {
|
||||
task = task->next;
|
||||
if (task->status == 0) {
|
||||
// LOG("УДАЛЕНИЕ %u(%s)\n", task->id, task->id_str);
|
||||
task_t *prev = task->last;
|
||||
task_t *next = task->next;
|
||||
fb_set_text_color(0x00D000);
|
||||
|
||||
prev->next = next;
|
||||
next->last = prev;
|
||||
|
||||
mem_free(task->stack);
|
||||
mem_free(task);
|
||||
while (1) {
|
||||
uint64_t byte = inb(0x60);
|
||||
if (byte == 0x1) {
|
||||
LOG("Exit!\n");
|
||||
return;
|
||||
}
|
||||
} while (task->id != 0);
|
||||
|
||||
task_switch( );
|
||||
}
|
||||
}
|
56
kernel/sys.c
56
kernel/sys.c
|
@ -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,24 +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->task_switch = &task_switch;
|
||||
module->get_time = &rtc_get_time;
|
||||
module->set_int = &idt_set_int;
|
||||
module->mod_update_info = &mod_update_info;
|
||||
module->ret = NULL;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* task.c
|
||||
* Управление потоками
|
||||
*
|
||||
* Данный файл содержит функции для создания и удаления потоков.
|
||||
*
|
||||
*/
|
||||
|
||||
void task_init( ) {}
|
||||
|
||||
void task_new_thread( ) {
|
||||
return;
|
||||
}
|
||||
|
||||
void task_delete_thread( ) {
|
||||
return;
|
||||
}
|
145
kernel/tool.c
145
kernel/tool.c
|
@ -23,17 +23,6 @@ void *tool_memset(void *ptr, uint8_t n, uint64_t size) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
void tool_memmove(void *dest, void *src, uint64_t n) {
|
||||
unsigned char *cdest = (unsigned char *)dest;
|
||||
unsigned char *csrc = (unsigned char *)src;
|
||||
|
||||
if (cdest < csrc) {
|
||||
for (uint64_t i = 0; i < n; i++) { cdest[i] = csrc[i]; }
|
||||
} else {
|
||||
for (uint64_t i = n; i > 0; i--) { cdest[i - 1] = csrc[i - 1]; }
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t tool_strlen(const char *str) {
|
||||
uint64_t length = 0;
|
||||
while (*str) {
|
||||
|
@ -43,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);
|
||||
|
@ -77,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;
|
||||
|
@ -112,14 +62,6 @@ void tool_reverse_str(char *str) {
|
|||
}
|
||||
}
|
||||
|
||||
int tool_strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *(const unsigned char *)s1 - *(const unsigned char *)s2;
|
||||
}
|
||||
|
||||
// Преобразование целого числа "i" в системе счисления "base" в строку "buf"
|
||||
void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
|
||||
bool negative = false;
|
||||
|
@ -136,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);
|
||||
|
||||
|
@ -159,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);
|
||||
|
||||
|
@ -170,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; // Неожиданный конец строки формата
|
||||
}
|
||||
|
@ -239,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);
|
||||
|
@ -260,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++;
|
||||
|
@ -271,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++;
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
#include <mem.h>
|
||||
#include <tool.h>
|
||||
|
||||
#define NONS (0x98)
|
||||
#define SKIP_OR_NOT (dest != NONS)
|
||||
#define M(W40, W45, W201) ((((W40)-0x80) << 10) | (((W45) - (W40)) << 5) | ((W201)-0x80))
|
||||
|
||||
unsigned int utf8_2_win1251(const char *utf8, char *win) {
|
||||
unsigned int dest, p, l1, l2, l3, inc, i, j, b1, b2, b3;
|
||||
const unsigned short AR[16] = {
|
||||
M(NONS, NONS, 0x86), M(0xA8, 0xB8, 0x87), M(0x80, 0x90, 0x95), M(0x81, 0x83, 0x96),
|
||||
M(0xAA, 0xBA, 0x97), M(0xBD, 0xBE, NONS), M(0xB2, 0xB3, NONS), M(0xAF, 0xBF, NONS),
|
||||
M(0xA3, 0xBC, 0x91), M(0x8A, 0x9A, 0x92), M(0x8C, 0x9C, 0x82), M(0x8E, 0x9E, NONS),
|
||||
M(0x8D, 0x9D, 0x93), M(NONS, NONS, 0x94), M(0xA1, 0xA2, 0x84), M(0x8F, 0x9F, NONS)
|
||||
};
|
||||
|
||||
for (i = 0, j = 0; utf8[i] != 0; i += inc) {
|
||||
b1 = utf8[i];
|
||||
b2 = utf8[i + 1];
|
||||
b3 = utf8[i + 2];
|
||||
|
||||
// Utf8 переводим в Unicode.
|
||||
inc = (0xE5000000u >> (((b1) >> 4) << 1)) & 0x3;
|
||||
p = ((((b1) << 12) + (((b2)&0x3F) << 6) + ((b3)&0x3F)) & (0x7FFFF >> inc)) >>
|
||||
(((0xC5FFAAAAu >> (((b1) >> 4) << 1)) & 0x3) * 6);
|
||||
|
||||
// Добавляем все остающиеся на месте.
|
||||
dest = (((inc != 0) & (((p >> 5) != 0x5) | (0xF71C852E >> b2))) - 1) & p;
|
||||
inc++;
|
||||
|
||||
// Добавляем русские буквы кроме ё и Ё.
|
||||
dest += ((((p - 0x10) >> 6) != 0x10) - 1) & (p - 0x350);
|
||||
|
||||
// Добавляем символы из диапазонов: 0x401-0x40F, 0x451-0x45F, 0x2013-0x2022.
|
||||
l1 = ((p >> 4) != 0x40) - 1;
|
||||
l2 = ((p >> 4) != 0x45) - 1;
|
||||
l3 = (((p - 3) >> 4) != 0x201) - 1;
|
||||
dest += ((((l2 & (AR[p & 0xF] >> 5)) | (l3 & AR[p & 0xF])) & 0x1F) + ((l1 | l2) & (AR[p & 0xF] >> 10))) +
|
||||
((l1 | l2 | l3) & 0x80);
|
||||
|
||||
// Добавляем оставшиеся.
|
||||
dest += (((p != 0x490) - 1) & 0xA5) | (((p != 0x491) - 1) & 0xB4) | (((p != 0x2026) - 1) & 0x85) |
|
||||
(((p != 0x2030) - 1) & 0x89) | (((p != 0x2039) - 1) & 0x8B) | (((p != 0x203A) - 1) & 0x9B) |
|
||||
(((p != 0x20AC) - 1) & 0x88) | (((p != 0x2116) - 1) & 0xB9) | (((p != 0x2122) - 1) & 0x99);
|
||||
|
||||
// Отличаем настоящий 0 от просто отсутствующих в win 1251 символов.
|
||||
dest += (((b1 == 0) | (dest != 0)) - 1) & NONS;
|
||||
|
||||
win[j] = dest;
|
||||
j += SKIP_OR_NOT;
|
||||
}
|
||||
win[j] = 0;
|
||||
return j;
|
||||
}
|
||||
|
||||
#undef M
|
||||
#undef NONS
|
||||
#undef SKIP_OR_NOT
|
||||
|
||||
char *utf8cp(char *str) {
|
||||
size_t len = tool_strlen(str);
|
||||
char *result = (char *)mem_alloc(len + 1);
|
||||
if (result) { utf8_2_win1251(str, result); }
|
||||
return result;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
libmod.a
|
|
@ -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
|
|
@ -1,69 +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 *arg);
|
||||
void (*delete_thread)( );
|
||||
void (*task_switch)( );
|
||||
time_t (*get_time)( );
|
||||
void (*mod_update_info)(env_t *ret);
|
||||
void (*set_int)(uint8_t vector, void (*func)(void *));
|
||||
uint64_t offset;
|
||||
|
||||
void init_env(env_t *loader_env) {
|
||||
if (loader_env == NULL) {
|
||||
for (;;) {}
|
||||
}
|
||||
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;
|
||||
task_switch = loader_env->task_switch;
|
||||
get_time = loader_env->get_time;
|
||||
mod_update_info = loader_env->mod_update_info;
|
||||
set_int = loader_env->set_int;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
106
modlib/system.h
106
modlib/system.h
|
@ -9,58 +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, void *arg);
|
||||
extern void (*delete_thread)( );
|
||||
extern void (*task_switch)( );
|
||||
extern time_t (*get_time)( );
|
||||
extern void (*mod_update_info)(env_t *ret);
|
||||
extern void (*set_int)(uint8_t vector, void (*func)(void *));
|
||||
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
|
||||
|
|
130
modlib/types.h
130
modlib/types.h
|
@ -1,130 +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; // Номер прерывания
|
||||
void *irq_handler; // Адрес обработчика прерываний
|
||||
void *(*get_func)(uint64_t id);
|
||||
void (*after_init)( );
|
||||
void *env; // env_t
|
||||
} __attribute__((packed)) module_info_t;
|
||||
|
||||
typedef struct env_t_s {
|
||||
uint64_t offset;
|
||||
uint64_t id;
|
||||
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 *arg);
|
||||
void (*delete_thread)( );
|
||||
void (*task_switch)( );
|
||||
time_t (*get_time)( );
|
||||
void (*set_int)(uint8_t vector, int_entry_t handler);
|
||||
void (*mod_update_info)(struct env_t_s *ret);
|
||||
module_info_t *ret;
|
||||
} __attribute__((packed)) env_t;
|
||||
#endif // types.h
|
|
@ -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"
|
||||
|
|
|
@ -2,92 +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);
|
||||
}
|
||||
|
||||
void __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( ); }
|
||||
|
||||
env->ret = &((module_info_t){ .name = (char *)"CPUBENCH",
|
||||
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 });
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
};
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
PureDOOM.h
|
||||
*.wad
|
|
@ -1,20 +0,0 @@
|
|||
#/bin/sh
|
||||
echo "Название: DOOM"
|
||||
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
|
||||
|
||||
wget https://github.com/Daivuk/PureDOOM/raw/refs/heads/master/PureDOOM.h
|
||||
wget https://github.com/Daivuk/PureDOOM/raw/refs/heads/master/doom1.wad
|
||||
|
||||
$CC $ARCH_FLAGS -I../../modlib -finput-charset=UTF-8 -fexec-charset=cp1251 -c main.c -o doom.o
|
||||
$CC $ARCH_FLAGS -Wl,--entry=init,--build-id=none -T ../link.ld doom.o -L../../modlib/lib/ -lmod -o doom.ko
|
||||
|
||||
cp doom.ko ../bin/
|
||||
cp doom1.wad ../bin/
|
||||
echo "Сборка завершена, файл: doom.ko"
|
|
@ -1,27 +0,0 @@
|
|||
#include "PureDOOM.h"
|
||||
#include <system.h>
|
||||
|
||||
static const char name[] = "[APP]DOOM";
|
||||
static const char message[] = "DOOM :)";
|
||||
|
||||
static int app_main( ) {
|
||||
log_printf("[%s]\n", message);
|
||||
return 2 + 2;
|
||||
}
|
||||
|
||||
void __attribute__((section(".minit"))) init(env_t *env) {
|
||||
init_env(env);
|
||||
env->ret = &((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 });
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -1,82 +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;
|
||||
}
|
||||
|
||||
void __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);
|
||||
env->ret = &((module_info_t){ .name = (char *)&name,
|
||||
fb_printf("[%s]\n", message);
|
||||
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 });
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
.err_code = 2023,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -1,171 +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;
|
||||
}
|
||||
}
|
||||
|
||||
void __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);
|
||||
|
||||
env->ret = &((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 });
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
}
|
|
@ -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"
|
|
@ -1,122 +0,0 @@
|
|||
#include <system.h>
|
||||
|
||||
static module_info_t *mod_list = NULL;
|
||||
static uint64_t mod_count = 0;
|
||||
static uint64_t app_count = 0;
|
||||
static module_info_t *app_list = NULL;
|
||||
static char (*getc)( ) = NULL;
|
||||
env_t *env;
|
||||
|
||||
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");
|
||||
mod_update_info(env);
|
||||
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_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;
|
||||
|
||||
log_printf("%u модулей\n", mod_count);
|
||||
for (uint64_t i = 0; i < mod_count; i++) {
|
||||
if (mod_list[i].name) {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (;;) { delete_thread( ); }
|
||||
}
|
||||
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
void __attribute__((section(".minit"))) init(env_t *envm) {
|
||||
env = envm;
|
||||
init_env(env);
|
||||
|
||||
env->ret = &((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 });
|
||||
mod_update_info(env);
|
||||
task_switch( );
|
||||
main( );
|
||||
for (;;) { delete_thread( ); }
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
|
@ -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"
|
|
@ -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 каждый раз
|
||||
}
|
||||
}
|
|
@ -1,23 +1,7 @@
|
|||
#/bin/sh
|
||||
echo "Название: PCI"
|
||||
echo "Лицензия: Публичное достояние"
|
||||
|
||||
|
||||
CC=${CC:-gcc}
|
||||
ARCH_FLAGS="-fno-stack-protector -fdata-sections -fno-stack-check -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"
|
||||
|
|
|
@ -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,65 +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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((section(".minit"))) init(env_t *env) {
|
||||
module_info_t init(env_t *env) {
|
||||
init_env(env);
|
||||
|
||||
log_printf("pci_data %x\n", 1);
|
||||
module_info_t *pci_data = get_module("[PCI][ADAPTER]");
|
||||
log_printf("pci_data %x\n", pci_data);
|
||||
|
||||
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( );
|
||||
env->ret = &((module_info_t){ .name = "[PCI]",
|
||||
.message = "PCI драйвер",
|
||||
.type = 0,
|
||||
.data_size = 0,
|
||||
.data = 0,
|
||||
return (module_info_t){
|
||||
.name = (char *)"[PCI]",
|
||||
.message = (char *)"PCI драйвер",
|
||||
.err_code = 0,
|
||||
.module_id = 0,
|
||||
.irq = 0,
|
||||
.irq_handler = 0,
|
||||
.get_func = 0,
|
||||
.after_init = 0 });
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
};
|
||||
}
|
|
@ -1,91 +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);
|
||||
}
|
||||
}
|
||||
|
||||
void __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][DATA]База PCI не найдена!\n");
|
||||
delete_thread( );
|
||||
}
|
||||
|
||||
uint64_t num_vendors = count_chars(pci_data->data, ';');
|
||||
log_printf("[PCI][DATA]Количество вендоров: %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);
|
||||
env->ret = &((module_info_t){ .name = "[PCI][ADAPTER]",
|
||||
.message = "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 });
|
||||
log_printf("Готово %x\n", vendor_list);
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
}
|
|
@ -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.
|
|
@ -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"
|
|
@ -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 };
|
||||
}
|
|
@ -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"
|
|
@ -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 */
|
||||
};
|
|
@ -1,168 +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( );
|
||||
}
|
||||
|
||||
void __attribute__((section(".minit"))) init(env_t *env) {
|
||||
init_env(env);
|
||||
current_state = NORMAL_STATE;
|
||||
keyboard_buffer.ctrl_pressed = 0;
|
||||
keyboard_buffer.shift_pressed = 0;
|
||||
|
||||
env->ret = &((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 });
|
||||
log_printf("Драйвер PS/2 клавиатуры установлен\n");
|
||||
set_int(33, handler);
|
||||
mod_update_info(env);
|
||||
delete_thread( );
|
||||
}
|
|
@ -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;
|
|
@ -0,0 +1,7 @@
|
|||
#/bin/sh
|
||||
echo "Название: SIMD"
|
||||
echo "Лицензия: Публичное достояние"
|
||||
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"
|
|
@ -0,0 +1,35 @@
|
|||
#include <system.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
module_info_t init(env_t *env) {
|
||||
init_env(env);
|
||||
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 23) & 1) { env->fb_printf("MMX поддерживается!\n"); }
|
||||
|
||||
if ((edx >> 25) & 1) {
|
||||
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;
|
||||
env->fb_printf("SSE%u включен\n", sse_version);
|
||||
}
|
||||
|
||||
if ((ecx >> 28) & 1) { env->fb_printf("AVX поддерживается!\n"); }
|
||||
|
||||
return (module_info_t){
|
||||
.name = (char *)"SIMD",
|
||||
.message = (char *)"SIMD инструкции",
|
||||
.err_code = 0,
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue