1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-10 04:22:05 +03:00

Add a CRC32 over progmem and ESP.checkFlashCRC (#6566)

* Add a CRC32 over progmem and ESP.checkFlashCRC

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

* Add example that corrupts itself, comments

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

* Check linker script for CRC space in bootsector

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.

* Add note about what to do if CRC check fails

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.

* Only single, flash/ram friendly crc32() function

* Combine the CRC calc and bin generation in 1 step

Per discussion w/@mcspr, combine the CRC calculation with the binary
generation, removing the additional build step.
This commit is contained in:
Earle F. Philhower, III
2019-12-20 14:38:35 -08:00
committed by GitHub
parent 9985a32914
commit 52d84b1ead
7 changed files with 124 additions and 1 deletions

View File

@ -26,6 +26,7 @@
#include "MD5Builder.h"
#include "umm_malloc/umm_malloc.h"
#include "cont.h"
#include "coredecls.h"
extern "C" {
#include "user_interface.h"
@ -447,6 +448,25 @@ bool EspClass::checkFlashConfig(bool needsEquals) {
return false;
}
bool EspClass::checkFlashCRC() {
// The CRC and total length are placed in extra space at the end of the 4K chunk
// of flash occupied by the bootloader. If the bootloader grows to >4K-8 bytes,
// we'll need to adjust this.
uint32_t flashsize = *((uint32_t*)(0x40200000 + 4088)); // Start of PROGMEM plus 4K-8
uint32_t flashcrc = *((uint32_t*)(0x40200000 + 4092)); // Start of PROGMEM plus 4K-4
uint32_t z[2];
z[0] = z[1] = 0;
// Start the checksum
uint32_t crc = crc32((const void*)0x40200000, 4096-8, 0xffffffff);
// Pretend the 2 words of crc/len are zero to be idempotent
crc = crc32(z, 8, crc);
// Finish the CRC calculation over the rest of flash
crc = crc32((const void*)0x40201000, flashsize-4096, crc);
return crc == flashcrc;
}
String EspClass::getResetReason(void) {
char buff[32];
if (resetInfo.reason == REASON_DEFAULT_RST) { // normal startup by power on

View File

@ -176,6 +176,8 @@ class EspClass {
bool checkFlashConfig(bool needsEquals = false);
bool checkFlashCRC();
bool flashEraseSector(uint32_t sector);
bool flashWrite(uint32_t offset, uint32_t *data, size_t size);
bool flashRead(uint32_t offset, uint32_t *data, size_t size);

View File

@ -20,6 +20,7 @@
*/
#include "coredecls.h"
#include "pgmspace.h"
// moved from core_esp8266_eboot_command.cpp
uint32_t crc32 (const void* data, size_t length, uint32_t crc /*= 0xffffffff*/)
@ -27,7 +28,7 @@ uint32_t crc32 (const void* data, size_t length, uint32_t crc /*= 0xffffffff*/)
const uint8_t* ldata = (const uint8_t*)data;
while (length--)
{
uint8_t c = *ldata++;
uint8_t c = pgm_read_byte(ldata++);
for (uint32_t i = 0x80; i > 0; i >>= 1)
{
bool bit = crc & 0x80000000;