Разборка прошивки электросамоката Xiaomi M365

Форум / Электротранспорт / Электросамокаты / Xiaomi Mijia Electric Scooter / Разборка прошивки электросамоката Xiaomi M365
#прошивка
+
Форум / Электротранспорт / Электросамокаты / Xiaomi Mijia Electric Scooter / Разборка прошивки электросамоката Xiaomi M365
Открыть шапку темы
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
26 july 2018, 19:47
Posted: 26 july 2018, 19:47
[quote="Conejo"]либо просто записать вместо бута копию таблицы векторов основной части, как писал выше - оно хоть и выглядит примитивно, но работать должно идеально, полный минимализм, никакого промежуточного кода вообще, ядро всё сделает само.[/quote]

Супер! Способ работает. Обычный HEX-editor - загрузить-отрезать-выгрузить и бинарник бута готов)

---

После запуска прошивки и мигания светодиодами, в свободной области flash автоматически образовалась таблица. Точно туда ничего не писал (были только FF). Похоже, это и есть пустая таблица пользовательских данных и активации.


Адрес: 0x0800F800

Длина: 512 Байт

(63-я страница)


И несколько ячеек в адресе 0x0800FC00

(это на последней 64-й странице flash-памяти)


 3   
Conejo
Форумчанин
МадридRating: 309
Conejo
26 july 2018, 22:41
Posted: 26 july 2018, 22:41

Смотрю эту страницу по 0800F800 - ошибка 27 как раз из-за неё, по смещению 1B4 (т.е. полный адрес 0800F9B4) должна быть копия серийного номера процессора (который регистр U_ID по адресу 1FFFF7E8, длина 0xC). Вообще есть команда 0x18 по UART, которая прописывает серийный номер (самоката) и заодно сама копирует этот U_ID откуда надо куда надо (видимо это и есть пресловутая активация, поразбираюсь с ней ещё), но если есть возможность вычитать U_ID вручную - можно и прописать его на нужное место вручную - в результате должны проскочить ошибку 27 (она сейчас рубит старт в самом-самом начале).

 3   
Conejo
Форумчанин
МадридRating: 309
Conejo
26 july 2018, 23:56
Posted: 26 july 2018, 23:56

Очередные найденные в прошивке мелочи:

- прошивка сама себе выставляет 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 (который не закрыт от чтения).

 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
27 july 2018, 3:02
Posted: 27 july 2018, 3:02

Столько инфо, просто нет слов!

[quote="Conejo"]при старте проверяет флажок и если тот взведён, копирует обновление из 08008400 по 08001000[/quote]

Тоже видел в дампе БМС две копии прошивки. Это и беспокоит. Значит, в том эксперименте по ошибочной заливке прошивки, контроллер завис не по причине передачи ей управления. Дело до копирования в рабочую область не дошло.

И загрузить другую программу на исполнение не так просто...

[quote="Conejo"]после успешного прохождения инициализации (мы туда пока не дошли) прошивается байтик защиты от чтения[/quote]

Ожидал, что сразу после старта прошивки, чип закроется. Удивился что этого не произошло. Теперь понятно.

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

---

Нарисовал карту памяти)


 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
27 july 2018, 12:04
Posted: 27 july 2018, 12:04

Если пофантазировать на тему создания "ремонтной  прошивки" для поднятия чистого чипа в контроллере:

[quote="Conejo"]обновление прошивается не сразу куда нужно, а в пустую область[/quote]

Если прошивку сделать в виде образа всей flash-памяти (64KB), то универсальный прошивальщик не сможет начать заливку через голову. Т.к она больше буфера приема. Тогда не нужно будет писать предупреждения, что только для ST-LINK. Станет безопасней.

[quote="Conejo"]должна быть копия серийного номера процессора (который регистр U_ID по адресу 1FFFF7E8, длина 0xC)[/quote]

Видимо это действие нужно добавить в бут-загрузчик (автоактивация). А чтобы прошивка не обнулила ячейки при первом старте, таблица в образе flash должна присутствовать изначально. Если это сработает, прошивка станет универсальной.

[quote="Conejo"]меняем на 01 - будет думать что уже залочено[/quote]

Очень было бы полезно для отладки и прямого редактирования чипа. Пока не пробовал.

 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
28 july 2018, 16:04
Posted: 28 july 2018, 16:04

Выгрузил из контроллера оригинальный boot-загрузчик и таблицу!

Механизм обновления в точности как описан выше. Сразу спешу успокоить, что выгрузить таким образом любую прошивку нельзя. Т.к программа-ридер попав в контроллер, частично затирает ее собой.

 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
28 july 2018, 18:47
Posted: 28 july 2018, 18:47

При извлечении дампа, самокат естественно окирпичился. Все что он делает - это циклически транслирует содержимое своей flash-памяти в шину UART батареи.


Теперь, имея полный дамп, методом простой сборки: (оригинальный boot + прошивка v1.34 + буфер с прошивкой v1.34 + ориг. таблица), собрал полный образ содержимого flash. Залил в чистый чип на макетке. Чип запустился и ведет себя адекватно.


Теперь попробую через ST-LINK залить этот образ (64KB) обратно в кирпич. И посмотреть что будет.

 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
28 july 2018, 21:29
Posted: 28 july 2018, 21:29

Подключил к кирпичу ST-LINK. Чип опознался. Он естественно залочен. Утилитой выключил защиту - чип превратился в чистый, но открытый для записи.


После обратной заливки полного образа flash-памяти в контроллер через ST-LINK, "кирпич" снова ожил. Работают все функции, которые проверял. Подключается к приложению. Отклонений не заметил.


После первого рестарта, чип автоматически закрылся от чтения. Кирпич, ожидаемо восстановлен!

 4   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
29 july 2018, 0:59
Posted: 29 july 2018, 0:59
[quote="Conejo"]на 01 - будет думать что уже залочено[/quote]
[quote="Conejo"]U_ID вручную - можно и прописать его на нужное место[/quote]

Работает!

---

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

По умолчанию черный. В MiHome обновился 1.34-->1.40.

SN в адресе 0x0800F820 текст по таблице ASCII


 4   
Conejo
Форумчанин
МадридRating: 309
Conejo
29 july 2018, 1:18
Posted: 29 july 2018, 1:18

Ed01, сколько отличных новостей!


Бут посмотрел уже, ничего более того, что предполагал о нём выше, там нет. Никаких загрузчиков по UART на случай повреждения основной части (как это часто бывает в бутах). Будет просто мигать светодиодом (если вообще поймёт что она повреждена, там единственная проверка - чтобы значение MSP в таблице векторов смотрело в RAM). Т.е. в случае окирпичивания - только полная перепрошивка (кстати, кроме SWD должен бы работать и заводской бутлоадер, активируемый ногой BOOT0. Она притянута к земле резистором R57).


Формат серийного номера проверяется только командой его записи (55 AA 20 18 10...), допустимые варианты:

M1Gxxxxxxxxxxx

1367xxxxxxxxxx
1613xxxxxxxxxx
16057xxxxxxxxx
1634xxxxxxxxxx

Запись серийного номера этой самой командой по всей видимости и является активацией, она также копирует в зону параметров правильный U_ID, тем самым выводя из ошибки 27, разбираюсь с этим. 

 4   
Conejo
Форумчанин
МадридRating: 309
Conejo
29 july 2018, 4:30
Posted: 29 july 2018, 4:30

Заборол активацию!

Пока всё на скорую руку, но работает: https://github.com/flowswitch/pyxm365

- 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 - должно в конце сказать ОК

 7   
M365 spain
Участник
Rating: 41
M365 spain
29 july 2018, 18:55
Posted: 29 july 2018, 18:55

Ed01 Привет! у меня есть контроллер кирпич.. скажи могу ли я теперь его оживить? уже пришел st-link с ибея.. Спасибо!

Conejo
Форумчанин
МадридRating: 309
Conejo
29 july 2018, 20:55
Posted: 29 july 2018, 20:55

M365 spain, не Мадрид случайно? Пиши в личку и заходи если что, денег не нужно, в порядке эксперимента.

 1   
Conejo
Форумчанин
МадридRating: 309
Conejo
30 july 2018, 4:13
Posted: 30 july 2018, 4:13

Алгоритм активации на человеческом языке для желающих запрограммировать не на Питоне.


Для чтения исходных данных, необходимых для расчёта авторизации, используется известная команда "прочитать регистры":

> 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;

}


 3   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
30 july 2018, 11:25
Posted: 30 july 2018, 11:25
Ответ пользователю
M365 spain : 29 july 2018, 18:55
на это сообщение (развернуть)

Ed01 Привет! у меня есть контроллер кирпич.. скажи могу ли я теперь его оживить? уже пришел st-link с ибея.. Спасибо!

Да, но при условии, что контроллер неисправен по вине прошивки.


Как это выяснить:

  • Подключите к контроллеру все разъемы (силовой и сигнальные).
  • Нажмите кнопку включения самоката на голове. Если в контроллере засветится красный диод, то вся цепочка источников DC (42V, 12V, 5V и 3.3V) исправна и на чип поступает питание.
  • Если диод не светится, проверьте тестером напряжение на выходе батареи (32-42V) и кнопку включения на голове. При отключенной батарее, кнопку можно "прозвонить" на нижнем разъеме контроллера (P1) между контактами "P" и "G". Нажатие на кнопку должно их соединять.
  • Если кнопка и батарея исправны, контакты проверены, но диод все равно не светится - то вероятно, виноваты преобразователи питания DC-DC. Контроллер неисправен физически и требует другого ремонта.

Если самокат включается (горит красный светодиод), но не реагирует на органы управления, не выключается, или мигает задним фонарем, то вероятно, это наш случай. Неисправна прошивка или сам чип.

 2   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
30 july 2018, 15:38
Posted: 30 july 2018, 15:38
[quote="Conejo"]Заборол активацию![/quote]

Conejo, Огромное спасибо за алгоритм и все ключевые наработки!

---

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

Похоже, для контроллера он безразличен. Но имеет значение для приложений:

  • Чтобы отличить самокат черного цвета от белого (входная страница MiHome)
  • Европейскую версию от китайской (и предоставить соответствующие обновления)
  • M365 от M187

По умолчанию - китайский черный.


При заливке прошивки в чип мы видим его содержимое. Вероятно, можно сделать за одно и copy-paste SN процессора, и записать серийный номер самоката. Если на руках неактивированный контроллер с закрытым чипом, то проще наверное, очистить чип и залить все заново не закрывая чип.


Однако, команда 18, ИМХО, была бы очень полезна для бесконтактного способа активации через BT

А сам алгоритм, еще и для автоактивации (если до такого дойдет)


p.s Табличка SN найдена в чатах


 2   
M365 spain
Участник
Rating: 41
M365 spain
30 july 2018, 15:41
Posted: 30 july 2018, 15:41

Ed01 контроллер полностью рабочий.. слетела именно прошивка при обновлении получил кирпич.

Ed01
Продвинутый форумчанин
Rating: 568
Ed01
30 july 2018, 16:21
Posted: 30 july 2018, 16:21
Ответ пользователю
M365 spain : 30 july 2018, 15:41
на это сообщение (развернуть)

Ed01 контроллер полностью рабочий.. слетела именно прошивка при обновлении получил кирпич.

Тогда, надеюсь в ближайшее время исправим)

 1   
Conejo
Форумчанин
МадридRating: 309
Conejo
30 july 2018, 17:32
Posted: 30 july 2018, 17:32

Ed01, однозначно, если кирпич и всё равно подключаться к SWD - смысла в лишних движениях через порт нет, всё сделается и по SWD. Активация через порт - для исправления ошибок 27 и 35 на живом контроллере без вскрытия (например новый неактивированный из Китая), она по идее вообще через Bluetooth должна отрабатывать. Позже посмотрю то же самое для BMS, попадались жалобы на ошибку 22, а там кроме UID похоже ещё контрольная сумма есть, активация поправит и то и другое.

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

 1   
Ed01
Продвинутый форумчанин
Rating: 568
Ed01
30 july 2018, 20:07
Posted: 30 july 2018, 20:07

Подключение ST-LINK к контроллеру:


Корпус контроллера посажен на термопасту и прикручен к деке 3-мя винтами. Откручиваем их. Снимаем прозрачную крышку, аккуратно поддев защелки по ее краям. Извлекаем плату контроллера.


К сожалению, на плате контроллера разъем SWD не распаян. Припаял пины (отрезки выводов от резисторов).

Стандартные пины от макеток не подойдут, они слишком толстые. Далее, к этим пинам можно подключить шлейф ST-LINK (который идет в комплекте). Можно обойтись и без пинов, просто припаяв провода.  Распиновка разъема SWD на фото.


UPDATE: Сократил описание, добавил фото.


 5