Как написать свой bios

Пишем для UEFI BIOS в Visual Studio. Часть 1 — разворачивание среды разработки, компиляция и запуск на отладку

В этой статье будет описано, как быстро начать программировать для UEFI во фреймворке edk2 в среде Visual Studio, не тратя массу времени на настройку среды обычным способом, по оригинальным мануалам. Достаточно дать команду git clone . в корневом каталоге диска, и это на самом деле все, среда будет полностью установлена и готова к работе. Требуются 64-разрядная Windows 7 и выше c Visual Studio 2008-2015. Эти два условия не обязательны, но тогда придется немного потрудиться над собиранием системы edk2Visual Studio в единое целое, краткая памятка будет приведена.

Цель статьи — провести начинающего за руку по первому UEFI проекту, оставаясь в привычной ему среде. Для более опытных людей, надеюсь, будет интересным поработать в VS вместо привычной командной строки, или разобрать подход и перенести его в любимый Eclipse.

Начнем с простых вещей, вывода строки на консоль и русификации (довольно востребованная вещь, причем простая в реализации), потом будет работа с формами в HII (то, что называлось в обиходе страницами BIOS Setup), потом графика, потом Boot Manager, а потом видно будет (с).

Желающие — прошу пожаловать под кат.

Сейчас необходимо решить, оно вам надо или нет. Потратим на это пол-страницы на старте, чтобы не тратить пол-дня и в конце понять, что вам надо совсем другое. Или, надеюсь, наоборот — загореться энтузиазмом и выкроить время на прочтение статьи.

Вначале хорошее

1) Аппаратура не понадобится от слова совсем. Никаких Evaluation Boards, никаких Intel BlueBox JTAG за $3000. Все будет отлаживаться в 32-битной виртуальной машине OVMF – портированной Интелом виртуалке qemu для отладки UEFI Firmware. Для перекомпиляции под реальную платформу достаточно потом — после отладки — переставить пару ключей в настройках компиляции, и на этом все.

2) Работать будем со всеми возможностями Visual Studio, т.е. доступны breakpoints, watch, step execution и остальное. Перекомпиляция и запуск несложного модуля занимает 8-10 секунд.

3) Файловая система виртуалки доступна на Windows-машине для записи-чтения. Очень пригодится, если надо будет редактировать скрипты UEFI Shell, после запуска посмотреть скриншоты и проанализировать логи средствами Windows.

4) Никакого ассемблера, только С/С++.

Теперь о том, что мы делать не будем

1) Мы будем работать в DXE (где уже есть UEFI Shell) и поздних фазах. В более ранние фазы не полезем, поскольку нас туда никто не пустит, по крайней мере – для Intel-процессоров. Позже будет объяснение, почему. Если хотите сделать полный цикл, от включения до загрузки ОС, причем быстро и не забивая голову кучей ненужной и неинтересной вам в данный момент информацией, а ручное конфигурирование системы вам совершенно не требуется – дальше не читайте, а наберите в Гугле «coreboot».

2) «Графического» UEFI с мышкой и кнопками, как у Dell, MSI и прочих, здесь не будет. Это платные среды, для использования в крупных компаниях. Есть, разумеется, энтузиасты, которые сами создают их своими руками, не ответив предварительно на вопрос «Зачем?», но обычно их энтузиазм заканчивается на второй форме с кнопками.

3) Мы будем работать с компилятором Visual Studio. Желающие могут настроить gcc в cygwin, или icc, но в данный момент не стоит задача получить оптимальный быстрый код, а стоит задача быстро пройти путь к началу полноценной работы.

Все, предварительные танцы закончены, кто надо – воодушевлен, кто надо – напуган.

Переходим к делу

Первым делом, скачиваем репозиторий в корень диска. Развернется он в с:/FW. Если каталог FW в корне диска уже наличествует, то лучше бы его переименовать, потому что все конфиги настроены именно туда в абсолютных путях. Не по фэн-шуй, но перфекционисты всегда могут поправить абсолютные пути на относительные, написав соответствующий скрипт, который это делает.

Итак, у кого на машине есть git в командной строке, выполняют команду в cmd окне (или в Far Commander, не суть) из корневого каталога:

git clone https://github.com/ProgrammingInUEFI/FW

а те, у кого нет, идут по ссылке на github, скачивают zip-файл и раскрывают его в каталог с:/FW.

Как было ранее обещано, приведем подсказку из Интеловского тренинга по использованию другой конфигурации, отличной от указанной в начале статьи. Ищите свое сочетание в табличке, если предлагаемое по каким-то причинам не подходит:

Конфигурирование среды для версии, отличной от VS2010

Открываем файл c:FWedk2Conftarget.txt и в строчке
TOOL_CHAIN_TAG = VS2010x86

Заменяем VS2010x86 на тэг установленной у вас версии Visual Studio. Для Visual Studio 2010 тэг останется как есть, для других версий VS – смотрите картинку выше, или список в начале файла c:FWedk2Conftools_def.txt

Собственно, среда разработки edk2 развернута полностью и в ней можно работать из командной строки. Некоторые так и работают всю жизнь («угорать по хардкору, поддерживать дух старой школы и всё такое» — (с) CodeRush в своей ставшей классической статье). Но мы все же пойдем дальше, пересаживать человека из MSVS обратно в командную строку — негуманно, особенно в 2017.

Настраиваем проект в Visual Studio

Открываем Visual Studio, в нем открываем Solution NT32.sln из каталога C:FWVSNT32. В целях уменьшения времени входа в тему, в solution уже создан одноименный проект NT32, в котором уже сделаны описанные ниже настройки. Это если не получится создать самим – чтобы иметь гарантированно рабочие настройки проекта. Такой подход сильно сократит время поиска источника проблем, в случае их появления. Тем не менее, лучше пройти описанный ниже путь самим, и понять смысл настроек – это облегчит настройку следующих проектов.

Полезно будет сразу в Tools->Options настроить рабочий каталог на c:FWVS, но если в VS ведется другой, рабочий проект, то так делать не надо:

Создание проекта

Создаем в Solution NT32 новый проект для Visual C++ (правой клавишей на Solution NT32, Add->New Project, выбираем опцию Makefile Project), и назовем его MyFirstUEFIProject (или как угодно еще). Жмем Finish.

Выбираем в Solution проект NT32, выбираем из контекстного меню Project->Properties и производим настройки проекта.

Настройка NMake опций

Выбираем в окне слева строку Configurarion Properties → NMake, в окне справа — строку Build Command Line

Жмем Edit… и в открывшемся текстовом окне вводим:

Сейчас стоит немного объяснить, что мы делаем. По сути, мы пишем в этом окне обычный пакетный bat-файл вместо makefile.

В первой строке устанавливается переменная окружения ассемблера NASM_PREFIX в том виде, как ее понимает edk2, то есть путь, по которому лежит файл nasm.exe. На ассемблере мы сами писать не будем, но нашей системе сборки ассемблер нужен обязательно.

Во второй строке вызывается скрипт настройки среды edk2 и настраиваются переменные окружения для данного сеанса компиляции и запуска (вне VS эти переменные не отражаются). Ключ –nt32 указывает системе сборки, что компилировать исходники надо для пакета (package) Nt32Pkg, расположенного в C:FWedk2Nt32Pkg. Этих пакетов там много, мы их рассмотрим, но не сейчас.

В третьей строке мы даем команду на компиляцию в только что настроенной среде (build.exe лежит в C:FWedk2BaseToolsBinWin32, этот путь прописывается в предыдущей строчке, в edksetup.bat)

Итак, вот что у нас должно появиться в итоге в текстовом окне Build Command Line:

Затем вводим в следующей строке Rebuild Command Line в открывшееся по Edit … окно следующий текст

Команда build clean означает то самое, что вы предполагаете. Она делает полную перестройку проекта с перекомпиляцией всех модулей.

Что мы вводим в окне из Clean Command Line, наверное, все уже догадались:

Честно говоря, особо эта опция не нужна, в 99% случаев хватит Rebuild, но пускай будет – например, очистить среду для ее переноса в другое место или заливки на github.
В итоге, у нас должно получиться вот такое окно:

Все с настройкой NMake.

Настройка опции Debugging

Итак, открываем строчку Debugging и вводим:
В строчке Command:

В строчке “Working Directory”:

SecMain.exe – объяснять сейчас, что это такое – долго, если очень кратко и упрощенно – то это аналог bootloader-a, который запускает все остальное.

Рабочий каталог – сюда будут помещаться все успешно созданные модули, и доступны они будут все сразу из командной строки.

Итак, вот что мы должны получить после настроек в этом окне:

На этом все с настройками проекта.

Построение проекта

Вызываем Build Solution, смотрим на экран примерно минуту, в течение которой есть наибольший риск быть обруганным компилятором, и идем пить кофе – создаваться это все будет 10-15 мин, в зависимости от ресурсов вашего компьютера. Ничто нудное не вечно, и в конце концов мы получаем сообщение:

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Если же вместо этого получено что-то иное, смотрите, правильно ли вы прошли все шаги. Наиболее тяжелый случай – получить:

LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt

это баг среды VS2010 и означает, что VS2010 установлен без SP1. Поставьте SP1, или ищите способы затыкания этой ошибки в инете.

Если же получили ошибку и из сообщений компилятора не понятно, что это такое – переставьте дефолтный проект на NT32 и запустите его на компиляцию с отладкой. Если и там ошибка – проверьте еще раз соответствие TOOL_CHAIN_TAG предопределенным значениям, описанным в tools_def.txt. Больше ничего там упираться не может, разве что сам Visual Studio установлен, хм, не вполне стандартно, или использует сторонний компилятор.

Работа в UEFI Shell

Итак, все скомпилялось хорошо, и вы читаете эти строки. Теперь жмем на любимую F5 и после примерно минуты работы с диском (чуть позже сократим и это время) получаем вот такую требуемую картинку:

Собственно, это и есть UEFI Shell. Как в нем работать – написана куча руководств, посмотрите в Гугле, а мы пока сделаем в нем несколько вещей.

1. Смотрим, что мы там накомпиляли за эти 10 минут. Вводим fs0: (UEFI Shell нечувствителен к регистру) и затем ls –b, где опция –b означает ожидание нажатия Enter для прокрутки страницы, ибо список там большой, не на один экран.

Теперь стало понятно, что означал параметр “Working Directory” в настройке опций проекта Visual Studio — C:FWedk2BuildNT32IA32DEBUG_VS2010x86IA32. Там этот же самый список файлов, и лучше его смотреть (и редактировать скрипты) через развитую оболочку Far Commander (или Total Commander), чем с командной строки в UEFI Shell.

2. В UEFI Shell и набираем “hel”, жмем Tab и видим на экране Helloworld.efi. Не то, чтобы мы совсем не догадывались, что будет, если нажать после этого Enter, но проверить-то надо! Жмем и получаем троекратное UEFI Hello World!. Число повторений – это конфигурируемый в настройках среды (а не в исходниках) внешний параметр и мы будем эту конфигурацию потом разбирать.

3. Набираем exit и попадаем в наше любимое и знакомое окно:

Ну вот, можно любоваться на плоды своих трудов. После этого стрелками гоним фокус на Reset и виртуалка закрывается, возвращая нас в знакомое окно MSVC.

Выводим свою строку

Создание полностью своего приложения потребует достаточно много настроек, которые лучше будет рассмотреть в следующей статье — иначе получится большой объем, а длинные простыни никто не читает. Однако же в заголовке этой статьи написано «Программирование», а мы пока занимались только настройкой. Чтобы сдержать обещание, давайте в этой статье сделаем очень простую модификацию приложения HelloWorld, используя его имеющийся набор файлов, а в следующей статье создадим свой, при помощи Интеловской утилиты UEFI Driver Wizard, поскольку прогонять начинающих по полному циклу создания набора файлов для UEFI драйвера (или приложения) — это нечеловеколюбиво, дико рутинно и несет риск потери 90% аудитории. Если человека зацепит — он сам к этому придет со временем, а если хочется просто поиграться — нет смысла тратить на это кучу времени, благо многое давно уже делается автоматически через UEFI Driver Wizard, причем по фэн-шуй, чего от новичка ждать наивно.

Итак, открываем в Visual Studio файл
C:FWedk2MdeModulePkgApplicationHelloWorldHelloWorld.c

И добавим свою простую строчку, сразу после объявления переменных в единственной функции:

Разумеется, текст можно заменить на что угодно, только английскими буквами — русский шрифт edk2 еще не понимает, мы добавим его в следующих статьях. Можете поставить на эту строку обычный breakpoint и посмотреть, как себя поведет Visual Studio.

Жмем F5, после компиляции и устранения ошибок вводим «fs0:», HelloWorld.efi и получим такой вывод:

На этом все. В следующей статье мы немного поработаем в UEFI Shell, чтобы освоиться, и разберем немного теории.

Какой язык программирования используется для написания программы BIOS?

Как я понимаю, код / ​​битовый поток BIOS, который содержится в ПЗУ, должен быть общим (работать вместе с несколькими типами процессоров или ISA). Кроме того, я увидел упомянутое в сети, что можно сбросить его код (и «разобрать» его).

Итак, на каком языке, в наборе команд или в машинном коде написано? Разве ему не нужен какой-либо процессор для выполнения своих операций? Если да, то я предполагаю, что он будет использовать внешний процессор, тогда как он узнает конкретный набор команд используемого?

Может быть, у него есть внутренний процессор?

БИОСы были написаны исключительно на ассемблере, но переход был сделан давно, чтобы написать большую часть кода на каком-либо языке более высокого уровня, и оставить на ассемблере как можно меньше его частей, предпочтительно только загрузчик, (первые несколько сотен инструкций, к которым процессор переходит после запуска / сброса) и все подпрограммы, связанные с конкретными особенностями базовой архитектуры.

BIOS уже писались в основном на C еще в начале девяностых. (Я написал BIOS на 90% C, сборка 10% в начале девяностых.)

Что также очень помогло в этом направлении:

Библиотеки C, предназначенные для конкретной архитектуры и включающие функции для работы с особенностями этой архитектуры, например, функции для чтения / записи байтов в / из портов ввода-вывода архитектуры x86. Microsoft C всегда предлагал библиотечные функции для такого рода вещей.

Компиляторы C, которые не только нацелены на конкретную архитектуру ЦП, но даже предлагают расширения для языка С, которые можно использовать для написания кода, использующего специальные функции ЦП. Например, архитектура x86 поддерживает вещи, известные как прерывания, которые вызывают подпрограммы, известные как обработчики прерываний, и требует, чтобы они имели специальные последовательности команд входа / выхода. С самого начала Microsoft C поддерживал специальные ключевые слова, которые можно было использовать для обозначения функции как обработчика прерываний, чтобы она могла вызываться непосредственно прерыванием ЦП, поэтому вам не нужно было писать для нее какую-либо сборку.

В настоящее время я предполагаю, что большая часть BIOS написана на C ++, если не на каком-либо языке более высокого уровня.

Подавляющее большинство кода, составляющего BIOS, относится к конкретному аппаратному обеспечению, поэтому его не нужно переносить: гарантируется, что он всегда будет работать на одном и том же типе CPU. Процессор может развиваться, но пока он поддерживает обратную совместимость с предыдущими версиями, он все еще может работать с BIOS без изменений. Кроме того, вы всегда можете перекомпилировать части BIOS, написанные на C, для естественной работы на любом новом процессоре, который появится, если возникнет такая необходимость.

Причина, по которой мы пишем BIOS на языках более высокого уровня, чем на ассемблере, заключается в том, что писать их проще, а не потому, что они действительно должны быть переносимыми.

Хотя теоретически можно писать BIOS на любом языке, современная реальность заключается в том, что большинство BIOS пишется с использованием Assembly, C или их комбинации .

BIOS должен быть написан на языке, который может компилироваться в машинный код , понятный физическому аппаратному компьютеру. Это устраняет языки с прямой или промежуточной интерпретацией (Perl, Python, PHP, Ruby, Java, C #, JavaScript и т. Д.) Как подходящие для написания BIOS. (Хотя, теоретически, можно реализовать один из этих языков либо для прямой компиляции в статический машинный код, либо встроить интерпретатор в BIOS. Например, есть проект GCJ для Java, созданный на основе программного обеспечения).

Большинство OEM-производителей внедряют BIOS, расширяя проприетарные, универсальные реализации BIOS такими компаниями, как American Megatrends и Phoenix Techologies . (Вероятно, вы уже видели одну из этих компаний, отображенную на первом экране загрузки компьютера.) Исходный код для этих реализаций не является общедоступным, но некоторые из них утекли. Я не хочу ссылаться на это непосредственно на C и исходный код сборки, но в Интернете есть места, где обсуждается этот исходный код для тех, кто хочет заглянуть.

Некоторые производители оборудования, например производители, ориентированные на высокопроизводительные и игровые рынки, насыщают свои реализации BIOS функциями настройки, статистикой и привлекательными пользовательскими интерфейсами, разработанными для их точных реализаций. Многие из этих функций выходят за рамки того, что предлагается в универсальных продуктах, выпускаемых American Megatrends и другими. К сожалению, эти компании часто рассматривают выпуск своего исходного кода как угрозу безопасности , поэтому об этих реализациях высокого уровня известно мало, потому что о них мало что известно. Конечно, можно найти способы доступа и декомпиляции таких реализаций BIOS, но это может быть трудным и, возможно, незаконным.

Возвращаясь к первоначальному вопросу, из-за необходимости создавать собственный машинный код, BIOS должен быть реализован на языке программирования, поддерживаемом компилятором машинного кода . Хотя таких языков много, и хотя я уверен, что за последние несколько десятилетий в экспериментах использовалось несколько языков, каждая открытая реализация BIOS, которую я смог найти, специально основана на комбинации C и / или сборки. Реализации BIOS с открытым исходным кодом, на которые я смотрел, чтобы сформировать этот вывод, включают OpenBIOS , tinyBIOS , coreboot , Intel BIOS и Libreboot, Я также рассмотрел некоторые очень старые реализации BIOS, которые не актуальны сегодня, но также следовали правилу C и / или сборки.

Я думаю также уместно взглянуть на другое программное обеспечение, созданное для непосредственного взаимодействия с оборудованием. Мы знаем, например, что ядро Linux , то OS X ядро и ядро Windows , в основном C с некоторой сборкой и некоторыми высокоуровневыми языками для выполнения конкретных задач. Мы также знаем, что аппаратные драйверы для Linux и аппаратные драйверы для Windows написаны в основном на C.

Возвращаясь к BIOS, я думаю, что также важно учитывать экономику выбранного языка программирования. BIOS обычно пишется как необходимость дополнять продажи оборудования. Известно, что современные системы BIOS в основном написаны на C и / или на ассемблере. Переход к другому инструменту привел бы к значительным затратам к тому, что обычно считается товарной продукцией, что может очень негативно повлиять на продажи. Не вдаваясь в экономику 101, я могу заверить вас, что, возможно, ОЕМ-изготовителю не стоит отказываться от проверенных временем инструментов, проверенных десятилетиями.

Конечно, есть и будут проекты для любителей писать BIOS. Похоже, что они тоже до сих пор выбирают C и / или сборку. Возможно, однажды будут использованы другие технологии. Но сегодня выбор четко определен.

Написание собственного BIOS

Я не сумасшедший, просто изобретаю колесо: D
Я написал загрузчики, мини-драйверы для мыши и клавиатуры, мини-ОС и так далее.

Я всегда стараюсь избегать прерываний DOS, используя только BIOS, пытаясь продвигать unity mini OS, но внезапно я решил написать свой собственный BIOS:)

легенда сказал :
Я был программистом высокого уровня, потом низкого. Однажды я стану программистом машинного языка!

написан ли BIOS в сборке? Как могу я помахать им? Каков механизм? Могу ли я начать редактирование текущего BIOS?

4 ответов

BIOS может быть записан в сборке, но не обязательно, некоторые части должны быть, чтобы получить параметры для системного вызова, поскольку они не соответствуют Соглашению о вызове компиляторов.

Как прошить его? Варьируется от материнской платы к материнской плате, я бы начал с виртуальной машины с открытым исходным кодом и написал bios для этого. Или создайте виртуальную машину, на которой вы написали bios. Механизм варьируется от поставщика к поставщику, как правило, вы загружаете dos (dos не мертв, это очень жив в мире ПК, разработке материнских плат esp и встроенных систем). Я бы не возился с реальной материнской платой, если вы еще не знаете ответов на все эти вопросы, вы собираетесь заложить кирпичом ряд материнских плат, если вы пойдете по этому пути.

вы можете попробовать взять обновление bios для вашей материнской платы и реконструировать его (хотя, вероятно, есть соглашение, в котором говорится, что вы не будете). Если вы поймете это, вы можете загрузить его и взломать на. Я бы не пошел туда, вы заложите кирпичом свою систему, прежде чем поймете это.

действительно ли вы пишете bios? Довольно старая школа, было бы похоже на написание кода 6502 для удовольствия. Есть много проблем низкого уровня, которые являются более полезными и интересными.

Если вы можете написать asm код пишущей машины не так сложно, вы можете просто пойти сделать это для удовольствия. x86 ужасен, вы должны потратить некоторое время на изучение других систем и их asm и машинный код (и написание операционных систем для них). ARM доминирует в мире и не полагается на bios. Мне сказали, что для того, чтобы получить видеокарту в системе, отличной от x86, вам все равно нужно что-то возиться в x86 в x86 bios, можно выяснить, как поднять основную видеокарту без необходимости запускать x86 bios. посмотрите, как эмулятор запускает bios и посмотрите,что он делает, выясните, замените это питание на init без bios. Написание тренажера набора инструкций или дизассемблер-это следующий шаг после написания машинного кода, я бы не стал тратить ни секунды времени на x86, хотя, я могу предложить список альтернатив (или вы можете просто поиграть в симуляторы я написал или собираются).

Если bios x86-это то, что вы хотите, ваш лучший путь-написать, заменить или взломать bios для виртуальной машины qemu, virtualbox или другого. Замена этого bios на ваш, вероятно, заменит файл в каком-либо каталоге или с помощью команды опция line для указания альтернативного bios. После того, как вы хорошо опытны в этом, то если есть еще материнские платы с наследием bioses на них, возможно, вы можете взломать свой путь в программировании один (нужно купить несколько каждого типа материнской платы, как вы будете кирпич некоторые). С таким количеством встроенных систем, которые могут быть за $20 до $ 200 С таким же уровнем опыта, не имеет смысла взломать материнскую плату ПК без достойных схем и документации. Можно нарыть оригинальный ПК со схемой и списком bios документируется, а bios закрепляется, поэтому, если ваш не загружается (и не разрушает материнскую плату), это не кирпич, который вы можете перепрограммировать или заменить чип bios. Вероятно, хотите использовать микроконтроллер, чтобы стоять в качестве поддельного bios, так как найти правильное оборудование для перепрограммирования большего количества чипов bios, возможно, сложнее найти, что работает оригинальный ПК. Существует сообщество amiga, которое, вероятно, намного веселее и будет рад вас видеть улучшение / настройка их bios, скажем, размещение современного оборудования за устаревшими системными вызовами.

Fwiw Modbin-это программа DOS, которая, как следует из названия, изменяет изображения BIN, особенно с целью простых qnd довольно экстремальных изменений существующего кода BIOS.

Если вы можете получить старый mobo (многие выбрасываются все еще работают), я бы рекомендовал вам поиграть с BIOS. Это информативно и весело, если кто-то так склонен, и Вы, кажется,:) было время, когда я загружал изображения BIOS с mobos, которые имели те же или похожие чипсеты, хотя сделано другим изготовителем. иногда для значительного преимущества, включая такие простые, как продолжение получения обновлений BIOS после того, как оригинальный производитель mobo уронил мяч или пошел животом вверх, а также функции и параметры производительности и изменения.

Это привело к «горячему миганию», которое тянет вверх чип BIOS с носком, так что штыри едва вошли в контакт и один раз загрузились, потянув его и заменив плохой (часто тот, который я fuxored), в то время как все еще работает и мигает, используя кэшированную функцию BIOS, которая поддерживала активность системы. Забавные вещи для тех из нас, кто выродок убеждения и дал мне уверенность, чтобы написать драйверы устройств для OS / 2

есть способы прошить bios, кроме того, чтобы компьютер работал, возможно. Но это требует некоторого оборудования. Хотя это не должно быть слишком дорого.

Он объяснил это более подробно, хотя вы, возможно, не ищете инфекции, некоторые технологии для получения bios покрыты, где клип программирования является одним из них.

Если вы хотите написать BIOS для IBM PC совместимого компьютера (который является то, что большинство настольных ПК сегодня, хотя и с большим количеством расширений для набора инструкций CPU, и некоторые различные интерфейсы шины), то я предлагаю вам посмотреть через IBM PC, IBM PC XT и IBM PC AT технические справочники. В частности, IBM PC AT manual, как таков фактический стандарт.

в этих руководствах есть список программ полного BIOS, который IBM использовала на своих компьютерах, и они находятся на языке ассемблера. Возможно, вам придется немного порыться в этих руководствах (особенно в IBM PC at one), чтобы найти их, поскольку некоторые из них не перечислены непосредственно в оглавлении, но они есть. Надеюсь, те первые версии BIOS, может вам для начала.

Пишем свой bootloader

Это статья была написана для людей, которым всегда интересно знать как работают разные вещи. Для тех разработчиков которые обычно пишут свои программы на высоком уровне, C, C++ или Java — не важно, но при этом столкнулись с необходимостью сделать что-то на низком уровне. Мы будем рассматривать низкоуровневое программирование на примере работы bootloader-а.

Мы опишем что происходит после включения компьютера и как система загружается. В качестве практического примера, рассмотрим как вы можете написать свой собственный загрузчик, который фактически является отправной точкой при загрузки системы.

Что такое Boot Loader

Boot loader — это программа, которая записана на первом секторе жесткого диска. BIOS автоматически считывает всё содержимое первого сектора в память, сразу после включения питания. Первый сектор также называется главной загрузочной записью. На самом деле, это не является обязательным для первого сектора жесткого диска для загрузки чего либо. Это название было исторически сложившиеся, так как разработчики использовали такой механизм для загрузки операционной системы.

Будьте готовы погружаться глубже

В этом разделе я расскажу о том, какие знания и инструменты, необходимы для разработки собственного загрузчика, а также напомню некоторую полезную информацию о загрузке системы.

И так, какой язык Вы должны знать, чтобы написать Boot Loader

В первую очереди, при работе компьютера, контроль аппаратного обеспечения осуществляется преимущественно посредством функций BIOS, известный как «прерывания». Вызвать прерывание можно только на ассемблере — будет здорово если вы хоть немного знакомы с этим языком. Но это не обязательное условие. Почему? Мы будем использовать технологию «смешанного кода», где можно совместить высокоуровневые конструкции с командами низкого уровня. Это не много упрощает нашу задачу.

В этой статье в основном будет использоваться язык C++. Но если вы знаете C, то вам будет легко узнать необходимые C++ элементы. В общем, даже знание языка C будет достаточно, но тогда вам придется изменять исходный код примеров.

Если вы знаете Java или C#, то к сожалению это не поможет для нашей задачи. Дело в том, что код Java и C#, который производится после компиляции является промежуточным. Специальная виртуальная машина используется, для последующей обработки(Java машину для Java и .NET для C#), преобразовывая промежуточный код в инструкции для процессора. После преобразования он может быть выполнен. Такая архитектура делает невозможным использование технологию смешанного кода — но мы будем использовать ее, чтобы сделать нашу жизнь проще, так что Java и C# здесь не помогут.

И так, для разработки простого загрузчика вы должны знать, C или C++, а также было бы не плохо если вы знаете немного Ассемблера.

Какой компилятор вам нужен

Чтобы использовать технологию смешанного кода, нужно по крайней мере два компилятора: для ассемблера и для C/C++, а также компоновщик который объединит объектные файлы(.obj) в один исполняемый файл.

Теперь, давайте поговорим о некоторых особых моментов. Есть два режима функционирования процессора: реальный и защищенный режим. Реальный режим является 16-битным и имеет некоторые ограничения. Защищенный режим является 32-битным и полностью используется операционной системой. Когда компьютер только начинает работу, процессор работает в 16-битном режиме. Таким образом, чтобы написать программу и получить исполняемый файл, вам понадобится компилятор и компоновщик для ассемблера для 16-битного режима. Для C/C++ вам потребуется только компилятор, который умеет создавать объектные файлы для 16-битного режима.

Современные компиляторы сделаны для 32-разрядных приложений, поэтому мы не сможем их использовать.

Я пробовал несколько бесплатных и коммерческих компиляторов для 16-битного режима и выбрал продукт от Microsoft. Компилятор вместе с компоновщиком для ассемблера, C и C++ включены в Microsoft Visual Studio 1.52, его можно скадать с официального сайта компании. Некоторые подробности о компиляторов которые нам нужны приведены ниже.

ML 6,15 — компилятор ассемблера от Microsoft для 16-битного режима.
LINK 5,16 — компоновщик, который умеет создавать COM-файлы для 16-битного режима.
CL — С, С++ компилятор для 16-битного режима.

Вы также можете использовать несколько альтернативных вариантов.

DMC — бесплатный компилятор для компиляции ассемблера, C, C++ для 16 и 32-битном режиме Digital Mars.
LINK — бесплатный компоновщик для компилятора DMC.

Есть также некоторые продукты от Borland.

BCC 3,5 — С, С++ компилятор, который умеет создавать файлы для 16-битного режима.
TASM — компилятор асемблера для 16-битного режима.
TLINK — компоновщик, который может создавать файлы COM для 16-битного режима.

Все примеры кода в этой статьи, были разработаны с инструментами от Microsoft.

Как система загружается

Для того, чтобы решить нашу задачу мы должны вспомнить, как система загружает.
Рассмотрим кратко, как компоненты системы взаимодействуют при загрузке системы.

После того, как управление было передано по адресу 0000:7C00, Master Boot Record (MBR) начинает свою работу и запускает загрузку операционной системы.

Давайте перейдем к кодированию

В следующих разделах мы будем непосредственно заняты низкоуровневым программированием — мы будем писать наш собственный загрузчик.

Архитектура программы

Мы разрабатываем загрузчик для себя. Его задачами являются только следующие:

  1. Правильная загрузка в память по адресу 0000:7 C00.
  2. Вызов BootMain функции, которую мы написали в языке высокого уровня.
  3. Вывести на дисплей фразу — ”Hello, world…”, from low-level.

Первый объект это StartPoint, который написан исключительно в ассемблере, поскольку в языках высокого уровня нет необходимых нам инструкции. Это говорит компилятору, какой тип памяти должен использоваться, и адрес команды в RAM, которая должна выполняться после его чтения. Он также исправляет регистры процессора и передает управление функции BootMain, которая написано на языке высокого уровня.

Следующий объект- BootMain — является аналогом main, что, в свою очередь является основной функцией в которой сконцентрированы все функции программы.

Классы CDisplay и CString заботиться о функциональной части программы и выводит сообщение на экран. Как вы можете видеть на предыдущей картинки, класс CDisplay использует класс CString в своей работе.

Среда разработки

Здесь я использую стандартные среды разработки Microsoft Visual Studio 2005 или 2008. Вы можете использовать любые другие инструменты, но я уверен, что эти два, с некоторыми настройками, компилируют и работают легко и удобно.

Сначала мы должны создать проект Makefile Project, где будет выполнена основная работа.

File->NewProject->ОбщиеMakefile Project

BIOS прерывания и очистка экрана

Чтобы вывести сообщение на экране, мы должны очистить его для начала. Мы будем использовать специальные BIOS прерывания для этой цели.

BIOS предлагает ряд прерываний для работы с железом, таким как видеокарта, клавиатура, системный диск. Каждое прерывание имеет следующую структуру:

Где «number_of_interrupt» является числом прерывания.

Каждое прерывание имеет некоторое количество параметров, которые должны быть установлены до его вызова. Регистр процессора — ah, всегда несет ответственность за количество функций для текущего прерывания, и другие регистры обычно используются для других параметров текущей операции. Давайте посмотрим, как работа прерывания номер 10h выполняется на ассемблере. Мы будем использовать 00-функцию, она меняет видео режим и очищает экран:

Мы будем рассматривать только те прерывания и функции, которые будут использоваться в нашем приложении. Нам понадобится:

«Смешанный код»

Компилятор C++ поддерживает встроенный Ассемблер, то есть при написании кода на языке высокого уровня вы можете также использовать язык низкого уровня. Инструкции ассемблера, которые используются на высоком уровне, также называют asm вставками. Они состоят из ключевого слова “__asm” и блока ассемблерных инструкций:

Чтобы продемонстрировать пример смешанного кода мы будем использовать ранее упомянутый код на ассемблере, который выполняет очистку экрана и объединим его с кодом написанный на C++.

CString реализация

CString класс предназначен для работы со строками. Он включает в себя метод Strlen(), который получает в качестве параметра указатель на строку и возвращает количество символов в этой строке.

CDisplay класс предназначен для работы с экраном. Он включает в себя несколько методов:

  1. TextOut() — выводит строку на экране.
  2. ShowCursor() — управляет курсором представления на экране: показать, скрыть.
  3. ClearScreen() — изменяет видео режим и таким образом очищает экран.
CDisplay — реализация
Types.h — реализация

Types.h является заголовочным файлом, который включает определения типов данных и макросов.

BootMain.cpp — реализация

BootMain() является основной функцией программы, которая является первой точкой входа (аналог main()). Основная работа проводится здесь.

StartPoint.asm — реализация

Давайте соберем все

Создание COM файла

Теперь, когда код разработан мы должны преобразовать его в файл для 16-битных ОС. Такими файлами являются .COM-файлы. Мы можем запустить компилятор из командной строки, передавая необходимые параметры, в качестве результата мы получим несколько объектных файлов. Далее мы запускаем компоновщик для преобразования всех .COM файлов в один исполняемый файл с расширением. COM. Это работа способный вариант но не очень легок.

Давайте лучше автоматизируем этот процесс. Для этого нам нужно созать .bat файл и записать в нем нужные команды с необходимыми параметрами.

Поместите компиляторы и компоновщик в каталог проекта. В том же каталоге, мы создаем командный файл и заполняем в соответствии с примером (можно использовать любой каталог вместо VC152, главное чтобы компиляторы и компоновщик находились в нем).:

Ассамблирование — автоматизация

В качестве заключительного этапа в этом разделе мы опишем как превратить Microsoft Visual Studio 2005, 2008, в среду разработки с поддержкой любого компилятора. Для этого нужно перейти в свойствах проекта: Project->Properties->Configuration PropertiesGeneral->Configuration Type.

Вкладка Configuration Properties включает в себя три пункта: General, Debugging и NMake. Выберите NMake и укажите путь к «build.bat» в Build Command Line и Rebuild Command Lin.

Если все сделано правильно, то вы можете скомпилировать нажав клавиши F7 или Ctrl + F7. При этом вся сопутствующие информация будет отображаться в окне вывода. Основным преимуществом здесь является не только автоматизация сборки, но и мониторинг ошибок в коде если они будут.

Тестирование и демонстрация

Этот раздел расскажет, как увидеть сделанный загрузчик в действии, как выполнить тестирование и отладку.

Как проверить загрузчик

Вы можете проверить загрузчик на реальном оборудовании или с использованием разработанных для этих целей виртуальных машинам — VMware. Тестирование на реальном оборудовании дает вам больше уверенности, что он работает также как и на виртуальной машине. Конечно, мы можем сказать, что VmWare отличный способ для тестирования и отладки. Мы рассмотрим оба метода.

Прежде всего, нужен инструмент, чтобы записать наш загрузчик на виртуальный или физический диск. Насколько я знаю, есть несколько бесплатных и коммерческих консолей и GUI приложений. Я использовал Disk Explorer для NTFS 3.66 (версия для FAT, называется Disk Explorer для FAT) для работы в ОС Windows и Norton Disk Editor 2002 для работы в MS-DOS.

Я опишу только Disk Explorer для NTFS 3,66 потому что это самый простой способ и подходит для наших целей больше всего.

Тестирование с помощью виртуальной машины VmWare
Создание виртуальной машины

Нам понадобится VmWare версия программы 5.0, 6.0 или выше. Чтобы проверить загрузчик мы создадим новую виртуальную машину с минимальным размером диска, например, 1 Gb. Отформатируйте его в файловую систему NTFS. Теперь нам нужно отобразить отформатированный жесткий диск на VmWare в качестве виртуального диска. Для этого выберите:

File->Map or Disconnect Virtual Disks.

После этого появится окно. Там вы должны нажать кнопку «Map». В следующем появившемся окне вы должны указать путь к диску. Теперь Вы также можете выбрать букву диска.

Не забудьте снять флажок «Open file in read-only mode (recommended)». После того как выполнили все выше описанные индикации диск должен быть доступен в режиме только для чтения чтобы избежать повреждения данных.

После этого мы можем работать с диском виртуальной машины, как с обычными логическим диском в ОС Windows. Теперь мы должны использовать Disk Explorer для NTFS 3,66 чтобы записать загрузочную запись с позиции 0.

Работа с Disk Explorer для NTFS

После запуска программы мы идем в наш диск (File-> Drive). В появившемся окне идем в раздел логические диски и выбираем наш созданный диск(в моем случае это Z).

Теперь мы выбираем меню пункт View как Hex команды. В это появившемся окне мы можем видеть информацию диска в 16-разрядном представлении, разделенная на сектора. Сейчас у нас только 0-ли, так как диск пуст, пока что.

Сейчас мы должны записать наш загрузчик в первый сектор. Мы устанавливаем маркер в положение 00, как это показано на предыдущей картинке. Чтобы скопировать загрузчик мы используем пункт меню Edit->Paste from file command. В открывшемся окне укажите путь к файлу и кликните Open. После этого содержимое первого сектора должен измениться и выглядеть, как это показано на картинке — если вы, конечно, ничего не меняли в коде.

Вы также должны записать подпись 55AAh по позиции 1FE от начала сектора. Если вы не сделаете это, BIOS проверит последние два байта, и не найдя указанную подписи, будет считать что этот сектор не является загрузочным и не загрузит его в память.

Для переключения в режим редактирования нажмите клавишу F2 и напишите необходимые номера — 55AAh подписи. Чтобы выйти из режима редактирования нажмите ESC.

Теперь нам нужно подтвердить записанные данные.

Чтобы применить записанное мы идем в Tools-> Options, теперь мы идем в пункт Mode и выбираем метод записывания — Virtual Write и нажмите кнопку Write.

Большую часть рутинных действий закончили, наконец, и теперь вы можете видеть, что мы разработали с самого начала этой статьи. Давайте вернемся к VwWare чтобы отключить виртуальный диск (File->Map or Disconnect Virtual Disks … and click Disconnect).

Давайте запустим виртуальную машину. Мы видим теперь, как из глубины царства машинных кодов появляются знакомые строки — «Hello World… », from low-level. “.

Тестирование на реальном оборудовании

Тестирование на реальном оборудовании почти такая же, как и на виртуальной машине, за исключением того, что если что-то не работает, вам потребуется намного больше времени, чтобы восстановить ее, чем создать новую виртуальную машину. Чтобы проверить загрузчик не имея возможность потерять данные (все может случиться), я предлагаю использовать флэш-накопитель, но сначала вы должны перезагрузить компьютер, зайдите в BIOS и убедитесь, что он поддерживает загрузку с флэш-накопителя. Если он поддерживает его, то все в порядке. Если нет, то вы должны ограничить тестированием на виртуальной тестовой машине.

Процесс написание загрузчика на флэш-диск в Disk Explorer для NTFS 3,66 такой же как и для виртуальной машины. Вы просто должны выбрать сам жесткий диск вместо своего логического раздела.

Заключение

В этой статье мы рассмотрели, что такое загрузчик, как работает BIOS, и как компоненты системы взаимодействуют при загрузке системы. Практическая часть дала нам понимание о том, как можно разработать свой собственный, простой загрузчик. Мы продемонстрировали технологию смешанного кода и процесс автоматизации сборки с использованием Microsoft Visual Studio 2005, 2008.

Конечно, это лишь малая часть по сравнению с огромной темой низкоуровневого программирования, но если вам было интересна это статья — то это круто.

Источник статьи: http://habr.com/ru/post/173705/

November 24 2022, 20:10

Category:

  • IT
  • Cancel

Тот уникальный случай, когда я пишу пост в ЖЖ сильно позже, чем вышел пост на хабре. В телеге вышел вовремя. Прошу понять, простить и полюбить, в командировке, было просто не до того. Исправляюсь, пишу с сапсановского вайфая.

Хотели ли вы когда-нибудь написать свой BIOS? А BIOS вместе со встроенным BASIC? А вообще представляете как работает BIOS и как писать свои модули расширения? Уже давно у людей витает в воздухе идея сделать свой ROM BASIC и поиграться с ним, но вот прям рабочих и живых решений, по крайне мере в рунете я не встречал. В чатике давно муссируется тема, как это сделать. И сложнее всего было не проболтаться, что я знаю как это делать и уже есть готовое решение.
И вот, настал счастливый миг, когда могу явить это решение широкой публике. Подробности в моей статье:

Буду рад вашим комментариям, лайкам, дополнениям.

Я не сумасшедший, просто изобретаю колесо: D
Я написал загрузчики, мини-драйверы для мыши и клавиатуры, мини-ОС и так далее.

Я всегда стараюсь избегать прерываний DOS, используя только BIOS, пытаясь продвигать unity mini OS, но внезапно я решил написать свой собственный BIOS:)

легенда сказал :
Я был программистом высокого уровня, потом низкого. Однажды я стану программистом машинного языка!

написан ли BIOS в сборке? Как могу я помахать им? Каков механизм? Могу ли я начать редактирование текущего BIOS?

4 ответов


BIOS может быть записан в сборке, но не обязательно, некоторые части должны быть, чтобы получить параметры для системного вызова, поскольку они не соответствуют Соглашению о вызове компиляторов.

Как прошить его? Варьируется от материнской платы к материнской плате, я бы начал с виртуальной машины с открытым исходным кодом и написал bios для этого. Или создайте виртуальную машину, на которой вы написали bios. Механизм варьируется от поставщика к поставщику, как правило, вы загружаете dos (dos не мертв, это очень жив в мире ПК, разработке материнских плат esp и встроенных систем). Я бы не возился с реальной материнской платой, если вы еще не знаете ответов на все эти вопросы, вы собираетесь заложить кирпичом ряд материнских плат, если вы пойдете по этому пути.

вы можете попробовать взять обновление bios для вашей материнской платы и реконструировать его (хотя, вероятно, есть соглашение, в котором говорится, что вы не будете). Если вы поймете это, вы можете загрузить его и взломать на. Я бы не пошел туда, вы заложите кирпичом свою систему, прежде чем поймете это.

действительно ли вы пишете bios? Довольно старая школа, было бы похоже на написание кода 6502 для удовольствия. Есть много проблем низкого уровня, которые являются более полезными и интересными.

Если вы можете написать asm код пишущей машины не так сложно, вы можете просто пойти сделать это для удовольствия. x86 ужасен, вы должны потратить некоторое время на изучение других систем и их asm и машинный код (и написание операционных систем для них). ARM доминирует в мире и не полагается на bios. Мне сказали, что для того, чтобы получить видеокарту в системе, отличной от x86, вам все равно нужно что-то возиться в x86 в x86 bios, можно выяснить, как поднять основную видеокарту без необходимости запускать x86 bios. посмотрите, как эмулятор запускает bios и посмотрите,что он делает, выясните, замените это питание на init без bios…Написание тренажера набора инструкций или дизассемблер-это следующий шаг после написания машинного кода, я бы не стал тратить ни секунды времени на x86, хотя, я могу предложить список альтернатив (или вы можете просто поиграть в симуляторы я написал или собираются).

Если bios x86-это то, что вы хотите, ваш лучший путь-написать, заменить или взломать bios для виртуальной машины qemu, virtualbox или другого. Замена этого bios на ваш, вероятно, заменит файл в каком-либо каталоге или с помощью команды опция line для указания альтернативного bios. После того, как вы хорошо опытны в этом, то если есть еще материнские платы с наследием bioses на них, возможно, вы можете взломать свой путь в программировании один (нужно купить несколько каждого типа материнской платы, как вы будете кирпич некоторые). С таким количеством встроенных систем, которые могут быть за $20 до $ 200 С таким же уровнем опыта, не имеет смысла взломать материнскую плату ПК без достойных схем и документации. Можно нарыть оригинальный ПК со схемой и списком bios документируется, а bios закрепляется, поэтому, если ваш не загружается (и не разрушает материнскую плату), это не кирпич, который вы можете перепрограммировать или заменить чип bios. Вероятно, хотите использовать микроконтроллер, чтобы стоять в качестве поддельного bios, так как найти правильное оборудование для перепрограммирования большего количества чипов bios, возможно, сложнее найти, что работает оригинальный ПК…Существует сообщество amiga, которое, вероятно, намного веселее и будет рад вас видеть улучшение / настройка их bios, скажем, размещение современного оборудования за устаревшими системными вызовами.


Fwiw Modbin-это программа DOS, которая, как следует из названия, изменяет изображения BIN, особенно с целью простых qnd довольно экстремальных изменений существующего кода BIOS.

Если вы можете получить старый mobo (многие выбрасываются все еще работают), я бы рекомендовал вам поиграть с BIOS. Это информативно и весело, если кто-то так склонен, и Вы, кажется,:) было время, когда я загружал изображения BIOS с mobos, которые имели те же или похожие чипсеты, хотя сделано другим изготовителем…иногда для значительного преимущества, включая такие простые, как продолжение получения обновлений BIOS после того, как оригинальный производитель mobo уронил мяч или пошел животом вверх, а также функции и параметры производительности и изменения.

Это привело к «горячему миганию», которое тянет вверх чип BIOS с носком, так что штыри едва вошли в контакт и один раз загрузились, потянув его и заменив плохой (часто тот, который я fuxored), в то время как все еще работает и мигает, используя кэшированную функцию BIOS, которая поддерживала активность системы. Забавные вещи для тех из нас, кто выродок убеждения и дал мне уверенность, чтобы написать драйверы устройств для OS / 2



Если вы хотите написать BIOS для IBM PC совместимого компьютера (который является то, что большинство настольных ПК сегодня, хотя и с большим количеством расширений для набора инструкций CPU, и некоторые различные интерфейсы шины), то я предлагаю вам посмотреть через IBM PC, IBM PC XT и IBM PC AT технические справочники. В частности, IBM PC AT manual, как таков фактический стандарт.

в этих руководствах есть список программ полного BIOS, который IBM использовала на своих компьютерах, и они находятся на языке ассемблера. Возможно, вам придется немного порыться в этих руководствах (особенно в IBM PC at one), чтобы найти их, поскольку некоторые из них не перечислены непосредственно в оглавлении, но они есть. Надеюсь, те первые версии BIOS, может вам для начала.


A BIOS can be written in assembly but doesn’t have to be, some parts need to be to get the parameters for the system call since they don’t match the compilers calling convention.

How do you flash it? Varies from motherboard to motherboard, I would start with an open source virtual machine and write a bios for that. Or create a virtual machine where you have written the bios. The mechanism varies from vendor to vendor, generally you boot dos (dos is not dead, it is very much alive in the PC world, esp motherboard development and embedded systems). I wouldn’t mess around with a real motherboard, if you don’t already know the answers to all of these questions you are going to brick a number of motherboards if you take that path.

You can try to take a bios upgrade for your mother board and reverse engineer it (although there is probably a click through agreement that says that you wont). If you figure it out you can both load it and hack at at. I wouldn’t go there, you will brick your system before you figure it out.

Is writing a bios really what you are after? Fairly old school, would be like writing 6502 code for fun. There are many low level problems that are more useful and as interesting.

If you can write asm the writing machine code is not that difficult at all, you could just go do that for fun. x86 is dreadful, you should spend some time learning other systems and their asm and machine code (and writing operating systems for them). ARM dominates the world and doesn’t rely on a bios. I have been told that to get a video card up on a non-x86 system you still have to fiddle something in x86 on the x86 bios, could figure out how to bring up a mainstream video card without the need to run the x86 bios. watch an emulator run the bios and see what it does, figure it out replace that power on init without the bios doing it…Writing an instruction set simulator or disassembler is the next step beyond writing machine code, I wouldn’t waste even a second of time on x86 though, I can suggest a list of alternatives (or you could just play with the simulators I have written or collected).

If an x86 bios is the way you want to go, your best path is to write, replace, or hack on a bios for a virtual machine being qemu, virtualbox, or other. Replacing that bios with yours would likely be replacing a file in some directory or using a command line option to specify an alternate bios. Once you are well experienced in that then if there are still motherboards with legacy bioses on them perhaps you can hack your way into programming one (need to buy several of each type of motherboard as you WILL brick some). With so many embedded systems out there that can be had for $20 to $200 with the same level of experience gained, it doesn’t make sense to hack on a pc motherboard without decent schematics and documentation. You could dig up an original PC with the schematic and bios listing being documented, and the bios being socketed so if yours doesn’t boot (and doesn’t destroy the motherboard) it isn’t a brick you can reprogram or replace the bios chip. Probably want to use a microcontroller to stand in as a fake bios, as finding the right hardware to reprogram more bios chips is perhaps harder to find that working original PC’s…There is an amiga community that is likely a lot more fun and would be happy to have you improving/tweaking their bios, say putting modern hardware behind the legacy system calls.

Понравилась статья? Поделить с друзьями:
  • Как написать своими словами резюме
  • Как написать своими словами отказ от прививки
  • Как написать своими словами мужчине чтобы тронуть его до слез смс любимому
  • Как написать своими словами значение слова бряцание
  • Как написать своим почерком на компьютере