imgtool: dumpinfo improvements
Fix trailer info dumping reads pad characters as values for status
Refactor printing styled texts and frames
Use isinstance() for type checking
Fold notice text depending on line length
Refactoring some parts for readability
Fix additional linting issues
Signed-off-by: Rustam Ismayilov <rustam.ismayilov@arm.com>
Change-Id: I741562bb70b18407bdd32e9c7391048faf6394c6
diff --git a/scripts/imgtool/dumpinfo.py b/scripts/imgtool/dumpinfo.py
index 6058fe1..5544657 100644
--- a/scripts/imgtool/dumpinfo.py
+++ b/scripts/imgtool/dumpinfo.py
@@ -17,13 +17,15 @@
"""
Parse and print header, TLV area and trailer information of a signed image.
"""
-from imgtool import image
-import click
-import struct
-import yaml
import os.path
+import struct
import sys
+import click
+import yaml
+
+from imgtool import image
+
HEADER_ITEMS = ("magic", "load_addr", "hdr_size", "protected_tlv_size",
"img_size", "flags", "version")
TLV_TYPES = dict((value, key) for key, value in image.TLV_VALUES.items())
@@ -39,6 +41,59 @@
0x1f, 0x8a, ])
BOOT_MAGIC_SIZE = len(BOOT_MAGIC)
_LINE_LENGTH = 60
+STATUS = {
+ '0x1': 'SET',
+ '0x2': 'BAD',
+ '0x3': 'UNSET',
+ '0x4': 'ANY',
+}
+
+
+def parse_enc(key_field_len):
+ if key_field_len is not None:
+ return "(len: {}, if BOOT_SWAP_SAVE_ENCTLV is unset)".format(hex(key_field_len))
+ else:
+ return "Image not encrypted"
+
+
+def parse_size(size_hex):
+ if size_hex == '0xffffffff':
+ return "unknown"
+ return size_hex + " octal: " + str(int(size_hex, 0))
+
+
+def parse_status(status_hex):
+ return f"{STATUS[status_hex]} ({status_hex})" if status_hex in STATUS else f"INVALID ({status_hex})"
+
+
+def parse_boot_magic(trailer_magic):
+ magic = ""
+ for i in range(BOOT_MAGIC_SIZE):
+ magic += "{0:#04x} ".format(trailer_magic[i])
+ if i == (BOOT_MAGIC_SIZE / 2 - 1):
+ magic += ("\n" + " ")
+ return magic
+
+
+def print_in_frame(header_text, content):
+ sepc = " "
+ header = "#### " + header_text + sepc
+ post_header = "#" * (_LINE_LENGTH - len(header))
+ print(header + post_header)
+
+ print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
+ offset = (_LINE_LENGTH - len(content)) // 2
+ pre = "|" + (sepc * (offset - 1))
+ post = sepc * (_LINE_LENGTH - len(pre) - len(content) - 1) + "|"
+ print(pre, content, post, sep="")
+ print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
+ print("#" * _LINE_LENGTH)
+
+
+def print_in_row(row_text):
+ row_text = "#### " + row_text + " "
+ fill = "#" * (_LINE_LENGTH - len(row_text))
+ print(row_text + fill)
def print_tlv_records(tlv_list):
@@ -66,10 +121,11 @@
def dump_imginfo(imgfile, outfile=None, silent=False):
"""Parse a signed image binary and print/save the available information."""
trailer_magic = None
- swap_size = 0
- swap_info = 0
- copy_done = 0
- image_ok = 0
+ # set to INVALID by default
+ swap_size = 0x99
+ swap_info = 0x99
+ copy_done = 0x99
+ image_ok = 0x99
trailer = {}
key_field_len = None
@@ -92,16 +148,16 @@
# Parsing the TLV area
tlv_area = {"tlv_hdr_prot": {},
- "tlvs_prot": [],
- "tlv_hdr": {},
- "tlvs": []}
+ "tlvs_prot": [],
+ "tlv_hdr": {},
+ "tlvs": []}
tlv_off = header["hdr_size"] + header["img_size"]
protected_tlv_size = header["protected_tlv_size"]
if protected_tlv_size != 0:
_tlv_prot_head = struct.unpack(
- 'HH',
- b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
+ 'HH',
+ b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
tlv_area["tlv_hdr_prot"]["magic"] = _tlv_prot_head[0]
tlv_area["tlv_hdr_prot"]["tlv_tot"] = _tlv_prot_head[1]
tlv_end = tlv_off + tlv_area["tlv_hdr_prot"]["tlv_tot"]
@@ -110,8 +166,8 @@
# Iterating through the protected TLV area
while tlv_off < tlv_end:
tlv_type, tlv_len = struct.unpack(
- 'HH',
- b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
+ 'HH',
+ b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
tlv_off += image.TLV_INFO_SIZE
tlv_data = b[tlv_off:(tlv_off + tlv_len)]
tlv_area["tlvs_prot"].append(
@@ -128,8 +184,8 @@
# Iterating through the TLV area
while tlv_off < tlv_end:
tlv_type, tlv_len = struct.unpack(
- 'HH',
- b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
+ 'HH',
+ b[tlv_off:(tlv_off + image.TLV_INFO_SIZE)])
tlv_off += image.TLV_INFO_SIZE
tlv_data = b[tlv_off:(tlv_off + tlv_len)]
tlv_area["tlvs"].append(
@@ -177,7 +233,7 @@
# Encryption key 0/1
if ((header["flags"] & image.IMAGE_F["ENCRYPTED_AES128"]) or
- (header["flags"] & image.IMAGE_F["ENCRYPTED_AES256"])):
+ (header["flags"] & image.IMAGE_F["ENCRYPTED_AES256"])):
# The image is encrypted
# Estimated value of key_field_len is correct if
# BOOT_SWAP_SAVE_ENCTLV is unset
@@ -192,7 +248,7 @@
# sort_keys - from pyyaml 5.1
yaml.dump(imgdata, outf, sort_keys=False)
-###############################################################################
+ ###############################################################################
if silent:
sys.exit(0)
@@ -200,9 +256,8 @@
print("Printing content of signed image:", os.path.basename(imgfile), "\n")
# Image header
- str1 = "#### Image header (offset: 0x0) "
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
+ section_name = "Image header (offset: 0x0)"
+ print_in_row(section_name)
for key, value in header.items():
if key == "flags":
if not value:
@@ -214,45 +269,34 @@
if flag_string:
flag_string += ("\n" + (" " * 20))
flag_string += "{} ({})".format(
- flag, hex(image.IMAGE_F[flag]))
+ flag, hex(image.IMAGE_F[flag]))
value = flag_string
- if type(value) != str:
+ if not isinstance(value, str):
value = hex(value)
print(key, ":", " " * (19 - len(key)), value, sep="")
print("#" * _LINE_LENGTH)
# Image payload
_sectionoff = header["hdr_size"]
- sepc = " "
- str1 = "#### Payload (offset: {}) ".format(hex(_sectionoff))
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
- print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
- str1 = "FW image (size: {} Bytes)".format(hex(header["img_size"]))
- numc = (_LINE_LENGTH - len(str1)) // 2
- str2 = "|" + (sepc * (numc - 1))
- str3 = sepc * (_LINE_LENGTH - len(str2) - len(str1) - 1) + "|"
- print(str2, str1, str3, sep="")
- print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
- print("#" * _LINE_LENGTH)
+ frame_header_text = "Payload (offset: {})".format(hex(_sectionoff))
+ frame_content = "FW image (size: {} Bytes)".format(hex(header["img_size"]))
+ print_in_frame(frame_header_text, frame_content)
# TLV area
_sectionoff += header["img_size"]
if protected_tlv_size != 0:
# Protected TLV area
- str1 = "#### Protected TLV area (offset: {}) ".format(hex(_sectionoff))
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
+ section_name = "Protected TLV area (offset: {})".format(hex(_sectionoff))
+ print_in_row(section_name)
print("magic: ", hex(tlv_area["tlv_hdr_prot"]["magic"]))
print("area size:", hex(tlv_area["tlv_hdr_prot"]["tlv_tot"]))
print_tlv_records(tlv_area["tlvs_prot"])
print("#" * _LINE_LENGTH)
_sectionoff += protected_tlv_size
- str1 = "#### TLV area (offset: {}) ".format(hex(_sectionoff))
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
+ section_name = "TLV area (offset: {})".format(hex(_sectionoff))
+ print_in_row(section_name)
print("magic: ", hex(tlv_area["tlv_hdr"]["magic"]))
print("area size:", hex(tlv_area["tlv_hdr"]["tlv_tot"]))
print_tlv_records(tlv_area["tlvs"])
@@ -261,40 +305,24 @@
if _img_pad_size:
_sectionoff += tlv_area["tlv_hdr"]["tlv_tot"]
_erased_val = b[_sectionoff]
- str1 = "#### Image padding (offset: {}) ".format(hex(_sectionoff))
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
- print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
- str1 = "padding ({})".format(hex(_erased_val))
- numc = (_LINE_LENGTH - len(str1)) // 2
- str2 = "|" + (sepc * (numc - 1))
- str3 = sepc * (_LINE_LENGTH - len(str2) - len(str1) - 1) + "|"
- print(str2, str1, str3, sep="")
- print("|", sepc * (_LINE_LENGTH - 2), "|", sep="")
- print("#" * _LINE_LENGTH)
+ frame_header_text = "Image padding (offset: {})".format(hex(_sectionoff))
+ frame_content = "padding ({})".format(hex(_erased_val))
+ print_in_frame(frame_header_text, frame_content)
# Image trailer
- str1 = "#### Image trailer (offset: unknown) "
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
- print("(Note: some field may not be used, \n"
- " depending on the update strategy)\n")
-
+ section_name = "Image trailer (offset: unknown)"
+ print_in_row(section_name)
+ notice = "(Note: some fields may not be used, depending on the update strategy)\n"
+ notice = '\n'.join(notice[i:i + _LINE_LENGTH] for i in range(0, len(notice), _LINE_LENGTH))
+ print(notice)
print("swap status: (len: unknown)")
- if key_field_len is not None:
- print("enc. keys: (len: {}, if BOOT_SWAP_SAVE_ENCTLV is unset)"
- .format(hex(key_field_len)))
- print("swap size: ", hex(swap_size))
- print("swap_info: ", hex(swap_info))
- print("copy_done: ", hex(copy_done))
- print("image_ok: ", hex(image_ok))
- print("boot magic: ", end="")
- for i in range(BOOT_MAGIC_SIZE):
- print("{0:#04x}".format(trailer_magic[i]), end=" ")
- if i == (BOOT_MAGIC_SIZE / 2 - 1):
- print("\n", end=" ")
+ print("enc. keys: ", parse_enc(key_field_len))
+ print("swap size: ", parse_size(hex(swap_size)))
+ print("swap_info: ", parse_status(hex(swap_info)))
+ print("copy_done: ", parse_status(hex(copy_done)))
+ print("image_ok: ", parse_status(hex(image_ok)))
+ print("boot magic: ", parse_boot_magic(trailer_magic))
print()
- str1 = "#### End of Image "
- str2 = "#" * (_LINE_LENGTH - len(str1))
- print(str1 + str2)
+ footer = "End of Image "
+ print_in_row(footer)