Don’t be a Dilbert #4: грехи молодости

Предыстория

A long time ago in a… Тьфу! В далеком 2013 году один мой товарищ заказал мне девайс для создания «крутого танцевального номера», который он подсмотрел на бескрайних просторах интернета. У него был свой небольшой танцевальный коллектив и он хотел разнообразить репертуар номером с танцующими в темноте гражданками, на которых налеплены электролюминесцентные провода (т.н. «гибкий неон»), моргающие по заданному сценарию. К слову сказать, при грамотной постановке номер выглядит действительно круто!

Выглядело это в результате вот так

Для реализации этого проекта было разработано два устройства: передатчик соединялся к ноутбуком (для портабельности), а приемники вешались на танцующих. Передача происходила через радио-канал. На ноутбуке запускалась программа, управляющая всей этой вакханалией. Она выдавала в передатчик значения (ВКЛ/ВЫКЛ) для каждого приемника.

Носимый блок для светового шоу

И всё шло хорошо до тех пор пока мы не решили с заказчиком проапгрейдить всю эту систему. Предполагался новый передатчик и новый протокол общения с приемниками. Чтобы не лишать заказчика возможности выступать, на работу с новым передатчиком были прошиты только 3 блока (всего их было сделано 5). Но что-то не пошло с новой системой и заказчик продолжил выступать со старым передатчиком и двумя блоками, которых ему на тот момент хватало. На этом наша длинная и утомительная предыстория заканчивается.

Проблемы

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

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

Казалось бы, можно вылить прошивку из «старого» блока (который нормально работает со старым передатчиком) и просто зашить его в «новый» блок. Да, если бы я был чуть-чуть поумнее 5 лет назад, то так можно было бы сделать. Но тогда я был молодой и глупый, поэтому адреса приемников были (как это по-русски?) hardcoded в прошивке. Поэтому все пять блоков имели разную прошивку.

Binary patching

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

В блоке приемника стоит микроконтроллер MSP430G2553. Бегло просмотрев даташит я выяснил, что флэш память (вернее, та ее часть, где лежит программа) начинается у контроллера с адреса 0xC000. Начиная с этого адреса и нужно смотреть различия. Вытащив прошивку из двух работающих блоков с номерами 1 и 5 я получил следующую картинку:

Сравнение двух бинарников

Различия нашлись только в двух байтах. Однако, это мало чем помогло. Ни один из них не был похож на адрес, адреса были простые: с 1 до 5. Как из этих байтов получить нужную цифру осталось неясным. И так как времени оставалось все меньше, пришлось прибегнуть к более серьезным инструментам.

Я загрузил это непотребство в IDA и, опираясь на (не последний, но все-таки похожий исходник) определил названия некоторых переменных, что сразу резко облегчило задачу поиска нужного адреса. Открыв в дизассемблере нужный адрес, я увидел, что разница в прошивках блоков заключается в значении переменной offset, которая является не адресом (как я предполагал), а сдвигом в общей посылке. Таким образом, для первого блока сдвиг был 0, а для пятого — 8 (т.к. в посылке было по два байта для каждого блока).

IDA disassebler

Мне нужно было оживить блок №2, а значит выставить offset = 2. Путем нехитрых манипуляций с разбором специально собранного для этой цели бинарника, было выявлено, что для реализации инструкции mov.w #2, &0248 (адрес переменной offset) нужно записать в бинарник следующее: A2 43 48 02. Почему именно так — не знаю, никакой внятной информации о том, как преобразуются ассемблерные инструкции MSP430 в бинарник я не нашел. То есть, чтобы получить прошивку второго блока из прошивки пятого, мне надо заменить B2 42 на A2 43.
Теперь нужно только прошить получившийся бинарник в МК с помощью штатной утилиты UniFlash (к слову, вытаскивал прошивку я ей же). С первого раза почему-то не заработало (может перепутал адреса), пришлось повторить процедуру. Блок ожил и начал отвечать на посылки передатчика радостным морганием неонового провода.

Проверка сценария на двух блоках

Мораль на сегодня следующая: не теряйте исходники и сохраняйте бинарники прошивок. Никогда не знаешь, когда и при каких обстоятельствах они могут понадобится. Ну и, конечно, не зашивайте адреса намертво 🙂

DON’T BE A DILBERT!

About the Author: admin

Добавить комментарий