38,4
рейтинг
17 сентября 2014 в 23:41

Разработка → Разработка и отладка 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
Николай Шлей @CodeRush
карма
189,0
рейтинг 38,4
Firmware Engineer
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (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'ах почти без бубна. Проблема с ними только одна — стоимость, сравнимая со стоимостью самой платы.

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