startup nsh что это

BootDev

Создание загрузочных дисков и прочие полезные мелочи

Страницы

2018-12-06

UEFI Shell: Скрипт автозапуска startup.nsh

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Содержание

Файлы с расширением *.nsh

Файлы с расширением *.nsh, для оболочки UEFI Shell являются командными, и имеют статус исполняемых. То есть, создав файл с этим расширение, вписав в него команды оболочки UEFI Shell, и выполнив запуск полученного файла, произойдет поочередное выполнение содержащихся в нем команд. Такие файлы называют скриптами.

Особенность файла startup.nsh является в том, что при запуске UEFI Shell происходит его выполнение, если конечно пользователь не отменит данное действие нажатием клавиши ESC. Это по сути делает данный файл, файлом автозапуска (по аналогии с файлом autoexec.bat для операционной системы MS-DOS).

Как можно использовать данную особенность? Самое простое, что можно сделать, это выполнить автоматическое изменение размера и цветовой схемы командной оболочки. Более усложненный вариант, выполнение указанных *.efi приложений, в зависимости от выполненных условий.

Возможности скриптов

Как было сказано в предыдущем разделе, скрипты могут содержать в себе команды оболочки UEFI Shell. Абсолютно любые. Используя их вы можете составить свой сценарий выполнения необходимых вам команд. Рассмотрим самые типичные действия для скриптов:

1. Вывод информации.
2. Выполнение команд, или исполняемых файлов.
3. Условные переходы.
4. Чтение информации.
5. Циклические действия.

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

Список доступных команд, а так же особенности командной оболочки UEFI Shell, читаем по этой ссылке. Пример работы с командной оболочкой UEFI Shell.

Простой скрипт

Реализуем самые частые действия в простых скриптах, это вывод текстовой информации и выполнение запуска команд/приложений. Далее приведен текст тестового скрипта:

Сохраним данный текст в файл (обычный текстовый файл) под именем simple_script.nsh, в корень загрузочной флешки с UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Загрузимся в UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Перейдем в корень флешки и выведем список файлов.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Файл simple_script.nsh отмечен зеленым цветом, что говорит о возможности его запуска. Выполним запуск файла simple_script.nsh.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Скрипт, выполнил изменение цветовой схемы, размера экрана, и вывел текстовые сообщения о проделанной работе. К сожалению, текст на русском выводить невозможно. Хоть кодировка UCS-2 позволяет это сделать, но в самой оболочке не содержатся соответствующие шрифты.

Интерактивный скрипт

Интерактивным называется тот скрипт, который взаимодействует с пользователем. То есть, ожидает от пользователя выполнения какого либо действия. Это может быть нажатие клавиши, или ввод какого либо текста.

Пример интерактивного скрипта:

Создаем файл interactive_script.nsh с данным текстом в корне загрузочной флешки с UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Загружаемся в UEFI Shell, переходим в корень флешки, выводим список файлов.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Выполняем запуск интерактивного скрипта interactive_script.nsh.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Первое сообщение, с выбором. Приглашение.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Шаг первый. Вывод информации о версии UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Шаг второй. Вывод смонтированных дисков с поддерживаемыми файловыми системами.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Шаг третий. Вывод списка доступных PCI-устройств.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

На каждом их этих шагов, можно нажать клавишу q и вернуться обратно к командной строке.

Скрипт с условиями и циклами

Попробуем написать скрипт, который использует циклы и условия:

Сохраняем полученный код в файл complex_script.nsh и размещаем его в корне загрузочной флешки с UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Запускаем UEFI Shell, переходим в корень флешки, выводим список файлов.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Выполним запуск скрипта complex_script.nsh.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Startup.nsh

Получив в предыдущих главах, представление о скриптах *.nsh, командной оболочки UEFI, перейдем к файлу startup.nsh. Данный файл, это обычный скрипт, единственной особенностью которого является автоматический запуск его оболочкой UEFI.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Обращаем внимание на переменную path. Данной переменной присвоены пути, через знак точки с запятой «;«, по которым происходит поиск исполняемых файлов. Разместив скрипт startup.nsh в один из этих каталогов, он гарантированно запустится.

Пути, вне зависимости от диска, по которым происходит поиск \EFI\boot, \EFI\tools, \ (то есть корень диска). Причем поиск происходит именно в указанной последовательности.

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

Сохраняем полученный файл под именем startup.nsh, и копируем его в одну из указанных выше директорий.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Запускаем UEFI Shell.

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

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

Источник

Пишем для UEFI BIOS в Visual Studio. Часть 2 – создаем свой первый драйвер и ускоряем отладку

Введение

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

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

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Подготовка

Сразу же сделаем свой каталог для наших упражнений в корне edk2 и назовем его EducationPkg. Все проекты будем создавать внутри него. Можно создавать в корне edk2 и каждый отдельный проект, никаких препятствий для этого нет, но примерно на десятом проекте в корне разведется зоопарк из своих проектов и пакетов фреймворка edk2, что приведет, в лучшем случае, к путанице. Итак, создаем каталог C:\FW\edk2\EducationPkg.

Использование UEFI Driver Wizard

Созание набора файлов для проекта edk2 — большая тема, заслуживающая отдельной статьи. Можно про это почитать, если хочется узнать правду прямо сейчас, в документе EDK II Module Writer’s Guide, глава 3 Module Development – здесь или погуглите. Мы же пока будем использовать для создания набора файлов интеловскую утилиту UEFI Driver Wizard, которая лежит в скачанном каталоге в C:\FW\UEFIDriverWizard

Запускаем UEFI Driver Wizard, и первое, что надо сделать – указать рабочую среду Workspace C:\FW\edk2 по команде File → OPEN WORKSPACE. Если этого не сделать вначале, то UEFI Driver Wizard заботливо проведет нас по всем этапам создания, а потом, с извинениями, скажет, что проект драйвера создать не может.

После указания Workspace выбираем File → New UEFI Driver и производим следующие действия:

1. Жмем на кнопку Browse, заходим в каталог C:\FW\edk2\EducationPkg и создаем внутри него свой каталог MyFirstDriver, в котором и будем работать дальше. Имя драйвера примет то же название

2. Выставляем Driver Revision в 1.0. Меньше единицы выставлять не советую — в Wizard ошибка, в результате которой ревизия получается 0.0 после создания файлов проекта.

3. Все остальное оставляем без изменений, так чтобы получилось, как показано на скриншоте

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Жмем кнопку Next и переходим к следующему экрану:

Ставим галочки напротив Component Name Protocol и Component Name 2 Protocol, остальное не трогаем:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

и после сразу жмем Finish, не трогая другие настройки. Получаем сообщение об успешном создании проекта:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это
Жмем Ок и закрываем UEFI Driver Wizard, он нам больше не понадобится.

Добавление модуля в список для компиляции

Поскольку в мире ничего идеального нет, нам придется вручную добавить строчку для нашего драйвера в список модулей для компиляции. Тут надо остановиться и дать небольшую справку.

Все модули в edk2 входят в т.н. рackages – группы модулей, которые объединены между собой по какому-то общему признаку. Чтобы включить новый модуль в состав какого-либо package, нам необходимо добавить путь к исходникам модуля в файл PackageName.dsc (dsc – сокращение от Description), и этот модуль будет компилироваться в составе Package. UEFI Wizard Driver наш драйвер для компиляции добавить автоматически, увы, не может по объективным причинам (ну откуда ему знать, что за свой новый package вы создали (или с каким из существующих намерены работать?). Поэтому – прописываем ручками.

Просьба понимать, что наш EducationPkg — пока не package, а всего лишь набор проектов, и не более того.

Открываем файл C:\FW\edk2\Nt32Pkg\Nt32Pkg.dsc, ищем в нем строчку

# Add new modules here

и после этой строки прописываем путь к файлу MyFirstDriver.inf нашего драйвера относительно C:\FW\edk2. Должно получиться вот так:

Очень важное лирическое отступление

Теперь вы уныло думаете, что придется снова настраивать проект в Visual Studio, и совершенно напрасно. Вспомните, мы в первой статье нигде не указали, о каком именно проекте идет речь. Поэтому править ничего не надо, компиляция после добавления в Nt32Pkg нашего inf-файла пойдет и так. Это приводит нас к очень важному следствию: мы можем добавить в уже имеющийся проект Visual Studio, например, NT32, файлы любого проекта из огромного дерева edk2 и все они будут доступны на редактирование и – это главное – постановку контрольных точек, просмотра Watch и всех остальных возможностей, которые предлагает Visual Studio. Собственно, в этом и состоит одно из наиболее интересных преимуществ данного подхода к работе в UEFI с помощью Visual Studio. И при нажатии на F5 перед началом компиляции будет произведено автосохранение измененных исходников, добавленных в проект. Мы, правда, платим за этот подход увеличенным временем компиляции, но дальше разберемся и с этой проблемой.

Давайте проделаем то, о чем только что говорили, для нашего проекта. Щелкаем в Visual Studio правой клавишей на проекте NT32 (не забыв переключить его в проект по умолчанию в Solution), выбираем Add → Existing Item, переходим в наш каталог

выделяем мышкой все файлы и жмем на Add, добавляя их в наш проект NT32.

Компиляция и запуск драйвера

Жмем в Visual Studio на F5 или кнопку Debugging, ждем загрузки Shell, в ней вводим:

fs0:
load MyFirstDriver.efi

И затем смотрим на сообщение об успешной загрузке нашего драйвера. Он ничего не делает, что совсем не удивительно – никакую функциональность в него мы еще не добавляли. Нам надо лишь проверить, что мы правильно добавили наш драйвер в среду edk2, и не более того.
Вот то, что мы должны видеть (адрес может быть любой):

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это
Закрываем окно нажатим кнопки Stop Debugging, или Shift + F5 в Visual Studio.

Добавление своего кода

Открываем в Visual Studio файл MyFirstDriver.c из получившегося дерева проекта и добавляем в него наш код. Но вначале немного теории, перед тем, как перейдем к практике.

В UEFI BIOS все взаимодействие с «железом» — в нашем случае, его эмуляцией на виртуальной машине – происходит через протоколы, вот прямо так взять и записать определенный байт в определенный порт — нельзя. В очень упрощенном виде можно рассматривать протокол как имя “класса”, экземпляр которого создается для работы с устройством при его регистрации в системе. Как и обычный экземпляр класса, протокол содержит данные и функции, и вся работа с аппаратурой обеспечивается вызовом соответствующих приватных функций класса.

При работе в UEFI используются таблицы, в которых содержатся указатели на все экземпляры «классов». Этих таблиц несколько, в случае с нашим драйвером мы используем System Table, используя уже объявленный указатель gST. Иерархия этих таблиц довольно проста: есть основная таблица System Table, в которой содержатся (среди прочего) ссылки на таблицы Boot Services и Runtime Services. Впрочем, наверное, будет проще показать код:

По названиям переменных: gST расшифровывается как:
g — означает, что переменная глобальная
ST, как вы уже догадались, означает System Table

Итак, наша задача – послать на устройство вывода (в нашем случае – дисплей) строку I have written my first UEFI driver. Хорошо бы, конечно, при этом в unix-style использовать ту же printf и просто указать разные потоки, но увы – с использованием printf в UEFI есть очень серьезные ограничения, поэтому пока давайте оставим ее в сторонке, до лучших времен.

Вставим вывод нашей строки в функцию EntryPoint() нашего драйвера. Добавляем в области объявления переменных нашу переменную типа CHAR16 (используется двухбайтовая кодировка символов UCS-2) в функции MyFirstDriverDriverEntryPoint() в MyFirstDriver.c:

После, в самом конце функции MyFirstDriverDriverEntryPoint() вставьте код вывода нашей текстовой переменной на консоль вывода (экран по дефолту, в нашем случае):

Жмем на F5, вводим fs0:, load MyFirstDriver.efi, и получаем нашу строку на экране:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Первая программа с нуля написана и работает. Можем себя поздравить.

Разберем сейчас эту нашу строчку:

В ней:
gST – указатель на таблицу System Table
ConOutпротокол, или, как мы его условно обозвали, «класс» вывода текста
OutputString – сама функция вывода. Первый параметр в ней, как легко догадаться – this для нашего протокола EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.

Давайте переформулируем вышесказанное в другом виде, для лучшего понимания. Вот иерархия главной таблицы System Table, получена в окне Watch при останове на breakpoint в Visual Studio. Подсвечена используемая нами функция OutputString. Обратите также внимание на элементы BootServices и RuntimeServices в нижней части таблицы, о чем шла речь ранее:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Ввод текста с клавиатуры и вывод его на экран

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

Сделаем еще один скриншот той же gST, но уже в части ConIn. Выглядит он вот так:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это
В нашем следующем примере будем запоминать вводимый с клавиатуры пароль, отображая вводимые символы разноцветными звездочками в новогоднем (или наркоманском, как заметил один товарищ) стиле, а после нажатия Enter — выводить пароль в следующей строке. Это всего лишь учебный пример, замещение вводимого пароля звездочками уже реализовано в HII API, равно как и повторный ввод пароля, и проверка совпадения повторного ввода.

Вначале добавим локальные переменные в функции MyFirstDriverDriverEntryPoint() вместо нашей ранее добавленной переменной MyString.

Теперь вводим текст программы, заместив ранее добавленную нами функцию

Жмем F5 и устраиваемся в уже ставшей привычной позе на пару минут:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

После приглашения Shell, как всегда, вводим fs0: и load MyFirstDriver (или load my и затем два раза жмем на Tab, ибо Shell). Получаем такую вот картинку (разумеется, текст будет тот, что вы ввели сами):

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Жмем Shift+F5, чтобы закрыть отладку, после того, как налюбовались.

Дальше в статье будем знакомиться ближе со средой UEFI Shell, PCD и отладочными сообщениями — без этого двигаться дальше нельзя. Но знакомиться будем не абстрактно, а в полезном процессе ускорения и автоматизации запуска драйвера на отладку.

Создание и редактирование загрузочного скрипта UEFI Shell

Теперь, поскольку вы, вероятно, уже перекомпилировали программу не раз и не два, то морально дозрели до того, чтобы сократить это раздражающее время ожидания загрузки UEFI Shell и вбивания каждый раз одних и тех же команд для загрузки нашего драйвера. Начнем с того, что уберем весь ручной ввод текста в Shell написанием соответствующего скрипта. Писать скрипт будем прямо в Shell. С точки зрения здравого смысла, лучше открыть файл скрипта в Far Manager и отредактировать его там, но мало ли какими судьбами в будущем вас выбросит в Shell реальной машины, а не виртуалки с доступом к ее файловой системе с хоста. Поэтому один раз создадим скрипт в редакторе Shell и запишем его, чтобы получить соответствующий навык.

Файл скрипта, исполняемый при старте (подобный autoexec.bat или bashrc) для UEFI Shell, называется startup.nsh, тот самый, что Shell каждый раз предлагает нам пропустить при загрузке. Загрузитесь в UEFI Shell, нажав в Visual Studio клавишу F5, и введите fs0:, чтобы перейти в нашу файловую систему. Теперь из Shell введем команду

и в открывшемся редакторе введем, с переводом строки по Enter:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Дальше жмем F2, затем Enter для записи и затем F3 для выхода из редактора обратно в Shell.

Перекомпилять все заново на этот раз не будем, поскольку мы в программе ничего не меняли. Наберем в Shell команду Exit, и в открывшемся текстовом окне a-la BIOS Setup, а в терминах UEFIMain Form, выберем пункт Continue. После этого нас снова выбросит в Shell, но в этот раз исполнится созданный нами скрипт startup.nsh и автоматом запустится наш драйвер.

Отладочные сообщения

Пока мы можем писать отладочные сообщения на экран, но когда будем работать с формами HII (Human Interface Infrastructure) – такой возможности не представится, экран будет занят формами конфигурирования аппаратуры. Что делать в этом случае?

В самом начале после получения новой платы с завода не всегда, ох, не всегда бывает доступна дисплейная консоль вывода отладки. По вероятности возможных ошибок подключения дисплей идет сильно впереди последовательного порта, в котором напортачить можно разве что с направлением RX-TX. Поэтому существует также и вывод в последовательный порт, полностью аналогичный выводу на экран, с заменой ConOut на StdErr. Т.е. функция

будет выводить “Test string” на дисплей, а функция

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

Вывод отладочной информации в окно OVMF

Для вывода информации в окно OVMF есть макрос DEBUG”, который обычно используется следующим образом:

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

Первый аргумент может принимать следующие значения:

#define EFI_D_INIT 0x00000001 // Initialization style messages
#define EFI_D_WARN 0x00000002 // Warnings
#define EFI_D_LOAD 0x00000004 // Load events
#define EFI_D_FS 0x00000008 // EFI File system
#define EFI_D_POOL 0x00000010 // Alloc & Free’s
#define EFI_D_PAGE 0x00000020 // Alloc & Free’s
#define EFI_D_INFO 0x00000040 // Informational debug messages
#define EFI_D_VARIABLE 0x00000100 // Variable
#define EFI_D_BM 0x00000400 // Boot Manager (BDS)
#define EFI_D_BLKIO 0x00001000 // BlkIo Driver
#define EFI_D_NET 0x00004000 // SNI Driver
#define EFI_D_UNDI 0x00010000 // UNDI Driver
#define EFI_D_LOADFILE 0x00020000 // UNDI Driver
#define EFI_D_EVENT 0x00080000 // Event messages
#define EFI_D_VERBOSE 0x00400000 // Detailed debug messages that may significantly impact boot performance
#define EFI_D_ERROR 0x80000000 // Error

Регулируя уровень появления этих сообщений в логе, мы можем выдержать требуемый баланс между уровнем логгирования и производительностью системы в целом.

1. Его вывод имеет форматирование и работает как форматирование printf. Для отладки очень полезен формат %r, который выводит диагностическую переменную Status не в виде 32-битного числа в HEX, а в виде человекочитаемой строки типа Supported, Invalid Argument и т.п.

2. Этот макрос автоматически отключается при смене Debug на Release, поэтому не спешите его комментировать или обвешивать ifndef-ами – все уже сделано за нас.

3. Двойные скобки там действительно нужны. Попробуйте убрать и посмотреть, что получится.

Небольшой пример

Чтобы проиллюстрировать написанное, добавим в функцию MyFirstDriverDriverEntryPoint(), сразу после объявления переменных, вывод текста из нескольких сообщений в лог с разными уровнями отладки и посмотрим, какие из них выведутся, а какие будут отфильтрованы:

Запускаем на отладку и смотрим в окно OVMF:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Видно, что сообщения с уровнем EFI_D_INFO и EFI_D_ERROR попали в лог, а с уровнем EFI_D_WARN – не попало.

Механизм регулирования уровней отладки достаточно прост: как мы видим в списке выше, каждый уровень характеризуется одним битом в 32-битном слове. Чтобы отфильтровать ненужные нам в данный момент сообщения, мы ставим битовую маску на значение уровня, который отсекает биты, не попадающие в данную маску. В нашем случае маска была 0x80000040, поскольку уровень EFI_D_WARN со значением 0x00000002 отфильтровался и не попал в вывод, а уровень EFI_D_INFO со значением 0x00000040, и EFI_D_ERROR с его значением 0x80000000 попали в маску и соответствующие сообщения были выведены.

Сейчас не будем дальше углубляться в рассмотрение реализации механизма настройки уровня вывода отладки, рассмотрим только способы его изменения на практике. Их два, первый из них быстрый, а второй – правильный. Начнем, понятно, с быстрого. Открываем файл c:\FW\Nt32Pkg\Nt32Pkg.dsc и ищем в нем строку, содержащую PcdDebugPrintErrorLevel. Вот она:

Изменяем значение маски на 0x80000042 и запускаем на построение и отладку снова.

Поскольку мы изменили конфигурационный файл, edk2 будет снова долго пересобирать все-все-все бинарники для Nt32Pkg, но этот процесс конечен, и вот мы видим в логе закономерные все три строчки, что и требовалось доказать:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Как сделать быстро, разобрались. Теперь сделаем правильно.

Platform Configuration Database (PCD)

Проблема предыдущего подхода в том, что дерево edk2 и пакет Nt32Pkg у нас единственные, и менять системные настройки ради единственного проекта – прямой путь в преисподнюю, ибо в лучшем случае через неделю вы про это изменение забудете напрочь и будете проклинать исчадье ада под названием edk2, что месяц назад исправно создавало из оттестированных исходников под версионным контролем именно то, что надо, а сейчас выдает нечто совершенно другое. Поэтому в edk2 реализован механизм изменения системных настроек под единственный проект, чтобы локализовать изменения этих настроек только для данного проекта. Называется этот механизм PCDPlatform Configuration Database, и позволяет очень многое. Вообще, хорошим стилем в edk2 считается выносить из исходников в PCD любой параметр, который может быть изменен в будущем. Объем статьи не позволяет остановиться на описании PCD подробнее, поэтому лучше подробности про PCD посмотреть вот здесь в п.3.7.3 или вот здесь. На первое время вполне достаточно ограничиться прочтением файла C:\FW\edk2\MdeModulePkg\Universal\PCD\Dxe\Pcd.inf

С точки зрения практики, конфигурирование при помощи PCD производится вот так: в том же самом файле c:\FW\Nt32Pkg\Nt32Pkg.dsc изменяем уровень показа сообщений в окне OVMF:

Не спешите сразу записывать файл. Вначале поправьте обратно 0x80000042 к дефолтному значению 0x80000040 в строчке, которую мы редактировали ранее:

И вот теперь можно записать файл и пересобрать проект. Запускаем на отладку по F5 и видим наши заветные три строчки в отладочной консоли.

Ускоряем отладку дальше

Уберем еще пару раздражающих задержек при запуске на отладку. Очевидно, первый кандидат – это ожидание тех самых 5 сек перед запуском скрипта startup.nsh. Оно, конечно, можно и на пробел нажать, но любой уважающий себя лентяй программист должен автоматизировать ручные операции насколько возможно.

Теперь придется противоречить тому, что было сказано ранее. Проблема состоит в том, что в эти 5 секунд задержки прописываются не через PCD, а вопреки фэн-шуй, напрямую, в исходниках Shell. Поэтому и нам, хотим мы того или нет, придется поступить аналогично: откроем файл C:\FW\edk2\ShellPkg\Application\Shell\Shell.c и поменяем в инициализации значение «5» на «1»

Можно было бы и в 0 выставить, но мало ли… Забудем поменять на реальной аппаратной системе, а возможности перекомпилировать потом не будет.

Жмем F5 и радуемся 1 сек. задержки вместо 5.

Если кто-то знает, как выставить это значение задержки правильно, через PCD и без правки исходников Shell — дайте знать в личку или в комменты, я поправлю.

Еще ускоряемся

Вспоминаем про строку прогресса, а на самом деле – просто таймера ожидания выбора опции загрузки. Вот так это выглядит на основном экране:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

А в окне запуска OVMF это смотрится несколько иначе:

startup nsh что это. Смотреть фото startup nsh что это. Смотреть картинку startup nsh что это. Картинка про startup nsh что это. Фото startup nsh что это

Как говорил Винни-Пух, «Это ж-ж-ж – неспроста!» Надо найти источник и также уменьшить до 1 сек.

Запускаем поиск по всем файлам с расширением *.c строки Zzzzz, находим эту строку в исходнике C:\FW\MdeModulePkg\Universal\BdsDxe\BdsEntry.c и видим там вот такой блок кода:

Соответственно, понятно, что переменная TimeoutRemain читается из конфигурационной базы PCD, в параметре PcdPlatformBootTimeOut. Ок, открываем наш конфигурационный файл c:\FW\Nt32Pkg\Nt32Pkg.dsc, ищем там строку с PcdPlatformBootTimeOut:

Здесь уже вариант, как ранее, с конфигурацией PcdDebugPrintErrorLevel исключительно для нашего драйвера, не получится – в данном случае задержка будет выполняться задолго до того, как наш модуль MyFirstDriver будет загружен стартовым скриптом startup.nsh, поэтому придется менять глобально, хотим мы этого или нет. В данном случае — хотим, потому что эта задержка в процессе разработки драйверов обычно ни к чему. Меняем 10 на 1 в нашем конфигурационном файле, жмем F5 и радуемся быстрой загрузке. На моей машине это занимает теперь 23 секунды.

Еще тюнинг, на этот раз — интерфейса

Убираем второй дисплей, который нам незачем пока что, а раздражать уже начал. Правим строки в нашем любимом конфигурационном файле c:\FW\Nt32Pkg\Nt32Pkg.dsc, открыв его и убрав !My EDK II 2 и !UGA Window 2 в двух строчках, чтобы получилось:

Можно, разумеется, и саму надпись в заголовке окна UGA Window 1 поменять на что-то духовно более близкое вам лично, но это уже на ваше усмотрение.

На будущее

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

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *