Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a CRC32 over progmem and ESP.checkFlashCRC #6566

Merged
merged 17 commits into from
Dec 20, 2019

Conversation

earlephilhower
Copy link
Collaborator

Automatically embed a CRC32 of the program memory (including bootloader
but excluding any filesystems) in all images in unused space in the
bootloader block.

Add a call, ESP.checkFlashCRC() which returns false if the calculated
CRC doesn't match the one stored in the image (i.e. flash corruption).

Fixes #4165

Automatically embed a CRC32 of the program memory (including bootloader
but excluding any filesystems) in all images in unused space in the
bootloader block.

Add a call, ESP.checkFlashCRC() which returns false if the calculated
CRC doesn't match the one stored in the image (i.e. flash corruption).

Fixes esp8266#4165
cores/esp8266/Esp.cpp Outdated Show resolved Hide resolved
Show CRC checking catch a 1-bit error in program code by corrupting a
large array, and then return it to clean and verify the CRC matches once
again.

Add comments to the CRC check routine

Clean up pylint complaints on crc32bin.py
Add an assertion in the eboot linker file to guarantee that we have at
least 8 bytes of unused space at the end of the boot sector to patch in
the CRC.  If not, the eboot link will fail.
Per discussion with @d-a-v.

When the CRC check fails, you could *try* to do certain things (but may
not succeed since there is known flash corruption at that point).  List
a few ideas for application authors.
platform.txt Outdated Show resolved Hide resolved
@earlephilhower earlephilhower merged commit 52d84b1 into esp8266:master Dec 20, 2019
@earlephilhower earlephilhower deleted the crc32 branch December 20, 2019 22:38
@dok-net
Copy link
Contributor

dok-net commented Dec 21, 2019

@earlephilhower Is this supposed to work out of the box just yet? Like pulling master, restarting the IDE, rebuilding my sketch.

I get on one board:

esptool.py v2.8
Serial port COM3
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: […]
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 16MB
Flash params set to 0x0290
Compressed 278784 bytes to 205050...
Writing at 0x00000000... (7 %)
[…]
Writing at 0x00030000... (100 %)
Wrote 278784 bytes (205050 compressed) at 0x00000000 in 18.9 seconds (effective 118.2 kbit/s)...
	The upload process has finished.
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Repeater example for EspSoftwareSerial
CRC check: ERROR
Vcc = 3020V

But, on another board:

esptool.py v2.8
Serial port COM5
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: […]
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 278784 bytes to 205049...
Writing at 0x00000000... (7 %)
[…]
Writing at 0x00030000... (100 %)
Wrote 278784 bytes (205049 compressed) at 0x00000000 in 18.1 seconds (effective 123.3 kbit/s)...
	The upload process has finished.
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Repeater example for EspSoftwareSerial
CRC check: OK
Vcc = 3041V

Immediately noticeable is the 1 byte difference in compressed size.

@@ -30,6 +30,9 @@
ffreqb = { '40': 0, '26': 1, '20': 2, '80': 15 }
fsizeb = { '512K': 0, '256K': 1, '1M': 2, '2M': 3, '4M': 4, '8M': 8, '16M': 9 }

crcsize_offset = 4088
crcval_offset = 4092
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I think it is off by one error, starting index should be 4087?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcspr Build+upload with crcsize_offset = 4087 crashes on boot.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, nvm :)

@dok-net
Copy link
Contributor

dok-net commented Dec 21, 2019

@earlephilhower Ah, OK, I never knew that I HAVE TO select the precise right board w.r.t. flash size. Building for LOLIN D1 mini Pro (16MB flash settings in config) it's fine:

Repeater example for EspSoftwareSerial
CRC check: OK
Vcc = 3018V

Please allow one remark: could you be more precise in the readme on the use of
ADC_MODE(ADC_VCC); - my first quite naïve take on "at the top of your sketch" was to place it inside setup() ;-)
How does this CRC complement, or is superseded, by signing the sketch? Would using an auto-generated keypair not have been an equal solution, albeit more tamper proof, but perhaps more resource consuming?

@earlephilhower
Copy link
Collaborator Author

@dok-net, your comment explains it! If you send the wrong flash size, the Updater will change one byte silently to match what's already set. So the CRC check did succeed and found an error...what was in flash was not what you sent in! :)

This was related to another bug (already fixed) where the Updater was always changing 1 byte of an uploaded image, even when it was a FS.

Signing guarantees that you created the bin being uploaded, and is a 1-time check on upload only.

CRC checks dynamically (when you call it) for changes to the flash vs. when you generated the bitstream. Random bit flips, flash page failures, etc.

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.

feature request: CRC for program memory
4 participants