Files
rt-4d/tools/bk_bootloader_catch.py
T
viktorиClaude Opus 4.8 1dedc4150b ПРОРЫВ: загрузчик HKLFBOOT достижим + ВЧ-чип = BK4819
Слушая COM при включении в режим прошивки, поймал boot модуля: баннер HKLFBOOT......
VERSION:01020032 RF_IC:BK_4819. ВЧ-трансивер = Beken BK4819 (как в UV-K5, полностью
реверснут) -> частотная калибровка = регистры BK4819, можно чинить TX по мануалу.
Загрузчик HKLFBOOT достижим через мост (мост прозрачен, CH34x держит связь через
перезагрузку), ждёт хендшейк в окне '......'; стандартный Beken 01 E0 FC не подходит.
Обновлены docs/fm100b-firmware-re.md, память.

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

62 строки
3.1 KiB
Python

#!/usr/bin/env python3
"""Поймать Beken-загрузчик модуля во время включения (через мост RT-4D, WSL/powershell).
Формат флеша модуля = стандартный Beken (32+2 CRC), значит у него Beken UART-загрузчик,
который слушает link-check КОРОТКОЕ окно после сброса. Этот тул одним процессом powershell
в тайтовом цикле спамит link-check `01 E0 FC 01 00` и ловит ответ `04 0E 05 ...`.
Использование: запусти тул, и в течение его работы ВЫКЛЮЧИ и включи рацию в режим
«Обновление DMR чипа» (питание + MENU). Если поймаем ответ — загрузчик достижим через мост.
ТОЛЬКО ЧТЕНИЕ/handshake — ни erase, ни write не шлём.
"""
import argparse, subprocess, sys
PS = r'''
$port="{port}"; $sec={sec}
$p = New-Object System.IO.Ports.SerialPort $port,115200,"None",8,"one"
$p.ReadTimeout=20; $p.WriteTimeout=50
try {{ $p.Open() }} catch {{ Write-Output "ERR:$($_.Exception.Message)"; exit }}
$lc=[byte[]]@(1,224,252,1,0) # 01 E0 FC 01 00
$sw=[Diagnostics.Stopwatch]::StartNew()
$hit=$false
while($sw.Elapsed.TotalSeconds -lt $sec){{
try {{ $p.Write($lc,0,$lc.Length) }} catch {{}}
Start-Sleep -Milliseconds 8
$n=$p.BytesToRead
if($n -gt 0){{
$b=New-Object byte[] $n; $p.Read($b,0,$n)|Out-Null
$hex=($b|ForEach-Object{{"{{0:x2}}"-f $_}}) -join ""
if($hex -match "e0fc"){{ Write-Output ("HIT:"+$hex); $hit=$true; break }}
else {{ Write-Output ("RX:"+$hex) }}
}}
}}
$p.Close()
if(-not $hit){{ Write-Output "NOHIT" }}
'''
def main():
ap=argparse.ArgumentParser()
ap.add_argument("--port", default="COM4")
ap.add_argument("--sec", type=int, default=25)
a=ap.parse_args()
print(f"[спам link-check на {a.port} @115200, {a.sec}с]")
print(">>> СЕЙЧАС выключи рацию и включи в режим «Обновление DMR чипа» (питание+MENU) <<<\n")
r=subprocess.run(["powershell.exe","-NoProfile","-Command",PS.format(port=a.port,sec=a.sec)],
capture_output=True, text=True)
for line in r.stdout.replace("\r","").split("\n"):
line=line.strip()
if line.startswith("HIT:"):
print(f"✅ ЗАГРУЗЧИК ОТВЕТИЛ: {line[4:]}")
print(" -> Beken-загрузчик достижим через мост. Можно читать флеш.")
elif line.startswith("RX:") and line[3:]:
print(f" (эхо/данные: {line[3:][:60]})")
elif line=="NOHIT":
print("❌ Ответа загрузчика не поймано. Либо мост не пробрасывает загрузчик,")
print(" либо окно/бод другие. Попробуй ещё раз или обсудим физ.доступ.")
elif line.startswith("ERR:"):
print(line)
if __name__=="__main__":
main()