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

  • Tutorial

Здравствуйте, уважаемые хабровчане.
Опрос в первой части показал, что тема разработки 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
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 22
  • 0
    Осталось придумать что можно сделать на такой платке. АЦП на ней насколько быстрый? Можно ли будет на ней сделать SDR?
    • +3
      У нее почти все выводы GPIO сделаны через I2C port expander, так что максимальная частота — 100 кГц, и задержка еще около 2-3 мс, так что SDR из нее если и получится, то совсем никакой.
      Меня эта плата заинтересовала как платформа с открытым UEFI, а сама по себе она — первый блин, который комом. Совместимость с Arduino прикручена сбоку и реализована откровенно плохо, GPU в SoC встроить забыли, да и сам он ни производительностью, ни сверхнизким энергопотреблением не блещет, да и x86 там такой, что Windows все равно не грузится и 95% старого софта не работает. Посмотрим, что будет в следующем поколении, надеюсь, что Intel избавит его от совсем уж детских болезней.
    • 0
      Выводы GPIO это отдельный разговор, АЦП там стоит отдельный и подключен напрямую. К сожалению я не смог узнать быстрым гуглением какой же именно там АЦП стоит, часто на первых страницах поиска попадаются слишком общие характеристики платы в целом и упоминание что АЦП там есть а иногда еще тот факт что он быстрее чем в ардуиновских контроллерах. Но насколько? Видимо ответ на этот вопрос поможет чтение подробной документации, но… проще спросить у того кто её уже наверняка читал.
      • +1
        Не углядел, что ADC напрямую подключен, теперь внимательно посмотрел в схему — это действительно так. В качестве ADC на плате выступает чип Analog Devices AD7298, подключенный по SPI.
        Вот его характеристики:
        12-bit SAR ADC
        8 single-ended inputs
        Channel sequencer functionality
        Fast throughput of 1 MSPS
        Analog input range: 0 V to 2.5 V
        12-bit temperature-to-digital converter
        Temperature sensor accuracy of ±1°C
        Temperature range: −40°C to +125°C
        Specified for VDD: 2.8 V to 3.6 V
        Logic voltage VDRIVE: 1.65 V to 3.6 V
        Power-down current: <10 μA
        Internal 2.5 V reference
        Internal power-on reset
        High speed serial interface SPI

        Я не очень знаком с темой SDR, поэтому сделать вывод из них не могу, но мне кажется, что даже 30 Мгц на прием FM-станций все равно не хватит.
        • +1
          Где 30Мгц? там всего 1МSPS, т.е. осилить можно частоту до 500кГц.

          Можно конечно дополнить синтезатором и смесителем, 500кГц ширины для последующей обработки это не так уж и мало(ширина полосы стерео FM-станции порядка 70кГц), можно покрывать разом отдельные любительские диапазоны и/или вести непрерывный приём SSTV. Вобщем, есть возможность принимать сигналы точного времени на частоте 77кГц, тоже хорошая задача для практики. Лишь бы хватило производительности для математики.
          • –1
            Про 30 Мгц написано в даташите:
            The device contains a low noise, wide bandwidth track-and-hold amplifier that can handle input frequencies in excess of 30 MHz.

            Посоветуйте, что почитать по теме, может быть и сделаю что-нибудь простое в качестве упражнения.
            • +2
              Это входной усилитель имеет такую полосу пропускания. Но АЦП обеспечивает только 1Мсемпл в секунду.

              Для начала можно взять статью оттуда можно уже отправляться смотреть математику и всё остальное.

              Основное что может понадобится из математики — сдвиг спектра путём умножения сигнала на косинус опорной частоты и низкочастотные фильтры(FIR)
            • +1
              Забыл написать про производительность: Linpack — 15,5 MFLOPS, у RPi — 22,7. Могу проверить еще через openssl speed, если нужно.
        • +1
          Не думал что SPI-эмуляторы стоят так дорого, доводилось делать самому такой на коленке. Чип с EMC и USB-стэком, 128 метров оперативки, вот всё что нужно.
          Код там тривиальный.
          • 0
            Я тоже не думал, пока не столкнулся. На самом деле, тривиально там все только на первый взгляд, ведь нужно правильно эмулировать целый ворох чипов разных производителей с разными же командами, эмулировать режимы DualSPI и QuadSPI, которые аппаратно не поддерживает почти никто, да и сама по себе поддержка базы эмулируемых чипов в актуальном состоянии стоит приличных денег. Думаю сделать в качестве упражнения на коленке эмулятор ровно одного чипа — одного из самых распространенных на десктопных платах Winbond W25Q64BV/128BV в SPI-only режиме, ибо даже такого хватало бы сейчас на 90% плат, с которыми приходится работать.
            • 0
              Так-то да, у меня был конкретный чип, без экзотики.
              Кроме того + еще один с собственным протоколом шины, но схемотехника была практически один-в-один.
          • +2
            О, как раз недавно собирал себе тестовую платформу для экспериментов с UEFI на базе Intel DQ77KB.
            С одной стороны удручает отсутствие JTAG, с другой — это полноценная десктопная плата на нормальном чипсете с поддержкой всех security и management фич.
            Для программирования Galileo удобнее всего должно быть использование платок на FT2232H — там два канала, одни можно утилизировать под SPI и второй под JTAG (у меня оба канала заняты под SPI т.к. на моей плате используется два чипа).
            Еще в процессе перепробовал SIOC8 клипсы и микрозажимы всех мастей и калибров, в итоге забил — удобнее и надежнее всего оказалось просто подпаяться к чипам на прямую.
            pic
            image
            • 0
              Прикрутить FT2232H — первое, что я попробовал. JTAG работает, SPI — тоже, но flashrom не может достучаться до чипа по каким-то причинам, которые я выяснять не стал, ибо программаторов у меня много. По поводу «нормальности» — Minnovboard MAX обещают почти нормальную (на двуядерном Атоме), но при этом с полностью открытой реализацией UEFI. Осталось дождать ее выхода.
              • 0
                У flashrom довольно адекватное сообщество, если запостить модель чипа и консольный вывод с ключом -v — то с большой долей вероятности поддержку этого чипа добавят в скором времени.
                • 0
                  Чип там известный Winbond W25Q64FV, проблема где-то между разъемом ISP и FT2232H. Толи питания не хватает, толи частота SPI слишком высокая — пока не могу сказать, некогда было отлаживать, просто взял другой программатор с полки. Будет время — попвтаюсь выяснить, кто виноват и что делать.
                  • 0
                    Да, чип очень распространенный, на моих железках где он встречается — flashrom 100% УМВР.
                • 0
                  обещают почти нормальную (на двуядерном Атоме), но при этом с полностью открытой реализацией

                  ME/AMT, я так понимаю, там не будет?
                  • 0
                    На Bay Trail может быть только TXE, но на этой плате его не будет, ибо с открытостью такие вещи несовместимы. Вместо этого ядро Quark, которое у «взрослых» Atom'ов выполняет код TXE, может быть использовано как встроенный в SoC MCU, но в момент выпуска для него нет никакого ПО, поэтому проще считать, что его нет совсем.
              • 0
                Еще QEMU+OVMF нормальная тема для отладки UEFI кода, к QEMU можно подключить свой любимый отладочный фронтенд через GDB stub (причем он может работать на удаленном хосте через сетевое соединение).
                pic
                image
                • +1
                  Согласен, но пробрасывать в QEMU свое реальное устройство, для которого разрабатывается UEFI-драйвер — тот еще цирк с конями, да и отлаживать, скажем, какие-то защитные механизмы или работу с SMM стоит, на мой взгляд, на реальном железе.
                  Если же с железом работать не надо, а драйвер ваш, к примеру, для ФС — QEMU + QVMF рулят и педалят.
                  • 0
                    Кстати, по повду реальных устройств — в е-зине PoC||GTFO issue 0x05 была полезная в контексте обсуждаемой темы статья про подключение к Galileo «больших» PCIe плат на примере видеокарты. Вот здесь лежат чертежи печатной платы для переходника: github.com/securelyfitz/PEXternalizer
                    • +1
                      Видел уже, когда исследовал возможность подключения GPU, слишком громоздкий получается сетап. Лучше тогда уже использовать либо mPCIe-карту вроде такой, либо USB-GPU на базе чипов серии DisplayLink 1x5, ибо они относительно хорошо работают в современных Linux'ах почти без бубна. Проблема с ними только одна — стоимость, сравнимая со стоимостью самой платы.

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