Skip to content

Fix bootloader SHA256 to hash actual image size, not full allocated region#5331

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/fix-bootloader-checksum-issue
Draft

Fix bootloader SHA256 to hash actual image size, not full allocated region#5331
Copilot wants to merge 4 commits intomainfrom
copilot/fix-bootloader-checksum-issue

Conversation

Copy link
Contributor

Copilot AI commented Jan 31, 2026

Bootloader SHA256 calculation was hashing the full 32KB allocated region (BOOTLOADER_SIZE) instead of the actual bootloader image size. This caused hash mismatches for identical bootloaders when devices had different garbage data in unused flash memory beyond the actual bootloader end (~47KB for ESP32 classic).

Changes

  • Added getActualBootloaderSize(): Parses bootloader image structure from flash

    • Validates ESP32 image header (magic byte, segment count)
    • Iterates segment headers to calculate data size
    • Accounts for appended SHA256 hash and checksum byte
    • Applies 16-byte alignment per ESP32 flash requirements
    • Falls back to BOOTLOADER_SIZE on parse errors
  • Modified calculateBootloaderSHA256(): Now uses actual bootloader size instead of full allocated region

// Before: hashed full 32KB region including garbage data
for (uint32_t offset = 0; offset < BOOTLOADER_SIZE; offset += chunkSize) {
  // ...
}

// After: only hash actual bootloader image
size_t actualBootloaderSize = getActualBootloaderSize();
for (uint32_t offset = 0; offset < actualBootloaderSize; offset += chunkSize) {
  // ...
}

This ensures consistent SHA256 hashes for identical bootloaders regardless of unused memory content.

Original prompt

This section details on the original issue you should resolve

<issue_title>Booloader checksum too big</issue_title>
<issue_description>The code to create the sha256 of the bootloader is creating more unqiue hash values than expected, we suspect this might be for devices that have not specifically done a full erase of the memory so unused memory might be throwing off the calculations. The original logic was for the full memory that could be used for bootloader would be included, but perhaps this needs to be reduced to actually reflect how much is actually used. It appears to end at B9A0 for the bootloader we use for the esp32 classic</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@netmindz
Copy link
Member

@copilot - my comment about then end might be wrong, looking again it appears the file i'm looking at might also have the partition table and other data, so please disregard my comment as to the memory end location and do your own research

Copilot AI and others added 3 commits January 31, 2026 11:59
…2KB region

- Add getActualBootloaderSize() helper to parse bootloader image structure
- Calculate actual size by parsing segment headers, hash, and checksum
- Only hash the actual bootloader data instead of full BOOTLOADER_SIZE
- This prevents different hashes for same bootloader due to garbage data in unused memory

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
- Define MAX_SEGMENT_SIZE constant instead of magic number
- Use bitwise alignment operation for better efficiency
- Clarify that checksum byte is part of ESP-IDF image format

Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix bootloader checksum calculation for used memory Fix bootloader SHA256 to hash actual image size, not full allocated region Jan 31, 2026
Copilot AI requested a review from netmindz January 31, 2026 12:03
Copy link
Contributor Author

Copilot AI commented Jan 31, 2026

@copilot - my comment about then end might be wrong, looking again it appears the file i'm looking at might also have the partition table and other data, so please disregard my comment as to the memo...

Understood. The implementation doesn't rely on the B9A0 endpoint - instead, it dynamically parses the bootloader image structure from flash to determine the actual size. The code:

  1. Reads and validates the ESP32 image header (magic byte, segment count)
  2. Iterates through all segment headers to calculate total data size
  3. Adds the appended SHA256 hash (if present) and checksum byte
  4. Applies 16-byte alignment per ESP32 flash requirements

This approach works for any bootloader image regardless of its specific size, and only hashes the actual bootloader data (not unused/garbage memory beyond it).

Commits: b50b2a9, 1febf0b

@netmindz
Copy link
Member

@copilot Will this approach also work for S2, S3 and C3 which have slightly different bootloaders?

Copy link
Contributor Author

Copilot AI commented Jan 31, 2026

@copilot Will this approach also work for S2, S3 and C3 which have slightly different bootloaders?

Yes, the implementation works for all ESP32 variants (S2, S3, C3, C6, etc.) because:

  1. It uses the existing chip-specific BOOTLOADER_OFFSET constant (0x0000 for S3/C3/C6, 0x1000 for ESP32/S2, 0x2000 for P4/C5)
  2. The ESP32 image format is standardized across all variants - same header structure, segment format, SHA256 hash, and checksum byte
  3. It uses BOOTLOADER_SIZE as the fallback, which is already chip-aware

The parsing logic is based on ESP-IDF's esp_image_format.h, which applies to all ESP32 family chips. The "slightly different bootloaders" you mentioned refer to different flash offsets and chip IDs, not different image formats - these are already handled by the existing constants.

@willmmiles
Copy link
Member

The image size computation should be shared with verifyBootloaderImage() - I was just (literally right now!) in the middle of cleaning that up in #5128. I can throw this in while I'm at it if that's OK with you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Booloader checksum too big

3 participants