Реверс-инжиниринг железа: находим UART и извлекаем прошивку при помощи UBoot / Хабр

postal Обзоры
Содержание
  1. Что делать если tinker board — s не загружается восстановление прошивки
  2. Краткое описание оборудования
  3. Длинное введение
  4. Введение
  5. Что такое прошивка и где её взять?
  6. Uboot
  7. Usb-программатор микросхем spi-flash 25 серии.
  8. Анализ разъёмов
  9. Видео как восстановить tinker board, два варианта прошивки
  10. Дамп флэш-памяти при помощи depthcharge
  11. Декодируем трафик uart
  12. Демонтаж микросхемы памяти.
  13. Задачи
  14. Инструменты uart
  15. Используем raspi config
  16. Исследование отладочных контактов
  17. Команды uboot
  18. Конфигурируем raspberry pi
  19. Первая «прошивка»
  20. Переменные среды uboot
  21. Перепрошивка tinker board — s пошагово
  22. Подбор spi-flash памяти для замены.
  23. Подключение к uart и обнаружение командной строки uboot
  24. Продолжение введения про подход к программированию плис
  25. Процесс разработки и отладки «прошивок»
  26. Разборка автомата
  27. Скриптинг uboot при помощи depthcharge
  28. Содержимое файловой системы
  29. Структурная схема комплекса
  30. Считывание и запись во флэш-память при помощи depthcharge
  31. Считывание и запись на usb при помощи depthcharge
  32. Выводы и дальнейшая работа
  33. Узнайте больше о Huawei

Что делать если tinker board — s не загружается восстановление прошивки

После прошивки микрокомпьютера система перестала загружаться? При включении питания на экране ничего не происходит?  Скорее всего залили не ту прошивку или  повреждена текущая рабочая. Несовместимая прошивка затирает загрузочные разделы на внутренней памяти Tinker Board.

Я по ошибке (не разобравшись с ревизиями платы ) залил туда 11 андройд.

https://www.youtube.com/watch?v=HzeIIXSLjZQ

Характерный  симптом — программа balenaEtcher-Portable  при попытке прошить повторно теперь не обнаруживает Tinker Board. В «диспетчере устройств» Windows микрокомьютер висит как  «неизвестное устройство».

Подготавливаемся к процессу прошивки основательнее, если одноплатное устройство Tinker Board перестало загружаться, устройство не обнаружено. Мне потребовалось:

К штекеру блока питания  изолентой примотал провода. Проверил  полярность и подключил вот так (красный черный минус);

Теперь скачиваем совместимую версию прошивки, запускаем программу  balenaEtcher-Portable-1.7.1 или win32diskimager; записываем прошивку на карту памяти.  Можно считать, что подготовка к реанимации завершена.

Перехожу непосредственно к сути процесса. Обратите внимание на фото ниже:

Рядом с HDMI-портом (слева) находится  джампер.  Когда с микрокомпьютером все хорошо джампер находится в положении parking (режим «no function)».  В этом режиме он находится сейчас. И если нет повреждений прошивки то он и запускается и шьется без проблем.

Но, если Вы окирпичили Tinker Board перед началом процесса перепрошивки  джампер необходимо переключить в положение maskRoom Mode как на фото ниже:

Краткое описание оборудования

При изучении новой платформы одна из первых задач заключается в анализе доступных интерфейсов. В случае этого аркадного автомата поначалу кажется, что набор интерфейсов очень ограничен. Пользователи взаимодействуют с устройством посредством джойстика/кнопок и USB-разъёмом на боковой панели автомата. Похоже, относительно USB-разъёма существует довольно мало информации. Стоит заметить, что даже на

с сайта производителя USB-разъёма нет. Однако наличие разъёма для USB-устройств подразумевает поддержку внешних контроллеров. На другой стороне устройства есть стандартный разъём для наушников. Эти два периферийных разъёма ведут себя как положено — к USB-разъёму можно подключить внешний контроллер, да и разъём наушников работает в соответствии с описанием.

Интересный факт: на некоторых старых мобильных телефонах можно было настроить аудиоразъём так, чтобы при запуске он работал в качестве последовательного терминала. Подробнее об этом можно прочитать здесь. К сожалению, подобные модификации не работают на нашей платформе.

Учитывая всю эту информацию, похоже, возможности внешнего исследования устройства завершены. Поэтому теперь мы вскроем автомат и посмотрим, что внутри!

Длинное введение

Я не очень люблю теоретизировать, предпочитая выкладывать сразу какие-то практические вещи. Но в начале первой статьи, без длинного введения никуда. В нём я обосную текущий подход к разработке. И всё будет вертеться вокруг одного: человеко-час — очень дорогой ресурс.

И дело не только в сроках, отведённых на проект. Он физически дорог. Если он тратится на разработку конечного продукта, ну что ж поделать, без этого никуда. Но когда он тратится на вспомогательные работы, это, на мой взгляд, плохо. Помню, был у меня спор с одним разработчиком, который говорил, что изготовив прототипы самостоятельно, он сэкономит родной компании деньги.

Я же привёл довод, что он на изготовление потратит примерно 3 дня. То есть 24 человеко-часа. Берём его зарплату за эти часы, добавляем социальный налог, который «платит работодатель», а также аренду офиса за эти часы. И с удивлением видим, что заказав платы на стороне, можно получить меньшие затраты. Но это я так, утрирую. В целом, если можно избежать трудозатрат, их надо избегать.

Что такое разработка «прошивок» для комплекса Redd? Это вспомогательная работа. Основной проект будет жить долго и счастливо, он должен быть сделан максимально эффективно, с отличной оптимизацией и т.п. А вот тратить силы и время на вспомогательные вещи, которые уйдут в архив после окончания разработки, расточительно.

Именно с оглядкой на этот принцип велась разработка аппаратуры Redd. Все функции, по возможности, реализованы в виде стандартных вещей. Шины SPI, I2C и UART реализованы на штатных микросхемах от FTDI и программируются через штатные драйверы, без каких-либо изысков.

Управление релюшками реализовано в формате виртуального COM-порта. Его можно доработать, но по крайней мере, всё сделано для того, чтобы такого желания не возникало. В общем, всё стандартное, по возможности, реализовано стандартным образом. Из проекта в проект разработчики просто должны быстренько писать типовой код для PC, чтобы обращаться к этим шинам.

Но особняком в комплексе стоит ПЛИС. Она добавлена в систему для случаев, если понадобится реализовывать какие-либо нестандартные протоколы с высоким требованием к быстродействию. Если таковые требуются — для неё «прошивку» делать придётся. Вот про программирование ПЛИС и хочется поговорить особо, как раз всё с той же целью — сократить время разработки вспомогательных вещей.

Чтобы не запутать читателя, сформулирую мысль в рамке:

Не обязательно в каждом проекте вести разработку для ПЛИС. Если для работы с целевым устройством хватает шинных контроллеров, подключённых напрямую к центральному процессору, стоит пользоваться ими.
ПЛИС добавлена в комплекс для реализации нестандартных протоколов.

Введение

В этом посте мы расскажем об UART, UBoot и USB, а нашей целью станет игровой автомат Arcade 1UP Marvel. Серия автоматов Arcade 1Up предоставляет возможность за приемлемую цену приобрести домашнюю аркадную машину. С момента выпуска этих автоматов появилось множество

, демонстрирующих, как заменить внутренние компоненты автомата для запуска стандартного ПО MAME. В посте мы исследуем оборудование автомата и узнаем, как извлечь его прошивку.

Что такое прошивка и где её взять?

Прошивка представляет собой файл в формате .bin, который иногда ещё называют дампом памяти или просто дампом. Она является микропрограммой, которая управляет работой ЖК-телевизора.

Где взять рабочую прошивку?

Uboot

— это загрузчик в open-source, часто используемый во встроенных системах. Он имеет поддержку широкого ассортимента архитектур и типов CPU. Однако задача UBoot обычно заключается в загрузке ядра операционной системы или основного приложения встроенной системы.

Также UBoot содержит утилиты, полезные в процессе реверс-инжиниринга; самым примечательным является командная строка UBoot.

Usb-программатор микросхем spi-flash 25 серии.

В качестве программатора для прошивки микросхем памяти я уже давно использую USB-программатор Postal 3. Он же Postal AVR. Покупал набор для самостоятельной сборки. Вместе с рассыпухой, которой нет в наборе, программатор обошёлся мне в сумму около 500 руб. Покупал его специально для прошивки микросхем SPI-Flash от LCD-телевизоров.

Ссылка на сайт, где можно заказать Postal 3 (USB). Там же найдёте инструкцию по установке и настройке софта.

Вот так программатор выглядит в сборе.

Разумеется, сейчас в продаже можно найти и другие программаторы (например, CH341A).

Ориентироваться надо на ремонтопригодность, доступность по цене, необходимую функциональность и поддержку сообщества (изделие должно быть популярным в радиолюбительской среде, иметь доступную документацию и софт).

Если руки прямые и есть время, то можно собрать программатор самому.

Для работы с USB-программатором Postal 3 используется программа с аналогичным названием (Postal 2/3).

Актуальную информацию по программатору Postal 3 (рисунок печатки, прошивка для микроконтроллера, софт, вопросы/ответы и пр.) можно найти в профильных темах на форумах Монитора и Ремонта бытовой техники и электроники.

Анализ разъёмов


Задокументировав все дискретные компоненты материнской платы, мы попытаемся распознать её внешние разъёмы. Во-первых, у нас есть круглый разъём, показанный на изображении внизу синим цветом:

Этот разъём используется для подачи питания на автомат.

Справа от круглого разъёма есть разъём micro-USB. Это сразу вызывает удивление по двум причинам:

  1. Это разъём не для пользователя
  2. Это не разъём USB-хоста; это разъём micro, намекающий на USB-устройство или, возможно, на контроллер OTG (on the go)

Ещё правее находится два ряда контактов. Они были подключены к серому гибкому шлейфу, показанному на предыдущих изображениях. Этот разъём соединяется с отдельной платой управления и используется для управления джойстиками/кнопками.


После разъёма платы управления есть ещё один четырёхконтактный разъём. Не совсем очевидно, куда он ведёт. Например, этот разъём может вести к USB-разъёму или к разъёму для наушников. Мы можем попробовать определить это при помощи мультиметра и

. Прозвонка позволяет проверить, может ли течь ток между двумя щупами и обычно обозначается на мультиметре одним из следующих символов:

Мы можем использовать эту модель для проверки того, соединены ли два компонента. Я вставил в разъём для наушников кабель и прижал щуп к одному из металлических колец, чтобы проверить соединение. Другим щупом я касался каждой точки четырёхконтактного разъёма и на одной из линий мультиметр издал громкий писк, сообщая, что между этими двумя точками есть соединение. Каждый из трёх контактов совпадал с кольцом на аудиоразъёме; это разъём для наушников!


Далее у нас находится разъём для дисплея:

Рядом с дисплеем расположены два двухконтактных разъёма, один в правом нижнем углу, он используется для питания подсветки самого автомата, а другой идёт к переключателю «вкл./выкл.», находящемуся снаружи металлического корпуса.

Следующий разъём похож на аудиоразъём; это четырёхконтактный соединитель, кабели которого ведут к панели управления. Остался только один интерфейс, который мы пока не рассмотрели: USB-разъём на боковой панели автомата. Если переключить мультиметр на режим прозвонки цепей и проверить контакты этот разъёма с USB-разъёмом, то мы убедимся, что они действительно связаны. Это наш внешний USB-разъём.

Мы разобрались со всеми разъёмами, которые пришлось отсоединить, чтобы лучше видеть плату. Следовательно, исследовать нам осталось не так много. При изучении печатной платы стоит рассмотреть неиспользуемые тестовые площадки или переходные соединения; на изображении ниже я выделил неиспользуемые контакты/площадки.

На показанном выше изображении мы видим три набора неподключённых контактов или площадок. Наверху платы есть три переходных соединения; переходное соединение используется для создания связей между несколькими слоями печатной платы. При исследовании встроенных систем подобные соединения являются хорошей начальной точкой, потому что они могут содержать отладочный контакт, применявшийся во время разработки.


Ещё одна группа состоит из 16 площадок, обозначенных белым прямоугольником и небольшим кружком. Эта группа площадок с большой вероятностью предназначалась для другой интегральной схемы, которая не требуется на этой плате.

Последняя группа площадок выглядит очень похоже на разъёмы, использованные для USB и аудио. Подобные четырёхконтактные соединения неиспользуемых площадок часто являются кандидатами на отладочную консоль через UART; мы исследуем эти контакты и обсудим UART в следующем разделе.

Видео как восстановить tinker board, два варианта прошивки

Действуем следующим образом (питание отключено):

  • вставляем карту памяти c  записанной на нее прошивкой в слот Tinker Board;
  • Джампер выставляем в MaskRoom mode;
  • выключаем питание, подсоединяем компьютер/ноутбук к Tinker Board кабелем;
  • Запускаем balenaEtcher-Portable; выбираем скаченный ранее совместимый образ прошивки (который записывали на карту MicroSD);
  • находим устройства (будут видны разделы карты памяти и внутренней памяти в balenaEtcher-Portable;
  • прошиваем устройство;
  • Отсоединяем кабель MicroUSB;
  • переводим джампер в положение parking (no function);
  • подключаем питание;
  • Ждем переноса прошивки с карты памяти в микросхемы Tinker Board; далее Андройд на Tinker Board запустится сам.
  • отключаем питание, вытаскиваем карту памяти;
  • Подключаем питание к плате, если все прошло хорошо Андройд запустится.

Принцип прошивки других моделей Tinker Board  сходный . Только может потребоваться кабель TYPE C. Н Кстати, на карту памяти Micro SD в качестве эксперимента  я записывал и Linux Debian Strech (совместимый), все работает. До встречи на страницах блога!

Дамп флэш-памяти при помощи depthcharge


Теперь, когда мы подготовили соответствующие функции, попробуем сделать следующее:

if __name__ == "__main__":
    log.info("Marvel Super Heroes Depthcharge Test...")
    ctx = console_setup()
    usb_setup(ctx,reset=False)
    # Read the SPI flash into RAM
    rksfc_read(ctx,TARGET_RAM_ADDR,0,0x35E00)
    log.info("Flash read into RAM")
    # Write the data from RAM to a USB drive
    usb_raw_write(ctx,TARGET_RAM_ADDR,0,0x35E00)
    log.info("Flash written to USB")

После запуска этого скрипта получим следующий результат:

Декодируем трафик uart

С помощью pulseview мы можем попытаться декодировать этот трафик и посмотреть, действительно ли это активный UART. Для подготовки декодера нужно нажать на показанные ниже зелёный и жёлтый символы. Откроется окно выбора декодера, введите в панели поиска

uart

и выберите декодер UART.


Далее нужно настроить декодер UART. Нам нужно выбрать соответствующие каналы и задать все параметры протокола, необходимые этому декодеру. См. настраиваемые параметры ниже:

Сначала выберем линию Rx как содержащий трафик канал; в нашем случае это будет

D1

. Во всех остальных полях оставим стандартные значения: 8-битная ширина данных, отключенный контроль чётности и т. п.

Нам нужно определить и указать самостоятельно один параметр: baud rate. Не забывайте, что стороны должны заранее согласовать baud rate; нет никакого этапа согласования/запуска. Нам нужно определить этот baud rate самостоятельно; в противном случае, декодер не будет знать, как правильно парсить эти сигналы. Для определения baud rate мы можем сделать следующее.

  1. Приблизить то, что кажется одним из наименьших импульсов (предположительно, он обозначает передаваемый по проводнику один бит)
  2. Выбрать ширину импульса при помощи маркеров данных в Pulseview, нажать показанную ниже кнопку, чтобы включить их:
  3. После выбора диапазона малого импульса Pulseview автоматически вычислит частоту и выдаст нам показатель в герцах, как показано на скриншоте ниже.

Герц измеряется в тактах на секунду; вспомним, что baud rate измеряется в битах на секунду. Следовательно, если мы выделили один бит, передаваемый по проводнику, и частоту этого импульса, то у нас есть и baud rate.

Согласно Pulseview, вычисленная частота равна 115,384 кГц, что эквивалентно baud rate в 115385 бит/с. Те, кто знаком с консолями отладки, должны заметить, что это очень близко к стандартно используемому baud rate, равному 115200. Так что давайте вставим это значение в декодер и посмотрим, что произойдёт.

На скриншоте ниже мы видим настоящий лог отладки.

У нас есть активный UART и мы наем его baud rate, но теперь нам нужно найти способ взаимодействия с ним. Для этого мы воспользуемся Raspberry Pi. Дополненная схема расположения выводов автомата имеет следующий вид:

Демонтаж микросхемы памяти.

Вскрываем заднюю крышку телевизора. При этом его лучше положить на диван или кровать, чтобы исключить повреждение ЖК-матрицы.

Откручиваем болты по периметру задней крышки. Не удивляйтесь тому, что LED-подсветка включена. Фото я делал уже на рабочем телевизоре.

Почти вся электронная начинка сосредоточена на одной печатной плате.

Здесь и блок питания, и инвертор DC/DC для питания LED-подсветки, и скалер (центральный процессор), а также блок тюнера и усилитель. Всё на одной плате.

Кстати, номер LCD панели у нашего телевизора Mystery MTV-3223LT2 (V4N09) указан на наклейке (V320BJ7-PE1).

После осмотра печатной платы и замера основных напряжений стало ясно, что “железо” исправно, а неисправность, скорее всего связана с программной частью аппарата.

Снимаем плату, чтобы выпаять микросхему памяти. Если не уверены в том, что потом, во время сборки, сможете правильно подключить все провода и шлейфы, то делаем качественное фото или записываем/маркируем что и с чем соединяется.

Далее ищем на плате “флэшку”. Обычно она располагается рядом со скалером (центральным процессором), на который установлен или чаще всего приклеен алюминиевый радиатор.

Теперь нам надо подобрать замену нашей микросхеме. Как видим, в данном телевизоре используется 25Q64BSIG с объёмом памяти 8 Мбайт (64 Мбит). Вместо неё я установлю новую микросхему W25Q64FVSIG фирмы Winbond.

Далее выпаиваем микросхему. Раньше я справлялся обычным паяльником и медной проволочкой, иногда выпаивал феном термовоздушной паяльной станции. Но теперь использую сплав Розе. С ним и не перегреешь ничего, и дорожки на печатной плате не отслаиваются.

Выпаиваем чип и убираем остатки припоя с дорожек медной оплёткой.

Отмываем остатки флюса изопропиловым спиртом. Место под установку прошитой памяти готово.

Теперь настало время прошить новую флэш-память.

Задачи


В этом посте мы раскроем следующие темы:

Цель этой статьи заключается в том, чтобы познакомить читателей с процессом нахождения активного UART в системе, работой с консолью UBoot и в конечном итоге использованием этих компонентов для извлечения флэш-памяти из системы. Прочитав статью, вы познакомитесь с утилитой

screen

из библиотеки

depthcharge

python3.

Инструменты uart


При помощи интерфейса UART на Raspberry Pi мы можем попытаться подключиться к этому последовательному порту нашей цели. Для взаимодействия с этим последовательным портом мы будем использовать утилиту

screen

. При взаимодействии с UART утилите Screen нужно передать устройство и baud rate; так как мы знаем baud rate из предыдущего раздела, то мы запустим screen следующим образом:

sudo screen -L -Logfile cabinet-bootup.log /dev/ttyS0 115200

Теперь мы можем включить питание автомата, сконфигурировав UART и запустив screen. При включении питания автомата мы видим следующее:


И наконец мы оказываемся в консоли:

Теперь у нас есть консоль рута; мы можем исследовать файловую систему, посмотреть, что запущено на целевой системе и больше узнать о том, как она устроена. Нашим следующим этапом будет попытка создать образ разделов; давайте начнём с изучения того, как смонтированы эти разделы:

Используем raspi config

raspi-config

— это инструмент пользовательского пространства, позволяющий нам конфигурировать различные аспекты Raspberry Pi, одним из которых является включение различных внешних интерфейсов. Мы воспользуемся

raspi-config

для включения интерфейса UART; начнём с запуска инструмента:

sudo raspi-config

При этом появится следующий экран:

Далее мы выберем

Interface Options

, а затем

Serial Port

, как показано на изображении ниже:


После выбора этой опции отобразится два вопроса:

  1. Would you like a login shell to be accessible over serial? (Сделать login shell доступной через последовательный порт?)
  2. Would you like the serial port hardware to be enabled? (Включить оборудование последовательного порта?)

Так мы включили UART на Raspberry Pi. Далее нужно подключить его к автомату. Мы подключим Tx автомата к Rx устройства Pi, а Rx автомата — к Tx устройства Pi:

Исследование отладочных контактов

Изучая неизвестные контакты наподобие описанных в предыдущем разделе, я обычно начинаю с замера напряжения. Это можно сделать при помощи

. Чтобы вычислить напряжение на этих площадках, мы переключим мультиметр в режим измерения постоянного тока и будем касаться щупом интересующих нас точек, держа чёрный щуп на точке заземления. Эти контакты имеют следующие показания:

На этих линиях нет напряжения; хоть это нас и разочаровало, но неожиданностью не стало. Если бы передавался активный UART или другой цифровой сигнал, мы бы ожидали увидеть активность в виде колебаний напряжения. Давайте перейдём к другому трёхконтактному разъёму.

При замерах на этом разъёме начинаются резкие колебания на втором контакте, постепенно сводящиеся к 3,3 В; пример того, как выглядят эти колебания, см. в показанном ниже gif:

Примечание:

при поиске последовательного разъёма вы не всегда сможете увидеть колебания напряжения такой величины. Колебания напрямую коррелируют с уровнем активности сигнала, то есть если трафик небольшой, то колебания будут небольшими или их вообще не будет. Если вы подозреваете, что нашли контакт UART или какой-то цифровой интерфейс, то всегда стоит проверить его логическим анализатором.

Мы видим то, что может походить на активность сигнала (на основании колебаний напряжения). Далее нам нужно исследовать этот трафик логическим анализатором. Логические анализаторы помогают нам преобразовать эти колебания напряжения в человекочитаемую последовательность единиц и нулей.

Подключив анализатор, мы запустим Pulseview и выберем его в раскрывающемся меню; в приложении это устройство отображается как «Saleae Logic». Для этого анализатора максимальная частота захвата составляет 24 МГц, и именно её мы будем использовать для анализа. Также нам нужно указать количество сэмплов. Я выбрал значение 500G (500 миллиардов).

Мы запустим захват нажатием на Run, а затем включим питание автомата с этими параметрами.

Успех! Мы перехватили какой-то трафик; прежде чем двигаться дальше в Pulseview, давайте подробнее поговорим о том, как работает UART на уровне сигналов. Мы убедились в том, что по этим линиям передаётся некий трафик; далее нам нужно чуть больше узнать о трафике UART и о том, как его анализировать.

Команды uboot

Консоль UBoot может содержать большое количество встроенных утилит. Эти утилиты можно использовать в процессе стандартной загрузки (часто с помощью переменных среды) или в командной строке UBoot. Набор команд зависит от того как был собран образ UBoot.

Теперь, когда мы обнаружили консоль UBoot, давайте начнём с того, что посмотрим, какие команды публично доступны нам, выполнив help command

Конфигурируем raspberry pi

Raspberry Pi имеет множество UART; тот, который мы будем использовать, выделен на изображении ниже:

Чтобы включить этот UART, нам нужно убедиться, что включен блоб дерева соответствующего устройства. Блоб дерева устройства (device tree blob, DTB) необходим для того, чтобы ядро понимало доступную аппаратную периферию. Ядро считывает эту двоичную информацию при запуске и перечисляет указанную периферию.

Все нужные нам блобы дерева устройств в raspberry pi могут находиться в /boot/overlays/. Найдите в этой папке двоичные объекты дерева устройств для различных аппаратных конфигураций, некоторые для конкретных HAT (специализированных печатных плат, спроектированных для Pi), подключаемых к Pi, и другие для включения различной периферии ввода-вывода. Мы можем включить соответствующий DTB для периферии UART при помощи инструмента raspi-config.

Первая «прошивка»

Ну что ж. Чтобы статья имела реальную практическую ценность, давайте разберём простейшую «прошивку», сделанную с применением вышеописанных методов. Самое простое, что мне довелось реально реализовать для комплекса, это тест микросхемы SDRAM. Вот на этом примере и потренируемся.

Переменные среды uboot

При сборке или конфигурировании образа UBoot для устройства могут быть настроены различные переменные среды. Эти переменные управляют тем, какие операции выполняются при запуске. Такие переменные могут храниться различным образом. Иногда они жёстко прописаны в самом двоичном файле; также они могут находиться на разделе флэш-памяти, что позволяет пользователям изменять их через командную строку UBoot.

Мы можем исследовать переменные среды при помощи команды printenv:

Перепрошивка tinker board — s пошагово

Типовая ситуация — нужно обновить установленную операционную систему до менее корявой. Что нужно для прошивки:

Никаких дополнительных драйверов на компьютер/ноутбук устанавливать не нужно. Если  ваша плата Tinker Board не обнаруживается — читаем далее!

Утилита balenaEtcher-Portable работает как средство безопасной записи (флеширования)  операционной системы в память устройства и полностью совместима с ним.

Скачиваем совместимый образ для Вашей  Tinker board -s на сайте производителя или тут. Точно версию  и ревизию платы можно посмотреть на ее обратной стороне; в моем случае не стал отрывать гарантийную наклейку. Действовал наугад.  К чему это привело читаем в следующей главе :).

Устанавливаем на ноутбук (или обычный  компьютер) и запускаем balenaEtcher-Portable ; на первом этапе утилита попросит выбрать файл прошивки :

Соединяем кабелем ноутбук и плату  Tinker Board…

Питание микрокомпьютера Tinker board необходимо  непосредственно перед началом прошивки отключить!

На следующем этапе программа попросит найти устройство (наш одноплатный компьютер)…

При отключенном питании микрокомпьютера оно найдется и должно выглядеть примерно так:

Далее, начинаем непосредственно процесс прошивки:

Дожидаемся окончания процесса; после чего программа еще будет проверять целостность записанного в память устройства образа. Последнее можно прервать. После окончания процесса отсоединяем кабели и включаем питание. Если все хорошо, то система загрузится в штатном режиме.

Подбор spi-flash памяти для замены.

Флэш-память (SPI-Flash память) применяется в современных ЖК-телевизорах, автомобильных MP3-ресиверах, видеорегистраторах всех мастей, материнских платах персональных компьютеров, телевизионных приставках и даже в говорящих игрушках и фоторамках.

Как правило, в них используются микросхемы SPI-Flash памяти 25 серии (MX25L1633E, MX25L1605A, MX25Q32B-104HIP, W25Q32FVSSIG, G25Q16-15G, GD25Q32, HG25Q32BVSIG и т.п.). Питание у данной серии микросхем 3-ёх вольтовое (2,7…3,6V), в отличие от 24 серии у которой номинальное напряжение питания составляет 5 вольт, да и тип памяти другой.

Зачастую на корпусе микросхемы указывается неполная маркировка что-то вроде 25Q64BSIG, но обязательно присутствует надпись 25Qxx, 25Lxx или что в этом духе. Вместо xx – кодовая маркировка объёма памяти микросхемы.

Микросхемы имеют корпус SOIC-8 под планарный монтаж.

Также могут применяться и другие типы корпусов, например, SOIC-16 (300 mil).

Не исключено, что на практике встретите не только микросхемы spi-flash с выводами (pin), но и в корпусах под BGA-монтаж (на шарах) или с выводами в виде контакта (pad), например, WSON-8 (DFN-8). К счастью, такие в ЖК-телевизорах встречаются довольно редко. Но это пока…

Вместо родной микросхемы памяти лучше использовать новую или заведомо исправную. Родная может быть с браком или дефектом. Даже если мы её удачно перешьём рабочей прошивкой, то не факт, что микросхема будет корректно работать в будущем.

Родную микросхему SPI-Flash лучше не выкидывать или считать и сохранить с неё родную, заводскую прошивку. Это страховка на случай, если новая прошивка не подойдёт.

Бывает, что после повторной перепрошивки родной микросхемы памяти своим же заводским дампом телевизор начинает работать. Но, как уже говорил, лучше заменить микросхему новой.

По моему мнению, большинство “слётов” прошивки происходит из-за брака в микросхемах памяти, криво написанного софта (микропрограммы) или же после проблем с питанием, которые приводят к некорректной работе микросхемы. Порой приходится перепрошивать микросхемы памяти в телевизорах, которые пришли в ремонт по причине выхода из строя элементов блока питания (из-за грозы или скачков напряжения в электросети).

Наиболее часто в ЖК-телевизорах можно обнаружить микросхемы 25Q32 на 32 Мбит (4 Мбайт или 4194304 байт) и 25Q64 на 64 Мбит (8 Мбайт или 8388608 байт).

Почему 8388608 байт, а не 8000000? Кому не понятна эта путаница с килобайтами и мегабайтами, и, почему надо умножать не на 1000, а на 1024, советую погуглить “Кибибайт”. Возможно, развеете для себя очередной миф, наподобие того, что ток течёт не от плюса ” ” к минусу “-“, а наоборот.

Итак, с теорией более-менее разобрались, теперь займёмся практикой.

Перепрошивать память будем на примере ЖК-телевизора Mystery MTV-3223LT2. На фото он уже исправно работает.

Неисправность проявлялась следующим образом. Телевизор не включался, но при нажатии кнопки “Power” на пульте ДУ или кнопочной панели светодиодный индикатор менял свой цвет.

Подключение к uart и обнаружение командной строки uboot

Мы можем подключиться к командной строке UBoot при помощи следующего кода на python:

def console_setup():
    console=Console("/dev/ttyS0",baudrate=115200)
    ctx = Depthcharge(console,arch="arm")
    return ctx


В представленной выше функции и мы создаём объект

Console

, требующий, чтобы мы указали путь к последовательному порту и baud rate. Этот объект консоли затем используется для создания контекста Depthcharge, которым мы будем пользоваться для доступа к возможностям Depthcharge. В

есть хорошо описанный пример этого и подробно излагается процесс настройки.

Продолжение введения про подход к программированию плис

При разработке высокопроизводительной управляющей логики для ПЛИС обычно первую скрипку играет его величество конечный автомат. Именно на автоматах удаётся реализовать быстродействующую, но сложную логику. Но с другой стороны, автомат разрабатывается медленнее, чем программа для процессора, а его модификация — тот ещё процесс.

Существуют системы, упрощающие разработку и сопровождение автоматов. Одна из них даже разработана нашей компанией, но всё равно процесс проектирования для сколь-либо сложной логики получается не быстрым. Когда разрабатываемая система является конечным продуктом, имеет смысл подготовиться, спроектировать хороший управляющий автомат и потратить время на его реализацию.

Но с другой стороны, при разработке аппаратуры самый модный на сегодняшний день вариант, ПЛИС с ядром ARM, был отвергнут. Во-первых, по ценовым соображениям. Макетная плата на базе Cyclone V SoC стоит средне дорого, но, как ни странно, отдельная ПЛИС намного дороже.

Скорее всего, цена на макетные платы демпинговая, чтобы заманить разработчиков на использование данных ПЛИС, а платы продаются штучно. На серию придётся брать отдельные микросхемы. Но кроме того, есть ещё и «во-вторых». Во-вторых, когда я проводил опыты с Cyclone V SoC, оказалось, что не так эта процессорная система и производительна, если речь идёт об единичных обращениях к портам.

Пакетные — да, там работа идёт быстро. А в случае единичных обращений при тактовой частоте процессорного ядра 925 МГц, можно получить обращения к портам на частоте единицы мегагерц. Всем желающим я предлагаю повызывать штатную функцию постановки данных в FIFO блока UART, которая проверяет переполненность очереди, но вызывать её, когда очередь заведомо пуста, то есть, операциям ничего не мешает.

Производительность у меня вышла от миллиона до пятисот тысяч вызовов в секунду (разумеется, работа с памятью при этом шла на нормальной скорости, все кэши были настроены, даже вариант функции, не проверяющий FIFO на переполненность, работал быстрее, просто в обсуждаемой функции имеются обильно перемешанные записи и чтения из портов). Это FIFO!

Виной всему латентность. Между процессорным ядром и аппаратурой располагается от трёх мостов и более. Причём скорость доступа к портам зависит от контекста (несколько записей подряд будут идти быстро, но первое же чтение остановит процесс до полной выгрузки закэшированных данных, слишком много записей подряд — также замедлятся, так как исчерпаются буферы записи).

Наконец, осмотр трасс, накопленных в отладочном буфере, показал, что у архитектуры Cortex A один и тот же участок может исполняться за различное число тактов из-за сложной системы кэшей. В сумме, глядя на все эти факторы (цена, просадки быстродействия при работе с аппаратурой, нестабильность скорости доступа к аппаратуре, общая зависимость от контекста), было решено не ставить такую микросхему в комплекс.

Эксперименты с PSoC фирмы Cypress показали, что там ядро Cortex M даёт более предсказуемые и повторяемые результаты, но логическая ёмкость и предельная рабочая частота этих контроллеров не соответствовали ТЗ, поэтому их тоже отбросили.

Было решено установить недорогую типовую ПЛИС Cyclone IV и рекомендовать использование синтезируемого процессорного ядра NIOS II. Ну, а при необходимости — вести разработки с использованием любых других методов (автоматы, жёсткая логика и т.п.).

Отдельно упомяну (и даже выделю этот абзац), что основной процессор комплекса — это x86 (x64). Именно он является центральным процессором системы. Именно на нём исполняется основная логика комплекса. Процессорная система, о которой речь пойдёт ниже, призвана просто обеспечивать логику работы аппаратуры, «прошиваемой» в ПЛИС. Причём эта аппаратура реализуется только в том случае, если разработчикам не хватает штатных модулей, подключённых напрямую к центральному процессору.

Процесс разработки и отладки «прошивок»

Если комплекс Redd работает под управлением ОС Linux, то это не значит, что и разработка должна вестись в этой ОС. Redd — это удалённый исполнитель, а разработку следует вести на своей ЭВМ, какая бы там ОС ни стояла. У кого стоит Linux — тем проще, но кто привык к Windows (когда-то я очень не любил WIN 3.

Так как у меня с Линуксом дружба не задалась, пошаговых инструкций настройки среды под ним я не дам, а ограничусь общими словами. Кто с этой ОС работает — тому этого будет достаточно, а остальным… Поверьте, проще обратиться к системным администраторам. Я, в итоге, так и сделал. Но тем не менее.

Разборка автомата

Внутри автомат практически пуст, если не считать прикреплённого к экрану металлического корпуса.

Под металлической крышкой находится основная печатная плата автомата; аккуратно сняв дополнительную металлическую накладку, мы видим следующее:


Впервые изучая печатную плату, стоит записать все номера деталей и посмотреть, не удастся ли найти по ним даташиты. Первый компонент, бросившийся мне в глаза, выделен синим.

На этой компоненте написано

Rockchip RK3128

. Если поискать этот артикул онлайн, мы найдём очень много информации; информация ниже взята из

  • CPU
  • GPU
  • Память
  • Видео
  • Аудио
  • Разъёмы

Из одного этого описания мы уже достаточно много узнали о процессоре. Мы знаем архитектуру, доступную периферию и интерфейсы; они полезны для нас, потому что могут стать основой для векторов атак в будущем. Важно помнить, что на этом этапе процесса реверс-инжиниринга никакая информация не будет лишней. Мы хотим как можно больше узнать о цели, прежде чем попытаемся взаимодействовать с ней.

Непосредственно рядом с CPU есть ещё один компонент, на изображении ниже выделенный оранжевым.

Этот компонент имеет маркировку

SEC931 K4B2G1646F-BYMA

, и нам повезло найти этот артикул в результатах поиска на

Скриптинг uboot при помощи depthcharge

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

создали инструмент

, который поможет нам в этом. Можно использовать его для автоматизации процесса считывания и записи данных между флэш-чипом и внешним USB-накопителем. Наш скрипт должен уметь делать следующее:

  1. Подключаться к UART и обнаруживать командную строку UBoot
  2. Выполнять считывание и запись в SPI flash с помощю команд rksfc read/write
  3. Выполнять считывание и запись на USB-накопитель при помощи команд USB read/write

Сначала нужно установить модуль; мы можем установить

depthcharge

на Pi, выполнив

sudo pip install depthcharge

Содержимое файловой системы


Теперь, когда мы надёжным образом можем считывать и записывать флэш-память, давайте вкратце изучим её содержимое. Интересные файлы расположены в папке

/moo

. В этой папке находится эмулятор и его ресурсы. Moo — это специализированный эмулятор, использующий собственный формат ROM; в 2020 году исследователи

другую версию этого эмулятора. Однако если посмотреть на содержимое папки, в глаза бросается нечто интересное:

Структурная схема комплекса

Давайте рассмотрим структурную схему комплекса

В нижней части схемы расположился «вычислитель». Собственно, это стандартный PC с ОС Linux. Разработчики могут писать обычные программы на языках Си, C , Python и т.п., которые будут исполняться силами вычислителя. В правой верхней части расположены штатные порты типовых шин.

Слева располагается коммутатор стандартных устройств (SPI Flash, SD карта и несколько слаботочных твердотельных реле, которые могут, например, имитировать нажатие кнопок). А по центру размещается именно та часть, работу с которой и планируется рассмотреть в данном цикле статей.

Её сердцем является ПЛИС класса FPGA, из которой на разъём выходят прямые линии (могут использоваться как дифференциальные пары либо обычные небуферизированные линии), линии GPIO с задаваемым логическим уровнем, а также шина USB 2.0, реализуемая через микросхему ULPI.

Считывание и запись во флэш-память при помощи depthcharge

Теперь, когда мы подключились к интерфейсу, нам нужно реализовать команды read и write

rksfc

. Мы можем это сделать при помощи API

send_command()

утилиты depthcharge. Этот вызов API позволяет нам генерировать и передавать команду UBoot в командную строку и возвращать ответ. В примере ниже мы создаём команду чтения в переменной

cmd_str

и проверяем правильность форматирования аргументов, а затем отправляем команду при помощи API

send_command()

def rksfc_read(ctx,dest_addr,src_addr,size):
    cmd_str = f"rksfc read  0x{dest_addr:02x} 0x{src_addr:02x} 0x{size:02x}"
    resp = ctx.send_command(cmd_str)
    return resp

def rksfc_write(ctx,dest_addr,src_addr,size):
    cmd_str = f"rksfc write 0x{dest_addr:02x} 0x{src_addr:02x} 0x{size:02x}"
    resp = ctx.send_command(cmd_str)
    time.sleep(10)
    return resp


Реализовав считывание и запись флэш-памяти, мы должны теперь зарегистрировать стек USB, а затем выполнять считывание/запись с накопителя.

Считывание и запись на usb при помощи depthcharge

Аналогично тому, как мы реализовали команды

rksfc

, далее нам нужно реализовать команды

usb

. Этот процесс будет схож с тем, который мы использовали для команд

rksfc

Выводы и дальнейшая работа

В этом посте мы рассказали о том, как подходить к разборке встроенного устройства и идентифицировать потенциальные отладочные разъёмы при помощи мультиметров/логических анализаторов. Затем мы рассказали о том, как анализировать неизвестный трафик UART и подключаться к последовательному порту при помощи

screen

на Raspberry Pi. Подключившись к последовательному порту, мы обнаружили, что доступ к консоли UBoot можно получить нажатием

Ctrl-C

. Изучив консоль UBoot, мы написали скрипт

для извлечения каждого из разделов SPI flash на внешний флэш-накопитель. В следующем посте мы подробно рассмотрим двоичный файл UBoot и узнаем, как создавать и модифицировать схемы распределения памяти при помощи Ghidra; затем мы попробуем прошить устройство собственным ядром и установить свою прошивку.

Все использованные скрипты и инструменты можно найти на github.

Оцените статью
Huawei Devices
Добавить комментарий