Detect RGN-in-RGN structure.

This commit is contained in:
Markus Birth 2019-10-12 17:55:16 +02:00
parent 3545d2b12e
commit 9d9dc3671b
Signed by: mbirth
GPG Key ID: A9928D7A098C3A9A
2 changed files with 48 additions and 7 deletions

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Thanks to Herbert Oppmann (herby) for all your work! # Thanks to Herbert Oppmann (herby) for all your work!
from .ansi import RESET, RED from .ansi import RESET, RED, YELLOW
from .chksum import ChkSum from .chksum import ChkSum
from .rgnbin import RgnBin from .rgnbin import RgnBin
from struct import unpack from struct import unpack
@ -38,8 +38,6 @@ class Rgn:
def load(self): def load(self):
if self.filename is None: if self.filename is None:
return False return False
last_tlv6 = None
last_tlv7 = None
with open(self.filename, "rb") as f: with open(self.filename, "rb") as f:
sig = f.read(4) sig = f.read(4)
if sig != RGN_SIG: if sig != RGN_SIG:
@ -59,6 +57,29 @@ class Rgn:
self.add_rec(rec) self.add_rec(rec)
f.close() f.close()
def load_from_bytes(self, payload: bytes):
pos = 0
sig = payload[pos:pos+4]
if sig != RGN_SIG:
raise ParseException("Signature mismatch ({}, should be {})!".format(repr(sig), repr(RGN_SIG)))
pos += 4
self.version = unpack("<H", payload[pos:pos+2])[0]
pos += 2
while True:
cur_offset = pos
if pos >= len(payload):
#print("End of file reached.")
break
header = payload[pos:pos+5]
pos += 5
(length, type_id) = unpack("<Lc", header)
#print("Found record type: {} with {} Bytes length.".format(type_id, length))
rec = RgnRecord.factory(type_id, length, offset=cur_offset)
inner_payload = payload[pos:pos+length]
pos += length
rec.set_payload(inner_payload)
self.add_rec(rec)
def add_rec(self, new_rec): def add_rec(self, new_rec):
self.struct.append(new_rec) self.struct.append(new_rec)
@ -66,10 +87,7 @@ class Rgn:
""" """
Prints the structure of the parsed RGN file Prints the structure of the parsed RGN file
""" """
print("RGN File Version: {}".format(self.version)) print(str(self))
print("{} records.".format(len(self.struct)))
for i, rec in enumerate(self.struct):
print("#{:03d}: {}".format(i, rec))
def print_struct_full(self): def print_struct_full(self):
""" """
@ -94,6 +112,13 @@ class Rgn:
def save(self, filename): def save(self, filename):
pass pass
def __str__(self):
txt = "RGN File Version: {}".format(self.version)
txt += "\n{} records.".format(len(self.struct))
for i, rec in enumerate(self.struct):
txt += "\n#{:03d}: {}".format(i, rec)
return txt
class RgnRecord(): class RgnRecord():
def __init__(self, type_id, expected_length, payload=None, offset=None): def __init__(self, type_id, expected_length, payload=None, offset=None):
self.type_id = type_id self.type_id = type_id
@ -215,6 +240,11 @@ class RgnRecordR(RgnRecord):
self.delay_ms = None self.delay_ms = None
self.size = None self.size = None
def id_payload(self):
if self.payload[10:10+len(RGN_SIG)] == RGN_SIG:
return "RGN"
return "BIN"
def parse(self): def parse(self):
if self.is_parsed: if self.is_parsed:
# already parsed # already parsed
@ -230,4 +260,13 @@ class RgnRecordR(RgnRecord):
txt += "\n - Region ID: {:04x} ({})".format(self.region_id, rgn_type) txt += "\n - Region ID: {:04x} ({})".format(self.region_id, rgn_type)
txt += "\n - Flash delay: {} ms".format(self.delay_ms) txt += "\n - Flash delay: {} ms".format(self.delay_ms)
txt += "\n - Binary size: {} Bytes".format(self.size) txt += "\n - Binary size: {} Bytes".format(self.size)
if len(self.payload) - 10 == self.size:
txt += " (OK)"
else:
txt += " (" + RED + "MISMATCH!" + RESET + ")"
if self.id_payload() == "RGN":
txt += "\n " + YELLOW + "PAYLOAD IS ANOTHER RGN STRUCTURE:" + RESET
rgn = Rgn()
rgn.load_from_bytes(self.payload[10:])
txt += "\n " + "\n ".join(str(rgn).split("\n"))
return txt return txt

View File

@ -9,6 +9,8 @@ from struct import unpack
# RGN = outside hull # RGN = outside hull
# BIN = firmware + hwid + checksum # BIN = firmware + hwid + checksum
END_PATTERN = b"\xff\xff\x5a\xa5\xff\xff\xff\xff"
class ParseException(Exception): class ParseException(Exception):
pass pass