F-7067: elf scatter: fix PART_IS_EXT arg and check load result

In the DISABLE_BACKUP branch of wolfBoot_update() the ELF-scatter restore
block passed the boot struct by value to the pointer-taking PART_IS_EXT
macro, so DISABLE_BACKUP + WOLFBOOT_ELF_FLASH_SCATTER + EXT_FLASH did not
even compile, and the load result was discarded. Mirror the
wolfBoot_start() pattern (PART_IS_EXT(&boot), panic on load failure), drop
the dead base local, and add a compile check for the combination
(unit-elf-scatter-db-build.py) guarding the one test that needs a
DISABLE_BACKUP-excluded symbol.

Verification: full unit suite 1096 checks, 0 failures; new test fails
pre-fix (struct vs pointer compile error), passes post-fix.
pull/882/head
Daniele Lacamera 2026-09-04 09:52:22 +02:00
parent f598b3fd41
commit 455c1c6cc6
4 changed files with 69 additions and 2 deletions

View File

@ -1332,12 +1332,16 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
#else /* DISABLE_BACKUP */
#ifdef WOLFBOOT_ELF_FLASH_SCATTER
unsigned long entry;
void* base = (void*)WOLFBOOT_PARTITION_BOOT_ADDRESS;
wolfBoot_printf("ELF Scattered image digest check\n");
if (wolfBoot_check_flash_image_elf(PART_BOOT, &entry) < 0) {
wolfBoot_printf("ELF Scattered image digest check: failed. Restoring "
"scattered image...\n");
wolfBoot_load_flash_image_elf(PART_BOOT, &entry, PART_IS_EXT(boot));
if (wolfBoot_load_flash_image_elf(PART_BOOT, &entry,
PART_IS_EXT(&boot)) < 0) {
wolfBoot_printf(
"ELF: [UPDATE] ERROR: could not store scattered image\n");
wolfBoot_panic();
}
if (wolfBoot_check_flash_image_elf(PART_BOOT, &entry) < 0) {
wolfBoot_printf(
"Fatal: Could not verify digest after scattering. Panic().\n");

View File

@ -222,6 +222,7 @@ run: $(TESTS)
python3 unit-sign-delta-cert-inv-off.py || exit 1
python3 unit-sign-delta-basehash-cleanup.py || exit 1
python3 unit-delta-sector-align.py || exit 1
python3 unit-elf-scatter-db-build.py || exit 1
python3 unit-sign-custom-tlv-le.py || exit 1
python3 unit-sign-custom-tlv-large.py || exit 1
python3 unit-sign-custom-tlv-pubkey-der.py || exit 1
@ -273,6 +274,15 @@ unit-update-flash-delta-misalign:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -D
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT \
-DDELTA_UPDATES -DDELTA_BLOCK_SIZE=1536 -D__WOLFBOOT \
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
# Compile-only check for the DISABLE_BACKUP + WOLFBOOT_ELF_FLASH_SCATTER +
# EXT_FLASH combination: the ELF restore block in wolfBoot_update() must
# compile (it used to pass a struct where PART_IS_EXT expects a pointer).
# Used by unit-elf-scatter-db-build.py only, so it is not part of $(TESTS).
unit-update-flash-elf-scatter-db:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT \
-DWOLFBOOT_ELF_FLASH_SCATTER -DWOLFBOOT_ELF -DIMAGE_HEADER_SIZE=256 \
-DDISABLE_BACKUP -D__WOLFBOOT \
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
unit-update-flash-self-update:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT \
-DRAM_CODE -DARCH_SIM -DUNIT_TEST_SELF_UPDATE_ONLY \
@ -821,6 +831,9 @@ unit-update-flash-delta-misalign: ../../include/target.h unit-update-flash.c
gcc -o $@ unit-update-flash.c ../../src/image.c ../../src/delta.c \
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c $(CFLAGS) $(LDFLAGS)
unit-update-flash-elf-scatter-db: ../../include/target.h unit-update-flash.c FORCE
gcc -c -o /dev/null unit-update-flash.c $(CFLAGS)
unit-update-flash-enc:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \
-DPART_SWAP_EXT -DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DHAVE_CHACHA \

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# unit-elf-scatter-db-build.py
#
# Compile check for the DISABLE_BACKUP + WOLFBOOT_ELF_FLASH_SCATTER +
# EXT_FLASH combination: the ELF-scatter restore block in
# wolfBoot_update() (src/update_flash.c) used to pass the boot struct by
# value to the pointer-taking PART_IS_EXT macro, so this configuration
# failed to build and the branch could never be exercised. It must now
# compile, with the load result checked like in wolfBoot_start().
#
# Copyright (C) 2026 wolfSSL Inc.
#
# This file is part of wolfBoot.
#
# wolfBoot is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# wolfBoot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
import subprocess
import sys
def main():
p = subprocess.run(["make", "unit-update-flash-elf-scatter-db"],
capture_output=True, text=True)
if p.returncode != 0:
print("FAIL: DISABLE_BACKUP + ELF scatter + EXT_FLASH "
"does not compile:\n")
print(p.stderr[-2000:])
return 1
print("PASS: DISABLE_BACKUP + ELF scatter + EXT_FLASH compiles")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1280,6 +1280,7 @@ START_TEST (test_empty_boot_but_update_sha_corrupted_denied) {
cleanup_flash();
}
#ifndef DISABLE_BACKUP
START_TEST (test_swap_resume_noop)
{
reset_mock_stats();
@ -1291,6 +1292,7 @@ START_TEST (test_swap_resume_noop)
cleanup_flash();
}
END_TEST
#endif
START_TEST (test_diffbase_version_reads)
{
@ -1868,7 +1870,9 @@ Suite *wolfboot_suite(void)
tcase_add_test(emergency_rollback_failure_due_to_bad_update, test_emergency_rollback_failure_due_to_bad_update);
tcase_add_test(empty_boot_partition_update, test_empty_boot_partition_update);
tcase_add_test(empty_boot_but_update_sha_corrupted_denied, test_empty_boot_but_update_sha_corrupted_denied);
#ifndef DISABLE_BACKUP
tcase_add_test(swap_resume, test_swap_resume_noop);
#endif
tcase_add_test(diffbase_version, test_diffbase_version_reads);
tcase_add_test(diffbase_version, test_diffbase_version_reads_from_little_endian_bytes);
tcase_add_test(get_total_size, test_get_total_size_preserves_uint32_range);