New feature: allow swapping from external memory (e.g. SPI flash)

pull/5/head
Daniele Lacamera 2019-02-14 15:08:36 +01:00
parent 07db864ab1
commit 503b008cf5
11 changed files with 466 additions and 149 deletions

View File

@ -69,16 +69,17 @@ ifeq ($(FASTMATH),1)
CFLAGS+=-DUSE_FAST_MATH
endif
ifeq ($(EXT_FLASH),1)
CFLAGS+=-DEXT_FLASH -DPART_UPDATE_EXT
endif
CFLAGS+=-mthumb -Wall -Wextra -Wno-main -Wstack-usage=1024 -ffreestanding -Wno-unused \
-Ilib/bootutil/include -Iinclude/ -Ilib/wolfssl -nostartfiles \
-DWOLFSSL_USER_SETTINGS \
-mthumb -mlittle-endian -mthumb-interwork \
-DPLATFORM_$(TARGET)
ifeq ($(EXT_FLASH),1)
CFLAGS+=-DEXT_FLASH=1 -DPART_UPDATE_EXT=1 -DPART_SWAP_EXT=1
endif
ifeq ($(SIGN),ED25519)
OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
./lib/wolfssl/wolfcrypt/src/ed25519.o \
@ -131,7 +132,7 @@ wolfboot-align.bin: wolfboot.elf
$(SIZE) wolfboot.elf
test-app/image.bin:
make -C test-app TARGET=$(TARGET)
make -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH)
tools/ed25519/ed25519_sign:
make -C tools/ed25519
@ -165,7 +166,7 @@ src/ecc256_pub_key.c: ecc256.der
keys: $(PRIVATE_KEY)
clean:
rm -f *.bin *.elf $(OBJS) wolfboot.map *.bin *.hex
rm -f *.bin *.elf $(OBJS) wolfboot.map *.bin *.hex hal/*.o
make -C test-app clean
distclean: clean

View File

@ -112,9 +112,9 @@
#define FLASH_SECTOR_5 0x0020000
#define FLASH_SECTOR_6 0x0040000
#define FLASH_SECTOR_7 0x0060000
#define FLASH_TOP 0x007FFFF
#define FLASH_TOP 0x0080000
const uint32_t flash_sector[8] = {
const uint32_t flash_sector[9] = {
FLASH_SECTOR_0,
FLASH_SECTOR_1,
FLASH_SECTOR_2,
@ -122,7 +122,8 @@ const uint32_t flash_sector[8] = {
FLASH_SECTOR_4,
FLASH_SECTOR_5,
FLASH_SECTOR_6,
FLASH_SECTOR_7
FLASH_SECTOR_7,
FLASH_TOP
};
static void flash_set_waitstates(int waitstates)
@ -194,17 +195,20 @@ void hal_flash_lock(void)
int hal_flash_erase(uint32_t address, int len)
{
int start = -1, end = -1;
uint32_t end_address = address + len;
uint32_t end_address;
int i;
if (len == 0)
return -1;
end_address = address + len - 1;
if (address < flash_sector[0] || end_address > FLASH_TOP)
return -1;
for (i = 0; i < 7; i++)
for (i = 0; i < 8; i++)
{
if ((address >= flash_sector[i]) && (address < flash_sector[i + 1])) {
start = i;
}
if ((end_address >= flash_sector[i]) && (address < flash_sector[i + 1])) {
if ((end_address >= flash_sector[i]) && (end_address < flash_sector[i + 1])) {
end = i;
}
if (start > 0 && end > 0)
@ -325,3 +329,78 @@ void hal_prepare_boot(void)
clock_pll_off();
}
#ifdef EXT_FLASH
#define SIM_ADDRESS (0x40000)
int ext_flash_read(uint32_t address, uint8_t *data, int len)
{
int i;
uint32_t val;
address += SIM_ADDRESS;
for (i = 0; i < len; i++)
data[i] = *((uint8_t *)(address + i));
return len;
}
int ext_flash_write(uint32_t address, const uint8_t *data, int len)
{
int i;
uint32_t val;
address += SIM_ADDRESS;
flash_wait_complete();
clear_errors();
/* Set 8-bit write */
FLASH_CR &= (~(0x03 << 8));
for (i = 0; i < len; i++) {
FLASH_CR |= FLASH_CR_PG;
*((uint8_t *)(address + i)) = data[i];
flash_wait_complete();
FLASH_CR &= ~FLASH_CR_PG;
}
return 0;
}
void ext_flash_unlock(void)
{
FLASH_CR |= FLASH_CR_LOCK;
FLASH_KEYR = FLASH_KEY1;
FLASH_KEYR = FLASH_KEY2;
}
void ext_flash_lock(void)
{
FLASH_CR |= FLASH_CR_LOCK;
}
int ext_flash_erase(uint32_t address, int len)
{
int start = -1, end = -1;
uint32_t end_address;
int i;
address += SIM_ADDRESS;
end_address = address + len - 1;
if (address < flash_sector[0] || end_address > FLASH_TOP)
return -1;
for (i = 0; i < 8; i++)
{
if ((address >= flash_sector[i]) && (address < flash_sector[i + 1])) {
start = i;
}
if ((end_address >= flash_sector[i]) && (end_address < flash_sector[i + 1])) {
end = i;
}
if (start > 0 && end > 0)
break;
}
if (start < 0 || end < 0)
return -1;
for (i = start; i <= end; i++)
flash_erase_sector(i);
return 0;
}
#endif

View File

@ -3,11 +3,21 @@
#include <inttypes.h>
#include "target.h"
void hal_init(void);
int hal_flash_write(uint32_t address, const uint8_t *data, int len);
int hal_flash_erase(uint32_t address, int len);
void hal_flash_unlock(void);
void hal_flash_lock(void);
void hal_prepare_boot(void);
#ifdef EXT_FLASH
/* external flash interface */
int ext_flash_write(uint32_t address, const uint8_t *data, int len);
int ext_flash_read(uint32_t address, uint8_t *data, int len);
int ext_flash_erase(uint32_t address, int len);
void ext_flash_lock(void);
void ext_flash_unlock(void);
#endif
#endif /* H_HAL_FLASH_ */

View File

@ -3,6 +3,7 @@
#include <stdint.h>
#include <target.h>
#include <wolfboot/wolfboot.h>
#include "image.h"
#define SECT_FLAG_NEW 0x0F
@ -11,32 +12,6 @@
#define SECT_FLAG_UPDATED 0x00
#ifdef EXT_FLASH
# ifndef PART_UPDATE_DRIVER
# define PART_UPDATE_DRIVER (&internal_flash_driver)
# endif
# define flash_lock(x) (x->flash_driver.lock())
# define flash_unlock(x) (x->flash_driver.unlock())
# define flash_erase(x, addr, len) (x->flash_driver.erase(addr, len)
# define flash_write(x, addr, data, len) (x->flash_driver.write(addr, data, len)
# define flash_read(x, addr, data, len) (x->flash_driver.read(addr, data, len)
#else
# define flash_lock(x) hal_flash_lock()
# define flash_unlock(x) hal_flash_unlock()
# define flash_erase(x, addr, len) (x->flash_driver.erase(addr, len)
# define flash_write(x, addr, data, len) (x->flash_driver.write(addr, data, len)
# define flash_read(x, addr, data, len) (memcpy(data, addr, len) - data + len)
#endif
struct wolfBoot_flash_driver {
int (*write)(uint32_t address, const uint8_t *data, int len);
int (*read)(uint32_t address, uint8_t *data, int len);
int (*erase)(uint32_t address, int len);
void (*lock)(void);
void (*unlock)(void);
};
extern const struct wolfBoot_flash_driver internal_flash_driver;
struct wolfBoot_image {
uint8_t *hdr;
@ -47,7 +22,6 @@ struct wolfBoot_image {
uint8_t *fw_base;
uint32_t fw_size;
uint8_t part;
struct wolfBoot_flash_driver *flash_driver;
};
@ -59,4 +33,64 @@ int wolfBoot_set_sector_flag(uint8_t part, uint8_t sector, uint8_t newflag);
int wolfBoot_get_partition_state(uint8_t part, uint8_t *st);
int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag);
#ifdef EXT_FLASH
# ifdef PART_UPDATE_EXT
# define UPDATE_EXT 1
# else
# define UPDATE_EXT 0
# endif
# ifdef PART_SWAP_EXT
# define SWAP_EXT 1
# else
# define SWAP_EXT 0
# endif
# define PART_IS_EXT(x) (((x)->part == PART_UPDATE)?UPDATE_EXT:(((x)->part == PART_SWAP)?SWAP_EXT:0))
#include "hal.h"
static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off, uint32_t size)
{
if (PART_IS_EXT(img))
return ext_flash_erase((uint32_t)(img->hdr) + off, size);
else
return hal_flash_erase((uint32_t)(img->hdr) + off, size);
}
static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off, const void *data, uint32_t size)
{
if (PART_IS_EXT(img))
return ext_flash_write((uint32_t)(img->hdr) + off, data, size);
else
return hal_flash_write((uint32_t)(img->hdr) + off, data, size);
}
static inline int wb_flash_write_verify_word(struct wolfBoot_image *img, uint32_t off, uint32_t word)
{
int ret;
volatile uint32_t copy;
if (PART_IS_EXT(img))
{
ext_flash_read((uint32_t)(img->hdr) + off, (void *)&copy, sizeof(uint32_t));
while (copy != word) {
ret = ext_flash_write((uint32_t)(img->hdr) + off, (void *)&word, sizeof(uint32_t));
if (ret < 0)
return ret;
ext_flash_read((uint32_t)(img->hdr) + off, (void *)&copy, sizeof(uint32_t));
}
} else {
volatile uint32_t *pcopy = (volatile uint32_t*)(img->hdr + off);
while(*pcopy != word) {
hal_flash_write((uint32_t)pcopy, (void *)&word, sizeof(uint32_t));
}
}
return 0;
}
#else
# define PART_IS_EXT(x) (0)
# define wb_flash_erase(im, of, siz) hal_flash_erase(((uint32_t)(((im)->hdr)) + of), siz)
# define wb_flash_write(im, of, dat, siz) hal_flash_write(((uint32_t)((im)->hdr)) + of, dat, siz)
# define wb_flash_write_verify_word(im, of, x) do { hal_flash_write(((uint32_t)((im)->hdr)) + of, (void *)&x, sizeof(uint32_t)); } while (*(uint32_t *)(((im)->hdr) + of) != x)
#endif /* EXT_FLASH */
#endif /* IMAGE_H */

View File

@ -10,7 +10,7 @@
#define WOLFBOOT_PARTITION_SIZE 0x20000
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x20000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x40000
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x60000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x0
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x20000
#endif

View File

@ -29,5 +29,8 @@
void wolfBoot_erase_partition(uint8_t part);
void wolfBoot_update_trigger(void);
void wolfBoot_success(void);
uint32_t wolfBoot_get_image_version(uint8_t part);
#define wolfBoot_current_firmware_version() wolfBoot_get_image_version(PART_BOOT)
#define wolfBoot_update_firmware_version() wolfBoot_get_image_version(PART_UPDATE)
#endif /* IMAGE_H */

View File

@ -26,6 +26,10 @@
#ifdef WOLFBOOT_SIGN_ED25519
#include <wolfssl/wolfcrypt/ed25519.h>
extern uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr);
static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
{
int ret, res;
@ -82,6 +86,7 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
}
#endif
#if 0
static uint8_t find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr)
{
uint8_t *p = haystack;
@ -101,6 +106,7 @@ static uint8_t find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr)
*ptr = NULL;
return 0;
}
#endif
@ -108,16 +114,13 @@ static uint8_t get_header_ext(struct wolfBoot_image *img, uint8_t type, uint8_t
static uint8_t get_header(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr)
{
#if defined(PART_UPDATE_EXT) && defined(EXT_FLASH)
#if defined(PART_UPDATE_EXT)
if(img->part == PART_UPDATE)
return get_header_ext(img, type, ptr);
#endif
return find_header(img->hdr + IMAGE_HEADER_OFFSET, type, ptr);
return wolfBoot_find_header(img->hdr + IMAGE_HEADER_OFFSET, type, ptr);
}
static uint8_t ext_hash_block[SHA256_BLOCK_SIZE];
static uint8_t *get_sha_block(struct wolfBoot_image *img, uint32_t offset)
@ -126,23 +129,55 @@ static uint8_t *get_sha_block(struct wolfBoot_image *img, uint32_t offset)
return NULL;
#ifdef PART_UPDATE_EXT
if (img->part == PART_UPDATE) {
ext_flash_read(img->fw_base + offset, ext_hash_block, SHA256_BLOCK_SIZE);
ext_flash_read((uint32_t)(img->fw_base) + offset, ext_hash_block, SHA256_BLOCK_SIZE);
return ext_hash_block;
}
#endif
return (uint8_t *)(img->fw_base + offset);
}
static uint8_t digest[SHA256_DIGEST_SIZE];
static uint8_t verification[IMAGE_SIGNATURE_SIZE];
#ifdef EXT_FLASH
static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
static int hdr_cpy_done = 0;
static uint8_t *fetch_hdr_cpy(struct wolfBoot_image *img)
{
if (!hdr_cpy_done) {
ext_flash_read((uint32_t)img->hdr, hdr_cpy, IMAGE_HEADER_SIZE);
hdr_cpy_done = 1;
}
return hdr_cpy;
}
static uint8_t get_header_ext(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr)
{
return wolfBoot_find_header(fetch_hdr_cpy(img) + IMAGE_HEADER_OFFSET, type, ptr);
}
#endif
static uint8_t *get_img_hdr(struct wolfBoot_image *img)
{
#ifdef PART_UPDATE_EXT
if (img->part == PART_UPDATE) {
return fetch_hdr_cpy(img);
}
#endif
return (uint8_t *)(img->hdr);
}
static int image_hash(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *stored_sha, *end_sha;
uint8_t stored_sha_len;
uint8_t *p = img->hdr;
uint8_t *fw_end = img->fw_base + img->fw_size;
uint8_t *p = get_img_hdr(img);
int blksz;
uint32_t position = 0;
wc_Sha256 sha256_ctx;
if (!img || !img->hdr)
if (!img)
return -1;
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
if (stored_sha_len != SHA256_DIGEST_SIZE)
@ -188,39 +223,8 @@ static void key_hash(uint8_t *hash)
wc_Sha256Final(&sha256_ctx, hash);
}
static uint8_t digest[SHA256_DIGEST_SIZE];
static uint8_t verification[IMAGE_SIGNATURE_SIZE];
#ifdef EXT_FLASH
static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
static int hdr_cpy_done = 0;
static uint8_t *fetch_hdr_cpy(struct wolfBoot_image *img)
{
if (!hdr_cpy_done) {
ext_flash_read(img->hdr, hdr_cpy, IMAGE_HEADER_SIZE);
hdr_cpy_done = 1;
}
return hdr_cpy;
}
static uint8_t get_header_ext(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr)
{
return find_header(fetch_hdr_cpy(img) + IMAGE_HEADER_OFFSET, type, ptr);
}
#endif
static uint8_t *get_img_hdr(struct wolfBoot_image *img)
{
#ifdef PART_UPDATE_EXT
if (img->part == PART_UPDATE) {
return fetch_hdr_cpy(img);
}
#endif
return (uint8_t *)(img->hdr);
}
int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
{
@ -230,12 +234,19 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
if (!img)
return -1;
memset(img, 0, sizeof(struct wolfBoot_image));
if (part == PART_SWAP) {
img->part = PART_SWAP;
img->hdr = (void *)WOLFBOOT_PARTITION_SWAP_ADDRESS;
img->fw_base = img->hdr;
img->fw_size = WOLFBOOT_SECTOR_SIZE;
return 0;
}
if (part == PART_BOOT) {
img->hdr = (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
image = (uint8_t *)img->hdr;
} else if (part == PART_UPDATE) {
img->hdr = (void *)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
#if defined(PART_UPDATE_EXT)
#ifdef PART_UPDATE_EXT
image = fetch_hdr_cpy(img);
#else
image = (uint8_t *)img->hdr;

View File

@ -23,83 +23,165 @@
#include <inttypes.h>
#include <wolfboot/wolfboot.h>
static uint8_t *get_trailer(uint8_t part)
#ifndef NULL
# define NULL (void *)0
#endif
uint32_t ext_cache;
#ifndef TRAILER_SKIP
# define TRAILER_SKIP 0
#endif
#define PART_BOOT_ENDFLAGS ((WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) - TRAILER_SKIP)
#define PART_UPDATE_ENDFLAGS ((WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE) - TRAILER_SKIP)
#if defined PART_UPDATE_EXT
static uint8_t *get_trailer_at(uint8_t part, uint32_t at)
{
if (part == PART_BOOT)
return (void *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE);
else if (part == PART_UPDATE)
return (void *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE);
else
return (void *)0;
return (void *)(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at));
else if (part == PART_UPDATE) {
ext_flash_read(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&ext_cache, sizeof(uint32_t));
return (uint8_t *)&ext_cache;
} else
return NULL;
}
static void set_trailer_at(uint8_t part, uint32_t at, uint8_t val)
{
if (part == PART_BOOT) {
hal_flash_write(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1);
}
else if (part == PART_UPDATE) {
ext_flash_write(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1);
}
}
static void set_partition_magic(uint8_t part)
{
uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
if (part == PART_BOOT) {
hal_flash_write(PART_BOOT_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t));
}
else if (part == PART_UPDATE) {
ext_flash_write(PART_UPDATE_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t));
}
}
#else
static uint8_t *get_trailer_at(uint8_t part, uint32_t at)
{
if (part == PART_BOOT)
return (void *)(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at));
else if (part == PART_UPDATE) {
return (void *)(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at));
} else
return NULL;
}
static void set_trailer_at(uint8_t part, uint32_t at, uint8_t val)
{
if (part == PART_BOOT) {
hal_flash_write(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1);
}
else if (part == PART_UPDATE) {
hal_flash_write(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1);
}
}
static void set_partition_magic(uint8_t part)
{
uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
if (part == PART_BOOT) {
hal_flash_write(PART_BOOT_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t));
}
else if (part == PART_UPDATE) {
hal_flash_write(PART_UPDATE_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t));
}
}
#endif /* PART_UPDATE_EXT */
static uint32_t *get_partition_magic(uint8_t part)
{
return (uint32_t *)get_trailer_at(part, 0);
}
static uint8_t *get_partition_state(uint8_t part)
{
return (uint8_t *)get_trailer_at(part, 1);
}
static uint8_t *get_sector_flags(uint8_t part, uint32_t pos)
{
return (uint8_t *)get_trailer_at(part, 2 + pos);
}
static void set_partition_state(uint8_t part, uint8_t val)
{
set_trailer_at(part, 1, val);
}
static void set_sector_flags(uint8_t part, uint32_t pos, uint8_t val)
{
set_trailer_at(part, 2 + pos, val);
}
int wolfBoot_set_partition_state(uint8_t part, uint8_t newst)
{
uint8_t *trailer_end = get_trailer(part);
uint32_t *magic;
uint8_t *state;
uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
if (!trailer_end)
return -1;
magic = (uint32_t *)(trailer_end - sizeof(uint32_t));
magic = get_partition_magic(part);
if (*magic != WOLFBOOT_MAGIC_TRAIL)
hal_flash_write((uint32_t)magic, (void *)&wolfboot_magic_trail, sizeof(uint32_t));
state = (trailer_end - sizeof(uint32_t)) - 1;
set_partition_magic(part);
state = get_partition_state(part);
if (*state != newst)
hal_flash_write((uint32_t)state, (void *)&newst, 1);
set_partition_state(part, newst);
return 0;
}
int wolfBoot_set_sector_flag(uint8_t part, uint8_t sector, uint8_t newflag)
{
uint8_t *trailer_end = get_trailer(part);
uint32_t *magic;
uint8_t *flags;
uint8_t fl_value;
uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
uint8_t pos = sector >> 1;
if (!trailer_end)
return -1;
magic = (uint32_t *)(trailer_end - sizeof(uint32_t));
magic = get_partition_magic(part);
if (*magic != WOLFBOOT_MAGIC_TRAIL)
hal_flash_write((uint32_t)magic, (void *)&wolfboot_magic_trail, sizeof(uint32_t));
flags = (trailer_end - sizeof(uint32_t)) - (2 + pos);
set_partition_magic(part);
flags = get_sector_flags(part, pos);
if (sector == (pos << 1))
fl_value = (*flags & 0xF0) | (newflag & 0x0F);
else
fl_value = ((newflag & 0x0F) << 4) | (*flags & 0x0F);
if (fl_value != *flags)
hal_flash_write((uint32_t)flags, &fl_value, 1);
set_sector_flags(part, pos, fl_value);
return 0;
}
int wolfBoot_get_partition_state(uint8_t part, uint8_t *st)
{
uint8_t *trailer_end = get_trailer(part);
uint32_t *magic;
uint8_t *state;
if (!trailer_end)
return -1;
magic = (uint32_t *)(trailer_end - sizeof(uint32_t));
magic = get_partition_magic(part);
if (*magic != WOLFBOOT_MAGIC_TRAIL)
return -1;
state = (trailer_end - sizeof(uint32_t)) - 1;
state = get_partition_state(part);
*st = *state;
return 0;
}
int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag)
{
uint8_t *trailer_end = get_trailer(part);
uint32_t *magic;
uint8_t *flags;
uint8_t pos = sector >> 1;
if (!trailer_end)
return -1;
magic = (uint32_t *)(trailer_end - sizeof(uint32_t));
magic = get_partition_magic(part);
if (*magic != WOLFBOOT_MAGIC_TRAIL)
return -1;
flags = (trailer_end - sizeof(uint32_t)) - (2 + pos);
flags = get_sector_flags(part, pos);
if (sector == (pos << 1))
*flag = *flags & 0x0F;
else
@ -111,8 +193,15 @@ void wolfBoot_erase_partition(uint8_t part)
{
if (part == PART_BOOT)
hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS, WOLFBOOT_PARTITION_SIZE);
if (part == PART_UPDATE)
if (part == PART_UPDATE) {
#ifdef PART_UPDATE_EXT
ext_flash_unlock();
ext_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_PARTITION_SIZE);
ext_flash_lock();
#else
hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_PARTITION_SIZE);
#endif
}
if (part == PART_SWAP)
hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE);
}
@ -120,9 +209,15 @@ void wolfBoot_erase_partition(uint8_t part)
void wolfBoot_update_trigger(void)
{
uint8_t st = IMG_STATE_UPDATING;
#ifdef PART_UPDATE_EXT
ext_flash_unlock();
wolfBoot_set_partition_state(PART_UPDATE, st);
ext_flash_lock();
#else
hal_flash_unlock();
wolfBoot_set_partition_state(PART_UPDATE, st);
hal_flash_lock();
#endif
}
void wolfBoot_success(void)
@ -132,3 +227,59 @@ void wolfBoot_success(void)
wolfBoot_set_partition_state(PART_BOOT, st);
hal_flash_lock();
}
uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr)
{
uint8_t *p = haystack;
while (*p != 0) {
if (*p == HDR_PADDING) {
p++;
continue;
}
if (*p == type) {
p++;
*ptr = (p + 1);
return *p;
}
p++;
p += (*p + 1);
}
*ptr = NULL;
return 0;
}
#ifdef EXT_FLASH
static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
static uint32_t hdr_cpy_done = 0;
#endif
uint32_t wolfBoot_get_image_version(uint8_t part)
{
uint32_t *version_field = NULL;
uint32_t version = 0;
uint8_t *image = NULL;
uint32_t *magic = NULL;
if(part == PART_UPDATE) {
#ifdef PART_UPDATE_EXT
ext_flash_read((uint32_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS, hdr_cpy, IMAGE_HEADER_SIZE);
hdr_cpy_done = 1;
image = hdr_cpy;
#else
image = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
#endif
}
if (part == PART_BOOT)
image = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
if (image) {
magic = (uint32_t *)image;
if (*magic != WOLFBOOT_MAGIC)
return 0;
wolfBoot_find_header(image + IMAGE_HEADER_OFFSET, HDR_VERSION, (void *)&version_field);
if (version_field)
return *version_field;
}
return 0;
}

View File

@ -24,19 +24,35 @@
extern void do_boot(const uint32_t *app_offset);
static int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size)
static int wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector)
{
uint32_t *orig, *copy;
volatile uint32_t *orig, *copy;
uint32_t pos = 0;
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
uint32_t dst_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
if (src == dst)
return 0;
if ((src & 0x03) || (dst & 0x03))
return -1;
while (pos < size) {
orig = (uint32_t *)(src + pos);
copy = (uint32_t *)(dst + pos);
while (*orig != *copy)
hal_flash_write(dst + pos, (void *)orig, sizeof(uint32_t));
if (src->part == PART_SWAP)
src_sector_offset = 0;
if (dst->part == PART_SWAP)
dst_sector_offset = 0;
#ifdef EXT_FLASH
if (PART_IS_EXT(src)) {
uint32_t word;
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
while (pos < WOLFBOOT_SECTOR_SIZE) {
ext_flash_read((uint32_t)(src->hdr) + src_sector_offset + pos, (void *)&word, sizeof(uint32_t));
wb_flash_write_verify_word(dst, dst_sector_offset + pos, word);
pos += sizeof(uint32_t);
}
return pos;
}
#endif
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
while (pos < WOLFBOOT_SECTOR_SIZE) {
orig = (volatile uint32_t *)(src->hdr + src_sector_offset + pos);
wb_flash_write_verify_word(dst, dst_sector_offset + pos, *orig);
pos += sizeof(uint32_t);
}
return pos;
@ -45,16 +61,20 @@ static int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size)
static int wolfBoot_update(void)
{
uint32_t total_size = 0;
uint32_t sector_size = WOLFBOOT_SECTOR_SIZE;
const uint32_t sector_size = WOLFBOOT_SECTOR_SIZE;
uint32_t sector = 0;
uint8_t flag, st;
struct wolfBoot_image boot, update;
struct wolfBoot_image boot, update, swap;
/* No Safety check on open: we might be in the middle of a broken update */
wolfBoot_open_image(&update, PART_UPDATE);
wolfBoot_open_image(&boot, PART_BOOT);
wolfBoot_open_image(&swap, PART_SWAP);
/* Use biggest size for the swap */
if ((wolfBoot_open_image(&update, PART_UPDATE) == 0) && (update.fw_size + IMAGE_HEADER_SIZE) > total_size)
total_size = boot.fw_size + IMAGE_HEADER_SIZE;
if ((update.fw_size + IMAGE_HEADER_SIZE) > total_size)
total_size = update.fw_size + IMAGE_HEADER_SIZE;
if ((wolfBoot_open_image(&boot, PART_BOOT) == 0) && (boot.fw_size + IMAGE_HEADER_SIZE) > total_size)
total_size = boot.fw_size + IMAGE_HEADER_SIZE;
if (total_size < IMAGE_HEADER_SIZE)
return -1;
@ -73,6 +93,9 @@ static int wolfBoot_update(void)
}
hal_flash_unlock();
#ifdef EXT_FLASH
ext_flash_unlock();
#endif
/* Interruptible swap
* The status is saved in the sector flags of the update partition.
@ -81,10 +104,7 @@ static int wolfBoot_update(void)
while ((sector * sector_size) < total_size) {
if ((wolfBoot_get_sector_flag(PART_UPDATE, sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
flag = SECT_FLAG_SWAPPING;
hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE);
wolfBoot_copy(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size,
WOLFBOOT_PARTITION_SWAP_ADDRESS,
WOLFBOOT_SECTOR_SIZE);
wolfBoot_copy_sector(&update, &swap, sector);
wolfBoot_set_sector_flag(PART_UPDATE, sector, flag);
}
if (flag == SECT_FLAG_SWAPPING) {
@ -92,11 +112,7 @@ static int wolfBoot_update(void)
if (size > sector_size)
size = sector_size;
flag = SECT_FLAG_BACKUP;
hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size,
WOLFBOOT_SECTOR_SIZE);
wolfBoot_copy(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size,
WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size,
WOLFBOOT_SECTOR_SIZE);
wolfBoot_copy_sector(&boot, &update, sector);
wolfBoot_set_sector_flag(PART_UPDATE, sector, flag);
}
if (flag == SECT_FLAG_BACKUP) {
@ -104,25 +120,22 @@ static int wolfBoot_update(void)
if (size > sector_size)
size = sector_size;
flag = SECT_FLAG_UPDATED;
hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size,
sector_size);
wolfBoot_copy(WOLFBOOT_PARTITION_SWAP_ADDRESS,
WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size,
size);
wolfBoot_copy_sector(&swap, &boot, sector);
wolfBoot_set_sector_flag(PART_UPDATE, sector, flag);
}
sector++;
}
while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) {
hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + sector * sector_size,
sector_size);
hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS + sector * sector_size,
sector_size);
wb_flash_erase(&boot, sector * sector_size, sector_size);
wb_flash_erase(&update, sector * sector_size, sector_size);
sector++;
}
hal_flash_erase(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE);
wb_flash_erase(&swap, 0, WOLFBOOT_SECTOR_SIZE);
st = IMG_STATE_TESTING;
wolfBoot_set_partition_state(PART_BOOT, st);
#ifdef EXT_FLASH
ext_flash_lock();
#endif
hal_flash_lock();
return 0;
}

View File

@ -1,13 +1,17 @@
CROSS_COMPILE:=arm-none-eabi-
CC:=$(CROSS_COMPILE)gcc
LD:=$(CROSS_COMPILE)gcc
OBJS:=startup.o main.o timer.o led.o system.o
OBJS:=startup.o main.o timer.o led.o system.o ../src/libwolfboot.o ../hal/$(TARGET).o
TARGET?=none
LSCRIPT:=app.ld
OBJCOPY:=$(CROSS_COMPILE)objcopy
CFLAGS:=-mcpu=cortex-m3 -mthumb -g -ggdb -Wall -Wno-main -Wstack-usage=200 -ffreestanding -Wno-unused -nostdlib -DPLATFORM_$(TARGET)
CFLAGS:=-mcpu=cortex-m3 -mthumb -g -ggdb -Wall -Wno-main -Wstack-usage=200 -ffreestanding -Wno-unused -nostdlib -DPLATFORM_$(TARGET) -I../include
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -nostdlib
ifeq ($(EXT_FLASH),1)
CFLAGS+=-DEXT_FLASH=1 -DPART_UPDATE_EXT=1
endif
image.bin: image.elf
$(OBJCOPY) -O binary $^ $@

View File

@ -26,10 +26,12 @@
#include "system.h"
#include "timer.h"
#include "led.h"
#include "wolfboot/wolfboot.h"
#ifdef PLATFORM_stm32f4
void main(void) {
uint32_t version;
boot_led_on();
flash_set_waitstates();
clock_config();
@ -43,6 +45,15 @@ void main(void) {
* effect.
*/
timer_init(CPU_FREQ, 1, 50);
version = wolfBoot_current_firmware_version();
if (version & 0x01) {
/* Odd version: unstable, trigger update */
if (wolfBoot_update_firmware_version() != 0)
wolfBoot_update_trigger();
} else {
/* Even version, stabilise */
wolfBoot_success();
}
asm volatile ("cpsie i");
while(1)
WFI();