Compare commits
208 Commits
Author | SHA1 | Date |
---|---|---|
Aren Elchinyan | 1c408d21d8 | |
Aren Elchinyan | d8fd702296 | |
Konstantin Avadov | 862e9b3328 | |
Aren Elchinyan | a93ca306ce | |
Aren Elchinyan | e4b16535ac | |
Aren Elchinyan | d2a0fc6162 | |
Aren Elchinyan | add8945f53 | |
Aren Elchinyan | 52f8c14a8f | |
Aren Elchinyan | 140790cf92 | |
Aren Elchinyan | 7631e05421 | |
Aren Elchinyan | fb2effa5b7 | |
Aren Elchinyan | 18ceec804b | |
Aren Elchinyan | f214c92430 | |
Aren Elchinyan | ae0c7db85b | |
Aren Elchinyan | 03742e31bb | |
Aren Elchinyan | 5175bba935 | |
Aren Elchinyan | 9a56ff681a | |
Aren Elchinyan | cce42f26e6 | |
Aren Elchinyan | c41fe4a8a5 | |
Aren Elchinyan | 6d414307dc | |
Aren Elchinyan | 89652e9819 | |
Aren Elchinyan | af1d9d80a9 | |
Aren Elchinyan | 5858814e6b | |
Aren Elchinyan | d8457784f7 | |
Aren Elchinyan | 121c408a6c | |
Aren Elchinyan | ac3e6705d4 | |
Aren | 230eecc911 | |
Aren | 14457a8266 | |
Aren | 40c1604109 | |
Арен Елчинян | 09abbdbb2b | |
Арен Елчинян | 82cec87a36 | |
Aren | e7233a7b4c | |
Aren Elchinyan | d6691de198 | |
Aren | 00cbc46cb7 | |
Aren | e258525c8a | |
Aren Elchinyan | ae0b51beb1 | |
Aren Elchinyan | a950c792ef | |
Aren | ed3af8d570 | |
Vadim Zhukov | 88fbf011e9 | |
Aren Elchinyan | bf12663b3b | |
Aren | e1e88ada09 | |
Aren Elchinyan | 3bb064c9d9 | |
Aren Elchinyan | b57b453332 | |
Aren Elchinyan | a893d61040 | |
Aren Elchinyan | 1dbaf29a96 | |
Aren Elchinyan | 384d04b89b | |
Aren Elchinyan | 7e9cbe5e07 | |
Aren Elchinyan | 114e30614b | |
Aren Elchinyan | b424a5a055 | |
Aren Elchinyan | e21551f008 | |
Aren Elchinyan | 9deba0b828 | |
Aren Elchinyan | d5cb26f9a4 | |
Aren | 89307ea263 | |
Aren | 3a6c3b3ca7 | |
Aren Elchinyan | 8fe1df88a3 | |
Aren | 885a097feb | |
Aren Elchinyan | 84e5169bff | |
Aren Elchinyan | ba1047a70d | |
Aren Elchinyan | 933baa57f9 | |
Aren Elchinyan | e31c9db524 | |
Aren Elchinyan | 70d6805c0f | |
Aren Elchinyan | 8ad4c32272 | |
Aren Elchinyan | 1ab27c1a70 | |
Aren Elchinyan | 176fe9b66b | |
Aren Elchinyan | 70d722deee | |
Aren Elchinyan | 2b35ed412f | |
Aren Elchinyan | 8c54109dc9 | |
Aren Elchinyan | 7c07bf5ffd | |
Aren Elchinyan | 112da40706 | |
Aren Elchinyan | 709116f554 | |
Aren Elchinyan | f218333bd0 | |
Aren Elchinyan | 29b9d6ba3a | |
Aren Elchinyan | 11a130c9ab | |
Aren Elchinyan | 73bf252f98 | |
Aren Elchinyan | adf6d4a8b9 | |
Aren Elchinyan | fc43b6746a | |
Aren Elchinyan | 39fb9c7f2e | |
Aren Elchinyan | c875299b3d | |
Aren | 29bfc8faba | |
Aren | 87d9ebeb7e | |
Aren | edc848704c | |
Aren | 1c12dd6625 | |
Aren | a52835dd47 | |
Aren Elchinyan | 883c977b28 | |
Aren Elchinyan | df965c2218 | |
Aren Elchinyan | 969ef786bd | |
Aren | 93934c6605 | |
Aren Elchinyan | feaab75a6f | |
Aren Elchinyan | a59ba3412f | |
Aren Elchinyan | 2915242902 | |
Aren Elchinyan | 50ad112d7f | |
Aren Elchinyan | a7703f54ab | |
Aren Elchinyan | f61e12d5f8 | |
Aren Elchinyan | c4b8ec6787 | |
Aren Elchinyan | 90cf91ee31 | |
Aren Elchinyan | d8e5d5f081 | |
Aren Elchinyan | e0d42d991c | |
Aren Elchinyan | 99b04b5481 | |
Aren Elchinyan | 9527feb839 | |
Aren Elchinyan | 662004cbef | |
Aren Elchinyan | 15d1b4aaf9 | |
Aren Elchinyan | ddc1a1a931 | |
Aren Elchinyan | 1fc22169cd | |
Aren Elchinyan | 687ec44829 | |
Aren Elchinyan | 365aacf4bc | |
Aren Elchinyan | 4fee1d1c64 | |
Aren Elchinyan | 5febf988a5 | |
Aren Elchinyan | c29578d020 | |
Aren Elchinyan | e7a2a02300 | |
Aren | 013791d40f | |
Aren | 2c14e03d8b | |
Aren | 976da0bee1 | |
Aren | 4396a2bba4 | |
Aren | 2c462b6eed | |
Aren | 2e3fadb9a1 | |
Aren Elchinyan | 5155e7adae | |
Aren Elchinyan | fb0af09414 | |
Aren Elchinyan | e5aae06c09 | |
Aren Elchinyan | 08bc26c87f | |
Aren Elchinyan | 471ee3cde3 | |
Aren Elchinyan | 37269c9fba | |
Aren Elchinyan | dca0a33564 | |
Aren Elchinyan | 8769136f2f | |
Aren Elchinyan | 210bea4f42 | |
Aren Elchinyan | b6ad573dfa | |
Aren | 9c11be08c9 | |
Aren Elchinyan | 224256a8ac | |
Aren Elchinyan | b9d186cc2f | |
Aren Elchinyan | 2d0a37f6a5 | |
Aren Elchinyan | 36d28d5f90 | |
Aren Elchinyan | bb86ea4071 | |
Aren Elchinyan | 799cd72615 | |
Aren Elchinyan | 63bf02229c | |
Aren Elchinyan | f8cf58a450 | |
Aren Elchinyan | 22a59655b6 | |
Aren Elchinyan | a2be2a4add | |
Aren Elchinyan | bed0cd45e6 | |
Aren Elchinyan | a2b2b1282b | |
Aren Elchinyan | c376f903b0 | |
Aren Elchinyan | 76724a1b07 | |
Aren Elchinyan | b909a5f963 | |
Aren Elchinyan | f4d5158799 | |
Aren Elchinyan | 8ca0335c8f | |
Aren | 02ba9d199b | |
Aren | 481dcb5ab8 | |
Aren | 069ea689e1 | |
Aren | c212598468 | |
Aren | 1b1528dff1 | |
Aren | dc73ee66df | |
Aren | 1f6eaf3ca0 | |
Aren | cc7c21f0fd | |
Aren Elchinyan | e36201c412 | |
Aren Elchinyan | 1d06b2443d | |
Aren Elchinyan | 7fb682ba9e | |
Aren Elchinyan | 730fa37119 | |
Aren Elchinyan | 56d3e73f6d | |
Aren Elchinyan | 65b35be40f | |
Aren Elchinyan | acb527b874 | |
Aren Elchinyan | ffe5b07d83 | |
Aren Elchinyan | b337fa32f6 | |
Aren Elchinyan | 5236f156e6 | |
Aren Elchinyan | f4d7b3e4e9 | |
Aren Elchinyan | fa67828241 | |
Aren Elchinyan | a540661cf4 | |
Aren | 3909eb183c | |
Aren | 67af4e64bc | |
Aren | 7d0133a964 | |
Aren | a477da15b5 | |
Aren Elchinyan | a838b8e825 | |
Aren Elchinyan | dd45b2ef6c | |
Aren Elchinyan | 2de168dc78 | |
Aren Elchinyan | 4bcd50a63f | |
Aren Elchinyan | ad38cbda6b | |
Aren | 9f67ee3a58 | |
Aren | 11f07cb832 | |
Aren Elchinyan | 4244853b13 | |
Aren Elchinyan | a0de7f8034 | |
Aren Elchinyan | cd571ddfb4 | |
Aren Elchinyan | 27fe3e827a | |
Aren Elchinyan | cccde49d4d | |
Aren Elchinyan | 151a4a1589 | |
Aren Elchinyan | 8f5fb3eba3 | |
Aren Elchinyan | 96b3696cf6 | |
Aren Elchinyan | 86ff34a34a | |
Aren Elchinyan | beb3ab0eb6 | |
Aren Elchinyan | 4338b6f75c | |
Aren | ded87d7513 | |
Aren | 469acb6782 | |
Aren Elchinyan | 01f7054d55 | |
Aren Elchinyan | 6b07435415 | |
Aren Elchinyan | fb398b9b84 | |
Aren | e964524c03 | |
Aren Elchinyan | 24b3297754 | |
Aren Elchinyan | 3abb4168be | |
Aren Elchinyan | 28c1a6ef55 | |
Aren Elchinyan | 90c3fd689c | |
Aren Elchinyan | 8b0742c4f9 | |
Aren Elchinyan | 1d2095a2b7 | |
Aren Elchinyan | 1106d531df | |
Aren Elchinyan | 18c2d9f67e | |
Aren Elchinyan | 4500aa6869 | |
Aren | 25aa542963 | |
Aren | ca48172026 | |
Aren | 2db3de3d1b | |
Aren | 25b77bb8bb | |
Aren | 8a32d4070e | |
Aren | 8369696931 | |
Aren | 28effc26e8 |
|
@ -1,4 +1,4 @@
|
||||||
ColumnLimit: 80
|
ColumnLimit: 120
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
UseTab: ForIndentation
|
UseTab: ForIndentation
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
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,8 +3,6 @@ name: CI BUILD
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore: [ "pages" ]
|
branches-ignore: [ "pages" ]
|
||||||
pull_request:
|
|
||||||
branches-ignore: [ "pages" ]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -15,17 +13,21 @@ jobs:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: install depends
|
- name: install depends
|
||||||
run: sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt upgrade
|
||||||
|
sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
|
||||||
|
|
||||||
- name: install limine
|
- name: install limine
|
||||||
run: |
|
run: |
|
||||||
git clone https://git.synapseos.ru/Aren/limine.git --branch=v5.x-branch-binary --depth=1
|
git clone https://git.synapseos.ru/mirrors/limine.git --branch=v5.x-branch-binary --depth=1
|
||||||
cd limine && make && cd ..
|
cd limine && make && cd ..
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
dos2unix *.sh
|
dos2unix *.sh
|
||||||
chmod +x build.sh
|
chmod +x *.sh
|
||||||
|
./build_mods.sh
|
||||||
./build.sh
|
./build.sh
|
||||||
|
|
||||||
- name: check root dir
|
- name: check root dir
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
# 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}}"
|
|
@ -0,0 +1,70 @@
|
||||||
|
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,8 +5,12 @@ limine/
|
||||||
ovmf/
|
ovmf/
|
||||||
iso_root/
|
iso_root/
|
||||||
output/
|
output/
|
||||||
sdk/
|
sdk*/
|
||||||
*.so
|
*.so
|
||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
*.elf
|
*.elf
|
||||||
|
*.zip
|
||||||
|
*.log
|
||||||
|
*.lck
|
||||||
|
configs/media/*
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"C_Cpp.errorSquiggles": "disabled",
|
"C_Cpp.errorSquiggles": "disabled",
|
||||||
|
"files.eol": "\n",
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"bitset": "cpp",
|
"bitset": "cpp",
|
||||||
|
@ -13,6 +14,15 @@
|
||||||
"arch.h": "c",
|
"arch.h": "c",
|
||||||
"fb.h": "c",
|
"fb.h": "c",
|
||||||
"system.h": "c",
|
"system.h": "c",
|
||||||
"mod.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"
|
||||||
}
|
}
|
||||||
}
|
}
|
18
AUTHORS.md
18
AUTHORS.md
|
@ -6,16 +6,20 @@
|
||||||
|
|
||||||
Автор идеи, главный разработчик
|
Автор идеи, главный разработчик
|
||||||
|
|
||||||
* aren@synapseos.ru
|
* <aren@synapseos.ru>
|
||||||
* https://t.me/nera00
|
* <https://t.me/nera00>
|
||||||
* https://vk.com/0nera
|
* <https://vk.com/0nera>
|
||||||
* https://github.com/0nera
|
* <https://github.com/0nera>
|
||||||
* https://0nera.ru
|
* <https://0nera.ru>
|
||||||
|
|
||||||
## Основные участники
|
## Основные участники
|
||||||
|
|
||||||
__Тут могло быть ваше имя__
|
* __Тут могло быть ваше имя__
|
||||||
|
|
||||||
## Другие участники
|
## Другие участники
|
||||||
|
|
||||||
__Тут могло быть ваше имя__
|
### Долганов Илья Владимирович
|
||||||
|
|
||||||
|
* <https://vk.com/xkrulex>
|
||||||
|
* <https://t.me/amakesla>
|
||||||
|
* <dolganov.19@mail.ru>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Приглашаем к сотрудничеству
|
||||||
|
|
||||||
|
Мы ищем талантливых специалистов, обладающих опытом разработки на C/C++, включая умение работать с ассемблером для x86_64, а также экспертов в области документирования.
|
||||||
|
Если у вас есть опыт разработки на C/C++ для архитектуры x86_64, вы можете присоединиться к проекту и внести свой вклад следующими способами:
|
||||||
|
|
||||||
|
1. Вы можете помочь улучшить производительность и эффективность существующего кода, а также добавить новые функциональные возможности.
|
||||||
|
2. Вы можете принять участие в процессе тестирования, находя и исправляя ошибки в коде.
|
||||||
|
3. Вы можете анализировать и просматривать код, написанный другими участниками, и предлагать способы его улучшения.
|
||||||
|
|
||||||
|
Если вы специалист в области документации или готовы написать статьи или обучающие материалы по данному проекту, то ваш вклад может быть следующим:
|
||||||
|
|
||||||
|
1. Создание документации: разработайте документацию по архитектуре проекта, опишите его API, создайте руководства для пользователей.
|
||||||
|
2. Создание обучающих материалов: напишите статьи, снимите видеоуроки, создайте презентации для обучения ваших менее опытных коллег.
|
14
HISTORY.md
14
HISTORY.md
|
@ -1,14 +0,0 @@
|
||||||
# История разработки
|
|
||||||
|
|
||||||
## 25.10.2023
|
|
||||||
|
|
||||||
Создание проекта
|
|
||||||
|
|
||||||
## 12.10.2023
|
|
||||||
|
|
||||||
Смена вектора и названия проекта МСООС (минимальная студенческая обучающая операционная система) -> БМПОС (базовая модульная платформа операционных систем)
|
|
||||||
|
|
||||||
## 21.10.2023
|
|
||||||
|
|
||||||
- Выпуск релиза 0.1.231
|
|
||||||
- Перевод кодовой базы с C++ на язык C
|
|
13
README.md
13
README.md
|
@ -1,15 +1,18 @@
|
||||||
# БМПОС: Базовая Модульная Платформа Операционных Систем
|
# БМПОС: Базовая Модульная Платформа Операционных Систем
|
||||||
|
|
||||||
[![CI сборка](https://github.com/0Nera/BMOSP/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/0Nera/BMOSP/actions/workflows/build.yml)
|
[![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)
|
[![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.
|
БМПОС - Базовая Модульная Платформа Операционных Систем для платформы x86_64 (BIOS/UEFI). Это отечественное программное обеспечение, созданное при поддержке Синапс ОС на языке программирования C.
|
||||||
|
|
||||||
БМПОС не является операционной системой. Это платформа для изучения.
|
БМПОС не является операционной системой. Это платформа для изучения.
|
||||||
|
|
||||||
Философия БМПОС - "всё есть модуль".
|
Философия БМПОС - "всё есть модуль".
|
||||||
|
|
||||||
![Скриншот вывода ядра в эмуляторе Qemu](https://0nera.github.io/BMOSP/assets/0_0.1.367.png)
|
![Скриншот вывода ядра в эмуляторе Qemu](https://git.synapseos.ru/Aren/BMOSP/raw/branch/pages/assets/0_0.2.0.png)
|
||||||
|
|
||||||
## Список задач
|
## Список задач
|
||||||
|
|
||||||
|
@ -17,7 +20,7 @@
|
||||||
|
|
||||||
## Партнеры
|
## Партнеры
|
||||||
|
|
||||||
- ООО **"НПО ТЕ-ОН"**
|
- Синапс ОС
|
||||||
|
|
||||||
## Помощь проекту
|
## Помощь проекту
|
||||||
|
|
||||||
|
@ -25,7 +28,7 @@
|
||||||
|
|
||||||
### Доработка кодовой базы
|
### Доработка кодовой базы
|
||||||
|
|
||||||
Если вы владеете C/C++, ассемблерами GAS или FASM, то вы можете доработать ядро проекта или написать свой пользовательский модуль.
|
Если вы владеете C/C++, ассемблером GAS, то вы можете доработать ядро проекта или написать свой пользовательский модуль.
|
||||||
|
|
||||||
Для добавления своего модуля используйте инструкцию `modules/README.md`.
|
Для добавления своего модуля используйте инструкцию `modules/README.md`.
|
||||||
|
|
||||||
|
@ -42,11 +45,11 @@
|
||||||
- Номер карты: 2200 7009 4662 4201
|
- Номер карты: 2200 7009 4662 4201
|
||||||
- Номер счета: 40817810400099892231
|
- Номер счета: 40817810400099892231
|
||||||
- БИК: 044525974
|
- БИК: 044525974
|
||||||
- Банк-получатель: АО «Тинькофф Банк»
|
- Банк-получатель: АО «Т-Банк»
|
||||||
|
|
||||||
## Сборка и запуск
|
## Сборка и запуск
|
||||||
|
|
||||||
Перенесено в файл `BUILD.md`
|
Перенесено в файл `docs/BUILD.md`
|
||||||
|
|
||||||
## Предупреждение
|
## Предупреждение
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Безопасность
|
||||||
|
|
||||||
|
## Поддерживаемые версии
|
||||||
|
|
||||||
|
| Версия | Поддержка |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 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] Буфер ввода-вывода
|
||||||
|
|
||||||
Модули:
|
Модули:
|
||||||
|
|
||||||
- [ ] Оболочка ввода-вывода
|
- [X] Оболочка ввода-вывода
|
||||||
|
|
||||||
Драйвера:
|
Драйвера:
|
||||||
|
|
||||||
- [ ] PS/2 (Клавиатура)
|
- [X] PS/2 (Клавиатура)
|
||||||
- [ ] SATA (AHCI) (Чтение)
|
- [ ] SATA (AHCI) (Чтение)
|
||||||
- [ ] EXT2
|
- [ ] EXT2
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@
|
||||||
Примеры:
|
Примеры:
|
||||||
|
|
||||||
- [X] Пример модуля
|
- [X] Пример модуля
|
||||||
- [ ] Пример драйвера
|
- [X] Пример драйвера
|
||||||
- [ ] Пример программы-модуля
|
- [ ] Пример программы-модуля
|
||||||
- [ ] Пример модуля ввода-вывода
|
- [X] Пример модуля ввода-вывода
|
||||||
|
|
||||||
Общая работа:
|
Общая работа:
|
||||||
|
|
||||||
- [ ] Ядро
|
- [X] Ядро
|
||||||
- [ ] Модули
|
- [ ] Модули
|
||||||
- [ ] Драйвера
|
- [ ] Драйвера
|
||||||
- [ ] Документация
|
- [ ] Документация
|
||||||
|
@ -53,6 +53,13 @@
|
||||||
|
|
||||||
### Второстепенные задачи
|
### Второстепенные задачи
|
||||||
|
|
||||||
|
Общее:
|
||||||
|
|
||||||
|
- [ ] Разделение менеджера памяти
|
||||||
|
- [ ] Страничная адресация
|
||||||
|
- [ ] Поддержка ПО в пространстве пользователя
|
||||||
|
- [ ] Переход на make
|
||||||
|
|
||||||
Модули:
|
Модули:
|
||||||
|
|
||||||
- [ ] Отладчик
|
- [ ] Отладчик
|
||||||
|
@ -60,10 +67,14 @@
|
||||||
- [ ] Lua
|
- [ ] Lua
|
||||||
- [ ] SQLite
|
- [ ] SQLite
|
||||||
- [ ] Криптограф
|
- [ ] Криптограф
|
||||||
|
- [ ] Сетевой стек (ARP, IP, TCP, UDP, HTTP)
|
||||||
|
- [ ] DOOM
|
||||||
|
- [ ] IRC
|
||||||
|
|
||||||
Драйвера:
|
Драйвера:
|
||||||
|
|
||||||
- [ ] PS/2 (Мышь)
|
- [ ] PS/2 (Мышь)
|
||||||
|
- [ ] AMD PCnet
|
||||||
- [ ] SATA (AHCI) (Запись)
|
- [ ] SATA (AHCI) (Запись)
|
||||||
- [ ] SIMD (SSE, SSE2, SSE3, SSE4, AVX) - отдельный драйвер для инициализации SIMD инструкций
|
- [ ] SIMD (SSE, SSE2, SSE3, SSE4, AVX) - отдельный драйвер для инициализации SIMD инструкций
|
||||||
|
|
||||||
|
|
15
build.sh
15
build.sh
|
@ -1,12 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cd modules/
|
|
||||||
mkdir -p bin
|
dos2unix *.sh
|
||||||
dos2unix */*.sh
|
|
||||||
#cd helloworld/ && chmod +x build.sh && ./build.sh && cd ..
|
python3 scripts/pbuild.py
|
||||||
#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
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/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,31 +2,40 @@ GRAPHICS=yes
|
||||||
TIMEOUT=5
|
TIMEOUT=5
|
||||||
DEFAULT_ENTRY=0
|
DEFAULT_ENTRY=0
|
||||||
INTERFACE_BRANDING=git.synapseos.ru/Aren/bmosp
|
INTERFACE_BRANDING=git.synapseos.ru/Aren/bmosp
|
||||||
|
INTERFACE_RESOLUTION=1280x720
|
||||||
BACKGROUND_STYLE=stretched
|
BACKGROUND_STYLE=stretched
|
||||||
BACKGROUND_PATH=boot:///boot.tga
|
TERM_WALLPAPER=boot:///mod/boot.jpg
|
||||||
TERM_WALLPAPER=boot:///boot.jpg
|
|
||||||
#TERM_FONT=boot:///CYRILL2.F16
|
#TERM_FONT=boot:///CYRILL2.F16
|
||||||
#TERM_FONT_SIZE=8x16
|
#TERM_FONT_SIZE=8x16
|
||||||
|
|
||||||
:BMOSP (KASLR off)
|
:BMOSP (KASLR off)
|
||||||
#RESOLUTION=640x480
|
#RESOLUTION=640x480
|
||||||
#RESOLUTION=1024x768
|
#RESOLUTION=1024x768
|
||||||
RESOLUTION=1280x720
|
RESOLUTION=1280x720x32
|
||||||
PROTOCOL=limine
|
PROTOCOL=limine
|
||||||
KASLR=no
|
KASLR=no
|
||||||
KERNEL_PATH=boot:///kernel.elf
|
KERNEL_PATH=boot:///kernel.elf
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot.tga
|
MODULE_PATH=boot:///mod/pci_vendors.txt
|
||||||
MODULE_CMDLINE=[BOOTIMG]
|
MODULE_CMDLINE=[PCI][DATA][VENDORS]
|
||||||
|
|
||||||
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_PATH=boot:///mod/pci_data.ko
|
||||||
MODULE_CMDLINE=[MOD]pci_data.ko
|
MODULE_CMDLINE=[MOD]pci_data.ko
|
||||||
|
|
||||||
MODULE_PATH=boot:///mod/pci.ko
|
MODULE_PATH=boot:///mod/pci.ko
|
||||||
MODULE_CMDLINE=[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,6 +57,7 @@ SECTIONS
|
||||||
|
|
||||||
/* Игнорируем разделы .note.* и .eh_frame, так как они могут вызывать проблемы на некоторых хостах. */
|
/* Игнорируем разделы .note.* и .eh_frame, так как они могут вызывать проблемы на некоторых хостах. */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
|
*(.comment)
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Системные вызовы
|
# Системные вызовы
|
||||||
|
|
||||||
## mem_alloc(size_t size)
|
## alloc(size_t size)
|
||||||
|
|
||||||
Выделение блока памяти размером `size`.
|
Выделение блока памяти размером `size`.
|
||||||
Вовзращает адрес на блок памяти или 0 в случае ошибки.
|
Вовзращает адрес на блок памяти или 0 в случае ошибки.
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
- `-1 не хватает ОЗУ`;
|
- `-1 не хватает ОЗУ`;
|
||||||
- `-2 неправильный размер блока`.
|
- `-2 неправильный размер блока`.
|
||||||
|
|
||||||
## mem_free(uintptr_t mem)
|
## free(uintptr_t mem)
|
||||||
|
|
||||||
Освобождение блока памяти `mem`.
|
Освобождение блока памяти `mem`.
|
||||||
Вовзращает 0 в случае успеха или -1 в случае ошибки.
|
Вовзращает 0 в случае успеха или -1 в случае ошибки.
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
- `-1 блок не найден`.
|
- `-1 блок не найден`.
|
||||||
|
|
||||||
## sys_alloc_framebuffer()
|
## alloc_framebuffer()
|
||||||
|
|
||||||
Выделяет память под буфер кадра для отображения графического интерфейса.
|
Выделяет память под буфер кадра для отображения графического интерфейса.
|
||||||
Возвращает указатель на структуру `framebuffer_t` или 0, если произошла ошибка.
|
Возвращает указатель на структуру `framebuffer_t` или 0, если произошла ошибка.
|
||||||
|
@ -28,7 +28,15 @@
|
||||||
|
|
||||||
- `-1 не удалось выделить память для буфера кадра`.
|
- `-1 не удалось выделить память для буфера кадра`.
|
||||||
|
|
||||||
## sys_free_framebuffer(framebuffer_t *frame)
|
## log_printf(char *str, ...)
|
||||||
|
|
||||||
|
Форматированный вывод строки на экран используя функцию ядра log_printf.
|
||||||
|
|
||||||
|
### Будет удалено в ближайших обновлениях
|
||||||
|
|
||||||
|
- Для вывода используйте любой графический или псевдографический модуль
|
||||||
|
|
||||||
|
## free_framebuffer(framebuffer_t *frame)
|
||||||
|
|
||||||
Освобождает ранее выделенную память `frame` для буфера кадра. Возвращает 0 в случае успеха или -1, если произошла ошибка.
|
Освобождает ранее выделенную память `frame` для буфера кадра. Возвращает 0 в случае успеха или -1, если произошла ошибка.
|
||||||
|
|
||||||
|
@ -36,23 +44,23 @@
|
||||||
|
|
||||||
- `-1 ошибка при освобождении памяти для буфера кадра`.
|
- `-1 ошибка при освобождении памяти для буфера кадра`.
|
||||||
|
|
||||||
## sys_exit(int code)
|
## exit(int code)
|
||||||
|
|
||||||
Завершает выполнение текущего потока с кодом `code`.
|
Завершает выполнение текущего потока с кодом `code`.
|
||||||
|
|
||||||
## sys_get_error()
|
## get_error()
|
||||||
|
|
||||||
Получает код ошибки последней операции. Возвращает целочисленное значение, представляющее код ошибки.
|
Получает код ошибки последней операции. Возвращает целочисленное значение, представляющее код ошибки.
|
||||||
|
|
||||||
## sys_get_info()
|
## get_info()
|
||||||
|
|
||||||
Получает информацию о текущей системе. Возвращает структуру `sys_info_t` содержащую информацию о системе.
|
Получает информацию о текущей системе. Возвращает структуру `sys_info_t` содержащую информацию о системе.
|
||||||
|
|
||||||
## sys_get_module(uid_t module_id)
|
## get_module(char *module_id)
|
||||||
|
|
||||||
Получает информацию о модуле `module_id`. Возвращает структуру, содержащую информацию о модуле.
|
Получает информацию о модуле `module_id`. Возвращает структуру `module_info_t` содержащую информацию о модуле.
|
||||||
|
|
||||||
## sys_new_thread(func_t func)
|
## new_thread(func_t func)
|
||||||
|
|
||||||
Создает новый поток выполнения для функции `func`. Возвращает идентификатор созданного потока или 0 в случае ошибки.
|
Создает новый поток выполнения для функции `func`. Возвращает идентификатор созданного потока или 0 в случае ошибки.
|
||||||
|
|
||||||
|
@ -60,7 +68,7 @@
|
||||||
|
|
||||||
- `-1 ошибка при создании потока`.
|
- `-1 ошибка при создании потока`.
|
||||||
|
|
||||||
## sys_delete_thread(uid_t thread_id)
|
## delete_thread(uid_t thread_id)
|
||||||
|
|
||||||
Удаляет указанный поток выполнения `thread_id`. Возвращает 0 в случае успеха или -1 в случае ошибки.
|
Удаляет указанный поток выполнения `thread_id`. Возвращает 0 в случае успеха или -1 в случае ошибки.
|
||||||
|
|
||||||
|
@ -69,11 +77,11 @@
|
||||||
- `-1 поток не найден`.
|
- `-1 поток не найден`.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
## sys_get_time()
|
## get_time()
|
||||||
|
|
||||||
Получает текущее время системы в формате timestamp. Возвращает целое число, представляющее количество секунд с начала эпохи.
|
Получает текущее время системы в формате timestamp. Возвращает целое число, представляющее количество секунд с начала эпохи.
|
||||||
|
|
||||||
## sys_set_alarm(time_t time, func_t func)
|
## set_alarm(time_t time, func_t func)
|
||||||
|
|
||||||
Устанавливает сигнал будильника на время time. При наступлении указанного времени будет вызвана функция func.
|
Устанавливает сигнал будильника на время time. При наступлении указанного времени будет вызвана функция func.
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
# Сборка из исходного кода
|
# Сборка из исходного кода
|
||||||
|
|
||||||
|
## Установка SDK
|
||||||
|
|
||||||
|
Перед сборкой рекомендуем установить готовый пакет SDK вместе с libc6
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install unzip
|
||||||
|
./scripts/get_sdk.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Ubuntu 18.04+
|
## Ubuntu 18.04+
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install clang-format python3 git qemu-system-x86 gdisk dos2unix xorriso
|
sudo apt install clang-format python3 git qemu-system-x86 qemu-system-gui gdisk dos2unix xorriso libc6 gcc make curl mtools
|
||||||
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
||||||
cd BMOSP/
|
cd BMOSP/
|
||||||
chmod +x build.sh
|
chmod +x *.sh
|
||||||
|
./build_mods.sh
|
||||||
./build.sh
|
./build.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,22 +27,11 @@ chmod +x build.sh
|
||||||
В qemu недоступен флаг `-cpu max`, просто уберите его при запуске
|
В qemu недоступен флаг `-cpu max`, просто уберите его при запуске
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install clang-format python3.7 git qemu-system-x86 gdisk dos2unix xorriso
|
sudo apt install clang-format python3.7 git qemu-system-x86 gdisk dos2unix xorriso libc6 gcc make curl mtools
|
||||||
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
git clone https://git.synapseos.ru/Aren/BMOSP.git
|
||||||
cd BMOSP/
|
cd BMOSP/
|
||||||
python3.7 pbuild.py
|
chmod +x *.sh
|
||||||
```
|
./build_mods.sh
|
||||||
|
|
||||||
## 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
|
./build.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -39,13 +39,13 @@ chmod +x build.sh
|
||||||
|
|
||||||
## Qemu
|
## Qemu
|
||||||
|
|
||||||
Стандартная конфигурация загрузки с HDD
|
Стандартная конфигурация загрузки с HDD под x86_64(AMD64) UEFI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd
|
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd
|
||||||
```
|
```
|
||||||
|
|
||||||
Стандартная конфигурация загрузки с ISO образа
|
Стандартная конфигурация загрузки с ISO образа под x86_64(AMD64) UEFI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -cdrom bmosp.iso -boot d --no-reboot
|
qemu-system-x86_64 -name "БМПОС" -cpu max -m 128M -smp 1 -cdrom bmosp.iso -boot d --no-reboot
|
|
@ -21,8 +21,7 @@
|
||||||
#define FONT_6X8_SLIM_CHAR_WIDTH 6
|
#define FONT_6X8_SLIM_CHAR_WIDTH 6
|
||||||
#define FONT_6X8_SLIM_CHAR_HEIGHT 8
|
#define FONT_6X8_SLIM_CHAR_HEIGHT 8
|
||||||
#define FONT_6X8_SLIM_FONT_TYPE (FONT_TYPE_MONOSPACED)
|
#define FONT_6X8_SLIM_FONT_TYPE (FONT_TYPE_MONOSPACED)
|
||||||
#define FONT_6X8_SLIM_ARRAY_LENGTH \
|
#define FONT_6X8_SLIM_ARRAY_LENGTH (FONT_6X8_SLIM_LENGTH * FONT_6X8_SLIM_CHAR_HEIGHT)
|
||||||
(FONT_6X8_SLIM_LENGTH * FONT_6X8_SLIM_CHAR_HEIGHT)
|
|
||||||
|
|
||||||
static const unsigned char font_6x8_slim[FONT_6X8_SLIM_ARRAY_LENGTH] = {
|
static const unsigned char font_6x8_slim[FONT_6X8_SLIM_ARRAY_LENGTH] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 32 < >
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 32 < >
|
||||||
|
|
123
include/arch.h
123
include/arch.h
|
@ -10,16 +10,78 @@
|
||||||
#ifndef ARCH_H
|
#ifndef ARCH_H
|
||||||
#define ARCH_H
|
#define ARCH_H
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
#include <stdint.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 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 cpu_init( );
|
||||||
void gdt_init( );
|
void pic_init( );
|
||||||
|
void pit_init( );
|
||||||
void idt_init( );
|
void idt_init( );
|
||||||
void idt_set_int(uint8_t vector, void *int_handler);
|
void idt_set_int(uint8_t vector, int_entry_t handler);
|
||||||
uint64_t arch_get_tick_b( );
|
uint64_t arch_get_tick_b( );
|
||||||
uint64_t arch_get_tick_l( );
|
uint64_t arch_get_tick_l( );
|
||||||
uint64_t arch_get_tick( );
|
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) {
|
static inline void outb(uint16_t port, uint8_t val) {
|
||||||
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
@ -31,4 +93,61 @@ static inline uint8_t inb(uint16_t port) {
|
||||||
return ret;
|
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
|
#endif // arch.h
|
19
include/fb.h
19
include/fb.h
|
@ -10,6 +10,7 @@
|
||||||
#ifndef FB_H
|
#ifndef FB_H
|
||||||
#define FB_H
|
#define FB_H
|
||||||
|
|
||||||
|
#include <6x8_slim_font.h>
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -26,22 +27,22 @@ enum colors {
|
||||||
DARK_GREEN = 0x013220,
|
DARK_GREEN = 0x013220,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_TICK_BIG arch_get_tick_b( )
|
extern int fb_init_status;
|
||||||
#define GET_TICK_lOW arch_get_tick_l( )
|
extern uint32_t *fb_addr;
|
||||||
|
extern uint64_t width;
|
||||||
|
extern uint64_t height;
|
||||||
|
extern uint16_t bpp;
|
||||||
|
|
||||||
#define SCREEN_WIDTH width
|
#define SCREEN_WIDTH width
|
||||||
#define SCREEN_HEIGHT height
|
#define SCREEN_HEIGHT height
|
||||||
#define SCREEN_BUFFER fb_addr
|
#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);
|
void fb_set_text_color(uint32_t color);
|
||||||
|
uint32_t fb_get_text_color( );
|
||||||
void fb_init( );
|
void fb_init( );
|
||||||
void fb_print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf);
|
void fb_print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf);
|
||||||
void fb_printf(char *str, ...);
|
void log_printf(char *str, ...);
|
||||||
void fb_printf_at(size_t x, size_t y, 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);
|
||||||
|
|
||||||
#endif // fb.h
|
#endif // fb.h
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* 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,16 +14,21 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int lock;
|
int lock;
|
||||||
const char* file;
|
const char *func;
|
||||||
|
int line;
|
||||||
} lock_t;
|
} lock_t;
|
||||||
|
|
||||||
|
#define LOCK(lock) \
|
||||||
|
lock.line = __LINE__; \
|
||||||
|
lock_acquire(lock);
|
||||||
|
|
||||||
#define LOCK_INIT \
|
#define LOCK_INIT \
|
||||||
(lock_t) { \
|
(lock_t) { \
|
||||||
0, __FILE__ \
|
0, __FILE__, __LINE__ \
|
||||||
}
|
}
|
||||||
|
|
||||||
int lock_swap(lock_t* lock);
|
int lock_swap(lock_t lock);
|
||||||
void lock_acquire(lock_t* lock);
|
void lock_acquire(lock_t lock);
|
||||||
void lock_release(lock_t* lock);
|
void lock_release(lock_t lock);
|
||||||
|
|
||||||
#endif // lock.h
|
#endif // lock.h
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* 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
|
|
@ -16,8 +16,15 @@
|
||||||
#define BLOCK_SIZE 4096
|
#define BLOCK_SIZE 4096
|
||||||
#define HHDM_OFFSET (hhdm_request.response->offset)
|
#define HHDM_OFFSET (hhdm_request.response->offset)
|
||||||
|
|
||||||
|
// Вывод состояния всех блоков памяти
|
||||||
void mem_dump_memory( );
|
void mem_dump_memory( );
|
||||||
|
|
||||||
|
// Вывод размеров занятой и освобожденной памяти
|
||||||
|
void mem_get_stat( );
|
||||||
|
|
||||||
|
// Инициализация менеджера памяти
|
||||||
void mem_init( );
|
void mem_init( );
|
||||||
|
|
||||||
void *mem_alloc(size_t size);
|
void *mem_alloc(size_t size);
|
||||||
void mem_add_block(void *addr, size_t size);
|
void mem_add_block(void *addr, size_t size);
|
||||||
void mem_free(void *addr);
|
void mem_free(void *addr);
|
||||||
|
|
129
include/mod.h
129
include/mod.h
|
@ -7,35 +7,128 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <log.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
#ifndef MOD_H
|
#ifndef MOD_H
|
||||||
#define MOD_H
|
#define MOD_H
|
||||||
|
|
||||||
// Максимальное количество модулей 16. Позже перепишем на динамический массив,
|
#define EI_MAG0 0
|
||||||
// сейчас для прототипа это не так важно
|
#define ELFMAG0 0x7f
|
||||||
#define MOD_MAX 16
|
#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; // Малое целое число без знака
|
||||||
|
|
||||||
// Структуры соответствующие ELF заголовкам
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char e_ident[16];
|
elf64_small_t e_ident[16]; // Идентификация ELF
|
||||||
uint16_t e_type;
|
elf64_half_t e_type; // Тип объектного файла
|
||||||
uint16_t e_machine;
|
elf64_half_t e_machine; // Тип компьютера
|
||||||
uint32_t e_version;
|
elf64_word_t e_version; // Версия объектного файла
|
||||||
uint64_t e_entry;
|
elf64_addr_t e_entry; // Адрес точки входа
|
||||||
uint64_t e_phoff;
|
elf64_offset_t e_phoff; // Смещение заголовка программы
|
||||||
uint64_t e_shoff;
|
elf64_offset_t e_shoff; // Смещение заголовка раздела
|
||||||
uint32_t e_flags;
|
elf64_word_t e_flags; // Флаги, зависящие от процессора
|
||||||
uint16_t e_ehsize;
|
elf64_half_t e_ehsize; // Размер заголовка ELF
|
||||||
uint16_t e_phentsize;
|
elf64_half_t e_phentsize; // Размер записи заголовка программы
|
||||||
uint16_t e_phnum;
|
elf64_half_t e_phnum; // Количество записей в заголовке программы
|
||||||
uint16_t e_shentsize;
|
elf64_half_t e_shentsize; // Размер записи в заголовке раздела
|
||||||
uint16_t e_shnum;
|
elf64_half_t e_shnum; // Количество записей в заголовке раздела
|
||||||
uint16_t e_shstrndx;
|
elf64_half_t e_shstrndx; // Строковый табличный индекс названия раздела
|
||||||
} elf64_header_t;
|
} 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_init( );
|
||||||
|
void mod_after_init( );
|
||||||
void mod_list_show( );
|
void mod_list_show( );
|
||||||
module_info_t *mod_find(char *tag);
|
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
|
#endif // mod.h
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef SYS_H
|
#ifndef SYS_H
|
||||||
#define SYS_H
|
#define SYS_H
|
||||||
|
|
||||||
|
#include <arch.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -30,16 +31,6 @@ typedef struct {
|
||||||
void *addr;
|
void *addr;
|
||||||
} module_func_t;
|
} 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 {
|
typedef struct {
|
||||||
int reserved;
|
int reserved;
|
||||||
} func_t;
|
} func_t;
|
||||||
|
@ -52,27 +43,51 @@ typedef struct {
|
||||||
} uid_t;
|
} uid_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t year;
|
uint8_t year;
|
||||||
uint8_t month;
|
uint8_t month;
|
||||||
uint8_t day;
|
uint8_t day;
|
||||||
|
uint8_t hours;
|
||||||
|
uint8_t minutes;
|
||||||
uint8_t second;
|
uint8_t second;
|
||||||
} time_t;
|
} time_t;
|
||||||
|
|
||||||
typedef struct {
|
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 offset;
|
||||||
module_info_t *info;
|
uint64_t id;
|
||||||
void (*fb_printf)(char *str, ...); // Временная функция
|
void (*log_printf)(char *str, ...); // Временная функция
|
||||||
framebuffer_t *(*alloc_framebuffer)( );
|
framebuffer_t (*alloc_framebuffer)( );
|
||||||
void (*free_framebuffer)(framebuffer_t *frame);
|
void (*free_framebuffer)(framebuffer_t *frame);
|
||||||
|
void *(*alloc)(uint64_t size);
|
||||||
|
void (*free)(void *ptr);
|
||||||
void (*exit)(int code);
|
void (*exit)(int code);
|
||||||
int (*get_error)( );
|
int (*get_error)( );
|
||||||
sys_info_t *(*get_info)( );
|
sys_info_t *(*get_info)( );
|
||||||
module_info_t *(*get_module)(char *module_id);
|
module_info_t *(*get_module)(char *module_id);
|
||||||
uint64_t (*new_thread)(uint64_t func);
|
module_info_t *(*mod_list_get)(uint64_t *count);
|
||||||
int (*delete_thread)(uint64_t thread_id);
|
uint64_t (*new_thread)(void (*func)(void *), char *name, void *arg);
|
||||||
|
void (*delete_thread)( );
|
||||||
|
void (*task_switch)( );
|
||||||
time_t (*get_time)( );
|
time_t (*get_time)( );
|
||||||
} env_t;
|
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 sys_install(env_t module);
|
env_t *sys_install(env_t *module);
|
||||||
|
|
||||||
#endif // sys.h
|
#endif // sys.h
|
|
@ -13,21 +13,21 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
||||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||||
|
|
||||||
#define assert(check) \
|
#define assert(check) \
|
||||||
do { \
|
do { \
|
||||||
if (!(check)) { \
|
if (!(check)) { \
|
||||||
fb_printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
|
LOG("\nassert() ошибка в %s() (%s:%d)\n", __func__, __FILE__, __LINE__); \
|
||||||
__FILE__, __LINE__); \
|
|
||||||
for (;;) asm volatile("hlt"); \
|
for (;;) asm volatile("hlt"); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ALIGN_UP(NUM, ALIGN) (((NUM) + ALIGN - 1) & ~(ALIGN - 1))
|
#define ALIGN_UP(NUM, ALIGN) (((NUM) + ALIGN - 1) & ~(ALIGN - 1))
|
||||||
#define ALIGN_DOWN(NUM, ALIGN) ((NUM) & ~(ALIGN - 1))
|
#define ALIGN_DOWN(NUM, ALIGN) ((NUM) & ~(ALIGN - 1))
|
||||||
#define CONTAINER_OF(PTR, TYPE, MEMBER) \
|
#define CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
|
||||||
((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
|
|
||||||
|
|
||||||
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
|
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
|
||||||
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
|
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
|
||||||
|
@ -41,8 +41,12 @@ static inline void pause( ) {
|
||||||
|
|
||||||
void tool_memcpy(void *dest, void *src, uint64_t n);
|
void tool_memcpy(void *dest, void *src, uint64_t n);
|
||||||
void *tool_memset(void *ptr, uint8_t n, uint64_t size);
|
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);
|
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_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);
|
void tool_format(void (*putc)(char c), const char *format_string, va_list args);
|
||||||
|
|
||||||
#endif // tool.h
|
#endif // tool.h
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 1
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_BUILD 505
|
#define VERSION_BUILD 257
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
/**
|
|
||||||
* 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( );
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/**
|
|
||||||
* 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");
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
/**
|
|
||||||
* 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");
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
#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,15 +0,0 @@
|
||||||
.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
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* 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( );
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* 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]); }
|
||||||
|
}
|
|
@ -8,25 +8,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
|
#include <log.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
|
|
||||||
static bool acpi_msrs_support = false;
|
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,
|
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
|
||||||
uint32_t *edx) {
|
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
|
||||||
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) {
|
static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
|
||||||
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
|
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused))
|
static void __attribute__((unused)) msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
|
||||||
msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
|
|
||||||
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
|
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +62,24 @@ static void do_amd( ) {
|
||||||
LOG("cpu_family = [%u]\n", cpu_family);
|
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( ) {
|
static void brandname( ) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
char brand_string[49];
|
char brand_string[49];
|
||||||
|
@ -71,8 +87,7 @@ static void brandname( ) {
|
||||||
uint32_t manufacturer[4];
|
uint32_t manufacturer[4];
|
||||||
char manufacturer_string[13];
|
char manufacturer_string[13];
|
||||||
|
|
||||||
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2],
|
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2], &manufacturer[1]);
|
||||||
&manufacturer[1]);
|
|
||||||
tool_memcpy(manufacturer_string, manufacturer, 12);
|
tool_memcpy(manufacturer_string, manufacturer, 12);
|
||||||
|
|
||||||
brand_string[48] = 0;
|
brand_string[48] = 0;
|
||||||
|
@ -90,29 +105,17 @@ static void brandname( ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manufacturer[0] == 0x68747541) { do_amd( ); }
|
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( ) {
|
void cpu_init( ) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
cpuid(1, &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) {
|
if ((edx >> 22) & 1) {
|
||||||
acpi_msrs_support = true;
|
acpi_msrs_support = true;
|
||||||
LOG("Встроенный терморегулятор MSRS для ACPI\n");
|
LOG("Встроенный терморегулятор MSRS для ACPI\n");
|
||||||
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
|
LOG("Температура: %d (в QEMU/KVM всегда 0)\n", get_cpu_temperature_intel( ));
|
||||||
get_cpu_temperature_intel( ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||||
|
@ -128,9 +131,7 @@ void cpu_init( ) {
|
||||||
"поддерживается!\n");
|
"поддерживается!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((edx >> 10) & 1) {
|
if ((edx >> 10) & 1) { LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n"); }
|
||||||
LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
|
|
||||||
}
|
|
||||||
if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); }
|
if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); }
|
||||||
|
|
||||||
if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); }
|
if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); }
|
||||||
|
@ -138,12 +139,19 @@ void cpu_init( ) {
|
||||||
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); }
|
if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); }
|
||||||
if ((edx >> 4) & 1) {
|
if ((edx >> 4) & 1) { LOG("Аппаратный терморегулятор (HTC) поддерживается!\n"); }
|
||||||
LOG("Аппаратный терморегулятор (HTC) поддерживается!\n");
|
if ((edx >> 5) & 1) { LOG("Программный терморегулятор (STC) поддерживается!\n"); }
|
||||||
}
|
|
||||||
if ((edx >> 5) & 1) {
|
|
||||||
LOG("Программный терморегулятор (STC) поддерживается!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
brandname( );
|
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 ((ecx >> 28) & 1) { LOG("AVX поддерживается!\n"); }
|
||||||
}
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* 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( );
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
#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,9 +1,10 @@
|
||||||
.text
|
.text
|
||||||
.code64
|
.code64
|
||||||
.global isr_stubs
|
.global isr_stubs
|
||||||
.extern exception_handler
|
.extern isr_generic
|
||||||
|
|
||||||
common:
|
common:
|
||||||
|
.align 16
|
||||||
subq $120, %rsp
|
subq $120, %rsp
|
||||||
movq %rbp, 0(%rsp)
|
movq %rbp, 0(%rsp)
|
||||||
movq %rbx, 8(%rsp)
|
movq %rbx, 8(%rsp)
|
||||||
|
@ -22,7 +23,7 @@ common:
|
||||||
movq %rdi, 112(%rsp)
|
movq %rdi, 112(%rsp)
|
||||||
cld
|
cld
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
call exception_handler
|
call isr_generic
|
||||||
movq 0(%rsp), %rbp
|
movq 0(%rsp), %rbp
|
||||||
movq 8(%rsp), %rbx
|
movq 8(%rsp), %rbx
|
||||||
movq 16(%rsp), %r15
|
movq 16(%rsp), %r15
|
||||||
|
@ -40,7 +41,6 @@ common:
|
||||||
movq 112(%rsp), %rdi
|
movq 112(%rsp), %rdi
|
||||||
addq $136, %rsp
|
addq $136, %rsp
|
||||||
iretq
|
iretq
|
||||||
.align 16
|
|
||||||
entry0:
|
entry0:
|
||||||
pushq $0
|
pushq $0
|
||||||
pushq $0
|
pushq $0
|
|
@ -0,0 +1,15 @@
|
||||||
|
.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
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* 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( ));
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 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");
|
||||||
|
}
|
|
@ -7,26 +7,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <fb.h>
|
#include <log.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
|
|
||||||
static uint64_t count = 0;
|
|
||||||
|
|
||||||
static void isr_generic( ) {
|
|
||||||
LOG("\nТик! %u", count++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pit_set_interval(int hz) {
|
void pit_set_interval(int hz) {
|
||||||
int divisor = 1193180 / hz; // Вычисляем делитель
|
int divisor = 1193180 / hz; // Вычисляем делитель
|
||||||
outb(0x43, 0x36); // Устанавливаем байт команды 0x36
|
outb(0x43, 0x34); // Устанавливаем байт команды 0x34
|
||||||
outb(0x40, divisor & 0xFF); // Устанавливаем младший байт делителя
|
outb(0x40, divisor & 0xFF); // Устанавливаем младший байт делителя
|
||||||
outb(0x40, divisor >> 8); // Устанавливаем старший байт делителя
|
outb(0x40, divisor >> 8); // Устанавливаем старший байт делителя
|
||||||
}
|
}
|
||||||
|
|
||||||
void pit_init( ) {
|
void pit_init( ) {
|
||||||
idt_set_int(32, isr_generic);
|
LOG("PIT установлен\n");
|
||||||
pit_set_interval(100);
|
pit_set_interval(1);
|
||||||
asm volatile("sti");
|
|
||||||
}
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/**
|
||||||
|
* 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");
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
.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
|
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
* 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 <6x8_slim_font.h>
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <log.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
|
|
||||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0, .response = (struct limine_framebuffer_response *)0
|
||||||
.revision = 0,
|
|
||||||
.response = (struct limine_framebuffer_response *)0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct limine_framebuffer_response *framebuffer_response;
|
static struct limine_framebuffer_response *framebuffer_response;
|
||||||
static struct limine_framebuffer *boot_framebuffer;
|
static struct limine_framebuffer *boot_framebuffer;
|
||||||
|
|
||||||
|
int fb_init_status = 0;
|
||||||
uint32_t *fb_addr;
|
uint32_t *fb_addr;
|
||||||
uint32_t text_color = GREEN;
|
uint32_t text_color = GREEN;
|
||||||
uint32_t background = DARK_GREEN;
|
uint32_t background = DARK_GREEN;
|
||||||
|
@ -31,19 +31,18 @@ uint64_t width;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
uint64_t pitch;
|
uint64_t pitch;
|
||||||
uint16_t bpp;
|
uint16_t bpp;
|
||||||
|
uint64_t pos_x = 0;
|
||||||
uint64_t pos_x = 4;
|
uint64_t pos_y = 0;
|
||||||
uint64_t pos_y = 4;
|
|
||||||
|
|
||||||
void fb_set_text_color(uint32_t color) {
|
|
||||||
text_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Настройка прослойки графики ядра
|
// Настройка прослойки графики ядра
|
||||||
void fb_init( ) {
|
void fb_init( ) {
|
||||||
framebuffer_response = framebuffer_request.response;
|
framebuffer_response = framebuffer_request.response;
|
||||||
|
|
||||||
if (framebuffer_response == NULL) { asm volatile("hlt"); }
|
if (framebuffer_response == NULL) { return; }
|
||||||
|
|
||||||
|
if (framebuffer_response->framebuffer_count < 1) { return; }
|
||||||
|
|
||||||
|
fb_init_status = framebuffer_response->framebuffer_count;
|
||||||
|
|
||||||
boot_framebuffer = framebuffer_response->framebuffers[0];
|
boot_framebuffer = framebuffer_response->framebuffers[0];
|
||||||
fb_addr = (uint32_t *)boot_framebuffer->address;
|
fb_addr = (uint32_t *)boot_framebuffer->address;
|
||||||
|
@ -54,28 +53,23 @@ void fb_init( ) {
|
||||||
|
|
||||||
for (uint64_t i = 0; i < width * height; i++) { fb_addr[i] = background; }
|
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; }
|
if (framebuffer_response->framebuffer_count == 1) { return; }
|
||||||
|
|
||||||
LOG("Инициализация дополнительных: %u мониторов\n",
|
#ifdef DEBUG_FB
|
||||||
framebuffer_response->framebuffer_count);
|
LOG("Инициализация дополнительных: %u мониторов\n", framebuffer_response->framebuffer_count);
|
||||||
|
#endif
|
||||||
for (uint64_t i = 1; i < framebuffer_response->framebuffer_count; i++) {
|
for (uint64_t i = 1; i < framebuffer_response->framebuffer_count; i++) {
|
||||||
struct limine_framebuffer *framebuffer =
|
struct limine_framebuffer *framebuffer = framebuffer_response->framebuffers[i];
|
||||||
framebuffer_response->framebuffers[i];
|
|
||||||
uint32_t *framebuffer_addr = (uint32_t *)framebuffer->address;
|
uint32_t *framebuffer_addr = (uint32_t *)framebuffer->address;
|
||||||
LOG("[%u]->0x%x %ux%u\n", i, framebuffer->address, framebuffer->width,
|
#ifdef DEBUG_FB
|
||||||
framebuffer->height);
|
LOG("[%u]->0x%x %ux%u\n", i, framebuffer->address, framebuffer->width, framebuffer->height);
|
||||||
for (uint64_t ij = 0; ij < width * height; ij++) {
|
#endif
|
||||||
framebuffer_addr[ij] = background;
|
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,
|
void fb_print_buf(uint64_t x, uint64_t y, uint64_t h, uint64_t w, uint32_t *buf) {
|
||||||
uint32_t *buf) {
|
|
||||||
for (uint64_t j = 0; j < h; j++) {
|
for (uint64_t j = 0; j < h; j++) {
|
||||||
for (uint64_t i = 0; i < w; i++) {
|
for (uint64_t i = 0; i < w; i++) {
|
||||||
uint64_t where = (i + x) + (j + y) * width;
|
uint64_t where = (i + x) + (j + y) * width;
|
||||||
|
@ -84,92 +78,20 @@ void fb_print_buf(uint64_t x, uint64_t y, uint64_t h, uint64_t w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void print_bits(size_t x, size_t y, uint8_t num) {
|
void fb_print_bits(size_t x, size_t y, uint8_t num) {
|
||||||
for (size_t i = 0; i <= 7; i++) {
|
for (size_t i = 0; i <= 7; i++) {
|
||||||
if ((num >> i) & 1) {
|
if ((num >> i) & 1) { SCREEN_BUFFER[x + i + y * SCREEN_WIDTH] = text_color; }
|
||||||
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( ) {
|
void scroll_fb( ) {
|
||||||
size_t last_line_index =
|
size_t last_line_index = (SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH;
|
||||||
(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 y = 0; y < SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT); y++) {
|
||||||
for (uint64_t x = 0; x < SCREEN_WIDTH; x++) {
|
for (uint64_t x = 0; x < SCREEN_WIDTH; x++) {
|
||||||
SCREEN_BUFFER[x + y * SCREEN_WIDTH] =
|
SCREEN_BUFFER[x + y * SCREEN_WIDTH] = SCREEN_BUFFER[x + (y + (FONT_6X8_SLIM_CHAR_HEIGHT)) * 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++) {
|
for (uint64_t i = last_line_index; i < SCREEN_HEIGHT * SCREEN_WIDTH; i++) { SCREEN_BUFFER[i] = background; }
|
||||||
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);
|
|
||||||
}
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* 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,31 +8,36 @@
|
||||||
|
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <log.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
|
|
||||||
// Если не заблокировано - блокируем
|
// Если не заблокировано - блокируем
|
||||||
int lock_swap(lock_t *lock) {
|
int lock_swap(lock_t lock) {
|
||||||
return __sync_bool_compare_and_swap(&lock->lock, 0, 1);
|
if (lock.lock) { return 0; }
|
||||||
|
lock.lock = 1;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запрос блокировки ресурса
|
// Запрос блокировки ресурса
|
||||||
void lock_acquire(lock_t *lock) {
|
void lock_acquire(lock_t lock) {
|
||||||
uint64_t count = 0;
|
uint64_t count = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (lock_swap(lock)) { break; }
|
if (lock_swap(lock)) { break; }
|
||||||
count++;
|
count++;
|
||||||
if (count > 1000000) {
|
if (count > 10000) {
|
||||||
LOG("%s блокировка зависла", lock->file);
|
LOG("%s:%u блокировка зависла", lock.func, lock.line);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
asm volatile("pause");
|
asm volatile("pause");
|
||||||
|
|
||||||
|
if (task_f_init) { task_switch( ); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запрос разблокировки ресурса
|
// Запрос разблокировки ресурса
|
||||||
void lock_release(lock_t *lock) {
|
void lock_release(lock_t lock) {
|
||||||
__sync_bool_compare_and_swap(&lock->lock, 1, 0);
|
if (lock.lock) { lock.lock = 0; }
|
||||||
}
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -1,186 +0,0 @@
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
137
kernel/mem.c
137
kernel/mem.c
|
@ -9,25 +9,34 @@
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <log.h>
|
||||||
#include <mem.h>
|
#include <mem.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <tool.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,
|
.revision = 0,
|
||||||
.response = (struct limine_memmap_response *)0
|
.response = (struct limine_memmap_response *)0 };
|
||||||
};
|
|
||||||
static volatile struct limine_hhdm_request hhdm_request = {
|
|
||||||
.id = LIMINE_HHDM_REQUEST,
|
|
||||||
.revision = 0,
|
|
||||||
.response = (struct limine_hhdm_response *)0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Запрос к загрузчику Limine о виртуальном адресе Higher Half
|
||||||
|
static volatile struct limine_hhdm_request hhdm_request = { .id = LIMINE_HHDM_REQUEST,
|
||||||
|
.revision = 0,
|
||||||
|
.response = (struct limine_hhdm_response *)0 };
|
||||||
|
|
||||||
|
// Менеджер памяти выделяет память отдельными участками (блоками). Информация обо
|
||||||
|
// всех выделенных блоках хранится в виде односвязного списка структур mem_entry_t.
|
||||||
|
// Каждая mem_entry_t содержит информацию об отдельном выделенном блоке памяти
|
||||||
struct mem_entry {
|
struct mem_entry {
|
||||||
|
// Ссылка на следующий элемент списка
|
||||||
struct mem_entry *next;
|
struct mem_entry *next;
|
||||||
|
// Флаг, помечающий память как освобожденную
|
||||||
bool free;
|
bool free;
|
||||||
size_t size;
|
// Поток, владеющий памятью
|
||||||
|
uint64_t task_id;
|
||||||
|
// Размер блока
|
||||||
|
uint64_t size;
|
||||||
|
// Адрес блока
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,27 +59,55 @@ static uint64_t highest = 0;
|
||||||
// Количество записей в карте памяти
|
// Количество записей в карте памяти
|
||||||
static uint64_t mmmap_count = 0;
|
static uint64_t mmmap_count = 0;
|
||||||
|
|
||||||
static const char memory_types[8][82] = {
|
extern task_t *current_task;
|
||||||
"Доступно", "Зарезервировано", "ACPI, можно освободить",
|
extern uint64_t full_init;
|
||||||
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
|
|
||||||
"Ядро и модули", "Буфер кадра"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static const char memory_types[8][82] = { "Доступно", "Зарезервировано", "ACPI, можно освободить",
|
||||||
|
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
|
||||||
|
"Ядро и модули", "Буфер кадра" };
|
||||||
|
|
||||||
|
// Ответ от загрузчика Limine о состоянии памяти
|
||||||
static struct limine_memmap_response *memmap_response;
|
static struct limine_memmap_response *memmap_response;
|
||||||
|
|
||||||
|
// Описание перого выделенного блока памяти - начало списка с данными о памяти
|
||||||
static mem_entry_t *first_node;
|
static mem_entry_t *first_node;
|
||||||
|
|
||||||
void mem_dump_memory( ) {
|
void mem_dump_memory( ) {
|
||||||
mem_entry_t *curr = first_node;
|
mem_entry_t *curr = first_node;
|
||||||
|
|
||||||
|
// Проход по всему списку записей о выделенных блоках памяти
|
||||||
while (curr) {
|
while (curr) {
|
||||||
LOG("->0x%x | %u.%u kb | %s | 0x%x\n", &curr->data, (curr->size) / 1024,
|
if (curr->next) {
|
||||||
(curr->size) % 1024, curr->free ? memory_types[0] : memory_types[1],
|
LOG("->0x%x | %u килобайт | %s | 0x%x | поток %u\n", &curr->data, (curr->size) / 1024,
|
||||||
curr->next);
|
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);
|
||||||
|
}
|
||||||
curr = 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( ) {
|
void mem_check_dynamic_memory( ) {
|
||||||
mem_entry_t *curr = first_node;
|
mem_entry_t *curr = first_node;
|
||||||
uint64_t free_mem = 0;
|
uint64_t free_mem = 0;
|
||||||
|
@ -134,7 +171,12 @@ static void merge_blocks(mem_entry_t *start) {
|
||||||
mem_entry_t *block = start;
|
mem_entry_t *block = start;
|
||||||
while (block->next && block->next->free) {
|
while (block->next && block->next->free) {
|
||||||
block->size += block->next->size + sizeof(mem_entry_t);
|
block->size += block->next->size + sizeof(mem_entry_t);
|
||||||
|
|
||||||
|
if (block->next->next) {
|
||||||
block->next = block->next->next;
|
block->next = block->next->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
block->next = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,12 +219,13 @@ static void *alloc_align(size_t size, size_t alignment) {
|
||||||
mem_entry_t *curr = first_node;
|
mem_entry_t *curr = first_node;
|
||||||
|
|
||||||
while (curr) {
|
while (curr) {
|
||||||
if (curr->free) {
|
if (curr->free && curr->size >= (alignment + sizeof(mem_entry_t) + size)) {
|
||||||
void *addr = curr->data + alignment - 1;
|
void *addr = curr->data + alignment - 1;
|
||||||
addr -= (uintptr_t)addr % alignment + sizeof(mem_entry_t);
|
addr -= (uintptr_t)addr % alignment + sizeof(mem_entry_t);
|
||||||
mem_entry_t *second = (mem_entry_t *)addr;
|
mem_entry_t *second = (mem_entry_t *)addr;
|
||||||
if (curr->size >= (second->data - curr->data + size)) {
|
|
||||||
mem_entry_t *third = (mem_entry_t *)(second->data + size);
|
mem_entry_t *third = (mem_entry_t *)(second->data + size);
|
||||||
|
tool_memset(third, 0, sizeof(mem_entry_t));
|
||||||
|
|
||||||
third->size = curr->size - (third->data - curr->data);
|
third->size = curr->size - (third->data - curr->data);
|
||||||
third->next = curr->next;
|
third->next = curr->next;
|
||||||
|
@ -191,6 +234,9 @@ static void *alloc_align(size_t size, size_t alignment) {
|
||||||
second->size = size;
|
second->size = size;
|
||||||
second->next = third;
|
second->next = third;
|
||||||
second->free = 0;
|
second->free = 0;
|
||||||
|
second->task_id = 0;
|
||||||
|
|
||||||
|
if (task_f_init) { second->task_id = current_task->id; }
|
||||||
|
|
||||||
if (curr != second) {
|
if (curr != second) {
|
||||||
curr->next = second;
|
curr->next = second;
|
||||||
|
@ -200,16 +246,17 @@ static void *alloc_align(size_t size, size_t alignment) {
|
||||||
|
|
||||||
return second->data;
|
return second->data;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mem_alloc(size_t size) {
|
void *mem_alloc(size_t size) {
|
||||||
mem_check_dynamic_memory( );
|
mem_check_dynamic_memory( );
|
||||||
return alloc_align(size, 1);
|
void *data = alloc_align(size, 1);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_free(void *addr) {
|
void mem_free(void *addr) {
|
||||||
|
@ -218,6 +265,7 @@ void mem_free(void *addr) {
|
||||||
if (curr->data == addr) {
|
if (curr->data == addr) {
|
||||||
curr->free = 1;
|
curr->free = 1;
|
||||||
merge_blocks(prev ? prev : curr);
|
merge_blocks(prev ? prev : curr);
|
||||||
|
mem_merge_all_blocks( );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prev = curr;
|
prev = curr;
|
||||||
|
@ -250,19 +298,21 @@ void mem_init( ) {
|
||||||
mmmap_count = memmap_response->entry_count;
|
mmmap_count = memmap_response->entry_count;
|
||||||
struct limine_memmap_entry **mmaps = memmap_response->entries;
|
struct limine_memmap_entry **mmaps = memmap_response->entries;
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEM
|
||||||
LOG("Записей в карте памяти: %u\n", memmap_response->entry_count);
|
LOG("Записей в карте памяти: %u\n", memmap_response->entry_count);
|
||||||
|
#endif
|
||||||
// Обработка каждой записи в карте памяти
|
// Обработка каждой записи в карте памяти
|
||||||
for (uint64_t i = 0; i < mmmap_count; i++) {
|
for (uint64_t i = 0; i < mmmap_count; i++) {
|
||||||
available += mmaps[i]->length;
|
available += mmaps[i]->length;
|
||||||
|
|
||||||
// LOG("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
|
// LOG("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1, mmaps[i]->base, mmaps[i]->length,
|
||||||
// mmaps[i]->base, mmaps[i]->length, memory_types[mmaps[i]->type]);
|
// memory_types[mmaps[i]->type]);
|
||||||
if (mmaps[i]->type == LIMINE_MEMMAP_FRAMEBUFFER) {
|
if (mmaps[i]->type == LIMINE_MEMMAP_FRAMEBUFFER) {
|
||||||
|
#ifdef DEBUG_MEM
|
||||||
LOG("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
|
LOG("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
|
||||||
"килобайт\n",
|
"килобайт\n",
|
||||||
mmaps[i]->length / 1024 / 1024,
|
mmaps[i]->length / 1024 / 1024, (mmaps[i]->length / 1024) % 1024);
|
||||||
(mmaps[i]->length / 1024) % 1024);
|
#endif
|
||||||
}
|
}
|
||||||
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
||||||
|
|
||||||
|
@ -290,30 +340,33 @@ void mem_init( ) {
|
||||||
|
|
||||||
// Освобождаем все доступные фреймы памяти
|
// Освобождаем все доступные фреймы памяти
|
||||||
for (uint64_t i = 0; i < mmmap_count; i++) {
|
for (uint64_t i = 0; i < mmmap_count; i++) {
|
||||||
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
|
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) { bitmap_limit++; }
|
||||||
bitmap_limit++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
||||||
|
|
||||||
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
|
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) { mem_frame_free((void *)mmaps[i]->base + t, 1); }
|
||||||
mem_frame_free((void *)mmaps[i]->base + t, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEM
|
||||||
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||||
LOG("Размер битовой карты: %u\n", bitmap_size);
|
LOG("Размер битовой карты: %u\n", bitmap_size);
|
||||||
alloc_init(mem_frame_alloc(1), BLOCK_SIZE);
|
#endif
|
||||||
LOG("%u мегабайт выделено в динамичную память\n",
|
|
||||||
(256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
alloc_init(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
|
||||||
for (uint64_t i = 256 * 16; i > 0; i -= BLOCK_SIZE) {
|
#ifdef DEBUG_MEM
|
||||||
mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
|
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); }
|
||||||
|
|
||||||
mem_merge_all_blocks( );
|
mem_merge_all_blocks( );
|
||||||
mem_dump_memory( );
|
mem_dump_memory( );
|
||||||
LOG("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
|
#ifdef DEBUG_MEM
|
||||||
(bitmap_available * BLOCK_SIZE) / 1024 / 1024, available / 1024 / 1024);
|
|
||||||
|
LOG("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n", (bitmap_available * BLOCK_SIZE) / 1024 / 1024,
|
||||||
|
available / 1024 / 1024);
|
||||||
|
|
||||||
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||||
LOG("Проверка менеджера памяти\n");
|
#endif
|
||||||
}
|
}
|
170
kernel/mod.c
170
kernel/mod.c
|
@ -9,68 +9,82 @@
|
||||||
|
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <log.h>
|
||||||
#include <mod.h>
|
#include <mod.h>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
|
|
||||||
static volatile struct limine_module_request module_request = {
|
static volatile struct limine_module_request module_request = { .id = LIMINE_MODULE_REQUEST,
|
||||||
.id = LIMINE_MODULE_REQUEST,
|
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
.response = (struct limine_module_response *)0
|
.response = (struct limine_module_response *)0 };
|
||||||
};
|
|
||||||
|
|
||||||
static struct limine_module_response *module_response;
|
static struct limine_module_response *module_response;
|
||||||
uint64_t modules_count = 0;
|
uint64_t modules_count = 0;
|
||||||
module_info_t module_list[MOD_MAX];
|
module_info_t *module_list = NULL;
|
||||||
static char *graphics_module_message = "Графический модуль-объект";
|
static char *graphics_module_message = "Графический модуль-объект";
|
||||||
static char *other_module_message = "Неизвестный тип модуля";
|
static char *other_module_message = "Неизвестный тип модуля";
|
||||||
|
|
||||||
static env_t main_env;
|
static env_t *main_env = NULL;
|
||||||
|
|
||||||
void *bootpng_ptr;
|
void *bootpng_ptr;
|
||||||
uint64_t bootpng_size;
|
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( ) {
|
void mod_list_show( ) {
|
||||||
|
LOG("Список модулей:\n");
|
||||||
for (uint64_t i = 0; i < modules_count; i++) {
|
for (uint64_t i = 0; i < modules_count; i++) {
|
||||||
fb_printf("Имя: %s\n", module_list[i].name);
|
LOG("Имя: %s | ID: %u \n", module_list[i].name ? module_list[i].name : "(NULL)", i);
|
||||||
fb_printf("Описание модуля: %s\n", module_list[i].message);
|
LOG("Описание модуля: %s\n", module_list[i].message ? module_list[i].message : "(NULL)");
|
||||||
fb_printf("Тип модуля: %u\n", module_list[i].type);
|
LOG("Тип модуля: %u\n", module_list[i].type);
|
||||||
fb_printf("Код ошибки модуля: %u\n", module_list[i].err_code);
|
LOG("Код ошибки модуля: %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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Запуск модулей имеющих дополнительную точку входа
|
||||||
|
module_info_t *mod_list_get(uint64_t *count) {
|
||||||
|
*count = modules_count;
|
||||||
|
return module_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Поиск модуля по тегу
|
||||||
module_info_t *mod_find(char *tag) {
|
module_info_t *mod_find(char *tag) {
|
||||||
for (uint64_t i = 0; i < modules_count; i++) {
|
for (uint64_t i = 0; i < modules_count; i++) {
|
||||||
if (!tool_starts_with(module_list[i].name, tag)) {
|
if (module_list[i].name) {
|
||||||
return &module_list[i];
|
if (tool_str_contains(module_list[i].name, tag)) { return &module_list[i]; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (module_info_t *)NULL;
|
return (module_info_t *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_init( ) {
|
void mod_init( ) {
|
||||||
module_response = module_request.response;
|
module_response = module_request.response;
|
||||||
|
|
||||||
uint64_t module_count = module_response->module_count;
|
uint64_t module_count = module_response->module_count;
|
||||||
struct limine_file *module_ptr = (struct limine_file *)0;
|
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++) {
|
for (uint64_t i = 0; i < module_count; i++) {
|
||||||
module_ptr = module_response->modules[i];
|
module_ptr = module_response->modules[i];
|
||||||
|
|
||||||
LOG("[%d] %s [%s] 0x%x Размер: %u\n", i, module_ptr->path,
|
LOG("[%u] %s [%s] 0x%x Размер: %u\n", i, module_ptr->path, module_ptr->cmdline, module_ptr->address,
|
||||||
module_ptr->cmdline, module_ptr->address, module_ptr->size);
|
module_ptr->size);
|
||||||
|
|
||||||
if (modules_count >= MOD_MAX) {
|
if (modules_count >= module_count) {
|
||||||
LOG("Модуль не обработан. Максимум %u модулей!\n", MOD_MAX);
|
LOG("Модуль не обработан. Максимум %u модулей!\n", module_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,35 +103,99 @@ void mod_init( ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tool_starts_with(module_ptr->cmdline, "[MOD]")) {
|
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; // Неизвестный тип модуля
|
module_list[modules_count].type = 255; // Неизвестный тип модуля
|
||||||
modules_count++;
|
modules_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
module_info_t (*module_init)(env_t * env) =
|
module_info_t (*module_init)(env_t * env) = (module_info_t(*)(env_t * env)) elf_entry(module_ptr->address);
|
||||||
(module_info_t(*)(env_t * env))
|
|
||||||
elf_entry((elf64_header_t *)module_ptr->address);
|
|
||||||
|
|
||||||
LOG("\t->Точка входа: 0x%x\n", module_init);
|
if (module_init == NULL) {
|
||||||
|
LOG("Модуль %s неисправен\n", module_ptr->cmdline);
|
||||||
main_env.offset = (uint64_t)module_ptr->address;
|
continue;
|
||||||
main_env.info = (module_info_t *)0;
|
|
||||||
|
|
||||||
sys_install(main_env);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
modules_count++;
|
modules_count++;
|
||||||
}
|
}
|
||||||
LOG("Модулей обработано: %u\n", 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,43 +8,62 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <fb.h>
|
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <log.h>
|
||||||
#include <mem.h>
|
#include <mem.h>
|
||||||
#include <mod.h>
|
#include <mod.h>
|
||||||
#include <tool.h>
|
#include <tool.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
|
||||||
|
uint64_t full_init = 0;
|
||||||
|
|
||||||
// Точка входа
|
// Точка входа
|
||||||
void _start( ) {
|
void _start( ) {
|
||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
|
|
||||||
fb_init( );
|
log_init( );
|
||||||
arch_init( );
|
|
||||||
mem_init( );
|
mem_init( );
|
||||||
|
fb_init( );
|
||||||
|
log_init_mem( );
|
||||||
|
arch_init( );
|
||||||
|
pit_init( );
|
||||||
|
task_init( );
|
||||||
|
task_f_init = 1;
|
||||||
|
mod_init( );
|
||||||
|
|
||||||
fb_set_text_color(0x00FF00);
|
|
||||||
LOG("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
|
LOG("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
|
||||||
"версии %u.%u.%u ***\n",
|
"версии %u.%u.%u %s***\n",
|
||||||
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, KERNEL_GIT_TAG);
|
||||||
|
|
||||||
LOG("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
|
LOG("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
|
||||||
fb_set_text_color(0x00D000);
|
|
||||||
|
|
||||||
mod_init( );
|
time_t time = rtc_get_time( );
|
||||||
// pit_init( );
|
LOG("Время: %u:%u.%u, %u.%u.%u\n", time.hours, time.minutes, time.second, time.day, time.month, time.year);
|
||||||
|
|
||||||
mod_list_show( );
|
full_init = 1;
|
||||||
|
|
||||||
|
task_after_init( );
|
||||||
|
mem_get_stat( );
|
||||||
|
|
||||||
fb_set_text_color(0x00FF00);
|
|
||||||
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
|
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
|
||||||
fb_set_text_color(0x00D000);
|
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;
|
||||||
|
|
||||||
while (1) {
|
prev->next = next;
|
||||||
uint64_t byte = inb(0x60);
|
next->last = prev;
|
||||||
if (byte == 0x1) {
|
|
||||||
LOG("Exit!\n");
|
mem_free(task->stack);
|
||||||
return;
|
mem_free(task);
|
||||||
}
|
}
|
||||||
|
} while (task->id != 0);
|
||||||
|
|
||||||
|
task_switch( );
|
||||||
}
|
}
|
||||||
}
|
}
|
56
kernel/sys.c
56
kernel/sys.c
|
@ -6,16 +6,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fb.h>
|
#include <fb.h>
|
||||||
|
#include <log.h>
|
||||||
|
#include <mem.h>
|
||||||
#include <mod.h>
|
#include <mod.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
module_info_t *current_module;
|
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( ) {}
|
void sys_init( ) {}
|
||||||
|
|
||||||
static framebuffer_t *sys_alloc_framebuffer( ) {
|
static framebuffer_t sys_alloc_framebuffer( ) {
|
||||||
return (framebuffer_t *)0;
|
return (framebuffer_t){
|
||||||
|
.address = fb_addr, .width = width, .height = height, .pitch = pitch, .bpp = bpp, .reserved = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sys_free_framebuffer(framebuffer_t *frame) {
|
static void sys_free_framebuffer(framebuffer_t *frame) {
|
||||||
|
@ -38,29 +49,24 @@ static module_info_t *sys_get_module(char *module_id) {
|
||||||
return (module_info_t *)mod_find(module_id);
|
return (module_info_t *)mod_find(module_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sys_new_thread(uint64_t func) {
|
env_t *sys_install(env_t *module) {
|
||||||
return func;
|
module->log_printf = &log_printf;
|
||||||
}
|
module->alloc_framebuffer = &sys_alloc_framebuffer;
|
||||||
|
module->free_framebuffer = &sys_free_framebuffer;
|
||||||
static int sys_delete_thread(uint64_t thread_id) {
|
module->alloc = &mem_alloc;
|
||||||
return thread_id;
|
module->free = &mem_free;
|
||||||
}
|
module->exit = &sys_exit;
|
||||||
|
module->get_error = &sys_get_error;
|
||||||
static time_t sys_get_time( ) {
|
module->get_info = &sys_get_info;
|
||||||
return (time_t){ .year = 2023, .month = 10, .day = 31, .second = 1 };
|
module->get_module = &sys_get_module;
|
||||||
}
|
module->mod_list_get = &mod_list_get;
|
||||||
|
module->new_thread = &task_new_thread;
|
||||||
env_t sys_install(env_t module) {
|
module->delete_thread = &task_del_current;
|
||||||
module.fb_printf = &fb_printf;
|
module->task_switch = &task_switch;
|
||||||
module.alloc_framebuffer = &sys_alloc_framebuffer;
|
module->get_time = &rtc_get_time;
|
||||||
module.free_framebuffer = &sys_free_framebuffer;
|
module->set_int = &idt_set_int;
|
||||||
module.exit = &sys_exit;
|
module->mod_update_info = &mod_update_info;
|
||||||
module.get_error = &sys_get_error;
|
module->ret = NULL;
|
||||||
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;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
* task.c
|
|
||||||
* Управление потоками
|
|
||||||
*
|
|
||||||
* Данный файл содержит функции для создания и удаления потоков.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void task_init( ) {}
|
|
||||||
|
|
||||||
void task_new_thread( ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void task_delete_thread( ) {
|
|
||||||
return;
|
|
||||||
}
|
|
145
kernel/tool.c
145
kernel/tool.c
|
@ -23,6 +23,17 @@ void *tool_memset(void *ptr, uint8_t n, uint64_t size) {
|
||||||
return ptr;
|
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 tool_strlen(const char *str) {
|
||||||
uint64_t length = 0;
|
uint64_t length = 0;
|
||||||
while (*str) {
|
while (*str) {
|
||||||
|
@ -32,6 +43,27 @@ uint64_t tool_strlen(const char *str) {
|
||||||
return length;
|
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 tool_starts_with(const char *str, const char *prefix) {
|
||||||
uint64_t str_len = tool_strlen(str);
|
uint64_t str_len = tool_strlen(str);
|
||||||
uint64_t prefix_len = tool_strlen(prefix);
|
uint64_t prefix_len = tool_strlen(prefix);
|
||||||
|
@ -45,6 +77,24 @@ uint64_t tool_starts_with(const char *str, const char *prefix) {
|
||||||
return 1;
|
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) {
|
void tool_reverse_str(char *str) {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
@ -62,6 +112,14 @@ 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"
|
// Преобразование целого числа "i" в системе счисления "base" в строку "buf"
|
||||||
void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
|
void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
|
@ -78,10 +136,7 @@ void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
|
||||||
int64_t remainder = i % base;
|
int64_t remainder = i % base;
|
||||||
// Преобразовываем остаток в символ и добавляем его в строку
|
// Преобразовываем остаток в символ и добавляем его в строку
|
||||||
buf[index++] =
|
buf[index++] =
|
||||||
(remainder > 9)
|
(remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; // Если остаток > 9, добавляем заглавную букву А
|
||||||
? (remainder - 10) + 'A'
|
|
||||||
: remainder +
|
|
||||||
'0'; // Если остаток > 9, добавляем заглавную букву А
|
|
||||||
i /= base;
|
i /= base;
|
||||||
} while (i > 0);
|
} while (i > 0);
|
||||||
|
|
||||||
|
@ -104,10 +159,7 @@ void tool_uint_to_str(uint64_t i, uint8_t base, char *buf) {
|
||||||
uint64_t remainder = i % base;
|
uint64_t remainder = i % base;
|
||||||
// Преобразовываем остаток в символ и добавляем его в строку
|
// Преобразовываем остаток в символ и добавляем его в строку
|
||||||
buf[index++] =
|
buf[index++] =
|
||||||
(remainder > 9)
|
(remainder > 9) ? (remainder - 10) + 'A' : remainder + '0'; // Если остаток > 9, добавляем заглавную букву А
|
||||||
? (remainder - 10) + 'A'
|
|
||||||
: remainder +
|
|
||||||
'0'; // Если остаток > 9, добавляем заглавную букву А
|
|
||||||
i /= base;
|
i /= base;
|
||||||
} while (i > 0);
|
} while (i > 0);
|
||||||
|
|
||||||
|
@ -118,18 +170,67 @@ void tool_uint_to_str(uint64_t i, uint8_t base, char *buf) {
|
||||||
tool_reverse_str(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,
|
void tool_format(void (*putc)(char c), const char *format_string, va_list args) {
|
||||||
va_list args) {
|
|
||||||
while (*format_string != '\0') {
|
while (*format_string != '\0') {
|
||||||
if (*format_string == '%') {
|
if (*format_string == '%') {
|
||||||
char buf[48];
|
char buf[48];
|
||||||
uint64_t point = 0;
|
uint64_t point = 0;
|
||||||
const char *arg_s;
|
char *arg_s;
|
||||||
int64_t arg_d = 0;
|
int64_t arg_d = 0;
|
||||||
uint64_t arg_u = 0;
|
uint64_t arg_u = 0;
|
||||||
|
int64_t width = 0;
|
||||||
|
|
||||||
format_string++;
|
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') {
|
if (*format_string == '\0') {
|
||||||
break; // Неожиданный конец строки формата
|
break; // Неожиданный конец строки формата
|
||||||
}
|
}
|
||||||
|
@ -138,12 +239,19 @@ void tool_format(void (*putc)(char c), const char *format_string,
|
||||||
case '%': putc('%'); break;
|
case '%': putc('%'); break;
|
||||||
case 'c': putc(va_arg(args, int)); break;
|
case 'c': putc(va_arg(args, int)); break;
|
||||||
case 's':
|
case 's':
|
||||||
arg_s = va_arg(args, const char *);
|
arg_s = va_arg(args, char *);
|
||||||
|
|
||||||
|
if (width) { width -= tool_strlen(arg_s); }
|
||||||
|
|
||||||
// Вывод каждого символа строки
|
// Вывод каждого символа строки
|
||||||
while (*arg_s != '\0') {
|
while (*arg_s != '\0') {
|
||||||
putc(*arg_s);
|
putc(*arg_s);
|
||||||
arg_s++;
|
arg_s++;
|
||||||
}
|
}
|
||||||
|
while (width > 0) {
|
||||||
|
putc(' ');
|
||||||
|
width--;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
arg_d = va_arg(args, int64_t);
|
arg_d = va_arg(args, int64_t);
|
||||||
|
@ -152,11 +260,10 @@ void tool_format(void (*putc)(char c), const char *format_string,
|
||||||
putc(buf[point]);
|
putc(buf[point]);
|
||||||
point++;
|
point++;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
arg_u = va_arg(args, uint64_t);
|
arg_u = va_arg(args, uint64_t);
|
||||||
tool_uint_to_str(arg_u, 10, buf);
|
tool_uint_to_wstr(arg_u, 10, buf, width);
|
||||||
while (buf[point] != '\0') {
|
while (buf[point] != '\0') {
|
||||||
putc(buf[point]);
|
putc(buf[point]);
|
||||||
point++;
|
point++;
|
||||||
|
@ -164,15 +271,7 @@ void tool_format(void (*putc)(char c), const char *format_string,
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
arg_u = va_arg(args, uint64_t);
|
arg_u = va_arg(args, uint64_t);
|
||||||
tool_uint_to_str(arg_u, 16, buf);
|
tool_uint_to_wstr(arg_u, 16, buf, width);
|
||||||
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') {
|
while (buf[point] != '\0') {
|
||||||
putc(buf[point]);
|
putc(buf[point]);
|
||||||
point++;
|
point++;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
libmod.a
|
|
@ -0,0 +1,11 @@
|
||||||
|
#/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
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* 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,76 +9,58 @@
|
||||||
#ifndef SYSTEM_H
|
#ifndef SYSTEM_H
|
||||||
#define SYSTEM_H
|
#define SYSTEM_H
|
||||||
|
|
||||||
typedef unsigned char uint8_t;
|
#include <modstd.h>
|
||||||
typedef unsigned short uint16_t;
|
#include <types.h>
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned long long uint64_t;
|
|
||||||
typedef long long int64_t;
|
|
||||||
|
|
||||||
typedef struct {
|
extern void *(*alloc)(uint64_t size);
|
||||||
int reserved;
|
extern void (*free)(void *ptr);
|
||||||
} framebuffer_t;
|
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 {
|
void init_env(env_t *loader_env);
|
||||||
int reserved;
|
void *realloc(void *addr, size_t size);
|
||||||
} sys_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
static inline void outb(uint16_t port, uint8_t val) {
|
||||||
char *name;
|
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
void *addr;
|
}
|
||||||
} module_func_t;
|
|
||||||
|
|
||||||
typedef struct {
|
static inline uint8_t inb(uint16_t port) {
|
||||||
char *name;
|
uint8_t ret;
|
||||||
char *message;
|
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
uint64_t type;
|
return ret;
|
||||||
uint64_t data_size;
|
}
|
||||||
void *data;
|
|
||||||
int64_t err_code;
|
|
||||||
uint64_t module_id;
|
|
||||||
} module_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
static inline void outw(uint16_t port, uint16_t val) {
|
||||||
int reserved;
|
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
|
||||||
} func_t;
|
}
|
||||||
|
|
||||||
typedef struct {
|
static inline uint16_t inw(uint16_t port) {
|
||||||
uint8_t a[4];
|
uint16_t ret;
|
||||||
uint8_t b[4];
|
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
uint8_t c[4];
|
return ret;
|
||||||
uint8_t d[4];
|
}
|
||||||
} uid_t;
|
|
||||||
|
|
||||||
typedef struct {
|
static inline uint32_t inl(uint16_t port) {
|
||||||
uint16_t year;
|
uint32_t data;
|
||||||
uint8_t month;
|
asm volatile("inl %1, %0" : "=a"(data) : "Nd"(port));
|
||||||
uint8_t day;
|
return data;
|
||||||
uint8_t second;
|
}
|
||||||
} time_t;
|
|
||||||
|
|
||||||
typedef struct {
|
static inline void outl(uint16_t port, uint32_t data) {
|
||||||
uint64_t offset;
|
asm volatile("outl %0, %1" : : "a"(data), "Nd"(port));
|
||||||
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
|
#endif // system.h
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/**
|
||||||
|
* 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,7 +1,16 @@
|
||||||
#/bin/sh
|
#/bin/sh
|
||||||
echo "Название: CPUBENCH"
|
echo "Название: CPUBENCH"
|
||||||
echo "Лицензия: Публичное достояние"
|
echo "Лицензия: Публичное достояние"
|
||||||
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
|
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
|
||||||
cp cpubench.ko ../bin/
|
cp cpubench.ko ../bin/
|
||||||
echo "Сборка завершена, файл: cpubench.ko"
|
echo "Сборка завершена, файл: cpubench.ko"
|
||||||
|
|
|
@ -2,59 +2,92 @@
|
||||||
|
|
||||||
static char fxsave_region[512] __attribute__((aligned(16)));
|
static char fxsave_region[512] __attribute__((aligned(16)));
|
||||||
|
|
||||||
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
|
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
|
||||||
uint32_t *ecx, uint32_t *edx) {
|
asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
|
||||||
asm volatile("cpuid"
|
|
||||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
|
||||||
: "a"(leaf));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void L1_cache_size( ) {
|
static inline void L1_cache_size( ) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||||
if ((edx & 0xFF) == 0) {
|
if ((edx & 0xFF) == 0) {
|
||||||
fb_printf("L1 кэш недоступен\n");
|
log_printf("L1 кэш недоступен\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fb_printf(
|
log_printf("L1: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", ecx & 0xFF, (ecx >> 12) & 0x07,
|
||||||
"L1: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
|
(ecx >> 16) & 0xFFff);
|
||||||
ecx & 0xff, (ecx >> 12) & 0x07, (ecx >> 16) & 0xffff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void L2_cache_size( ) {
|
static inline void L2_cache_size( ) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||||
if ((edx & 0xFF) == 0) {
|
if ((edx & 0xFF) == 0) {
|
||||||
fb_printf("L2 кэш недоступен\n");
|
log_printf("L2 кэш недоступен\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fb_printf(
|
log_printf("L2: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", ecx & 0xFF, (ecx >> 12) & 0x0F,
|
||||||
"L2: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
|
(ecx >> 16) & 0xFFFF);
|
||||||
ecx & 0xff, (ecx >> 12) & 0x0F, (ecx >> 16) & 0xFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void L3_cache_size( ) {
|
static inline void L3_cache_size( ) {
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||||
if ((edx & 0xFF) == 0) {
|
if ((edx & 0xFF) == 0) {
|
||||||
fb_printf("L3 кэш недоступен\n");
|
log_printf("L3 кэш недоступен\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fb_printf(
|
log_printf("L3: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n", edx & 0xFF, (edx >> 12) & 0x0F,
|
||||||
"L3: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
|
(edx >> 16) & 0xFFFF);
|
||||||
edx & 0xff, (edx >> 12) & 0x0F, (edx >> 16) & 0xFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_info_t init(env_t *env) {
|
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;
|
||||||
|
|
||||||
init_env(env);
|
init_env(env);
|
||||||
|
|
||||||
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
if (ecx & (1 << 31)) {
|
||||||
|
log_printf("Запуск на эмуляторе\n");
|
||||||
|
} else {
|
||||||
|
log_printf("Запуск на физическом процессоре\n");
|
||||||
|
}
|
||||||
|
|
||||||
L1_cache_size( );
|
L1_cache_size( );
|
||||||
L2_cache_size( );
|
L2_cache_size( );
|
||||||
L3_cache_size( );
|
L3_cache_size( );
|
||||||
|
|
||||||
return (module_info_t){
|
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||||
.name = (char *)"CPUBENCH",
|
if (eax >= 0x8000001E) { cpu_info( ); }
|
||||||
|
|
||||||
|
env->ret = &((module_info_t){ .name = (char *)"CPUBENCH",
|
||||||
.message = (char *)"Дополнительная информация о процессоре",
|
.message = (char *)"Дополнительная информация о процессоре",
|
||||||
|
.type = 0,
|
||||||
|
.data_size = 0,
|
||||||
|
.data = (void *)0,
|
||||||
.err_code = 0,
|
.err_code = 0,
|
||||||
};
|
.module_id = 0,
|
||||||
|
.irq = 0,
|
||||||
|
.irq_handler = 0,
|
||||||
|
.get_func = 0,
|
||||||
|
.after_init = 0 });
|
||||||
|
mod_update_info(env);
|
||||||
|
delete_thread( );
|
||||||
}
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
PureDOOM.h
|
||||||
|
*.wad
|
|
@ -0,0 +1,20 @@
|
||||||
|
#/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"
|
|
@ -0,0 +1,27 @@
|
||||||
|
#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,7 +1,17 @@
|
||||||
#/bin/sh
|
#/bin/sh
|
||||||
echo "Название: Hello world"
|
echo "Название: Hello world"
|
||||||
echo "Лицензия: Публичное достояние"
|
echo "Лицензия: Публичное достояние"
|
||||||
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
|
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
|
||||||
|
|
||||||
cp hello.ko ../bin/
|
cp hello.ko ../bin/
|
||||||
echo "Сборка завершена, файл: hello.ko"
|
echo "Сборка завершена, файл: hello.ko"
|
||||||
|
|
|
@ -1,14 +1,82 @@
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
|
|
||||||
static const char name[] = "Привет мир!";
|
static const char name[] = "[APP]Привет мир!";
|
||||||
static const char message[] = "Привет из модуля!";
|
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";
|
||||||
|
|
||||||
module_info_t init(env_t *env) {
|
static int app_main( ) {
|
||||||
init_env(env);
|
log_printf("[%s]\n", message);
|
||||||
fb_printf("[%s]\n", message);
|
return 2 + 2;
|
||||||
return (module_info_t){
|
}
|
||||||
.name = (char *)&name,
|
|
||||||
.message = (char *)&message,
|
void __attribute__((section(".minit"))) init(env_t *env) {
|
||||||
.err_code = 2023,
|
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,
|
||||||
|
.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( );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#/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"
|
|
@ -0,0 +1,171 @@
|
||||||
|
#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( );
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#/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"
|
|
@ -0,0 +1,122 @@
|
||||||
|
#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( ); }
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"info": "Официальный репозиторий модулей",
|
||||||
|
"git": "https://git.synapseos.ru/Aren/BMOSP_repo.git",
|
||||||
|
"list": [
|
||||||
|
"https://git.synapseos.ru/Aren/BMOSP_repo/raw/branch/master/list.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,7 +0,0 @@
|
||||||
#/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"
|
|
|
@ -1,65 +0,0 @@
|
||||||
#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,7 +1,23 @@
|
||||||
#/bin/sh
|
#/bin/sh
|
||||||
echo "Название: PCI"
|
echo "Название: PCI"
|
||||||
echo "Лицензия: Публичное достояние"
|
echo "Лицензия: Публичное достояние"
|
||||||
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
|
|
||||||
|
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
|
||||||
|
|
||||||
cp pci.ko ../bin/
|
cp pci.ko ../bin/
|
||||||
|
cp pci_data.ko ../bin/
|
||||||
|
cp pci_vendors.txt ../bin/
|
||||||
|
|
||||||
echo "Сборка завершена, файл: pci.ko"
|
echo "Сборка завершена, файл: pci.ko"
|
||||||
|
|
|
@ -5,54 +5,72 @@ typedef struct {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
} vendor_t;
|
} vendor_t;
|
||||||
|
|
||||||
static inline uint32_t inl(uint16_t port) {
|
static vendor_t **vendor_list;
|
||||||
uint32_t data;
|
static uint64_t num_vendors;
|
||||||
asm volatile("inl %1, %0" : "=a"(data) : "Nd"(port));
|
|
||||||
return data;
|
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 void outl(uint16_t port, uint32_t data) {
|
static inline uint16_t pci_read_word(uint16_t bus, uint16_t slot, uint16_t func, uint16_t offset) {
|
||||||
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 address;
|
||||||
uint64_t lbus = (uint64_t)bus;
|
uint64_t lbus = (uint64_t)bus;
|
||||||
uint64_t lslot = (uint64_t)slot;
|
uint64_t lslot = (uint64_t)slot;
|
||||||
uint64_t lfunc = (uint64_t)func;
|
uint64_t lfunc = (uint64_t)func;
|
||||||
uint16_t tmp = 0;
|
uint16_t tmp = 0;
|
||||||
address = (uint64_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) |
|
address = (uint64_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) | ((uint32_t)0x80000000));
|
||||||
(offset & 0xFC) | ((uint32_t)0x80000000));
|
|
||||||
outl(0xCF8, address);
|
outl(0xCF8, address);
|
||||||
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
|
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
|
||||||
return (tmp);
|
return (tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t get_vendor_id(uint16_t bus, uint16_t device,
|
static inline uint16_t get_vendor_id(uint16_t bus, uint16_t slot, uint16_t function) {
|
||||||
uint16_t function) {
|
uint32_t r0 = pci_read_word(bus, slot, function, 0);
|
||||||
uint32_t r0 = pci_read_word(bus, device, function, 0);
|
|
||||||
return r0;
|
return r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t get_device_id(uint16_t bus, uint16_t device,
|
static inline uint16_t get_device_id(uint16_t bus, uint16_t slot, uint16_t function) {
|
||||||
uint16_t function) {
|
uint32_t r0 = pci_read_word(bus, slot, function, 2);
|
||||||
uint32_t r0 = pci_read_word(bus, device, function, 2);
|
|
||||||
return r0;
|
return r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t get_class_id(uint16_t bus, uint16_t device,
|
static inline uint16_t get_class_id(uint16_t bus, uint16_t slot, uint16_t function) {
|
||||||
uint16_t function) {
|
uint32_t r0 = pci_read_word(bus, slot, function, 0xA);
|
||||||
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
|
|
||||||
return (r0 & ~0x00FF) >> 8;
|
return (r0 & ~0x00FF) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t get_sub_class_id(uint16_t bus, uint16_t device,
|
static inline uint16_t get_sub_class_id(uint16_t bus, uint16_t slot, uint16_t function) {
|
||||||
uint16_t function) {
|
uint32_t r0 = pci_read_word(bus, slot, function, 0xA);
|
||||||
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
|
|
||||||
return (r0 & ~0xFF00);
|
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( ) {
|
static inline void scan( ) {
|
||||||
uint64_t devices = 0;
|
uint64_t devices = 0;
|
||||||
for (uint32_t bus = 0; bus < 256; bus++) {
|
for (uint32_t bus = 0; bus < 256; bus++) {
|
||||||
|
@ -65,21 +83,65 @@ static inline void scan( ) {
|
||||||
uint16_t device_id = get_device_id(bus, slot, function);
|
uint16_t device_id = get_device_id(bus, slot, function);
|
||||||
uint16_t class_id = get_class_id(bus, slot, function);
|
uint16_t class_id = get_class_id(bus, slot, function);
|
||||||
|
|
||||||
fb_printf("[%u] vendor: 0x%x, device: 0x%x, class: %u\n",
|
uint16_t status = pci_read_word(bus, slot, function, 0x6);
|
||||||
devices, vendor, device_id, class_id);
|
/*
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
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++;
|
devices++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module_info_t init(env_t *env) {
|
void __attribute__((section(".minit"))) init(env_t *env) {
|
||||||
init_env(env);
|
init_env(env);
|
||||||
scan( );
|
|
||||||
return (module_info_t){
|
log_printf("pci_data %x\n", 1);
|
||||||
.name = (char *)"[PCI]",
|
module_info_t *pci_data = get_module("[PCI][ADAPTER]");
|
||||||
.message = (char *)"PCI драйвер",
|
log_printf("pci_data %x\n", pci_data);
|
||||||
.err_code = 0,
|
|
||||||
};
|
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,
|
||||||
|
.err_code = 0,
|
||||||
|
.module_id = 0,
|
||||||
|
.irq = 0,
|
||||||
|
.irq_handler = 0,
|
||||||
|
.get_func = 0,
|
||||||
|
.after_init = 0 });
|
||||||
|
mod_update_info(env);
|
||||||
|
delete_thread( );
|
||||||
}
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#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( );
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
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.
|
|
@ -1,7 +0,0 @@
|
||||||
#/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"
|
|
|
@ -1,18 +0,0 @@
|
||||||
#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 };
|
|
||||||
}
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#/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"
|
|
@ -0,0 +1,165 @@
|
||||||
|
#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 */
|
||||||
|
};
|
|
@ -0,0 +1,168 @@
|
||||||
|
#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( );
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#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;
|
|
@ -1,7 +0,0 @@
|
||||||
#/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"
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue