Files
rt-4d/docs/fm100b-firmware-re.md
T
viktorиClaude Opus 4.8 bf55e9e53f Вариант A: загрузчик HKLFBOOT write-only (read флеша нет) — дамп через него недостижим
Загрузчик ловится/держится на Linux (catch link-check + SetBaudRate смена бода). Но read-команды
флеша нет (0x03/08/09/0a/0b не дают флеш; 0x08 = битовая карта). Сходится с DMR Upgrade Tool
(только erase/write). Дамп только физически (SPI-клипса). Но BK4819 найден -> TX-фикс без дампа.
tools/bk_module_dump.py, bk_bootloader_catch.py, bk_read_probe.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NikMGoqQWWk9wy2ww2vJAr
2026-07-24 20:09:31 +09:00

172 строки
18 KiB
Markdown
Исходник Ответственный История

Этот файл содержит неоднозначные символы Юникода
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FM100B (HF6853/Auctus A6) — реверс прошивки модуля и вокодера
Образы: `firmware/FM100B_V1.2.0.32_20260130.bin` (1 527 808 Б), `FM100B_V1.2.0.13` (тот же размер).
Грузятся из внешнего SPI-flash модуля (см. [[rt4d-fm100b-is-hf6853]]).
## Архитектура кода
- **ARM.** Вектор @0x0: `EA00000E` (B reset) + 7×`LDR PC,[PC,#0x14]` (undef/SWI/abort/IRQ/FIQ).
- **Reset @0x40:** маскирует IRQ/FIQ, ставит режимы CPSR (SYS/FIQ/IRQ стеки) — классический ARM-старт,
затем переключается в **Thumb-2 с FPU** (`b580` push, `ed4d` VPUSH, `f38b` MSR) — основной код Thumb-2.
- Значит ядро XCPU — ARM с VFP (ARM11/Cortex-A/R класс), не Cortex-M. База RAM ≈ 0x0360_xxxx
(по литералам векторов). Символов НЕТ (release), строки — PC-relative (базу в лоб по литералу не взять).
## Карта регионов (по энтропии + строкам)
| Offset | Что |
|--------|-----|
| 0x000000 | вектора ARM + startup |
| 0x000100–0x0b0000 | основной код (Thumb-2), ent≈6.3 |
| 0x0b0000–0x0d0000 | разреженная регулярная таблица (нули + повтор `80 29`), ent 2.5–3.6 — коэфф./LUT (не AMBE-кодбук) |
| 0x0cc000–0x0d0000 | **символы/лог-строки аудио-подсистемы** (ATC_*, «vocoder mutex», «codec ad/da») |
| 0x0d0000–0x160000 | код/данные |
| 0x15b000–0x15e000 | **WebRTC-аудио**: `VocoderVersion\WebRTC\source\nsx_core.c` (шумодав NSX), `digital_agc.c` (AGC); функции `WebRtcNsx_ProcessCore`, `WebRtcAgc_CalculateGain` |
| ~0x160000 | строки/константы, `EasyFlash` (NV) |
| 0x170000–конец | хвост (padding) |
## ⭐ Что такое «вокодер» в прошивке
**«Vocoder» здесь = WebRTC audio processing** (noise suppression NSX + digital AGC), т.е. пред/пост-
обработка ГОЛОСА, а **НЕ AMBE-кодек**. Это открытый код (github WebRTC) — можно понять и тюнить.
**Сам AMBE (DMR-кодек) — вне модифицируемого ARM-кода.** В образе только ИНТЕРФЕЙС к нему:
`ATVoiceEncCnf`/`ATVoiceDecCnf`, `ATCRecvAmbedataCnf`/`ATCRecvAmbe6sdataCnf`, `vocoder mutex`.
AMBE выполняется на отдельном DSP-ядре/хардварном блоке A6 (RDA8809 двухъядерный; jhart99:
«вокодер на шине XCPU»). Отдельного DSP-блоба в этом образе по энтропии не видно → AMBE, вероятно,
в ROM чипа или в кремнии.
## Используемые open-source библиотеки (найдены по строкам)
- **EasyFlash** (armink/EasyFlash) — NV-хранилище во flash. **Здесь лежит калибровка** (VCCN/Mod/PWR,
см. docs/tuning-software-protocol.md). Формат документирован → можно читать/править cal прямо во flash-дампе.
- **WebRTC** (nsx, digital_agc) — аудио.
## Честная оценка «свой вокодер»
- Заменить AMBE на свой кодек **для эфирного DMR нельзя** — другие рации ждут AMBE (нет совместимости).
- Сам AMBE в этом ARM-образе не лежит (DSP/ROM) → «переписать вокодер» здесь нечего.
- РЕАЛЬНО моддится: параметры WebRTC (агрессивность шумодава/AGC, качество звука), кодек-гейны
(`ATC_MICCodecGainSet`/`ATC_SPKCodecGainSet`), DTMF, логика управления DMR, NV-калибровка (EasyFlash).
## ⭐ Таблица разделов flash модуля (найдена @0x15e828)
```
Bootloader | Application | RF Firmware | NET info
```
**SoC модуля = Beken, серия «beken378»** (пути `beken378\intercom\` в образе; HAL `bk_gpio_*`/`bk_pwm_*`/
`bk_flash_*`; приложение `INTERCOM`; синтезатор `DPLL`; RTOS + RT-Thread FAL/EasyFlash + WebRTC).
Это ОКОНЧАТЕЛЬНАЯ идентификация — НЕ Auctus A6/RDA8809 (та гипотеза неверна; RDA-debug молчал именно
потому, что чип не RDA). Схемная маркировка чипа — «HF6853».
Разбивка flash модуля:
- **Bootloader** — загрузчик (в т.ч. режим «Обновление DMR чипа»).
- **Application** — ЭТО наш `FM100B_*.bin` (управление + WebRTC-аудио + интерфейс к AMBE).
- **RF Firmware** — ОТДЕЛЬНЫЙ раздел: DMR-baseband / модем / **предположительно AMBE-DSP**. У нас его НЕТ.
- **NET info** — NV-настройки (**EasyFlash ENV** — то, что нужно для доступа к хранимым параметрам).
Плюс сырые cal-таблицы во flash: `manual_cal_write_flash`, `save txpwr tab to flash` (темп-компенсация
мощности), efuse-cal ADC/батареи (`efuse get cal`, `CodeOffset`, `dvbatref`), кодек `set dac vol dig/ana`.
## Как получить NV/RF Firmware: ДАМП flash модуля
Ни NV, ни RF Firmware в образе Application нет — нужен **дамп SPI-flash модуля** (все разделы).
Путь: протокол загрузчика/апдейтера (режим «Обновление DMR чипа» активен) — у него есть чтение flash.
Реверснуть команду чтения из `RT-4D Upgrade V3_25_260205.exe` (как сделали с тюнером) → безопасно
снять полный дамп → распарсить EasyFlash ENV (NET info) + разобрать RF Firmware (vocoder/DMR).
Это разблокирует СРАЗУ: NV-настройки, калибровку, и сам DMR-baseband для реверса.
**ВАЖНО (проверено 24.07):** `RT-4D Upgrade` шьёт AT32, НЕ модуль (см. ниже). Реальные пути дампа:
- Через **загрузчик Beken** модуля (download-режим): если модуль выставить в штатный UART-bootloader
Beken, подойдёт экосистема **bk7231tools / BKFIL / BK7231GUIFlashTool** (openshwprojects) — они
умеют backup/read flash. НО эти тулы под WiFi-чипы BK7231; протокол загрузчика 378x надо проверить.
Как войти в download модуля из RT-4D — неизвестно (возможно boot-пин/спец-команда); ЖИВАЯ операция.
- Либо найти команду чтения flash в протоколе «Обновление DMR чипа» (у приложения её нет — см. API).
Оба варианта — при владельце (риск). Ссылки: github.com/openshwprojects/BK7231GUIFlashTool.
## Апдейтеры: кто что прошивает (реверс .NET)
- **RT-4D Upgrade V3_25** (`Ido_Update`, DES+RSA) прошивает **AT32 (главный CPU рации)**, НЕ модуль:
команды `Send_Connect=39 33 05 10 c9`, `Send_Update=39 33 05 55 0e`, `Send_End=39 33 05 ee a7`
— это протокол **загрузчика AT32** (тот же `39 33 05`, что в `tools/flash_ps.py`). Для дампа
flash модуля НЕ годится.
- **Radio Tuning Software** — калибровка модуля по 0x68 (см. docs/tuning-software-protocol.md).
- Отдельного PC-апдейтера МОДУЛЯ на рабочем столе нет; образы `FM100B_*.bin` = раздел Application
(0x175000 = ровно размер раздела), т.е. из вендорского пакета, не live-дамп.
## API-поверхность модуля (172 команды, research/module-fw/module_api_commands.txt)
Полный список ATC_*/SP*-команд (протокол 0x68 AT32↔модуль). Важное:
- Калибровка (NV): `SPCaliic_FreqOpt`/`SPCaliFreqSetCnf` (частота!), `SPCali_AnaVccnOpt` (VCCN аналог=0x80),
`SPCali_DigMod1Opt` (девиация), `SPCali_ChannelParamOpt`, `SPCali_AnaSQthOpt`, `SPCali_SQRXFreqOpt`,
`SPCali_HeadGQParamOpt`. Это NV-элементы, которые читаются/пишутся B-командами (0xB0–0xBD).
- ⚠️ `ATC_ClearNVdataReq` — СТИРАНИЕ NV (не слать!).
- **Команды дампа flash в приложении НЕТ** → полный дамп NV(«NET info»)/RF Firmware возможен только
через **загрузчик модуля** (download-режим), не через рабочую прошивку. Это живая операция (при владельце).
Сами cal-значения доступны и так — через B-команды (tools/tuning_read.py).
## Возможности модуля (по API, 172 команды)
- **SMS:** `ATC_Msg`, `ATC_SMSProc`, `ATC_SmsmodeSetReq`, `ATUploadRxSmsCnf`, `ATCRxSmsSendAck` — полный DMR-SMS.
- **Шифрование голоса:** `ATC_CurChKeySetReq`, `ATC_SetEncrypt`, `ATVoiceEncryptQuery`, `ATC_KeyHandle_*`.
- **DMR-вызовы:** call setup/roaming (`SPRoamList`), группы/контакты, digital monitor, emergency (`ATRecvEmgCallInd`), busy-status.
- **Аудио/голос:** `ATVoiceEncCnf/DecCnf`, `ATCRecvAmbedataCnf` (AMBE-кадры), `SPATVoicedata` (сырой голос-путь),
кодек-гейны, DTMF, `ATC_PlaySingleToneReq`, `SPKirisunEffectCnf` (→ общий кодбейс с **Kirisun**).
- **Запись/данные:** `ATC_LocalRecordPlayReq`/`ATC_RecordDataPlayReq` (запись голоса!), inband-данные
(`SPSendInBandDataReq`/`SPCclSpInBandDataInd`).
Вывод: модуль — универсальный Beken-378x DMR/intercom SoC, используемый разными брендами
(Radtel/Kirisun/iRadio). Многое из этого можно дёргать по 0x68 через мост (осторожно — только Query/Read вслепую).
## ⭐ Формат образа: Beken CRC16-каждые-32-байта (де-интерливинг)
Образы `FM100B_*.bin` — сырой дамп Beken-флеша: **32 байта данных + 2 байта CRC16 = блоки по 34 байта**
(подтверждено: непечатные пары строго через 34 байта). Те «битые» 2 байта в строках (`ef 10`,
`a8 2c`) — это CRC, не порча. Снятие CRC даёт ЧИСТУЮ прошивку:
- `tools/bk_deinterleave.py raw.bin clean.bin` (выкинуть 2 CRC из каждых 34 байт, фаза 0).
- Чистый образ: `research/module-fw/FM100B_V1.2.0.32_clean.bin` (1 437 938 Б, снято 89 870 CRC).
- После снятия строки целые («RF Firmware», «check failed» и т.д.). **Для будущего реверса — брать
чистый образ.**
Это **окончательно подтверждает стандартный Beken-флеш** → для дампа живого модуля подойдут
**ltchiptool / bk7231tools** (они читают этот формат и сами снимают CRC). Путь варианта A ниже.
## Достоверность образов и версии
- Оба образа (.13 2025-04, .32 2026-01) — plaintext, надёжны (в обоих `beken378`/`EasyFlash`/партиции/
`check failed`). Встречаются одиночные не-ASCII байты в строках (в разных местах у .13 и .32) —
косметика/артефакт дампа, на структуру выводов не влияет.
- Поблочный diff .13↔.32: **91% блоков различаются** — крупный рефакторинг прошивки за 9 месяцев
(не мелкий патч). Идентичны лишь ~32 блока 4КБ.
## Граница статического реверса (что БЕЗ дампа/живой рации недостижимо)
Достигнуто статикой: чип (Beken 378x), архитектура, разделы, API (172 cmd), «вокодер»=WebRTC,
протокол калибровки 0x68 (реверснут, работает). НЕ достаётся из имеющихся файлов:
- **AMBE/DMR-baseband** — в разделе **RF Firmware**, которого у нас НЕТ (нужен дамп flash модуля).
- **Ключи/значения EasyFlash NV** — в разделе NET info (нужен дамп) либо глубокий Thumb-2 disasm
ef_default_env (тяжело, без символов).
- **База загрузки** ≈0x0360_0000 (по векторам), но строки — PC-relative, точные xref требуют disasm.
Вывод: следующий разблокирующий шаг — **дамп flash модуля**, а это ЖИВАЯ операция (загрузчик Beken/
download-режим) при владельце, с риском. Пока владелец недоступен — статика исчерпана по безопасному ROI.
## Реальные следующие шаги (реверс+правка+тест)
1. **API-поверхность:** извлечь полный список ATC_*/SP*-команд (это протокол 0x68 между AT32 и модулем)
— карта того, чем вообще можно управлять. Уже частично в docs/fm100b-commands.md.
2. **WebRTC-параметры:** найти конфиг NSX/AGC (режим/пороги) в коде, изменить, перешить модуль
(режим «Обновление DMR чипа»), проверить звук/приём. Это и есть «поменять и посмотреть заведётся ли».
3. **EasyFlash NV:** распарсить NV-регион (cal) во flash-дампе — прямой доступ к калибровке без live-протокола.
## ⭐⭐ ПРОРЫВ (24.07): загрузчик HKLFBOOT + ВЧ-чип BK4819
Слушая COM во время включения рации в режим «Обновление DMR чипа», поймал загрузку модуля
(мост ПРОЗРАЧНО передаёт boot; CH34x-шнурок держит связь через перезагрузку рации):
```
\r\nHKLFBOOT......\r\n VERSION:01020032\r\n RF_IC:BK_4819\r\n
68 06 02 76 85 83 00 00 10 (далее приложение шлёт 0x68)
```
- **RF_IC = BK4819** — ВЧ-трансивер модуля = **Beken BK4819** (тот же, что в Quansheng UV-K5,
ПОЛНОСТЬЮ реверснут сообществом). Частотная калибровка/девиация/AFC RT-4D = **регистры BK4819**.
SPCali_* (0xB4 VCCN=freq-трим, FreqOpt, DigMod=девиация) отображаются в регистры BK4819.
→ чинить TX можно по документации BK4819 (UV-K5), возможно без полного дампа.
- **Загрузчик = «HKLFBOOT»** (кастом, не гуглится). ДОСТИЖИМ через мост, ждёт хендшейк во время
«......», затем грузит app. Стандартный Beken `01 E0 FC` НЕ подходит. Инструменты:
`tools/bk_bootloader_catch.py` (ловит баннер/линк), `tools/bk_deinterleave.py` (снять CRC с дампа).
- Дамп флеша модуля разблокируется, как найдём HKLF-хендшейк (реверс прошивки AT32 «Update DMR Chip»,
либо аккуратный перебор в boot-окне). Тогда получим RF Firmware (AMBE) + NET info (NV).
## Вариант A (дамп через загрузчик) — РЕЗУЛЬТАТ (24.07, на Linux 10.0.0.63)
Загрузчик HKLFBOOT ловится и держится (нативный Linux, /dev/ttyACM0, tools/bk_module_dump.py):
catch link-check `01 e0 fc 01 00``04 0e 05...`, затем **SetBaudRate short CMD 0x0F <baud:4> <delay>**
с РЕАЛЬНОЙ сменой бода (921600/2M) — фиксирует download-режим (иначе модуль грузит app).
Фрейминг: preamble `01 E0 FC`, short `<len><cmd>`, long `FF F4 <len16 LE><cmd>`. Erase=long 0x0F, Write=0x10.
**ПРОБЛЕМА: команды ЧТЕНИЯ флеша нет.** Пробовал read-опкоды 0x03/0x08/0x09/0x0a/0x0b (long, addr:4 LE):
0x09/0x0a/0x0b/0x03 — пусто; 0x08@0x1000 вернул 580 байт ТОЛЬКО из 0x00/0x80 (битовая карта/статус,
не флеш; другие адреса пусто). Сходится с DMR Upgrade Tool — у него только Connect/SetBaud/Erase/Write,
**READ отсутствует**. Вывод: **загрузчик write-only**, дамп флеша через него недостижим.
Остаётся физический дамп (SPI-клипса CH341A на флеш-чип модуля) — при вскрытии.
НО: ВЧ-чип BK4819 уже найден → TX-фикс и калибровка достижимы БЕЗ дампа, через 0x68 SPCali + мануал BK4819.