"""Parser für Huawei `update.app`-Container. Format-Beschreibung (öffentlich aus splituapp / Huawei Update Extractor): Datei beginnt mit 0x5C Bytes Padding/Header, danach folgen Section-Header. Jeder Section-Header ist 98 Bytes: uint32 magic = 0xA55AAA55 uint32 header_length = 98 uint32 unknown1 char[8] hardware_id z.B. "WAS-LX1" uint32 file_sequence uint32 file_size char[16] file_date z.B. "2018.04.16" char[16] file_time z.B. "10:23:45" char[16] file_type z.B. "BOOT", "SYSTEM", "USERDATA", "CRC" char[16] blank1 uint16 header_checksum uint16 block_size uint16 blank2 Danach `file_size` Bytes Section-Daten, gefolgt von einer CRC-Tabelle (eine uint16 pro `block_size` Bytes Daten), dann 4-Byte-Alignment auf die nächste Section-Header-Position. """ from __future__ import annotations import struct from dataclasses import dataclass, field from pathlib import Path UPDATE_MAGIC = 0xA55AAA55 HEADER_FMT = " str: return b.split(b"\x00", 1)[0].decode("ascii", errors="replace").strip() def parse(path: Path, max_sections: int = 500) -> UpdateAppInfo | None: """Header der ersten N Sections einlesen, ohne das ganze Image zu lesen.""" if not path.is_file(): return None if path.stat().st_size < 0x100: return None with path.open("rb") as f: # Magic suchen — sitzt meist bei 0x5C, manche Builds variieren head = f.read(0x200) idx = head.find(struct.pack(" SoC-Mapping. Wird mit der Zeit erweitert; was hier nicht steht, # kommt als 'unknown' raus und der User kann es manuell pflegen. HUAWEI_MODEL_SOC = { "WAS-LX1": "kirin-658", "WAS-LX2": "kirin-658", "WAS-LX3": "kirin-658", "PRA-LX1": "kirin-655", # P8 Lite 2017 "VTR-L09": "kirin-960", # P10 "VTR-L29": "kirin-960", "VKY-L09": "kirin-960", # P10 Plus "EML-L09": "kirin-970", # P20 "EML-L29": "kirin-970", "CLT-L29": "kirin-970", # P20 Pro "ANE-LX1": "kirin-710", # P20 Lite } def soc_for(hardware_id: str) -> str | None: return HUAWEI_MODEL_SOC.get(hardware_id.upper())