Move rboot_verify_image to rboot-api

Removes rboot-integration.c, removes need for clients to include rboot-integration.h
This commit is contained in:
Angus Gratton 2016-05-03 11:07:10 +10:00
parent 6eceb5843c
commit 03559de5cb
5 changed files with 162 additions and 136 deletions

View file

@ -4,6 +4,8 @@
// richardaburton@gmail.com
// See license.txt for license terms.
// OTA code based on SDK sample from Espressif.
//
// esp-open-rtos additions Copyright 2016 Angus Gratton
//////////////////////////////////////////////////
#include <rboot.h>
@ -209,6 +211,150 @@ bool ICACHE_FLASH_ATTR rboot_get_last_boot_mode(uint8 *mode) {
}
#endif
/* NOTE: Functions below here were added for esp-open-rtos only */
uint32_t rboot_get_slot_offset(uint8_t slot) {
rboot_config conf;
conf = rboot_get_config();
if (slot >= conf.count) return (uint32_t)-1;
return conf.roms[slot];
}
/* Structures for parsing the rboot OTA image format */
typedef struct __attribute__((packed)) {
uint8_t magic;
uint8_t section_count;
uint8_t val[2]; /* flash size & speed when placed @ offset 0, I thik ignored otherwise */
uint32_t entrypoint;
} image_header_t;
typedef struct __attribute__((packed)) {
uint32_t load_addr;
uint32_t length;
} section_header_t;
#define ROM_MAGIC_OLD 0xe9
#define ROM_MAGIC_NEW 0xea
bool rboot_verify_image(uint32_t initial_offset, uint32_t *image_length, const char **error_message)
{
uint32_t offset = initial_offset;
char *error = NULL;
RBOOT_DEBUG("rboot_verify_image: verifying image at 0x%08x\n", initial_offset);
if(offset % 4) {
error = "Unaligned flash offset";
goto fail;
}
/* sanity limit on how far we can read */
uint32_t end_limit = offset + 0x100000;
image_header_t image_header __attribute__((aligned(4)));
if(sdk_spi_flash_read(offset, &image_header, sizeof(image_header_t))) {
error = "Flash fail";
goto fail;
}
offset += sizeof(image_header_t);
if(image_header.magic != ROM_MAGIC_OLD && image_header.magic != ROM_MAGIC_NEW) {
error = "Missing initial magic";
goto fail;
}
bool is_new_header = (image_header.magic == ROM_MAGIC_NEW); /* a v1.2/rboot header, so expect a v1.1 header after the initial section */
int remaining_sections = image_header.section_count;
uint8_t checksum = CHKSUM_INIT;
while(remaining_sections > 0 && offset < end_limit)
{
/* read section header */
section_header_t header __attribute__((aligned(4)));
if(sdk_spi_flash_read(offset, &header, sizeof(section_header_t))) {
error = "Flash fail";
goto fail;
}
RBOOT_DEBUG("Found section @ 0x%08x (abs 0x%08x) length %d load 0x%08x\n", offset-initial_offset, offset, header.length, header.load_addr);
offset += sizeof(section_header_t);
if(header.length+offset > end_limit) {
break; /* sanity check: will reading section take us off end of expected flashregion? */
}
if(header.length % 4) {
error = "Header length not modulo 4";
goto fail;
}
if(!is_new_header) {
/* Add individual data of the section to the checksum. */
char chunk[16] __attribute__((aligned(4)));
for(int i = 0; i < header.length; i++) {
if(i % sizeof(chunk) == 0)
sdk_spi_flash_read(offset+i, (uint32_t *)chunk, sizeof(chunk));
checksum ^= chunk[i % sizeof(chunk)];
}
}
offset += header.length;
/* pad section to 4 byte align */
offset = (offset+3) & ~3;
remaining_sections--;
if(is_new_header) {
/* pad to a 16 byte offset */
offset = (offset+15) & ~15;
/* expect a v1.1 header here at start of "real" sections */
sdk_spi_flash_read(offset, (uint32_t *)&image_header, sizeof(image_header_t));
offset += sizeof(image_header_t);
if(image_header.magic != ROM_MAGIC_OLD) {
error = "Bad second magic";
goto fail;
}
remaining_sections = image_header.section_count;
is_new_header = false;
}
}
if(remaining_sections > 0) {
error = "Image truncated";
goto fail;
}
/* add a byte for the image checksum (actually comes after the padding) */
offset++;
/* pad the image length to a 16 byte boundary */
offset = (offset+15) & ~15;
uint32_t read_checksum;
sdk_spi_flash_read(offset-1, &read_checksum, 1);
if((uint8_t)read_checksum != checksum) {
error = "Invalid checksum";
goto fail;
}
RBOOT_DEBUG("rboot_verify_image: verified expected 0x%08x bytes.\n", offset - initial_offset);
if(image_length)
*image_length = offset - initial_offset;
return true;
fail:
if(error_message)
*error_message = error;
if(error) {
printf("%s: %s\n", __func__, error);
}
if(image_length)
*image_length = offset - initial_offset;
return false;
}
#ifdef __cplusplus
}
#endif