Files
rt-4d/tools/bk_bootloader_catch.py
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

66 строки
3.6 KiB
Python

#!/usr/bin/env python3
"""Поймать загрузчик модуля (HKLFBOOT) — ТАЙТОВЫЙ спам Connect (как DMR Upgrade Tool).
DMR Upgrade Tool: жмёшь Upgrade (спам Connect=01 E0 FC 01 00), затем MENU+включение —
загрузчик ловит connect в окне до старта приложения. Наш powershell-цикл со Start-Sleep был
слишком медленный и промахивался. Здесь — спам БЕЗ пауз (тысячи/сек), ловит короткое окно.
Процедура: запусти тул, затем зажми MENU и включи рацию. Успех = ответ загрузчика на link-check
(04 0E 05 ...) и приложение (0x68 06 02) НЕ стартует. Только connect — ни erase, ни write.
"""
import argparse, subprocess
PS = r'''
$p = New-Object System.IO.Ports.SerialPort "{port}",115200,"None",8,"one"
$p.ReadTimeout=1; $p.WriteTimeout=50; $p.ReadBufferSize=8192
try {{ $p.Open() }} catch {{ Write-Output "ERR:$($_.Exception.Message)"; exit }}
$lc=[byte[]]@(1,224,252,1,0)
$sw=[Diagnostics.Stopwatch]::StartNew()
$acc=New-Object System.Collections.Generic.List[byte]
$caught=$false
while($sw.Elapsed.TotalSeconds -lt {sec}){{
if(-not $caught){{ try {{ $p.Write($lc,0,$lc.Length) }} catch {{}} }}
$n=$p.BytesToRead
if($n -gt 0){{
$b=New-Object byte[] $n; $p.Read($b,0,$n)|Out-Null
foreach($x in $b){{ $acc.Add($x) }}
$hex=($b|ForEach-Object{{"{{0:x2}}"-f $_}}) -join ""
Write-Output ("t"+[int]$sw.Elapsed.TotalSeconds+"|"+$hex)
# ответ загрузчика на link-check: 04 0e 05 ...
if($hex -match "040e05"){{ Write-Output "CAUGHT"; $caught=$true }}
}}
}}
$p.Close(); Write-Output "END"
'''
def main():
ap=argparse.ArgumentParser()
ap.add_argument("--port", default="COM4"); ap.add_argument("--sec", type=int, default=30)
a=ap.parse_args()
print(f"[ТАЙТОВЫЙ спам 01 e0 fc 01 00 на {a.port}, {a.sec}с]")
print(">>> ЗАЖМИ MENU и включи рацию СЕЙЧАС (как при прошивке модуля) <<<\n")
r=subprocess.run(["powershell.exe","-NoProfile","-Command",PS.format(port=a.port,sec=a.sec)],
capture_output=True, text=True)
banner=app=caught=False; n=0
for line in r.stdout.replace("\r","").split("\n"):
line=line.strip()
if line.startswith("ERR:"): print(line); return
if line=="CAUGHT": caught=True; continue
if "|" not in line: continue
t,hexs=line.split("|",1); n+=1
try: asc=bytes.fromhex(hexs).decode("latin1")
except: asc=""
asc="".join(c if 32<=ord(c)<127 else "." for c in asc)
print(f" {t}: {asc[:48]} [{hexs[:40]}]")
if "HKLF" in asc: banner=True
if "680602" in hexs: app=True
print()
if caught: print("✅✅✅ ЗАГРУЗЧИК ПОЙМАН (ответ 04 0e 05)! Держим сессию — можно читать флеш.")
elif banner and app: print("⚠️ Баннер+приложение стартовало. Окно ещё промахнули — повтори (спам уже без пауз).")
elif banner: print("✅ Баннер был, приложение не стартовало — возможно, поймали. Проверю ответ.")
elif not n: print("Тишина — не попал во включение? Порт COM4? Повтори.")
else: print("Данные без баннера — перезагрузка вне окна. Повтори.")
if __name__=="__main__":
main()