67#include <sys/unistd.h>
71#include "mmhal_flash.h"
80#define MAX_UPDATE_ATTEMPTS 10
83#define MAX_SEGMENT_SIZE 32768
89 BOOTLOADER_ERR_FILE_NOT_FOUND,
90 BOOTLOADER_ERR_SIGNATURE_NOT_FOUND,
91 BOOTLOADER_ERR_FILE_VERIFICATION_FAILED,
92 BOOTLOADER_ERR_INVALID_FILE,
93 BOOTLOADER_ERR_FILE_CORRUPT,
94 BOOTLOADER_ERR_ERASE_FAILED,
95 BOOTLOADER_ERR_PROGRAM_FAILED,
96 BOOTLOADER_ERR_TOO_MANY_ATTEMPTS,
97 BOOTLOADER_ERR_FILE_DECOMPRESSION,
120 for (i = 0; i < approx_delay_ms; i++)
139 for (ii = 0; ii < code; ii++)
193 while (block_address < end_address)
225 int ret = read(fd, &hdr_overlay,
sizeof(hdr_overlay));
226 if (ret !=
sizeof(hdr_overlay))
228 return BOOTLOADER_ERR_FILE_CORRUPT;
231 seg_hdr->
type = le16toh(hdr_overlay.
type);
232 seg_hdr->
len = le16toh(hdr_overlay.
len);
234 return BOOTLOADER_OK;
248 int ret = read(fd, &tmp,
sizeof(tmp));
249 if (ret !=
sizeof(tmp))
251 return BOOTLOADER_ERR_FILE_CORRUPT;
256 return BOOTLOADER_OK;
269 uint32_t mbin_magic = 0;
270 uint32_t load_address, load_size;
271 unsigned long compressed_size, puffed_size;
274 bool modified =
false;
277 int fd = open(fname, O_RDONLY);
281 return BOOTLOADER_ERR_FILE_NOT_FOUND;
286 if (ret != BOOTLOADER_OK)
288 ret = BOOTLOADER_ERR_FILE_CORRUPT;
291 if (seg_hdr.
type != FIELD_TYPE_MAGIC)
293 ret = BOOTLOADER_ERR_INVALID_FILE;
296 if (seg_hdr.
len !=
sizeof(mbin_magic))
298 ret = BOOTLOADER_ERR_FILE_CORRUPT;
304 ret = BOOTLOADER_ERR_INVALID_FILE;
312 if (ret != BOOTLOADER_OK)
317 switch (seg_hdr.
type)
319 case FIELD_TYPE_SW_SEGMENT:
321 if (ret != BOOTLOADER_OK)
327 load_size = seg_hdr.
len -
sizeof(load_address);
331 ret = BOOTLOADER_ERR_FILE_CORRUPT;
336 if (ret != (
int)load_size)
339 ret = BOOTLOADER_ERR_FILE_CORRUPT;
354 ret = BOOTLOADER_ERR_PROGRAM_FAILED;
362 ret = BOOTLOADER_ERR_INVALID_FILE;
367 case FIELD_TYPE_SW_SEGMENT_DEFLATED:
369 if (ret != BOOTLOADER_OK)
376 if (ret != BOOTLOADER_OK)
385 ret = BOOTLOADER_ERR_FILE_CORRUPT;
389 compressed_size = seg_hdr.
len -
sizeof(load_address) -
sizeof(load_size);
393 ret = BOOTLOADER_ERR_FILE_CORRUPT;
398 if (ret != (
int)compressed_size)
401 ret = BOOTLOADER_ERR_FILE_CORRUPT;
406 puffed_size = load_size;
408 if (puffed_size != load_size)
411 ret = BOOTLOADER_ERR_FILE_DECOMPRESSION;
426 ret = BOOTLOADER_ERR_PROGRAM_FAILED;
434 ret = BOOTLOADER_ERR_INVALID_FILE;
439 case FIELD_TYPE_EOF_WITH_SIGNATURE:
448 case FIELD_TYPE_FW_SEGMENT:
449 case FIELD_TYPE_FW_SEGMENT_DEFLATED:
450 case FIELD_TYPE_FW_TLV_BCF_ADDR:
451 case FIELD_TYPE_BCF_BOARD_CONFIG:
452 case FIELD_TYPE_BCF_REGDOM:
456 ret = BOOTLOADER_ERR_FILE_CORRUPT;
461 if (ret != seg_hdr.
len)
464 ret = BOOTLOADER_ERR_FILE_CORRUPT;
469 case FIELD_TYPE_MAGIC:
472 ret = BOOTLOADER_ERR_FILE_CORRUPT;
480 ret = BOOTLOADER_ERR_FILE_CORRUPT;
488 ret = BOOTLOADER_ERR_INVALID_FILE;
513 if (
mmconfig_read_bytes(
"IMAGE_SIGNATURE", compare,
sizeof(compare), 0) !=
sizeof(compare))
516 return BOOTLOADER_ERR_SIGNATURE_NOT_FOUND;
520 int fd = open(fname, O_RDONLY);
524 return BOOTLOADER_ERR_FILE_NOT_FOUND;
529 bytesread = read(fd, data,
sizeof(data));
535 sha256_update(&ctx, data, bytesread);
536 }
while (bytesread ==
sizeof(data));
538 sha256_final(&ctx, hash);
541 if (memcmp(hash, compare,
sizeof(hash)) != 0)
544 return BOOTLOADER_ERR_FILE_VERIFICATION_FAILED;
546 return BOOTLOADER_OK;
554 static char update_path[128];
575 if (ret != BOOTLOADER_OK)
584 int update_attempts = 0;
598 if (ret != BOOTLOADER_OK)
603 if (ret != BOOTLOADER_OK)
636 uint32_t go_address = (*((
volatile uint32_t *)(((uint32_t)&
application_start) + 4)));
637 void (*jump_to_app)(void) = (
void (*)(void))go_address;
uint8_t application_start
Start of Application region in flash.
static void check_update()
Check for an update, if an update is found, perform it.
static int read_segment_header(int fd, struct mbin_tlv_hdr *seg_hdr)
Loads the segment header from file.
static void erase_application_area(void)
This function erases the entire application flash region.
static void blink_error_code(int code)
Blinks the hardware error LED to indicate the error code.
#define MAX_UPDATE_ATTEMPTS
Maximum number of times we attempt to update before giving up.
#define MAX_SEGMENT_SIZE
Maximum size of a segment, set to 32768.
static int verify_signature(const char *fname)
Verifies the signature of the file.
static uint8_t segment_buffer[MAX_SEGMENT_SIZE]
Temporary buffer for loading segments.
int main(void)
The bootloader entry point.
bootloader_return_codes
Bootloader return codes.
static int load_and_flash_mbin(const char *fname, bool make_changes)
Loads and flashes the image.
uint8_t application_end
End of Application region in flash.
static uint8_t deflate_buffer[MAX_SEGMENT_SIZE]
Temporary buffer for deflating segments.
static void delay_ms(uint32_t approx_delay_ms)
Implements a delay of approximately the duration specified.
static int read_uint32(int fd, uint32_t *val)
Loads a 32 bit integer from file and converts to host endian.
static void update_failed(int code)
Called when multiple attempts to update failed, must not return.
#define MBIN_SW_MAGIC_NUMBER
Expected value of the magic field for a SW image MMSW.
int mmconfig_write_int(const char *key, int value)
Converts the given integer to a string and writes to persistent store.
static int mmconfig_delete_key(const char *key)
Deletes the specified key(s) from persistent store.
int mmconfig_read_string(const char *key, char *buffer, int bufsize)
Returns the persistent store string value identified by the key.
int mmconfig_read_int(const char *key, int *value)
Returns the integer stored in persistent store identified by the key.
int mmconfig_read_bytes(const char *key, void *buffer, uint32_t buffsize, uint32_t offset)
Returns the persistent store data identified by the key.
int mmconfig_write_string(const char *key, const char *value)
Writes the null terminated string to persistent store location identified by key.
void mmhal_set_error_led(bool state)
Set the error LED to the requested state.
int mmhal_flash_erase(uint32_t block_address)
Erases a block of Flash pointed to by the block_address.
uint32_t mmhal_flash_getblocksize(uint32_t block_address)
Returns the size of the Flash block at the specified address.
int mmhal_flash_write(uint32_t write_address, const uint8_t *data, size_t size)
Write a block of data to the specified Flash address.
void mmhal_reset(void)
Reset the microcontroller.
#define MMOSAL_ASSERT(expr)
Assert that the given expression evaluates to true and abort execution if not.
uint32_t mmosal_get_time_ticks(void)
Get the system time in ticks.
TLV header data structure.
uint16_t len
Length of payload (excludes header).
uint16_t type
Type (see mbin_tlv_types).