# 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 ** с РЕАЛЬНОЙ сменой бода (921600/2M) — фиксирует download-режим (иначе модуль грузит app). Фрейминг: preamble `01 E0 FC`, short ``, long `FF F4 `. 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.