Skip to content

Commit b9dc7ee

Browse files
authored
Merge pull request #463 from jpbland1/bad-image-recovery
add emergency fallback test, currently fails due to
2 parents eedd86f + 6c3940f commit b9dc7ee

File tree

10 files changed

+362
-151
lines changed

10 files changed

+362
-151
lines changed

.github/workflows/test-powerfail-simulator.yml

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ jobs:
5151
run: |
5252
tools/scripts/sim-update-powerfail-resume.sh
5353
54+
- name: Rebuild wolfboot.elf
55+
run: |
56+
make clean && make test-sim-internal-flash-with-update
57+
58+
- name: Run emergency fallback test
59+
run: |
60+
tools/scripts/sim-update-emergency-fallback.sh
61+
5462
5563
# TEST with NVM_WRITEONCE enabled
5664
- name: make clean
@@ -89,6 +97,14 @@ jobs:
8997
run: |
9098
tools/scripts/sim-update-powerfail-resume.sh
9199
100+
- name: Rebuild wolfboot.elf
101+
run: |
102+
make clean && make test-sim-internal-flash-with-update
103+
104+
- name: Run emergency fallback test
105+
run: |
106+
tools/scripts/sim-update-emergency-fallback.sh
107+
92108
93109
# TEST with NVM_WRITEONCE AND FLAGS_HOME enabled
94110
- name: make clean
@@ -127,6 +143,14 @@ jobs:
127143
run: |
128144
tools/scripts/sim-update-powerfail-resume.sh
129145
146+
- name: Rebuild wolfboot.elf
147+
run: |
148+
make clean && make test-sim-internal-flash-with-update
149+
150+
- name: Run emergency fallback test
151+
run: |
152+
tools/scripts/sim-update-emergency-fallback.sh
153+
130154
131155
# TEST with NVM_WRITEONCE AND FLAGS_HOME AND FLAGS_INVERT enabled
132156
- name: make clean
@@ -165,6 +189,14 @@ jobs:
165189
run: |
166190
tools/scripts/sim-update-powerfail-resume.sh
167191
192+
- name: Rebuild wolfboot.elf
193+
run: |
194+
make clean && make test-sim-external-flash-with-update
195+
196+
- name: Run emergency fallback test
197+
run: |
198+
tools/scripts/sim-update-emergency-fallback.sh
199+
168200
169201
# TEST with DELTA updates
170202
- name: make clean
@@ -189,15 +221,15 @@ jobs:
189221
190222
- name: Rebuild wolfboot.elf
191223
run: |
192-
make test-sim-internal-flash-with-delta-update
224+
make clean && make test-sim-internal-flash-with-delta-update
193225
194226
- name: Run update-revert test (DELTA)
195227
run: |
196228
tools/scripts/sim-update-fallback.sh
197229
198230
- name: Rebuild wolfboot.elf
199231
run: |
200-
make test-sim-internal-flash-with-delta-update
232+
make clean && make test-sim-internal-flash-with-delta-update
201233
202234
- name: Run update-revert test with power failures (DELTA)
203235
run: |
@@ -248,6 +280,14 @@ jobs:
248280
run: |
249281
tools/scripts/sim-update-powerfail-resume.sh
250282
283+
- name: Rebuild wolfboot.elf
284+
run: |
285+
make clean && make test-sim-external-flash-with-enc-update
286+
287+
- name: Run emergency fallback test
288+
run: |
289+
tools/scripts/sim-update-emergency-fallback.sh
290+
251291
# TEST with encryption (aes128) and delta updates
252292
- name: make clean
253293
run: |
@@ -322,6 +362,14 @@ jobs:
322362
run: |
323363
tools/scripts/sim-update-powerfail-resume.sh
324364
365+
- name: Rebuild wolfboot.elf
366+
run: |
367+
make clean && make test-sim-external-flash-with-enc-update
368+
369+
- name: Run emergency fallback test
370+
run: |
371+
tools/scripts/sim-update-emergency-fallback.sh
372+
325373
# TEST with encryption (aes128) and NVM_WRITEONCE and FLAGS_HOME
326374

327375
- name: make clean
@@ -355,6 +403,14 @@ jobs:
355403
run: |
356404
tools/scripts/sim-update-powerfail-resume.sh
357405
406+
- name: Rebuild wolfboot.elf
407+
run: |
408+
make clean && make test-sim-external-flash-with-enc-update
409+
410+
- name: Run emergency fallback test
411+
run: |
412+
tools/scripts/sim-update-emergency-fallback.sh
413+
358414
# TEST with encryption (aes128) and NVM_WRITEONCE and FLAGS_HOME and FLAGS_INVERT
359415

360416
- name: make clean
@@ -388,6 +444,14 @@ jobs:
388444
run: |
389445
tools/scripts/sim-update-powerfail-resume.sh
390446
447+
- name: Rebuild wolfboot.elf
448+
run: |
449+
make clean && make test-sim-external-flash-with-enc-update
450+
451+
- name: Run emergency fallback test
452+
run: |
453+
tools/scripts/sim-update-emergency-fallback.sh
454+
391455
# TEST with encryption (aes128) and NVM_WRITEONCE and DELTA updates
392456
- name: make clean
393457
run: |
@@ -451,6 +515,7 @@ jobs:
451515
- name: Run update test with DISABLE_BACKUP and powefail
452516
run: |
453517
tools/scripts/sim-update-powerfail-resume-nobackup.sh
518+
454519
# TEST with backup disabled + NVM_WRITEONCE
455520
- name: make clean
456521
run: |
@@ -478,6 +543,7 @@ jobs:
478543
- name: Run update test with DISABLE_BACKUP and powefail
479544
run: |
480545
tools/scripts/sim-update-powerfail-resume-nobackup.sh
546+
481547
# TEST with backup disabled + FLAGS_HOME
482548
- name: make clean
483549
run: |

hal/sim.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
uint8_t *sim_ram_base;
4646
static uint8_t *flash_base;
4747

48+
int forceEmergency = 0;
4849
uint32_t erasefail_address = 0xFFFFFFFF;
4950

5051
#define INTERNAL_FLASH_FILE "./internal_flash.dd"
@@ -105,8 +106,29 @@ void hal_prepare_boot(void)
105106

106107
int hal_flash_write(uintptr_t address, const uint8_t *data, int len)
107108
{
108-
/* implicit cast abide compiler warning */
109-
memcpy((void*)address, data, len);
109+
int i;
110+
if (forceEmergency == 1 && address == WOLFBOOT_PARTITION_BOOT_ADDRESS) {
111+
/* implicit cast abide compiler warning */
112+
memset((void*)address, 0, len);
113+
/* let the rest of the writes work properly for the emergency update */
114+
forceEmergency = 0;
115+
}
116+
else {
117+
for (i = 0; i < len; i++) {
118+
#ifdef NVM_FLASH_WRITEONCE
119+
if (((uint8_t*)address)[i] != FLASH_BYTE_ERASED) {
120+
/* no writing to non-erased page in NVM_FLASH_WRITEONCE */
121+
printf("NVM_FLASH_WRITEONCE non-erased write detected!\n");
122+
return -1;
123+
}
124+
#endif
125+
#ifdef WOLFBOOT_FLAGS_INVERT
126+
((uint8_t*)address)[i] |= data[i];
127+
#else
128+
((uint8_t*)address)[i] &= data[i];
129+
#endif
130+
}
131+
}
110132
return 0;
111133
}
112134

@@ -150,8 +172,11 @@ void hal_init(void)
150172
erasefail_address = strtol(main_argv[++i], NULL, 16);
151173
fprintf(stderr, "Set power fail to erase at address %x\n",
152174
erasefail_address);
153-
break;
154175
}
176+
/* force a bad write of the boot partition to trigger and test the
177+
* emergency fallback feature */
178+
else if (strcmp(main_argv[i], "emergency") == 0)
179+
forceEmergency = 1;
155180
}
156181
}
157182

include/wolfboot/wolfboot.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,18 @@ extern "C" {
257257
#ifndef WOLFBOOT_FLAGS_INVERT
258258
#define IMG_STATE_NEW 0xFF
259259
#define IMG_STATE_UPDATING 0x70
260-
#define IMG_STATE_FINAL_FLAGS 0x30
260+
/* now just an intermediary state, update state will always be either new or
261+
* updating before the application boots*/
262+
#define IMG_STATE_FINAL_FLAGS 0x30
261263
#define IMG_STATE_TESTING 0x10
262264
#define IMG_STATE_SUCCESS 0x00
263265
#define FLASH_BYTE_ERASED 0xFF
264266
#define FLASH_WORD_ERASED 0xFFFFFFFFUL
265267
#else
266268
#define IMG_STATE_NEW 0x00
267269
#define IMG_STATE_UPDATING 0x8F
268-
#define IMG_STATE_FINAL_FLAGS 0xBF
269270
#define IMG_STATE_TESTING 0xEF
271+
#define IMG_STATE_FINAL_FLAGS 0xBF
270272
#define IMG_STATE_SUCCESS 0xFF
271273
#define FLASH_BYTE_ERASED 0x00
272274
#define FLASH_WORD_ERASED 0x00000000UL

src/image.c

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,6 @@ static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
611611
*/
612612
static void key_sha256(uint8_t key_slot, uint8_t *hash)
613613
{
614-
int blksz;
615-
unsigned int i = 0;
616614
uint8_t *pubkey = keystore_get_buffer(key_slot);
617615
int pubkey_sz = keystore_get_size(key_slot);
618616
wc_Sha256 sha256_ctx;
@@ -621,13 +619,7 @@ static void key_sha256(uint8_t key_slot, uint8_t *hash)
621619
return;
622620

623621
wc_InitSha256(&sha256_ctx);
624-
while (i < (uint32_t)pubkey_sz) {
625-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
626-
if ((i + blksz) > (uint32_t)pubkey_sz)
627-
blksz = pubkey_sz - i;
628-
wc_Sha256Update(&sha256_ctx, (pubkey + i), blksz);
629-
i += blksz;
630-
}
622+
wc_Sha256Update(&sha256_ctx, pubkey, (word32)pubkey_sz);
631623
wc_Sha256Final(&sha256_ctx, hash);
632624
}
633625
#endif /* WOLFBOOT_NO_SIGN */
@@ -700,8 +692,6 @@ static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
700692
*/
701693
static void key_sha384(uint8_t key_slot, uint8_t *hash)
702694
{
703-
int blksz;
704-
unsigned int i = 0;
705695
uint8_t *pubkey = keystore_get_buffer(key_slot);
706696
int pubkey_sz = keystore_get_size(key_slot);
707697
wc_Sha384 sha384_ctx;
@@ -710,13 +700,7 @@ static void key_sha384(uint8_t key_slot, uint8_t *hash)
710700
return;
711701

712702
wc_InitSha384(&sha384_ctx);
713-
while (i < (uint32_t)(pubkey_sz)) {
714-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
715-
if ((i + blksz) > (uint32_t)pubkey_sz)
716-
blksz = pubkey_sz - i;
717-
wc_Sha384Update(&sha384_ctx, (pubkey + i), blksz);
718-
i += blksz;
719-
}
703+
wc_Sha384Update(&sha384_ctx, pubkey, (word32)pubkey_sz);
720704
wc_Sha384Final(&sha384_ctx, hash);
721705
}
722706
#endif /* WOLFBOOT_NO_SIGN */
@@ -789,22 +773,14 @@ static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
789773
*/
790774
static void key_sha3_384(uint8_t key_slot, uint8_t *hash)
791775
{
792-
int blksz;
793-
unsigned int i = 0;
794776
uint8_t *pubkey = keystore_get_buffer(key_slot);
795777
int pubkey_sz = keystore_get_size(key_slot);
796778
wc_Sha3 sha3_ctx;
797779

798780
if (!pubkey || (pubkey_sz < 0))
799781
return;
800782
wc_InitSha3_384(&sha3_ctx, NULL, INVALID_DEVID);
801-
while (i < (uint32_t)pubkey_sz) {
802-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
803-
if ((i + blksz) > (uint32_t)pubkey_sz)
804-
blksz = pubkey_sz - i;
805-
wc_Sha3_384_Update(&sha3_ctx, pubkey + i, blksz);
806-
i += blksz;
807-
}
783+
wc_Sha3_384_Update(&sha3_ctx, pubkey, (word32)pubkey_sz);
808784
wc_Sha3_384_Final(&sha3_ctx, hash);
809785
}
810786
#endif /* WOLFBOOT_NO_SIGN */

src/libwolfboot.c

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -350,12 +350,8 @@ static int RAMFUNCTION trailer_write(uint8_t part, uintptr_t addr, uint8_t val)
350350
/* Calculate write address */
351351
addr_write = addr_align - ((!nvm_cached_sector) * NVM_CACHE_SIZE);
352352

353-
/* Ensure that the destination was erased, or force erase */
354-
if (*((uint32_t *)(addr_write + NVM_CACHE_SIZE - sizeof(uint32_t)))
355-
!= FLASH_WORD_ERASED)
356-
{
357-
hal_flash_erase(addr_write, NVM_CACHE_SIZE);
358-
}
353+
/* Ensure that the destination was erased */
354+
hal_flash_erase(addr_write, NVM_CACHE_SIZE);
359355
#if FLASHBUFFER_SIZE != WOLFBOOT_SECTOR_SIZE
360356
addr_off = 0;
361357
while ((addr_off < WOLFBOOT_SECTOR_SIZE) && (ret == 0)) {
@@ -718,17 +714,21 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
718714
uint32_t address = 0;
719715
int size = 0;
720716

721-
if (part == PART_BOOT) {
722-
address = (uint32_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
723-
size = WOLFBOOT_PARTITION_SIZE;
724-
}
725-
if (part == PART_UPDATE) {
726-
address = (uint32_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
727-
size = WOLFBOOT_PARTITION_SIZE;
728-
}
729-
if (part == PART_SWAP) {
730-
address = (uint32_t)WOLFBOOT_PARTITION_SWAP_ADDRESS;
731-
size = WOLFBOOT_SECTOR_SIZE;
717+
switch (part) {
718+
case PART_BOOT:
719+
address = (uint32_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
720+
size = WOLFBOOT_PARTITION_SIZE;
721+
break;
722+
case PART_UPDATE:
723+
address = (uint32_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
724+
size = WOLFBOOT_PARTITION_SIZE;
725+
break;
726+
case PART_SWAP:
727+
address = (uint32_t)WOLFBOOT_PARTITION_SWAP_ADDRESS;
728+
size = WOLFBOOT_SECTOR_SIZE;
729+
break;
730+
default:
731+
break;
732732
}
733733

734734
if (size > 0) {
@@ -819,16 +819,10 @@ void RAMFUNCTION wolfBoot_success(void)
819819
if (FLAGS_BOOT_EXT()) {
820820
ext_flash_unlock();
821821
wolfBoot_set_partition_state(PART_BOOT, st);
822-
/* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls
823-
* to wolfBoot update */
824-
wolfBoot_set_partition_state(PART_UPDATE, st);
825822
ext_flash_lock();
826823
} else {
827824
hal_flash_unlock();
828825
wolfBoot_set_partition_state(PART_BOOT, st);
829-
/* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls
830-
* to wolfBoot update */
831-
wolfBoot_set_partition_state(PART_UPDATE, st);
832826
hal_flash_lock();
833827
}
834828
#ifdef EXT_ENCRYPTED
@@ -866,13 +860,9 @@ uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
866860
unit_dbg("Explicit end of options reached\n");
867861
break;
868862
}
869-
if (*p == HDR_PADDING) {
870-
/* Padding byte (skip one position) */
871-
p++;
872-
continue;
873-
}
874-
/* Sanity check to prevent dereferencing unaligned half-words */
875-
if ((((size_t)p) & 0x01) != 0) {
863+
/* Sanity check to prevent dereferencing unaligned half-words and skip
864+
* past padding bytes */
865+
if ((*p == HDR_PADDING) || ((((size_t)p) & 0x01) != 0)) {
876866
p++;
877867
continue;
878868
}

0 commit comments

Comments
 (0)