uzbek-plus/r2/segboots.py
q 8d7721c775 B7: add network time bootstrap and persistent B7C cache
B7A: QMI DMS time vs VNIIFTRI NTP (DMS = UTC - 0.28 s, sigma 1 ms; NITZ = DMS
truncated to 1 s). B7B: a 1970 -> 2026 date -s step is harmless for the modem
stack. B7C: aurora-modem probes DMS/NITZ along the start flow and steps
CLOCK_REALTIME once at the first valid sample (REG registered/attached), never
RTC; background SNTP check (query only) after START OK. 3/3 class-A cold boots
PASS (residual +0.04/+0.36/+0.84 s), cache 14fe453a written (B7C_WRITE_VERIFIED)
and verified by a normal power-on (V1, +0.26 s).

Also publishes the prerequisite R2 (boot-hang / lk eMMC investigation, T4
telnet baseline that B7C builds on) and R3 (autonomous cold boot, NCM loss)
material, and extends tools/publish-sanitize.py to r2/, r3/, b7/.
Binary images, initramfs, busybox and raw logs stay out (see b7/*/SHA256SUMS).
2026-10-02 20:18:25 +03:00

64 lines
3.2 KiB
Python

#!/usr/bin/env python3
# Split UART logs into boots and classify where each boot stopped.
import sys, re, glob, os, datetime
STAGES = [
("sbl_start", r"SBL1, Start"),
("pm_dev", r"pm_device_init, Start"),
("flash", r"boot_flash_init, Start"),
("ddr_params", r"sbl1_ddr_set_params, Start"),
("preddr_clk", r"Pre_DDR_clock_init, Start"),
("preddr_done", r"Pre_DDR_clock_init, Delta"),
("pm_drv", r"pm_driver_init, Start"),
("batt", r"batt_voltage="),
("clock_init", r"clock_init, Start"),
("efs", r"sbl1_efs_handle_cookies"),
("img_load", r"Image Load, Start"),
("qsee", r"QSEE Execution"),
("sbl_end", r"SBL1, End"),
("lk_uart", r"Android Bootloader - UART_DM"),
("lk_welcome", r"welcome to lk"),
("target_init", r"target_init\(\)"),
("mmc", r"MMC card: "),
("blkdev", r"block devices:"),
("fastboot", r"fastboot: processing commands|fastboot_init|USB init ept"),
("jump", r"Jumping to kernel|booting linux @"),
("linux", r"Booting Linux on physical CPU"),
("userspace", r"Run /init|Freeing unused kernel memory"),
("shell", r"~ # |/ # |aurora-modem"),
]
REB = re.compile(r"reboot: Restarting|reboot: Power down|Restarting system|sysrq: |Kernel panic|Internal error|Unable to handle|watchdog|rcu_sched self-detected|BUG:")
def hts(line):
m = re.match(r"(\d\d):(\d\d):(\d\d)\.(\d{3}) ", line)
return (int(m[1])*3600+int(m[2])*60+int(m[3])+int(m[4])/1000) if m else None
out=[]
for f in sorted(glob.glob(sys.argv[1]+"/*.log")):
lines=open(f,errors="replace").read().splitlines()
boots=[]; cur=None; day=0; last=None
for i,l in enumerate(lines):
t=hts(l)
if t is not None:
if last is not None and t+day < last-3600: day+=86400
t+=day; last=t
if "Format: Log Type" in l or ("SBL1, Start" in l and (cur is None or cur["stage_i"]>0)):
if cur is None or "Format: Log Type" in l or cur["stage_i"]>0:
cur={"file":os.path.basename(f),"line":i+1,"t0":t,"stage_i":-1,"stage":"hdr","tlast":t,"batt":None,"events":[],"lastline":l,"ktime":None,"tlinux":None}
boots.append(cur)
if cur is None: continue
for k,(name,rx) in enumerate(STAGES):
if k>cur["stage_i"] and re.search(rx,l):
cur["stage_i"]=k; cur["stage"]=name
if name=="linux": cur["tlinux"]=t
m=re.search(r"batt_voltage=(\d+)",l)
if m: cur["batt"]=int(m[1])
m=re.match(r"\S+ \[\s*(\d+\.\d+)\]",l)
if m: cur["ktime"]=float(m[1])
if REB.search(l): cur["events"].append((i+1,l[:140]))
if t is not None and l[13:].strip(): cur["tlast"]=t; cur["lastline"]=l[:160]; cur["lastno"]=i+1
for j,b in enumerate(boots):
b["next_gap"]=(boots[j+1]["t0"]-b["tlast"]) if j+1<len(boots) and boots[j+1]["t0"] and b["tlast"] else None
b["dur_linux"]=(b["tlast"]-b["tlinux"]) if b["tlinux"] else None
out+=boots
for b in out:
print(f'{b["file"][:34]:34} L{b["line"]:>7} {b["stage"]:11} batt={b["batt"]} ktime={b["ktime"]} linux_dur={None if b["dur_linux"] is None else round(b["dur_linux"],1)} gap_next={None if b["next_gap"] is None else round(b["next_gap"],1)}')
print(f' last(L{b.get("lastno")}): {b["lastline"]}')
for e in b["events"][:4]: print(f' ev L{e[0]}: {e[1]}')