|
Bog BOS: hardware: EFI, UEFI и PI
|
Последнее изменение файла: 2024.09.24
Скопировано с www.bog.pp.ru: 2024.11.23
Bog BOS: hardware: EFI, UEFI и PI
Unified Extensible Firmware Interface (UEFI) - спецификация интерфейса между ОС и прошивкой вычислительной платформы,
пришедшая на смену интерфейсу BIOS (16-bit Real Mode (в реальности адаптированный 32-bit Protected Mode), 1MB на всех и 192 КиБ на ROM карт расширения).
Большинство реализаций UEFI поддерживают (поддерживали) интерфейсы BIOS для совместимости хотя бы для видео.
Первоначально называлась EFI (1999) и предназначалась для Intel/HP Itanium,
затем права EFI 1.10 были переданы Unified EFI Forum и в 2006 году появилась UEFI 2.0
(слово EFI осталась в именах файлов, библиотек и утилит).
Спецификация UEFI описывает состояние после завершения инициализации платформы и определяет интерфейс
между прошивкой и приложениями UEFI - внешними программами, используемыми, в частности, для загрузки ОС.
Кроме приложений UEFI определяются драйверы UEFI - вспомогательные программы, реализующие до загрузки ОС определённые в спецификации протоколы.
Центральной частью UEFI является менеджер загрузки, который (после инициализации платформы) загружает
в определённом порядке драйверы и приложения до тех пор, пока не окажется запущенной ОС.
Предоставляемые UEFI сервисы делятся на сервисы периода загрузки (недоступны после запуска ОС)
и очень небольшой набор сервисов периода выполнения (доступны всегда).
В комплекте с UEFI разработаны спецификации инициализации платформы PI (Platform Initialization Specification),
ранее называлась Intel Framework, формат пакетов UEFI/PI и UEFI Shell.
Имеется открытая реализация верхней части PI/UEFI - Tianocore
(EDK - EFI Development Kit, далее EDK2, UDK2010 и т.д.).
В настоящий момент поддерживает следующие платформы (только little-endian, 32 или 64-битные):
IA-32, IA-64, x64, AArch32, AArch64, RISC-V, LoongArch; существуют проекты для добавления POWERPC64, OpenPOWER и MIPS.
Разрядность UEFI прошивки должна соответствовать разрядности UEFI приложений (загрузчики и пр.).
На практике прошивка платформы x86-64 будет 64-битной (кроме старых Atom-ов), проверить можно в /sys/firmware/efi/fw_platform_size.
Дополнительно определяется архитектура виртуальной машины EBC (EFI Byte Code), которая может быть использована для написания драйверов и приложений.
Предполагается возможность написания драйверов и приложений на языках высокого уровня, интерфейсы описываются в стиле языка C.
Декларируется совместимость со "старой жизнью" - возможность загрузки ОС, совместимых с BIOS или UEFI,
на одной и той же платформе с одного и того же носителя, а также возможность для разработчиков карт расширения
поддерживать одновременно UEFI драйвера и BIOS-совместимые ROM.
Intel планировала отказаться от режима совместимости к 2020 году.
Класс UEFI:
- 0 - BIOS есть, интерфейсов UEFI и UEFI PI нет
- 1 - интерфейс UEFI имеется, но для ОС предоставляется только BIOS
- 2 - интерфейс UEFI имеется, для ОС предоставляется BIOS и UEFI
- 3 - интерфейс UEFI имеется, для ОС предоставляется только UEFI
- 3+ - интерфейс UEFI имеется, для ОС предоставляется только UEFI, включена безопасная загрузка
В качестве кодировки символов используется UCS-2 (конец строки - 0x0000).
Для нумерации объектов (протокол, драйвер, пространство имён переменных, раздел и т.д.) повсеместно используется
GUID (Globally Unique IDentifier, RFC 4122) длиной 128-бит, предполагается, что даже случайный выбор GUID в пространстве такой мощности
обеспечит уникальность без согласования между разработчиками в центральной конторе.
Структура EFI GUID определяется как сочетание 60-битной отметки времени (100-наносекундные отсчёты от 15 октября 1582 года по Грегорианскому календарю),
4 бита на версию, 16 бит на ClockSeq (?) и 48 бит на идентификатор узла (например, MAC адрес).
Текстовое представление из шестнадцатеричных цифр (ещё надо байты перемешать в словах): "tttttttt-tttt-tvtv-cscs-nnnnnnnnnnnn".
Принципиальное наличие поддержки UEFI в прошивке можно узнать в SMBIOS: BIOS Information:
BIOS Characteristics Extension Byte 2 ("dmidecode -t 0|fgrep 'UEFI is supported'").
Включена ли она сейчас можно узнать по наличию /sys/firmware/efi/fw_platform_size.
Текущая (2022 год) версия 2.10, но в самой свежей прошивке от Intel (2017 год) стоит UEFI версии 2.4, поэтому для ориентировки в возможностях реализации
важно знать, что было добавлено в очередной версии:
- 2.1, 2.1A, 2.1B, 2.1C (январь 2007 - июнь 2008) - HII (интерфейс пользователя), EFI переименован в UEFI, EFI Loaded Image Device Path Protocol
- 2.2, 2.2A (июль 2008 - февраль 2009)- IPv6 (UDPv6, DHCPv6, IPv6Configuration, MTFTP6, TCP6), PXE+, IPSec, EFI Driver Health Protocol, FTP, VLAN, EAP,
UEFI HII Animation, UEFI Setup Question, UEFI ATA Pass-Through Protocol, Firmware/OS Trusted Key Exchange, multipath
- 2.3, 2.3A, 2.3B, 2.3C, 2.3D, 2.3.1, 2.3.1A, 2.3.1B, 2.3.1C, 2.3.1D (февраль 2009 - апрель 2013)- поддержка ARM,
управление прошивками, UNDIBuffer usage, PXE IPv6, Secure Boot (Key Management Service Protocol), зашифрованные НЖМД, EFI_BLOCK_IO_PROTOCOL_REVISION3,
EFI_SCSI_PASS_THRU_PROTOCOL, Indications Variable, File IO Async extenstion, загрузка iSCSI DHCP6
- 2.4, 2.4A, 2.4B, 2.4C (апрель 2013 - январь 2015) - переменные KeyXXXX (горячие клавиши), Timestamp Protocol, Random Number Generator / Entropy Protocol,
формат Capsule для обновления прошивок, Disk IO 2 Protocol, Adapter Information Protocol (AIP), EFI_LOAD_OPTION, Universal Flash Storage (UFS) Device Path
- 2.5, 2.5A (февраль 2015 - октябрь 2015) - NVDIMM, смарт-карты (и edge), BMC Device Path, SD-карты, PXE загрузка по HTTP (и DNS и TLS) и из ISO-образов и с виртуальных дисков,
IPv6 в UNDI, поддержка VLAN, Bluetooth и Wi-Fi/EAP2, обновление частей прошивки, EFI_HASH2_PROTOCOL, System Prep Applications, Persistent Memory Type,
PKCS7 Signature Verification, NVM Express Pass Thru Protocol, USB Function I/O Protocol, REST Protocol, Platform recovery,
EFI_REGULAR_EXPRESSION_PROTOCOL, IP_CONFIG2 Protocol, RAM Disk UEFI Device Path, протокол настройки маршрутизации
- 2.6, 2.6A, 2.6B (ноябрь 2015 - апрель 2017) - SD/eMMC PassThru Protocol, ARMCPER, шрифты, EFI HII Image Decoder protocol, UEFI Ram disk protocol
- 2.7, 2.7A, 2.7B (апрель 2017 - март 2019) - улучшение регулярных выражений, RISC-V, DNS device path,
BluetoothLE, HII Popup, NVDIMM Label Protocol (таблица трансляции блоков и метки), UFS DEVICECONFIG Protocol, GPT Protective MBR
- 2.8, 2.8A, 2.8B, 2.8C (март 2019 - январь 2021) - UEFI JSON Capsule, EFI_JSON_CAPSULE_ID_GUID, EFI REST JSON Structure Protocol,
Redfish Discover Protocol, Peripheral-attached Memory, загружаемый NVDIMM Device Path, UEFI REST EX Protocol, Extend SERIAL_IO
- 2.9, 2.9A (март 2021 - ?) - CXL (CPER, CDAT), инклюзивная терминология
- 2.10 (август 2022) - LoongArch, confidential computing extension, NVM Express over Fabrics messaging device path, UEFI_MEMORY_ATTRIBUTE protocol, SHA-384/SHA-512
Заголовок файлов UEFI исполняемых образов (драйверы, приложения) д.б. оформлен в формате подмножества PE32+
(PE/COFF с 64-битным расширением,
Microsoft Portable Executable and Common Object File Format), в котором указывается архитектура (м.б. EBC) и тип файла (pre-OS agent):
- приложение, освобождает память и теряет состояние по выходу;
может вызывать другое приложение или драйверы;
первое встроенное приложение - менеджер загрузок)
- загрузчик ОС: особый вид приложения, вместо возвращения по завершению вызывает EFI_BOOT_SERVICES.ExitBootServices(),
передающий контроль над платформой ОС, освобождает ресурсы, занятые сервисами периода загрузки
- драйвер сервиса периода загрузки (резидентный при успешном завершении, память освобождается по ExitBootServices()),
загружается менеджером загрузки, прошивкой или приложением
- драйвер сервиса периода выполнения (резидентный при успешном завершении, сосуществуют с ОС,
загружается менеджером загрузки, прошивкой или приложением
Образы могут храниться на материнской плате (System ROM), карте расширения (Expansion ROM, PCI Option ROM, OpROM, OROM),
устройстве хранения (media), загрузочном сетевом сервере.
Копия PCI Option ROM в памяти не должна быть более 16 МБ, может содержать несколько образов Legacy BIOS
(первым, стандартный заголовок PCI Expansion ROM, см. PCI Firmware Specification)
и/или EFI (PCI Expansion ROM и PE/COFF)) для нескольких платформ, включая EBC, образы могут быть сжаты, также можно включать приложения (не загружаются).
Пакет flashrom позволяет искать, читать и писать прошивку для поддерживаемых материнских плат, сетевых карт, SATA и прочих.
Например, для материнской платы на C60X:
flashrom --programmer internal
Found chipset "Intel C60x/X79"
Found Micron/Numonyx/ST flash chip "N25Q128..3E" (16384 kB, SPI) mapped at physical address 0x00000000ff000000
Материнская плата на C610:
flashrom --programmer internal
No DMI table found.
Found chipset "Intel C610/X99 (Wellsburg)".
This chipset is marked as untested.
Warning: BIOS region SMM protection is enabled!
Warning: Setting Bios Control at 0xdc from 0x2a to 0x09 failed.
New value is 0x2a.
Warning: SPI Configuration Lockdown activated.
FREG2: Warning: Management Engine region (0x00021000-0x003fffff) is locked.
Not all flash regions are freely accessible by flashrom. This is most likely
due to an active ME. Please see https://flashrom.org/ME for details.
PR0: Warning: 0x00000000-0x00000fff is read-only.
PR1: Warning: 0x00a70000-0x00efffff is read-only.
PR2: Warning: 0x00001000-0x00010fff is read-only.
PR4: Warning: 0x00490000-0x004dffff is read-only.
Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) mapped at physical address 0x00000000ff000000.
Пример разбора для сетевой карты Intel 82599 10-Gigabit SFI/SFP+ Network Controller (X520-2),
замена прошивки на UEFI.
Определён формат архивов (FirmwareVolume, FV), содержащих образы, - файловая система FFS.
Утилита VolInfo из edk2-tools.
Platform Initialization (PI) Specification - стандарт на процедуру инициализации, реализация базы, на которой зиждется UEFI,
делится на фазы:
- SEC (код располагается и выполняется в ROM):
- обработать различные виды начал работы (включение питания, перезагрузка, S3 и др.) - сброс кеша, переход на процедуру инициализации в ROM,
переход в защищённый режим и с плоской памятью, инициализация MTRR, обновление микрокода всех процессоров
- подготовка временной памяти - располагается в кеше
- проверка остальных частей PI на валидность
- подготовить структуры данных и передать управление PEI
- PEI (Pre-EFI Initialization):
- имеет модульную структуру - ядро (PEI Foundation) и модули (PEIM) - модули разрабатываются изготовителями устройств
- PEIF и PEIM хранятся в первичном архиве BFV (Boot Firmware Volume)
- ядро отображается во временную память, выполняется из ROM
- ядро реализует базовые сервисы PEI и по очереди запускает PEIM
- описываются зависимости между модулями для определения порядка их загрузки PEIF (порядок получается не жёсткий)
- PEIM ищутся в BFV или других томах, обеспечиваемых ранее запущенными PEIM, выполняется из ROM или RAM
- указывается GUID соответствующего DXE драйвера: ЦП, чипсет, SMBus, ОП
- временные сервисы PEI: межмодульный интерфейс PPI, режим загрузки, структуры данных (HOB) для передачи информации в DXE,
обслуживание файловой системы FFS, обслуживание временной и постоянной памяти, вывод кода состояния, сброс
- инициализация достаточного количества настоящей памяти для DXE
- подготовить данные об обнаруженных устройствах для DXE в настоящей памяти
- DXE (Driver Execution Environment): встроенные сервисы, диспетчер драйверов, драйверы шин, устройств и сервисов;
DXE ядро формирует системную таблицу UEFI, сервисы периода загрузки и периода выполнения, сервисы DXE;
диспетчер DXE ищет и запускает требуемые DXE драйверы в требуемом порядке (имеется список первоочередных драйверов, в драйверах описаны зависимости);
драйверы обеспечивают инициализацию устройств и программную абстракцию (Architectural Protocol) для консоли и загрузочных устройств;
в частности, драйвер SMM выполняется в памяти SMRAM, доступ к которой для ОС блокируется (код в режиме SMM выполняется по прерыванию SMI);
при нормальной загрузке каждый драйвер дописывает S3 BootScript, при загрузке из S3 выполняется S3 BootScript вместо полной инициализации
Предусмотрены следующие программные абстракции (Architectural Protocol): безопасность, ЦП, метроном, таймер,
BDS (Boot Device Select), сторожевой таймер, переменные UEFI, запись переменных UEFI, сброс, монотонный счётчик, часы реального времени, коды состояния,
runtime (обеспечивает переход сервисов из физического режима памяти к виртуальному).
Драйверы обеспечивают сервисы для других модулей с помощью протоколов (протокол определяется в спецификации UEFI);
могут быть написаны на EBC или с использованием родной системы команд.
Драйверы делятся на:
- драйверы EFI 1.02 (запускается сразу после загрузки, ищет и инициализирует оборудование, запускает таймеры для опроса устройства)
- сервисные (регистрирует протокол и ручки управления им)
- инициализации (инициализирует оборудование и возвращает код ошибки, чтобы его выгрузили)
- корневого моста (для расширяемых шин типа PCI, работает с Device Path)
- драйверы, соблюдающие EFI Driver Model (при старте только регистрирует сервисы для запуска и останова при потребности;
никакого доступа к оборудованию при старте;
позволяют обеспечить горячее подключение и обслуживание неопределённого числа устройств одного типа - Driver Binding Protocol;
привязку контроллера к драйверу (сервис запуска драйвера) обычно вызывает менеджер загрузки
- неописываемый в стандарте механизм предварительно составляет список контроллеров верхнего уровня (Host Bus Controllers,
корней Device Path); осуществляется базовой прошивкой или не соблюдающим модель драйвером;
например, PCI Root Bridge - PciRoot(0x0)
- драйвер шины (сервис запуска привязывает устройство к существующему протоколу, ищет и привязывает подчинённый контроллер,
создаёт для него устройство; может искать все устройства на шине при запуске или искать их по одному;
устройство также может быть шиной;
промежуточный элемент Device Path - Pci(0x1f,0x2) или Pci(0x1c,0x4)/Pci(0x0,0x0))
- драйвер устройства (сервис запуска привязывает созданное драйвером шины устройство к существующему абстрактному протоколу
(протокол привязки имеет функции: Supported(), Start(), Stop()); абстрактные протоколы - блочный, текстовый ввод и т.д.;
новых устройств не создаёт;
лист Device Path - Sata(1,0,0) или MAC(a4bf010603c4,1)
- гибридный драйвер (совмещает драйвер устройства и шины)
Обработка событий (событие м.б. в 2 состояниях - ожидание и сигнальное):
- создать (устанавливается функция извещения и её приоритет TPL)
- удалить
- проверить состояние
- ждать перехода события в сигнальное состояние
- перевести в сигнальное состояние
Прерываний от оборудования нет (кроме single-timer interrupt?), только опрос (polling).
Извещение с высоким приоритетом прерывает выполнение извещения с низким приоритетом.
Приоритет TPL_HIGH_LEVEL блокирует даже прерывания от таймера.
Типы событий:
- события ожидания - функция извещения вызывается при проверке состояния и вызове функции ожидания
- сигнальное событие - функция извещения вызывается при переходе события в сигнальное состояние
- события от таймера: одноразовые и периодические
- ExitBootServices()
- SetVirtualAddressMap() (переход ОС от физической адресации к виртуальной)
После PI выполняется фаза выбора загрузочного устройства (BDS, Boot Device Select), загрузка UEFI приложений и выполнение ОС.
CSM (Compatibility Support Module) обеспечивает совместимость с BIOS, включает CSM16 (обеспечивается писателем BIOS) и интерфейс с PI.
Разработка приложений под EFI возможна с использованием пакетов edk2-tools (edk2-tools-doc, edk2-tools-python) - утилиты без компилятора от UEFI Forum
или на базе более старой версия от Intel - gnu-efi (gnu-efi-utils, gnu-efi-devel) - библиотека без инструментов.
В UEFI отсутствует вытесняющая многозадачность, хотя можно задействовать много ядер - EFI_MP_SERVICES_PROTOCOL,
по умолчанию функции не реентерабельны.
Спецификация UEFI описывает состояние после завершения инициализации и включает следующие понятия:
- системная таблица UEFI - содержит ссылки на все остальные объекты, передаётся каждому приложению или драйверу;
ведётся список указателей (handle) на протоколы, образы и устройства;
содержит ссылки на реализацию функций в драйверах и приватные данные;
список управляется драйверами и приложениями, тип указателя идентифицируется GUID, к каждому указателю привязан список пользователей объекта;
основные элементы: поставщик, ревизия, консольный ввод, консольный вывод, stderr, сервисы периода загрузки,
сервисы периода выполнения, ссылка на таблицы конфигурации
- таблицы конфигурации UEFI (ссылка из системной таблицы) - ACPI 2.0, ACPI, SMBIOS, SMBIOS 3, SAL (Itanium), MPS и др. (список в стандарте не полон)
- формат таблицы разделов GPT и EFI System partition,
содержащего понимаемую UEFI и ОС файловую систему с драйверами и приложениями;
UEFI может работать и с MBR
- Block Translation Table (BTT) - таблица трансляции адресов для флеш/NVDIMM без собственной аппаратной поддержки атомарности и устойчивости к истиранию
- переменные EFI
- байтовый код 64-битной виртуальной машины EBC (EFI Byte Code), little endian,
однопоточный интерпретатор виртуальной машины EFI_EBC_PROTOCOL;
из EBC можно вызывать процедуры, написанные с использованием "родной" системы команд;
из "родного" кода можно вызывать EBC
- таблица глобальных сервисов периода загрузки (необходимо прекратить использования после EFI_BOOT_SERVICES.ExitBootServices()),
эти сервисы обязательны к реализации:
- сервисы работы с базой протоколов (протокол - набор реализующих сервисы функций и описание связанных с ними приватных данных, идентифицируется GUID);
драйвер регистрирует реализацию протокола для обслуживаемого устройства с помощью сервиса InstallProtocolInterface
(также имеются разрегистрация и перерегистрация), привязка хранится в приватных данных устройства;
HandleProtocol и LocateProtocol ищут указатель на реализацию протокола по его GUID;
открыть и закрыть протокол для устройства отслеживают использование протоколов;
ещё одна группа функций отслеживает привязку драйверов к контроллерам;
реализация может содержать не описанные в стандарте протоколы
- управление приоритетами
- управление памятью (страницы и пулы)
- протоколы управления событиями (группами событий) и таймером (100 нс)
- протоколы для загрузки исполняемых образов UEFI в память и выполнения (выделяется память, копируются секции,
настраиваются адреса, устанавливаются атрибуты памяти, передаётся управление), запуск, выгрузка, выход из приложения,
завершения загрузки (ExitBootServices) и получения информации об образе - EFI_LOADED_IMAGE_PROTOCOL, EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL
- протоколы локации устройства Device Path (двоичное описание пути подключения устройства) EFI_DEVICE_PATH_PROTOCOL,
протокол поиска EFI_LOCATE_DEVICE_PATH, EFI_DEVICE_PATH_UTILITIES_PROTOCOL, протокол преобразования в текстовый вид EFI_DEVICE_PATH_TO_TEXT_PROTOCOL,
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
- протоколы работы с драйверами: подсоединить и отсоединить контроллер - EFI_DRIVER_BINDING_PROTOCOL, EFI_SERVICE_BINDING_PROTOCOL, EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL,
EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL, EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL, EFI_COMPONENT_NAME2_PROTOCOL, EFI_DRIVER_DIAGNOSTICS2_PROTOCOL,
EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL, EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL,
EFI_DRIVER_HEALTH_PROTOCOL (опрос состояния с выдачей сообщения и лечение с запросом к пользователю),
EFI_ADAPTER_INFORMATION_PROTOCOL (опросить и поменять: состояние носителя сети (для UNDI, SNP, MNP),
возможность загрузиться по сети (iSCSI IPv4, iSCSI IPv6, FCoE, TOE (TCP Offload Engine)),
MAC адрес, поддержка IPv6, тип носителя сети (Ethernet, WiFi); этот сетевой стек параллелен сетевому стеку PXE)
- вспомогательные сервисы: монотонный счётчик (старшая част увеличивается при сбросе, младшая - при каждом вызове,
охранный таймер (5 минут до сброса), ожидание (микросекунды),
CRC32, копирование и заполнение памяти, работа с таблицами конфигурации из системной таблицы
- таблица сервисов периода выполнения (дата, время, доступ к переменным UEFI и пр.), эти сервисы обязательны к реализации
- менеджер загрузки (BDS; выбор и загрузка драйверов и приложений; загрузчик ОС - тоже приложение UEFI)
- абстрактные протоколы
- протоколы поддержки текстовой консоли - EFI_SIMPLE_TEXT_INPUT_PROTOCOL, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
- дисковый и блочный протоколы - EFI_DISK_IO_PROTOCOL (создаётся как побайтовый доступ над EFI_BLOCK_IO_PROTOCOL, если не реализован самостоятельно);
EFI_DISK_IO2_PROTOCOL (неблокирующий доступ);
EFI_BLOCK_IO_PROTOCOL (создаётся также для каждого раздела MBR, GPT и El Torito (no emulation, идентификатор платформы 0xEF) или UDF 2.0 (UDF Bridge),
возможно кеширование записи; флажки сменяемости носителя, наличия носителя, запрета записи, кеширования записи; размеры логического и физического блоков и пр.);
EFI_BLOCK_IO2_PROTOCOL (неблокирующий доступ);
EFI_PARTITION_INFO_PROTOCOL (для каждого блочного устройства кешируется информация о MBR и GPT);
EFI_BLOCK_IO_CRYPTO_PROTOCOL (выборочное шифрование своими силами);
EFI_ERASE_BLOCK_PROTOCOL (абстракция для TRIM и т.п.);
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL (шифрование в устройстве - TRUSTED SEND/RECEIVE в ATA8-ACS, SECURITY PROTOCOL IN/OUT в SPC-4);
- протоколы доступа к хранилищу (Media Access), файловой системе и загрузки файлов - EFI_LOAD_FILE_PROTOCOL (не блочное устройство и не файловая система,
PXE (DHCP запрос,
для уточнения имени загружаемого файла может потребоваться помощь оператора - выбор из меню,
затем используется MTFTP для загрузки файла));
EFI_LOAD_FILE2_PROTOCOL (не блочное устройство и не файловая система, не источник загрузки);
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL (автоматически надстраивается над системным разделом или просто FAT
на блочном устройстве, только открытие тома);
EFI_FILE_PROTOCOL (доступ к файлам после открытия файловой системы с помощью EFI_SIMPLE_FILE_SYSTEM_PROTOCOL: открыть, закрыть, чтение (включая каталоги), запись,
управление позицией, сброс буферов, удаление файла, вариант с неблокирующим доступом);
EFI_TAPE_IO_PROTOCOL (тоже можно загрузиться, описывается формат заголовка ленты, начинается с "EFI BOOT")
- отладочный агент для удалённой отладки - EFI_DEBUG_SUPPORT_PROTOCOL (для родной системы команд и EBC: регистрация периодически вызываемой на целевой системе функции
для указанного процессора (д.б. обеспечено сохранение и восстановление контекста, интервал определяется реализацией);
регистрация функции обработки указанного типа прерывания (в т.ч. точка отладки) для указанного процессора),
EFI_DEBUGPORT_PROTOCOL (абстракция аппаратного интерфеса с отладчиком: сброс, чтение, запись, опрос;
выполняется внутри прерывания, поэтому не может вызывать сервисы UEFI;
настройка порта осуществляется указанием переменной UEFI с именем DEBUGPORT перед инициализацией драйвера, например,
"PciRoot(0)/Pci(0x1f,0)/ACPI(PNP0501,0)/UART(115200,N,8,1)/DebugPort()";
механизм для поиска системной таблицы без использования сервисов UEFI)
- спецификация сжатия (Tiano (сначала LZ77, затем код Хаффмана) и LZMA (в стандарте отсутствует)) и протокол восстановления - EFI_DECOMPRESS_PROTOCOL (обязателен),
в стандарте приведён исходный код программ сжатия и декомпрессии
- обработка строк, включая Unicode и регулярные выражения - EFI_UNICODE_COLLATION_PROTOCOL (лексическое сравнение строк и поиск по шаблону,
для поддержки работы с именами файлов в FAT - OEM (какой?) 8.3 и UCS-2);
EFI_REGULAR_EXPRESSION_PROTOCOL (регулярные выражения POSIX EXTENDED, Perl и ECMA 262 в UCS-2)
- абстрактные протоколы доступа к шинам и устройствам на шинах PCI, SCSI, iSCSI, USB
-
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL (работа с шинами PCI, один PCI Host Bus Controller (общее пространство адресов IO и MMIO) может иметь несколько корней,
PCI сегмент - набор шин с общим пространством конфигурации - может обслуживаться одним PCI Root Bridges или несколькими,
PCI Root Bridges может обслуживать локальную PCI или целый сегмент PCI),
EFI_PCI_IO_PROTOCOL (работа с IO, MMIO и памятью конфигурации PCI устройств; в ROM - копируется в память - может располагаться UEFI драйвер),
-
EFI_ATA_PASS_THRU_PROTOCOL (передача ATA команд, в т.ч. для логическим устройств RAID контроллера, опционально неблокирующий режим),
-
EFI_EXT_SCSI_PASS_THRU_PROTOCOL (драйвер многоканального контроллера, передача расширенных SCSI команд для любого устройства, для блочного ввода-вывода и SMART,
для комплекта требуются драйвер SCSI шины и драйвер SCSI устройства: установить режим (физическое или логическое устройство RAID контроллера,
опционально неблокирующий режим; а как описывается CacheCade? промежуточный слой? экспандеры? широкие порты?),
сбросить канал или LUN, получить следующий LUN, передать команду;
на логических устройствах можно строить блочный ввод-вывод),
EFI_SCSI_IO_PROTOCOL (драйвер SCSI устройства: передать команду, сбросить устройство или шину, узнать тип устройства (см. SPC-4), таргет и LUN;
в чём разница между шиной и каналом?),
-
EFI_ISCSI_INITIATOR_NAME_PROTOCOL (позволяет записать в NVRAM и прочитать имя iSCSI инициатора;
д.б. EFI_ADAPTER_INFORMATION_PROTOCOL, возвращающий EFI_ADAPTER_INFO_NETWORK_BOOT, что позволяет отличить
iSCSI UEFI драйвер над UEFI сетевым стеком (не PXE) и самостоятельную реализацию EFI_EXT_SCSI_PASS_THRU_PROTOCOL (TOE - аппаратная поддержка iSCSI)),
-
EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL (передача NVM Express команд), в т.ч. для логическим устройств RAID контроллера, опционально неблокирующий режим,
-
EFI_USB2_HC_PROTOCOL (драйвер контроллера USB 2.0 и 1.1 (XHCI, EHCI, UHCI и OHCI)), для драйвера шины USB и корневого концентратора:
опрос возможностей (LOW, FULL, HIGH, SUPER, количество портов корневого концентратора, 64-битные адреса),
сброс (контроллер, шина и устройства), опрос и установка состояния, управление передачей (прерывания, изохронность), опрос и управление корневым концентратором;
также периодически монитоит состояния портов корневого концентратора и создаёт или удаляет устройства USB),
EFI_USB_IO_PROTOCOL (драйвер устройства USB, устанавливает соответствующий типу устройства протокол, например, EFI_SIMPLE_TEXT_INPUT_PROTOCOL для клавиатуры:
передача данных управления, больших данных, прерываний и изохронная, получение описателя устройства, получение конфигурации устройства,
получение описателя интерфейса, получение описателя оконечника (endpoint), "This is a 16-bit ID defined by Microsoft" и даже без ссылки),
EFI_USBFN_IO_PROTOCOL (управление питанием и пр.),
-
EFI_SD_MMC_PASS_THRU_PROTOCOL (передача SD/eMMC команд),
-
EFI_NVDIMM_LABEL_PROTOCOL (хранилише описаний адресного пространства),
-
EFI_UFS_DEVICE_CONFIG_PROTOCOL (Universal Flash Storage)
- байтовый поток EFI_SERIAL_IO_PROTOCOL (параметры: глубина буфера, скорость, чётность, количество бит данных и пр.;
управление RTS и DTR, петля, контроль потока; состояния CTS, DSR, CD и RI)
- протоколы поддержки графики - EFI_SIMPLE_POINTER_PROTOCOL (3 координаты и 2 кнопки) и EFI_ABSOLUTE_POINTER_PROTOCOL,
EFI_GRAPHICS_OUTPUT_PROTOCOL (GOP, для замены VGA BIOS и UGA/UGA Draw Protocol, чтение и установка режима,
Blt - Block Transfer, 32 бита на пиксель, 800x600 или 640x480, поддержка нескольких устройств вывода),
EFI_EDID_DISCOVERED_PROTOCOL, EFI_EDID_ACTIVE_PROTOCOL, EFI_EDID_OVERRIDE_PROTOCOL
- обновление прошивки платформы и/или OpROM (см. OsIndicationsSupported для интерфейса с ОС)
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL (FMP): получить информацию о прошивке (версия дескриптора прошивки (3), номер прошивки в пакете,
номер и имя образа прошивки, имя и номер версии прошивки, атрибуты образа прошивки (можно менять, при обновлении требуется сброс, требуется аутентификация,
используется), есть поддержка проверки совместимости, самая старая поддерживаемая версия дескриптора, какую версию пытались поставить и чем дело кончилось,
экземпляр оборудования (MAC, серийный номер и т.п.)),
извлечь копию прошивки, изменить прошивку, проверить прошивку, получить информацию о пакете прошивок (версия пакета прошивок, имя версии пакета прошивок),
изменить информацию о пакете прошивок; см. протокол периода выполнения;
таблица конфигурации содержит ссылку на ESRT (EFI System Resource Table), которая может хранить вспомогательную информацию для облегчения поиска
- сетевые протоколы загрузки (SNP, PXE, BIS,
HTTP; наличие драйверов можно проверить командой оболочки drivers) - EFI_SIMPLE_NETWORK_PROTOCOL (абстракция пакетной передачи, SNP),
EFI_PXE_BASE_CODE_PROTOCOL (BC - IP, UDP, ARP, DHCP, TFTP - наследуется из PXE), ? (PxeDhcp4),
EFI_BIS_PROTOCOL, EFI_HTTP_SERVICE_BINDING_PROTOCOL, EFI_HTTP_PROTOCOL, EFI_HTTP_UTILITIES_PROTOCOL
- MNP (EFI_MANAGED_NETWORK_PROTOCOL) - асинхронный сетевой пакетный сервис - и EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL (поиск сетевого устройства)
- UNDI (Universal Network Driver Interface) - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL;
используется для PXE - наследуется из PXE;
реализуется драйвером устройства или в PCIe OpROM
- управление сетью (включая VLAN, Wi-Fi, EAP, Bluetooth) - EFI_VLAN_CONFIG_PROTOCOL;
EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL;
EFI_EAP_PROTOCOL, EFI_EAP_CONFIGURATION_PROTOCOL, EFI_EAP_MANAGEMENT2_PROTOCOL,
EFI_SUPPLICANT_PROTOCOL, EFI_EAP_CONFIGURATION_PROTOCOL;
EFI_BLUETOOTH_HC_PROTOCOL, EFI_BLUETOOTH_IO_PROTOCOL, EFI_BLUETOOTH_CONFIG_PROTOCOL, EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL, EFI_BLUETOOTH_LE_CONFIG_PROTOCOL
- сетевые протоколы (IP, TCP, UDP, IPsec, TFTP, TLS, ARP, DHCP, DNS, REST -
ещё 1 параллельный стек сетевых протоколов независимо от PXE и EFI_ADAPTER_INFORMATION_PROTOCOL;
наличие драйверов можно проверить командой оболочки drivers; настройка - ifconfig) - EFI_ARP_SERVICE_BINDING_PROTOCOL, EFI_ARP_PROTOCOL,
EFI_DHCP4_SERVICE_BINDING_PROTOCOL, EFI_DHCP4_PROTOCOL, EFI_TCP4_SERVICE_BINDING_PROTOCOL, EFI_TCP4_PROTOCOL, EFI_IP4_SERVICE_BINDING_PROTOCOL,
EFI_IP4_PROTOCOL, EFI_IP4_CONFIG_PROTOCOL, EFI_IP4_CONFIG2_PROTOCOL, EFI_UDP4_SERVICE_BINDING_PROTOCOL, EFI_UDP4_PROTOCOL и аналоги для IPv6;
EFI_TLS_SERVICE_BINDING_PROTOCOL, EFI_TLS_PROTOCOL, EFI_TLS_CONFIGURATION_PROTOCOL;
EFI_IPSEC_CONFIG_PROTOCOL, EFI_IPSEC2_PROTOCOL;
EFI_MTFTP4_SERVICE_BINDING_PROTOCOL, EFI_MTFTP4_PROTOCOL;
EFI_DNS4_SERVICE_BINDING_PROTOCOL, EFI_DNS4_PROTOCOL, EFI_DNS6_SERVICE_BINDING_PROTOCOL, EFI_DNS6_PROTOCOL;
EFI_REST_PROTOCOL
- безопасная загрузка и цифровая подпись драйверов и приложений
- интерфейс пользователя (HII), описывается в виде форм и строк в UCS-2 (базы строк, шрифтов и изображений),
драйвер при инициализации регистрирует свою часть в базе HII, а затем реагирует на события конфигурации -
EFI_HII_DATABASE_PROTOCOL, EFI_HII_STRING_PROTOCOL, EFI_HII_CONFIG_ROUTING_PROTOCOL, EFI_HII_CONFIG_ACCESS_PROTOCOL, EFI_HII_FONT_PROTOCOL.
- идентификация пользователя по паролю, смарт-картам, биометрическим устройствам и т.д. с раздачей прав
(например, только администратор может загрузить нестандартное приложение), для запроса используется HII - EFI_AUTHENTICATION_INFO_PROTOCOL
- протоколы безопасности (хеширование, управление ключами, датчик случайных чисел, Smart Card) - EFI_HASH_PROTOCOL, EFI_HASH_SERVICE_BINDING_PROTOCOL;
EFI_RNG_PROTOCOL
- EFI_RAM_DISK_PROTOCOL (регистрация RAM диска)
- протокол работы с таблицами ACPI - EFI_ACPI_TABLE_PROTOCOL (System Description Table или FACS)
- формат записей об аппаратных ошибках (каждая запись имеет заголовок 128 байт ('CPER', версия, уровень (некорректируемая, фатальная, корректируемая, информационная),
время, GUID платформы, GUID раздела, GUID автора, GUID типа механизма извещения (MCE - Machine Check Exception, PCIe - прерывание корневого порта PCIe,
INIT - кнопка пульта (см. IPF SAL - Itanium Processor Family System Abstraction Layer), NMI, Boot - запись о аварийной перезагрузке из SEL,
DMAr - DMA Remapping Error, CMC - Corrected Machine Check, CPE - Corrected Platform Error, SEA - Synchronous External Abort (ARM),
SEI - асинхронная SError Interrupt (ARM), PEI - Platform Error Interrupt (ARM)),
номер записи, флаги (восстановлено, старая, тестирование)),
описатели секций (по 72 байта: ревизия, флаги (главная, был сброс, превышен лимит ошибок, ресурс недоступен, восстановление незавершено, наведённая ошибка,
переполнение буфера ошибок), GUID типа секции (процессор вообще, процессор конкретный (ARM, IA32 и т.д.), IPF, ARM, ппамять латформы, PCIe, прошивка,
шина PCI/PCI-X, устройство PCI, DMAr, Intel VT, IOMMU), GUID FRU, имя FRU, уровень (некорректируемая, фатальная, корректируемая, информационная)),
секции (описан формат секций различных типов))
- UEFI shell
Device Path - протокол локации устройства (двоичный) EFI_DEVICE_PATH_PROTOCOL, разрабатывался с учётом ACPI.
Имеются протоколы преобразования в текстовый формат EFI_DEVICE_PATH_TO_TEXT_PROTOCOL и обратно EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL.
Путь (список путей) состоит из неограниченной последовательности узлов, в текстовом формате узлы представляются в виде
функции со списком аргументов через запятую, узлы разделяются символом "/".
Узлы бывают следующих типов (если тип нераспознан, то "Path(тип,подтип,данные)"):
- HardwarePath(подтип,данные) - физическое подключение (MMIO, IO), шина предоставляет ресурсы в домене когерентности
(пространство памяти, IO, пространство конфигурации PCI), подтипы:
- Pci - функция и устройство в пространстве конфигурации PCI, шина не указывается т.к. может меняться,
перед PCI узлом в цепочке должен быть ACPI узел, определяющий корень PCI шины; например: "PciRoot(0x0)/Pci(0x1f,0x2)/Sata(1,0,0)"
или "PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)"
- PcCard - номер функции (нумеруются с 0)
- MemoryMapped - тип (MMIO, IO Port и т.д.), начало, конец
- VenHW - GUID поставщика, данные
- Ctrl - номер контроллера
- BMC - тип интерфейса (1 - KCS, 2 - SMIC, 3 - Block Transfer), базовый адрес BMC в памяти или IO
- AcpiPath(подтип,данные) - ACPI устройство, идентификаторы PnP оборудования (_HID) и уникальные идентификаторы (_UID, серийный номер),
используется при отсутствии возможности Hardware Device Path (корень PCI шины), подтипы:
- Acpi - указывается _HID и _UID, например: "PciRoot(0)/Pci(0x1f,0)/ACPI(PNP0501,0)", где _HID
- PNP0A03 - PciRoot(идентификатор)
- PNP0A08 - PcieRoot(идентификатор)
- PNP0301 - Keyboard(идентификатор) - клавиатура
- PNP0501 - Serial(идентификатор) - последовательный порт (_UID от 0 до 3 - номер порта)
- PNP0401 - ParallelPort(идентификатор) - параллельный порт (_UID от 0 до 3 - номер порта)
- AcpiEx - указывается _HID, _UID и _CID в двоичном или текстовом (ASCII) формате
- AcpiAdr - атрибуты видеовывода - указывается _ADR (таблица B-2 ACPI 3.0); также используется для NVDIMM (NFIT, ACPI 6.0)
- Messaging Device Path - Msg(подтип,данные) - не координатные методы поиска устройств, шина потребляет ресурсы домена когерентности
и предоставляет ресурсы вне домена когерентности
- Ata(контроллер,устройство,LUN) - ATAPI - указывается первичный/вторичный, главный/подчинённый,
например, "PciRoot(0)/PCI(7,0)/ATA(Primary,Master,0)"
- SCSI - указывается номер исполнителя и LUN, например, "PciRoot(0)/PCI(7,0)/SCSI(2,0)";
для многоканального контроллера за мостом: "PciRoot(0)/PCI(5,0)/PCI(7,0)/Ctrl(3)/SCSI(2,0)"
- Fibre - FibreChannel - указывается WWN и LUN, например, "PciRoot(0)/PCI(8,0)/Fibre(0x21000050cc205ed4,0)"
- I1394 - Firewire (IEEE 1394) - указывается GUID в терминах IEEE 1394
- USB - указывается номер порта и номер интерфейса, например: "PciRoot(0x0)/Pci(0x1d,0x0)/USB(1,0)/USB(3,0)"
- I2O - указывается целевой идентификатор (TID)
- InfiniBand - указывается GID удалённого порта фабрики, постоянный адрес удалённого устройства и др.
- VenMsg - указывается GUID поставщика и пр. параметры, определены GUID для PC-ANSI (VenPcAnsi()), VT-100 (VenVt100()),
VT-100+ (VenVt100Plus()), VT-UTF8 (VenUtf8()), UartFlowCtrl (0 - None, 1 - Hardware, 2 - XonXoff);
должны стоять в конце цепочки узлов, например: "PciRoot(0)/Pci(0x1f,0)/ACPI(PNP0501,0)/UART(115200,N,8,1)/UartFlowCtrl(2)/DebugPort()";
сюда же почему-то попал SAS с GUID d487ddb4-008b-11d9-afdc-001083ffca4d (есть и отдельный подтип для SAS) -
указывается SAS адрес исполнителя, LUN, топология (внутренние SAS по SSP и SATA, внещние SAS или SATA черех экспандер), порт исполнителя,
например: "PciRoot(0)/PCI(1,0)/Sas(0x31000004CF13F6BD, 0, SATA)"; сложности с двухпортовыми устройствами
- MAC адрес - указывается MAC адрес и тип сети, напимер: "PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)"
- IPv4 - указывается местный адрес, удалённый адрес, локальный порт, удалённый порт, сетевой протокол (UDP/TCP),
адрес получен по DHCP или статически, адрес шлюза, маска подсети,
например: "PciRoot(0)/Pci(19,0)/Mac(001320F5FA77,0x01)/IPv4(192.168.0.100,TCP,Static,192.168.0.1)"
- IPv6 - указывается местный адрес, удалённый адрес, локальный порт, удалённый порт, сетевой протокол (UDP/TCP),
адрес получен статически или с помощью автоматической конфигурации, длина префикса, адрес шлюза
- UART - указываются параметры последовательного порта, например: "PciRoot(0)/Pci(0x1f,0)/ACPI(PNP0501,0)/UART(115200,N,8,1)
- UsbClass - указывается идентификатор изготовителя, идентификатор продукта, класс, подкласс, код протокола;
может использоваться в сокращённой форме (без указания начала последовательности узлов и/или с использованием шаблона 0xFF в любых позициях,
например (любая клавиатура): "UsbHID()")
- UsbWwid - указывается идентификатор изготовителя, идентификатор продукта, номер интерфейса, последние 64 бита серийного номера в UTF-16;
может использоваться в сокращённой форме (без указания начала последовательности узлов)
- Unit - указывается LUN
- Sata - указывается номер порта HBA и номер порта мультипликатора портов (0xFFFF при отсутствии мультипликатора) и LUN
например: "PciRoot(0x0)/Pci(0x1f,0x2)/Sata(1,0,0)"
- iSCSI - указывается сетевой протокол (TCP), опции регистрации, LUN, имя узла исполнителя, портальная группа (TPGT),
например: "PciRoot(0)/Pci(19,0)/Mac(001320F5FA77,0x01)/IPv4(192.168.0.100,TCP,Static,192.168.0.1)/iSCSI(iqn.1991-05.com.microsoft:iscsitarget-iscsidisk-target,0x1,0x0,None,None,None,TCP)/HD(1,GPT,15E39A00-1DD2-1000-8D7F-00A0C92408FC,0x22,0x2710000)"
- VLAN - указывается идентификатор VLAN
- FibreEx - FibreChannel расширенный - указывается WWN и LUN в виде массива байт
(в FC принят порядок следования байт big endian, в UEFI - liitle endian)
- SasEx - SAS расширенный (в виде массивов, чтобы избежать борьбы маленьких и больших индейцев) - указывается SAS адрес исполнителя, LUN,
топология и порт исполнителя
- NVMe - NVM Express - указывается идентификатор пространства имён (NSID), IEEE Extended Unique Identifier (EUI-64)
- URI - указывается URI
- UFS (Universal Flash Storage) - указывается PUN и LUN
- SD - Secure Digital - указывается номер слота
- Bluetooth - указывается адрес Bluetooth
- Wi-Fi - указывается SSID
- eMMC - указывается номер слота
- BluetoothLE - указывается адрес Bluetooth и тип адреса
- DNS - указываются адреса DNS серверов
- Media Device Path - MediaPath(подтип,данные) - внутренности устройства
- HD - указываются номер раздела (0 - весь диск), формат таблицы разделов (1 - MBR, 2 - GPT),
тип уникального идентификатора раздела и уникальный идентификатор раздела (GUID для GPT),
начальный сектор раздела (LBA), размер раздела; может использоваться в сокращённой форме
(GUID достаточно для поиска), например: "HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)"
- CDROM (ISO-9660 и El Torito) (no emulation, идентификатор платформы 0xEF)
или UDF 2.0 (UDF Bridge) - указываются номер загрузочной записи в каталоге,
относительный LBA начала раздела, размер раздела
- VenMedia - указывается GUID поставщика и пр. параметры
- File - полное имя файла в стандарте системного раздела EFI, можно разбивать на несколько узлов,
добавление '\' между узлами и удаление лишних '\' производится автоматически;
может использоваться в сокращённой форме,
например: "HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)"
- Media - указывается GUID протокола
- PI Firmware File, например: "FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)"
- PI Firmware Volume, например: "FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)"
- Offset (смещение от начала устройства) - указывюется смещение первого байта и смещение последнего байта
- RamDisk - указываются начальный адрес памяти, конечный адрес памяти,
тип диска (GUID из ACPI NFIT: EFI_VIRTUAL_DISK_GUID - VirtualDisk(), EFI_VIRTUAL_CD_GUID - VirtualCD(),
EFI_PERSISTENT_VIRTUAL_DISK_GUID - PersistentVirtualDisk(), EFI_PERSISTENT_VIRTUAL_CD_GUID - PersistentVirtualCD()),
номер экземпляра
- BIOS Boot Specification Device Path - BbsPath(подтип,данные) - для загрузки в режиме BIOS
- BBS (BIOS Boot Specification Version 1.01) - указываются тип устройства (01h - флоппи, 02h - НЖМД, 03h - CD-ROM, 04h - PCMCIA,
05h - USB, 06h - встроенная сеть, 80h - BEV (Bootstrap Entry Vector)), текст описания устройства (ASCII), флаг состояния
- End of Hardware Device Path - конец цепочки, подтипы:
- 0x1 - конец устройства и начало следующего устройства в списке
- 0xFF - конец всему
Для создания и манипуляции путями используется EFI_DEVICE_PATH_UTILITIES_PROTOCOL (узнать размер,
сделать копию, добавить путь, добавить узел, создать узел, добавить путь в список, извлечь путь из списка).
Протоколы поддержки текстовой консоли (устройства ConIn, ConOut, ConErr) используются для ввода и вывода текстовой
информации во время работы сервисов загрузки, нет поддержки устройств указания и вывода битовых карт:
- UEFI Simple Text Input (сканкоды (позиционирования курсора, Ins, Del, Esc, F1-F10) или UCS-2)
- UEFI Simple Text Input Ex (+ сканкоды Shift, Ctrl, Alt, logo, Menu, SysReq, ScrollLock, NumLock, CapsLock, управления громкостью и яркостью, F11-F24;
обработка горячих клавиш)
- UEFI Simple Text Output (минимум 80x25, UCS-2, символы псевдографики, сброс, запрос поддержки режима и установка режима (0 - 80x25, 1 - 80x50),
очистка экрана, цвет текста и фона, видимость курсора, позиционирование курсора, скролинг)
Приведены примеры для USB HID, ANSI X3.64 (VT200, ISO 6429), VT100+ (VT-UTF8 (Hyperterm и PC_ANSI), AT 101/102 Keyboard.
Консоль может быть реализована через последовательный порт или сеть.
UEFI Simple Text Output может быть реализован с помощью VGA или видеоконтроллера
(Graphics Output Protocol - GOP, Block Transfer - BLT).
Переменные EFI (идентифицируются по GUID производителя и имени;
каждый изготовитель прошивки имеет свой физический формат хранения: Intel - VSS, AMI - NVAR)
- имеют GUID производителя (пространство имён)
- имеют имя (UCS-2)
- имеют атрибуты (можно задавать только при создании, хочешь поменять - удали и создай заново)
- тип:
- обычные (хранятся в RAM), после ExitBootServices() их можно только читать
- NV (хранятся в NVRAM)
- HR (сообщения об ошибках аппаратуры, хранятся в NVRAM)
- уровень доступа
- BS (Boot Service Access)
- RT (Runtime Service Access, влечёт взведение бита BS, при отсутствии атрибута недоступны после ExitBootServices())
- AW (для записи требуется аутентификация), самая первая версия, устарела
- AT (для записи требуется аутентификация с учётом метки времени), вторая версия (сертификат X.509 PKCS#7 версии 1.5 в формате DER (RFC2315)),
используется для Secure Boot
- APPEND_WRITE (лишь флажок при записи)
- ENHANCED_AUTHENTICATED_ACCESS (вместе с данными хранятся метаданные - сертификат X.509 PKCS#7 версии 1.5 в формате DER (RFC2315) для расшифровки и пр.),
третья версия
- хранят данные (как минимум 1 байт, запись 0 байт - это удаление, место освобождается при следующей загрузке)
Переменные RT без NV во время работы ОС можно только читать.
Глобальные переменные (GUID 8be4df61-93ca-11d2-aa0d-00e098032b8c):
- LangCodes (BS, RT) - список 3-символьных кодов поддерживаемых языков общения (ISO-639-2), устарело вместе с протоколами UNICODE_COLLATION_INTERFACE,
EFI_DRIVER_CONFIGURATION_PROTOCOL, EFI_DRIVER_DIAGNOSTICS_PROTOCOL и EFI_COMPONENT_NAME_PROTOCOL
- Lang (NV, BS, RT) - 3-символьный код языка общения (ISO-639-2), будет действовать пи следующей загрузке, устарело
- PlatformLangCodes (BS, RT) - список кодов поддерживаемых языков общения (RFC 4646 (2-символьные ISO 639-1, затем 3-символьные ISO 639-2/T, затем ISO 639-2/B);
почти как в locale (список через ';'): 'en;fr;en-US;fr-FR')
- PlatformLang (NV, BS, RT) - код языка общения ((RFC 4646; почти как в locale)
- Timeout (NV, BS, RT) - задержка в секундах перед началом выбора загружаемой системы (UINT16), 0xFFFF или отсутствие пременной означает ожидание ввода
- ConIn, ConOut, ErrOut (NV, BS, RT) - device path консольного ввода, вывода и сообщений об ошибках по умолчанию
(двоичный), неправильное устройство замещается автоматически
- ConInDev, ConOutDev, ErrOutDev (BS, RT) - список возможных device path консольного ввода, вывода и сообщений об ошибках
(двоичный)
- AuditMode (BS, RT) - загрузка в режиме аудита
- DeployedMode (BS, RT)
- HwErrRecSupport (NV, BS, RT) - поддержка регистрации аппаратных ошибок, двоичный, в ОС только чтение;
1 - поддержка имеется, ОС может записывать информацию об аппаратных ошибках в переменные UEFI
414e6bdd-e47b-47cc-b244-bb61020cf516 HwErrRec#### (NV, BS, RT, HR), Common Platform Error Record;
Linux ничего сюда не пишет
- переменные менеджера загрузки
- dbDefault (BS, RT), dbrDefault (BS, RT), dbtDefault (BS, RT), dbxDefault (BS, RT), KEK (NV, BS, RT, AT), KEKDefault (BS, RT),
PK (NV, BS, RT, AT), PKDefault (BS, RT), SignatureSupport (BS, RT, список алгоритмов подписей),
SecureBoot (BS, RT), SetupMode (BS, RT, в режиме Setup не требуется аутентификация для изменения переменных безопасной загрузки),
VendorKeys (BS, RT, 1 - никто не менял ключи поставщика) - переменные безопасной загрузки
Почти все настройки хранятся в переменной с именем Setupю
Обнаружил у себя ec87d643-eba4-4bb5-a1e5-3f3e36b20da9-Setup, 01239999-fc0e-4b6e-9e79-d54d5db6cd20-Setup
и ec87d643-eba4-4bb5-a1e5-3f3e36b20da9-BmcSetup. В новой версии уже больше: BmcSetup-ec87d643-eba4-4bb5-a1e5-3f3e36b20da9,
Setup-01239999-fc0e-4b6e-9e79-d54d5db6cd20, SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c, PcSetupCommon-ec87d643-eba4-4bb5-a1e5-3f3e36b20da9,
PcSetupGeneration-4990bfe4-35f8-492d-8081-5938169c0d6c, DefPcSetupCommon-8add7331-f51a-499b-a299-3fa0c757bb18, DefPcSetupGeneration-8add7332-f51c-499d-a599-3fa0c757bb18,
DefSetup-591e2ee3-27a0-465a-986f-0bef888ad8ba.
Переменные с атрибутом BS недоступны при работе ОС, но доступны через EFI Shell.
Доступны ОС при загрузке в режиме UEFI (/usr/share/doc/kernel-doc-*/Documentation/filesystems/efivarfs.txt)
- /sys/firmware/efi/efivars (файловая система типа efivarfs, опции монтирования rw,nosuid,nodev,noexec,relatime;
рекомендуется поменять на ro, если нет насущной необходимости); kernel 3.8;
каждая переменная в отдельном файле (права на запись) с именем "имя_переменной-GUID"
- /sys/firmware/efi/vars (отдельный каталог - attributes, data (только чтение), guid,
raw_var (структура ядра efi_variable, права на запись), size (в текстовом виде) - на каждую переменную
и файлы del_var (сюда записывать структуру ядра efi_variable) и new_var (сюда записывать структуру ядра efi_variable);
ограничение на размер значения переменной - 1024 байта); старый стиль
- /sys/firmware/efi/fw_vendor - физический адрес поля поставщика в системной таблице EFI
- /sys/firmware/efi/runtime - физический адрес таблицы сервисов периода выполнения в системной таблице EFI
- /sys/firmware/efi/config_table - физический адрес таблицы конфигурации в системной таблице EFI
- /sys/firmware/efi/fw_platform_size - разрядность платформы (текстовый формат, 64 бита)
- /sys/firmware/efi/esrt/ (UEFI 2.5; доступ к ESRT - EFI System Resource Table,
/usr/share/doc/kernel-doc-*/Documentation/ABI/testing/sysfs-firmware-efi-esrt; каталог прошивок, отсутствует в Intel H2000G)
Если переменные недоступны, то вы загрузились в режиме BIOS.
Для работы с переменными EFI можно использовать утилиту efivar
(пакеты efivar-libs.x86_64, efivar.x86_64, efivar-devel.x86_64). Ключи:
- --list # вывести список текущих переменных (GUID-имя брать отсюда)
- --list-guids # вывести список известных переменных
- --print --name GUID-имя # в шестнадцатеричном и символном формате, без интерпретации
- --print-decimal --name GUID-имя
- --append --name GUID-имя --attributes=атрибуты
- --write --name GUID-имя --attributes=атрибуты
Для платформы Intel можно использовать утилиту syscfg:
syscfg /bvar {create | overwrite} имя-EFI-переменной GUID значение [3 | 7]
Ключ ядра efi_no_storage_paranoia отключает защитные механизмы записи в переменные UEFI
(иногда ядро собрано так, что переменые можно только читать), что поможет вам окирпичить свой компьютер.
Загрузка (фаза Boot Device Selection, BDS) может производиться в режиме UEFI
или CSM (Compatibility Support Module) для совместимости с BIOS (legacy mode).
Выбор производится явно или неявно (например, обнаружение загрузочного устройства в формате MBR может приводить к переходу в режим совместимости).
Некоторые дополнительные устройства имеют прошивку только для BIOS (CSM) и если они требуются для вывода сообщений или загрузки,
то загружаться придётся в CSM режиме. Но с UEFI.
CSM также может потребоваться при расхождении битности UEFI и UEFI приложения.
Установщик ОС, загруженный в режиме BIOS, не сможет добавить установленную ОС в список загрузки UEFI.
BIOS не знает, с какого устройства будет загрузка, поэтому будит всех, менеджер загрузки UEFI в начале будит только ту цепочку устройств,
которые необходимы для загрузки драйверов и первого источника загрузки.
Предусмотрены различные режимы загрузки: режим восстановления (перемычка, инициализировать только устройство для
чтения образа восстановления и восстановление прошивки или запускать DXE с резервного тома),
обновление прошивки (новую версию прошивки предварительно где-то сохранили),
возвращение из режима S3 (было сохранение в память и не надо её инициализировать, не надо вызывать DXE, надо восстановить состояние и возобновить работу ОС),
минимальная конфигурация,
полная настройка (из S0, стандартный режим), полная конфигурация и диагностика, с настройками по умолчанию, из S4 (на диск), из S5 (мягкое выключение), из S2.
Загрузчик должен иметь возможность:
- определить, откуда он был загружен (чтобы подгрузить вспомогательные файлы)
- определить, где находится ОС (возможно потребуется драйвер файловой системы)
- построить карту физической памяти
- прочитать переменные окружения для определения опций загрузки и записать их для передачи параметров загружаемой ОС
- ExitBootServices() (ОС сама может его вызвать), grub2?
- передать адрес системной таблицы UEFI (как передать - стандарт умалчивает)
Для нормальной загрузки с блочного устройства в режиме UEFI требуется наличие раздела EFI System Partition
(как при использовании GPT, так и MBR), обычно монтируется как /boot/efi, содержащий
загрузчики и другие UEFI приложения, например средства диагностики, обновления прошивки и пр..
Для каждой загружаемой ОС в каталоге /EFI/ обычно создаётся подкаталог для хранения её загрузчиков и прочих файлов.
Драйверы UEFI позволяют добраться к файлам из других файловых систем
(например: btrfs, exFAT, ext2/ext3/ext4, ISO9660, JFS, NTFS, XFS, ZFS и др.).
Встроенный менеджер загрузки определяет консоль (см. PlatformLang, ConIn, ConOut, ErrOut), загружает драйверы (переменная DriverOrder),
подготовительные приложения (переменная SysPrepOrder) и выбирает из упорядоченного (переменная BootOrder)
списка источников загрузки (Boot####) первый активный и работоспособный,
затем загружает приложение (загрузчик второй ступени (GRUB (shim), rEFInd, Gummiboot, Windows Boot Manager), EFI Shell, диагностическую программу и т.д.),
устанавливает сторожевой таймер на 5 минут и запускает приложение.
При отсутствии BootOrder менеджер загрузки ищет \efi\BOOT\BOOTX64.EFI (для архитектуры X86-64)
на всех мобильных устройствах хранения, которые поддерживают EFI_SIMPLE_FILE_SYSTEM_PROTOCOL (путь файла включает ссылку на устройство и абсолютное имя файла)
или EFI_BLOCK_IO_PROTOCOL (пробегает по разделам и пытается найти в них EFI_SIMPLE_FILE_SYSTEM_PROTOCOL)
или EFI_LOAD_FILE_PROTOCOL (например, сетевой интерфейс; путь файла включает ссылку на устройство и специфическую для устройства
информацию - не используется при загрузке, а передаётся как параметр при запуске; напрямую выдаётся один файл),
а затем разделах EFI System Partition фиксированных устройств хранения,
найденный путь обрабатывается как будто он был подставлен в PlatformRecovery####.
Аналогичный поиск проиводится в рамках устройства, если источник загрузки указывает на EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, но без указания имени файла.
Путь к USB устройству может иметь сокращённую форму с указанием USB WWID или класса устройства USB (при поиске придётся
включить все устройства).
Путь к НЖМД или SSD может иметь сокращённую форму с указанием типа таблицы разделов, номера раздела (0 - весь диск), GUID раздела, смещения и размера
(при поиске будут включены все блочные устройства).
Сокращённая форма может состоять только из полного имени файла, в этом случае будут перепробованы все устройства, поддерживающие протокол
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL или EFI_BLOCK_IO_PROTOCOL.
Сокращённая форма может состоять из URI.
Загрузка может открыть новые тома с драйверами (ROM платы расширения). Если загрузка была неудачной, то эти драйверы запускаются диспетчером DXE и процедура повторяется.
Интерфейс пользователя, в частности, меню загрузчика стандартом не определяется.
Информация для менеджера загрузки хранится в NVRAM в глобальных переменных UEFI (номера переменных шестнадцатеричные, 4 знака,
без подавления незначащих нулей):
- Timeout - секунд (никакого меню загрузки не выводится, просто ожидание перед началом выбора; отсутствие переменной означает ожидание ввода)
- BootCurrent - текущий источник загрузки
- BootOrder - список номеров Boot#### по порядку через запятую, попытки загрузить по очереди, двоичный
- Boot0000 - описание источника загрузки 0: атрибуты (является ли источник активным, требуется ли переподключать
все драйверы после загрузки из списка DriverOrder, является ли источник скрытым (не показывать в меню), категория - загрузчик или приложение,
приложение может быть вызвано только из меню или горячей клавишей),
метка для вывода на экран (UCS-16), путь к загружаемому UEFI приложению (на самом деле список из которого менеджер загрузки
использует первый элемент), передаваемые приложению данные; источник д.б. типа EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
- Key0000 - горячие клавиши для вызова источника загрузки, двоичный формат: номер источника загрузки, коды клавиш (от 0 до 3),
необходимость удержания Shift, Ctrl, Alt, Logo, Menu и SysReq
- Boot0001 - описание источника загрузки 1
- ...
- BootNext - для следующей загрузки указанный источник (4 шестнадцатеричных цифры) вставляется в начало BootOrder,
удаляется до передачи управления приложению;
например, можно установить запуск программы настройки, в частности, с помощью "systemctl reboot --firmware-setup")
- BootOptionSupport - типы опций загрузки, поддерживаемые менеджером загрузки, двоичный формат:
- поддержка горячих клавиш - 0x1
- возможность загрузки приложений, отличных от загрузчика - 0x2
- поддержка SysPrep - 0x10
- максимальная длина последовательности горячих клавиш - 0x0300
- SysPrepOrder (UEFI 2.5) - активные источники запускаются по очереди после загрузки драйверов,
но до выбора запускаемого приложения (разбора BootOrder) - шифровальщики дисков, эмуляторы IPMI;
приложение получает доступ к консоли и сети; не должно вызывать ExitBootServices()
- SysPrep0000 - источник приложения SysPrep
- SysPrep0001 - ...
- DriverOrder - список номеров Driver#### по порядку через запятую, попытки загрузить по очереди
- Driver0000 - описание источника 0 драйвера DXE (UEFI 2.3), источник д.б. типа EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
или EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
- Driver0001 - описание источника 1 драйвера DXE
- ...
- SecureBoot - 0 (нет)
- OsIndications - позволяет ОС требовать каких-то действий от прошивки, двоичный
- OsIndicationsSupported - какие действия можно потребовать, двоичный:
- бит EFI_OS_INDICATIONS_BOOT_TO_FW_UI - запустить интерфейс пользователя при следующей перезагрузке
- бит EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION - почистить dbt (отметки времени)
- бит EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED - обработка капсул модификации прошивки (EFI_FIRMWARE_MANAGEMENT_PROTOCOL)
- бит EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED - запустить обработку капсул модификации прошивки на устройстве хранения при следующей перезагрузке
- бит EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED - результат обработки капсулы модификации в переменную UEFI EFI_CAPSULE_REPORT_GUID:CapsuleXXXX
(NV, BS, RT, не более чем EFI_CAPSULE_REPORT_GUID:CapsuleMax, последний в EFI_CAPSULE_REPORT_GUID:CapsuleLast);
EFI_CAPSULE_REPORT_GUID - 39b68c46-f7fb-441b-b6ec-16b0f69821f3
- бит EFI_OS_INDICATIONS_START_OS_RECOVERY - обработать OsRecoveryOrder
- бит EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY - обработать PlatfromRecoveryOrder
- OsRecoveryOrder - список номеров OsRecover#### по порядку через запятую, попытки загрузить по очереди;
механизм запускается при установке флага EFI_OS_INDICATIONS_START_OS_RECOVERY или неудаче BootOrder, только при активированном Secure Boot;
типа AT (dbr, не dbx, KEK, PK)
- OsRecovery0000 - источник приложения для восстановления загрузчика, только при активированном Secure Boot; типа AT (dbr, не dbx, KEK, PK); не глобальное имя?
- OsRecovery0001 ...
- PlatfromRecoveryOrder - список номеров PlatformRecover#### по порядку через запятую, попытки загрузить по очереди,
недоступен для ОС (гарантийный сервис, диагностика); механизм запускается при установке флага EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY
или неудаче OsRecoveryOrder
- PlatfromRecovery0000 - источник приложения для восстановления загрузчика, недоступен для ОС
- PlatfromRecovery0001 ...
- IpmiBootForceIntoSetup - в стандарте не указана
- IpmiForcedPersistent - в стандарте не указана
Описание загрузчиков отделено от их физического расположения (перенести диск недостаточно - надо ещё заполнить
переменные менеджера загрузки).
Менеджер загрузки может самостоятельно изменять загрузочные переменные (в стандарте не описано): удалять ошибочные по его мнению,
добавлять свои (например, запуск программы настройки или UEFI Shell). Возможно (но не обязательно) средство ручной настройки источников и порядка загрузки.
Типы загрузочных устройств (если имя файла не указано, то выбирается файл по умолчанию - "\EFI\BOOT\BOOTx64.EFI"):
- блочные устройства (дисковое устройство целиком) - "HD(номер,0,00)"
- блочные устройства с разделами MBR/GPT - раздел рассматривается как логическое блочное устройство
- блочные устройства с файловой системой формата Simple File System (FAT и другие при наличии дополнительных драйверов) в разделе, есть запись и даже кеш -
"HD(номер,тип-таблицы-разделов,GUID-раздела,стартовый-сектор,число-секторов)/File(путь-в-формате-UEFI)"
- CD/DVD (El Torito, no emulation, идентификатор платформы 0xEF) или UDF 2.0 (UDF Bridge) - логическое блочное устройство
- устройства, непосредственно реализующие протокол File System
- устройства, непосредственно реализующие протокол Load File (сетевое устройство) -
"PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)/IPv4(0.0.0.0:0<->0.0.0.0:0,0,0)"
- BIOS устройство для загрузки в режиме совместимости (диск MBR или CD/DVD) - "BIOS(номер,0,00)канал: модель"
- USB устройство - "PciRoot(0x0)/Pci(0x1d,0x0)/USB(1,0)/USB(3,0)"
Некоторые реализации предлагают меню источников загрузки по нажатию некоторой кнопки после включения (F6? F11? F12? для платформ Intel).
Если при загрузке не получается запустить утилиту настройки (Setup, кнопки F2, Del, Fn+F2 и др.),
то можно попробовать отсоединить все устройства хранения перед перезагрузкой и зайдя в Setup отключить быструю загрузку.
Настройка переменных производится средствами встроенного менеджера загрузки или командой bcfg UEFI Shell.
Утилита efibootmgr (пакет efibootmgr) позволяет редактировать переменные менеджера загрузки,
требуется доступ на UEFI переменным через /sys/firmware/efi/vars или /sys/firmware/efi/efivars/,
посмотреть текущее состояние (пример после установки системы с размещением /boot и ESP на отдельных mdraid RAID-1),
звёздочка - активный источник загрузки (Fv - Firmware Volume, идентифицируется по GUID):
efibootmgr -v
BootCurrent: 000B
Timeout: 0 seconds
BootOrder: 000B,0009,0005,0006,0004,0007,0008,0000,0001,0002,0003,000A,000C
Boot0000* Enter Setup FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001 Boot Device List FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(eec25bdc-67f2-4d95-b1d5-f81b2039d11d)
Boot0002 Payload Launch FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(98feaa7f-d726-4d8e-8157-a51ff8beb6e3)
Boot0003 Network Boot FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(9e09e6fd-4e16-6468-9b78-bdaeaf609cff)
Boot0004* UEFI IPv6: Intel I350 Network 00 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)/IPv6([::]:<->[::]:,0,0)
Boot0005* UEFI IPv4: Intel I350 Network 00 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)/IPv4(0.0.0.0:0<->0.0.0.0:0,0,0)
Boot0006* Launch EFI Shell FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(c57ad6b7-0515-40a8-9d21-551652854e37)
Boot0007* UEFI IPv6: Intel I350 Network 01 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x1)/MAC(a4bf010603c5,1)/IPv6([::]:<->[::]:,0,0)
Boot0008* UEFI IPv4: Intel I350 Network 01 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x1)/MAC(a4bf010603c5,1)/IPv4(0.0.0.0:0<->0.0.0.0:0,0,0)
Boot0009* CentOS HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)
Boot000A* UEFI SATA0:HGST HTS725050A7E630 PciRoot(0x0)/Pci(0x1f,0x2)/Sata(0,0,0)
Boot000B* CentOS HD(2,GPT,51c99c89-ae76-4638-adc6-235759772589,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)
Boot000C* UEFI SATA1:HGST HTS725050A7E630 PciRoot(0x0)/Pci(0x1f,0x2)/Sata(1,0,0)
aa23ecbc-796d-46a1-a852-a3ca1b43c329 - это sda2
51c99c89-ae76-4638-adc6-235759772589 - это sdb2
cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0 - ?
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 1000M 0 part
│ └─md2 9:2 0 999.4M 0 raid1 /boot
├─sda2 8:2 0 200M 0 part
│ └─md1 9:1 0 200M 0 raid1 /boot/efi
└─sda3 8:3 0 464.6G 0 part
└─md3 9:3 0 464.5G 0 raid1
├─system-root 253:0 0 19.5G 0 lvm /
└─system-swap 253:1 0 58.6G 0 lvm [SWAP]
sdb 8:16 0 465.8G 0 disk
├─sdb1 8:17 0 1000M 0 part
│ └─md2 9:2 0 999.4M 0 raid1 /boot
├─sdb2 8:18 0 200M 0 part
│ └─md1 9:1 0 200M 0 raid1 /boot/efi
└─sdb3 8:19 0 464.6G 0 part
└─md3 9:3 0 464.5G 0 raid1
├─system-root 253:0 0 19.5G 0 lvm /
└─system-swap 253:1 0 58.6G 0 lvm [SWAP]
Если efibootmgr не работает, то вы загрузились в режиме BIOS.
Ключи efibootmgr (осторожно: можно получить попорченные переменные загрузчика - у меня был неудаляемый источник 1001
и лишний "Enter Setup" первым в списке):
- --verbose
- --quiet
- --unicode | --UCS-2 # дальнейшие аргументы не в ASCII, а в UCS-2
- --bootnum #### # указать Boot#### для воздействия
- --edd30 {1|3|-1} # выбрать версию EDD, -1 - догадаться
- --gpt # считать, что диск в формате GPT, хоть и не похож
- --driver # оперировать с Driver#### вместо Boo####
- --sysprep # оперировать с SysPrep#### вместо Boot####
- --iface имя # интерфейс для сетевой загрузки
- --inactive # деактивировать строку
- --active # активировать строку
- --delete-bootnum # удаляем строку загрузки
- --create --label 'строка текста в меню' --loader 'абсолютный путь загрузчика в стиле UEFI' --part номер-раздела --disk диск -u "параметры-загрузчика"
# добавить строку загрузки Boot#### и внести её в список BootOrder, некоторые реализации не умеют сохранять параметры загрузчика вовсе
или сохраняют их криво
- --bootorder ####,... # установить BootOrder
- --remove-dups # удалить дубли из BootOrder
- --delete-bootorder
- --bootnext #### # установить переменную BootNext
- --delete-bootnext
- --timeout секунд # установить переменную Timeout
- --delete-timeout
Установка memtest86 от PassMark (free, 7.4, ISO версия) на сервер с UEFI для прямой загрузки:
SYSLINUX поддерживает загрузку ядра Linux в режиме UEFI с версии 6 (syslinux.efi, syslinux.cfg).
GRUB Legacy (0.97) официально не поддерживает загрузку UEFI,
но модифицированная версия (Fedora 11 до 17, RHEL 6) - поддерживает загрузку ядра Linux и UEFI приложений,
отсутствует поддержка Secure Boot.
Пакет grub-0.97-99.el6.x86-64.rpm устанавливает /boot/efi/EFI/redhat/grub.efi, конфигурация grub.conf в том же каталоге,
в документации слов EFI и UEFI не обнаружил (grub.info, multiboot.info, grub-crypt.8, grub-install.8, grub-md5-crypt.8, grub-terminfo.8, grub.8).
Позволяет загружаться с устройств GPT с размером сектора 4 КиБ со времён RHEL 6.1, с разделов более 2 ТиБ со времён RHEL 6.2.
GRUB2 поддерживает загрузку ядра Linux, FreeBSD, Mac OS и пр.,
а также UEFI приложений. Поддерживает (и даже настаивает на) Secure Boot.
Отдельные версии для UEFI-32 (grub2-efi-ia32.x86_64, grub2-efi-ia32-cdboot.x86_64, grub2-efi-ia32-modules.noarch) и
UEFI-64 (grub2-efi-x64.x86_64, grub2-efi-x64-cdboot.x86_64, grub2-efi-x64-modules.noarch), сам загрузчик всегда 64-битный.
Настройки изготавливаются из /etc/default/grub с помощью команды "grub2-mkconfig -o /boot/grub2/grub.cfg"
и "grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg".
При установке CentOS 7 создаётся /boot/efi/EFI/centos/shim.efi (/EFI/centos/shim.efi от начала раздела ESP),
содержащий 64-битный подписанный Microsoft (подпись для чужого ПО) загрузчик "первой" ступени shim.efi, который
загружает настоящий загрузчик (grub2) после проверки подписи для безопасной загрузки.
Копии кладутся в /boot/efi/EFI/centos/shimx64.efi и /boot/efi/EFI/BOOT/BOOTX64.EFI.
Запись о загрузке CentOS добавляется в список источников загрузки в NVRAM.
Варианты 32- и 64-битных подписанных и неподписанных загрузчиков можно найти в пакетах shim-ia32, shim-unsigned-ia32, shim-x64 и shim-unsigned-x64.
shimx64-centos.efi подписан CentOS вместо Microsoft.
Новый стандарт UAPI рекомендует монтировать ESP раздел не в /boot/efi, а в /efi, причём и /boot и /efi как autofs.
Файл [/boot]/efi/EFI/rocky/grub.cfg (совпадает с /boot/grub2/grub.cfg) теперь лишь
определяет значения переменных - boot (где найти раздел для монтирования /boot, обычно тип - mduuid - и уникальный идентификатор),
$kernelopts, $tuned_params, $grub_users). Меню загрузки генерируется командой blscfg из тексотвых (UTF-8) файлов *.conf
в каталогах /boot/loader/entries/ и ESP/loader/entries/, каждая строка содержит ключ, пробел, значение.
Комментарии начинаются с '#'. Ключи:
- title - описание строки меню загрузки
- version - например, версия ядра; используется для сортировки строк меню
- machine-id - уникальный идентификатор хоста
- sort-key - строка для сортировки строк меню
- linux - имя файла ядра Linux относительно корня boot; рекомендуется создавать подкаталог с именем идентификатора машины и подкаталог с именем версии
- initrd - имя файла initrd относительно корня boot
- efi - имя файла EFI программы относительно корня boot
- options - параметры ядра
- devicetree
- devicetree-overlay
- architecture - архитектура в соответствии со стандартом UEFI (IA32, x64, IA64, ARM, AA64)
Например:
title Rocky Linux (4.18.0-553.8.1.el8_10.x86_64) 8.10 (Green Obsidian)
version 4.18.0-553.8.1.el8_10.x86_64
linux /vmlinuz-4.18.0-553.8.1.el8_10.x86_64
initrd /initramfs-4.18.0-553.8.1.el8_10.x86_64.img $tuned_initrd
options $kernelopts $tuned_params
id rocky-20240702172104-4.18.0-553.8.1.el8_10.x86_64
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel
Unified Kernel Images
Для случая потери записей в NVRAM (достаточно вынуть диск и включить питание!)
в /boot/efi/EFI/BOOT/fallback.efi (он же fbx64.efi) кладётся примитивный первичный загрузчик,
который ищет файлы BOOT.CSV или BOOTX64.CSV в каталоге EFI на своём блочном устройстве,
добавляет записи в список источников загрузки в NVRAM на основе содержимого найденных файлов, затем загружает исходя из первой записи.
Файл BOOT.CSV содержит строки (UCS-2! а может быть и UTF-16) с разделяемыми запятыми полями (CSV!): имя "первичного" загрузчика (shimx64.efi),
метка для списка источников загрузки, опции "первичного" загрузчика, описание метки.
В /boot/efi/EFI/centos/ кладутся эти самые BOOT.CSV (он же BOOTX64.CSV) для fallback.efi.
К сожалению, в /boot/efi/EFI/BOOT/BOOTX64.EFI кладётся shim.efi вместо fallback.efi, так что магия не работает.
В /boot/efi/EFI/centos/mmx64.efi (он же MokManager.efi)
кладётся UEFI приложение для управления базой ключей MOK (как запустить?).
Все UEFI файлы кроме shim подписаны распространителем ("Red Hat Inc."?).
shim загружает и выполняет "вторичный" загрузчик
сначала средствами UEFI LoadImage() и StartImage(),
а если не получается (например, включена безопасная загрузка и загрузчик не имеет допустимой подписи),
то проверяет наличие подписи распространителя по встроенному в shim сертификату (Red Hat Secure Boot (CA key 1)?) или из MOK.
При успехе запускает вторичный загрузчик. Также встраивает протокол, позволяющий запущенному загрузчику осуществлять аналогичную проверку.
Сам shim подписан Microsoft.
Базовое имя вторичного загрузчика намертво вшито в shim при компиляции и сборке, в нашем случае "grubx64.efi".
При формировании полного URI вторичного загрузчика
используется путь (имя каталога или адрес TFTP) самого shim (если начали по TFTP, то и всё будет по TFTP).
В нашем случае grub2 из пакета grub2-efi устанавливается в
/boot/efi/EFI/centos/grubx64.efi (его файлы рядом grub.cfg, grubenv и fonts/unicode.pf2) из пакета grub2-efi,
Загрузка модулей GRUB2 не допускается (всё, что посчитали нужным, уже в нём ;), механизма подписи модулей нет).
GRUB2 выводит меню (не подписано) для выбора, настройки и загрузки
ядра и его верного initrd (не подписано, dracut для RHEL7),
[проверяет с помощью shim подпись распространителя (Red Hat Secure Boot (CA key 1)?) или из MOK для собранных ядер] и запускает.
Ядро CentOS 7 в режиме безопасной загрузки проверяет (за рамками стандарта) подписи модулей перед их установкой
(при каждой сборке ядра генерируются приватные ключи, которыми подписываются модули, публичные ключи встраиваюттся в ядро, приватные - удаляются),
также ограничивается (ограничивался?) функционал (setpci, hibernate, kexec, модуль msr, acpi_rspd, /dev/kmem, systemtap kprobe).
В ESP можно записать ядро Linux, оформленное как UEFI приложение (UEFI boot stub, CONFIG_EFI_STUB,
в RHEL 7.4 включено, /usr/share/doc/kernel-doc-3.10.0/Documentation/x86/efi-stub.txt), в этом случае загрузчик вообще не нужен,
но возникают проблемы с безопасной загрузкой (надо каждое собранное ядро подписывать основным ключом).
Ключи ядра при запуске из UEFI Shell передаются как аргументы UEFI приложения, ключ initrd= позволяет указать абсолютное имя initrd файла в стиле EFS
("fs0:\Kernels> bzImage.efi initrd=\Ramdisks\initrd-large.img"). При запуске из менеджера загрузки параметры придётся прошить в ядро.
Также можно в качестве загрузчика указать UEFI Shell и в его скрипте startup.nsh указать ядро с нужными параметрами.
Или задать параметры с помощью efibootmgr или команды UEFI Shell или BIOS Setup.
Поменять параметры (например, загрузиться в single mode) при загрузке нельзя.
Пример прямой загрузки (обратите внимание на формат initrd, и он д.б. в начале строки):
- имеем свежеустановленную систему CentOS 7.4, см. выше вывод lsblk и efibootmgr
- cp /boot/vmlinuz-3.10.0-693.5.2.el7.x86_64 /boot/efi/EFI/centos/
- cp /boot/initramfs-3.10.0-693.5.2.el7.x86_64.img /boot/efi/EFI/centos/
- efibootmgr -v --create --label 'Direct CentOS 7.4' --loader '\EFI\centos\vmlinuz-3.10.0-693.5.2.el7.x86_64'
--part 2 --disk /dev/sda -u "inird=\EFI\centos\initramfs-3.10.0-693.5.2.el7.x86_64.img
root=/dev/mapper/system-root ro rd.md.uuid=39942dc1:042f00a9:0a4b45ed:94a7f25e
rd.lvm.lv=system/root rd.md.uuid=ce975460:abc2f8b9:9bf9a176:39accccd rd.lvm.lv=system/swap
selinux=0 LANG=en_US.UTF-8 rd.shell"
- нужен второй для второго диска зеркала, но поленился
- reboot
- efibootmgr -v # 2 штуки CentOS (000B и 0009) сделаны при установке, "Direct CentOS 7.4" только что
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000D,0000,000B,0009,0005,0006,0004,0007,0008,000A,000C,0001,0002,0003
Boot0000* Enter Setup FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001 Boot Device List FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(eec25bdc-67f2-4d95-b1d5-f81b2039d11d)
Boot0002 Payload Launch FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(98feaa7f-d726-4d8e-8157-a51ff8beb6e3)
Boot0003 Network Boot FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(9e09e6fd-4e16-6468-9b78-bdaeaf609cff)
Boot0004* UEFI IPv6: Intel I350 Network 00 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)/IPv6([::]:<->[::]:,0,0)
Boot0005* UEFI IPv4: Intel I350 Network 00 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)/IPv4(0.0.0.0:0<->0.0.0.0:0,0,0)
Boot0006* Launch EFI Shell FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(c57ad6b7-0515-40a8-9d21-551652854e37)
Boot0007* UEFI IPv6: Intel I350 Network 01 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x1)/MAC(a4bf010603c5,1)/IPv6([::]:<->[::]:,0,0)
Boot0008* UEFI IPv4: Intel I350 Network 01 at Baseboard PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x1)/MAC(a4bf010603c5,1)/IPv4(0.0.0.0:0<->0.0.0.0:0,0,0)
Boot0009* CentOS HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)
Boot000A* UEFI SATA0:HGST HTS725050A7E630 PciRoot(0x0)/Pci(0x1f,0x2)/Sata(0,0,0)
Boot000B* CentOS HD(2,GPT,51c99c89-ae76-4638-adc6-235759772589,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)
Boot000C* UEFI SATA1:HGST HTS725050A7E630 PciRoot(0x0)/Pci(0x1f,0x2)/Sata(1,0,0)
Boot000D* Direct CentOS 7.4 HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)/File(\EFI\centos\vmlinuz-3.10.0-693.5.2.el7.x86_64)
Формально поддержка UEFI и GPT в RHEL 7 имеется и улучшается (например, в RHEL 7.2 в kickstart)
была добавлена команда reqpart для создания ESP раздела), но напильник понадобится (установка на md вручную, memtest86+ не работает в UEFI.
Загрузка с использованием PXE в UEFI перенесена в статью по PXE.
UEFI клиент PXE при DHCP запросе взводит бит требования широковещательного ответа и этот широковещательный ответ
не всегда доходит до него (VLAN со внутренней маршрутизацией, DHCP клиент CentOS 7.4 работает без проблем).
Пришлось на время установки отключать DHCP Relay и ставить локальный DHCP сервер.
- развернуть установочный диск CentOS 7.4 и обеспечить анонимный доступ по FTP по ftp://ftp/pub/CentOS7.4/base/x86_64
- положить файл для kickstart и дополнительные файлы на сервер FTP
под именем /pub/kickstarts/полное-имя-хоста.CentOS74.cfg, особенности (LVM поверх программного RAID,
полный текст):
...
ignoredisk --only-use=/dev/sda,/dev/sdb
zerombr
clearpart --drives=/dev/sda,/dev/sdb --all
bootloader --location=mbr --driveorder=/dev/sda,/dev/sdb --boot-drive=/dev/sda
partition raid.008001 --size=200 --asprimary --ondisk=/dev/sda
partition raid.008017 --size=200 --asprimary --ondisk=/dev/sdb
# metadata=1.0
raid /boot/efi --fstype="efi" --level=1 --device=1 --label=ESP raid.008001 raid.008017
partition raid.008002 --size=1000 --asprimary --ondisk=/dev/sda
partition raid.008018 --size=1000 --asprimary --ondisk=/dev/sdb
# metadata=1.2
raid /boot --fstype="ext4" --level=1 --device=2 --label=boot raid.008002 raid.008018
partition raid.008003 --size=100 --grow --asprimary --ondisk=/dev/sda
partition raid.008019 --size=100 --grow --asprimary --ondisk=/dev/sdb
# metadata=1.2
raid pv.009001 --level=1 --device=3 raid.008003 raid.008019
volgroup system pv.009001
logvol / --fstype="ext4" --label=root --name=root --vgname=system --size=20000
logvol swap --fstype="swap" --name=swap --vgname=system --size=60000
...
- создать каталог uefi для TFTP сервера, в который положить:
- подписанный shim.efi из пакета shim-x64 в CentOS 7
- grubx64.efi (взять из пакета grub2-efi в CentOS 7), grub.cfg
- initrd.img и vmlinuz из images/pxeboot установочного DVD-ROM под именами CentOS74.vmlinuz и CentOS74.initrd.img
- отредактировать файл конфигурации GRUB2 uefi/grub.cfg (параметризация по ${net_efinet2_hostname} или ${net_efinet1_hostname}
при выключенной загрузке PXE IPv6 - серверов будет много, вариант bond -
объединение ethernet портов):
set timeout=60
menuentry 'CentOS 7.4' {
linuxefi uefi/CentOS74.vmlinuz ramdisk_size=16000 selinux=0 ip=:::::eno1:dhcp:9000 lang=en_US.UTF-8 rd.locale.LANG=en_US.UTF-8 rd.vconsole.keymap=us rd.vconsole.font=latarcyrheb-sun16 rd.vconsole.unicode inst.geoloc=0 inst.lang=en_US.UTF-8 inst.keymap=us inst.sshd ks=ftp://ftp/pub/kickstarts/${net_efinet1_hostname}.CentOS74.cfg kernel.ixgbe.allow_unsupported_sfp=1 inst.syslog=192.168.172.181:514 inst.loglevel=info inst.kdump_addon=off inst.selinux=0 inst.gpt
initrdefi uefi/CentOS74.initrd.img
}
menuentry 'CentOS 7.4 bond' {
linuxefi uefi/CentOS74.vmlinuz ramdisk_size=16000 selinux=0 bond=bond0:eno1,eno2:mode=0 ip=:::::bond0:dhcp:9000 lang=en_US.UTF-8 rd.locale.LANG=en_US.UTF-8 rd.vconsole.keymap=us rd.vconsole.font=latarcyrheb-sun16 rd.vconsole.unicode inst.geoloc=0 inst.lang=en_US.UTF-8 inst.keymap=us inst.sshd ks=ftp://ftp/pub/kickstarts/${net_efinet1_hostname}.CentOS74.cfg kernel.ixgbe.allow_unsupported_sfp=1 inst.syslog=192.168.172.181:514 inst.loglevel=info inst.kdump_addon=off inst.selinux=0 inst.gpt
initrdefi uefi/CentOS74.initrd.img
}
menuentry rescue {
linuxefi uefi/vmlinuz inst.repo=ftp://ftp/pub/CentOS7.4/base/x86_64 ip=:::::eno1:dhcp:9000 inst.syslog=syslog.cs.niisi.ras.ru lang=en_US.UTF-8 rd.locale.LANG=en_US.UTF-8 rd.vconsole.keymap=us rd.vconsole.font=latarcyrheb-sun16 rd.vconsole.unicode inst.rescue kernel.ixgbe.allow_unsupported_sfp=1
initrdefi uefi/initrd.img
}
menuentry 'rescue bond' {
linuxefi uefi/vmlinuz inst.repo=ftp://ftp/pub/CentOS7.4/base/x86_64 bond=bond0:eno1,eno2:mode=0 ip=:::::bond0:dhcp:9000 inst.syslog=syslog.cs.niisi.ras.ru lang=en_US.UTF-8 rd.locale.LANG=en_US.UTF-8 rd.vconsole.keymap=us rd.vconsole.font=latarcyrheb-sun16 rd.vconsole.unicode inst.rescue kernel.ixgbe.allow_unsupported_sfp=1
initrdefi uefi/initrd.img
}
menuentry memtest {
chainloader uefi/BOOTX64.MEMTEST86-74.EFI
}
- настроить DHCP сервер для загрузки установщика PXE, особенности для UEFI:
if option architecture-type = 00:07 { # установка в режиме UEFI EBC
filename "uefi/shim.efi";
} else { # предыдущий вариант уустановки в режиме BIOS
filename "linux-install/pxelinux.0";
}
- перевести загрузку сервера в режим UEFI (самое время настроить остальные параметры, в т.ч. IPMI), перезагрузиться
- отредактировать список источников загрузки: загрузка по PXE с первого сетевого интерфейса, при неудаче UEFI Shell, всё лишнее удалить
- загрузиться по сети, установка должна пройти автоматически
- задокументировать
- в результате в каталоге /boot/efi/EFI/BOOT/ должны оказаться файлы BOOTX64.EFI и fbx64.efi, а в каталоге /boot/efi/EFI/centos/ -
файлы shim.efi (подписанный Microsoft), shimx64.efi (копия), shimx64-centos.efi (?), mmx64.efi (MokManager - управление базой ключей MOK),
BOOT.CSV (строка описания в UCS-2 для программы восстановления fbx64.efi), BOOTX64.CSV (копия), grubx64.efi, grub.cfg, grubenv,
Отказ от инициализации USB в фазе DXE/BDS экономит целых 0.5 секунды (и ещё 0.5 секунды на ожидание ввода),
правда при этом нельзя нажать клавишу входа в настройки, т.к. USB клавиатура не работает. И как обновляться с USB устройств?
Отказ от загрузки в режиме CSM экономит время - опциональные ROM карт расширения могут ждать ввода пользователя
для вызова программы конфигурации (2 секунды на сетевой карте Intel);
опциональные ROM карт расширения должны быть запущены все и каждый ROM перебирает всё дерево устройств в поиске "своего" контроллера.
Без CSM можно инициализировать только минимальный набор устройств, необходимых для загрузки (3 секунды на обычном ПК),
правда, не все устройства могут включиться (ОС должна проинициализировать устройство самостоятельно).
Отказ от CSM позволяет инициализировать только консоль и первое устройство из BootOrder вместо всего подряд
(если в BootOrder не использовано сокращённое описание загрузочного устройства в виде GUID раздела или класса устройства).
Отключение графической заставки экономит 0.3 секунды на инициализации графики и неизвестно сколько на демонстрации картинки.
SSD (не Intel X25-E ;) экономит несколько секунд.
Прямая загрузка ядра вместо shim-grub2-kernel, но нужно оставить "чёрный ход"
для варианта загрузки с редактированием параметров ядра.
Сервисы периода выполнения доступны как во время загрузки (после PEI), так и во время выполнения ОС,
поэтому должны быть готовы как к физическому режиму работы памяти, так и к виртуальному.
Все сервисы неблокирующие (имеются ограничения на последовательность вызовов, которые ОС должна соблюдать самостоятельно)
и могут выполняться с включёнными прерываниями (при необходимости самостоятельно отключают прерывания), память резервируется и не используется ОС,
используемые аппаратные ресурсы описываются и ОС должна согласовывать их использование или не использовать сервисы периода выполнения вовсе.
Минимальный набор сервисов:
- переменные UEFI - прочитать значение переменной по имени и GUID,
записать значение переменной по имени и GUID, дать имя и GUID следующей переменной (начинать с NULL UCS-2 в поле имени),
получить информацию о системе хранения переменных UEFI (максимальный размер, свободное место, максимальный размер переменной)
- время и дата (наносекунды, часовой пояс, летнее время - позволяет абстрагироваться от аппаратной реализации - прочитать и установить,
узнать возможность хранения и другие параметры (разрешение, точность), прочитать и установить будильник
- виртуальная память - переключить сервисы из режима плоской физической адресации памяти в виртуальный
и преобразовать указатели в системной таблице (может вызываться из режима плоской физической адресации памяти, только после ExitBootServices(), только 1 раз);
конвертация указателей для работы в виртуальном режиме (также вызывается из обработчиков события переключения таблицы адресации)
- прочитать старшую часть монотонного счётчика (хранится между загрузками, старшая часть увеличивается на 1 при сбросе и опросе старшей части,
младшая часть увеличивается на 1 при опросе)
- сброс системы (холодный, тёплый (не чистить память), с выключением (ACPI G2/S5)), можно записать текстовое описание;
в системный журнал могут записываться все сбросы
- передать капсулу прошивке для обработки сейчас или при сбросе системы (подписанная изменённая прошивка кладётся в область ожидания обновлений);
капсула может содержать драйверы для загрузки при обработке обновления и/или обновления прошивки (payload);
можно проверить капсулу на допустимость;
можно инициировать сброс при передаче капсулы;
после сброса до загрузки специальный модуль проверяет подпись заявок в области ожиданий и удовлетворяет прошедшие контроль заявки;
при обработке капсулы сервисом периода выполнения результат может быть помещён в переменные UEFI, см. OsIndicationsSupported;
капсулы можно поместить в каталог \EFI\UpdateCapsule системного раздела EFI активного устройства (BootNext или BootOrder);
файлы обрабатываются в алфавитном порядке и удаляются после обработки независимо от результата
Для kexec требуется информация об отображении виртуальных адресов,
(/usr/share/doc/kernel-doc-*/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map), которая хранится в каталоге /sys/firmware/efi/runtime-map
(EFI_MEMORY_ATTRIBUTES_TABLE),
каждый подкаталог (0/, 1/ и т.д.) содержит информацию об регионе памяти (текстовое представление, шестнадцатеричный вид):
attribute, num_pages, phys_addr, type, virt_addr. На платформе Intel H2000G занято изрядно:
[ 0.000000] efi: EFI v2.40 by EDK II BIOS ID:SE5C610.86B.01.01.0022.062820171903
[ 0.000000] efi: SMBIOS=0x7a223000 ACPI=0x7b7cc000 ACPI 2.0=0x7b7cc014
[ 0.000000] efi: mem319: type=6, attr=0x800000000000000f, range=[0x000000007a127000-0x000000007a227000) (1MB)
[ 0.000000] efi: mem320: type=5, attr=0x800000000000000f, range=[0x000000007a227000-0x000000007a327000) (1MB)
[ 0.000000] efi: mem328: type=11, attr=0x8000000000000000, range=[0x0000000080000000-0x0000000090000000) (256MB)
[ 0.000000] efi: mem329: type=11, attr=0x8000000000000000, range=[0x00000000fed1c000-0x00000000fed20000) (0MB)
[ 0.000000] SMBIOS 2.7 present.
[ 0.000000] DMI: Intel Corporation S2600TPR/S2600TPR, BIOS SE5C610.86B.01.01.0022.062820171903 06/28/2017
Работа с капсулами в пакетах fwupdate (утилита /usr/bin/fwupdate, "--list",
"--supported" (Intel H2000Z нет поддержки, требуется UEFI 2.5), "--info"),
fwupdate-efi (приложение UEFI /boot/efi/EFI/centos/fwupx64.efi (fwupia32.efi)) и fwupdate-libs.
Манипулирует переменной UEFI с именем fwupdate и GUID 0abba7dc-e516-4167-bbf5-4d9d1c739416, а также перемеными менеджера загрузки для
установки и загрузки приложения UEFI для обновления прошивки в /boot/efi/EFI/centos/fw/fwupdate-* (флажок /usr/share/fwupdate/done).
Использование сервисов времени выполнения ядром Linux можно отключить (/usr/share/doc/kernel-doc-3.10.0/Documentation/x86/x86_64/uefi.txt)
при загрузке ядра ключами noefi (все) и reboot_type=k (только сервис перезагрузки).
Если карта памяти UEFI (UEFI MemMap) шире карты памяти E820, то её можно добавить ключом add_efi_memmap при загрузке (включено по умолчанию).
Ключ ядра efi_no_storage_paranoia отключает защитные механизмы записи в переменные UEFI (иногда ядро собрано так, что переменые можно только читать).
UEFI Shell - приложение UEFI, обеспечивает интерактивную командную оболочку для работы с консоли,
набор команд и обработку скриптов (.nsh, ASCII или UCS-2), может запускать приложения UEFI и скрипты из ПЗУ или устройств хранения,
для которых имеются UEFI драйвера.
В частности, умеет работать с системным разделом и прочими файловыми системами FAT112/FAT16/FAT32.
Также работает с переменными менеджера загрузки, разделами, файлами, имеется текстовый и шестнадцатеричный редактор,
инструменты исследования аппаратуры. Может быть встроенным в прошивку (например, Intel использует UEFI Shell как средство
обновления прошивки, вызывается из меню загрузки). Обеспечивает API для запущенных приложений (разбор и выполнение командной строки и т.д.).
Имеет средства работы с историей команд (стрелки вверх и вниз).
Выполнение скриптов, команд и приложений можно прервать нажатием Ctrl-C (не обязательна поддержка прерывания команд и приложений).
Ошибка в командах скрипта не останавливает его выполнение, кроме команд for, endfor, if, else, endif и goto.
Вывод на консоль можно приостанавливать нажатием Ctrl-S и возобновлять любой клавишей.
Буфер вывода (минимум 3 экрана) можно листать клавишами PageUp и PageDown во время ожидания.
Скрипты могут быть вложенными, включая рекурсию.
Дополнительные команды могут быть добавлены драйверами.
Стандарт определяет 4 уровня поддержки (в версии 2 появились профили):
- 0 - ничего нет (запуск приложений?)
- 1 - нет интерактива и большинства команд (имеются только команды управления)
- 2 - нет интерактива
- 3 - полный набор
Имя приложения или скрипта для запуска указывается в качестве параметра shell.efi, после чего можно задать параметры приложения.
При этом подразумевается ключ '-nostartup' (см. ниже). Все имена и параметры задаются в UCS-2.
Опции запуска (перед параметром):
- -nostartup (не выполнять startup.nsh при инициализации)
- -noconsoleout (не выводить)
- -noconsolein (не вводить)
- -delay [секунд] (пауза перед запуском startup.nsh, по умолчанию - 5 секунд)
- -nointerrupt (заблокировать прерывание выполнения)
- -nomap (не выводить начальное отображение устройств (map) командой "map -terse")
- -noversion (не выводить информацию о версии командой ver при инициализации)
- -startup (выполнять startup.nsh при инициализации)
- -nonesting (возможность вложенных вызовов управляется переменной окружения оболочки nonesting)
- -exit (завершиться после завершения вызванного приложения или скрипта)
При инициализации оболочки пути устройств (device path) отображаются на имена файловых системы (fsX:) и блочные устройства (blkX:),
читается список синонимов и переменных окружения из ПЗУ, в переменную окружения profiles читается список профилей (не обнаружен),
ищется (сначала в каталоге запуска самого shell.efi, затем в списке из переменной окружения PATH ("."))
и запускается startup.nsh (см. -startup и -nostartup).
Имена команд, файлов, переменных и пр. нечувствительны к регистру и разделяются пробелами и табуляциями.
Поддерживаются синонимы команд (alias).
Подстановка значений переменных окружения осуществляется символами '%' вокруг имени переменной,
позиционных переменных (от 0 - полное имя скрипта до 9) - символом '%' перед номером позиции,
индексных переменных - символом '%' перед буквой создаваемого командой for индекса.
Комментарии начинаются символом '#'. Метки начинаются символом ':'.
Специальные символы (включая пробел) окружаются двойными кавычками (подстановка значений переменных не отменяется).
Специальное значение символа блокируется символом '^' даже внутри кавычек.
Шаблоны имён файлов задаются с использованием символов '*' (любое число символов), '?' (1 любой символ,
'[' и ']' (1 символ из перечисленных в скобках) в "некоторых местах" ('^' не действует).
Символ '@' в начале строки отключает вывод текста команды на консоль ("echo -off" отключает для всех следующих команд).
Перенаправление ввода и/или вывода в файл или переменную окружения или другую команду,
специальные имена файлов NUL или NULL никуда не пишут:
- '>' (stderr и stdout в UCS-2)
- '>a' (stderr и stdout в ASCII)
- '1>' (stdout в UCS-2)
- '1>a' (stdout в ASCII)
- '2>' (stderr в UCS-2)
- '2>a' (stderr в ASCII)
- '>v' (stderr и stdout в переменую UCS-2, не NV)
- '1>v' (stdout в переменую UCS-2, не NV)
- '2>v' (stderr в переменную UCS-2, не NV)
- '>>' (добавление к файлу или переменной, все варианты с модификаторами a, v, 1, 2)
- '<' (ввод из файла в UCS-2)
- '<a' (ввод из файла в ASCII)
- '<v' (ввод из переменной окружения в UCS-2)
- '|' (передача вывода в UCS-2)
- '|a' (передача вывода в ASCII)
Имена переменных окружения чувствительны к регистру (в реализации версии 1 от Intel - нет).
Могут храниться как переменные UEFI в NVRAM (под именем "SEnv:имя", атрибуты - NV+BS; GUID - ?)
или пропадать при перезагрузке ("set -v имя значение", атрибуты - BS).
Некоторые имена зарезервированы:
- cwd # текущий рабочий каталог, включая текущую файловую систему и текущий каталог в ней
- lasterror
- path # список путей поиска через точку с запятой
- profiles
- uefishellsupport # уровень поддержки UEFI Shell, не реализовано в версии 1
- uefishellversion # не реализовано в версии 1
- nonesting
Переменные UEFI отображаются по возможности с именами пространства имён вместо GUID
(для регистрации своего имени пространства имён используется RegisterGuidName),
например "Efi:PlatformLangCodes" вместо "8be4df61-93ca-11d2-aa0d-00e098032b8c:PlatformLangCodes".
Для каждой файловой системы независимо ведётся текущий каталог (как в PC DOS),
ведётся текущая файловая система, которые используются при отсутствии файловой системы и/или каталога в имени файла.
Имена каталогов разделяются символом '\'. Имя файловой системы выглядит как 'fs', затем её номер, затем ':\'.
Длина полного имени файла не может быть более 255 символов (UCS-2?).
Начальное отображение путей устройств на файловые имена "fsX:" (и "map -r") не должно изменяться при перезагрузке при неизменном списке оборудования
(безумный ad hoc на 16 страниц ради получения "консистентных" имён, лучше просто верить, что вставленная флешка всегда будет "fs0:";
ну или fs2: при наличии пары файловых систем EFI на диске).
Общие ключи команд (не у всех команд, ключи нельзя конкатенировать - "-v -b", но не "-vb"):
- -?
- -v|-verbose # увеличить болтливость ("alias|drvcfg|set -v" - volatile, а не verbose)
- -q|-quite # работать тихо
- -t|terse # почти тихо ("smbiosview -t" - type, а не terse)
- -sfo # вывод в формате не для людей
- -b # делать паузу после вывода каждого экрана
Команды:
- help [имя-команды]
- ver # вывести номер версии UEFI или UEFI Shell ("-s"): UEFI 2.40 (EDK II) и UEFI Shell 1.0 (X64)
- alias # создание и удаление алиасов, без параметров выводит список
- работа с каталогами: cd (".." - по прежнему вверх; в документации запрещено использовать имена файловых систем, но работает),
ls (синоним dir, "-r" - рекурсивно, "-a{a|s|h|r|d|}" - фильтр по атрибуту или все файлы (по умолчанию системные и скрытые файлы не показываются)),
mkdir (синоним md)
- работа с консолью и интерактивом: cls (очистка консоли); echo (вывод сообщений и управление отображением команд из скрипта на консоли - "-on" и "-off");
mode [колонок строк] (просмотр списка режимов отображения и выбор режима); parse (разбор бесчеловечного формата -sfo);
pause (ждать ввода с клавиатуры, при вводе "q" или "Q" завершать скрипт, иначе продолжать);
stall (ждать указанное количество микросекунд)
- работа с файлами:
- attrib # установка и очистка атрибутов FAT (archive, system, hidden, read-only)
- comp [-b] имя-файла-1 имя-файла-2 [-n макс-число-различий|all] [-s байт-к-показу] # сравнить двоичные файлы
- cp [-r] [-q] исходный-шаблон ... [результат] # копирование файлов или каталогов, если результирующий файл/каталог не указан,
то в текущий рабочий каталог
- edit имя-файла # текстовый редактор (ASCII и UCS-2),
поддерживает UTF-8 (?!), ^E - вызов помощи (не работает, откуда информация?)
- eficompress и efidecompress # сжать и обратно
- hexedit {-f имя-файла|-d блочное-устройство смещение размер|-m фдрес размер} # шестнадцатеричное редактирование файла, блочные устройства, памяти
- mv исходный-шаблон ... [результат] # перемещение файлов или каталогов, если результирующий файл/каталог не указан, то в текущий рабочий каталог
- rm [-q] шаблон-имени-файла-или-каталога ... # каталоги удаляются рекурсивно
- setsize размер имя-файла ... # изменить размер файла
- touch [-r] шаблон-имени-файла-или-каталога ... # изменить время модификации файла на текущее
- type шаблон-имени-файла-или-каталога ... # вывести файл UCS-2 или ASCII на консоль
- работа с драйверами:
- connect (подключить драйвер к устройству, "-r" - всё что найдёт)
- disconnect (отключить драйвер от устройства, "-r" - отключить все и подключить обратно консоль)
- reconnect ("-r" - всё)
- drivers (вывести список драйверов): номер рукоятки, тип (B - шина, D - устройство), наличие протокола конфигурации,
наличие протокола диагностики, количество обслуживаемых устройств, количество порождённых устройств, имя драйвера, имя файла с драйвером
- drvcfg (настройка указанного драйвера для указанного устрйства;
"-c" - вывести список настраиваемых драйверов; "-f 0" - сброс настроек; "-s" - вызвать меню настроек; "-v" - проверить настройки);
для Intel PRO/1000 6.6.04 PCI-E (1GNicEFI) вызывается меню скорости и автосогласования, UEFI стек и PXE не настраиваются,
инициализация устройства и портов и IP и iscsi не управляется
- drvdiag (запустить диагностику указанного драйвера на указанном устройстве: "-s" - стандартную, "-e" - расширенную, "-m" - производственную;
без параметров выдаёт список поддерживающих диагностику устройств)
- load имя-файла # загрузить драйвер в память из файла в формате UEFI и подключить к устройству; "-nc" - не подключать
- loadpcirom имя-файла # загрузить драйвер в память из файла в формате ROM (все образы PE32) и подключить к устройству; "-nc" - не подключать
- unload рукоятка # выгрузить драйвер; "-n" - не слушать предупреждений
- дата и время: date (показать или установить текущую дату), getmtc (вывести значение монотонного счётчика, не работает),
time (показать или установить текущее время, часовой пояс и летнее время), timezone (показать или установить часовой пояс)
- dblk блочное-устройство [номер-начального-сектора] [число-секторов] [-b] # показать содержимое блочного устройства в шестнадцатеричном и символьном
виде, начало и число в шестнадцатеричном формате, число секторов не более 0x10, если блок содержит MBR или системный раздел, то дешифрует его
- работа с устройствами:
- devices (вывести список устройств - больше 100; типы устройств (R - контроллер корня, B - контроллер шины, D - контроллер устройства);
наличие протокола конфигурации;
наличие протокола диагностики; #P - количество родителей, #C - количество детей, #D - количество устройств этого типа; путь устройства или описание (?)
- devtree (вывести дерево устройств, выводит больше устройств, чем devices, "-d" - указывать путь устройства вместо имени);
в выводе присутствует номер рукоятки (device handler), которую можно подать команде dh или openinfo
Device Tree
Ctrl[EB] PciRoot(0x0)
Ctrl[231] PciRoot(0x0)Pci(0x1C,0x3) # PCI мост
Ctrl[232] PciRoot(0x0)Pci(0x1C,0x3)/Pci(0x0,0x0) # Matrox G200e Display Deviceа PCI мостом
Ctrl[247] PciRoot(0x0)Pci(0x1C,0x3)/Pci(0x0,0x0)AcpiAdr(0x80010100) # Analog Display VGA за мостом
Ctrl[19A] Primary Console Output Device (Txtout, Graphics Output, UgaDraw)
Ctrl[233] PciRoot(0x0)Pci(0x1C,0x4) # PCI мост
Ctrl[234] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0) # за PCI мостом
Ctrl[252] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC(A4BF0103A303,0x1) # Ethernet NIC, Intel I350 Gigabit Network Connection \
(Net, MNPSb, ARPSb, DHCPv4Sb, TCPv4Sb, IPv4Sb, IPv4Config, UDPv4Sb, MTFTPv4Sb, HiiConfAccess, номерные)
Ctrl[254] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC(A4BF0103A303,0x1)/VenHw(5BEDB5CC-D830-4EB2-8742-2D4CC9B54F2C)
Ctrl[27C] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC(A4BF0103A303,0x1)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0) # Messaging Device Path for IPv4 \
(Load, Net, Pxebc)
Ctrl[253] MNP (MAC=A4-BF-01-03-A3-03, ProtocolType=0x86DD, VlanId=0) # IPv6?
Ctrl[266] MNP (MAC=A4-BF-01-03-A3-03, ProtocolType=0x806, VlanId=0)
Ctrl[27A] PXE Controller # ARP
Ctrl[269] MNP (MAC=A4-BF-01-03-A3-03, ProtocolType=0x800, VlanId=0)
Ctrl[26A] IPv4 (SrcIP=0.0.0.0)
Ctrl[26B] TCPv4 (Not started) # iScsi?
Ctrl[26C] IPv4 (SrcIP=0.0.0.0)
Ctrl[26B] TCPv4 (Not started) # опять? iScsi?
Ctrl[26D] IPv4 (SrcIP=0.0.0.0)
Ctrl[26F] UDPv4 (SrcPort=68, DestPort=67) # Dhcp4
Ctrl[272] PXE Controller # DHCPv4
Ctrl[26E] IPv4 (SrcIP=0.0.0.0)
Ctrl[26F] UDPv4 (SrcPort=68, DestPort=67) # опять?
Ctrl[272] PXE Controller # UefiPxeBcDxe
Ctrl[265] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC(A4BF0103A303,0x1)/VenHw(...) # HiiConfAccess
Ctrl[268] PciRoot(0x0)Pci(0x1C,0x4)/Pci(0x0,0x0)/MAC(A4BF0103A303,0x1)/VenHw(...)) # HiiConfAccess
- dh (вывести рукоятки устройств или драйверов, более 500, можно указать конкретную рукоятку,
"-v" с большими подробностяими, можно указать тип протокола: "dh -p diskio -v -b";
вывести список протоколов: "dh decode" (не работает))
- openinfo номер-рукоятки (вывести информацию об устройстве)
- работа с памятью и другими устройствами:
- dmem адрес-начала размер # вывести содержимое памяти, регистра ввода/вывода ("-IO"), памяти устройства ("-MMIO"),
пространства конфигурации PCI ("-PCI", адрес в формате СегментШинаУстройствоФункцияРегистр),
пространство конфигурации PCIe ("-PCIE", адрес в формате СегментШинаУстройствоФункцияРегистр), числа в шестнадцатеричном формате
- memmap # вывести карту памяти (RT_Code - 1Mib, RT_Data - 1MiB)
- mm адрес [значение] [-w {1|2|4|8}] # посмотреть или заменить значение указанной ширины в памяти ("-MEM"),
постоянной памяти (?) ("-PMEM"), памяти устройства ("-MMIO"), пространстве ввода/вывода ("-IO"),
пространства конфигурации PCI ("-PCI", адрес в формате СегментШинаУстройствоФункцияРегистр),
пространство конфигурации PCIe ("-PCIE", адрес в формате СегментШинаУстройствоФункцияРегистр), числа в шестнадцатеричном формате;
по умолчанию (отменяется "-n") просмотр предлагает в интерактивном режиме изменить последовательность значений (выход - "q")
- pci [шина устройство [функция] [-s сегмент]] # вывести список устройств или информацию об устройстве; "-i" - с интерпретацией
- smbioview [-t тип|-a] # вывести информацию SMBIOS (встроенный неотключаемый делитель страниц, работает не всегда)
- работа с переменными UEFI
- bcfg - переменные менеджера загрузки (такой команды не оказалось, может в следующий раз повезёт), номера шестнадцатеричные:
- bcfg {driver|boot} dump # вывести переменные менеджера загрузки
- bcfg {driver|boot} add номер-источника полный-путь "метка" # добавить источник загрузки
- bcfg {driver|boot} -opt номер-источника {полный-путь-файла-с-параметрами|"параметры загрузчика"}
- bcfg {driver|boot} rm номер-источника # удалить источник загрузки из списка
- bcfg {driver|boot} mv номер-источника новый-номер # передвинуть источник загрузки в списке
- bcfg {driver|boot} mod номер-источника "метка" # изменить описание источника
- bcfg {driver|boot} modf номер-источника полный-путь # изменить имя файла
- dmpstore [-all|-guid GUID] [шаблон-имени-переменной-UEFI] # вывести переменные UEFI, удалить ("-d"), сохранить в файл ("-s имя-файла"),
восстановить из файла ("-l имя-файла")
- set [имя [значение]] # вывести или изменить переменные окружения UEFI Shel (пространство SEnv); "-d" - удалить;
"-v" - не сохранять переменную при перезагрузке
- setvar имя-переменной [-guid GUID] [=[значение]] ... # посмотреть или изменить переменную UEFI, по умолчанию из пространства глобальных переменных;
"-bs","-rt","-nv" - атрибуты создаваемой переменной (изменить атрибуты существующей переменной нельзя);
пустое значение - удаление переменной; значения конкатенируются; типы значений:
"=0x..." или "=0X...", "=H.. или =h..", =S"строка-ASCII", ="строка-ASCII", =L"строка-UCS-2" (терминатор надо добавлять вручную как "=0x0000"),
=P"путь-устройства" (преобразуется из текстового в двоичный вид); не реализовано
- управляющая логика:
- if условие then, else и endif; типы условий:
- [not] exist шаблон-имени-файла
- [/i] [not] строка1 == строка2 # "/i" - без учёта регистра
- [/i] [/s] выражение # выражение составляется из логических операций (not, or и and),
бинарных операций (gt, lt, eq, ne, ge, le, ==, ugt (без знака), ult, uge, ule),
логических функций (isint(), exists(), available(), profile()) и
функций отображения из целого в код ошибки соответствующего типа ifierror(), pierror() и oemerror();
"/i" - без учёта регистра; "/s" - сравнивать как строки
- for и endfor (команды между ними выполняются в цикле по переменной индекса
из элементов множества ("for %буква in список-шаблонов-через-пробел") или последовательности ("for %буква run (начало конец [шаг])"); )
- exit (завершить скрипт или оболочку; "/b" - только текущий скрипт; возвращает указанный код возврата)
- goto (переход на указанную метку)
- shift (сдвиг позиционных параметров влево)
- сеть: ifconfig ("-l" - посмотреть; "-s eth0 dhcp" - настроить; "-r" - всё на DHCP), ifconfig6,
ping [-n количество] [-l размер] [-s исходящий-IP], ping6
- map [шаблон] # "-r" - установить соответствия между путями устройств и файловыми системами ("fs0:") и блочными устройствами ("blk0:");
"-u" - добавить в список новые устройства и удалить отключённые;
без ключей - вывести список соответствий; "-v" - с подробностями; "-d имя" - удалить соответствие;
можно назначить своё имя - "map имя fs0:"
- reset # сброс системы; "-s" - выключение; "-w" - тёплый старт; "-c строка" - холодный старт;
"-fwui" - перезагрузка со входом в настройки (не реализовано)
- sermode (вывод характеристик или настройка последовательного порта)
- vol [имя-файловой-системы] # посмотреть информацию о файловой системе, изменить метку ("-n имя"), удалить метку ("-d")
Secure Boot есть расширение UEFI (UEFI 2.3.1 и новее), призванное уменьшить вероятность загрузки нехорошего кода.
При включении безопасной загрузки производится переход в режим установки (Setup,
8be4df61-93ca-11d2-aa0d-00e098032b8c-SetupMode=1), в котором возможна установка
публичных ключей платформы (PK, самоподписанный сертификат X509v2, заносится изготовителем), после чего производится переход в режим использования (User).
Приватные ключи платформы используются для подписи заявок на изменение базы ключей KEK (Key Exchange Keys, авторизованный пользователь,
подписанный приватным ключом PK сертификат X509v2, в каждом компьютере с логотипом "Windows 8 Ready" д.б. Microsoft Corporation KEK CA).
Приватные ключи KEK используются для подписи заявок на изменение базы ключей DB (доверенные ключи для цифровой подписи приложений,
в каждом компьютере с логотипом "Windows 8 Ready" д.б. Microsoft Windows Production PCA и Microsoft Corporation UEFI CA,
а также обычно добавляются ключи изготовителя для утилит) и DBX (приложения, подписанные этими ключами или имеющие указанный хеш, запрещены).
Рекомендуется проверить PK, KEK и DB при покупке - не поставил ли изготовитель или продавец чего лишнего.
В режиме User возможна загрузка только подписанных приватным ключами DB загрузчиков (приложений), прошивок карт расширений
(OpROM, например, PXE загрузка) и драйверов.
Возможен перевод в режим Custom, в котором возможно добавление пользователем произвольных публичных ключей в DB.
Возврат в режим Setup происходит при удалении ключей платформы (д.б. пункт в меню настройки).
При манипуляции с ключами используется инфраструктура Public Key Infrastructure (PKI),
для подписи используется приватный ключ (тайный), для проверки - соответствующий ему публичный (открытый) ключ.
Microsoft предлагает сервис цифровой подписи посторонних программ (кроме программ под GPLv3) своим ключом Microsoft Corporation UEFI CA,
в частности им подписаны загрузчики shim и PreLoader.
Какова дата завершения сертификата и проверяется ли она (сертификат Microsoft с 2011 по 2026 год)?
Утилита Intel BOOTUTIL64E.EFI не подписана, подозреваю, что другие тоже могут оказаться не подписаны
(iflash32.efi подписана от "Intel(R) PCSD commercial utilities").
Активированность проверяется по значению UEFI переменной /sys/firmware/efi/efivars/8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot:
efivar -p --name 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot
GUID: 8be4df61-93ca-11d2-aa0d-00e098032b8c
Name: "SecureBoot"
Attributes:
Boot Service Access
Runtime Service Access
Value:
00000000 00
bootctl status
System:
Machine ID: f443e7ac8f604c8dbbc3203bc02099d1
Boot ID: ce9c41ed188943f586958cfcf4041714
Secure Boot: disabled
Setup Mode: setup
Selected Firmware Entry:
Title: Direct CentOS 7.4
Partition: /dev/disk/by-partuuid/aa23ecbc-796d-46a1-a852-a3ca1b43c329
File: └─/EFI/centos/vmlinuz-3.10.0-693.5.2.el7.x86_64
Глобальные переменные UEFI:
dbDefault, dbrDefault, dbtDefault, dbxDefault, KEK, KEKDefault, PK, PKDefault, SignatureSupport (список алгоритмов подписей),
SecureBoot, SetupMode (в режиме Setup не требуется аутентификация для изменения переменных безопасной загрузки),
VendorKeys (1 - только ключи поставщика).
Используются алгоритмы хеширования SHA-1 и SHA-256, ассиметричное шифрование RSA2048 и Authenticode (?).
Загрузчик shim (Fedora, RHEL, CentOS, Ubuntu, SUSE, Alt) в режиме User перед запуском приложения проверяет,
что оно подписано или его хеш имеется в NVRAM в базе допустимых MOK. shim воспринимает ключи: встроенные в прошивку (или добавленные пользователем) DB,
встроенные в shim распространителем (в CentOS - "Red Hat Inc.", в Fedora - "Fedora CA"),
переменной UEFI MOK (Machine Owner Key, 605dab50-e046-4300-abb6-3dd810dd8b23-MokListRT, не является частью стандарта UEDI).
shim настроен на загрузку приложения с именем grubx64.efi (необязательно настоящий GRUB2).
Вместе с shim поставляются подписанные распространителем MokManager.efi (управление базой MOK, mmx64.efi) и fbx64.efi (драйвер frame buffer),
который вызывается при неудачной проверке подписи загружаемого
приложения и позволяет добавить X509v2 сертификат из файла или хеш в ESP в базу MOK (выбор из найденных им разделов, затем выбор файла)
и продолжить загрузку. Загруженное приложение в зависмости от возможности может загружать всё подряд,
загружать подписанные PK приложения, загружать подписанные MOK приложения (настоящий GRUB2 обращается к shim).
Пример процесса загрузки для CentOS 7.
Менеджер загрузки UEFI не обращается к MOK.
Загрузчик PreLoader вычисляет хеш загружаемого приложения loader.efi и проверяет её наличие в базе допустимых в NVRAM,
не умеет работать с подписями, утилита работы с базой - HashTool.efi. Обеспечивает доступ любых UEFI приложений к MOK.
Утилита mokutil (пакет mokutil) позволяет работать с базой MOK.
Ключи действия mokutil:
- --list-enrolled # получить список установленных публичных ключей (MokListRT, 605dab50-e046-4300-abb6-3dd810dd8b23-MokListRT);
на платформе Intel обнаружился протухший ключ от Red Hat
(то ли Intel так поставляет, то ли поставщик, то ли результат установки CentOS 7 в режиме UEFI?)
- --import файл # сформировать из файла в формате DER запрос на добавление, обрабатывается shim при следующей загрузке (MokNew)
- --list-new # получить список ключей, ожидающих установку
- --revoke-import
- --delete # сформировать из файла в формате DER запрос на удаление, обрабатывается shim при следующей загрузке (MokDel)
- --list-delete # получить список ключей, ожидающих удаление
- --revoke-delete
- --export
- --password ... # установить пароль (MokPW)
- --clear-password # сбросить пароль (MokPW)
- --sb-state # показать состояние Secure Boot
- --test-key файл # включён ли ключ в базу MOK
- --reset # сбросить MOK
- --ignore-db # указать shim не использовать ключи из MOK для проверки подписи
- --use-db # по умолчанию
- --set-verbosity {true|false} # управлять болтливостью shim
- --pk # получить список ключей платформы
- --kek # получить список ключей KEK
- --db # получить список подписей или хешей приложений, которые могут быть загружены неподписанными
- --dbx # получить чёрный список подписей или хешей приложений, которые не могут быть загружены
Опции mokutil:
- --disable-validation # не проверять в shim
- --enrolled-validation # проверять в shim
- --mokx # работать с чёрным списком вместо белого
- --root-pw # использовать хеш пароля root
Регистрация ключа RedHat для бета версий:
- отключить UEFI Secure Boot
- установить Linux
- mokutil --import /lib/modules/$(uname -r)/kernel-signing-ca.cer # /usr/share/doc/kernel-keys/3.10.0-693.5.2.el7/kernel-signing-ca.cer?
- выбрать и ввести пароль
- перезагрузиться, включив UEFI Secure Boot
- подтвердить импорт сертификата и ввести пароль
- любые ядра, подписанные ключом RedHat для бета версий будут загружаться, пока сертификат не будет удалён
Удаление импортированных сертификатов:
- mokutil --reset
- перезагрузиться
- подтвердить удаление сертификата и ввести пароль
Утилита pesign (пакет pesign) позволяет подписывать UEFI приложения, примеры подписанных приложений
(информации негусто - сертификат отсоединён, надо его где-то взять и запихнуть в базу /etc/pki/pesign)
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/BOOT/BOOTX64.EFI # shimx64.efi
---------------------------------------------
certificate address is 0x7f327a7e9580
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Microsoft Windows UEFI Driver Publisher
No signer email address.
No signing time included.
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/centos/shim.efi
---------------------------------------------
certificate address is 0x7fb1d01c4580
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Microsoft Windows UEFI Driver Publisher
No signer email address.
No signing time included.
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/centos/shimx64-centos.efi
---------------------------------------------
certificate address is 0x7f04eef32b68
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Red Hat Inc.
No signer email address.
Signing time: Fri Sep 01, 2017
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/centos/mmx64.efi
---------------------------------------------
certificate address is 0x7fdb62337568
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Red Hat Inc.
No signer email address.
Signing time: Fri Sep 01, 2017
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/BOOT/fbx64.efi
---------------------------------------------
certificate address is 0x7fcc67293550
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Red Hat Inc.
No signer email address.
Signing time: Fri Sep 01, 2017
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/centos/grubx64.efi
---------------------------------------------
certificate address is 0x7f4c89c5bc08
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Red Hat Inc.
No signer email address.
Signing time: Sat Oct 21, 2017
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/centos/vmlinuz-3.10.0-693.5.2.el7.x86_64
---------------------------------------------
certificate address is 0x7f034e7f52e8
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Red Hat Inc.
No signer email address.
Signing time: Fri Oct 20, 2017
There were certs or crls included.
pesign --verbose --show-signature --signature-number=0 --in=/boot/efi/EFI/memtest/BOOTX64.MEMTEST86-74.EFI
---------------------------------------------
certificate address is 0x7f36f6ccb1a8
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Microsoft Windows UEFI Driver Publisher
No signer email address.
No signing time included.
There were certs or crls included.
Ядро импортирует ключи из базы UEFI:
keyctl list %:.system_keyring
3 keys in keyring:
225464260: --alswrv 0 0 asymmetric: CentOS Linux kpatch signing key: ea0413152cde1d98ebdca3fe6f0230904c9ef717
171859011: --alswrv 0 0 asymmetric: CentOS Linux kernel signing key: c757a9fbbd0d82c9e54052029a0908d17cf1adc7
718091548: --alswrv 0 0 asymmetric: CentOS Linux Driver update signing key: 7f421ee0ab69461574bb358861dbe77762a4201b
при включённом Secure Boot д.б. аппаратные ключи
6 keys in keyring:
...asymmetric: Red Hat Enterprise Linux Driver Update Program (key 3): bf57f3e87...
...asymmetric: Red Hat Secure Boot (CA key 1): 4016841644ce3a810408050766e8f8a29...
...asymmetric: Microsoft Corporation UEFI CA 2011: 13adbf4309bd82709c8cd54f316ed...
...asymmetric: Microsoft Windows Production PCA 2011: a92902398e16c49778cd90f99e...
...asymmetric: Red Hat Enterprise Linux kernel signing key: 4249689eefc77e95880b...
...asymmetric: Red Hat Enterprise Linux kpatch signing key: 4d38fd864ebe18c5f0b7...
Утилита sbsign
также позволяет подписывать UEFI приложения (не нашёл в дистрибутиве, совпадение имени утилиты - keytool - с Java).
KeyTool.efi позволяет в режиме Setup (возможног придётся очистить все базы Secure Boot) управлять ключами PK, KEK, DB и MOK.
Коллекция сертификатов
(microsoft-pca-public.der - этим ключом Microsoft подписывает свои загрузчики,
microsoft-uefica-public.der - этим ключом Microsoft подписывает чужие приложения).
Проблемы реализации Secure Boot с помощью поставляемого в дистрибутиве shim
(метод борьбы):
- shim грузит любое UEFI приложение, подписанное ключом дистрибьютора
- /boot и initramfs в нём - не подписываются и не шифруются
- в подписанный GRUB не встроили криптографические модули, подгружать модули GRUB-у запрещено (можно пересобрать самому с нужными модулями,
но и подписывать придётся самому)
- конфигурационный файл GRUB не подписывается, даётся доступ к консоли (можно встроить grub.cfg в GRUB и установить пароль)
А ещё есть Secure Boot (Verified Boot, ранее PFAT) от Intel (2012),
переименованный в Intel Boot Guard (2013) - программа проверки подписи прошивки
перед её запуском.
- Unified Extensible Firmware Interface (UEFI) Specification, Version 2.7 Errata A, August 2017, 2500 страниц
- UEFI Shell Specification
- UEFI Platform Initialization Specification(здесь же описаны SMM, SMBus, SMBIOS, IDE, S3,
PCI Host Bridge и PCI, Super I/O и ISA Host Controller, CPU I/O, I2C, SPI, а рядом лежит описание ACPI и TCG (TPM))
- UEFI Platform Initialization Distribution Packaging Specification
- Fedora 18. UEFI Secure Boot Guide
- UEFI Booting 64-bit Redhat Enterprise Linux 6
- Arch Linux: Unified Extensible Firmware Interface
- Managing EFI Boot Loaders for Linux
- Arch Linux: Secure Boot
- The EFI boot process (старый текст)
- Беседы о UEFI
- EFI Architecture (очень старый текст)
- UEFI boot: how does that actually work, then?
- altlinux: UEFI SecureBoot mini-HOWTO
(процедура получения подписанного Microsoft shim)
- SecureBoot: Testing Secure Boot (Ubuntu)
- Используем Secure Boot в Linux на всю катушку (shim как угроза безопасности)
- серия статей о безопасности UEFI
(в частности, Укрощаем UEFI SecureBoot)
- Beyond BIOS. Developing with the Unified Extensible Firmware Interface. Second Edition. Vincent Zimmer, Michael Rothman, Suresh Marisetty.
Intel Press 2010 (книге нужен редактор, авторы гнали объём)
- NERF (Linux вместо UEFI, также разоружены ME и SMM)
- The Boot Loader Specification
(структура файлов для сосуществования нескольких ОС; каков статус стандарта, запрещающего /boot/efi?)
|
Bog BOS: hardware: EFI, UEFI и PI
|
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru