#arm64 #edk2
Вопрос:
Я новичок в EDK2.
Для переноса прошивки ekd2 на новую платформу ARM64 было бы неплохо сначала получить минимальный порт edk2, который может запускать, по крайней мере, оболочку UEFI, улучшения могут добавляться постепенно на основе этого.
Кажется, что первый шаг довольно крутой, например, как определить минимальный набор «элементов» в .dsc
.fdf
файле и для платформы? В моем случае я хотел бы создать .fd
для своей платформы и рассматривать ее как BL33 из TF-A, фактически я хотел бы создать прошивку edk2 для замены u-boot.
Кажется, что такое руководство трудно найти в Интернете. Я нашел старую версию edk2, которая содержит некоторые инструкции, но, по-видимому, они устарели (не существуют в последней master
ветке, хотя их можно найти в ветках UDK, таких как UDK2014
), и я не уверен, почему эти документы удалены из master
ветки.
В настоящее время я могу создавать .fd
для FVP ( edk2-platforms/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
), и кажется, что выходные данные сборки FVP_AARCH64_EFI.fd
должны обрабатываться как BL33. Теоретически это может быть прототипом для моей новой платформы ARM64, но для меня это слишком сложно для начала: размер прошивки составляет около 2,5 Мбайт (по сравнению с 500 КБ u-boot), поэтому я думаю, что это далеко не «минимальная» версия. но трудно понять, какие функции следует удалить (и как).
Мне интересно, есть ли подробное руководство по такой теме…
Ответ №1:
После 1 месяца проб и ошибок сегодня мне удалось перенести мою платформу ARM64 в среду оболочки UEFI. Я рассматриваю это как свою первую веху на пути к EDK2. Ниже я попытаюсь обобщить шаги, которые я предпринял до сих пор, в качестве предварительного ответа на мой вопрос выше. Руководство / исправления / комментарии приветствуются.
- Ознакомьтесь со спецификациями UEFI / PI и реализацией EDK2, прочитав книги / спецификации / статьи. Ну, спецификации UEFI / PI занимают тысячи страниц…с чего начать? Мой основной список чтения:
- «Помимо Bios — разработка с использованием унифицированного расширяемого интерфейса прошивки», 3-е издание, Винсент Циммер и др. Как объяснили авторы, книга представляет собой своего рода высокоуровневое резюме спецификаций на тысячи страниц. И я нахожу, что книга хорошо организована для новичка, чтобы ознакомиться с различными концепциями, связанными с UEFI. Основная цель 1-го чтения (перед началом работы с кодовой базой edk2) — ознакомиться с концепциями и архитектурными идеями, а не с деталями. С соответствующими разделами необходимо ознакомиться позже при чтении реализаций EDK2.
- Спецификации EDK2, в том числе:
- Руководство пользователя EDKII
- Спецификация сборки EDKII
- Спецификация файла EDKII DSC / FDF / DEC / INF
- Различные статьи в Интернете…
- Получите эталонную платформу, которая может корректно загружать образ FD, созданный из последнего исходного кода EDK2, и немного поиграйте с менеджером загрузки и оболочкой. В моем случае я выбрал RPi4B. Для меня это очень важно, поскольку эталонная платформа служит поручнем в течение всего процесса, что всякий раз, когда я сталкиваюсь с ошибками или у меня возникают сомнения, я проверяю источник / журнал эталонной платформы. Это решает большинство проблем, с которыми я столкнулся. Кстати, всегда генерируйте «журнал сборки» и «отчет о сборке» как для справочной платформы, так и для целевой платформы, поскольку два файла содержат очень подробную информацию для сравнения и проверки. Обратитесь к спецификации сборки EDK2 о том, как сгенерировать эти два файла во время сборки.
Я использую следующий скрипт для сборки для платформы RPi4B:
#!/bin/bash # https://github.com/tianocore/edk2-platforms#how-to-build-linux-environment export WORKSPACE=/home/bruin/work/tianocore export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi pushd $WORKSPACE rm -rf ./Build/RPi4 source edk2/edksetup.sh echo "Building BaseTools..." make -C edk2/BaseTools all #sudo apt install acpica-tools # iasl # pip install antlr4-python3-runtime # -Y EXECUTION_ORDER echo "Building firmware for Pi4B..." GCC5_AARCH64_PREFIX=aarch64-none-linux-gnu- build -n 4 -a AARCH64 -p Platform/RaspberryPi/RPi4/RPi4.dsc -t GCC5 -b NOOPT -v -d 9 -j RPi4-build.log -y RPi4-build-report.txt -Y PCD -Y LIBRARY -Y DEPEX -Y HASH -Y BUILD_FLAGS -Y FLASH -Y FIXED_ADDRESS -Y EXECUTION_ORDER all
How to use the build result
RPI_EFI.fd
on RPi4B, consult the following:edk2-platforms/Platform/RaspberryPi/RPi4/Readme.md
readme.md
inside https://github.com/pftf/RPi4/releases/download/v1.17/RPi4_UEFI_Firmware_v1.32.zip. btw, I need to replace the originalstart4.elf
andfixup4.dat
with the ones in the zip file, otherwise, the boot of RPi4 will fail, complaining something like below:RpiFirmwareGetClockRate: Get Clock Rate return: ClockRate=0 ClockId=C ASSERT [ArasanMMCHost] /home/bruin/work/tianocore/edk2-platforms/Platform/RaspberryPi/ Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.c(263): BaseFrequency != 0
- Стоит проанализировать
RPI_EFI.fd
содержимое в некоторой степени, используя некоторые утилиты UEFI. Я в основном использую версию GUIUEFITool
sudo apt install uefitool uefitool-cli
. Также доступны другие инструменты. АнотомияRPI_EFI.fd
помогает при чтении спецификаций сборки EDK2 для проверки понимания концепций.- Одним из особых аспектов
RPI_EFI.fd
является то, что 1-й 128K являетсяbl31.bin
двоичным из ATF. Я предполагаю, что это связано со специальными методами настройки подключения при загрузке для RPi. Для моей платформы мне не нужна такая упаковка, мне нужно только создать образ UEFIMY.fd
, который обрабатывается как образ BL33 и упаковываетсяfip.bin
вместе с образами BL2 и BL31 с помощью скрипта сборки ATF. - Еще один аспект, на который следует обратить внимание, — это «вектор сброса» в начале
.fd
файла. Это связано с точкой входа образа UEFI (и точкой входа каждого модуля EDK2), а также интерпретациейBL
инструкции для AArch64. В принципе, это можно резюмировать следующим образом:
Первый
[Components]
изRPI_EFI.fd
ArmPlatformPkg/PrePi/PeiUniCore.inf
них — это ofMODULE_TYPE = SEC
.- Что это за компонент: это первый (и единственный)
SEC
модуль (безопасности) в RPi4. ЧтоPrePi
Pei
означает название и?
… спецификация PI не привязана к edk2 PEIMS, и я не вижу, где модули EDKII PEI в настоящее время являются единственной «признанной» кремниевой средой инициализации. Само дерево edk2, похоже, содержит платформы, которые вообще не используют набор модулей edk2 PEI, но (IIRC) переходят от SEC к DXE. Я считаю, что «ArmPlatformPkg / PrePi» и «ArmVirtPkg / PrePi» связаны с этим.
— https://listman.redhat.com/archives/edk2-devel-archive/2020-November/msg00021.html
- Его точка входа: все компоненты UEFI имеют одинаковую точку входа (
_ModuleEntryPoint
).- Под «компонентом» подразумевается либо драйвер UEFI, либо приложение UEFI, оба являются исполняемыми файлами PE32, обычно с суффиксом
.efi
. - Файлы
.efi
преобразуются из исполняемых файлов ELF (.dll
) с помощьюGenFw
инструмента: изменение заголовков файлов. - Чтобы убедиться, что «точка входа всех компонентов»
_ModuleEntryPoint
:- Проверьте
.dll
командную строку генерации в build report (build -y <BUILD_REPORT_FILE>
), у нас есть два флага"aarch64-none-linux-gnu-gcc" -o xxx.dll -u _ModuleEntryPoint -Wl,-e,_ModuleEntryPoint ...
:-u
:gcc --help -v|grep "undefined SYMBOL"
дает-u SYMBOL --undefined SYMBOL: star with undefined reference to SYMBOL
.Wl,-e
:ld --help|grep "entry"
дает-e ADDRESS, --entry ADDRESS Set start address
.
- Проверьте все
.dll
файлы, которыеEntry point address == _ModuleEntryPoint
:find . -type f -name "*.dll" -exec sh -c "readelf -a {} |grep -E 'Entry point address|_ModuleEntryPoint'" ;
- Проверьте
- Под «компонентом» подразумевается либо драйвер UEFI, либо приложение UEFI, оба являются исполняемыми файлами PE32, обычно с суффиксом
- Его точка входа — это точка входа всего образа UEFI FD (т. Е. От
bl33_base_addr
перехода к этому_ModuleEntryPoint
):
Топология файла прошивки UEFI
Файл прошивки UEFI (на самом деле файл прошивки UEFI — FD Device — FD) представляет собой набор двоичных файлов UEFI, инкапсулированных в один образ. Формат этого изображения определяется спецификацией инициализации платформы, том 3. В основе этого файла находится векторная таблица. Инструкция перехода ‘BL’ в основании firwmare (местоположение записи сброса в векторной таблице) перейдет к первому модулю ‘SEC’ образа прошивки UEFI.
— https://github.com/lzeng14/tianocore/wiki/ArmPkg-Debugging
- Для проверки приведенных выше утверждений:
- Разберите вектор сброса (т. Е. 1-е слово) сгенерированного
.FD
(мы получили смещение =0x360
):$ xxd -l 4 -e TEST.fd <== dump 4 bytes in little endian 00000000: 140000d8 <== BL {PC} (0xd8<<2); offset=0x360
- Проверьте точку входа в
.dll
(мы получили смещение =0x240
):$ aarch64-none-elf-objdump -t ArmPlatformPrePiUniCore.dll|grep _ModuleEntryPoint 0000000000000240 g F .text 0000000000000000 _ModuleEntryPoint $ readelf -h ArmPlatformPrePiUniCore.dll|grep Entry Entry point address: 0x240
- Сравните содержимое двух файлов с разным смещением (мы получили идентичный контент):
$ xxd -s 0x360 -l 64 TEST.fd <== skip 0x360 bytes, dump 64 bytes 00000360: 901e 0094 050a 0094 ea03 00aa a1cd 0a58 ...............X 00000370: 0200 e0d2 2200 c0f2 0240 a0f2 0200 80f2 ...."....@...... 00000380: c303 a0d2 e3ff 9ff2 6304 00d1 6300 028b ........c...c... 00000390: 0400 a1d2 0400 80f2 2000 03eb 8400 0054 ........ ......T $ xxd -s 0x240 -l 64 ArmPlatformPrePiUniCore.dll <== skip 0x240 bytes 00000240: 901e 0094 050a 0094 ea03 00aa a1cd 0a58 ...............X 00000250: 0200 e0d2 2200 c0f2 0240 a0f2 0200 80f2 ...."....@...... 00000260: c303 a0d2 e3ff 9ff2 6304 00d1 6300 028b ........c...c... 00000270: 0400 a1d2 0400 80f2 2000 03eb 8400 0054 ........ ......T
- Разберите вектор сброса (т. Е. 1-е слово) сгенерированного
- Для проверки приведенных выше утверждений:
- Одним из особых аспектов
- Подготовьте пустой pkg и сделайте так, чтобы он был собран нормально. Основная цель — выполнить некоторые упражнения с системой сборки EDK2 и использовать пустой pkg в качестве отправной точки для новой платформы.
- Сделайте копию
RaspberryPi.dec
, измените всеgRaspberry
наgMyPlatform
. - Сделайте копию
RPi4.dsc
иRPi4.fdf
и закомментируйте все содержимое вDSC
FDF
файле and. - Замените все идентификаторы GUID в
DSC
/FDF
/DEC
files, сгенерировав новые с помощью онлайн-генератора идентификаторов guid. - Обратите внимание, что PCD объявляются в
DEC
файлах, а файлы DEC обозначаются модулями (INF
файлами). Поскольку пустой пакет не содержит модуля, в нем не будет доступно определение PCDFDF
. Итак, для успешной сборки пустого пакета нам нужно закомментировать все ссылки PCDFDF
. - Команда
NOOPT
сборки дляMyPlatform
как показано ниже:#!/bin/bash export WORKSPACE=/home/bruin/work/tianocore export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi pushd $WORKSPACE source edk2/edksetup.sh echo "Building BaseTools..." make -C edk2/BaseTools all echo "Building UEFI firmware for MyPlatform..." GCC5_AARCH64_PREFIX=aarch64-none-linux-gnu- build -n 4 -a AARCH64 -p Platform/MyCorp/MyPlatform/MyPlatform.dsc -t GCC5 -b NOOPT -v -d 9 -j MyPlatform-build.log -y MyPlatform-build-report.txt -Y EXECUTION_ORDER -Y PCD -Y LIBRARY -Y DEPEX -Y HASH -Y BUILD_FLAGS -Y FLASH -Y FIXED_ADDRESS all popd
- Сделайте копию
- Add the 1st component
ArmPlatformPrePiUniCore
. This component is to prepare the HOBs for DXE phae. The main purpose is to get serial port working and memory config correct. Another purpose of this step is to familiar with steps for adding a component/module/lib. Below is a brief summary of the steps:- Uncomment the module’s
INF
into bothDSC
([Components]
section), andFDF
([FV.FVMAIN_COMPACT]
). - Перестройте pkg и устраните все
Instance of library class [xxxLib] is not found
сообщенные ошибки, обновив[LibraryClasses]
разделыDSC
.- This step is a repeating process for dozens of times.
- Some lib-class has multiple lib-instances, making sure choose the appropriate lib-instance (ref the build-report of RPi4).
- при возникновении
ModuleEntryPoint.iiii:31: Error: immediate out of range
: включитьgArmTokenSpaceGuid.PcdFdBaseAddress
иgArmTokenSpaceGuid.PcdFdSize
FDF
включить. - если встречается
undefined reference to _gPcd_BinaryPatch_PcdSerialClockRate
: установитьPcdSerialClockRate
в[PcdsPatchableInModule]
разделеDSC
в. FIXME: почему? ссылка.
- Проверьте PCD, перечисленные в журнале сборки: проверьте все ненормальные значения PCD и укажите правильные значения.
- Настройка драйверов или библиотек, зависящих от платформы.
SerialPortLib
: найдите файл заголовка lib-класса (MdePkg/Include/Library/SerialPortLib.h
) с помощьюfind edk2 -type f -name "*.dec" -exec grep -Hn SerialPortLib
. Требуются следующие функции:SerialPortInitialize()
SerialPortWrite()
SerialPortRead()
SerialPortPoll()
SerialPortSetControl()
: RETURN_UNSUPPORTEDSerialPortGetControl()
: RETURN_UNSUPPORTEDSerialPortSetAttributes()
: RETURN_UNSUPPORTED
ArmPlatformLib
: заголовок интерфейса atInclude/Library/ArmPlatformLib.h
. Требуются следующие функции:ArmPlatformGetCorePosition()
: верните идентификатор процессора в кластере с учетом значения MPIDR. эта функция используется_ModuleEntryPoint
для настройки стека для вторичных ядер. На данный момент предполагается один кластер.ArmPlatformIsPrimaryCore()
ArmPlatformGetPrimaryCoreMpId()
ArmPlatformGetBootMode()
ArmPlatformPeiBootAction()
ArmPlatformInitialize()
ArmPlatformGetVirtualMemoryMap()
ArmPlatformGetPlatformPpiList()
- и т.д…
- Uncomment the module’s
- Раскомментируйте больше модулей в DSC / FDF, модуль за модулем…Для драйверов / библиотек, зависящих от платформы RPi, мы можем:
- либо выполните поиск в
edk2
/edk2-platform
для похожих экземпляров драйверов или библиотек, либо - скопируйте реализацию RPi4 и закомментируйте большую часть содержимого, сначала выполните успешную сборку pkg, а затем исправьте ошибку.
- либо выполните поиск в
- Отладка: мой текущий основной метод отладки заключается в добавлении «printf ()», то есть макроса
DEBUG((DEBUG_INFO,))
edk2 .gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel
Для просмотра дополнительной информации об отладке необходимо установить соответствующее значение.