Compare commits

...

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

74 changed files with 368 additions and 4925 deletions

View File

@ -1,30 +0,0 @@
ColumnLimit: 80
IndentWidth: 4
UseTab: ForIndentation
TabWidth: 4
SpacesBeforeTrailingComments: 1
NamespaceIndentation: None
AlignConsecutiveAssignments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortCaseLabelsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: true
IndentCaseLabels: true
KeepEmptyLinesAtTheStartOfBlocks: false
PointerAlignment: Right
ContinuationIndentWidth: 4
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles: false
SpaceInEmptyParentheses: true
IndentPPDirectives: None
IncludeBlocks: Preserve
Cpp11BracedListStyle: false
Standard: Cpp11

View File

@ -1,38 +0,0 @@
name: CI BUILD
on:
push:
branches-ignore: [ "pages" ]
pull_request:
branches-ignore: [ "pages" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: install depends
run: sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
- name: install limine
run: |
git clone https://git.synapseos.ru/Aren/limine.git --branch=v5.x-branch-binary --depth=1
cd limine && make && cd ..
- name: build
run: |
dos2unix *.sh
chmod +x build.sh
./build.sh
- name: check root dir
run: ls -la
- name: check iso_root
run: ls -la iso_root
- name: check bin
run: ls -la bin

24
.gitignore vendored
View File

@ -1,12 +1,12 @@
bmosp.hdd
bmosp.iso
bin/
limine/
ovmf/
iso_root/
output/
sdk/
*.so
*.o
*.ko
*.elf
limine/
iso_root/*
bin/*
output/*
*.elf
*.o
*.fd
*.so
*.hdd
*.iso
*.ko

18
.vscode/settings.json vendored
View File

@ -1,18 +0,0 @@
{
"C_Cpp.errorSquiggles": "disabled",
"files.associations": {
"array": "cpp",
"bitset": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"complex": "cpp",
"string": "cpp",
"limine.h": "c",
"tool.h": "c",
"sys.h": "c",
"arch.h": "c",
"fb.h": "c",
"system.h": "c",
"mod.h": "c"
}
}

View File

@ -1,6 +1,12 @@
# Сборка из исходного кода
# Сборка и запуск
## Ubuntu 18.04+
Для сборки нужен gcc собранный под архитектуру x86_64. Clang не рекомендуется для использования.
## Сборка из исходного кода
Понадобится Python версии 3.7 и новее. Для сборки на Windows используйте WSL или виртуальную машину.
### Ubuntu 18.04+
```bash
sudo apt install clang-format python3 git qemu-system-x86 gdisk dos2unix xorriso
@ -10,7 +16,7 @@ chmod +x build.sh
./build.sh
```
## Astra Linux
### Astra Linux
На текущий момент доступна только сборка ISO образов
В qemu недоступен флаг `-cpu max`, просто уберите его при запуске
@ -22,7 +28,7 @@ cd BMOSP/
python3.7 pbuild.py
```
## ArchLinux
### ArchLinux
Модули грузятся с ошибкой
@ -37,7 +43,9 @@ chmod +x build.sh
## Запуск
## Qemu
Помимо использования VirtualBox, Qemu, VMware и других эмуляторов допускается запись hdd (raw) образа на флэшку в режиме dd.
### Qemu
Стандартная конфигурация загрузки с HDD
@ -61,4 +69,4 @@ chmod +x run.sh
## Предупреждение
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
Мы не несем ответственности за нанесенный ущерб.
Мы не несем ответственности за нанесенный ущерб.

View File

@ -11,4 +11,8 @@
## 21.10.2023
- Выпуск релиза 0.1.231
- Перевод кодовой базы с C++ на язык C
- Перевод кодовой базы с C++ на язык C
## 21.10.2023
- Выпуск релиза 0.1.367

70
HOMEWORK.md Normal file
View File

@ -0,0 +1,70 @@
# Задания для домашней работы
## Ковальски, анализ
Напишите программу, которая использует функцию `sys_get_info` для получения информации о текущей системе.
Выведите полученную информацию в удобочитаемом формате.
## Что мы можем?
Напишите программу, которая использует функцию `sys_get_module` для получения информации о произвольном модуле.
Выведите полученную информацию на экран.
## От 1 до миллиона
Напишите программу, которая использует функцию `mem_alloc` для выделения блока памяти размером 4000000 байт.
Заполните этот блок памяти числами от 1 до 1 000 000 и найдите сумму всех чисел.
Используйте функцию `mem_free` для освобождения блока памяти. Проверьте, что блок памяти успешно освобожден.
## Улыбочку
Напишите программу, которая использует функцию `sys_alloc_framebuffer` для выделения памяти под буфер кадра.
Затем нарисуйте смайлик заполняя буффер.
Используйте функцию `sys_free_framebuffer` для освобождения памяти.
## Многопоточность
Напишите программу, которая использует функцию `sys_new_thread` для создания нового потока выполнения.
В этом потоке выполнения реализуйте алгоритм сортировки массива чисел. Выведите отсортированный массив на экран. Используйте функцию `sys_exit` для завершения выполнения потока или функцию `sys_delete_thread` для удаления потока выполнения.
## Матрица
Напишите программу, которая использует двумерный массив для создания и отображения матрицы размером 3x3.
Попросите пользователя ввести значения элементов матрицы, а затем выведите ее на экран.
## Проверка на палиндром
Напишите программу, которая проверяет, является ли введенная пользователем строка палиндромом.
Палиндром - это строка, которая читается одинаково слева направо и справа налево. Выведите сообщение "Это палиндром" или "Это не палиндром" в зависимости от результата проверки.
## Проверка на анаграмму
Напишите программу, которая проверяет, являются ли две введенные пользователем строки анаграммами, то есть состоят ли они из одних и тех же символов. Выведите сообщение "Это анаграммы" или "Это не анаграммы" в зависимости от результата проверки.
## Генератор псевдослучайных чисел
Напишите программу, которая генерирует и выводит на экран псевдослучайное число от 1 до 100.
Пример функции для генерации псевдослучайных чисел:
```C
static unsigned long int next = 1;
int rand() {
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32768;
}
```
## Перевод числа в двоичную систему счисления
Напишите программу, которая позволяет пользователю ввести число в десятичной системе счисления и выводит его в двоичной системе счисления.

1
KERNEL.md Normal file
View File

@ -0,0 +1 @@
# Строение ядра

73
LICENSE
View File

@ -1,73 +0,0 @@
ГОСУДАРСТВЕННАЯ ОТКРЫТАЯ ЛИЦЕНЗИЯ, ВЕРСИЯ 1.1
Пояснение к лицензии:
Любое заинтересованное лицо может по своему усмотрению применять Государственную открытую лицензию, версия 1.0 (далее Лицензия) в целях передачи права на использование конкретной программы для ЭВМ (далее программа или программное обеспечение). Передача права на использование программы не должна нарушать права других лиц в отношении данной программы. Поэтому лицо, передающее право на использование программы на условиях настоящей Лицензии, должно обладать исключительным правом или должно быть иным образом управомочено на передачу права на использование данной программы.
Лицензия составлена согласно нормам действующего законодательства Российской Федерации, предназначена для использования в качестве типовой Лицензии при лицензировании программ для ЭВМ.
Лицензия предназначена для программ, соответствующих определению свободного программного обеспечения по ГОСТ Р 54593-2011 «Информационные технологии (ИТ). Свободное программное обеспечение. Общие положения». Каждый вправе копировать и распространять со своим свободным программным обеспечением экземпляры настоящей Лицензии без внесения изменений в ее текст.
Если в текст Лицензии внесены любые иные изменения или дополнения, то наименование получившегося лицензионного договора должно отличаться от наименования настоящей Лицензии.
Права на переработку, внесение изменений и дополнений (включая передачу этого права другому юридическому лицу), а также подготовку и выпуск новых версий Лицензии в качестве типовой принадлежат Министерству цифрового развития, связи и массовых коммуникаций Российской Федерации (digital.gov.ru), которое не несет ответственности за любые потери или убытки, возникшие в связи с применением этой Лицензии, в том числе по причине возможных юридических ошибок или неточностей лицензионных положений.
Допускается копирование и распространение текста настоящего пояснения и Лицензии, а также перевод на любой другой язык для ознакомительных целей.
НАЧАЛО ТЕКСТА ЛИЦЕНЗИИ
ГОСУДАРСТВЕННАЯ ОТКРЫТАЯ ЛИЦЕНЗИЯ
ВЕРСИЯ 1.1, 25 июня 2021 г.
1. ОПРЕДЕЛЕНИЯ
"Лицензиар" юридическое лицо (организация), публично-правовое образование (государство или муниципальное образование) или физическое лицо, передавшее Лицензиату право на использование программы для ЭВМ на условиях настоящей Лицензии.
"Лицензиат" юридическое лицо (организация), публично-правовое образование (государство или муниципальное образование) или физическое лицо, получившее право на использование программы для ЭВМ на условиях настоящей Лицензии.
"Лицензия" настоящий лицензионный договор, заключенный между Лицензиаром и Лицензиатом.
"Исходный текст" программа для ЭВМ в форме текста на языке программирования, который может быть прочтен человеком.
"Объектный код" программа для ЭВМ в форме любого кода, предназначенного для исполнения ЭВМ, за исключением Исходного текста.
"Программа" программа для ЭВМ в форме Исходного текста и/или Объектного кода, экземпляр (копию) которой Лицензиар передает Лицензиату на условиях настоящей Лицензии.
"Производная программа" программа для ЭВМ, полученная в результате любых изменений или дополнений (модификаций) Исходного текста, осуществленных Лицензиатом или третьим лицом по поручению Лицензиата.
"Автор" физическое лицо, создавшее Программу или участвовавшее в создании/ изменении Программы.
2. ПРАВА ЛИЦЕНЗИАТА
2.1. Лицензиат вправе любым определенным настоящей Лицензией и не запрещенным законодательством Российской Федерации образом использовать, модифицировать, а также распространять Программу в исходном или модифицированном виде на территории Российской Федерации и государств - членов Евразийского экономического союза в течение срока действия исключительного права на Программу.
2.2. Целью настоящей Лицензии является юридическое оформление передачи Лицензиаром в пользу Лицензиата права использования Программы.
2.3. Действующее законодательство Российской Федерации и государств - членов Евразийского экономического союза может содержать специальные нормы об открытых или свободных лицензиях на произведения. Такие специальные нормы регулируют отношения сторон по настоящей Лицензии, если это согласуется с целью настоящей Лицензии в каждом конкретном случае. Противоречие настоящей Лицензии таким специальным нормам не означает незаконность, недействительность или отсутствие судебной защиты настоящей Лицензии, которая в этом случае применяется согласно действующим нормам о лицензионных договорах.
2.4 Лицензиат не вправе удалять или изменять содержащиеся в Программе, включая ее отдельные части, Исходном тексте и/или Объектном коде, а также в документации на Программу указание на Лицензиара и Автора (авторов), а также сведения о создании Программы (наименование, версия, дата создания и проч.). Правило настоящего пункта применяется и к Производной программе.
2.5. Право использования Программы по настоящей Лицензии предоставляется безвозмездно, кроме случая, когда стороны отдельно согласовали размер вознаграждения или порядок его определения.
3. ВСТУПЛЕНИЕ ЛИЦЕНЗИИ В СИЛУ
3.1. Настоящий лицензионный договор является договором присоединения и может заключаться любым способом, позволяющим достоверно установить, что предложение заключить Лицензию исходит от Лицензиара, а согласие с условиями Лицензии исходит от Лицензиата. В частности, использование Программы регулируется настоящей Лицензией, если:
(i) настоящая Лицензия или наименование и версия настоящей Лицензии, а также ссылка на общедоступную страницу в интернете, на которой размещен текст настоящей Лицензии, приведены в начале файла Исходного текста Программы или ее части, полученного Лицензиатом от Лицензиара; или
(ii) настоящая Лицензия или наименование и версия настоящей Лицензии, а также ссылка на общедоступную страницу в интернете, на которой размещен текст настоящей Лицензии, приведены в файле LICENSE, размещенном в корневом каталоге носителя (папки, машинного носителя или репозитории), содержащего Программу; или
(iii) настоящая Лицензия или наименование и версия настоящей Лицензии, а также ссылка на общедоступную страницу в интернете, на которой размещен текст настоящей Лицензии, отображаются в ходе осуществленной Лицензиатом установки или первом запуске Программы; или
(iv) настоящая Лицензия изложена в электронном виде на полученном Лицензиатом носителе с копией (экземпляром) Программы или на упаковке (оберточная лицензия); или
(v) настоящая Лицензия составлена в виде документа на бумаге, который подписан сторонами, при условии, что Лицензия включает указание на наименование и версию Программы.
3.2. Настоящая Лицензия вступает в силу с момента выражения Лицензиатом согласия с ее условиями. Если Лицензиат не выразил согласия с условиями настоящей Лицензии, Лицензиат не приобретает никаких прав по настоящей Лицензии.
3.3. Лицензиат признается согласившимся с условиями настоящей Лицензии с момента совершения Лицензиатом любого из следующих действий:
(i) использование Программы, а именно, осуществление Лицензиатом любого из действий, являющихся способом использования Программы согласно настоящей Лицензии; или
(ii) принятие Лицензиатом настоящей Лицензии посредством отметки соответствующего пункта или положительного ответа на вопрос о принятии Лицензии в диалоговом окне при установке или первом запуске Программы; или
(iii) подписание Лицензиатом настоящей Лицензии.
В этом случае письменная форма договора считается соблюденной.
3.4. Настоящая Лицензия не вступает в силу, несмотря на выражение Лицензиатом согласия с ее условиями, пока Лицензиат не получил Программу от Лицензиара.
3.5. Если настоящая Лицензия не вступила в силу, признана незаключенной или недействительной в целом, использование Программы регулируется нормами о свободном использовании программы для ЭВМ лицом, правомерно владеющим экземпляром программы для ЭВМ (статья 1280 Гражданского кодекса Российской Федерации или иные подобные нормы законодательства Российской Федерации). Соответственно, независимо от условий настоящей Лицензии, в случаях, когда использованием Программы нарушаются нормы закона, может быть признано допустимым ограниченное использование Программы, включая право запускать Программу по назначению. Права на Производную программу, любые иные права Лицензиата или третьего лица, возникшие вследствие использования Лицензиатом Программы до досрочного прекращения настоящей Лицензии, а также сублицензионные соглашения, заключенные Лицензиатом до досрочного прекращения настоящей Лицензии, сохраняют силу.
3.6. Лицензиар вправе в одностороннем порядке полностью или частично отказаться от лицензионного договора, если Лицензиат будет использовать Программу или предоставлять третьим лицам права на использование принадлежащего Лицензиару произведения либо на использование нового результата интеллектуальной деятельности, созданного Лицензиатом на основе Программы, за пределами прав, которые предусмотрены данной Лицензией.
3.7. Настоящей Лицензией не регулируется оказание услуг посредством удаленного доступа к Программе без передачи копии Программы (облачные вычисления и проч.).
4. ИСПОЛЬЗОВАНИЕ ПРОГРАММЫ
Данный раздел уточняет п.2.1 Лицензии.
4.1. Лицензиат вправе использовать Программу или ее части в любых не запрещенных законодательством Российской Федерации целях. Право на использование Программы предполагает как непосредственное исполнение инструкций процессором ЭВМ, так и процедуру её установки и упаковки в различные форматы (для последующего запуска).
4.2. Лицензиат вправе изучать, как Программа работает, и перерабатывать ее для своих целей. Лицензиар должен предоставить Лицензиату Исходный текст Программы в полном объеме или предоставить возможность его получить без дополнительных условий. Например, посредством скачивания из сети Интернет или по запросу. К Исходному тексту не должны быть применены меры намеренного запутывания (обфускации) и иные меры, не позволяющие изучать, дополнять или изменять Исходный текст Программы.
4.3. Лицензиат может распространять копии Программы. Право включает возможность воспроизводить Программу, то есть изготавливать экземпляры Программы или ее части в любой форме. Право включает возможность передавать экземпляры (копии) Программы любому лицу и на любых условиях, при передаче копий Программы следует учитывать, что личные неимущественные права Автора (авторов) Программы неотъемлемы и действуют бессрочно.
4.4. Лицензиат может перерабатывать и распространять свою измененную версию Программы. Право на переработку включает перевод на другие языки или осуществление иной адаптации Программы, то есть является созданием Производной программы. Право распространения Производной программы дает возможность передавать экземпляры (копии) Производной программы любому лицу в пределах прав, которые предусмотрены данной Лицензией, при условии соблюдения п.2.4 настоящего лицензионного договора.
5. ОТВЕТСТВЕННОСТЬ
5.1. Положения пунктов 5.2 5.5 настоящей Лицензии могут быть изменены путем заключения дополнительного соглашения в виде отдельного документа, заключаемого сторонами. Обязанности и ответственность, которые могут быть возложены на Лицензиара, не распространяются на Автора (авторов), если Автором является другое лицо, а также на лиц, от которых Лицензиар получил Программу или Исходный текст, использованный при создании Программы.
5.2. Программа передается Лицензиату в состоянии «как есть» со всеми возможными недостатками или ошибками, существующими на момент получения Лицензиатом экземпляра (копии) Программы или появившимися впоследствии по причинам, существовавшим на момент получения Лицензиатом экземпляра (копии) Программы. Лицензиар не отвечает за недостатки Программы, не обязан их исправлять или предоставлять техническую поддержку, не гарантирует коммерческую ценность Программы и пригодность для определённой цели. Лицензиат несет полную ответственность за определение целесообразности использования или распространения Программы.
5.3. Лицензиар не несет ответственности за убытки (как за реальный ущерб, так и за упущенную выгоду, а также за какие-либо другие убытки), вызванные возможными недостатками или ошибками Программы, даже если доказано, что Лицензиар знал или должен был знать о таких недостатках или ошибках. В частности, Лицензиар не несет ответственность за убытки Лицензиата по причине ненадлежащего функционирования Программы или невозможности ее использования. Равным образом Лицензиар не несет ответственности за убытки Лицензиата, возникшие по причине нарушения использованием и/или распространением Программы исключительных или иных прав третьих лиц.
5.4. Лицензиар не обязан исправлять недостатки или ошибки Программы независимо от времени обнаружения недостатков или ошибок, не обязан обучать Лицензиата работе с Программой или предоставлять Лицензиату техническую поддержку, а также не обязан передавать Лицензиату исправления или обновления, новые или измененные версии Программы.
5.5. Ни одна из сторон не вправе требовать от другой стороны возмещения убытков, уплаты штрафов или требовать применения к другой стороне любых иных мер ответственности. Лицензиат не несет ответственности за действия сублицензиата.
6. ПРОЧИЕ УСЛОВИЯ
6.1. Лицензия не требует от Лицензиата распространять Производную программу на условиях настоящей Лицензии. Применение настоящей Лицензии для производного произведения остается на усмотрение Лицензиата.
6.2. Настоящая лицензия является неисключительной. Лицензиар сохраняет за собой право использования Программы, а также может предоставлять право использования Программы иным лицам на любых условиях в пределах прав, которые предусмотрены данной Лицензией.
6.3. Лицензиат не обязан предоставлять отчеты об использовании Программы по настоящей Лицензии.
6.4. К отношениям сторон по настоящей Лицензии применяется право Российской Федерации. Компетентным судом для разрешения любых споров по настоящей Лицензии, включая споры в связи с заключением, исполнением, толкованием или недействительностью настоящей Лицензии или ее отдельных положений, является суд по месту нахождения ответчика, определяемый согласно процессуальным правилам, действующим в месте нахождения ответчика.
КОНЕЦ ТЕКСТА ЛИЦЕНЗИИ

View File

@ -1,79 +0,0 @@
# БМПОС: Базовая Модульная Платформа Операционных Систем
[![CI сборка](https://github.com/0Nera/BMOSP/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/0Nera/BMOSP/actions/workflows/build.yml)
[![Github pages сайт](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment/badge.svg?branch=pages)](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment)
БМПОС - Базовая Модульная Платформа Операционных Систем для платформы x86_64 (BIOS/UEFI). Это отечественное программное обеспечение, созданное при поддержке Синапс ОС на языке программирования C.
БМПОС не является операционной системой. Это платформа для изучения.
Философия БМПОС - "всё есть модуль".
![Скриншот вывода ядра в эмуляторе Qemu](https://0nera.github.io/BMOSP/assets/0_0.1.367.png)
## Список задач
Перенесено в файл `TODO.md`
## Партнеры
- ООО **"НПО ТЕ-ОН"**
## Помощь проекту
Мы рады предоставить вам полностью бесплатный доступ к **БМПОС** без каких-либо ограничений по распространению или монетизации. Если наш проект помог вам решить вашу проблему, мы будем благодарны за любую поддержку. Ниже вы найдете несколько вариантов для того, чтобы помочь нам.
### Доработка кодовой базы
Если вы владеете C/C++, ассемблерами GAS или FASM, то вы можете доработать ядро проекта или написать свой пользовательский модуль.
Для добавления своего модуля используйте инструкцию `modules/README.md`.
### Указание авторства
Текущая лицензия позволяет вам использовать код ядра **БМПОС** в любых проектах.
Вы можете просто указать, что ваш проект использует технологии **БМПОС**. Это поможет распространить информацию о проекте и привлечь новых пользователей.
### Денежное пожертвование
Вы можете пожертвовать произвольную сумму на развитие проекта и при желании указать, какие из задач наиболее интересны для вас.
- Номер карты: 2200 7009 4662 4201
- Номер счета: 40817810400099892231
- БИК: 044525974
- Банк-получатель: АО «Тинькофф Банк»
## Сборка и запуск
Перенесено в файл `BUILD.md`
## Предупреждение
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
Мы не несем ответственности за нанесенный ущерб.
## Ресурсы
- <https://vk.com/BMOSP> Страница вконтакте
- <https://t.me/bmosp> Телеграм (активный форум)
- <https://bmosp.ru> Вебсайт (в процессе)
- <https://wiki.synapseos.ru/index.php?title=БМПОС> Страница на вики
### Зеркала
Для отправки своих изменений вы можете использовать следующие зеркала:
- <https://git.synapseos.ru/Aren/BMOSP> - доверенный сервер(главный репозиторий)
- <https://github.com/0Nera/BMOSP> - зеркало с CI
- <https://tvoygit.ru/0Nera/BMOSP> - зеркало
- <https://hub.mos.ru/synapseos/BMOSP> - неактивное зеркало
### Использованные ресурсы
- <https://github.com/limine-bootloader/limine> (BSD 2-Clause)
- <https://github.com/nothings/stb> (MIT, Общественное достояние)
- <https://en.wikipedia.org/wiki/CPUID>
- <https://github.com/klange/toaruos> (NCSA)
- <https://wiki.osdev.org/Model_Specific_Registers>
- <https://sandpile.org/x86/msr.htm>

1
STD.md Normal file
View File

@ -0,0 +1 @@
# Стандартная библиотека модулей

77
TODO.md
View File

@ -1,77 +0,0 @@
# Список задач
## Основные задачи
Ядро:
- [x] Менеджер памяти
- [x] Менеджер видеопамяти
- [ ] Менеджер потоков
- [x] Загрузчик модулей
- [ ] Буферы ввода-вывода
Модули:
- [ ] Оболочка ввода-вывода
Драйвера:
- [ ] PS/2 (Клавиатура)
- [ ] SATA (AHCI) (Чтение)
- [ ] EXT2
Документация:
- [X] Системные вызовы
- [ ] Ядро
- [ ] Стандартная библиотека
Вебсайт:
- [X] Домен
- [X] Движок сайта
- [ ] Документация
- [ ] Статьи
- [ ] Примеры
Примеры:
- [X] Пример модуля
- [ ] Пример драйвера
- [ ] Пример программы-модуля
- [ ] Пример модуля ввода-вывода
Общая работа:
- [ ] Ядро
- [ ] Модули
- [ ] Драйвера
- [ ] Документация
- [ ] Вебсайт
- [ ] Примеры
- [ ] Видеоуроки
### Второстепенные задачи
Модули:
- [ ] Отладчик
- [ ] JavaScript
- [ ] Lua
- [ ] SQLite
- [ ] Криптограф
Драйвера:
- [ ] PS/2 (Мышь)
- [ ] SATA (AHCI) (Запись)
- [ ] SIMD (SSE, SSE2, SSE3, SSE4, AVX) - отдельный драйвер для инициализации SIMD инструкций
Видеоуроки:
- [ ] Основы языка C
- [ ] Основы ассемблера GAS
- [ ] Настройка окружения
- [ ] Сборка из исходного кода
- [ ] Привет мир!
- [ ] Написание драйвера

BIN
assets/0_0.1.231.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
assets/0_0.1.367.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

4
assets/css/main.css Normal file
View File

@ -0,0 +1,4 @@
a {
color: green;
text-decoration: none;
}

BIN
boot.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

BIN
boot.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

BIN
boot.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

BIN
boot.tga

Binary file not shown.

92
build.py Normal file
View File

@ -0,0 +1,92 @@
import os
import subprocess
import shutil
import time
def update_repo():
# Переходим в директорию с репозиторием
repo_path = '.'
os.chdir(repo_path)
# Выполняем команду git pull для обновления репозитория
result = subprocess.run(['git', 'pull'], capture_output=True, text=True)
# Проверяем вывод команды git pull
if 'up to date' in result.stdout.strip().lower():
print('No updates, waiting for further update...')
return False
print('Repository updated')
return True
def remove_header(file_path):
with open(file_path, 'r') as file:
html = file.read()
start_tag = '<header id="title-block-header">\n<h1 class="title">'
end_tag = '</h1>\n</header>'
start_index = html.find(start_tag)
end_index = html.find(end_tag) + len(end_tag)
if start_index != -1 and end_index != -1:
html = html[:start_index] + html[end_index:]
with open(file_path, 'w') as file:
file.write(html)
def convert_md_to_html(md_file):
# Получаем путь к папке "output"
bin_path = os.path.join(os.getcwd(), 'output')
# Получаем заголовок странцы из файла
title = ''
with open(md_file, 'r') as file:
for line in file:
if line.startswith('#'):
title = line.strip('#').strip()
break
# Генерируем имя файла HTML на основе имени файла MD
file_name = os.path.splitext(md_file)[0] + '.html'
html_file = os.path.join(bin_path, file_name)
# Преобразуем файл MD в HTML, используя, например, Pandoc
print(f"pandoc -s {md_file} -o {html_file} --metadata title=\"{title}\" --css=assets/css/main.css")
os.system(f"pandoc -s {md_file} -o {html_file} --metadata title=\"{title}\" --css=assets/css/main.css")
remove_header(html_file)
def main():
# Получаем путь к папке "output" и "assets"
bin_path = os.path.join(os.getcwd(), 'output')
assets_path = os.path.join(os.getcwd(), 'assets')
while True:
# Проверяем обновление репозитория Git
if not update_repo():
time.sleep(60)
shutil.rmtree(bin_path, ignore_errors=True)
os.makedirs(bin_path, exist_ok=True)
shutil.copytree(assets_path, os.path.join(bin_path, 'assets'))
# Получаем список всех файлов в репозитории
repo_files = os.listdir('.')
# Фильтруем только MD файлы
md_files = [file for file in repo_files if file.endswith('.md')]
# Преобразуем каждый MD файл в HTML и копируем в папку "output"
for md_file in md_files:
convert_md_to_html(md_file)
shutil.rmtree('/var/www/html/', ignore_errors=True)
shutil.copytree(bin_path, '/var/www/html/')
# Ожидаем 2 минуты перед следующей проверкой обновлений
time.sleep(120)
if __name__ == '__main__':
main()

View File

@ -1,12 +0,0 @@
#!/bin/sh
cd modules/
mkdir -p bin
dos2unix */*.sh
#cd helloworld/ && chmod +x build.sh && ./build.sh && cd ..
#cd music/ && chmod +x build.sh && ./build.sh && cd ..
cd simd/ && chmod +x build.sh && ./build.sh && cd ..
cd cpubench/ && chmod +x build.sh && ./build.sh && cd ..
cd pci/ && chmod +x build.sh && ./build.sh && cd ..
cd pci_data/ && chmod +x build.sh && ./build.sh && cd ..
cd ..
python3 pbuild.py

View File

View File

View File

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

View File

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

View File

@ -1,2 +0,0 @@
name=Aren
password=

View File

@ -1,2 +0,0 @@
#!/bin/sh
sudo dd if=bmosp.hdd of=/dev/sdc

View File

@ -1,267 +0,0 @@
// Название шрифта 6x8 Slim
// Автор шрифта Riva
// Дата и время генерации 06.06.2023 19:38:19
// Сгенерировано matrixFont v1.1.0.52
// Кодовая страница 1251 (ANSI - кириллица)
// https://gitlab.com/riva-lab/matrixFont
#ifndef FONT_6X8_SLIM_H
#define FONT_6X8_SLIM_H
#ifndef FONT_TYPE_MONOSPACED
#define FONT_TYPE_MONOSPACED 0
#endif
#ifndef FONT_TYPE_PROPORTIONAL
#define FONT_TYPE_PROPORTIONAL 1
#endif
#define FONT_6X8_SLIM_LENGTH 224
#define FONT_6X8_SLIM_START_CHAR 32
#define FONT_6X8_SLIM_CHAR_WIDTH 6
#define FONT_6X8_SLIM_CHAR_HEIGHT 8
#define FONT_6X8_SLIM_FONT_TYPE (FONT_TYPE_MONOSPACED)
#define FONT_6X8_SLIM_ARRAY_LENGTH \
(FONT_6X8_SLIM_LENGTH * FONT_6X8_SLIM_CHAR_HEIGHT)
static const unsigned char font_6x8_slim[FONT_6X8_SLIM_ARRAY_LENGTH] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 32 < >
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, // Символ 33 <!>
0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 34 <">
0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A, 0x00, // Символ 35 <#>
0x04, 0x1E, 0x05, 0x0E, 0x14, 0x0F, 0x04, 0x00, // Символ 36 <$>
0x00, 0x27, 0x15, 0x0B, 0x34, 0x2A, 0x39, 0x00, // Символ 37 <%>
0x06, 0x09, 0x05, 0x02, 0x15, 0x19, 0x0E, 0x00, // Символ 38 <&>
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 39 <'>
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, // Символ 40 <(>
0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, // Символ 41 <)>
0x00, 0x0A, 0x04, 0x1F, 0x04, 0x0A, 0x00, 0x00, // Символ 42 <*>
0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00, // Символ 43 <+>
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, // Символ 44 <,>
0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, // Символ 45 <->
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, // Символ 46 <.>
0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, // Символ 47 </>
// Digits / Цифры
0x06, 0x09, 0x0D, 0x0B, 0x09, 0x09, 0x06, 0x00, // Символ 48 <0>
0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, // Символ 49 <1>
0x06, 0x09, 0x08, 0x06, 0x01, 0x01, 0x0F, 0x00, // Символ 50 <2>
0x0F, 0x08, 0x06, 0x08, 0x08, 0x09, 0x06, 0x00, // Символ 51 <3>
0x08, 0x0C, 0x0A, 0x09, 0x09, 0x1F, 0x08, 0x00, // Символ 52 <4>
0x0F, 0x01, 0x07, 0x08, 0x08, 0x09, 0x06, 0x00, // Символ 53 <5>
0x06, 0x09, 0x01, 0x07, 0x09, 0x09, 0x06, 0x00, // Символ 54 <6>
0x0F, 0x08, 0x08, 0x04, 0x02, 0x01, 0x01, 0x00, // Символ 55 <7>
0x06, 0x09, 0x09, 0x06, 0x09, 0x09, 0x06, 0x00, // Символ 56 <8>
0x06, 0x09, 0x09, 0x0E, 0x08, 0x09, 0x06, 0x00, // Символ 57 <9>
0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, // Символ 58 <:>
0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x02, 0x01, // Символ 59 <;>
0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00, // Символ 60 <<>
0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00, // Символ 61 <=>
0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00, 0x00, // Символ 62 <>>
0x0E, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04, 0x00, // Символ 63 <?>
0x0E, 0x11, 0x1D, 0x15, 0x0D, 0x01, 0x0E, 0x00, // Символ 64 <@>
// Roman Capitals / Латиница, прописные
0x06, 0x09, 0x09, 0x0F, 0x09, 0x09, 0x09, 0x00, // Символ 65 <A>
0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, // Символ 66 <B>
0x06, 0x09, 0x01, 0x01, 0x01, 0x09, 0x06, 0x00, // Символ 67 <C>
0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00, // Символ 68 <D>
0x0F, 0x01, 0x01, 0x07, 0x01, 0x01, 0x0F, 0x00, // Символ 69 <E>
0x0F, 0x01, 0x01, 0x07, 0x01, 0x01, 0x01, 0x00, // Символ 70 <F>
0x06, 0x09, 0x01, 0x0D, 0x09, 0x09, 0x06, 0x00, // Символ 71 <G>
0x09, 0x09, 0x09, 0x0F, 0x09, 0x09, 0x09, 0x00, // Символ 72 <H>
0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, // Символ 73 <I>
0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, // Символ 74 <J>
0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x00, // Символ 75 <K>
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x00, // Символ 76 <L>
0x11, 0x1B, 0x15, 0x11, 0x11, 0x11, 0x11, 0x00, // Символ 77 <M>
0x11, 0x13, 0x15, 0x19, 0x11, 0x11, 0x11, 0x00, // Символ 78 <N>
0x06, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, // Символ 79 <O>
0x07, 0x09, 0x09, 0x07, 0x01, 0x01, 0x01, 0x00, // Символ 80 <P>
0x0E, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16, 0x00, // Символ 81 <Q>
0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, // Символ 82 <R>
0x0E, 0x01, 0x01, 0x06, 0x08, 0x08, 0x07, 0x00, // Символ 83 <S>
0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, // Символ 84 <T>
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, // Символ 85 <U>
0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04, 0x00, // Символ 86 <V>
0x11, 0x11, 0x11, 0x15, 0x15, 0x0A, 0x0A, 0x00, // Символ 87 <W>
0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11, 0x00, // Символ 88 <X>
0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, // Символ 89 <Y>
0x1F, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1F, 0x00, // Символ 90 <Z>
0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, // Символ 91 <[>
0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, // Символ 92 <\>
0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, // Символ 93 <]>
0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 94 <^>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, // Символ 95 <_>
0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 96 <`>
// Roman Smalls / Латиница, строчные
0x00, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x0E, 0x00, // Символ 97 <a>
0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x07, 0x00, // Символ 98 <b>
0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x06, 0x00, // Символ 99 <c>
0x08, 0x08, 0x0E, 0x09, 0x09, 0x09, 0x0E, 0x00, // Символ 100 <d>
0x00, 0x00, 0x06, 0x09, 0x0F, 0x01, 0x0E, 0x00, // Символ 101 <e>
0x0C, 0x02, 0x0F, 0x02, 0x02, 0x02, 0x02, 0x00, // Символ 102 <f>
0x00, 0x00, 0x0E, 0x09, 0x09, 0x0E, 0x08, 0x06, // Символ 103 <g>
0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x09, 0x00, // Символ 104 <h>
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, // Символ 105 <i>
0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, // Символ 106 <j>
0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00, // Символ 107 <k>
0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, // Символ 108 <l>
0x00, 0x00, 0x0F, 0x15, 0x15, 0x15, 0x15, 0x00, // Символ 109 <m>
0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x00, // Символ 110 <n>
0x00, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06, 0x00, // Символ 111 <o>
0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x07, 0x01, // Символ 112 <p>
0x00, 0x00, 0x0E, 0x09, 0x09, 0x09, 0x0E, 0x08, // Символ 113 <q>
0x00, 0x00, 0x05, 0x03, 0x01, 0x01, 0x01, 0x00, // Символ 114 <r>
0x00, 0x00, 0x0E, 0x01, 0x06, 0x08, 0x07, 0x00, // Символ 115 <s>
0x02, 0x02, 0x0F, 0x02, 0x02, 0x02, 0x0C, 0x00, // Символ 116 <t>
0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0E, 0x00, // Символ 117 <u>
0x00, 0x00, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00, // Символ 118 <v>
0x00, 0x00, 0x11, 0x11, 0x15, 0x0A, 0x0A, 0x00, // Символ 119 <w>
0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, // Символ 120 <x>
0x00, 0x00, 0x09, 0x09, 0x09, 0x0E, 0x08, 0x06, // Символ 121 <y>
0x00, 0x00, 0x0F, 0x04, 0x02, 0x01, 0x0F, 0x00, // Символ 122 <z>
0x04, 0x02, 0x02, 0x01, 0x02, 0x02, 0x04, 0x00, // Символ 123 <{>
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Символ 124 <|>
0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00, // Символ 125 <}>
0x00, 0x00, 0x02, 0x15, 0x08, 0x00, 0x00, 0x00, // Символ 126 <~>
0x0F, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0F, 0x00, // Символ 127 <DELETE>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 128 <Ђ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 129 <Ѓ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, // Символ 130 <>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 131 <ѓ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x12, 0x09, // Символ 132 <„>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, // Символ 133 <…>
0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, // Символ 134 <†>
0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x02, // Символ 135 <‡>
0x0C, 0x12, 0x07, 0x02, 0x07, 0x12, 0x0C, 0x00, // Символ 136 <€>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 137 <‰>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 138 <Љ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 139 <>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 140 <Њ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 141 <Ќ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 142 <Ћ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 143 <Џ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 144 <ђ>
0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 145 <>
0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 146 <>
0x12, 0x09, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 147 <“>
0x1B, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 148 <”>
0x00, 0x00, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, // Символ 149 <•>
0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, // Символ 150 <>
0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // Символ 151 <—>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 152 <˜>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 153 <™>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 154 <љ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 155 <>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 156 <њ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 157 <ќ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 158 <ћ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 159 <џ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 160 < >
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 161 <Ў>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 162 <ў>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 163 <Ј>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 164 <¤>
0x08, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, // Символ 165 <Ґ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 166 <¦>
0x0E, 0x01, 0x06, 0x09, 0x09, 0x06, 0x08, 0x07, // Символ 167 <§>
0x09, 0x00, 0x0F, 0x01, 0x07, 0x01, 0x0F, 0x00, // Символ 168 <Ё>
0x1E, 0x21, 0x2D, 0x25, 0x2D, 0x21, 0x1E, 0x00, // Символ 169 <©>
0x06, 0x09, 0x01, 0x07, 0x01, 0x09, 0x06, 0x00, // Символ 170 <Є>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 171 <«>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 172 <¬>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 173 <­>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 174 <®>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 175 <Ї>
0x07, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 176 <°>
0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x1F, 0x00, // Символ 177 <±>
0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, // Символ 178 <І>
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, // Символ 179 <і>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 180 <ґ>
0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x17, 0x01, // Символ 181 <µ>
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Символ 182 <¶>
0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, // Символ 183 <·>
0x09, 0x00, 0x06, 0x09, 0x0F, 0x01, 0x0E, 0x00, // Символ 184 <ё>
0x39, 0x2B, 0x3D, 0x09, 0x09, 0x09, 0x09, 0x00, // Символ 185 <№>
0x00, 0x00, 0x0E, 0x01, 0x07, 0x01, 0x0E, 0x00, // Символ 186 <є>
0x00, 0x00, 0x05, 0x0A, 0x14, 0x0A, 0x05, 0x00, // Символ 187 <»>
0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, // Символ 188 <ј>
0x06, 0x09, 0x01, 0x06, 0x08, 0x09, 0x06, 0x00, // Символ 189 <Ѕ>
0x00, 0x00, 0x0E, 0x01, 0x06, 0x08, 0x07, 0x00, // Символ 190 <ѕ>
0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, // Символ 191 <ї>
// Cyrillic Capitals / Кириллица, прописные
0x06, 0x09, 0x09, 0x0F, 0x09, 0x09, 0x09, 0x00, // Символ 192 <А>
0x0F, 0x01, 0x01, 0x07, 0x09, 0x09, 0x07, 0x00, // Символ 193 <Б>
0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, // Символ 194 <В>
0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, // Символ 195 <Г>
0x0C, 0x0A, 0x0A, 0x0A, 0x0A, 0x1F, 0x11, 0x00, // Символ 196 <Д>
0x0F, 0x01, 0x01, 0x07, 0x01, 0x01, 0x0F, 0x00, // Символ 197 <Е>
0x15, 0x15, 0x15, 0x0E, 0x15, 0x15, 0x15, 0x00, // Символ 198 <Ж>
0x06, 0x09, 0x08, 0x06, 0x08, 0x09, 0x06, 0x00, // Символ 199 <З>
0x11, 0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x00, // Символ 200 <И>
0x15, 0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x00, // Символ 201 <Й>
0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x00, // Символ 202 <К>
0x1C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x00, // Символ 203 <Л>
0x11, 0x1B, 0x15, 0x11, 0x11, 0x11, 0x11, 0x00, // Символ 204 <М>
0x09, 0x09, 0x09, 0x0F, 0x09, 0x09, 0x09, 0x00, // Символ 205 <Н>
0x06, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, // Символ 206 <О>
0x0F, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, // Символ 207 <П>
0x07, 0x09, 0x09, 0x07, 0x01, 0x01, 0x01, 0x00, // Символ 208 <Р>
0x06, 0x09, 0x01, 0x01, 0x01, 0x09, 0x06, 0x00, // Символ 209 <С>
0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, // Символ 210 <Т>
0x09, 0x09, 0x09, 0x0E, 0x08, 0x08, 0x06, 0x00, // Символ 211 <У>
0x04, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x04, 0x00, // Символ 212 <Ф>
0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11, 0x00, // Символ 213 <Х>
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x1F, 0x10, // Символ 214 <Ц>
0x09, 0x09, 0x09, 0x0E, 0x08, 0x08, 0x08, 0x00, // Символ 215 <Ч>
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1F, 0x00, // Символ 216 <Ш>
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3F, 0x20, // Символ 217 <Щ>
0x03, 0x02, 0x0E, 0x12, 0x12, 0x12, 0x0E, 0x00, // Символ 218 <Ъ>
0x21, 0x21, 0x27, 0x29, 0x29, 0x29, 0x27, 0x00, // Символ 219 <Ы>
0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x07, 0x00, // Символ 220 <Ь>
0x06, 0x09, 0x08, 0x0E, 0x08, 0x09, 0x06, 0x00, // Символ 221 <Э>
0x19, 0x25, 0x25, 0x27, 0x25, 0x25, 0x19, 0x00, // Символ 222 <Ю>
0x0E, 0x09, 0x09, 0x0E, 0x09, 0x09, 0x09, 0x00, // Символ 223 <Я>
// Cyrillic Smalls / Кириллица, строчные
0x00, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x0E, 0x00, // Символ 224 <а>
0x08, 0x06, 0x01, 0x07, 0x09, 0x09, 0x06, 0x00, // Символ 225 <б>
0x00, 0x00, 0x07, 0x09, 0x07, 0x09, 0x07, 0x00, // Символ 226 <в>
0x00, 0x00, 0x07, 0x01, 0x01, 0x01, 0x01, 0x00, // Символ 227 <г>
0x00, 0x00, 0x0C, 0x0A, 0x0A, 0x0A, 0x1F, 0x11, // Символ 228 <д>
0x00, 0x00, 0x06, 0x09, 0x0F, 0x01, 0x0E, 0x00, // Символ 229 <е>
0x00, 0x00, 0x15, 0x15, 0x0E, 0x15, 0x15, 0x00, // Символ 230 <ж>
0x00, 0x00, 0x07, 0x08, 0x06, 0x08, 0x07, 0x00, // Символ 231 <з>
0x00, 0x00, 0x09, 0x09, 0x0D, 0x0B, 0x09, 0x00, // Символ 232 <и>
0x06, 0x00, 0x09, 0x09, 0x0D, 0x0B, 0x09, 0x00, // Символ 233 <й>
0x00, 0x00, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00, // Символ 234 <к>
0x00, 0x00, 0x0C, 0x0A, 0x0A, 0x0A, 0x09, 0x00, // Символ 235 <л>
0x00, 0x00, 0x11, 0x1B, 0x15, 0x11, 0x11, 0x00, // Символ 236 <м>
0x00, 0x00, 0x09, 0x09, 0x0F, 0x09, 0x09, 0x00, // Символ 237 <н>
0x00, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06, 0x00, // Символ 238 <о>
0x00, 0x00, 0x0F, 0x09, 0x09, 0x09, 0x09, 0x00, // Символ 239 <п>
0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x07, 0x01, // Символ 240 <р>
0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x06, 0x00, // Символ 241 <с>
0x00, 0x00, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00, // Символ 242 <т>
0x00, 0x00, 0x09, 0x09, 0x09, 0x0E, 0x08, 0x06, // Символ 243 <у>
0x00, 0x00, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x04, // Символ 244 <ф>
0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, // Символ 245 <х>
0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x1F, 0x10, // Символ 246 <ц>
0x00, 0x00, 0x09, 0x09, 0x0E, 0x08, 0x08, 0x00, // Символ 247 <ч>
0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x1F, 0x00, // Символ 248 <ш>
0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x3F, 0x20, // Символ 249 <щ>
0x00, 0x00, 0x03, 0x0E, 0x12, 0x12, 0x0E, 0x00, // Символ 250 <ъ>
0x00, 0x00, 0x11, 0x13, 0x15, 0x15, 0x13, 0x00, // Символ 251 <ы>
0x00, 0x00, 0x01, 0x07, 0x09, 0x09, 0x07, 0x00, // Символ 252 <ь>
0x00, 0x00, 0x07, 0x08, 0x0E, 0x08, 0x07, 0x00, // Символ 253 <э>
0x00, 0x00, 0x09, 0x15, 0x17, 0x15, 0x09, 0x00, // Символ 254 <ю>
0x00, 0x00, 0x0E, 0x09, 0x0E, 0x09, 0x09, 0x00 // Символ 255 <я>
};
#endif // FONT_6X8_SLIM_H

View File

@ -1,34 +0,0 @@
/**
* arch.h
* Заголовок для инициализации архитектурно-зависимых функций
*
* Данный заголовочный файл содержит определения которые используются для
* инициализации архитектуры
*
*/
#ifndef ARCH_H
#define ARCH_H
#include <stdint.h>
void arch_init( );
void cpu_init( );
void gdt_init( );
void idt_init( );
void idt_set_int(uint8_t vector, void *int_handler);
uint64_t arch_get_tick_b( );
uint64_t arch_get_tick_l( );
uint64_t arch_get_tick( );
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;
}
#endif // arch.h

View File

@ -1,47 +0,0 @@
/**
* fb.h
* Заголовок с функциями фреймбуффера
*
* Данный заголовочный файл содержит определения которые используются для работы
* с экранным буффером(фреймбуффером)
*
*/
#ifndef FB_H
#define FB_H
#include <arch.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <tool.h>
enum colors {
WHITE = 0xFFFFFF,
BLACK = 0x000000,
RED = 0xFF0000,
GREEN = 0x00D000,
PRIMA_GREEN = 0x00FF00,
BLUE = 0x0000FF,
DARK_GREEN = 0x013220,
};
#define GET_TICK_BIG arch_get_tick_b( )
#define GET_TICK_lOW arch_get_tick_l( )
#define SCREEN_WIDTH width
#define SCREEN_HEIGHT height
#define SCREEN_BUFFER fb_addr
#define LOG(...) \
fb_printf("[%u]%s() (%s:%d) ", GET_TICK_BIG, __func__, __FILE__, \
__LINE__); \
fb_printf(__VA_ARGS__)
void fb_set_text_color(uint32_t color);
void fb_init( );
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 fb_printf_at(size_t x, size_t y, char *str, ...);
#endif // fb.h

View File

@ -1,29 +0,0 @@
/**
* lock.h
* Заголовок с функциями блокировок
*
* Данный заголовочный файл содержит определения которые используются для работы
* с блокировками ресурсов
*
*/
#ifndef LOCK_H
#define LOCK_H
#include <stdint.h>
typedef struct {
int lock;
const char* file;
} lock_t;
#define LOCK_INIT \
(lock_t) { \
0, __FILE__ \
}
int lock_swap(lock_t* lock);
void lock_acquire(lock_t* lock);
void lock_release(lock_t* lock);
#endif // lock.h

View File

@ -1,30 +0,0 @@
/**
* mem.h
* Заголовочный файл с функциями менеджера памяти
*
* Данный заголовочный файл содержит определения, которые используются для
* работы с памятью
*
*/
#ifndef MEM_H
#define MEM_H
#include <stddef.h>
#include <stdint.h>
#define BLOCK_SIZE 4096
#define HHDM_OFFSET (hhdm_request.response->offset)
void mem_dump_memory( );
void mem_init( );
void *mem_alloc(size_t size);
void mem_add_block(void *addr, size_t size);
void mem_free(void *addr);
void *mem_realloc(void *addr, size_t size);
void *mem_frame_alloc(uint64_t wanted_frames);
void mem_frame_free(void *ptr, uint64_t frames);
void *mem_frame_calloc(uint64_t frames);
void mem_merge_all_blocks( );
#endif // mem.h

View File

@ -1,41 +0,0 @@
/**
* mod.h
* Заголовочный файл с функциями работы с памятью
*
* Данный заголовочный файл содержит определения, которые используются для
* работы с памятью
*
*/
#include <sys.h>
#ifndef MOD_H
#define MOD_H
// Максимальное количество модулей 16. Позже перепишем на динамический массив,
// сейчас для прототипа это не так важно
#define MOD_MAX 16
// Структуры соответствующие ELF заголовкам
typedef struct {
unsigned char e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf64_header_t;
void mod_init( );
void mod_list_show( );
module_info_t *mod_find(char *tag);
#endif // mod.h

View File

@ -1,78 +0,0 @@
/**
* sys.h
* Заголовок содержащий определения для работы системного API
*
* Данный заголовочный файл содержит определения которые используются для
* объявления структур и системных функций
*
*/
#ifndef SYS_H
#define SYS_H
#include <stdint.h>
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 {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
} module_info_t;
typedef struct {
int reserved;
} func_t;
typedef struct {
uint8_t a[4];
uint8_t b[4];
uint8_t c[4];
uint8_t d[4];
} uid_t;
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t second;
} time_t;
typedef struct {
uint64_t offset;
module_info_t *info;
void (*fb_printf)(char *str, ...); // Временная функция
framebuffer_t *(*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void (*exit)(int code);
int (*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;
env_t sys_install(env_t module);
#endif // sys.h

View File

@ -1,48 +0,0 @@
/**
* tool.h
* Заголовок содержащий определения вспомогательных функций
*
* Данный заголовочный файл содержит определения которые используются для
* упрощения написания кода
*
*/
#ifndef TOOL_H
#define TOOL_H
#include <stdarg.h>
#include <stdint.h>
#define abs(x) ((x) < 0 ? -(x) : (x))
#define assert(check) \
do { \
if (!(check)) { \
fb_printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
__FILE__, __LINE__); \
for (;;) asm volatile("hlt"); \
} \
} while (0)
#define ALIGN_UP(NUM, ALIGN) (((NUM) + ALIGN - 1) & ~(ALIGN - 1))
#define ALIGN_DOWN(NUM, ALIGN) ((NUM) & ~(ALIGN - 1))
#define CONTAINER_OF(PTR, TYPE, MEMBER) \
((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
#define BIT_GET(BIT) ((bitmap[(BIT) / 8] >> ((BIT) % 8)) & 1)
static inline void pause( ) {
for (uint64_t i = 0; i < 1024; i++) {
for (uint64_t j = 0; j < 4; j++) { asm volatile("pause"); }
}
}
void tool_memcpy(void *dest, void *src, uint64_t n);
void *tool_memset(void *ptr, uint8_t n, uint64_t size);
uint64_t tool_strlen(const char *str);
uint64_t tool_starts_with(const char *str, const char *prefix);
void tool_format(void (*putc)(char c), const char *format_string, va_list args);
#endif // tool.h

View File

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

169
index.md Normal file
View File

@ -0,0 +1,169 @@
# БМПОС: Базовая Модульная Платформа Операционных Систем
[![CI сборка](https://github.com/0Nera/BMOSP/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/0Nera/BMOSP/actions/workflows/build.yml)
[![Github pages сайт](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment/badge.svg?branch=pages)](https://github.com/0Nera/BMOSP/actions/workflows/pages/pages-build-deployment)
БМПОС - Базовая Модульная Платформа Операционных Систем для платформы x86_64 (BIOS/UEFI). Это отечественное программное обеспечение, созданное при поддержке Синапс ОС на языке программирования C.
БМПОС не является операционной системой. Это платформа для изучения.
Философия БМПОС - "всё есть модуль".
![Скриншот вывода ядра в эмуляторе Qemu](https://git.synapseos.ru/Aren/BMOSP/raw/branch/pages/assets/0_0.1.367.png)
* [Системные вызовы](./API)
* [Домашняя работа](./HOMEWORK)
* [Ядро](./KERNEL)
* [Стандартная библиотека](./STD)
* [Авторы](./AUTHORS)
* [История](./HISTORY)
## Реализовано
Ядро:
- [x] Менеджер памяти
- [x] Менеджер видеопамяти
- [ ] Менеджер потоков
- [x] Загрузчик модулей
- [ ] Буфферы ввода-вывода
Модули:
- [ ] Оболочка ввода-вывода
Драйвера:
- [ ] PS/2 (Клавиатура)
- [ ] SATA (AHCI) (Чтение)
- [ ] EXT2
Документация:
- [X] Системные вызовы
- [ ] Ядро
- [ ] Стандартная библиотека
Вебсайт:
- [X] Домен
- [ ] Движок сайта
- [ ] Документация
- [ ] Статьи
- [ ] Примеры
Примеры:
- [ ] Пример модуля
- [ ] Пример драйвера
- [ ] Пример программы-модуля
- [ ] Пример модуля ввода-вывода
Видеоуроки:
- [ ] Основы языка C
- [ ] Основы ассемблера GAS
- [ ] Настройка окружения
- [ ] Сборка из исходного кода
- [ ] Привет мир!
- [ ] Написание драйвера
Общая работа:
- [ ] Ядро
- [ ] Модули
- [ ] Драйвера
- [ ] Документация
- [ ] Вебсайт
- [ ] Примеры
- [ ] Видеоуроки
### Второстепенные задачи
Модули:
- [ ] Отладчик
- [ ] JavaScript
- [ ] Lua
- [ ] SQLite
- [ ] Криптограф
Драйвера:
- [ ] PS/2 (Мышь)
- [ ] SATA (AHCI) (Запись)
- [ ] SIMD (SSE, SSE2, SSE3, SSE4, AVX) - отдельный драйвер для инициализации SIMD инструкций
## Партнеры
- ООО "НПО ТЕ-ОН"
## Сборка из исходного кода
### Ubuntu 18.04+
```bash
sudo apt install clang-format python3 git qemu-system-x86 gdisk dos2unix
git clone https://git.synapseos.ru/Aren/BMOSP.git
cd BMOSP/
chmod +x build.sh
./build.sh
```
### ArchLinux
```bash
yay -S clang-format
sudo pacman -S python3 git qemu-system-x86
git clone https://git.synapseos.ru/Aren/BMOSP.git
cd BMOSP/
chmod +x build.sh
./build.sh
```
## Запуск
### Qemu
Стандартная конфигурация
```bash
qemu-system-x86_64 -cpu max -m 1G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd -name "БМПОС"
```
Или
```bash
chmod +x run.sh
./run.sh
```
## Предупреждение
Использовать на свой страх и риск. Система расчитана на работу в эмулируемой среде Qemu под процессоры x86_64.
Мы не несем ответственности за нанесенный ущерб.
## Ресурсы
- <https://vk.com/BMOSP> Страница вконтакте
- <https://t.me/bmosp> Телеграм
- <https://bmosp.ru> Вебсайт
- <https://wiki.synapseos.ru/index.php?title=БМПОС> Страница на вики
### Зеркала
- <https://git.synapseos.ru/Aren/BMOSP> - доверенный сервер(главный репозиторий)
- <https://github.com/0Nera/BMOSP> - зеркало
- <https://tvoygit.ru/0Nera/BMOSP> - зеркало
- <https://hub.mos.ru/synapseos/BMOSP> - неактивное зеркало
### Использованные ресурсы
- <https://github.com/limine-bootloader/limine> (BSD 2-Clause)
- <https://github.com/nothings/stb> (MIT, Общественное достояние)
- <https://en.wikipedia.org/wiki/CPUID>
- <https://github.com/klange/toaruos> (NCSA)
- <https://wiki.osdev.org/Model_Specific_Registers>
- <https://sandpile.org/x86/msr.htm>

View File

@ -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( );
}

View File

@ -1,149 +0,0 @@
/**
* cpu.c
* Информация о процессоре
*
* Функционал получения дополнительной информации о процессоре и доступных
* процессорных инструкциях
*
*/
#include <fb.h>
#include <stdbool.h>
#include <stdint.h>
#include <tool.h>
static bool acpi_msrs_support = false;
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
}
static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
}
static void __attribute__((unused))
msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
}
static int64_t get_cpu_temperature_intel( ) {
uint32_t lo, hi;
// Чтение температуры из MSR
msr_get(0x19C, &lo, &hi);
uint64_t temp = ((uint64_t)hi << 32) | (uint64_t)lo;
// Преобразование значения температуры
int64_t temperature = (temp >> 16) / 256;
if (temperature == 0) { return 0; }
return ((temperature - 32) * 5 / 9);
}
static void do_amd( ) {
uint32_t eax, ebx, ecx, edx;
uint32_t eggs[4];
uint32_t cpu_model;
uint32_t cpu_family;
char eggs_string[13];
cpuid(0x8FFFFFFF, &eggs[0], &eggs[1], &eggs[2], &eggs[3]);
tool_memcpy(eggs_string, eggs, 12);
cpuid(1, &eax, &ebx, &ecx, &edx);
cpu_model = (eax >> 4) & 0x0F;
cpu_family = (eax >> 8) & 0x0F;
LOG("Используется процессор AMD, 0x8FFFFFFF = [%s]\n", eggs_string);
LOG("cpu_model = [%u]\n", cpu_model);
LOG("cpu_family = [%u]\n", cpu_family);
}
static void brandname( ) {
uint32_t eax, ebx, ecx, edx;
char brand_string[49];
uint32_t brand[12];
uint32_t manufacturer[4];
char manufacturer_string[13];
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2],
&manufacturer[1]);
tool_memcpy(manufacturer_string, manufacturer, 12);
brand_string[48] = 0;
manufacturer_string[12] = 0;
LOG("[CPUID] manufacturer [%s]\n", manufacturer_string);
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
if (eax >= 0x80000004) {
cpuid(0x80000002, &brand[0], &brand[1], &brand[2], &brand[3]);
cpuid(0x80000003, &brand[4], &brand[5], &brand[6], &brand[7]);
cpuid(0x80000004, &brand[8], &brand[9], &brand[10], &brand[11]);
tool_memcpy(brand_string, brand, 48);
LOG("[CPUID] 0x80000002:0x80000004 [%s]\n", brand_string);
}
if (manufacturer[0] == 0x68747541) { do_amd( ); }
}
void cpu_idle( ) {
if (acpi_msrs_support) {
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
get_cpu_temperature_intel( ));
}
}
void cpu_init( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(1, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) {
asm volatile("finit");
LOG("FPU(x87) поддерживается!\n");
}
if ((edx >> 22) & 1) {
acpi_msrs_support = true;
LOG("Встроенный терморегулятор MSRS для ACPI\n");
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
get_cpu_temperature_intel( ));
}
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
LOG("Максимально поддерживаемая функция CPUID = 0x%x (%u)\n", eax, eax);
cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
if ((edx >> 5) & 1) { LOG("Регистры MSR подерживаются!\n"); }
if ((edx >> 9) & 1) {
LOG("Усовершенствованный программируемый контроллер прерываний "
"поддерживается!\n");
}
if ((edx >> 10) & 1) {
LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
}
if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); }
if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); }
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); }
if ((edx >> 4) & 1) {
LOG("Аппаратный терморегулятор (HTC) поддерживается!\n");
}
if ((edx >> 5) & 1) {
LOG("Программный терморегулятор (STC) поддерживается!\n");
}
brandname( );
}

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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[];

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -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));
}

View File

@ -1,319 +0,0 @@
/**
* mem.c
* Функции управления памятью
*
* Основной функционал менеджера памяти
*
*/
#include <fb.h>
#include <limine.h>
#include <lock.h>
#include <mem.h>
#include <stdbool.h>
#include <tool.h>
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0,
.response = (struct limine_memmap_response *)0
};
static volatile struct limine_hhdm_request hhdm_request = {
.id = LIMINE_HHDM_REQUEST,
.revision = 0,
.response = (struct limine_hhdm_response *)0
};
struct mem_entry {
struct mem_entry *next;
bool free;
size_t size;
uint8_t data[0];
};
typedef struct mem_entry mem_entry_t;
// Битовая карта для отслеживания занятых и свободных фреймов памяти
static uint8_t *bitmap;
// Объем доступных блоков
static uint64_t bitmap_available = 0;
// Объем блоков
static uint64_t bitmap_limit = 0;
// Верхняя граница доступной памяти
static uint64_t limit;
// Объем всего доступного физического адресного пространства
static uint64_t usable = 0;
// Объем доступной виртуальной памяти
static uint64_t available = 0;
// Наивысший адрес в available space
static uint64_t highest = 0;
// Количество записей в карте памяти
static uint64_t mmmap_count = 0;
static const char memory_types[8][82] = {
"Доступно", "Зарезервировано", "ACPI, можно освободить",
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
"Ядро и модули", "Буфер кадра"
};
static struct limine_memmap_response *memmap_response;
static mem_entry_t *first_node;
void mem_dump_memory( ) {
mem_entry_t *curr = first_node;
while (curr) {
LOG("->0x%x | %u.%u kb | %s | 0x%x\n", &curr->data, (curr->size) / 1024,
(curr->size) % 1024, curr->free ? memory_types[0] : memory_types[1],
curr->next);
curr = curr->next;
}
}
void mem_check_dynamic_memory( ) {
mem_entry_t *curr = first_node;
uint64_t free_mem = 0;
while (curr) {
if (curr->free) { free_mem += curr->size; }
curr = curr->next;
}
if (free_mem < 1024 * BLOCK_SIZE) {
void *ptr = mem_frame_alloc(1024);
if (ptr == NULL) {
LOG("Память кончилась!\n");
return;
}
mem_add_block(ptr, 1024 * BLOCK_SIZE);
mem_merge_all_blocks( );
}
}
void mem_frame_free(void *addr, uint64_t frames) {
// Проход по фреймам памяти и очистка битов в битовой карте
uint64_t frame = (uint64_t)addr / BLOCK_SIZE;
for (uint64_t i = frame; i < frames + frame; i++) { BIT_CLEAR(i); }
bitmap_available += frames;
}
// Функция выделения памяти
void *mem_frame_alloc(uint64_t wanted_frames) {
void *addr;
uint64_t available_frames = 0;
for (uint64_t frame = 1; frame < limit; frame++) {
if (!BIT_GET(frame)) {
available_frames++;
} else if (available_frames != wanted_frames) {
available_frames = 0;
continue;
}
if (available_frames == wanted_frames) {
uint64_t i;
for (i = 0; i < wanted_frames; i++) { BIT_SET(frame - i); }
frame -= i - 1;
addr = (void *)(BLOCK_SIZE * frame);
bitmap_available -= wanted_frames;
return addr;
}
}
return NULL;
}
void *mem_frame_calloc(uint64_t frames) {
void *addr = mem_frame_alloc(frames);
tool_memset(addr + HHDM_OFFSET, 0, frames * BLOCK_SIZE);
return addr;
}
static void merge_blocks(mem_entry_t *start) {
if (!start->free) return;
mem_entry_t *block = start;
while (block->next && block->next->free) {
block->size += block->next->size + sizeof(mem_entry_t);
block->next = block->next->next;
}
}
void mem_merge_all_blocks( ) {
mem_entry_t *curr = first_node;
while (curr) {
merge_blocks(curr);
curr = curr->next;
}
}
void mem_add_block(void *addr, size_t size) {
mem_entry_t *new_entry = (mem_entry_t *)addr;
new_entry->size = size - sizeof(mem_entry_t);
new_entry->free = true;
if (first_node == NULL) {
first_node = new_entry;
new_entry->next = NULL;
} else {
mem_entry_t *curr = first_node;
while (curr->next != NULL) { curr = curr->next; }
curr->next = new_entry;
new_entry->next = NULL;
}
}
static void alloc_init(void *address, size_t length) {
first_node = (mem_entry_t *)address;
first_node->size = length - sizeof(mem_entry_t);
first_node->free = true;
first_node->next = NULL;
}
static void *alloc_align(size_t size, size_t alignment) {
mem_entry_t *curr = first_node;
while (curr) {
if (curr->free) {
void *addr = curr->data + alignment - 1;
addr -= (uintptr_t)addr % alignment + sizeof(mem_entry_t);
mem_entry_t *second = (mem_entry_t *)addr;
if (curr->size >= (second->data - curr->data + size)) {
mem_entry_t *third = (mem_entry_t *)(second->data + size);
third->size = curr->size - (third->data - curr->data);
third->next = curr->next;
third->free = 1;
second->size = size;
second->next = third;
second->free = 0;
if (curr != second) {
curr->next = second;
curr->size = (uintptr_t)second - (uintptr_t)curr->data;
curr->free = 1;
}
return second->data;
}
}
curr = curr->next;
}
return NULL;
}
void *mem_alloc(size_t size) {
mem_check_dynamic_memory( );
return alloc_align(size, 1);
}
void mem_free(void *addr) {
mem_entry_t *curr = first_node, *prev = NULL;
while (curr != NULL) {
if (curr->data == addr) {
curr->free = 1;
merge_blocks(prev ? prev : curr);
return;
}
prev = curr;
curr = curr->next;
}
}
void *mem_realloc(void *addr, size_t size) {
if (size == 0) {
mem_free(addr);
return NULL;
}
if (addr == NULL) { return mem_alloc(size); }
void *new_addr = mem_alloc(size);
if (new_addr == NULL) { return NULL; }
tool_memcpy(new_addr, addr, size);
mem_free(addr);
return new_addr;
}
// Инициализация менеджера памяти
void mem_init( ) {
// Получение информации о доступной памяти из Limine bootloader
memmap_response = memmap_request.response;
mmmap_count = memmap_response->entry_count;
struct limine_memmap_entry **mmaps = memmap_response->entries;
LOG("Записей в карте памяти: %u\n", memmap_response->entry_count);
// Обработка каждой записи в карте памяти
for (uint64_t i = 0; i < mmmap_count; i++) {
available += mmaps[i]->length;
// LOG("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
// mmaps[i]->base, mmaps[i]->length, memory_types[mmaps[i]->type]);
if (mmaps[i]->type == LIMINE_MEMMAP_FRAMEBUFFER) {
LOG("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
"килобайт\n",
mmaps[i]->length / 1024 / 1024,
(mmaps[i]->length / 1024) % 1024);
}
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
usable += mmaps[i]->length;
uint64_t top = mmaps[i]->base + mmaps[i]->length;
if (top > highest) highest = top;
}
limit = highest / BLOCK_SIZE;
uint64_t bitmap_size = ALIGN_UP(highest / BLOCK_SIZE / 8, BLOCK_SIZE);
// Находим доступное место для битовой карты и устанавливаем ее
for (uint64_t i = 0; i < mmmap_count; i++) {
if (!mmaps[i]->type == LIMINE_MEMMAP_USABLE) continue;
if (mmaps[i]->length >= bitmap_size) {
bitmap = (uint8_t *)mmaps[i]->base;
tool_memset(bitmap, 0xFF, bitmap_size);
mmaps[i]->length -= bitmap_size;
mmaps[i]->base += bitmap_size;
available -= bitmap_size;
break;
}
}
// Освобождаем все доступные фреймы памяти
for (uint64_t i = 0; i < mmmap_count; i++) {
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
bitmap_limit++;
}
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
mem_frame_free((void *)mmaps[i]->base + t, 1);
}
}
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
LOG("Размер битовой карты: %u\n", bitmap_size);
alloc_init(mem_frame_alloc(1), BLOCK_SIZE);
LOG("%u мегабайт выделено в динамичную память\n",
(256 * 16 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
for (uint64_t i = 256 * 16; i > 0; i -= BLOCK_SIZE) {
mem_add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
}
mem_merge_all_blocks( );
mem_dump_memory( );
LOG("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
(bitmap_available * BLOCK_SIZE) / 1024 / 1024, available / 1024 / 1024);
LOG("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
LOG("Проверка менеджера памяти\n");
}

View File

@ -1,123 +0,0 @@
/**
* mod.c
* Функции загрузки модулей
*
* Файл с функциями для загрузки модулей в формате ELF файлов полученных от
* загрузчика
*
*/
#include <fb.h>
#include <limine.h>
#include <mod.h>
#include <sys.h>
#include <tool.h>
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0,
.response = (struct limine_module_response *)0
};
static struct limine_module_response *module_response;
uint64_t modules_count = 0;
module_info_t module_list[MOD_MAX];
static char *graphics_module_message = "Графический модуль-объект";
static char *other_module_message = "Неизвестный тип модуля";
static env_t main_env;
void *bootpng_ptr;
uint64_t bootpng_size;
static void *elf_entry(elf64_header_t *module_bin) {
// Приводим заголовок ELF файла к типу elf64_header_t
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
// Возвращаем указатель на точку входа
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
}
void mod_list_show( ) {
for (uint64_t i = 0; i < modules_count; i++) {
fb_printf("Имя: %s\n", module_list[i].name);
fb_printf("Описание модуля: %s\n", module_list[i].message);
fb_printf("Тип модуля: %u\n", module_list[i].type);
fb_printf("Код ошибки модуля: %u\n", module_list[i].err_code);
fb_printf("Размер данных: %u\n", module_list[i].data_size);
fb_printf("Адрес данных: 0x%x\n", module_list[i].data);
}
}
module_info_t *mod_find(char *tag) {
for (uint64_t i = 0; i < modules_count; i++) {
if (!tool_starts_with(module_list[i].name, tag)) {
return &module_list[i];
}
}
return (module_info_t *)NULL;
}
void mod_init( ) {
module_response = module_request.response;
uint64_t module_count = module_response->module_count;
struct limine_file *module_ptr = (struct limine_file *)0;
for (uint64_t i = 0; i < module_count; i++) {
module_ptr = module_response->modules[i];
LOG("[%d] %s [%s] 0x%x Размер: %u\n", i, module_ptr->path,
module_ptr->cmdline, module_ptr->address, module_ptr->size);
if (modules_count >= MOD_MAX) {
LOG("Модуль не обработан. Максимум %u модулей!\n", MOD_MAX);
break;
}
module_list[modules_count].name = module_ptr->cmdline;
module_list[modules_count].message = other_module_message;
if (tool_starts_with(module_ptr->cmdline, "[BOOTIMG]")) {
module_list[modules_count].data_size = module_ptr->size;
module_list[modules_count].data = module_ptr->address;
bootpng_ptr = module_ptr->address;
bootpng_size = module_ptr->size;
module_list[modules_count].type = 1; // Графика
module_list[modules_count].message = graphics_module_message;
modules_count++;
continue;
}
if (!tool_starts_with(module_ptr->cmdline, "[MOD]")) {
module_list[modules_count].type = 255; // Неизвестный тип модуля
modules_count++;
continue;
}
module_info_t (*module_init)(env_t * env) =
(module_info_t(*)(env_t * env))
elf_entry((elf64_header_t *)module_ptr->address);
LOG("\t->Точка входа: 0x%x\n", module_init);
main_env.offset = (uint64_t)module_ptr->address;
main_env.info = (module_info_t *)0;
sys_install(main_env);
main_env.fb_printf = &fb_printf;
module_info_t ret = module_init(&main_env);
module_list[modules_count].message = ret.message;
module_list[modules_count].data_size = ret.data_size;
if (ret.data_size != 0) {
module_list[modules_count].data =
(&(ret.data) + (uint64_t)module_ptr->address);
}
modules_count++;
}
LOG("Модулей обработано: %u\n", modules_count);
}

View File

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

View File

@ -1,68 +0,0 @@
/**
* sys.c
* Файл с функциями управления системой
*
* Этот файл содержит имплементацию функций для управления системой
*/
#include <fb.h>
#include <mod.h>
#include <stdint.h>
#include <sys.h>
module_info_t *current_module;
void sys_init( ) {}
static framebuffer_t *sys_alloc_framebuffer( ) {
return (framebuffer_t *)0;
}
static void sys_free_framebuffer(framebuffer_t *frame) {
frame->reserved = 0;
}
static void sys_exit(int code) {
current_module->err_code = code;
}
static int sys_get_error( ) {
return current_module->err_code;
}
static sys_info_t *sys_get_info( ) {
return &(sys_info_t){ .reserved = 0 };
}
static module_info_t *sys_get_module(char *module_id) {
return (module_info_t *)mod_find(module_id);
}
static uint64_t sys_new_thread(uint64_t func) {
return func;
}
static int sys_delete_thread(uint64_t thread_id) {
return thread_id;
}
static time_t sys_get_time( ) {
return (time_t){ .year = 2023, .month = 10, .day = 31, .second = 1 };
}
env_t sys_install(env_t module) {
module.fb_printf = &fb_printf;
module.alloc_framebuffer = &sys_alloc_framebuffer;
module.free_framebuffer = &sys_free_framebuffer;
module.exit = &sys_exit;
module.get_error = &sys_get_error;
module.get_info = &sys_get_info;
module.get_module = &sys_get_module;
module.new_thread = &sys_new_thread;
module.delete_thread = &sys_delete_thread;
module.get_time = &sys_get_time;
return module;
}
// void sys_set_alarm(time_t time, func_t func) {}

View File

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

View File

@ -1,189 +0,0 @@
/**
* tool.c
* Функции для упрощения разработки
*
* Данный файл содержит реализацию функций для упрощения написания кода
*
*/
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
void tool_memcpy(void *dest, void *src, uint64_t n) {
char *d = (char *)dest;
const char *s = (const char *)src;
for (uint64_t i = 0; i < n; i++) { d[i] = s[i]; }
}
void *tool_memset(void *ptr, uint8_t n, uint64_t size) {
uint8_t *p = (uint8_t *)ptr;
for (uint64_t i = 0; i < size; i++) { p[i] = n; }
return ptr;
}
uint64_t tool_strlen(const char *str) {
uint64_t length = 0;
while (*str) {
length++;
str++;
}
return length;
}
uint64_t tool_starts_with(const char *str, const char *prefix) {
uint64_t str_len = tool_strlen(str);
uint64_t prefix_len = tool_strlen(prefix);
if (prefix_len > str_len) { return 0; }
for (uint64_t i = 0; i < prefix_len; i++) {
if (str[i] != prefix[i]) { return 0; }
}
return 1;
}
// Функция для переворачивания строки
void tool_reverse_str(char *str) {
int len = 0;
while (str[len] != '\0') { len++; }
int start = 0;
int end = len - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
// Преобразование целого числа "i" в системе счисления "base" в строку "buf"
void tool_int_to_str(int64_t i, uint8_t base, char *buf) {
bool negative = false;
// Проверяем, является ли число отрицательным
if (i < 0) {
negative = true;
i *= -1; // Если да, то умножаем на -1, чтобы сделать его положительным
}
int64_t index = 0;
// Деление с остатком для преобразования числа в нужную систему счисления
do {
int64_t remainder = i % base;
// Преобразовываем остаток в символ и добавляем его в строку
buf[index++] =
(remainder > 9)
? (remainder - 10) + 'A'
: remainder +
'0'; // Если остаток > 9, добавляем заглавную букву А
i /= base;
} while (i > 0);
// Если число было отрицательным, добавляем знак минуса в конец строки
if (negative) { buf[index++] = '-'; }
// Добавляем нулевой символ в конец строки, чтобы завершить ее
buf[index] = '\0';
// Переворачиваем строку, чтобы цифры были в правильном порядке
tool_reverse_str(buf);
}
// Преобразование неотрицательного целого числа "i" в системе счисления "base" в
// строку "buf"
void tool_uint_to_str(uint64_t i, uint8_t base, char *buf) {
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);
// Добавляем нулевой символ в конец строки, чтобы завершить ее
buf[index] = '\0';
// Переворачиваем строку, чтобы цифры были в правильном порядке
tool_reverse_str(buf);
}
// Функция для форматированного вывода
void tool_format(void (*putc)(char c), const char *format_string,
va_list args) {
while (*format_string != '\0') {
if (*format_string == '%') {
char buf[48];
uint64_t point = 0;
const char *arg_s;
int64_t arg_d = 0;
uint64_t arg_u = 0;
format_string++;
if (*format_string == '\0') {
break; // Неожиданный конец строки формата
}
switch (*format_string) {
case '%': putc('%'); break;
case 'c': putc(va_arg(args, int)); break;
case 's':
arg_s = va_arg(args, const char *);
// Вывод каждого символа строки
while (*arg_s != '\0') {
putc(*arg_s);
arg_s++;
}
break;
case 'd':
arg_d = va_arg(args, int64_t);
tool_int_to_str(arg_d, 10, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
}
break;
case 'u':
arg_u = va_arg(args, uint64_t);
tool_uint_to_str(arg_u, 10, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
}
break;
case 'x':
arg_u = va_arg(args, uint64_t);
tool_uint_to_str(arg_u, 16, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
}
break;
case 'l':
arg_u = va_arg(args, uint64_t);
tool_uint_to_str(arg_u, 16, buf);
while (buf[point] != '\0') {
putc(buf[point]);
point++;
}
break;
default: putc('?'); break;
}
} else {
putc(*format_string);
}
format_string++;
}
}

View File

@ -1,84 +0,0 @@
/**
* system.h
* Системные вызовы
*
* Заголовочный файл содержащий заготовку для работы с системными вызовами
*
*/
#ifndef SYSTEM_H
#define SYSTEM_H
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef long long int64_t;
typedef struct {
int reserved;
} framebuffer_t;
typedef struct {
int reserved;
} sys_info_t;
typedef struct {
char *name;
void *addr;
} module_func_t;
typedef struct {
char *name;
char *message;
uint64_t type;
uint64_t data_size;
void *data;
int64_t err_code;
uint64_t module_id;
} module_info_t;
typedef struct {
int reserved;
} func_t;
typedef struct {
uint8_t a[4];
uint8_t b[4];
uint8_t c[4];
uint8_t d[4];
} uid_t;
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t second;
} time_t;
typedef struct {
uint64_t offset;
module_info_t *info;
void (*fb_printf)(char *str, ...); // Временная функция
framebuffer_t *(*alloc_framebuffer)( );
void (*free_framebuffer)(framebuffer_t *frame);
void (*exit)(int code);
void (*get_error)( );
sys_info_t *(*get_info)( );
module_info_t *(*get_module)(char *module_id);
uint64_t (*new_thread)(uint64_t func);
int (*delete_thread)(uint64_t thread_id);
time_t (*get_time)( );
} env_t;
extern module_info_t static_info;
static void (*fb_printf)(char *str, ...);
static uint64_t offset;
static inline void init_env(env_t *loader_env) {
offset = loader_env->offset;
loader_env->info = (module_info_t *)&static_info + offset;
fb_printf = loader_env->fb_printf;
}
#endif // system.h

View File

@ -1,9 +0,0 @@
# Модули
Стандартные модули поставляются вместе с ядром БМПОС в виде исходного кода.
Вы можете создавать свои модули, ниже предоставлена информация о том как это сделать.
## Сборка модулей
Сборка стандартных модулей происходит во время сборки ядра из скрипта `build.sh`.

View File

@ -1,7 +0,0 @@
#/bin/sh
echo "Название: CPUBENCH"
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
cp cpubench.ko ../bin/
echo "Сборка завершена, файл: cpubench.ko"

View File

@ -1,60 +0,0 @@
#include <system.h>
static char fxsave_region[512] __attribute__((aligned(16)));
static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx) {
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
}
static inline void L1_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
fb_printf("L1 кэш недоступен\n");
return;
}
fb_printf(
"L1: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
ecx & 0xff, (ecx >> 12) & 0x07, (ecx >> 16) & 0xffff);
}
static inline void L2_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
fb_printf("L2 кэш недоступен\n");
return;
}
fb_printf(
"L2: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
ecx & 0xff, (ecx >> 12) & 0x0F, (ecx >> 16) & 0xFFFF);
}
static inline void L3_cache_size( ) {
uint32_t eax, ebx, ecx, edx;
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
if ((edx & 0xFF) == 0) {
fb_printf("L3 кэш недоступен\n");
return;
}
fb_printf(
"L3: Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
edx & 0xff, (edx >> 12) & 0x0F, (edx >> 16) & 0xFFFF);
}
module_info_t init(env_t *env) {
init_env(env);
L1_cache_size( );
L2_cache_size( );
L3_cache_size( );
return (module_info_t){
.name = (char *)"CPUBENCH",
.message = (char *)"Дополнительная информация о процессоре",
.err_code = 0,
};
}

View File

@ -1,7 +0,0 @@
#/bin/sh
echo "Название: Hello world"
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
cp hello.ko ../bin/
echo "Сборка завершена, файл: hello.ko"

View File

@ -1,14 +0,0 @@
#include <system.h>
static const char name[] = "Привет мир!";
static const char message[] = "Привет из модуля!";
module_info_t init(env_t *env) {
init_env(env);
fb_printf("[%s]\n", message);
return (module_info_t){
.name = (char *)&name,
.message = (char *)&message,
.err_code = 2023,
};
}

View File

@ -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"

View File

@ -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 каждый раз
}
}

View File

@ -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.o
gcc -Wl,--entry=init -fPIC -shared -nostdlib pci.o -o pci.ko
cp pci.ko ../bin/
echo "Сборка завершена, файл: pci.ko"

View File

@ -1,85 +0,0 @@
#include <system.h>
typedef struct {
char *name;
uint16_t id;
} vendor_t;
static inline uint32_t inl(uint16_t port) {
uint32_t data;
asm volatile("inl %1, %0" : "=a"(data) : "Nd"(port));
return data;
}
static inline void outl(uint16_t port, uint32_t data) {
asm volatile("outl %0, %1" : : "a"(data), "Nd"(port));
}
static inline uint16_t pci_read_word(uint16_t bus, uint16_t slot, uint16_t func,
uint16_t offset) {
uint64_t address;
uint64_t lbus = (uint64_t)bus;
uint64_t lslot = (uint64_t)slot;
uint64_t lfunc = (uint64_t)func;
uint16_t tmp = 0;
address = (uint64_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) |
(offset & 0xFC) | ((uint32_t)0x80000000));
outl(0xCF8, address);
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
return (tmp);
}
static inline uint16_t get_vendor_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0);
return r0;
}
static inline uint16_t get_device_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 2);
return r0;
}
static inline uint16_t get_class_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
return (r0 & ~0x00FF) >> 8;
}
static inline uint16_t get_sub_class_id(uint16_t bus, uint16_t device,
uint16_t function) {
uint32_t r0 = pci_read_word(bus, device, function, 0xA);
return (r0 & ~0xFF00);
}
static inline void scan( ) {
uint64_t devices = 0;
for (uint32_t bus = 0; bus < 256; bus++) {
for (uint32_t slot = 0; slot < 32; slot++) {
for (uint32_t function = 0; function < 8; function++) {
uint16_t vendor = get_vendor_id(bus, slot, function);
if (vendor == 0xFFFF) { continue; }
uint16_t device_id = get_device_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",
devices, vendor, device_id, class_id);
devices++;
}
}
}
}
module_info_t init(env_t *env) {
init_env(env);
scan( );
return (module_info_t){
.name = (char *)"[PCI]",
.message = (char *)"PCI драйвер",
.err_code = 0,
};
}

View File

@ -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"

View File

@ -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 };
}

View File

@ -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"

View File

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

173
pbuild.py
View File

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

6
run.sh
View File

@ -1,6 +0,0 @@
#!/bin/sh
qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -hda bmosp.hdd --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -cdrom bmosp.iso -boot d --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu max -m 1G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd -d int --no-reboot
#qemu-system-x86_64 -name "БМПОС" -cpu host -m 1G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd
#qemu-system-x86_64 -name "БМПОС" -enable-kvm -cpu host -m 6G -smp 1 -bios ovmf/OVMF.fd -hda bmosp.hdd -d int --no-reboot

View File

@ -1,29 +0,0 @@
#!/bin/bash
mkdir -p sdk
cd sdk
echo "Updating..."
sudo apt-get update
sudo apt-get -y install build-essential g++ make bison flex texinfo libgmp-dev libmpc-dev libmpfr-dev libisl-dev
if [ ! -d "gcc-12.3.0" ]; then
echo "Installing gcc..."
wget https://ftp.gnu.org/gnu/gcc/gcc-12.3.0/gcc-12.3.0.tar.xz
tar -xf gcc-12.3.0.tar.xz
fi
cd gcc-12.3.0/
echo "Configure..."
contrib/download_prerequisites
mkdir -p build
cd build
pwd
../configure --target=x86_64-elf --prefix=$PWD/cross --disable-nls --enable-languages=c --without-headers
echo "Build GCC..."
make all-gcc -j$(nproc)
echo "Build all-target-libgcc..."
make all-target-libgcc -j$(nproc)
echo "install-gcc..."
make install-gcc
echo "install-target-libgcc..."
make install-target-libgcc

View File

@ -1,18 +0,0 @@
# Генерируем код для isr_stubs
isr_stubs_code = ''
for i in range(256):
isr_stubs_code += f'\t.quad isr_stub_{i}\n'
# Генерируем код для isr_stub
isr_stub_code = ''
for i in range(256):
isr_stub_code += f'stub {i}\n'
# Сохраняем код в файл
with open('output.s', 'w') as file:
file.write('.section .text\n')
file.write(isr_stub_code)
file.write('.global isr_stubs\n')
file.write('.section .data\n')
file.write('isr_stubs:\n')
file.write(isr_stubs_code)

View File

@ -1,12 +0,0 @@
/**
* <название файла>.c
* Краткое описание
*
* Полное описание
*
*/
// Описание функции
void функция( ) {
Тело функции
}

View File

@ -1,14 +0,0 @@
/**
* <название файла>.h
* Краткое описание
*
* Полное описание
*
*/
#ifndef ИМЯ_ФАЙЛА_H
#define ИМЯ_ФАЙЛА_H
void функция( );
#endif // <название файла>.h