From e47029cc317db032788a2c269009647358b645f0 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 3 May 2022 17:51:07 +0200 Subject: [PATCH] Allow to change flash parameters only when no SHA256 digest is appended Partial fix for https://github.com/espressif/esp-idf/issues/8798 --- esptool/cmds.py | 34 +++++++++++++++++++++++++++++++--- test/test_esptool.py | 19 +++++++++++++++++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/esptool/cmds.py b/esptool/cmds.py index 5f9cb0e4bb..69eaac4944 100644 --- a/esptool/cmds.py +++ b/esptool/cmds.py @@ -260,16 +260,44 @@ def _update_image_flash_params(esp, address, args, image): ) return image + # After the 8-byte header comes the extended header for chips others than ESP8266. + # The 15th byte of the extended header indicates if the image is protected by + # a SHA256 checksum. In that case we should not modify the header because + # the checksum check would fail. + sha_implies_keep = args.chip != "esp8266" and image[8 + 15] == 1 + + def print_keep_warning(arg_to_keep, arg_used): + print( + "Warning: Image file at {addr} is protected with a hash checksum, " + "so not changing the flash {arg} setting. " + "Use the --flash_{arg}=keep option instead of --flash_{arg}={arg_orig} " + "in order to remove this warning".format( + addr=hex(address), arg=arg_to_keep, arg_orig=arg_used + ) + ) + if args.flash_mode != "keep": - flash_mode = FLASH_MODES[args.flash_mode] + new_flash_mode = FLASH_MODES[args.flash_mode] + if flash_mode != new_flash_mode and sha_implies_keep: + print_keep_warning("mode", args.flash_mode) + else: + flash_mode = new_flash_mode flash_freq = flash_size_freq & 0x0F if args.flash_freq != "keep": - flash_freq = esp.parse_flash_freq_arg(args.flash_freq) + new_flash_freq = esp.parse_flash_freq_arg(args.flash_freq) + if flash_freq != new_flash_freq and sha_implies_keep: + print_keep_warning("frequency", args.flash_freq) + else: + flash_freq = new_flash_freq flash_size = flash_size_freq & 0xF0 if args.flash_size != "keep": - flash_size = esp.parse_flash_size_arg(args.flash_size) + new_flash_size = esp.parse_flash_size_arg(args.flash_size) + if flash_size != new_flash_size and sha_implies_keep: + print_keep_warning("size", args.flash_size) + else: + flash_size = new_flash_size flash_params = struct.pack(b"BB", flash_mode, flash_size + flash_freq) if flash_params != image[2:4]: diff --git a/test/test_esptool.py b/test/test_esptool.py index 46cbd40415..79d22a63a2 100755 --- a/test/test_esptool.py +++ b/test/test_esptool.py @@ -759,9 +759,17 @@ def test_detect_size_changes_size(self): ) readback = self.readback(self.flash_offset, 8) self.assertEqual(self.header[:3], readback[:3]) # first 3 bytes unchanged - self.assertNotEqual(self.header[3], readback[3]) # size_freq byte changed + if chip in ["esp8266", "esp32"]: + self.assertNotEqual(self.header[3], readback[3]) # size_freq byte changed + else: + # Not changed because protected by SHA256 digest + self.assertEqual(self.header[3], readback[3]) # size_freq byte unchanged self.assertEqual(self.header[4:], readback[4:]) # rest unchanged + @unittest.skipUnless( + chip in ["esp8266", "esp32"], + "Bootloader header needs to be modifiable - without sha256", + ) def test_explicit_set_size_freq_mode(self): self.run_esptool( "write_flash -fs 2MB -fm dout -ff 80m 0x%x %s" @@ -855,7 +863,14 @@ def test_flash_header_rewrite(self): output = self.run_esptool( "write_flash -fm dout -ff 20m 0x%x %s" % (self.BL_OFFSET, bl_image) ) - self.assertIn("Flash params set to", output) + if chip in ["esp8266", "esp32"]: + # There is no SHA256 digest so the header can be changed - ESP8266 doesn't + # support this; The test image for ESP32 just doesn't have it. + self.assertIn("Flash params set to", output) + else: + self.assertNotIn("Flash params set to", output) + self.assertIn("not changing the flash mode setting", output) + self.assertIn("not changing the flash frequency setting", output) def test_flash_header_no_magic_no_rewrite(self): # first image doesn't start with magic byte, second image does