@ Карта сайта News Автора!

Bog BOS: hardware:  EFI, UEFI и PI

Последнее изменение файла: 2024.09.24
Скопировано с www.bog.pp.ru: 2024.11.21

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:

В качестве кодировки символов используется 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, поэтому для ориентировки в возможностях реализации важно знать, что было добавлено в очередной версии:

Формат исполняемых образов UEFI

Заголовок файлов UEFI исполняемых образов (драйверы, приложения) д.б. оформлен в формате подмножества PE32+ (PE/COFF с 64-битным расширением, Microsoft Portable Executable and Common Object File Format), в котором указывается архитектура (м.б. EBC) и тип файла (pre-OS agent):

Образы могут храниться на материнской плате (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, делится на фазы:

Предусмотрены следующие программные абстракции (Architectural Protocol): безопасность, ЦП, метроном, таймер, BDS (Boot Device Select), сторожевой таймер, переменные UEFI, запись переменных UEFI, сброс, монотонный счётчик, часы реального времени, коды состояния, runtime (обеспечивает переход сервисов из физического режима памяти к виртуальному). Драйверы обеспечивают сервисы для других модулей с помощью протоколов (протокол определяется в спецификации UEFI); могут быть написаны на EBC или с использованием родной системы команд.

Драйверы делятся на:

Обработка событий (событие м.б. в 2 состояниях - ожидание и сигнальное):

Прерываний от оборудования нет (кроме single-timer interrupt?), только опрос (polling). Извещение с высоким приоритетом прерывает выполнение извещения с низким приоритетом. Приоритет TPL_HIGH_LEVEL блокирует даже прерывания от таймера. Типы событий:

После 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 описывает состояние после завершения инициализации и включает следующие понятия:

Протокол локации устройства (Device Path)

Device Path - протокол локации устройства (двоичный) EFI_DEVICE_PATH_PROTOCOL, разрабатывался с учётом ACPI. Имеются протоколы преобразования в текстовый формат EFI_DEVICE_PATH_TO_TEXT_PROTOCOL и обратно EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL. Путь (список путей) состоит из неограниченной последовательности узлов, в текстовом формате узлы представляются в виде функции со списком аргументов через запятую, узлы разделяются символом "/".

Узлы бывают следующих типов (если тип нераспознан, то "Path(тип,подтип,данные)"):

  1. HardwarePath(подтип,данные) - физическое подключение (MMIO, IO), шина предоставляет ресурсы в домене когерентности (пространство памяти, IO, пространство конфигурации PCI), подтипы:
    1. 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)"
    2. PcCard - номер функции (нумеруются с 0)
    3. MemoryMapped - тип (MMIO, IO Port и т.д.), начало, конец
    4. VenHW - GUID поставщика, данные
    5. Ctrl - номер контроллера
    6. BMC - тип интерфейса (1 - KCS, 2 - SMIC, 3 - Block Transfer), базовый адрес BMC в памяти или IO
  2. AcpiPath(подтип,данные) - ACPI устройство, идентификаторы PnP оборудования (_HID) и уникальные идентификаторы (_UID, серийный номер), используется при отсутствии возможности Hardware Device Path (корень PCI шины), подтипы:
    1. 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 - номер порта)
    2. AcpiEx - указывается _HID, _UID и _CID в двоичном или текстовом (ASCII) формате
    3. AcpiAdr - атрибуты видеовывода - указывается _ADR (таблица B-2 ACPI 3.0); также используется для NVDIMM (NFIT, ACPI 6.0)
  3. Messaging Device Path - Msg(подтип,данные) - не координатные методы поиска устройств, шина потребляет ресурсы домена когерентности и предоставляет ресурсы вне домена когерентности
    1. Ata(контроллер,устройство,LUN) - ATAPI - указывается первичный/вторичный, главный/подчинённый, например, "PciRoot(0)/PCI(7,0)/ATA(Primary,Master,0)"
    2. SCSI - указывается номер исполнителя и LUN, например, "PciRoot(0)/PCI(7,0)/SCSI(2,0)"; для многоканального контроллера за мостом: "PciRoot(0)/PCI(5,0)/PCI(7,0)/Ctrl(3)/SCSI(2,0)"
    3. Fibre - FibreChannel - указывается WWN и LUN, например, "PciRoot(0)/PCI(8,0)/Fibre(0x21000050cc205ed4,0)"
    4. I1394 - Firewire (IEEE 1394) - указывается GUID в терминах IEEE 1394
    5. USB - указывается номер порта и номер интерфейса, например: "PciRoot(0x0)/Pci(0x1d,0x0)/USB(1,0)/USB(3,0)"
    6. I2O - указывается целевой идентификатор (TID)
    7. InfiniBand - указывается GID удалённого порта фабрики, постоянный адрес удалённого устройства и др.
    8. 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)"; сложности с двухпортовыми устройствами
    9. MAC адрес - указывается MAC адрес и тип сети, напимер: "PciRoot(0x0)/Pci(0x1c,0x4)/Pci(0x0,0x0)/MAC(a4bf010603c4,1)"
    10. IPv4 - указывается местный адрес, удалённый адрес, локальный порт, удалённый порт, сетевой протокол (UDP/TCP), адрес получен по DHCP или статически, адрес шлюза, маска подсети, например: "PciRoot(0)/Pci(19,0)/Mac(001320F5FA77,0x01)/IPv4(192.168.0.100,TCP,Static,192.168.0.1)"
    11. IPv6 - указывается местный адрес, удалённый адрес, локальный порт, удалённый порт, сетевой протокол (UDP/TCP), адрес получен статически или с помощью автоматической конфигурации, длина префикса, адрес шлюза
    12. UART - указываются параметры последовательного порта, например: "PciRoot(0)/Pci(0x1f,0)/ACPI(PNP0501,0)/UART(115200,N,8,1)
    13. UsbClass - указывается идентификатор изготовителя, идентификатор продукта, класс, подкласс, код протокола; может использоваться в сокращённой форме (без указания начала последовательности узлов и/или с использованием шаблона 0xFF в любых позициях, например (любая клавиатура): "UsbHID()")
    14. UsbWwid - указывается идентификатор изготовителя, идентификатор продукта, номер интерфейса, последние 64 бита серийного номера в UTF-16; может использоваться в сокращённой форме (без указания начала последовательности узлов)
    15. Unit - указывается LUN
    16. Sata - указывается номер порта HBA и номер порта мультипликатора портов (0xFFFF при отсутствии мультипликатора) и LUN например: "PciRoot(0x0)/Pci(0x1f,0x2)/Sata(1,0,0)"
    17. 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)"
    18. VLAN - указывается идентификатор VLAN
    19. FibreEx - FibreChannel расширенный - указывается WWN и LUN в виде массива байт (в FC принят порядок следования байт big endian, в UEFI - liitle endian)
    20. SasEx - SAS расширенный (в виде массивов, чтобы избежать борьбы маленьких и больших индейцев) - указывается SAS адрес исполнителя, LUN, топология и порт исполнителя
    21. NVMe - NVM Express - указывается идентификатор пространства имён (NSID), IEEE Extended Unique Identifier (EUI-64)
    22. URI - указывается URI
    23. UFS (Universal Flash Storage) - указывается PUN и LUN
    24. SD - Secure Digital - указывается номер слота
    25. Bluetooth - указывается адрес Bluetooth
    26. Wi-Fi - указывается SSID
    27. eMMC - указывается номер слота
    28. BluetoothLE - указывается адрес Bluetooth и тип адреса
    29. DNS - указываются адреса DNS серверов
  4. Media Device Path - MediaPath(подтип,данные) - внутренности устройства
    1. HD - указываются номер раздела (0 - весь диск), формат таблицы разделов (1 - MBR, 2 - GPT), тип уникального идентификатора раздела и уникальный идентификатор раздела (GUID для GPT), начальный сектор раздела (LBA), размер раздела; может использоваться в сокращённой форме (GUID достаточно для поиска), например: "HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)"
    2. CDROM (ISO-9660 и El Torito) (no emulation, идентификатор платформы 0xEF) или UDF 2.0 (UDF Bridge) - указываются номер загрузочной записи в каталоге, относительный LBA начала раздела, размер раздела
    3. VenMedia - указывается GUID поставщика и пр. параметры
    4. File - полное имя файла в стандарте системного раздела EFI, можно разбивать на несколько узлов, добавление '\' между узлами и удаление лишних '\' производится автоматически; может использоваться в сокращённой форме, например: "HD(2,GPT,aa23ecbc-796d-46a1-a852-a3ca1b43c329,0x1f4800,0x64000)/File(\EFI\centos\shimx64.efi)"
    5. Media - указывается GUID протокола
    6. PI Firmware File, например: "FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)"
    7. PI Firmware Volume, например: "FvVol(cdbb7b35-6833-4ed6-9ab2-57d2acddf6f0)"
    8. Offset (смещение от начала устройства) - указывюется смещение первого байта и смещение последнего байта
    9. 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()), номер экземпляра
  5. BIOS Boot Specification Device Path - BbsPath(подтип,данные) - для загрузки в режиме BIOS
    1. BBS (BIOS Boot Specification Version 1.01) - указываются тип устройства (01h - флоппи, 02h - НЖМД, 03h - CD-ROM, 04h - PCMCIA, 05h - USB, 06h - встроенная сеть, 80h - BEV (Bootstrap Entry Vector)), текст описания устройства (ASCII), флаг состояния
  6. End of Hardware Device Path - конец цепочки, подтипы:

Для создания и манипуляции путями используется EFI_DEVICE_PATH_UTILITIES_PROTOCOL (узнать размер, сделать копию, добавить путь, добавить узел, создать узел, добавить путь в список, извлечь путь из списка).

Текстовая консоль

Протоколы поддержки текстовой консоли (устройства ConIn, ConOut, ConErr) используются для ввода и вывода текстовой информации во время работы сервисов загрузки, нет поддержки устройств указания и вывода битовых карт:

Приведены примеры для 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

Переменные EFI (идентифицируются по GUID производителя и имени; каждый изготовитель прошивки имеет свой физический формат хранения: Intel - VSS, AMI - NVAR)

Переменные RT без NV во время работы ОС можно только читать.

Глобальные переменные (GUID 8be4df61-93ca-11d2-aa0d-00e098032b8c):

Почти все настройки хранятся в переменной с именем 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.

Переменные EFI и Linux

Доступны ОС при загрузке в режиме UEFI (/usr/share/doc/kernel-doc-*/Documentation/filesystems/efivarfs.txt)

Если переменные недоступны, то вы загрузились в режиме BIOS.

Для работы с переменными EFI можно использовать утилиту efivar (пакеты efivar-libs.x86_64, efivar.x86_64, efivar-devel.x86_64). Ключи:

Для платформы 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.

Загрузчик должен иметь возможность:

Для нормальной загрузки с блочного устройства в режиме 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 знака, без подавления незначащих нулей):

Описание загрузчиков отделено от их физического расположения (перенести диск недостаточно - надо ещё заполнить переменные менеджера загрузки).

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

Типы загрузочных устройств (если имя файла не указано, то выбирается файл по умолчанию - "\EFI\BOOT\BOOTx64.EFI"):

Некоторые реализации предлагают меню источников загрузки по нажатию некоторой кнопки после включения (F6? F11? F12? для платформ Intel).

Если при загрузке не получается запустить утилиту настройки (Setup, кнопки F2, Del, Fn+F2 и др.), то можно попробовать отсоединить все устройства хранения перед перезагрузкой и зайдя в Setup отключить быструю загрузку.

Настройка переменных производится средствами встроенного менеджера загрузки или командой bcfg UEFI Shell.

Настройка менеджера загрузки с помощью efibootmgr

Утилита 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" первым в списке):

Установка memtest86 от PassMark (free, 7.4, ISO версия) на сервер с UEFI для прямой загрузки:

Загрузка Linux в режиме 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 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, и он д.б. в начале строки):

Формально поддержка UEFI и GPT в RHEL 7 имеется и улучшается (например, в RHEL 7.2 в kickstart) была добавлена команда reqpart для создания ESP раздела), но напильник понадобится (установка на md вручную, memtest86+ не работает в UEFI.

Загрузка PXE UEFI

Загрузка с использованием PXE в UEFI перенесена в статью по PXE.

Установка CentOS 7.4 с PXE загрузкой

UEFI клиент PXE при DHCP запросе взводит бит требования широковещательного ответа и этот широковещательный ответ не всегда доходит до него (VLAN со внутренней маршрутизацией, DHCP клиент CentOS 7.4 работает без проблем). Пришлось на время установки отключать DHCP Relay и ставить локальный DHCP сервер.

Быстрая загрузка

Отказ от инициализации 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), так и во время выполнения ОС, поэтому должны быть готовы как к физическому режиму работы памяти, так и к виртуальному. Все сервисы неблокирующие (имеются ограничения на последовательность вызовов, которые ОС должна соблюдать самостоятельно) и могут выполняться с включёнными прерываниями (при необходимости самостоятельно отключают прерывания), память резервируется и не используется ОС, используемые аппаратные ресурсы описываются и ОС должна согласовывать их использование или не использовать сервисы периода выполнения вовсе.

Минимальный набор сервисов:

Для 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 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 появились профили):

Имя приложения или скрипта для запуска указывается в качестве параметра shell.efi, после чего можно задать параметры приложения. При этом подразумевается ключ '-nostartup' (см. ниже). Все имена и параметры задаются в UCS-2. Опции запуска (перед параметром):

При инициализации оболочки пути устройств (device path) отображаются на имена файловых системы (fsX:) и блочные устройства (blkX:), читается список синонимов и переменных окружения из ПЗУ, в переменную окружения profiles читается список профилей (не обнаружен), ищется (сначала в каталоге запуска самого shell.efi, затем в списке из переменной окружения PATH (".")) и запускается startup.nsh (см. -startup и -nostartup).

Имена команд, файлов, переменных и пр. нечувствительны к регистру и разделяются пробелами и табуляциями. Поддерживаются синонимы команд (alias). Подстановка значений переменных окружения осуществляется символами '%' вокруг имени переменной, позиционных переменных (от 0 - полное имя скрипта до 9) - символом '%' перед номером позиции, индексных переменных - символом '%' перед буквой создаваемого командой for индекса. Комментарии начинаются символом '#'. Метки начинаются символом ':'. Специальные символы (включая пробел) окружаются двойными кавычками (подстановка значений переменных не отменяется). Специальное значение символа блокируется символом '^' даже внутри кавычек. Шаблоны имён файлов задаются с использованием символов '*' (любое число символов), '?' (1 любой символ, '[' и ']' (1 символ из перечисленных в скобках) в "некоторых местах" ('^' не действует). Символ '@' в начале строки отключает вывод текста команды на консоль ("echo -off" отключает для всех следующих команд).

Перенаправление ввода и/или вывода в файл или переменную окружения или другую команду, специальные имена файлов NUL или NULL никуда не пишут:

Имена переменных окружения чувствительны к регистру (в реализации версии 1 от Intel - нет). Могут храниться как переменные UEFI в NVRAM (под именем "SEnv:имя", атрибуты - NV+BS; GUID - ?) или пропадать при перезагрузке ("set -v имя значение", атрибуты - BS). Некоторые имена зарезервированы:

Переменные 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"):

Команды:

UEFI Secure Boot

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:

Опции mokutil:

Регистрация ключа RedHat для бета версий:

  1. отключить UEFI Secure Boot
  2. установить Linux
  3. 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?
  4. выбрать и ввести пароль
  5. перезагрузиться, включив UEFI Secure Boot
  6. подтвердить импорт сертификата и ввести пароль
  7. любые ядра, подписанные ключом RedHat для бета версий будут загружаться, пока сертификат не будет удалён

Удаление импортированных сертификатов:

  1. mokutil --reset
  2. перезагрузиться
  3. подтвердить удаление сертификата и ввести пароль

Утилита 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 (метод борьбы):

А ещё есть Secure Boot (Verified Boot, ранее PFAT) от Intel (2012), переименованный в Intel Boot Guard (2013) - программа проверки подписи прошивки перед её запуском.

Ссылки

@ Карта сайта News Автора!

Bog BOS: hardware:  EFI, UEFI и PI



Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru