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

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

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 0004 0e 05..., затем SetBaudRate short CMD 0x0F baud:4 с РЕАЛЬНОЙ сменой бода (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.