Skip to content

Commit fc547e4

Browse files
committed
wolfBoot can update itself when compiled with RAM_CODE=1
- Added wolfBoot version - Added extra 16bit header tag to identify the image type and authentication - Implemented optional in-ram self-update of the bootloader, with version control and authentication mechanism (not fail-safe)
1 parent 937e9d4 commit fc547e4

11 files changed

Lines changed: 249 additions & 29 deletions

File tree

Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ EXT_FLASH?=0
2121
SPI_FLASH?=0
2222
ALLOW_DOWNGRADE?=0
2323
NVM_FLASH_WRITEONCE?=0
24+
WOLFBOOT_VERSION?=0
2425
V?=0
2526
SPMATH?=1
2627
RAM_CODE?=0
2728

2829

2930

3031
## Initializers
31-
CFLAGS:=-D__WOLFBOOT
32+
CFLAGS:=-D__WOLFBOOT -DWOLFBOOT_VERSION=$(WOLFBOOT_VERSION)UL
3233
LSCRIPT:=hal/$(TARGET).ld
3334
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles
3435
OBJS:= \
@@ -147,7 +148,8 @@ wolfboot-align.bin: wolfboot.bin
147148
@echo
148149

149150
test-app/image.bin:
150-
@make -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH) SPI_FLASH=$(SPI_FLASH) ARCH=$(ARCH) V=$(V) \
151+
@make -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH) SPI_FLASH=$(SPI_FLASH) ARCH=$(ARCH) \
152+
V=$(V) RAM_CODE=$(RAM_CODE) WOLFBOOT_VERSION=$(WOLFBOOT_VERSION)\
151153
KINETIS=$(KINETIS) KINETIS_CPU=$(KINETIS_CPU) KINETIS_DRIVERS=$(KINETIS_DRIVERS) \
152154
KINETIS_CMSIS=$(KINETIS_CMSIS) NVM_FLASH_WRITEONCE=$(NVM_FLASH_WRITEONCE) \
153155
FREEDOM_E_SDK=$(FREEDOM_E_SDK)

hal/hifive1.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ SECTIONS
1919
KEEP(*(.isr_vector))
2020
*(.text*)
2121
*(.rodata*)
22+
*(.srodata*)
2223
. = ALIGN(4);
2324
_end_text = .;
2425
} > FLASH

include/hal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
#include <inttypes.h>
66
#include "target.h"
7+
8+
/* Architecture specific calls */
9+
extern void do_boot(const uint32_t *app_offset);
10+
extern void arch_reboot(void);
11+
12+
13+
714
void hal_init(void);
815
int hal_flash_write(uint32_t address, const uint8_t *data, int len);
916
int hal_flash_erase(uint32_t address, int len);

include/image.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ int wolfBoot_set_sector_flag(uint8_t part, uint8_t sector, uint8_t newflag);
4141
int wolfBoot_get_partition_state(uint8_t part, uint8_t *st);
4242
int wolfBoot_get_sector_flag(uint8_t part, uint8_t sector, uint8_t *flag);
4343

44+
/* Defined in libwolfboot */
45+
uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr);
46+
4447
#ifdef EXT_FLASH
4548
# ifdef PART_UPDATE_EXT
4649
# define UPDATE_EXT 1

include/wolfboot/wolfboot.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,27 @@
1313
#define HDR_VERSION 0x01
1414
#define HDR_TIMESTAMP 0x02
1515
#define HDR_SHA256 0x03
16+
#define HDR_IMG_TYPE 0x04
1617
#define HDR_PUBKEY 0x10
1718
#define HDR_SIGNATURE 0x20
1819
#define HDR_PADDING 0xFF
1920

21+
#define HDR_IMG_TYPE_AUTH_ED25519 0x0100
22+
#define HDR_IMG_TYPE_AUTH_ECC256 0x0200
23+
#define HDR_IMG_TYPE_WOLFBOOT 0x0000
24+
#define HDR_IMG_TYPE_APP 0x0001
25+
26+
27+
#ifdef __WOLFBOOT
28+
#if defined(WOLFBOOT_SIGN_ED25519)
29+
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ED25519
30+
#elif defined(WOLFBOOT_SIGN_ECC256)
31+
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC256
32+
#else
33+
# error "no valid authentication mechanism selected. Please define WOLFBOOT_SIGN_ED25519 or WOLFBOOT_SIGN_ECC256"
34+
#endif /* defined WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ED25519 */
35+
#endif /* defined WOLFBOOT */
36+
2037
#define PART_BOOT 0
2138
#define PART_UPDATE 1
2239
#define PART_SWAP 2
@@ -26,6 +43,8 @@
2643
#define IMG_STATE_TESTING 0x10
2744
#define IMG_STATE_SUCCESS 0x00
2845

46+
47+
2948
void wolfBoot_erase_partition(uint8_t part);
3049
void wolfBoot_update_trigger(void);
3150
void wolfBoot_success(void);

src/boot_arm.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* boot_arm.c
1+
/* boot_arm.c
22
*
33
* Copyright (C) 2018 wolfSSL Inc.
44
*
@@ -18,9 +18,10 @@
1818
* along with this program; if not, write to the Free Software
1919
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
2020
*/
21-
#include <loader.h>
21+
#include "image.h"
22+
#include "loader.h"
2223
#include <stdint.h>
23-
#include <wolfboot/wolfboot.h>
24+
#include "wolfboot/wolfboot.h"
2425
extern unsigned int _stored_data;
2526
extern unsigned int _start_data;
2627
extern unsigned int _end_data;
@@ -33,7 +34,7 @@ extern void main(void);
3334

3435
void isr_reset(void) {
3536
register unsigned int *src, *dst;
36-
#ifdef PLATFORM_kinetis
37+
#ifdef PLATFORM_kinetis
3738
/* Immediately disable Watchdog after boot */
3839
/* Write Keys to unlock register */
3940
*((volatile unsigned short *)0x4005200E) = 0xC520;
@@ -86,6 +87,7 @@ void isr_empty(void)
8687
static void *app_entry;
8788
static uint32_t app_end_stack;
8889

90+
8991
void do_boot(const uint32_t *app_offset)
9092
{
9193

@@ -171,3 +173,18 @@ void (* const IV[])(void) =
171173
isr_empty,
172174
isr_empty,
173175
};
176+
177+
#ifdef RAM_CODE
178+
179+
#define AIRCR *(volatile uint32_t *)(0xE000ED0C)
180+
#define AIRCR_VKEY (0x05FA << 16)
181+
# define AIRCR_SYSRESETREQ (1 << 2)
182+
183+
void RAMFUNCTION arch_reboot(void)
184+
{
185+
AIRCR = AIRCR_SYSRESETREQ | AIRCR_VKEY;
186+
while(1)
187+
;
188+
189+
}
190+
#endif

src/boot_riscv.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121

2222
#include <stdint.h>
23+
#include "image.h"
2324

2425
extern void trap_entry(void);
2526
extern void trap_exit(void);
@@ -36,6 +37,12 @@ extern uint32_t _global_pointer;
3637
extern void (* const IV[])(void);
3738

3839
extern void main(void);
40+
void RAMFUNCTION reloc_iv(uint32_t *address)
41+
{
42+
asm volatile("csrw mtvec, %0":: "r"(address + 1));
43+
}
44+
45+
3946
void __attribute__((naked,section(".init"))) _reset(void) {
4047
register uint32_t *src, *dst;
4148
asm volatile("la gp, _global_pointer");
@@ -83,4 +90,31 @@ void isr_empty(void)
8390

8491
}
8592

93+
#ifdef RAM_CODE
94+
95+
#define AON_WDOGCFG *(volatile uint32_t *)(0x10000000UL)
96+
#define AON_WDOGKEY *(volatile uint32_t *)(0x1000001CUL)
97+
#define AON_WDOGFEED *(volatile uint32_t *)(0x10000018UL)
98+
#define AON_WDOGCMP *(volatile uint32_t *)(0x10000020UL)
99+
100+
#define AON_WDOGKEY_VALUE 0x0051F15E
101+
#define AON_WDOGCFG_SCALE 0x0000000F
102+
#define AON_WDOGCFG_RSTEN 0x00000100
103+
#define AON_WDOGCFG_ZEROCMP 0x00000200
104+
#define AON_WDOGCFG_ENALWAYS 0x00001000
105+
106+
107+
void RAMFUNCTION arch_reboot(void)
108+
{
109+
AON_WDOGKEY = AON_WDOGKEY_VALUE;
110+
AON_WDOGCMP = 0;
111+
//wdogconfig: : wdogrsten | enablealways | reset to 0 | max scale
112+
AON_WDOGKEY = AON_WDOGKEY_VALUE;
113+
AON_WDOGCFG |= (AON_WDOGCFG_RSTEN | AON_WDOGCFG_ENALWAYS | AON_WDOGCFG_ZEROCMP | AON_WDOGCFG_SCALE) ;
114+
AON_WDOGKEY = AON_WDOGKEY_VALUE;
115+
AON_WDOGFEED = 1;
116+
while(1)
117+
;
118+
}
119+
#endif
86120

src/image.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,16 @@
1818
* along with this program; if not, write to the Free Software
1919
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
2020
*/
21-
#include <image.h>
22-
#include <hal.h>
21+
#include "loader.h"
22+
#include "image.h"
23+
#include "hal.h"
2324
#include <wolfssl/wolfcrypt/sha256.h>
2425
#include <wolfssl/ssl.h>
25-
#include <loader.h>
2626

2727
#ifdef WOLFBOOT_SIGN_ED25519
2828
#include <wolfssl/wolfcrypt/ed25519.h>
2929

3030

31-
extern uint8_t wolfBoot_find_header(uint8_t *haystack, uint8_t type, uint8_t **ptr);
32-
3331
static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
3432
{
3533
int ret, res;
@@ -266,6 +264,9 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
266264
uint8_t stored_signature_size;
267265
uint8_t *pubkey_hint;
268266
uint8_t pubkey_hint_size;
267+
uint8_t *image_type_buf;
268+
uint16_t image_type;
269+
uint8_t image_type_size;
269270

270271
stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature);
271272
if (stored_signature_size != IMAGE_SIGNATURE_SIZE)
@@ -276,6 +277,15 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
276277
if (memcmp(digest, pubkey_hint, SHA256_DIGEST_SIZE) != 0)
277278
return -1;
278279
}
280+
image_type_size = get_header(img, HDR_IMG_TYPE, &image_type_buf);
281+
if (image_type_size != sizeof(uint16_t))
282+
return -1;
283+
image_type = (uint16_t)(image_type_buf[0] + (image_type_buf[1] << 8));
284+
285+
if ((image_type & 0xFF00) != HDR_IMG_TYPE_AUTH)
286+
return -1;
287+
288+
279289
if (image_hash(img, digest) != 0)
280290
return -1;
281291
if (wolfBoot_verify_signature(digest, stored_signature) != 0)

src/loader.c

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@
2222
#include "image.h"
2323
#include "hal.h"
2424
#include "spi_flash.h"
25+
#include "wolfboot/wolfboot.h"
2526

26-
extern void do_boot(const uint32_t *app_offset);
27+
#ifdef RAM_CODE
28+
extern unsigned int _start_text;
29+
static volatile const uint32_t wolfboot_version = WOLFBOOT_VERSION;
30+
extern void (** const IV_RAM)(void);
31+
#endif
2732

2833
#define FLASHBUFFER_SIZE 256
2934
static int wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector)
@@ -87,10 +92,16 @@ static int wolfBoot_update(int fallback_allowed)
8792
/* Check the first sector to detect interrupted update */
8893
if ((wolfBoot_get_sector_flag(PART_UPDATE, 0, &flag) < 0) || (flag == SECT_FLAG_NEW))
8994
{
95+
uint8_t *update_type;
9096
/* In case this is a new update, do the required
9197
* checks on the firmware update
9298
* before starting the swap
9399
*/
100+
101+
if (wolfBoot_find_header(update.hdr + IMAGE_HEADER_OFFSET, HDR_IMG_TYPE, &update_type) == sizeof(uint16_t)) {
102+
if ((update_type[0] != HDR_IMG_TYPE_APP) || update_type[1] != (HDR_IMG_TYPE_AUTH >> 8))
103+
return -1;
104+
}
94105
if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0)
95106
|| (wolfBoot_verify_authenticity(&update) < 0)) {
96107
return -1;
@@ -153,11 +164,89 @@ static int wolfBoot_update(int fallback_allowed)
153164
return 0;
154165
}
155166

167+
168+
#ifdef RAM_CODE
169+
170+
static void RAMFUNCTION wolfBoot_erase_bootloader(void)
171+
{
172+
uint32_t *start = (uint32_t *)&_start_text;
173+
uint32_t len = WOLFBOOT_PARTITION_BOOT_ADDRESS - (uint32_t)start;
174+
hal_flash_erase((uint32_t)start, len);
175+
176+
}
177+
178+
static void RAMFUNCTION wolfBoot_self_update(struct wolfBoot_image *src)
179+
{
180+
uint32_t pos = 0;
181+
uint32_t src_offset = IMAGE_HEADER_SIZE;
182+
183+
hal_flash_unlock();
184+
wolfBoot_erase_bootloader();
185+
#ifdef EXT_FLASH
186+
while (pos < src->fw_size) {
187+
if (PART_IS_EXT(src)) {
188+
uint8_t buffer[FLASHBUFFER_SIZE];
189+
if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
190+
ext_flash_read((uint32_t)(src->hdr) + src_offset + pos, (void *)buffer, FLASHBUFFER_SIZE);
191+
hal_flash_write(pos + (uint32_t)&_start_text, buffer, FLASHBUFFER_SIZE);
192+
}
193+
pos += FLASHBUFFER_SIZE;
194+
}
195+
goto lock_and_reset;
196+
}
197+
#endif
198+
while (pos < src->fw_size) {
199+
if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
200+
uint8_t *orig = (uint8_t*)(src->hdr + src_offset + pos);
201+
hal_flash_write(pos + (uint32_t)&_start_text, orig, FLASHBUFFER_SIZE);
202+
}
203+
pos += FLASHBUFFER_SIZE;
204+
}
205+
206+
lock_and_reset:
207+
hal_flash_lock();
208+
arch_reboot();
209+
}
210+
211+
static void wolfBoot_check_self_update(void)
212+
{
213+
uint8_t st;
214+
struct wolfBoot_image update;
215+
uint8_t *update_type;
216+
uint32_t update_version;
217+
218+
/* Check for self update in the UPDATE partition */
219+
if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING) &&
220+
(wolfBoot_open_image(&update, PART_UPDATE) == 0) &&
221+
(wolfBoot_find_header(update.hdr + IMAGE_HEADER_OFFSET, HDR_IMG_TYPE, &update_type) == sizeof(uint16_t)) &&
222+
update_type[0] == HDR_IMG_TYPE_WOLFBOOT &&
223+
update_type[1] == (HDR_IMG_TYPE_AUTH >> 8)) {
224+
uint32_t update_version = wolfBoot_update_firmware_version();
225+
if (update_version <= wolfboot_version) {
226+
hal_flash_unlock();
227+
wolfBoot_erase_partition(PART_UPDATE);
228+
hal_flash_lock();
229+
return;
230+
}
231+
if (wolfBoot_verify_integrity(&update) < 0)
232+
return;
233+
if (wolfBoot_verify_authenticity(&update) < 0)
234+
return;
235+
wolfBoot_self_update(&update);
236+
}
237+
}
238+
#endif /* RAM_CODE for self_update */
239+
156240
static void wolfBoot_start(void)
157241
{
158242
uint8_t st;
159243
struct wolfBoot_image boot, update;
160-
/* First, check if the BOOT partition is still in TESTING,
244+
245+
#ifdef RAM_CODE
246+
wolfBoot_check_self_update();
247+
#endif
248+
249+
/* Check if the BOOT partition is still in TESTING,
161250
* to trigger fallback.
162251
*/
163252
if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) {

0 commit comments

Comments
 (0)