Pull to refresh

Разработка и отладка UEFI-драйверов на Intel Galileo, часть 2: готовим плацдарм

Reading time 9 min
Views 13K

Здравствуйте, уважаемые хабровчане.
Опрос в первой части показал, что тема разработки UEFI-драйверов достаточно интересна сообществу, поэтому я приступаю к написанию дальнейших частей этого цикла. В этой речь пойдет о подготовке платы Intel Galileo к работе, необходимом и желательном железе и ПО, сборке и установке BSP. В результате получится недорогая аппаратная платформа, пригодная для аппаратной отладки UEFI-драйверов и доступная любому энтузиасту.

Вступление и отказ от ответственности

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

Готовим железо

Сама плата
Перво-наперво, вам необходимо достать каким-то образом плату Intel Galileo. Неважно, будет ли она первого или второго поколения (со стороны UEFI и ПО они не отличаются ничем), главное, чтобы вы смогли подключить к ней питание и UART-конвертер (обязательно), а также JTAG-отладчик и ISP-программатор (желательно). Ко мне эта плата попала в рамках изучения возможностей и перспектив Quark SoC нашей компанией и была получена непосредственно от немецкого представительства Intel. Обычному же человеку проще всего эту плату просто купить.

UART
Для подключения к Galileo Gen 1 по UART вам понадобится кабель AJ-COM, который проще всего изготовить самостоятельно по этой схеме:

Если на вашем ПК нет COM-порта, то придется использовать COM-USB-конвертер, которых на рынке много, и стоят они недорого, да и самостоятельно сделать такой конвертер из PL23xx/FT232 + MAX232 большой проблемы не составляет. В моем случае добрые люди из Intel положили кабель AJ-COM и конвертер COM-USB на базе PL2303 в коробку вместе с Galileo.
Отзывы пользователей и опыт эксплуатации Galileo Gen1 привели инженеров Intel к тому, что в Gen 2 разъем 3,5" Stereojack и микросхему MAX232, ранее выполнявшую сдвиг уровней совместимости с COM-портом, они заменили на гребенку, совместимую с USB-TTL-кабелями производства FTDI и имеющую вот такую распиновку:

Таким образом, для подключения к порту UART на Gen 2 достаточно кабеля, аналогичного TTL-232R-3V3, который можно опять же изготовить самостоятельно из вышеупомянутых PL23xx/FT232. Такая замена выгодна как для Intel (из схемы выкинули MAX232), так и для пользователей, которым теперь нужен только один кабель вместо двух. Более того, почти у всех, кто хоть немного знаком с миром DIY-электроники, конвертер USB-TTL уже есть.

JTAG
Как я уже писал в предыдущей части, Galileo пока остается единственной известной мне платой на базе x86 CPU, на которой порт JTAG TAP доступен сразу, без необходимости подключения дорогущих конвертеров вроде Intel XDP. С одной стороны, это открывает очень широкие возможности аппаратной отладки, а с другой — практически для всех случаев отладки UEFI-драйверов вполне достаточно отладочных сообщений через UART, для которых не нужны ни JTAG, ни дополнительное ПО, только терминал, только хардкор. С другой же стороны упускать такую возможность безблагодатно, поэтому съему подключения отладчика тоже стоит описать.
В качестве разъема JTAG на Galileo используется 10-пиновый коннектор с шагом 1,27 мм, к которому просто так не подключишься — мелкий, зараза. Intel предлагает использовать вот такой переходник на «нормальный» 20-пиновый коннектор JTAG, и это хорошее предложение, но для тех, кто умеет паять, у меня есть предложение получше: просто припаять пять проводов к промаркированным выводам на обратной стороне разъема, а с другой стороны припаять совместимый в вашим JTAG-отладчиком коннектор или по BLS-наконечнику на каждый провод. Со стороны платы это будет выглядеть примерно вот так (прошу прощения за неотмытый флюс):

Теперь никакие переходники не нужны, и можно подключать плату к любому отладчику из списка поддерживаемых OpenOCD. В Intel работоспособность отладки на Galileo проверяли с TinCanTools FLYSWATTER2 и Olimex ARM-USB-OCD-H, но оба этих отладчика — обыкновенная FT2232H в красивом корпусе, поэтому вы можете использовать для отладки на Galileo любую плату на чипе FTDI серии 232 с поддержкой MPSSE. Подробнее об отладчиках и отладке — в одной из следующих частей.

ISP
Ошибки при разработке и отладке UEFI-драйверов часто приводят к тому, что плата перестает загружаться, и приходится пользоваться восстановлением содержимого SPI-чипа при помощи recovery-образа или внешнего программатора. Кроме того, разработка подразумевает постоянное обновление прошивки, и каждый раз обновлять прошивку при помощи штатной утилиты CapsuleApp.efi получается долго и это моментально надоедает. Именно поэтому есть смысл подключить к Galileo программатор и шить им. К сожалению, попытки использовать плату на FT232H совместно с утилитой flashrom в качестве ISP-программатора на этой плате у меня успехом пока не увенчались, и пока эта проблема не решена, я буду использовать программатор Samedisk ZC2511. Intel, в свою очередь, предлагает использовать Dediprog SF100, который тоже вполне подойдет. Если же у вас уже есть SPI-программатор, вы можете попробовать подключить его к ISP-разъему, находящемуся в правой верхней части лицевой стороны платы согласно нижеуказанной распиновке:


Лирическое отступление или немного о SPI-эмуляторах
На самом деле, ISP — это не вершина прогресса, и для профессиональной разработки прошивок вместо SPI-программаторов используются SPI-эмуляторы, которые уменьшают время обновления прошивки до 1-2 секунд. Обычному человеку они недоступны вследствие высокой цены (порядка 500-700 долларов за штуку), поэтому совсем уж подробно останавливаться на них я не буду. Мы используем эмулятор Samedisk ZC25128, способный эмулировать SPI-чипы различных производителей емкостью до 128 Мбит. С точки зрения ОС эмулятор выглядит как обыкновенная USB-флешка, и обновить прошивку можно простым копированием файла с ней. Пока на моей памяти только один случай (Intel CRB для Bay Trail), когда система отказывалась загружаться с эмулятора, так что стоит признать, что решение имеет право на жизнь. Удивляет только редкость (и, в связи с ней, дороговизна) подобных устройств, ведь сейчас каждый второй микроконтроллер имеет по несколько аппаратных каналов SPI и производству эмуляторов ничего не мешает.
Для совместимости с эмулятором я доработал свою плату Galileo Gen 1, заменив SPI-чип на специальный разъем, к которому подключается либо эмулятор, либо SPI-чип в ZIF-кроватке. Выглядит это вот так:


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

Готовим ПО

Сборочная платформа
Для Galileo существует два принципиально различных набора ПО: это BSP и Arduino Software. Первый набор необходим для сборки как UEFI-прошивки, так и предлагаемой Intel в качестве базовой версии Yocto Linux в нескольких вариантах, самыми популярными из которых являются два — galileo-spi и galileo-full. Первый — минимальная Linux-система, стартующая непосредственно из SPI-чипа и способная выполнять Arduino-скетчи, вторая уже больше похожа на нормальный Linux, но загружать ее необходимо уже с SD-карты. С этим типом загрузки связана небольшая проблема: большая часть плат Gen1 требует обновления прошивки для того, чтобы с SD-карты запускалось хоть что-нибудь, поэтому «из коробки» запуск уже подготовленного Intel образа невозможен.
Совместимость с Arduino в этой статье нас не интересует, поэтому из всего комплекта ПО нам понадобится только архив с BSP, называющийся обычно Board_Support_Package_Sources_for_Intel_Quark_vX.Y.Z.T.zip, в данный момент его последняя версия — 1.0.1.7. Intel предлагает неистово огромный выбор платформ для сборки BSP в количестве ровно одной штуки — Ubuntu 12.04 x64. Вы, конечно, можете попробовать собирать из другого дистрибутива Linux'а (я пробовал из Ubuntu 14.04, минимальный образ собирается, полный — уже нет) или даже из OSX или Windows, но мне гораздо проще установить нужную версию на виртуальную машину и запускать сборку из нее. Останавливаться подробно на установке Ubuntu я не буду, лишь укажу список пакетов, которые нужно будет доустановить на каждом этапе сборки BSP.

Сборка BSP
Нулевой шаг
Итак, Ubuntu 12.04 x64 у вас установлена, обновлена и загружена, архив с последней BSP скачан и распакован, для определенности, в ~/Galileo/, у вас имеется соединение с Интернетом и вы готовы потратить немного времени.
Перед началом сборки необходимо установить следующие пакеты: build-essential и gcc-multilib. Они необходимы на всех этапах сборки. Рекомендую также для каждого шага открывать новый терминал в ~/Galileo/, чтобы предотвратить возможные конфликты создаваемых на каждом шаге сборочных окружений.

Сборка UEFI
Для сборки UEFI нужно установить пакеты subversion, uuid-dev и iasl. После этого необходимо распаковать архив Quark_EDKII_vX.Y.Z.tar.gz, перейти в созданную при распаковке директорию Quark_EDKII_vX.Y.Z и выполнить в ней сначала скрипт svn_setup.py, а затем команду svn update, которая загрузит необходимые ей для сборки части EFI Development Kit. После окончания загрузки необходимо выполнить команду ./quarkbuild.sh -d32 GCC46 QuarkPlatfrom, которая запустит сборку отладочной версии UEFI (ключ d32) при помощи GCC 4.6 (в Ubuntu 12.04 именно такой) для платформы на базе Quark SoC (которой Galileo и является). После окончания сборки в директории Build/QuarkPlatfrom/DEBUG_GCC46/FV/ будет находиться файл QUARK.fd — это неполный образ прошивки, который понадобится в следующей части, а в поддиректории Applications — утилита CapsuleApp.efi, используемая для обновления прошивки из UEFI Shell, которую придется использовать, если у вас нет программатора.

Сборка GRUB
В качестве загрузчика по умолчанию для фазы BDS на этой плате Intel предлагает использовать изрядно модифицированный GRUB v1. Его можно не собирать, если предполагается создание даже минимальной сборки Yocto Linux, но в нашем случае собирать его нужно. Понадобится установить пакеты gnu-efi, autoconf, libtool и git. Как обычно, распаковываем архив с GRUB, переходим в созданную после распаковки директорию и выполняем скрипт gitsetup.py, затем переходим в поддиректорию work и выполняем команды autoreconf --install, export CC4GRUB='gcc -m32 -march=i586 -fno-stack-protector', export GNUEFI_LIBDIR=/usr/lib32, CC="${CC4GRUB}" ./configure-quark.sh. Не торопитесь выполнять make, сначала необходимо исправить ошибку, если в вашей версии она имеется. Дело в том, что сборщики забыли положить в work/efi/ia32/ файл crt0-efi.S, а без него собрать GRUB невозможно (это startup-код), поэтому его нужно скачать (например, отсюда), правильно переименовать, скопировать в вышеуказанную директорию, а потом уже с чистой совестью выполнять команду make. В результате в work/efi/ окажется нужный нам файл grub.efi.

Сборка минимального образа Yocto Linux
Для сборки минимального образа ОС, который затем будет помещен в SPI-чип, нужно установить пакеты diffstat, texinfo, gawk и chrpath, а если не выполнять предыдущий шаг, то и git. Распаковываем архив meta-clanton_vX.Y.Z.tar.gz, переходим в созданную папку и выполняем скрипт setup.sh, теперь придется немного подождать. Дождавшись окончания загрузки сборочных скриптов, выполняем команды source poky/oe-init-build-env yocto_build и bitbake image-spi-galileo, после чего начнется довольно продолжительный процесс загрузки и сборки Yocto из исходных текстов. Для сборки минимального образа необходимо около 2 Гб дискового пространства, а сборка максимально полного образа требует около 35 Гб и выполняется в течении почти 7 часов на моем Core i5-2500K с 8 Гб оперативной памяти и SSD. Если вдруг кому-то будет интересно — напишу о сборке такого образа отдельную статью, ибо там хватает своих подводных граблей, которые здесь были бы лишними. В общем, на этом месте предлагаю отдохнуть и посмотреть на ход сборки, на который любой гентушник энтузиаст может смотреть также долго, как на текущую воду или горящий огонь.

Сборка всего вышеуказанного в один файл
Образ ОС готов, и можно собирать все компоненты вместе. Для этого необходимо распаковать архивы sysimage и spi-flash-tools и перейти в директорию sysimage_vX.Y.Z/sysimage.CP-8M-debug/, в которой, кроме всего остального, имеется файл layout.conf. Откройте его в любимом текстовом редакторе и исправьте все пути и названия файлов на верные, заменив «PLAIN/DEBUG_GCC» на «DEBUG_GCC46», «image-spi-clanton.cpio.lzma» на «image-spi-galileo-clanton.cpio.lzma» и добавив правильный номер версии к «meta-clanton» и «Quark_EDKII», после чего не забудьте сохранить изменения. Затем выполните команду ../../spi-flash-tools_vX.Y.Z/Makefile, в результате в директории sysimage.CP-8M-debug будут созданы файлы Flash-missingPDAT.bin, Flash-missingPDAT.cap и FVMAIN.fv. Последний используется как recovery-образ, второй можно копировать на microSD-карту и обновлять прошивку вашей Galileo с помощью CapsuleApp.efi из UEFI Shell, а для доводки первого необходим еще один шаг, последний.

Добавление Platfrom Data в Flash-missingPDAT.bin
Остался последний шаг — добавить зависимые от платформы настройки. Для этого необходимо перейти в директорию spi-flash-tools_vX.Y.Z/platform-data/, открыть в любимом редакторе файл sample-platfrom-data.ini и исправить в нем в разделе [Platfrom Type] значение data.value на 6 для Gen1 или 8 для Gen 2, в [Mrc Params] data.value на MRC/kipsbay-fabD.v1.bin (Gen 1) или MRC/GalileoGen2.bin (Gen 2), закомментировать пример с data.type=hex.string в том же разделе и изменить в разделе [MAC address 0] значение data.value на адрес, напечатанный на наклейке на Ethernet-разъеме платы, [MAC address 1] же на Galileo можно не изменять. После этого необходимо выполнить команду ./platform-data-patch.py -p sample-platfrom-data.ini -i ../../sysimage_vX.Y.Z/sysimage.CP-8M-debug/Flash-missingPDAT.bin, которая создаст, наконец, файл Flash+PlatfromData.bin, готовый к прошивке программатором.

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

Прошиваем полученный на предыдущем шаге образ, подключаем плату по UART к ПК, запускаем любимый терминал (для Windows могу посоветовать Putty/Kitty или TeraTerm), подключаемся к соответствующему COM-порту с настройками 115200 бод, данные — 8 бит, стоп — 1 бит, четность и контроль потока — отключены, и подключаем питание к Galileo.
Если видим поток отладочных сообщений UEFI, вроде того, что на картинке ниже — все сделано верно. Если нет — перепроверяем все еще пару раз, как говорится, УМВР.


Заключение и дальнейшие планы

По окончанию этой части статьи у нас получилась подготовленная и проверенная на работоспособность аппаратная платформа, которую можно успешно использовать для отладки самописных UEFI-драйверов, если интегрировать их сборку в образ UEFI на первом шаге. В следующей части я постараюсь показать, как можно значительно упростить и ускорить сборочный процесс, как именно осуществляется интеграция своих драйверов в кодовую базу EDK и как осуществлять их отладку, используя UART. О JTAG-отладке в Eclipse с помощью OpenOCD и GDB планируется поговорить отдельно.
К первой части, кстати, практически не было комментариев, надеюсь, что они будут к этой. Спасибо за внимание и до встречи в следующих частях.

Источники информации

Intel Quark SoC X1000 Board Support Package (BSP) Build and Software User Guide
Source Level Debug using OpenOCD/GDB/Eclipse on Intel Quark SoC X1000
Intel Galileo Gen1 Schematics
Intel Galileo Gen2 Schematics
FTDI TTL to USB Serial Converter Range of Cables Datasheet
Intel Embedded Community
Tags:
Hubs:
+28
Comments 22
Comments Comments 22

Articles