Skip to content

Commit

Permalink
esptool: Adds min_rev_full and max_rev_full (in format: major * 100 +…
Browse files Browse the repository at this point in the history
… minor)
  • Loading branch information
KonstantinKondrashov committed Sep 13, 2022
1 parent 56ea80d commit 84918ea
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 20 deletions.
8 changes: 6 additions & 2 deletions docs/en/advanced-topics/firmware-image-format.rst
Expand Up @@ -83,9 +83,13 @@ The image header is 8 bytes long:
+--------+---------------------------------------------------------------------------------------------------------+
| 4-5 | Chip ID (which ESP device is this image for) |
+--------+---------------------------------------------------------------------------------------------------------+
| 6 | Minimum chip revision supported by the image |
| 6 | Minimal chip revision supported by the image (deprecated, use the following field) |
+--------+---------------------------------------------------------------------------------------------------------+
| 7-14 | Reserved bytes in additional header space, currently unused |
| 7-8 | Minimal chip revision supported by the image (in format: major * 100 + minor) |
+--------+---------------------------------------------------------------------------------------------------------+
| 9-10 | Maximal chip revision supported by the image (in format: major * 100 + minor) |
+--------+---------------------------------------------------------------------------------------------------------+
| 11-14 | Reserved bytes in additional header space, currently unused |
+--------+---------------------------------------------------------------------------------------------------------+
| 15 | Hash appended (If 1, SHA256 digest is appended after the checksum) |
+--------+---------------------------------------------------------------------------------------------------------+
Expand Down
20 changes: 19 additions & 1 deletion esptool/__init__.py
Expand Up @@ -403,14 +403,32 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect):
default="1",
)
parser_elf2image.add_argument(
# it kept for compatibility
# Minimum chip revision (deprecated, consider using --min-rev-full)
"--min-rev",
"-r",
help="Minimum chip revision",
help=argparse.SUPPRESS,
type=int,
choices=range(256),
metavar="{0, ... 255}",
default=0,
)
parser_elf2image.add_argument(
"--min-rev-full",
help="Minimal chip revision (in format: major * 100 + minor)",
type=int,
choices=range(65536),
metavar="{0, ... 65535}",
default=0,
)
parser_elf2image.add_argument(
"--max-rev-full",
help="Maximal chip revision (in format: major * 100 + minor)",
type=int,
choices=range(65536),
metavar="{0, ... 65535}",
default=65535,
)
parser_elf2image.add_argument(
"--secure-pad",
action="store_true",
Expand Down
12 changes: 9 additions & 3 deletions esptool/bin_image.py
Expand Up @@ -548,7 +548,7 @@ class ESP32FirmwareImage(BaseFirmwareImage):
# to be set to this value so ROM bootloader will skip it.
WP_PIN_DISABLED = 0xEE

EXTENDED_HEADER_STRUCT_FMT = "<BBBBHB" + ("B" * 8) + "B"
EXTENDED_HEADER_STRUCT_FMT = "<BBBBHBHH" + ("B" * 4) + "B"

IROM_ALIGN = 65536

Expand All @@ -568,6 +568,8 @@ def __init__(self, load_file=None, append_digest=True):
self.wp_drv = 0
self.chip_id = 0
self.min_rev = 0
self.min_rev_full = 0
self.max_rev_full = 0

self.append_digest = append_digest

Expand Down Expand Up @@ -789,9 +791,11 @@ def split_byte(n):
)

self.min_rev = fields[5]
self.min_rev_full = fields[6]
self.max_rev_full = fields[7]

# reserved fields in the middle should all be zero
if any(f for f in fields[6:-1] if f != 0):
if any(f for f in fields[8:-1] if f != 0):
print(
"Warning: some reserved header fields have non-zero values. "
"This image may be from a newer esptool.py?"
Expand Down Expand Up @@ -819,8 +823,10 @@ def join_byte(ln, hn):
join_byte(self.hd_drv, self.wp_drv),
self.ROM_LOADER.IMAGE_CHIP_ID,
self.min_rev,
self.min_rev_full,
self.max_rev_full,
]
fields += [0] * 8 # padding
fields += [0] * 4 # padding
fields += [append_digest]

packed = struct.pack(self.EXTENDED_HEADER_STRUCT_FMT, *fields)
Expand Down
65 changes: 52 additions & 13 deletions esptool/cmds.py
Expand Up @@ -339,19 +339,48 @@ def write_flash(esp, args):
f"{argfile.name} is not an {esp.CHIP_NAME} image. "
"Use --force to flash anyway."
)
# In IDF, image.min_rev is set based on Kconfig option.
# For C3 chip, image.min_rev is the Minor revision
# while for the rest chips it is the Major revision.
if esp.CHIP_NAME == "ESP32-C3":
rev = esp.get_minor_chip_version()

# this logic below decides which min_rev to use, min_rev or min/max_rev_full
if image.max_rev_full == 0: # image does not have max/min_rev_full fields
use_rev_full_fields = False
elif image.max_rev_full == 65535: # image has default value of max_rev_full
if (
image.min_rev_full == 0 and image.min_rev != 0
): # min_rev_full is not set, min_rev is used
use_rev_full_fields = False
use_rev_full_fields = True
else: # max_rev_full set to a version
use_rev_full_fields = True

if use_rev_full_fields:
rev = esp.get_chip_revision()
if rev < image.min_rev_full or rev > image.max_rev_full:
error_str = f"{argfile.name} requires chip revision in range "
error_str += (
f"[v{image.min_rev_full // 100}.{image.min_rev_full % 100} - "
)
if image.max_rev_full == 65535:
error_str += "max rev not set] "
else:
error_str += (
f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}] "
)
error_str += f"(this chip is revision v{rev // 100}.{rev % 100})"
raise FatalError(f"{error_str}. Use --force to flash anyway.")
else:
rev = esp.get_major_chip_version()
if rev < image.min_rev:
raise FatalError(
f"{argfile.name} requires chip revision "
f"{image.min_rev} or higher (this chip is revision {rev}). "
"Use --force to flash anyway."
)
# In IDF, image.min_rev is set based on Kconfig option.
# For C3 chip, image.min_rev is the Minor revision
# while for the rest chips it is the Major revision.
if esp.CHIP_NAME == "ESP32-C3":
rev = esp.get_minor_chip_version()
else:
rev = esp.get_major_chip_version()
if rev < image.min_rev:
raise FatalError(
f"{argfile.name} requires chip revision "
f"{image.min_rev} or higher (this chip is revision {rev}). "
"Use --force to flash anyway."
)

# In case we have encrypted files to write,
# we first do few sanity checks before actual flash
Expand Down Expand Up @@ -683,7 +712,15 @@ def get_key_from_value(dict, val):
)
)
print("Chip ID: {}".format(image.chip_id))
print("Minimal chip revision: {}".format(image.min_rev))
print(
"Minimal chip revision: "
f"v{image.min_rev_full // 100}.{image.min_rev_full % 100}, "
f"(legacy min_rev = {image.min_rev})"
)
print(
"Maximal chip revision: "
f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}"
)
print()

# Segments overview
Expand Down Expand Up @@ -844,6 +881,8 @@ def elf2image(args):
if args.secure_pad_v2:
image.secure_pad = "2"
image.min_rev = args.min_rev
image.min_rev_full = args.min_rev_full
image.max_rev_full = args.max_rev_full
image.append_digest = args.append_digest
elif args.version == "1": # ESP8266
image = ESP8266ROMFirmwareImage()
Expand Down
3 changes: 2 additions & 1 deletion test/test_image_info.py
Expand Up @@ -97,7 +97,8 @@ def test_v2_esp32c3(self):
"cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0" in out,
"Wrong flash pins drive settings",
)
self.assertTrue("Minimal chip revision: 0" in out, "Wrong min revision")
self.assertTrue("Minimal chip revision: v0.0" in out, "Wrong min revision")
self.assertTrue("Maximal chip revision: v0.0" in out, "Wrong min revision")

# Segments
self.assertTrue(
Expand Down

0 comments on commit 84918ea

Please sign in to comment.