blflash: прошивальщик BL602, написанный на Rust |
![]() |
Добавил(а) microsin |
В разборках с протоколом прошивки BL602 очень помогла утилита blflash [1]. Она кроссплатформенная благодаря rust, можно установить и использовать как на Linux, так и на Windows. Как установить на Ubuntu, процесс по шагам: 1. Установка rust. Сначала надо установить Rust, для этого из домашней директории запустите команду [3]: $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Подтвердите установку по умолчанию (1), ответьте положительно на все запросы. После завершения работы установщика перезапустите терминал x-terminal-emulator (Alt+F4, Ctrl+Alt+t). 2. Закачка репозитория blflash. В любом каталоге, куда вы хотели бы поместить папку репозитория blflash [1], выполните команду: $ git clone https://github.com/spacemeowx2/blflash.git
Эта команда скачает репозиторий blflash, в текущем каталоге появится соответствующая папка blflash. 3. Компиляция blflash. Для компиляции blflash зайдите в папку blflash и скомпилируйте проект командой cargo build: $ cd blflash
$ cargo build
Через минуту процесс загрузки и компиляции завершится, появится каталог target/debug/, в котором будет скомпилированный бинарник blflash. Важное замечание: установка на Windows проходит аналогично, однако необходим тулчейн для компиляции кода C++ от Microsoft (Visual Studio Build Tools C++). Если тучейн не установлен, то rustup-init.exe предупредит вас об этом. Тулчейн устанавливается автоматически после установки Visual Studio, его можно скачать его с сайта Microsoft [4]. Выберите бесплатный вариант установки Community. Если Build Tools C++ уже установлен, то выполните следующие шаги: 1. Установка Rust. По ссылке [3] выберите закачку одного из вариантов установщиков, в зависимости от разрядности вашей Windows: "DOWNLOAD RUSTUP-INIT.EXE (32-BIT)" или "DOWNLOAD RUSTUP-INIT.EXE (64-BIT)". Закачается rustup-init.exe. 2. Запустите rustup-init.exe, откроется окно CMD со следующим диалогом выбора варианта установки. Welcome to Rust!
Выберите вариант 1 (просто нажмите Enter), начнется установка. По завершению установки нажмите Enter, окно консоли закроется. 3. Закачка репозитория blflash. Снова запустите cmd.exe, командой cd перейдите в любую папку, где должна будет находиться папка репозитория blflash. Для закачки репозитория выполните команду клонирования репозитория: m:\asm>git clone https://github.com/spacemeowx2/blflash.git
Cloning into 'blflash'...
remote: Enumerating objects: 582, done.
remote: Counting objects: 100% (98/98), done.
remote: Compressing objects: 100% (71/71), done.
remote: Total 582 (delta 45), reused 67 (delta 26), pack-reused 484
Receiving objects: 95% (553/582)
Receiving objects: 100% (582/582), 155.12 KiB | 2.22 MiB/s, done.
Resolving deltas: 100% (304/304), done.
4. Компиляция blflash. Зайдите в папку blflash, выполните команду установки cargo build, начнется загрузка и компиляция пакетов: m:\asm>cd blflash
После завершения процесса в папке blflash\target\debug\ появится исполняемый файл blflash.exe. m:\asm\blflash>cd target\debug
[Как пользоваться blflash] Получение подсказки: $ cd target/debug/
$ ./blflash
blflash 0.3.5
Сохранение содержимого памяти flash BL602: $ ./blflash dump dump_firmware.bin --port /dev/ttyUSB0
[INFO blflash::flasher] Start connection...
[TRACE blflash::flasher] 5ms send count 55
[TRACE blflash::flasher] handshake sent elapsed 9.04858ms
[INFO blflash::flasher] Connection Succeed
[INFO blflash] Bootrom version: 1
[TRACE blflash] Boot info: BootInfo { len: 14, bootrom_version: 1, otp_info:
[0, 0, 0, 0, 3, 0, 3, 0, dd, 88, 47, 94, 94, 24, 1c, 0] }
[INFO blflash::flasher] Sending eflash_loader...
[INFO blflash::flasher] Finished 2.733942606s 10.46KiB/s
[TRACE blflash::flasher] 5ms send count 500
[TRACE blflash::flasher] handshake sent elapsed 9.346236ms
[INFO blflash::flasher] Entered eflash_loader
[INFO blflash] Success
Прошивка: $ ./blflash flash firmware.bin --port /dev/ttyUSB0
[INFO blflash::flasher] Start connection...
[TRACE blflash::flasher] 5ms send count 55
[TRACE blflash::flasher] handshake sent elapsed 304µs
[INFO blflash::flasher] Connection Succeed
[INFO blflash] Bootrom version: 1
[TRACE blflash] Boot info: BootInfo { len: 14, bootrom_version: 1, otp_info:
[0, 0, 0, 0, 3, 0, 3, 0, dd, 88, 47, 94, 94, 24, 1c, 0] }
[INFO blflash::flasher] Sending eflash_loader...
[INFO blflash::flasher] Finished 3.0264115s 9.44KiB/s
[TRACE blflash::flasher] 5ms send count 500
[TRACE blflash::flasher] handshake sent elapsed 4.5616ms
[INFO blflash::flasher] Entered eflash_loader
[INFO blflash::flasher] Erase flash addr: 0 size: 47504
[INFO blflash::flasher] Program flash... c85e11a0083a27f72f6e1bab9b67cac98
d5d31ed90b64b78e6e89e070d782c58
[INFO blflash::flasher] Program done 1.2001555s 38.66KiB/s
[INFO blflash::flasher] Erase flash addr: e000 size: 272
[INFO blflash::flasher] Program flash... da4d2fe7d42a71246b0e84d64665b70ad
701435f89716c48e6f23ef55340eaa0
[INFO blflash::flasher] Program done 39.9625ms 6.81KiB/s
[INFO blflash::flasher] Erase flash addr: f000 size: 272
[INFO blflash::flasher] Program flash... da4d2fe7d42a71246b0e84d64665b70ad
701435f89716c48e6f23ef55340eaa0
[INFO blflash::flasher] Program done 21.0118ms 12.65KiB/s
[INFO blflash::flasher] Erase flash addr: 10000 size: 1052672
[INFO blflash::flasher] Program flash... 347fef1f1556baa72373c11b14cf61dc5
840a2877c603dfe57f856049554e8ce
[INFO blflash::flasher] Program done 24.2053376s 42.47KiB/s
[INFO blflash::flasher] Erase flash addr: 1f8000 size: 5671
[INFO blflash::flasher] Program flash... ae42d69b09c2eb134b202b412c00ff175
e10b625e2d3c0a2820378bd341926b8
[INFO blflash::flasher] Program done 113.0449ms 49.01KiB/s
[INFO blflash] Success
Это расшифровка дампа протокола команды blflash.exe dump dump_firmware.bin --port COM4, снятого под Windows 10 с помощью утилиты Device Monitoring Studio [7]. Далее рассмотрим процесс чтения по шагам. Передаваемые данные от утилиты blflash показаны синим шрифтом, а ответы от BL602 красным шрифтом. 1. Рукопожатие (handshaking). Утилита blflash.exe периодически отправляет пакеты рукопожатия (байты 0x55) и команду Get boot info (0x10), пока BL602 не ответит 0x4F 0x4B (OK): 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 10 00 00 00 В ответ BL602 посылает подтверждение 'OK': 4F 4B И далее BL602 посылает информацию о себе: 4F 4B 14 00 01 00 00 00 00 00 00 00 03 00 03 00 В этом пакете передается следующее: 4F 4B OK 14 00 Младший (0x14) и старший (0x00) байты длины пакета данных, который идет далее (т. е. далее идут 0x14 == 20 байт данных). 01 00 00 00 Версия Boot ROM (4 байта). 00 00 00 00 03 00 03 00 DD 88 47 94 94 24 1C 00 Это информация OTP info (16 байт). По ней хост получает информацию, относящуюся к BL602. Хост должен решить, требуется ли для BL602 подписанный образ, ориентируясь на значение sign_type. В соответствии с encrypted, хост также определяет, требует ли BL602 зашифрованный образ. Если известно, что чип не запускается с шифрованием и подписью, то анализ этой информации может быть пропущен. Структура данных OTP info: typedef struct { uint16_t len; // длина данных, начиная с bootrom_version uint32_t bootrom_version; // версия ROM-загрузчика uint8_t otp_info[16]; // информация OTP info }TBootInfo; Содержимое блока OTP info: 00 00 00 00 03 00 03 00 ??? 2. Передача RAM-загрузчика. Теперь утилита blflash должна передать содержимое файла загрузчика eflash_loader_40m.bin. Это программа RAM-загрузчика, которая обладает расширенным функционалом по сравнению с ROM-загрузчиком. Для этого blflash.exe посылает команду Load boot header (0x11): 11 00 B0 00 42 46 4E 50 01 00 00 00 46 43 46 47 Здесь передаются первые 0xB0 (176) байт из файла eflash_loader_40m.bin, т. е. следующие данные: 11 00 Команда 0x11 и зарезервированный байт 0x00 B0 00 Младший (0xB0) и старший (0x00) байты количества передаваемых далее байт. Т. е. далее идут 0x00B0 == 176 байт структуры заголовка загрузчика bootheader_t. 42 46 4E 50 01 00 00 00 46 43 46 47 Вот так этот блок выглядит при просмотре содержимого файла eflash_loader_40m.bin (выделено желтым цветом): Это блок данных накладывается на следующую структуру bootheader_t: typedef struct { uint32_t magiccode; // 4 uint32_t revison; // +4 = 8 boot_flash_cfg_t flashCfg; // +2 = 10 boot_clk_cfg_t clkCfg; // +16 = 26 ISP_protocol_BL602 bootcfg; // +4 = 30 uint32_t segment_cnt; // +4 = 34 uint32_t bootentry; /* точка входа образа */ // +4 = 38 uint32_t flashoffset; // +4 = 42 uint8_t hash[BFLB_BOOTROM_HASH_SIZE]; // +122 = 164 /* хэш образа */ uint32_t rsv1; // +4 = 168 uint32_t rsv2; // +4 = 172 uint32_t crc32; // +4 = 176 } __attribute__((packed)) bootheader_t; 42 46 4E 50 magiccode 'BFNP' 01 00 00 00 ревизия 46 43 flashCfg 46 47 14 01 00 0F 66 99 FF 03 9F 00 9F 00 04 EF clkCfg 00 01 C7 20 bootcfg 52 D8 06 02 segment_cnt 32 00 0B 01 bootentry 0B 01 3B 01 flashoffset BB 00 00 00 00 00 rsv1 00 00 00 00 rsv2 EA E2 30 06 crc32 Примечание: описание структур boot_flash_cfg_t, boot_clk_cfg_t, ISP_protocol_BL602 см. в статье [2]. В ответ BL602 посылает подтверждение 'OK': 4F 4B 3. Далее blflash.exe посылает команду загрузки заголовка сегмента Load Segment Header (0x17): 17 00 10 00 00 00 01 22 90 71 00 00 35 7D C8 6E Здесь 17 00 это код команды и зарезервированный байт, 10 00 длина блока данных (16 байт). 16 байт это структура segment_header_t: typedef struct { uint32_t destaddr; uint32_t len; uint32_t rsvd; uint32_t crc32; } __attribute__((packed)) segment_header_t; 00 00 01 22 destaddr 90 71 00 00 len 35 7D C8 6E rsvd 93 8A 7A 6F crc32 Данные segment_header_t это следующие 16 байт из того же файла eflash_loader_40m.bin. Вот так этот блок выглядит при просмотре содержимого файла eflash_loader_40m.bin (выделено желтым цветом): В ответ BL602 в качестве подтверждения выдает 'OK' и зеркально эти же данные: 4F 4B 10 00 00 00 01 22 90 71 00 00 35 7D C8 6E 4. blflash.exe начинает передавать данные из файла eflash_loader_40m.bin, пропустив 0xC0 байт от начала этого файла (от начала идет заголовок bootheader_t, который был передан на шаге 2, потом segment_header_t, переданный на шаге 3). Данные передаются блоками по 0x0FA0 = 4000 байт. Пример передачи одного такого блока: 18 00 A0 0F 97 11 01 20 .. .. Здесь закодированы следующие данные: 18 00 Команда Load Segment Data (0x18) и зарезервированный байт (0x00). A0 0F Младший (0xA0) и старший (0x0F) длины передаваемого блока данных, т. е. 0x0FA0 == 4000 байт. 97 11 01 20 .. .. 02 42 83 A7 4000 байт из файла eflash_loader_40m.bin без всякой контрольной суммы. В последнем блоке передается оставшееся количество байт (0x0430 = 1072 байта): 18 00 30 04 06 59 65 61 .. .. В ответ на каждый переданный блок BL602 отвечает 'OK': 4F 4B 5. blflash.exe посылает команду Check image (0x19): 19 00 00 00 BL602 проверяет образ, и посылает в ответ 'OK': 4F 4B 6. blflash.exe посылает команду Run image (0x1A): 1A 00 00 00 BL602 посылает в ответ 'OK': 4F 4B После этой команды активизируется RAM-загрузчик, который может работать на повышенной скорости UART, до 2 мегабит. 7. blflash.exe посылает рукопожатие на повышенной скорости, 660 байт 0x55: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 BL602 посылает в ответ 'OK': 4F 4B 8. blflash.exe посылает команды flash_read (0x32), вычитывая блоки один за другим по 4 килобайта: 32 00 08 00 00 00 00 00 00 10 00 00 Здесь посылаются следующие данные: 32 00 Команда flash_read (0x32) и зарезервированный байт (0x00). 08 00 Младший (0x08) и старший байт (0x00) количества байт в пакете. Таким образом, дальше идут 0x0008 = 8 байт. 00 00 00 00 Начальный адрес, откуда читать данные (0x00000000). 00 10 00 00 Сколько байт прочитать (0x00001000 = 4096 байт). В ответ BL602 передает 'OK' (4F 4B), запрошенное количество байт (0x1000 = 4096) и далее сами данные, без контрольной суммы: 4F 4B 00 10 42 46 4E 50 01 00 00 00 46 43 46 47 Так передаются все блоки, и в каждой команде увеличивается запрашиваемый адрес: 32 00 08 00 00 10 00 00 00 10 00 00 32 00 08 00 00 20 00 00 00 10 00 00 32 00 08 00 00 30 00 00 00 10 00 00 .. .. .. .. .. .. .. .. .. .. .. .. 32 00 08 00 00 F0 0F 00 00 10 00 00 Здесь приведен дамп обмена команды прошивки flash BL602 (blflash.exe flash firmware.bin --port COM4), снятый с помощью снифера Device Monitoring Studio [7]. Шаги 1 .. 7 те же самые - рукопожатие, отправка eflash_loader_40m.bin, проверка образа, запуск образа, рукопожатие на повышенной скорости (см. предыдущую врезку "Расшифровка протокола чтения flash-памяти BL602"). Начиная с шага 8 процесс меняется. 8. blflash.exe посылает команду flash_readSha (0x3D): 3D 00 08 00 00 00 00 00 90 B9 00 00 В этом пакете: 3D 00 Код команды и зарезервированный байт. 08 00 Количество байт, которое идет далее (8 байт). 00 00 00 00 начальный адрес (0x00000000). 90 B9 00 00 конечный адрес, не включая. Таким образом, должно быть вычислена SHA256 от (0x0000B990 - 0x00000000) == 47504 байт, начиная с адреса 0. BL602 в ответ посылает: 4F 4B 20 00 5E 5E FA 55 7A A8 31 C7 FC B8 A2 A4 В этом пакете: 4F 4B 'OK' 20 00 Младший (0x20) и старший байт (0x00) количества байт хэша SHA256, которые идут далее (0x0020 == 32 байта). 5E 5E FA 55 7A A8 31 C7 FC B8 A2 A4 9. blflash.exe проверяет соответствие хеша в своем образе файла для этого блока с хешем, который прислал BL602. В нашем примере хэш не совпал, поэтому blflash.exe посылает команду flash_erase (0x30): 30 00 08 00 00 00 00 00 90 B9 00 00 В этом пакете: 30 00 Код команды (0x30) и зарезервированный байт (0x00). 08 00 Количество байт, которое идет далее (8 байт). 00 00 00 00 начальный адрес 0x00000000. 90 B9 00 00 конечный адрес 0x0000B990. BL602 посылает в ответ 'OK': 4F 4B 10. blflash.exe посылает команду flash_write (0x31): 31 00 A4 0F 00 00 00 00 42 46 4E 50 01 00 00 00 В этом пакете: 31 00 Код команды flash_write. A4 0F Размер передаваемых данных (0x0FA4 = 4004 байта). В этот размер входит адрес назначения (4 байта) и сами данные (4000 байт). 00 00 00 00 Адрес назначения (0x00000000). 42 46 4E 50 .. FF FF FF Записываемые данные. В ответ BL602 посылает 'OK': 4F 4B Далее blflash посылает таким же образом следующие блоки данных, а BL602 отвечает на них 'OK': 31 00 A4 0F A0 0F 00 00 (0x0FA0 = 4000 байт, начиная с адреса 0x00000FA0) Таким образом, записываются данные в ранее стертом блоке, причем по возможности пропускаются чистые области (содержимое которых заполнено байтами 0xFF). 11. blflash проверяет только что записанный блок отправкой все той же команды flash_readSha (0x3D): 3D 00 08 00 00 00 00 00 90 B9 00 00 В ответ на эту команду BL602 присылает хэш SHA256 (см. шаг 8). После этого процесс прошивки продолжается аналогичным образом, с повторением шагов 8, 9, 10, 11. Общий алгоритм следующий: (A) Запрашивается SHA256 блока у BL602, сравнивается на соответствие с записываемым файлом (шаг 8). (B) Было совпадение? Если да, то происходит увеличение адреса, и переход на (A), пока все данные файла не будут записаны. Если же SHA256 не совпало, то (C). (C) Стирается не совпавший блок в BL602 (шаг 9), и записывается данными из файла порциями по 4000 байт (шаг 10), последняя порция может быть меньше. Качество записи проверяется по SHA256 (шаг 11). После этого происходит увеличение адреса, и если данные файла не закончились, то переход на (A). (D) Прошивка завершена (шаг 12). В моем случае стирались, и потом записывались следующие блоки: 30 00 08 00 00 00 00 00 90 B9 00 00 00000000 0000B990 12. Прошивка завершена. Передается команда сброса 0x21 (опциональный шаг). [Ссылки] 1. spacemeowx2 / blflash site:github.com. |