![]() | This forum section is linked to the series: Xiaomi Mijia Rating: 4.3 |
[quote="Conejo"]либо просто записать вместо бута копию таблицы векторов основной части, как писал выше - оно хоть и выглядит примитивно, но работать должно идеально, полный минимализм, никакого промежуточного кода вообще, ядро всё сделает само.[/quote]
Супер! Способ работает. Обычный HEX-editor - загрузить-отрезать-выгрузить и бинарник бута готов)
---
После запуска прошивки и мигания светодиодами, в свободной области flash автоматически образовалась таблица. Точно туда ничего не писал (были только FF). Похоже, это и есть пустая таблица пользовательских данных и активации.
Адрес: 0x0800F800
Длина: 512 Байт
(63-я страница)
И несколько ячеек в адресе 0x0800FC00
(это на последней 64-й странице flash-памяти)
Смотрю эту страницу по 0800F800 - ошибка 27 как раз из-за неё, по смещению 1B4 (т.е. полный адрес 0800F9B4) должна быть копия серийного номера процессора (который регистр U_ID по адресу 1FFFF7E8, длина 0xC). Вообще есть команда 0x18 по UART, которая прописывает серийный номер (самоката) и заодно сама копирует этот U_ID откуда надо куда надо (видимо это и есть пресловутая активация, поразбираюсь с ней ещё), но если есть возможность вычитать U_ID вручную - можно и прописать его на нужное место вручную - в результате должны проскочить ошибку 27 (она сейчас рубит старт в самом-самом начале).
Очередные найденные в прошивке мелочи:
- прошивка сама себе выставляет VTOR как надо перед включением прерываний, так что мои опасения были зря.
- после успешного прохождения инициализации (мы туда пока не дошли) прошивается байтик защиты от чтения, если не прошит. Для экспериментов можно запатчить это дело: по адресу 0x08002756 (т.е. смещение 0x1756 от начала файла) 00 меняем на 01 - будет думать что уже залочено. Адрес для версии 1.40 (для других версий ищите последовательность 03 49 00 20 C9 69 89 07 00 D5 01 20 70 47, нужный байт выделен жирным)
- данные в странице 0800FC00 управляют механизмом обновления прошивки в бутлоадере. Суть примерно такая: обновление прошивается не сразу куда нужно, а в пустую область по адресу 08008400, в странице 0800FC00 выставляется флажок "обновление есть" (0800FC04 = 1) и его размер (в страницах? 0800FC08=размер) и делается перезагрузка. Далее бутлоадер (которого у нас пока нет) при старте проверяет флажок и если тот взведён, копирует обновление из 08008400 по 08001000 (указанного размера), сбрасывает флажок и дальше стартует уже свежее приложение. Видел тот же самый алгоритм в бутлоадере BMS (который не закрыт от чтения).
Столько инфо, просто нет слов!
[quote="Conejo"]при старте проверяет флажок и если тот взведён, копирует обновление из 08008400 по 08001000[/quote]
Тоже видел в дампе БМС две копии прошивки. Это и беспокоит. Значит, в том эксперименте по ошибочной заливке прошивки, контроллер завис не по причине передачи ей управления. Дело до копирования в рабочую область не дошло.
И загрузить другую программу на исполнение не так просто...
[quote="Conejo"]после успешного прохождения инициализации (мы туда пока не дошли) прошивается байтик защиты от чтения[/quote]
Ожидал, что сразу после старта прошивки, чип закроется. Удивился что этого не произошло. Теперь понятно.
Если получится с инициализацией, из недостатков стороннего бута, только невозможность обновления.
---
Нарисовал карту памяти)
Если пофантазировать на тему создания "ремонтной прошивки" для поднятия чистого чипа в контроллере:
[quote="Conejo"]обновление прошивается не сразу куда нужно, а в пустую область[/quote]
Если прошивку сделать в виде образа всей flash-памяти (64KB), то универсальный прошивальщик не сможет начать заливку через голову. Т.к она больше буфера приема. Тогда не нужно будет писать предупреждения, что только для ST-LINK. Станет безопасней.
[quote="Conejo"]должна быть копия серийного номера процессора (который регистр U_ID по адресу 1FFFF7E8, длина 0xC)[/quote]
Видимо это действие нужно добавить в бут-загрузчик (автоактивация). А чтобы прошивка не обнулила ячейки при первом старте, таблица в образе flash должна присутствовать изначально. Если это сработает, прошивка станет универсальной.
[quote="Conejo"]меняем на 01 - будет думать что уже залочено[/quote]
Очень было бы полезно для отладки и прямого редактирования чипа. Пока не пробовал.
Выгрузил из контроллера оригинальный boot-загрузчик и таблицу!
Механизм обновления в точности как описан выше. Сразу спешу успокоить, что выгрузить таким образом любую прошивку нельзя. Т.к программа-ридер попав в контроллер, частично затирает ее собой.
При извлечении дампа, самокат естественно окирпичился. Все что он делает - это циклически транслирует содержимое своей flash-памяти в шину UART батареи.
Теперь, имея полный дамп, методом простой сборки: (оригинальный boot + прошивка v1.34 + буфер с прошивкой v1.34 + ориг. таблица), собрал полный образ содержимого flash. Залил в чистый чип на макетке. Чип запустился и ведет себя адекватно.
Теперь попробую через ST-LINK залить этот образ (64KB) обратно в кирпич. И посмотреть что будет.
Подключил к кирпичу ST-LINK. Чип опознался. Он естественно залочен. Утилитой выключил защиту - чип превратился в чистый, но открытый для записи.
После обратной заливки полного образа flash-памяти в контроллер через ST-LINK, "кирпич" снова ожил. Работают все функции, которые проверял. Подключается к приложению. Отклонений не заметил.
После первого рестарта, чип автоматически закрылся от чтения. Кирпич, ожидаемо восстановлен!
[quote="Conejo"]на 01 - будет думать что уже залочено[/quote]
[quote="Conejo"]U_ID вручную - можно и прописать его на нужное место[/quote]
Работает!
---
От цвета самоката зависит его серийный номер. Но похоже, может быть любой (см. скриншоты).
По умолчанию черный. В MiHome обновился 1.34-->1.40.
SN в адресе 0x0800F820 текст по таблице ASCII
Ed01, сколько отличных новостей!
Бут посмотрел уже, ничего более того, что предполагал о нём выше, там нет. Никаких загрузчиков по UART на случай повреждения основной части (как это часто бывает в бутах). Будет просто мигать светодиодом (если вообще поймёт что она повреждена, там единственная проверка - чтобы значение MSP в таблице векторов смотрело в RAM). Т.е. в случае окирпичивания - только полная перепрошивка (кстати, кроме SWD должен бы работать и заводской бутлоадер, активируемый ногой BOOT0. Она притянута к земле резистором R57).
Формат серийного номера проверяется только командой его записи (55 AA 20 18 10...), допустимые варианты:
M1Gxxxxxxxxxxx
1367xxxxxxxxxx
1613xxxxxxxxxx
16057xxxxxxxxx
1634xxxxxxxxxx
Запись серийного номера этой самой командой по всей видимости и является активацией, она также копирует в зону параметров правильный U_ID, тем самым выводя из ошибки 27, разбираюсь с этим.
Заборол активацию!
Пока всё на скорую руку, но работает:
- cтавим Python 2.7.x (отсюда www.python.org)
- в него доустанавливаем модуль pyserial (из консоли выполняем команду pip install pyserial)
- подключаемся к порту контроллера, тут варианты: я подключаюсь прямо к порту BMS, однако если Bluetooth компьютера видит порт "головы", то должно бы работать и через него (у меня тут не весь скутер, не на чем проверить)
- редактируем config.py, прописываем туда правильный номер порта
- пробуем считать дамп настроек ESC командой python read_esc.py - если всё хорошо, появится файл esc_config.bin - это копия того, что по 0800F800
- редактируем wr_sn.py, выставляем там желаемый серийный номер (см. пояснения внутри)
- запускаем python wr_sn.py - должно в конце сказать ОК
Алгоритм активации на человеческом языке для желающих запрограммировать не на Питоне.
Для чтения исходных данных, необходимых для расчёта авторизации, используется известная команда "прочитать регистры":
> 55 AA 03 20 01 ix ss ckl ckh
< 55 AA ss+2 23 01 ix data[ss] ckl ckh
где ix - адрес "регистра, ss - размер
Собственно команда авторизации:
> 55 AA 14 20 18 10 sn[0x0E] auth[4] ckl ckh
< 55 AA 02 23 18 rr ckl ckh
Где sn - новый серийный номер, длина 0x0E
auth - авторизация, длина 4, это uint32 little endian
rr - результат, 00-ошибка, 01-ок
Авторизация рассчитывается из нового sn, старого sn (читается с ix=0x10, ss=0x0E как байтовый массив), части U_ID (читается с ix=0xDE, ss=4 как uint32 little endian), код на С:
uint32 CalcSnAuth(uint8 new_sn[], uint8 old_sn[], uint32 uid)
{
int32 s=0, i;
for(i=0; i<0x0E; i++)
{
s+=old_sn[i];
s*=new_sn[i];
}
s+=uid+(uid<<4);
if (s<0) s = -s;
return s % 1000000;
}
Ed01 Привет! у меня есть контроллер кирпич.. скажи могу ли я теперь его оживить? уже пришел st-link с ибея.. Спасибо!
Да, но при условии, что контроллер неисправен по вине прошивки.
Как это выяснить:
Если самокат включается (горит красный светодиод), но не реагирует на органы управления, не выключается, или мигает задним фонарем, то вероятно, это наш случай. Неисправна прошивка или сам чип.
[quote="Conejo"]Заборол активацию![/quote]
Conejo, Огромное спасибо за алгоритм и все ключевые наработки!
---
Из экспериментов с серийным номером прослеживается следующее:
Похоже, для контроллера он безразличен. Но имеет значение для приложений:
По умолчанию - китайский черный.
При заливке прошивки в чип мы видим его содержимое. Вероятно, можно сделать за одно и copy-paste SN процессора, и записать серийный номер самоката. Если на руках неактивированный контроллер с закрытым чипом, то проще наверное, очистить чип и залить все заново не закрывая чип.
Однако, команда 18, ИМХО, была бы очень полезна для бесконтактного способа активации через BT
А сам алгоритм, еще и для автоактивации (если до такого дойдет)
p.s Табличка SN найдена в чатах
Ed01 контроллер полностью рабочий.. слетела именно прошивка при обновлении получил кирпич.
Тогда, надеюсь в ближайшее время исправим)
Ed01, однозначно, если кирпич и всё равно подключаться к SWD - смысла в лишних движениях через порт нет, всё сделается и по SWD. Активация через порт - для исправления ошибок 27 и 35 на живом контроллере без вскрытия (например новый неактивированный из Китая), она по идее вообще через Bluetooth должна отрабатывать. Позже посмотрю то же самое для BMS, попадались жалобы на ошибку 22, а там кроме UID похоже ещё контрольная сумма есть, активация поправит и то и другое.
Вообще подумываю сделать полный разбор протокола, в прошивке видны команды, которые не снять "с провода" при нормальной работе, может что интересное ещё найдётся.
Подключение ST-LINK к контроллеру:
Корпус контроллера посажен на термопасту и прикручен к деке 3-мя винтами. Откручиваем их. Снимаем прозрачную крышку, аккуратно поддев защелки по ее краям. Извлекаем плату контроллера.
К сожалению, на плате контроллера разъем SWD не распаян. Припаял пины (отрезки выводов от резисторов).
Стандартные пины от макеток не подойдут, они слишком толстые. Далее, к этим пинам можно подключить шлейф ST-LINK (который идет в комплекте). Можно обойтись и без пинов, просто припаяв провода. Распиновка разъема SWD на фото.
UPDATE: Сократил описание, добавил фото.
Language: English Scope: Форум Layout: Adaptive Except where otherwise noted, content on this site is licensed under the following license: CC Attribution-Share Alike 4.0 International © electro.club, 2015-2022 [email protected] |