Compare commits

..

205 Commits

Author SHA1 Message Date
Aren Elchinyan a93ca306ce
Merge pull request #14 from 0Nera/feature
Исправлена работа модулей, повышена стабильность системы
2024-09-17 21:53:13 +03:00
Aren Elchinyan e4b16535ac Убран python из CodeQL 2024-09-17 21:47:53 +03:00
Aren Elchinyan d2a0fc6162 Изменение настроек запуска CI 2024-09-17 21:47:19 +03:00
Aren Elchinyan add8945f53 Исправление настроек codeql 2024-09-17 21:45:40 +03:00
Aren Elchinyan 52f8c14a8f Исправление сборки на CI 2024-09-17 21:33:47 +03:00
Aren Elchinyan 140790cf92 Обновление инструкций по сборке 2024-09-17 21:33:02 +03:00
Aren Elchinyan 7631e05421 Заготовка для порта DOOM 2024-09-17 21:30:03 +03:00
Aren Elchinyan fb2effa5b7 Исправлена работа модулей, повышена стабильность системы 2024-09-17 21:29:52 +03:00
Aren Elchinyan 18ceec804b
Merge pull request #12 from 0Nera/feature
Более стабильная работа модулей
2024-09-17 10:10:49 +03:00
Aren Elchinyan f214c92430 Небольшие исправления 2024-09-17 10:05:22 +03:00
Aren Elchinyan ae0c7db85b
Merge pull request #11 from 0Nera/feature
Изменение API
2024-09-16 21:45:55 +03:00
Aren Elchinyan 03742e31bb Добавлена поддержка преобразования UTF8->CP1251 2024-09-16 21:43:13 +03:00
Aren Elchinyan 5175bba935 Переход на новый API 2024-09-16 21:42:47 +03:00
Aren Elchinyan 9a56ff681a Ускорение вывода на экран 2024-09-16 21:42:02 +03:00
Aren Elchinyan cce42f26e6 Модуль SIMD вынесен в ядро 2024-09-16 18:35:06 +03:00
Aren Elchinyan c41fe4a8a5 Удалён модуль TGA 2024-09-16 18:29:44 +03:00
Aren Elchinyan 6d414307dc Удалена сборка RAW образа 2024-09-16 18:29:16 +03:00
Aren Elchinyan 89652e9819 Исправление CI 2024-09-16 17:01:28 +03:00
Aren Elchinyan af1d9d80a9 Небольшие исправления 2024-09-16 16:58:28 +03:00
Aren Elchinyan 5858814e6b Удален партнер "НПО ТЕ-ОН" 2024-08-01 15:25:58 +03:00
Aren Elchinyan d8457784f7 Обновление Readme 2024-08-01 15:25:33 +03:00
Aren Elchinyan 121c408a6c Добавлен скрипт синхронизации 2024-08-01 15:24:47 +03:00
Aren Elchinyan ac3e6705d4 Небольшие исправления 2024-08-01 15:18:29 +03:00
Aren 230eecc911 Динамическая линковка символов [1/3] 2024-04-30 13:34:47 +03:00
Aren 14457a8266 Merge branch 'feature' 2024-04-25 19:46:39 +03:00
Aren 40c1604109 Добавлен разбор ELF файлов 2024-04-25 19:46:03 +03:00
Арен Елчинян 09abbdbb2b Обновлен список партнёров 2024-04-23 15:39:09 +03:00
Арен Елчинян 82cec87a36 Merge pull request 'Слияние веток' (#2) from feature into master
Reviewed-on: Aren/BMOSP#2
2024-03-04 16:20:34 +03:00
Aren e7233a7b4c Вернули в активную разработку Синапс ОС 2024-03-04 16:18:48 +03:00
Aren Elchinyan d6691de198 fb_printf заменен на log_printf
Мы не можем гарантировать наличие фреймбуффера
2024-03-03 14:43:11 +03:00
Aren 00cbc46cb7 Улучшение читаемости 2024-02-21 16:49:57 +03:00
Aren e258525c8a Добавлены функции развертывания таблиц страниц 2024-02-21 16:49:46 +03:00
Aren Elchinyan ae0b51beb1
Merge pull request #8 from 0Nera/master
Обновление ветки feature
2024-02-17 13:13:03 +03:00
Aren Elchinyan a950c792ef
Merge pull request #7 from grayed/master
Unhardcode GCC and AR values
2024-02-17 13:10:07 +03:00
Aren ed3af8d570 Исправлена сборка ISO образов 2024-02-15 18:05:06 +03:00
Vadim Zhukov 88fbf011e9 Unhardcode GCC and AR values. 2024-02-14 17:46:32 +03:00
Aren Elchinyan bf12663b3b Обновлен список задач 2024-02-14 17:43:06 +03:00
Aren e1e88ada09 Merge branch 'master' of https://git.synapseos.ru/Aren/BMOSP 2024-02-12 16:42:55 +03:00
Aren Elchinyan 3bb064c9d9 Основные работы по оболочке ввода-вывода выполнены 2024-02-06 22:46:10 +03:00
Aren Elchinyan b57b453332 Добавлен вывод информации для процессоров Intel 2024-02-05 22:21:58 +03:00
Aren Elchinyan a893d61040 Исправление опечатки 2024-02-05 21:19:04 +03:00
Aren Elchinyan 1dbaf29a96 Удаление лишней отладочной информации 2024-02-05 20:58:24 +03:00
Aren Elchinyan 384d04b89b Добавлены модули-приложения 2024-02-05 20:58:08 +03:00
Aren Elchinyan 7e9cbe5e07 Небольшие оптимизации 2024-02-05 20:57:44 +03:00
Aren Elchinyan 114e30614b Отключена загрузка модулей: tga, imfs 2024-02-05 20:57:17 +03:00
Aren Elchinyan b424a5a055 Удалена поддержка Arch Linux
В связи с нехваткой рук проверить на всех системах работоспособность функционала трудно, это временная мера
2024-02-05 20:56:28 +03:00
Aren Elchinyan e21551f008 Исправлена обработка нажатий PS/2 2024-02-02 19:18:55 +03:00
Aren Elchinyan 9deba0b828 Небольшое исправление вызовов 2024-02-02 19:07:34 +03:00
Aren Elchinyan d5cb26f9a4 Оптимизация потребления ОЗУ
Теперь для запуска требуется всего 27 мегабайт ОЗУ!
2024-02-02 18:36:48 +03:00
Aren 89307ea263 Добавлен флаг остановки эмулятора в случае ошибки 2024-02-02 13:13:15 +03:00
Aren 3a6c3b3ca7 Обновлен скриншот ядра 2024-02-01 20:40:45 +03:00
Aren Elchinyan 8fe1df88a3 0.2.0 2024-02-01 20:12:47 +03:00
Aren 885a097feb Исправление предупреждений 2024-02-01 18:24:01 +03:00
Aren Elchinyan 84e5169bff Добавлена трассировка стека 2024-02-01 11:12:35 +03:00
Aren Elchinyan ba1047a70d pci_data снова включен 2024-02-01 10:24:52 +03:00
Aren Elchinyan 933baa57f9 Небольшие оптимизации 2024-02-01 10:24:32 +03:00
Aren Elchinyan e31c9db524 Добавлена функция удаления поток по ID 2024-02-01 10:23:43 +03:00
Aren Elchinyan 70d6805c0f Добавлена настройка имени потока 2024-02-01 10:23:28 +03:00
Aren Elchinyan 8ad4c32272 Добавлен дамп потоков 2024-02-01 10:18:24 +03:00
Aren Elchinyan 1ab27c1a70 Добавлен начальный файл для страничной адресации 2024-01-31 21:01:19 +03:00
Aren Elchinyan 176fe9b66b Добавлена шапка для com.c 2024-01-31 20:56:56 +03:00
Aren Elchinyan 70d722deee Исправление версионирования 2024-01-31 20:19:33 +03:00
Aren Elchinyan 2b35ed412f Исправление предупреждений 2024-01-31 20:12:08 +03:00
Aren Elchinyan 8c54109dc9 GDT больше не используется 2024-01-31 20:09:55 +03:00
Aren Elchinyan 7c07bf5ffd Исправление CI/CD 2024-01-31 20:09:27 +03:00
Aren Elchinyan 112da40706 Оптимизация потоков 2024-01-31 19:41:43 +03:00
Aren Elchinyan 709116f554 Исправление типизации 2024-01-31 19:35:30 +03:00
Aren Elchinyan f218333bd0 Небольшое исправление документации 2024-01-31 19:35:12 +03:00
Aren Elchinyan 29b9d6ba3a Добавлен флаг ARCH_FLAGS="-fno-stack-protector -ffreestanding 2024-01-31 19:28:00 +03:00
Aren Elchinyan 11a130c9ab Обновлены инструкции 2024-01-29 22:13:27 +03:00
Aren Elchinyan 73bf252f98 Добавлена функция str_contains 2024-01-27 22:04:14 +03:00
Aren Elchinyan adf6d4a8b9 Добавлена функция удаления потока 2024-01-27 22:03:33 +03:00
Aren Elchinyan fc43b6746a Добавлен прототип менеджера модулей 2024-01-25 19:17:42 +03:00
Aren Elchinyan 39fb9c7f2e Добавление CONTRIBUTING.md 2024-01-23 21:07:11 +03:00
Aren Elchinyan c875299b3d Небольшое исправление инициализации потока 2024-01-23 21:00:04 +03:00
Aren 29bfc8faba Стек увеличен до 16 кб 2024-01-23 16:01:48 +03:00
Aren 87d9ebeb7e Шаблон для отчетов 2024-01-23 13:57:34 +03:00
Aren edc848704c Добавлено отображение поддерживаемых версий 2024-01-23 13:48:27 +03:00
Aren 1c12dd6625 Небольшие исправления в CI 2024-01-23 13:40:00 +03:00
Aren a52835dd47 Добавлен CodeQL 2024-01-23 13:33:08 +03:00
Aren Elchinyan 883c977b28 Небольшие исправления 2024-01-22 21:46:36 +03:00
Aren Elchinyan df965c2218 Добавлен RTC 2024-01-22 21:45:56 +03:00
Aren Elchinyan 969ef786bd Теперь интерфейс загрузчика 1280x720 2024-01-22 21:45:37 +03:00
Aren 93934c6605 Небольшие исправления 2024-01-22 17:45:34 +03:00
Aren Elchinyan feaab75a6f Добавлено время потока 2024-01-21 22:17:37 +03:00
Aren Elchinyan a59ba3412f Revert "Немного увеличен размер стека"
This reverts commit 2915242902.
2024-01-21 22:08:37 +03:00
Aren Elchinyan 2915242902 Немного увеличен размер стека 2024-01-21 22:05:23 +03:00
Aren Elchinyan 50ad112d7f Добавлены блокировки в отладчик 2024-01-21 22:00:56 +03:00
Aren Elchinyan a7703f54ab Монтирование данных из других модулей в IMFS 2024-01-21 22:00:25 +03:00
Aren Elchinyan f61e12d5f8 Основные работы по ядру закончены 2024-01-21 21:40:43 +03:00
Aren Elchinyan c4b8ec6787 Поддержка многопоточности 2024-01-21 21:40:21 +03:00
Aren Elchinyan 90cf91ee31 Уменьшено потребление памяти 2024-01-21 19:26:01 +03:00
Aren Elchinyan d8e5d5f081 Добавлена переменная среды after_init 2024-01-21 19:25:04 +03:00
Aren Elchinyan e0d42d991c Модули теперь используют статичную библиотеку 2024-01-20 21:44:02 +03:00
Aren Elchinyan 99b04b5481 Добавлено переключение потоков 2024-01-20 19:04:26 +03:00
Aren Elchinyan 9527feb839 Перенос директории с шаблонами в docs 2024-01-20 19:03:37 +03:00
Aren Elchinyan 662004cbef Добавлен новый участник 2024-01-18 22:34:45 +03:00
Aren Elchinyan 15d1b4aaf9 Улучшение читаемости отладочных логов 2024-01-18 22:18:36 +03:00
Aren Elchinyan ddc1a1a931 Удалены лишние операции при сборке 2024-01-18 22:17:56 +03:00
Aren Elchinyan 1fc22169cd Количество модулей неограниченно, добавлено: mod_add, mod_del 2024-01-18 22:17:38 +03:00
Aren Elchinyan 687ec44829 Удаление лишних переменных 2024-01-18 22:16:43 +03:00
Aren Elchinyan 365aacf4bc Улучшение визуального оформление в PCI 2024-01-18 22:10:57 +03:00
Aren Elchinyan 4fee1d1c64 Добавление функции tool_uint_pow и доработка форматированного вывода 2024-01-18 22:10:10 +03:00
Aren Elchinyan 5febf988a5 Отключен лишний блок кода в TGA 2024-01-17 22:01:58 +03:00
Aren Elchinyan c29578d020 Небольшие исправления путей 2024-01-17 22:01:40 +03:00
Aren Elchinyan e7a2a02300 Теперь boot.jpg и boot.tga относятся к модулю TGA 2024-01-17 22:00:00 +03:00
Aren 013791d40f Добавлены наработки по рендерингу TGA 2024-01-17 12:47:01 +03:00
Aren 2c14e03d8b Добавлен вывод размера файла 2024-01-17 12:46:13 +03:00
Aren 976da0bee1 Исправление для безопасного запуска 2024-01-17 12:45:27 +03:00
Aren 4396a2bba4 Добавлена инициализация всех функций API 2024-01-17 12:44:56 +03:00
Aren 2c462b6eed Изменен порядок модулей 2024-01-17 12:43:37 +03:00
Aren 2e3fadb9a1 Удалены лишние файлы 2024-01-17 12:43:22 +03:00
Aren Elchinyan 5155e7adae Теперь все символы обрабатываются 2024-01-16 22:23:26 +03:00
Aren Elchinyan fb0af09414 Исправление синтаксиса markdown 2024-01-14 18:15:31 +03:00
Aren Elchinyan e5aae06c09 Небольшие исправления предупреждений 2024-01-14 15:28:26 +03:00
Aren Elchinyan 08bc26c87f Отключены неисправные блоки кода 2024-01-14 15:28:12 +03:00
Aren Elchinyan 471ee3cde3 Добавлены буферы ввода-вывода 2024-01-14 15:27:52 +03:00
Aren Elchinyan 37269c9fba Небольшое исправление pci_vendors.txt 2024-01-14 14:59:05 +03:00
Aren Elchinyan dca0a33564 Исправлено дублирование символов
Исправлено дублирование первого символа при достижении новой строки
2024-01-14 14:53:31 +03:00
Aren Elchinyan 8769136f2f Небольшое исправление при проверке ОС 2024-01-13 20:51:45 +03:00
Aren Elchinyan 210bea4f42 Исправление отрисовки отладочной информации 2024-01-13 18:23:29 +03:00
Aren Elchinyan b6ad573dfa Новая система отладки 2024-01-13 00:00:11 +03:00
Aren 9c11be08c9 Исправлен механизм смены потоков 2024-01-10 19:29:17 +03:00
Aren Elchinyan 224256a8ac Создание тестового менеджера потоков 2024-01-02 16:32:32 +03:00
Aren Elchinyan b9d186cc2f Небольшие исправления 2023-12-28 23:57:07 +03:00
Aren Elchinyan 2d0a37f6a5 Доработка модуля Ps/2 2023-12-25 22:34:54 +03:00
Aren Elchinyan 36d28d5f90 Добавлена ширина в форматированный вывод 2023-12-17 15:21:27 +03:00
Aren Elchinyan bb86ea4071 Перенос скрипта записи на /dev/sdc в папку скриптов 2023-12-17 13:33:18 +03:00
Aren Elchinyan 799cd72615 Перенос документации в папку docs 2023-12-17 13:32:52 +03:00
Aren Elchinyan 63bf02229c Перенос медиафайлов в configs/media/ 2023-12-17 13:31:32 +03:00
Aren Elchinyan f8cf58a450 Добавлено предупреждение 2023-12-17 00:58:14 +03:00
Aren Elchinyan 22a59655b6 Отображение подсказки в режиме отладки 2023-12-17 00:54:13 +03:00
Aren Elchinyan a2be2a4add Мелкие исправления и оптимизации модулей 2023-12-17 00:51:17 +03:00
Aren Elchinyan bed0cd45e6 Портирован IMFS 2023-12-17 00:47:45 +03:00
Aren Elchinyan a2b2b1282b Добавлен вывод COM порта в файл 2023-12-16 00:14:48 +03:00
Aren Elchinyan c376f903b0 Создание шаблона для драйвера COM порта 2023-12-16 00:14:24 +03:00
Aren Elchinyan 76724a1b07 Отключение лишних логов при загрузке 2023-12-16 00:14:03 +03:00
Aren Elchinyan b909a5f963 Возврат текущего фреймбуффера ядром 2023-12-16 00:13:37 +03:00
Aren Elchinyan f4d5158799 Создание модуля TGA 2023-12-16 00:12:39 +03:00
Aren Elchinyan 8ca0335c8f Исправление ошибки операнда 2023-12-15 21:58:52 +03:00
Aren 02ba9d199b Вынос выхода из симуляции в отдельную функцию 2023-12-15 19:21:27 +03:00
Aren 481dcb5ab8 Исправление опечатки 2023-12-15 19:04:26 +03:00
Aren 069ea689e1 Обновление документации 2023-12-15 18:25:38 +03:00
Aren c212598468 Добавлена возможность вызывать функции из других модулей 2023-12-15 18:03:01 +03:00
Aren 1b1528dff1 Удален модуль music 2023-12-15 18:00:44 +03:00
Aren dc73ee66df Добавлен модуль PS/2 2023-12-15 18:00:33 +03:00
Aren 1f6eaf3ca0 Обновление стандартных модулей под новый API 2023-12-15 18:00:19 +03:00
Aren cc7c21f0fd Поддержка обработки прерываний в модулях 2023-12-15 17:59:43 +03:00
Aren Elchinyan e36201c412 Вынос кода в модуль ps/2 2023-12-15 00:39:28 +03:00
Aren Elchinyan 1d06b2443d Исправление мелких ошибок 2023-12-15 00:23:23 +03:00
Aren Elchinyan 7fb682ba9e Расширение получаемой информации от PCI 2023-12-14 12:48:27 +03:00
Aren Elchinyan 730fa37119 Цветная анимация индикации переключения задач 2023-12-14 11:33:10 +03:00
Aren Elchinyan 56d3e73f6d Добавлена функция получение последнего использованного цвета 2023-12-14 11:25:53 +03:00
Aren Elchinyan 65b35be40f При нажатии End будет вызвано переключение задач 2023-12-14 11:25:22 +03:00
Aren Elchinyan acb527b874 Тестирование многопоточности 2023-12-14 11:24:48 +03:00
Aren Elchinyan ffe5b07d83 Обработчик прерываний снова работает 2023-12-14 11:24:22 +03:00
Aren Elchinyan b337fa32f6 Revert "Удаление лишних файлов"
This reverts commit a540661cf4.
2023-12-14 09:54:11 +03:00
Aren Elchinyan 5236f156e6 Вынос инициализации FPU из кода ядра в 2023-12-12 21:42:25 +03:00
Aren Elchinyan f4d7b3e4e9 Добавление эмуляции AMD PCnet Am79C970 2023-12-12 21:18:22 +03:00
Aren Elchinyan fa67828241 Изменение структуры 2023-12-12 21:11:06 +03:00
Aren Elchinyan a540661cf4 Удаление лишних файлов 2023-12-12 21:10:56 +03:00
Aren 3909eb183c Добавлена отправка word в IO порт 2023-12-08 18:11:59 +03:00
Aren 67af4e64bc Стандартное завершение работы средствами виртуальных машин 2023-12-08 18:11:37 +03:00
Aren 7d0133a964 Добавлена проверка на последний блок памяти 2023-12-08 18:11:18 +03:00
Aren a477da15b5 Merge branch 'master' of https://git.synapseos.ru/Aren/BMOSP 2023-12-08 15:50:24 +03:00
Aren Elchinyan a838b8e825 Исправление табов на пробелы в YML 2023-12-07 13:19:35 +03:00
Aren Elchinyan dd45b2ef6c Теперь все модули - статично собираются 2023-12-07 13:17:05 +03:00
Aren Elchinyan 2de168dc78 Более безопасный способ обхода папок модулей 2023-12-07 13:16:34 +03:00
Aren Elchinyan 4bcd50a63f Добавление tool_strcpy 2023-12-07 13:15:53 +03:00
Aren Elchinyan ad38cbda6b Добавление доски отладки 2023-12-07 13:15:25 +03:00
Aren 9f67ee3a58 Исправил синтаксис YML 2023-11-30 17:04:07 +03:00
Aren 11f07cb832 Замена пробелов на таб 2023-11-30 17:00:24 +03:00
Aren Elchinyan 4244853b13 Совмещены директории pci и pci_data 2023-11-29 22:18:37 +03:00
Aren Elchinyan a0de7f8034 Исправление выделения ОЗУ под менеджер динамичной памяти
Теперь он потребляет все 16 мегабайт вместо 4
2023-11-29 00:33:36 +03:00
Aren Elchinyan cd571ddfb4 Изменение отладочного вывода 2023-11-29 00:11:15 +03:00
Aren Elchinyan 27fe3e827a Обновлен номер версии 2023-11-28 23:55:52 +03:00
Aren Elchinyan cccde49d4d Исправлен баг с неопределенным поставщиком, добавлен список классов 2023-11-28 23:55:40 +03:00
Aren Elchinyan 151a4a1589 Добавлено исключение git для отладочных логов и блокировок файлов 2023-11-28 23:54:59 +03:00
Aren Elchinyan 8f5fb3eba3 Добавлены новые поставщики в PCI 2023-11-28 23:54:32 +03:00
Aren Elchinyan 96b3696cf6 Запуск через SATA 2023-11-26 18:24:13 +03:00
Aren Elchinyan 86ff34a34a Поиск соответствий в базе PCI 2023-11-26 18:23:58 +03:00
Aren Elchinyan beb3ab0eb6 Парсер для адаптера данных 2023-11-26 13:12:57 +03:00
Aren Elchinyan 4338b6f75c Новая ветка для тестов 2023-11-25 21:22:34 +03:00
Aren ded87d7513 Добавлены данные поставщиков 2023-11-23 18:57:33 +03:00
Aren 469acb6782 Теперь модули автоматически собираются без указания пути 2023-11-22 19:16:03 +03:00
Aren Elchinyan 01f7054d55 Убран лишний этап сборки 2023-11-19 09:55:41 +03:00
Aren Elchinyan 6b07435415 Исправление проверок на наличие папки в CI 2023-11-19 09:53:45 +03:00
Aren Elchinyan fb398b9b84 Теперь CI добавляет все файлы в релиз 2023-11-19 09:50:15 +03:00
Aren e964524c03 Добавлен поиск модулей по тегам 2023-11-18 19:38:04 +03:00
Aren Elchinyan 24b3297754 Добавлено сохранение всех файлов в релизе 2023-11-18 15:29:14 +03:00
Aren Elchinyan 3abb4168be Исправление синтаксиса YML 2023-11-18 15:27:39 +03:00
Aren Elchinyan 28c1a6ef55 Добавлен режим "без отладочной информации" 2023-11-18 15:26:04 +03:00
Aren Elchinyan 90c3fd689c Обновлены инструкции по сборке 2023-11-18 15:25:22 +03:00
Aren Elchinyan 8b0742c4f9 Убрано лишнее поле 2023-11-18 14:55:11 +03:00
Aren Elchinyan 1d2095a2b7 Модули теперь грузятся по фиксированному адресу 2023-11-18 14:50:37 +03:00
Aren Elchinyan 1106d531df Добавлены инструкции по установке SDK 2023-11-18 14:50:08 +03:00
Aren Elchinyan 18c2d9f67e Добавлены вспомогательные информационные утилиты GIT 2023-11-18 14:47:30 +03:00
Aren Elchinyan 4500aa6869 Создан скрипт для установки SDK 2023-11-18 14:47:14 +03:00
Aren 25aa542963 Добавил в автосборку сохранение iso файлов 2023-11-17 22:11:25 +03:00
Aren ca48172026 Создан отдельный скрипт для выпуска сборок CI 2023-11-17 22:01:33 +03:00
Aren 2db3de3d1b Обновление вызовов системных функций в модуле SIMD 2023-11-17 21:14:40 +03:00
Aren 25b77bb8bb Создание библиотеки модулей 2023-11-17 21:09:26 +03:00
Aren 8a32d4070e Исправление загрузки модулей 2023-11-17 21:08:08 +03:00
Aren 8369696931 Исправление синтаксиса yml 2023-11-17 15:47:42 +03:00
Aren 28effc26e8 Обновлен процесс автосборки 2023-11-17 15:42:11 +03:00
112 changed files with 4462 additions and 1541 deletions

View File

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

View File

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

View File

@ -3,8 +3,6 @@ name: CI BUILD
on: on:
push: push:
branches-ignore: [ "pages" ] branches-ignore: [ "pages" ]
pull_request:
branches-ignore: [ "pages" ]
jobs: jobs:
build: build:
@ -13,19 +11,23 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: install depends - name: install depends
run: sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix run: |
sudo apt update
sudo apt upgrade
sudo apt install clang-format python3 git gdisk gcc g++ xorriso make mtools curl dos2unix
- name: install limine - name: install limine
run: | run: |
git clone https://git.synapseos.ru/Aren/limine.git --branch=v5.x-branch-binary --depth=1 git clone https://git.synapseos.ru/mirrors/limine.git --branch=v5.x-branch-binary --depth=1
cd limine && make && cd .. cd limine && make && cd ..
- name: build - name: build
run: | run: |
dos2unix *.sh dos2unix *.sh
chmod +x build.sh chmod +x *.sh
./build_mods.sh
./build.sh ./build.sh
- name: check root dir - name: check root dir
@ -35,4 +37,4 @@ jobs:
run: ls -la iso_root run: ls -la iso_root
- name: check bin - name: check bin
run: ls -la bin run: ls -la bin

80
.github/workflows/codeql.yml vendored Normal file
View File

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

70
.github/workflows/release.yml vendored Normal file
View File

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

6
.gitignore vendored
View File

@ -5,8 +5,12 @@ limine/
ovmf/ ovmf/
iso_root/ iso_root/
output/ output/
sdk/ sdk*/
*.so *.so
*.o *.o
*.ko *.ko
*.elf *.elf
*.zip
*.log
*.lck
configs/media/*

42
.vscode/settings.json vendored
View File

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

View File

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

13
CONTRIBUTING.md Normal file
View File

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

View File

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

View File

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

16
SECURITY.md Normal file
View File

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

29
TODO.md
View File

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

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.

View File

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

24
build_mods.sh Normal file
View File

@ -0,0 +1,24 @@
#!/bin/sh
dos2unix *.sh
cd modlib/lib/
dos2unix build.sh
chmod +x build.sh
./build.sh
cd ../..
cd modules/
mkdir -p bin
dos2unix */*.sh
chmod +x */build.sh
for dir in */; do
if [ $dir != "bin/" ]; then
cd $dir
./build.sh
cd ..
fi
done
cd ..

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,16 +10,78 @@
#ifndef ARCH_H #ifndef ARCH_H
#define ARCH_H #define ARCH_H
#include <lock.h>
#include <stdint.h> #include <stdint.h>
#include <sys.h>
#define STACK_SIZE 32 * 1024 // 16 килобайт на стек
typedef struct task {
uint64_t rax, rbx, rcx, rdx;
uint64_t rsi, rdi, rsp, rbp;
uint64_t cr3;
uint64_t cpu_time;
uint64_t cpu_time_expired;
uint64_t id;
char *id_str;
void *stack;
void *entry;
uint64_t status; // 0 - на удаление 1 - работает
struct task *last;
struct task *next;
} __attribute__((packed)) task_t;
struct frame {
uint64_t rbp;
uint64_t rbx;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t int_number;
uint64_t err;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed));
typedef void (*int_entry_t)(struct frame *state);
extern lock_t task_lock;
extern uint64_t task_f_init;
extern task_t *current_task;
void arch_init( ); void arch_init( );
void task_init( );
void task_after_init( );
void task_switch( );
uint64_t task_new_thread(void (*func)(void *), char *name, void *arg);
void task_del_current( );
void task_del(uint64_t id);
void cpu_init( ); void cpu_init( );
void gdt_init( ); void pic_init( );
void pit_init( );
void idt_init( ); void idt_init( );
void idt_set_int(uint8_t vector, void *int_handler); void idt_set_int(uint8_t vector, int_entry_t handler);
uint64_t arch_get_tick_b( ); uint64_t arch_get_tick_b( );
uint64_t arch_get_tick_l( ); uint64_t arch_get_tick_l( );
uint64_t arch_get_tick( ); uint64_t arch_get_tick( );
void com_write_byte(char byte);
void com_write_bytes(char *c, uint64_t n);
time_t rtc_get_time( );
static inline void outb(uint16_t port, uint8_t val) { static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
@ -31,4 +93,61 @@ static inline uint8_t inb(uint16_t port) {
return ret; return ret;
} }
static inline void outw(uint16_t port, uint16_t val) {
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint16_t inw(uint16_t port) {
uint16_t ret;
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void io_wait( ) {
outb(0x80, 0);
}
static inline void *hal_memset(void *s, char c, int64_t count) {
int64_t d0, d1;
asm volatile("rep\n\t"
"stosb"
: "=&c"(d0), "=&D"(d1)
: "a"(c), "1"(s), "0"(count)
: "memory");
return s;
}
static inline void *hal_memset_32(void *s, uint32_t c, int64_t count) {
int64_t d0, d1;
asm volatile("rep\n\t"
"stosl"
: "=&c"(d0), "=&D"(d1)
: "a"(c), "1"(s), "0"(count)
: "memory");
return s;
}
static inline void *hal_memcpy(void *dest, const void *src, int64_t count) {
int64_t d0, d1;
asm volatile("rep\n\t"
"movsb"
: "=&c"(d0), "=&D"(d1)
: "S"(src), "0"(count), "1"(dest)
: "memory");
return dest;
}
static inline void *hal_memcpy32(void *dest, const void *src, int64_t count) {
int64_t d0, d1;
asm volatile("rep\n\t"
"movsl"
: "=&c"(d0), "=&D"(d1)
: "S"(src), "0"(count), "1"(dest)
: "memory");
return dest;
}
#define GET_TICK_BIG arch_get_tick_b( )
#define GET_TICK_lOW arch_get_tick_l( )
#endif // arch.h #endif // arch.h

View File

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

26
include/io_buf.h Normal file
View File

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

View File

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

33
include/log.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

116
kernel/cpu/arch.c Normal file
View File

@ -0,0 +1,116 @@
/**
* arch.c
* Инициализация архитектуры
*
* Настройка архитектурнозависимых функций
*
*/
#include <arch.h>
#include <log.h>
typedef struct __attribute__((packed)) {
uint16_t limit;
uint64_t base;
} gdt_reg_t;
struct gdt_desc {
uint16_t limit;
uint16_t base_low;
uint8_t base_mid;
uint8_t access;
uint8_t granularity;
uint8_t base_hi;
} __attribute__((packed));
static uint64_t kernel_start_ticks = 0;
static uint64_t kernel_ticks = 0;
static gdt_reg_t gdtr;
static struct gdt_desc gdt_descs[] = { { 0 },
{ .limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011011,
.granularity = 0b00000000,
.base_hi = 0x00 },
{ .limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010011,
.granularity = 0b00000000,
.base_hi = 0x00 },
{ .limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011011,
.granularity = 0b11001111,
.base_hi = 0x00 },
{ .limit = 0xffff,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010011,
.granularity = 0b11001111,
.base_hi = 0x00 },
{ .limit = 0x0000,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10011011,
.granularity = 0b00100000,
.base_hi = 0x00 },
{ .limit = 0x0000,
.base_low = 0x0000,
.base_mid = 0x00,
.access = 0b10010011,
.granularity = 0b00000000,
.base_hi = 0x00 } };
extern void load_gdt(uint64_t gdtr);
void paging_init( );
uint64_t rdtsc( ) {
unsigned int lo, hi;
asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((uint64_t)hi << 32) | lo;
}
uint64_t arch_get_tick( ) {
if (kernel_start_ticks == 0) {
kernel_start_ticks = rdtsc( );
return 0;
}
kernel_ticks = rdtsc( ) - kernel_start_ticks;
return kernel_ticks;
}
uint64_t arch_get_tick_b( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick / 1000000;
}
uint64_t arch_get_tick_l( ) {
uint64_t tick = arch_get_tick( ) + 1;
return tick % 1000000;
}
void arch_init( ) {
LOG("Установка сегментов\n");
gdtr.limit = (sizeof(gdt_descs) - 1);
gdtr.base = (uint64_t)&gdt_descs;
load_gdt((uint64_t)&gdtr);
LOG("Установка сегментов успешна!\n");
pic_init( );
idt_init( );
cpu_init( );
paging_init( );
}

23
kernel/cpu/com.c Normal file
View File

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

View File

@ -8,25 +8,23 @@
*/ */
#include <fb.h> #include <fb.h>
#include <log.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <tool.h> #include <tool.h>
static bool acpi_msrs_support = false; static bool acpi_msrs_support = false;
static char fxsave_region[512] __attribute__((aligned(16)));
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
uint32_t *edx) { asm volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
asm volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf));
} }
static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) { static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr)); asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
} }
static void __attribute__((unused)) static void __attribute__((unused)) msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr)); asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
} }
@ -64,6 +62,24 @@ static void do_amd( ) {
LOG("cpu_family = [%u]\n", cpu_family); LOG("cpu_family = [%u]\n", cpu_family);
} }
static void do_intel( ) {
uint32_t eax, ebx, ecx, edx;
uint32_t cpu_model;
uint32_t cpu_family;
uint32_t cpu_brand_id;
cpuid(0, &eax, &ebx, &ecx, &edx);
cpu_brand_id = ebx;
cpu_family = ((eax >> 8) & 0xFF) + ((eax >> 20) & 0xFF);
cpu_model = ((eax >> 4) & 0xF) | ((eax >> 12) & 0xF0);
LOG("Используется процессор Intel\n");
LOG("cpu_brand_id = [%u]\n", cpu_brand_id);
LOG("cpu_family = [%u]\n", cpu_family);
LOG("cpu_model = [%u]\n", cpu_model);
}
static void brandname( ) { static void brandname( ) {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
char brand_string[49]; char brand_string[49];
@ -71,8 +87,7 @@ static void brandname( ) {
uint32_t manufacturer[4]; uint32_t manufacturer[4];
char manufacturer_string[13]; char manufacturer_string[13];
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2], cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2], &manufacturer[1]);
&manufacturer[1]);
tool_memcpy(manufacturer_string, manufacturer, 12); tool_memcpy(manufacturer_string, manufacturer, 12);
brand_string[48] = 0; brand_string[48] = 0;
@ -90,29 +105,17 @@ static void brandname( ) {
} }
if (manufacturer[0] == 0x68747541) { do_amd( ); } if (manufacturer[0] == 0x68747541) { do_amd( ); }
} if (manufacturer[0] == 0x756E6547) { do_intel( ); }
void cpu_idle( ) {
if (acpi_msrs_support) {
LOG("Температура: %d (в QEMU/KVM всегда 0)\n",
get_cpu_temperature_intel( ));
}
} }
void cpu_init( ) { void cpu_init( ) {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
cpuid(1, &eax, &ebx, &ecx, &edx); cpuid(1, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) {
asm volatile("finit");
LOG("FPU(x87) поддерживается!\n");
}
if ((edx >> 22) & 1) { if ((edx >> 22) & 1) {
acpi_msrs_support = true; acpi_msrs_support = true;
LOG("Встроенный терморегулятор MSRS для ACPI\n"); LOG("Встроенный терморегулятор MSRS для ACPI\n");
LOG("Температура: %d (в QEMU/KVM всегда 0)\n", LOG("Температура: %d (в QEMU/KVM всегда 0)\n", get_cpu_temperature_intel( ));
get_cpu_temperature_intel( ));
} }
cpuid(0x80000000, &eax, &ebx, &ecx, &edx); cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
@ -128,9 +131,7 @@ void cpu_init( ) {
"поддерживается!\n"); "поддерживается!\n");
} }
if ((edx >> 10) & 1) { if ((edx >> 10) & 1) { LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n"); }
LOG("SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
}
if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); } if ((edx >> 11) & 1) { LOG("SYSCALL/SYSRET подерживаются!\n"); }
if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); } if ((edx >> 29) & 1) { LOG("AMD64 поддерживается!\n"); }
@ -138,12 +139,19 @@ void cpu_init( ) {
cpuid(0x80000007, &eax, &ebx, &ecx, &edx); cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); } if ((edx >> 0) & 1) { LOG("Датчик температуры поддерживается!\n"); }
if ((edx >> 4) & 1) { if ((edx >> 4) & 1) { LOG("Аппаратный терморегулятор (HTC) поддерживается!\n"); }
LOG("Аппаратный терморегулятор (HTC) поддерживается!\n"); if ((edx >> 5) & 1) { LOG("Программный терморегулятор (STC) поддерживается!\n"); }
}
if ((edx >> 5) & 1) {
LOG("Программный терморегулятор (STC) поддерживается!\n");
}
brandname( ); brandname( );
cpuid(1, &eax, &ebx, &ecx, &edx);
if ((edx >> 25) & 1) {
LOG("SSE2 поддерживается!\n");
fpu_initialize( );
uint32_t sse_version = (ecx >> 25) & 0x7;
LOG("SSE%u включен\n", sse_version);
}
if ((ecx >> 28) & 1) { LOG("AVX поддерживается!\n"); }
} }

128
kernel/cpu/idt.c Normal file
View File

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

61
kernel/cpu/idt.h Normal file
View File

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

View File

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

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

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

58
kernel/cpu/paging.c Normal file
View File

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

28
kernel/cpu/pic.c Normal file
View File

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

View File

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

82
kernel/cpu/rtc.c Normal file
View File

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

157
kernel/cpu/task.c Normal file
View File

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

47
kernel/cpu/task_switch.s Normal file
View File

@ -0,0 +1,47 @@
.global task_switch_asm
task_switch_asm:
pushfq
movq %rax, (%rdi)
movq %rbx, 8(%rdi)
movq %rcx, 16(%rdi)
movq %rdx, 24(%rdi)
movq %rsi, 32(%rdi)
movq %rdi, 40(%rdi)
movq %rsp, 48(%rdi)
movq %rbp, 56(%rdi)
movq %cr3, %rax
movq %rax, 64(%rdi)
movq 64(%rsi), %rax
movq %rax, %cr3
movq 56(%rsi), %rbp
movq 48(%rsi), %rsp
movq 40(%rsi), %rdi
movq 24(%rsi), %rdx
movq 16(%rsi), %rcx
movq 8(%rsi), %rbx
movq (%rsi), %rax
movq 32(%rsi), %rsi
popfq
sti
retq
.global fpu_initialize
fpu_initialize:
clts
mov %cr0, %rax
and $0xFFFD, %ax
or $0x10, %ax
mov %rax, %cr0
fninit
mov %cr0, %rax
and $0xfffb, %ax
or $0x0002, %ax
mov %rax, %cr0
mov %cr4, %rax
or $0x600, %rax
mov %rax, %cr4
pushq $0x1F80
ldmxcsr (%rsp)
addq $8, %rsp
ret

165
kernel/elf.c Normal file
View File

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

View File

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

47
kernel/io_buf.c Normal file
View File

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

View File

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

128
kernel/log.c Normal file
View File

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

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

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

View File

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

View File

@ -8,43 +8,62 @@
*/ */
#include <arch.h> #include <arch.h>
#include <fb.h>
#include <limine.h> #include <limine.h>
#include <log.h>
#include <mem.h> #include <mem.h>
#include <mod.h> #include <mod.h>
#include <tool.h> #include <tool.h>
#include <version.h> #include <version.h>
uint64_t full_init = 0;
// Точка входа // Точка входа
void _start( ) { void _start( ) {
asm volatile("cli"); asm volatile("cli");
fb_init( ); log_init( );
arch_init( );
mem_init( ); mem_init( );
fb_init( );
log_init_mem( );
arch_init( );
pit_init( );
task_init( );
task_f_init = 1;
mod_init( );
fb_set_text_color(0x00FF00);
LOG("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем " LOG("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
"версии %u.%u.%u ***\n", "версии %u.%u.%u %s***\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, KERNEL_GIT_TAG);
LOG("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__); LOG("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
fb_set_text_color(0x00D000);
mod_init( ); time_t time = rtc_get_time( );
// pit_init( ); LOG("Время: %u:%u.%u, %u.%u.%u\n", time.hours, time.minutes, time.second, time.day, time.month, time.year);
mod_list_show( ); full_init = 1;
task_after_init( );
mem_get_stat( );
fb_set_text_color(0x00FF00);
LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n"); LOG("Готово! Для выхода из симуляции удерживайте: ESCAPE\n");
fb_set_text_color(0x00D000); asm volatile("sti");
for (;;) {
task_t *task = current_task;
do {
task = task->next;
if (task->status == 0) {
// LOG("УДАЛЕНИЕ %u(%s)\n", task->id, task->id_str);
task_t *prev = task->last;
task_t *next = task->next;
while (1) { prev->next = next;
uint64_t byte = inb(0x60); next->last = prev;
if (byte == 0x1) {
LOG("Exit!\n"); mem_free(task->stack);
return; mem_free(task);
} }
} while (task->id != 0);
task_switch( );
} }
} }

View File

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

View File

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

View File

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

65
kernel/utf8cp.c Normal file
View File

@ -0,0 +1,65 @@
#include <mem.h>
#include <tool.h>
#define NONS (0x98)
#define SKIP_OR_NOT (dest != NONS)
#define M(W40, W45, W201) ((((W40)-0x80) << 10) | (((W45) - (W40)) << 5) | ((W201)-0x80))
unsigned int utf8_2_win1251(const char *utf8, char *win) {
unsigned int dest, p, l1, l2, l3, inc, i, j, b1, b2, b3;
const unsigned short AR[16] = {
M(NONS, NONS, 0x86), M(0xA8, 0xB8, 0x87), M(0x80, 0x90, 0x95), M(0x81, 0x83, 0x96),
M(0xAA, 0xBA, 0x97), M(0xBD, 0xBE, NONS), M(0xB2, 0xB3, NONS), M(0xAF, 0xBF, NONS),
M(0xA3, 0xBC, 0x91), M(0x8A, 0x9A, 0x92), M(0x8C, 0x9C, 0x82), M(0x8E, 0x9E, NONS),
M(0x8D, 0x9D, 0x93), M(NONS, NONS, 0x94), M(0xA1, 0xA2, 0x84), M(0x8F, 0x9F, NONS)
};
for (i = 0, j = 0; utf8[i] != 0; i += inc) {
b1 = utf8[i];
b2 = utf8[i + 1];
b3 = utf8[i + 2];
// Utf8 переводим в Unicode.
inc = (0xE5000000u >> (((b1) >> 4) << 1)) & 0x3;
p = ((((b1) << 12) + (((b2)&0x3F) << 6) + ((b3)&0x3F)) & (0x7FFFF >> inc)) >>
(((0xC5FFAAAAu >> (((b1) >> 4) << 1)) & 0x3) * 6);
// Добавляем все остающиеся на месте.
dest = (((inc != 0) & (((p >> 5) != 0x5) | (0xF71C852E >> b2))) - 1) & p;
inc++;
// Добавляем русские буквы кроме ё и Ё.
dest += ((((p - 0x10) >> 6) != 0x10) - 1) & (p - 0x350);
// Добавляем символы из диапазонов: 0x401-0x40F, 0x451-0x45F, 0x2013-0x2022.
l1 = ((p >> 4) != 0x40) - 1;
l2 = ((p >> 4) != 0x45) - 1;
l3 = (((p - 3) >> 4) != 0x201) - 1;
dest += ((((l2 & (AR[p & 0xF] >> 5)) | (l3 & AR[p & 0xF])) & 0x1F) + ((l1 | l2) & (AR[p & 0xF] >> 10))) +
((l1 | l2 | l3) & 0x80);
// Добавляем оставшиеся.
dest += (((p != 0x490) - 1) & 0xA5) | (((p != 0x491) - 1) & 0xB4) | (((p != 0x2026) - 1) & 0x85) |
(((p != 0x2030) - 1) & 0x89) | (((p != 0x2039) - 1) & 0x8B) | (((p != 0x203A) - 1) & 0x9B) |
(((p != 0x20AC) - 1) & 0x88) | (((p != 0x2116) - 1) & 0xB9) | (((p != 0x2122) - 1) & 0x99);
// Отличаем настоящий 0 от просто отсутствующих в win 1251 символов.
dest += (((b1 == 0) | (dest != 0)) - 1) & NONS;
win[j] = dest;
j += SKIP_OR_NOT;
}
win[j] = 0;
return j;
}
#undef M
#undef NONS
#undef SKIP_OR_NOT
char *utf8cp(char *str) {
size_t len = tool_strlen(str);
char *result = (char *)mem_alloc(len + 1);
if (result) { utf8_2_win1251(str, result); }
return result;
}

1
modlib/lib/.gitignore vendored Normal file
View File

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

11
modlib/lib/build.sh Executable file
View File

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

69
modlib/lib/system.c Normal file
View File

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

259
modlib/lib/tool.c Normal file
View File

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

30
modlib/modstd.h Normal file
View File

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

View File

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

130
modlib/types.h Normal file
View File

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

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

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

View File

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

2
modules/doom/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
PureDOOM.h
*.wad

20
modules/doom/build.sh Normal file
View File

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

27
modules/doom/main.c Normal file
View File

@ -0,0 +1,27 @@
#include "PureDOOM.h"
#include <system.h>
static const char name[] = "[APP]DOOM";
static const char message[] = "DOOM :)";
static int app_main( ) {
log_printf("[%s]\n", message);
return 2 + 2;
}
void __attribute__((section(".minit"))) init(env_t *env) {
init_env(env);
env->ret = &((module_info_t){ .name = (char *)&name,
.message = (char *)&message,
.type = 0,
.data_size = 0,
.data = (void *)&app_main,
.err_code = 0,
.module_id = 0,
.irq = 0,
.irq_handler = 0,
.get_func = 0,
.after_init = 0 });
mod_update_info(env);
delete_thread( );
}

View File

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

View File

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

17
modules/imfs/build.sh Executable file
View File

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

171
modules/imfs/main.c Normal file
View File

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

17
modules/ios/build.sh Executable file
View File

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

122
modules/ios/main.c Normal file
View File

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

37
modules/link.ld Normal file
View File

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

9
modules/modules.json Normal file
View File

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

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

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

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

View File

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

91
modules/pci/pci_data.c Normal file
View File

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

View File

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

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

19
modules/ps2/build.sh Executable file
View File

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

165
modules/ps2/keymap.h Normal file
View File

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

168
modules/ps2/main.c Normal file
View File

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

18
modules/ps2/special.h Normal file
View File

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

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"

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