mirror of
https://github.com/espressif/esptool.git
synced 2025-10-22 16:37:36 +08:00
feat(image_info): Print application information if possible
This commit is contained in:
@@ -199,6 +199,10 @@ This information corresponds to the headers described in :ref:`image-format`.
|
|||||||
|
|
||||||
esptool.py image_info --version 2 my_esp_app.bin
|
esptool.py image_info --version 2 my_esp_app.bin
|
||||||
|
|
||||||
|
.. only:: not esp8266
|
||||||
|
|
||||||
|
If a valid `ESP-IDF application header <https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/app_image_format.html#application-description>`__ is detected in the image, specific fields describing the application are also displayed.
|
||||||
|
|
||||||
.. _merge-bin:
|
.. _merge-bin:
|
||||||
|
|
||||||
Merge Binaries for Flashing: merge_bin
|
Merge Binaries for Flashing: merge_bin
|
||||||
|
@@ -654,6 +654,7 @@ def image_info(args):
|
|||||||
return key
|
return key
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
print()
|
||||||
title = "{} image header".format(args.chip.upper())
|
title = "{} image header".format(args.chip.upper())
|
||||||
print(title)
|
print(title)
|
||||||
print("=" * len(title))
|
print("=" * len(title))
|
||||||
@@ -737,16 +738,19 @@ def image_info(args):
|
|||||||
"{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12)
|
"{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12)
|
||||||
)
|
)
|
||||||
format_str = "{:7} {:#07x} {:#010x} {:#010x} {}"
|
format_str = "{:7} {:#07x} {:#010x} {:#010x} {}"
|
||||||
|
app_desc = None
|
||||||
for idx, seg in enumerate(image.segments, start=1):
|
for idx, seg in enumerate(image.segments, start=1):
|
||||||
segs = seg.get_memory_type(image)
|
segs = seg.get_memory_type(image)
|
||||||
seg_name = ", ".join(segs)
|
seg_name = ", ".join(segs)
|
||||||
|
if "DROM" in segs: # The DROM segment starts with the esp_app_desc_t struct
|
||||||
|
app_desc = seg.data[:256]
|
||||||
print(
|
print(
|
||||||
format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name)
|
format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name)
|
||||||
)
|
)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
# Footer
|
# Footer
|
||||||
title = "Image footer"
|
title = f"{args.chip.upper()} image footer"
|
||||||
print(title)
|
print(title)
|
||||||
print("=" * len(title))
|
print("=" * len(title))
|
||||||
calc_checksum = image.calculate_checksum()
|
calc_checksum = image.calculate_checksum()
|
||||||
@@ -763,13 +767,40 @@ def image_info(args):
|
|||||||
if image.append_digest:
|
if image.append_digest:
|
||||||
is_valid = image.stored_digest == image.calc_digest
|
is_valid = image.stored_digest == image.calc_digest
|
||||||
digest_msg = "{} ({})".format(
|
digest_msg = "{} ({})".format(
|
||||||
hexify(image.calc_digest).lower(),
|
hexify(image.calc_digest, uppercase=False),
|
||||||
"valid" if is_valid else "invalid",
|
"valid" if is_valid else "invalid",
|
||||||
)
|
)
|
||||||
print("Validation hash: {}".format(digest_msg))
|
print("Validation hash: {}".format(digest_msg))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass # ESP8266 image has no append_digest field
|
pass # ESP8266 image has no append_digest field
|
||||||
|
|
||||||
|
if app_desc:
|
||||||
|
APP_DESC_STRUCT_FMT = "<II" + "8s" + "32s32s16s16s32s32s" + "80s"
|
||||||
|
(
|
||||||
|
magic_word,
|
||||||
|
secure_version,
|
||||||
|
reserv1,
|
||||||
|
version,
|
||||||
|
project_name,
|
||||||
|
time,
|
||||||
|
date,
|
||||||
|
idf_ver,
|
||||||
|
app_elf_sha256,
|
||||||
|
reserv2,
|
||||||
|
) = struct.unpack(APP_DESC_STRUCT_FMT, app_desc)
|
||||||
|
|
||||||
|
if magic_word == 0xABCD5432:
|
||||||
|
print()
|
||||||
|
title = "Application information"
|
||||||
|
print(title)
|
||||||
|
print("=" * len(title))
|
||||||
|
print(f'Project name: {project_name.decode("utf-8")}')
|
||||||
|
print(f'App version: {version.decode("utf-8")}')
|
||||||
|
print(f'Compile time: {date.decode("utf-8")} {time.decode("utf-8")}')
|
||||||
|
print(f"ELF file SHA256: {hexify(app_elf_sha256, uppercase=False)}")
|
||||||
|
print(f'ESP-IDF: {idf_ver.decode("utf-8")}')
|
||||||
|
print(f"Secure version: {secure_version}")
|
||||||
|
|
||||||
with open(args.filename, "rb") as f:
|
with open(args.filename, "rb") as f:
|
||||||
# magic number
|
# magic number
|
||||||
try:
|
try:
|
||||||
@@ -843,7 +874,7 @@ def image_info(args):
|
|||||||
if image.append_digest:
|
if image.append_digest:
|
||||||
is_valid = image.stored_digest == image.calc_digest
|
is_valid = image.stored_digest == image.calc_digest
|
||||||
digest_msg = "{} ({})".format(
|
digest_msg = "{} ({})".format(
|
||||||
hexify(image.calc_digest).lower(),
|
hexify(image.calc_digest, uppercase=False),
|
||||||
"valid" if is_valid else "invalid",
|
"valid" if is_valid else "invalid",
|
||||||
)
|
)
|
||||||
print("Validation Hash: {}".format(digest_msg))
|
print("Validation Hash: {}".format(digest_msg))
|
||||||
|
BIN
test/images/esp_idf_blink_esp32s2.bin
Normal file
BIN
test/images/esp_idf_blink_esp32s2.bin
Normal file
Binary file not shown.
@@ -167,6 +167,23 @@ class ImageInfoTests(unittest.TestCase):
|
|||||||
# Invalid image
|
# Invalid image
|
||||||
self.run_image_info("auto", "one_kb.bin", "2")
|
self.run_image_info("auto", "one_kb.bin", "2")
|
||||||
|
|
||||||
|
def test_application_info(self):
|
||||||
|
out = self.run_image_info("auto", "esp_idf_blink_esp32s2.bin", "2")
|
||||||
|
self.assertTrue("Application information" in out)
|
||||||
|
self.assertTrue("Project name: blink" in out)
|
||||||
|
self.assertTrue("App version: qa-test-v5.0-20220830-4-g4532e6" in out)
|
||||||
|
self.assertTrue("Secure version: 0" in out)
|
||||||
|
self.assertTrue("Compile time: Sep 13 2022" in out)
|
||||||
|
self.assertTrue("19:46:07" in out)
|
||||||
|
self.assertTrue("3059e6b55a965865febd28fa9f6028ad5" in out)
|
||||||
|
self.assertTrue("cd0dab311febb0a3ea79eaa223ac2b0" in out)
|
||||||
|
self.assertTrue("ESP-IDF: v5.0-beta1-427-g4532e6e0b2-dirt" in out)
|
||||||
|
# No application info in image
|
||||||
|
out = self.run_image_info("auto", "bootloader_esp32.bin", "2")
|
||||||
|
self.assertFalse("Application information" in out)
|
||||||
|
out = self.run_image_info("auto", NODEMCU_FILE, "2")
|
||||||
|
self.assertFalse("Application information" in out)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main(buffer=True)
|
unittest.main(buffer=True)
|
||||||
|
Reference in New Issue
Block a user