Это расшифровка дампа протокола команды 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
55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
55 55 55 55 55 55 55 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
DD 88 47 94 94 24 1C 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 ???
DD 88 47 94 94 24 Идентификатор чипа (chipid, серийный номер?) 0x2494944788DD.
1C 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
14 01 00 0F 66 99 FF 03 9F 00 9F 00 04 EF 00 01
C7 20 52 D8 06 02 32 00 0B 01 0B 01 3B 01 BB 00
6B 01 EB 02 EB 02 02 50 00 01 00 01 01 00 02 01
02 01 AB 01 05 35 00 00 01 01 00 00 38 FF A0 F0
77 03 02 40 77 03 02 F0 2C 01 B0 04 B0 04 32 00
20 4E 05 00 A2 AF F2 41 00 00 00 00 04 04 00 01
03 00 00 00 DE 73 F2 3A 00 02 00 00 01 00 00 00
00 00 00 00 00 00 01 22 BA CA E9 6E 53 D0 64 D7
31 5E 20 22 27 E2 3A CA AA 3D EC F3 1D 96 05 95
17 20 F8 D7 30 FC C3 02 00 00 00 00 00 00 00 00
EA E2 30 06
Здесь передаются первые 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
14 01 00 0F 66 99 FF 03 9F 00 9F 00 04 EF 00 01
C7 20 52 D8 06 02 32 00 0B 01 0B 01 3B 01 BB 00
6B 01 EB 02 EB 02 02 50 00 01 00 01 01 00 02 01
02 01 AB 01 05 35 00 00 01 01 00 00 38 FF A0 F0
77 03 02 40 77 03 02 F0 2C 01 B0 04 B0 04 32 00
20 4E 05 00 A2 AF F2 41 00 00 00 00 04 04 00 01
03 00 00 00 DE 73 F2 3A 00 02 00 00 01 00 00 00
00 00 00 00 00 00 01 22 BA CA E9 6E 53 D0 64 D7
31 5E 20 22 27 E2 3A CA AA 3D EC F3 1D 96 05 95
17 20 F8 D7 30 FC C3 02 00 00 00 00 00 00 00 00
EA E2 30 06
Вот так этот блок выглядит при просмотре содержимого файла eflash_loader_40m.bin (выделено желтым цветом):
![eflash loader 40m bootheader t](/images/stories/programming/Bouffalo/eflash_loader_40m-bootheader_t.png)
Это блок данных накладывается на следующую структуру 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
6B 01 EB 02 EB 02 02 50 00 01 00 01 01 00 02 01
02 01 AB 01 05 35 00 00 01 01 00 00 38 FF A0 F0
77 03 02 40 77 03 02 F0 2C 01 B0 04 B0 04 32 00
20 4E 05 00 A2 AF F2 41 00 00 00 00 04 04 00 01
03 00 00 00 DE 73 F2 3A 00 02 00 00 01 00 00 00
00 00 00 00 00 00 01 22 BA CA E9 6E 53 D0 64 D7
31 5E 20 22 27 E2 3A CA AA 3D EC F3 1D 96 05 95
17 20 F8 D7 30 FC C3 02 hash
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
93 8A 7A 6F
Здесь 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 (выделено желтым цветом):
![eflash loader 40m segment header t](/images/stories/programming/Bouffalo/eflash_loader_40m-segment_header_t.png)
В ответ BL602 в качестве подтверждения выдает 'OK' и зеркально эти же данные:
4F 4B 10 00 00 00 01 22 90 71 00 00 35 7D C8 6E
93 8A 7A 6F
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 .. ..
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. .. .. EF 50 10 0B B7 57
02 42 83 A7
Здесь закодированы следующие данные:
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 .. ..
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. .. .. 14 00 10 10 00 00
00 00 00 00
В ответ на каждый переданный блок 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
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
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
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
FF FF FF FF
Так передаются все блоки, и в каждой команде увеличивается запрашиваемый адрес:
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