62#include <sys/unistd.h>
66#include "mmhal_flash.h"
75#define MAX_UPDATE_ATTEMPTS 10
78#define MAX_SEGMENT_SIZE 32768
84 BOOTLOADER_ERR_FILE_NOT_FOUND,
85 BOOTLOADER_ERR_SIGNATURE_NOT_FOUND,
86 BOOTLOADER_ERR_FILE_VERIFICATION_FAILED,
87 BOOTLOADER_ERR_INVALID_FILE,
88 BOOTLOADER_ERR_FILE_CORRUPT,
89 BOOTLOADER_ERR_ERASE_FAILED,
90 BOOTLOADER_ERR_PROGRAM_FAILED,
91 BOOTLOADER_ERR_TOO_MANY_ATTEMPTS,
92 BOOTLOADER_ERR_FILE_DECOMPRESSION,
116 for (i = 0; i < approx_delay_ms; i++)
135 for (ii = 0; ii < code; ii++)
189 while (block_address < end_address)
222 int ret = read(fd, &hdr_overlay,
sizeof(hdr_overlay));
223 if (ret !=
sizeof(hdr_overlay))
225 return BOOTLOADER_ERR_FILE_CORRUPT;
228 seg_hdr->
type = le16toh(hdr_overlay.
type);
229 seg_hdr->
len = le16toh(hdr_overlay.
len);
231 return BOOTLOADER_OK;
245 int ret = read(fd, &tmp,
sizeof(tmp));
246 if (ret !=
sizeof(tmp))
248 return BOOTLOADER_ERR_FILE_CORRUPT;
253 return BOOTLOADER_OK;
266 uint32_t mbin_magic = 0;
267 uint32_t load_address, load_size;
268 unsigned long compressed_size, puffed_size;
271 bool modified =
false;
274 int fd = open(fname, O_RDONLY);
278 return BOOTLOADER_ERR_FILE_NOT_FOUND;
283 if (ret != BOOTLOADER_OK)
285 ret = BOOTLOADER_ERR_FILE_CORRUPT;
288 if (seg_hdr.
type != FIELD_TYPE_MAGIC)
290 ret = BOOTLOADER_ERR_INVALID_FILE;
293 if (seg_hdr.
len !=
sizeof(mbin_magic))
295 ret = BOOTLOADER_ERR_FILE_CORRUPT;
301 ret = BOOTLOADER_ERR_INVALID_FILE;
309 if (ret != BOOTLOADER_OK)
314 switch (seg_hdr.
type)
316 case FIELD_TYPE_SW_SEGMENT:
318 if (ret != BOOTLOADER_OK)
324 load_size = seg_hdr.
len -
sizeof(load_address);
328 ret = BOOTLOADER_ERR_FILE_CORRUPT;
333 if (ret != (
int)load_size)
336 ret = BOOTLOADER_ERR_FILE_CORRUPT;
351 ret = BOOTLOADER_ERR_PROGRAM_FAILED;
359 ret = BOOTLOADER_ERR_INVALID_FILE;
364 case FIELD_TYPE_SW_SEGMENT_DEFLATED:
366 if (ret != BOOTLOADER_OK)
373 if (ret != BOOTLOADER_OK)
382 ret = BOOTLOADER_ERR_FILE_CORRUPT;
386 compressed_size = seg_hdr.
len -
sizeof(load_address) -
sizeof(load_size);
390 ret = BOOTLOADER_ERR_FILE_CORRUPT;
395 if (ret != (
int)compressed_size)
398 ret = BOOTLOADER_ERR_FILE_CORRUPT;
403 puffed_size = load_size;
405 if (puffed_size != load_size)
408 ret = BOOTLOADER_ERR_FILE_DECOMPRESSION;
423 ret = BOOTLOADER_ERR_PROGRAM_FAILED;
431 ret = BOOTLOADER_ERR_INVALID_FILE;
436 case FIELD_TYPE_EOF_WITH_SIGNATURE:
445 case FIELD_TYPE_FW_SEGMENT:
446 case FIELD_TYPE_FW_SEGMENT_DEFLATED:
447 case FIELD_TYPE_FW_TLV_BCF_ADDR:
448 case FIELD_TYPE_BCF_BOARD_CONFIG:
449 case FIELD_TYPE_BCF_REGDOM:
453 ret = BOOTLOADER_ERR_FILE_CORRUPT;
458 if (ret != seg_hdr.
len)
461 ret = BOOTLOADER_ERR_FILE_CORRUPT;
466 case FIELD_TYPE_MAGIC:
469 ret = BOOTLOADER_ERR_FILE_CORRUPT;
477 ret = BOOTLOADER_ERR_FILE_CORRUPT;
485 ret = BOOTLOADER_ERR_INVALID_FILE;
510 if (
mmconfig_read_bytes(
"IMAGE_SIGNATURE", compare,
sizeof(compare), 0) !=
sizeof(compare))
513 return BOOTLOADER_ERR_SIGNATURE_NOT_FOUND;
517 int fd = open(fname, O_RDONLY);
521 return BOOTLOADER_ERR_FILE_NOT_FOUND;
527 bytesread = read(fd, data,
sizeof(data));
533 sha256_update(&ctx, data, bytesread);
534 }
while (bytesread ==
sizeof(data));
536 sha256_final(&ctx, hash);
539 if (memcmp(hash, compare,
sizeof(hash)) != 0)
542 return BOOTLOADER_ERR_FILE_VERIFICATION_FAILED;
544 return BOOTLOADER_OK;
552 static char update_path[128];
573 if (ret != BOOTLOADER_OK)
582 int update_attempts = 0;
596 if (ret != BOOTLOADER_OK)
601 if (ret != BOOTLOADER_OK)
634 uint32_t go_address = (*((
volatile uint32_t*) (((uint32_t)&
application_start) + 4)));
635 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.
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_set_error_led(bool state)
Set the error LED to the requested state.
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).