Merge pull request #562 from danielinux/update-flash-elf

Scatter/gather ELF files according to segments `paddr`
pull/568/head
Brett Nicholas 2025-04-16 07:14:22 -06:00 committed by GitHub
commit 60b208e5e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 883 additions and 109 deletions

View File

@ -220,6 +220,18 @@ jobs:
config-file: ./config/examples/sim.config
make-args: CFLAGS_EXTRA=-DWOLFBOOT_FLASH_MULTI_SECTOR_ERASE
sim_elf_scattered:
uses: ./.github/workflows/test-build.yml
with:
arch: host
config-file: ./config/examples/sim-elf-scattered.config
sim_elf_scattered_nobackup:
uses: ./.github/workflows/test-build.yml
with:
arch: host
config-file: ./config/examples/sim-elf-scattered.config
make-args: DISABLE_BACKUP=1
# TODO: SP math with small stack has issues

View File

@ -0,0 +1,36 @@
name: Test for scattered elf validation
on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
jobs:
elf_scattered_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: make clean
run: |
make keysclean
- name: Select config
run: |
cp config/examples/sim.config .config
- name: Build tools
run: |
make -C tools/keytools && make -C tools/bin-assemble
- name: Build wolfboot.elf
run: |
make clean && make test-sim-internal-flash-with-update ELF=1 ELF_SCATTERED=1
- name: Run bootloader with no arguments
run: |
./wolfboot.elf

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_fastmath_smallstack:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_fastmath:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_noasm_smallstack:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_noasm:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_base:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_multi_sha:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_multi_sha:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -8,7 +8,7 @@ on:
jobs:
renode_automated_smallstack:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@ -45,6 +45,9 @@ project(wolfBoot)
include(cmake/utils.cmake)
include(cmake/functions.cmake)
include_directories(include)
include_directories(lib/wolfssl)
if(NOT DEFINED WOLFBOOT_TARGET)
message(FATAL_ERROR "WOLFBOOT_TARGET must be defined")
else()
@ -620,6 +623,8 @@ if(NOT SPMATH AND NOT SPMATHALL)
list(APPEND USER_SETTINGS USE_FAST_MATH)
endif()
list(APPEND WOLFBOOT_DEFS WOLFSSL_USER_SETTINGS)
add_library(user_settings INTERFACE)
target_compile_definitions(user_settings INTERFACE ${USER_SETTINGS} ${SIGN_OPTIONS})
@ -699,7 +704,7 @@ configure_file(include/target.h.in ${CMAKE_CURRENT_BINARY_DIR}/target.h @ONLY)
add_library(target INTERFACE)
target_compile_definitions(target INTERFACE ${WOLFBOOT_DEFS})
target_include_directories(target BEFORE INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(target BEFORE INTERFACE ${CMAKE_CURRENT_BINARY_DIR} lib/wolfssl)
set(KEYSTORE ${CMAKE_CURRENT_BINARY_DIR}/keystore.c)

View File

@ -253,7 +253,7 @@ ifeq ($(ARCH),ARM)
CORTEX_A5=1
UPDATE_OBJS:=src/update_ram.o
CFLAGS+=-DWOLFBOOT_DUALBOOT -DEXT_FLASH -DNAND_FLASH -fno-builtin -ffreestanding
#CFLAGS+=-DWOLFBOOT_USE_STDLIBC
CFLAGS+=-DWOLFBOOT_USE_STDLIBC
endif
## Cortex CPU
@ -1125,7 +1125,9 @@ ifeq ($(TARGET),sim)
LD_END_GROUP=
BOOT_IMG=test-app/image.elf
CFLAGS+=-DARCH_SIM
CFLAGS+=-DWOLFBOOT_USE_STDLIBC
ifneq ($(ELF_SCATTERED),1)
CFLAGS+=-DWOLFBOOT_USE_STDLIBC
endif
ifeq ($(FORCE_32BIT),1)
CFLAGS+=-m32
LDFLAGS+=-m32

View File

@ -0,0 +1,28 @@
ARCH=sim
TARGET=sim
SIGN?=ED25519
HASH?=SHA256
WOLFBOOT_SMALL_STACK?=0
SPI_FLASH=0
DEBUG=1
ELF_SCATTERED=1
ELF=1
# sizes should be multiple of system page size
WOLFBOOT_PARTITION_SIZE=0x40000
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000
# if on external flash, it should be multiple of system page size
# Address from 0x100000 to 0x1FFFFF is reserved for ELF_SCATTERED
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x200000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x280000
# required for keytools
WOLFBOOT_FIXED_PARTITIONS=1
# For debugging XMALLOC/XFREE
#CFLAGS_EXTRA+=-DWOLFBOOT_DEBUG_MALLOC

View File

@ -0,0 +1,24 @@
ARCH=sim
TARGET=sim
SIGN?=ECC256
HASH?=SHA256
WOLFBOOT_SMALL_STACK?=0
SPI_FLASH=0
DEBUG=1
FORCE_32BIT=1
ELF=1
ELF_SCATTERED=1
# sizes should be multiple of system page size
WOLFBOOT_PARTITION_SIZE=0x40000
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000
# if on external flash, it should be multiple of system page size
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x100000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x180000
# required for keytools
WOLFBOOT_FIXED_PARTITIONS=1
# For debugging XMALLOC/XFREE
#CFLAGS_EXTRA+=-DWOLFBOOT_DEBUG_MALLOC

View File

@ -78,7 +78,7 @@ static int division(uint32_t dividend,
return 0;
}
static uint32_t div(uint32_t dividend, uint32_t divisor)
static uint32_t div_u(uint32_t dividend, uint32_t divisor)
{
uint32_t quotient = 0;
uint32_t remainder = 0;
@ -504,7 +504,7 @@ static void nand_read_info(void)
nand_flash.bad_block_pos = (*(uint16_t *)(onfi_data + PARAMS_POS_FEATURES)) & 1;
nand_flash.ext_page_len = *(uint16_t *)(onfi_data + PARAMS_POS_EXT_PARAM_PAGE_LEN);
nand_flash.parameter_page = *(uint16_t *)(onfi_data + PARAMS_POS_PARAMETER_PAGE);
nand_flash.pages_per_block = div(nand_flash.block_size, nand_flash.page_size);
nand_flash.pages_per_block = div_u(nand_flash.block_size, nand_flash.page_size);
nand_flash.pages_per_device = nand_flash.pages_per_block * nand_flash.block_count;
nand_flash.oob_size = *(uint16_t *)(onfi_data + PARAMS_POS_OOBSIZE);
nand_flash.revision = *(uint16_t *)(onfi_data + PARAMS_POS_REVISION);
@ -605,8 +605,8 @@ static int nand_check_bad_block(uint32_t block)
int ext_flash_read(uintptr_t address, uint8_t *data, int len)
{
uint8_t buffer_page[NAND_FLASH_PAGE_SIZE];
uint32_t block = div(address, nand_flash.block_size); /* The block where the address falls in */
uint32_t page = div(address, nand_flash.page_size); /* The page where the address falls in */
uint32_t block = div_u(address, nand_flash.block_size); /* The block where the address falls in */
uint32_t page = div_u(address, nand_flash.page_size); /* The page where the address falls in */
uint32_t start_page_in_block = mod(page, nand_flash.pages_per_block); /* The start page within this block */
uint32_t in_block_offset = mod(address, nand_flash.block_size); /* The offset of the address within the block */
uint32_t remaining = nand_flash.block_size - in_block_offset; /* How many bytes remaining to read in the first block */
@ -637,7 +637,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
} while (ret < 0);
/* Amount of pages to be read from this block */
pages_to_read = div((sz + nand_flash.page_size - 1), nand_flash.page_size);
pages_to_read = div_u((sz + nand_flash.page_size - 1), nand_flash.page_size);
if (pages_to_read * nand_flash.page_size > remaining)
pages_to_read--;

View File

@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#ifdef __APPLE__
#include <mach-o/loader.h>
@ -42,6 +43,10 @@
#include "target.h"
#include "printf.h"
#ifdef WOLFBOOT_ELF_SCATTERED
#include "elf.h"
#endif
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_client.h"
@ -304,6 +309,7 @@ void do_boot(const uint32_t *app_offset)
{
int ret;
size_t app_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
wolfBoot_printf("Simulator do_boot app_offset = %p\n", app_offset);
if (flashLocked == 0) {
wolfBoot_printf("WARNING FLASH IS UNLOCKED AT BOOT");
@ -348,18 +354,34 @@ void do_boot(const uint32_t *app_offset)
main = (main_entry)((uint8_t*)pSymbolAddress + epc->entryoff);
main(main_argc, main_argv, NULL, NULL);
#elif defined (WOLFBOOT_ELF_SCATTERED)
uint8_t *entry_point = (sim_ram_base + (unsigned long)app_offset);
printf("entry point: %p\n", entry_point);
printf("app offset: %p\n", app_offset);
typedef int (*main_entry)(int, char**);
main_entry main;
main = (main_entry)(entry_point);
/* TODO: call main ! */
/* main(main_argc, main_argv); */
wolfBoot_printf("Simulator for ELF_SCATTERED image not implemented yet. Exiting...\n");
exit(0);
#else
char *envp[1] = {NULL};
int fd = memfd_create("test_app", 0);
size_t wret;
if (fd == -1) {
wolfBoot_printf( "memfd error\n");
exit(-1);
}
if ((size_t)write(fd, app_offset, app_size) != app_size) {
wolfBoot_printf( "can't write test-app to memfd\n");
wret = write(fd, app_offset, app_size);
if (wret != app_size) {
wolfBoot_printf( "can't write test-app to memfd, address %p\n", app_offset);
exit(-1);
}
wolfBoot_printf("Stored test-app to memfd, address %p (%zu bytes)\n", app_offset, wret);
ret = fexecve(fd, main_argv, envp);
wolfBoot_printf( "fexecve error\n");

View File

@ -32,6 +32,7 @@ extern "C" {
#define ELF_IDENT_STR "\x7F""ELF"
/* header ident[4] */
#define ELF_CLASS_OFF (4)
#define ELF_CLASS_32 (1)
#define ELF_CLASS_64 (2)
@ -111,6 +112,11 @@ typedef struct elf64_header {
uint16_t sh_str_index;
} elf64_header;
union elf_header {
elf32_header *h32;
elf64_header *h64;
};
typedef struct elf64_section_header {
uint32_t name;
uint32_t type;
@ -136,9 +142,36 @@ typedef struct elf64_program_header {
} elf64_program_header;
/* support byte swapping if testing/reading an elf with different endianess */
#if defined(ELF_PARSER) || defined(ELF_ENDIAN_SUPPORT)
#ifdef BIG_ENDIAN_ORDER
#define GET16(x) (( is_le) ? __builtin_bswap16(x) : (x))
#define GET32(x) (( is_le) ? __builtin_bswap32(x) : (x))
#define GET64(x) (( is_le) ? __builtin_bswap64(x) : (x))
#else
#define GET16(x) ((!is_le) ? __builtin_bswap16(x) : (x))
#define GET32(x) ((!is_le) ? __builtin_bswap32(x) : (x))
#define GET64(x) ((!is_le) ? __builtin_bswap64(x) : (x))
#endif
#else
#define GET16(x) (x)
#define GET32(x) (x)
#define GET64(x) (x)
#endif
#define GET_H64(name) (is_elf32 ? GET32(h32->name) : GET64(h64->name))
#define GET_H32(name) (is_elf32 ? GET32(h32->name) : GET32(h64->name))
#define GET_H16(name) (is_elf32 ? GET16(h32->name) : GET16(h64->name))
#define GET_E64(name) (is_elf32 ? GET32(e32->name) : GET64(e64->name))
#define GET_E32(name) (is_elf32 ? GET32(e32->name) : GET32(e64->name))
typedef int (*elf_mmu_map_cb)(uint64_t, uint64_t, uint32_t);
int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb);
int elf_load_image(uint8_t *image, uintptr_t *entry);
int elf_load_image(uint8_t *image, uintptr_t *entry, int is_ext);
int elf_store_image_scattered(const unsigned char *image, unsigned long *entry_out, int ext_flash);
int elf_check_image_scattered(uint8_t part, unsigned long *entry_out);
int elf_hdr_size(const unsigned char *ehdr);
int elf_open(const unsigned char *ehdr, int *is_elf32);
#ifdef __cplusplus

View File

@ -79,6 +79,7 @@ extern "C" {
#define HDR_SIGNATURE 0x20
#define HDR_POLICY_SIGNATURE 0x21
#define HDR_SECONDARY_SIGNATURE 0x22
#define HDR_ELF_SCATTERED_HASH 0x23
#define HDR_PADDING 0xFF
/* Auth Key types */
@ -163,31 +164,49 @@ extern "C" {
/* Hashing configuration */
#if defined(WOLFBOOT_HASH_SHA256)
# include "wolfssl/wolfcrypt/sha256.h"
# ifndef WOLFBOOT_SHA_BLOCK_SIZE
# define WOLFBOOT_SHA_BLOCK_SIZE (256)
# endif
# define WOLFBOOT_SHA_HDR HDR_SHA256
# define WOLFBOOT_SHA_DIGEST_SIZE (32)
# define image_hash image_sha256
# define header_hash header_sha256
# define update_hash wc_Sha256Update
# define key_hash key_sha256
# define self_hash self_sha256
# define final_hash wc_Sha256Final
typedef wc_Sha256 wolfBoot_hash_t;
# define HDR_HASH HDR_SHA256
#elif defined(WOLFBOOT_HASH_SHA384)
# include "wolfssl/wolfcrypt/sha512.h"
# ifndef WOLFBOOT_SHA_BLOCK_SIZE
# define WOLFBOOT_SHA_BLOCK_SIZE (256)
# endif
# define WOLFBOOT_SHA_HDR HDR_SHA384
# define WOLFBOOT_SHA_DIGEST_SIZE (48)
# define image_hash image_sha384
# define header_hash header_sha384
# define update_hash wc_Sha384Update
# define key_hash key_sha384
# define self_hash self_sha384
# define final_hash wc_Sha384Final
typedef wc_Sha384 wolfBoot_hash_t;
# define HDR_HASH HDR_SHA384
#elif defined(WOLFBOOT_HASH_SHA3_384)
# include "wolfssl/wolfcrypt/sha3.h"
# ifndef WOLFBOOT_SHA_BLOCK_SIZE
# define WOLFBOOT_SHA_BLOCK_SIZE (128)
# endif
# define WOLFBOOT_SHA_HDR HDR_SHA3_384
# define WOLFBOOT_SHA_DIGEST_SIZE (48)
# define image_hash image_sha3_384
# define header_hash header_sha3_384
# define update_hash wc_Sha3Update
# define final_hash wc_Sha3Final
# define key_hash key_sha3_384
typedef wc_Sha3 wolfBoot_hash_t;
# define HDR_HASH HDR_SHA3_384
#else
# error "No valid hash algorithm defined!"
#endif
@ -291,6 +310,8 @@ extern "C" {
/* now just an intermediary state, update state will always be either new or
* updating before the application boots*/
#define IMG_STATE_FINAL_FLAGS 0x30
/* ELF loading state - only valid on boot partition so doesn't conflict with
* IMAGE_STATE_UPDATING */
#define IMG_STATE_TESTING 0x10
#define IMG_STATE_SUCCESS 0x00
#define FLASH_BYTE_ERASED 0xFF

View File

@ -786,6 +786,10 @@ ifeq ($(ELF),1)
ifneq ($(DEBUG_ELF),)
CFLAGS+=-DDEBUG_ELF=$(DEBUG_ELF)
endif
ifeq ($(ELF_SCATTERED),1)
CFLAGS+=-D"WOLFBOOT_ELF_SCATTERED=1"
endif
endif
ifeq ($(MULTIBOOT2),1)

164
src/elf.c
View File

@ -27,11 +27,16 @@
#include "printf.h"
#include "string.h"
#include "elf.h"
#include "hal.h"
#ifdef ARCH_PPC
#include "hal/nxp_ppc.h"
#endif
#ifdef WOLFBOOT_ELF_SCATTERED
#include "image.h"
#endif
/* support for elf parsing debug printf */
#if defined(DEBUG) || defined(ELF_PARSER)
#if defined(DEBUG_ELF) && DEBUG_ELF == 0
@ -42,29 +47,8 @@
#endif
#endif
/* support byte swapping if testing/reading an elf with different endianess */
#if defined(ELF_PARSER) || defined(ELF_ENDIAN_SUPPORT)
#ifdef BIG_ENDIAN_ORDER
#define GET16(x) (( is_le) ? __builtin_bswap16(x) : (x))
#define GET32(x) (( is_le) ? __builtin_bswap32(x) : (x))
#define GET64(x) (( is_le) ? __builtin_bswap64(x) : (x))
#else
#define GET16(x) ((!is_le) ? __builtin_bswap16(x) : (x))
#define GET32(x) ((!is_le) ? __builtin_bswap32(x) : (x))
#define GET64(x) ((!is_le) ? __builtin_bswap64(x) : (x))
#endif
#else
#define GET16(x) (x)
#define GET32(x) (x)
#define GET64(x) (x)
#endif
#define GET_H64(name) (is_elf32 ? GET32(h32->name) : GET64(h64->name))
#define GET_H32(name) (is_elf32 ? GET32(h32->name) : GET32(h64->name))
#define GET_H16(name) (is_elf32 ? GET16(h32->name) : GET16(h64->name))
#define GET_E64(name) (is_elf32 ? GET32(e32->name) : GET64(e64->name))
#define GET_E32(name) (is_elf32 ? GET32(e32->name) : GET32(e64->name))
#if defined(MMU) || defined (WOLFBOOT_FSP) || defined (ARCH_PPC)
/* Loader for elf32 or elf64 format program headers
* Returns the entry point function
*/
@ -165,11 +149,145 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
return 0;
}
#endif /* MMU || WOLFBOOT_FSP || ARCH_PPC */
int elf_load_image(uint8_t *image, uintptr_t *entry)
int elf_open(const unsigned char *ehdr, int *is_elf32)
{
const unsigned char *ident = ehdr;
/* Verify ELF header */
if (memcmp(ident, ELF_IDENT_STR, 4) != 0) {
return -1; /* not valid header identifier */
}
wolfBoot_printf("ELF image found\n");
*is_elf32 = !!(ident[ELF_CLASS_OFF] == ELF_CLASS_32);
return 0;
}
int elf_hdr_size(const unsigned char *ehdr)
{
int sz = 0;
int is_elf32;
if (elf_open(ehdr, &is_elf32) != 0)
return -1;
if (is_elf32) {
const elf32_header *elf32_hdr = (const elf32_header *)ehdr;
sz = sizeof(elf32_header);
sz += elf32_hdr->ph_entry_count * sizeof(elf32_program_header);
} else {
const elf64_header *elf64_hdr = (const elf64_header *)ehdr;
sz = sizeof(elf64_header);
sz += elf64_hdr->ph_entry_count * sizeof(elf64_program_header);
}
return sz;
}
#if !defined(MMU) && !defined(WOLFBOOT_FSP) && !defined(ARCH_PPC) && defined (WOLFBOOT_ELF_SCATTERED)
#ifdef ARCH_SIM
# define BASE_OFF ARCH_FLASH_OFFSET
#else
# define BASE_OFF 0
#endif
int elf_store_image_scattered(const unsigned char *hdr, unsigned long *entry_out, int ext_flash) {
const unsigned char *image;
int is_elf32;
unsigned short entry_count;
unsigned long entry_off;
int i;
image = hdr + IMAGE_HEADER_SIZE;
if (elf_open(image, &is_elf32) != 0) {
return -1;
}
if (is_elf32) {
const elf32_header *eh;
const elf32_program_header *ph;
wolfBoot_printf("ELF image is 32 bit\n");
eh = (const elf32_header *)image;
entry_count = eh->ph_entry_count;
entry_off = eh->ph_offset;
*entry_out = (unsigned long)eh->entry;
ph = (const elf32_program_header *)(image + entry_off);
for (i = 0; i < entry_count; ++i) {
unsigned long paddr;
unsigned long filesz;
unsigned long offset;
if (ph[i].type != ELF_PT_LOAD)
continue;
paddr = (unsigned long)ph[i].paddr;
offset = (unsigned long)ph[i].offset;
filesz = (unsigned long)ph[i].file_size;
wolfBoot_printf("Writing section at address %lx offset %lx\n", paddr, offset);
#ifdef EXT_FLASH
if (ext_flash) {
ext_flash_unlock();
ext_flash_erase(paddr + BASE_OFF, filesz);
ext_flash_write(paddr + BASE_OFF, image + offset, filesz);
ext_flash_lock();
}
else
#endif
{
hal_flash_unlock();
hal_flash_erase(paddr + BASE_OFF, filesz);
hal_flash_write(paddr + BASE_OFF, image + offset, filesz);
hal_flash_lock();
}
}
} else { /* 64 bit ELF */
const elf64_header *eh;
const elf64_program_header *ph;
wolfBoot_printf("ELF image is 64 bit\n");
eh = (const elf64_header *)image;
entry_count = eh->ph_entry_count;
entry_off = eh->ph_offset;
*entry_out = (unsigned long)eh->entry;
ph = (const elf64_program_header *)(image + entry_off);
for (i = 0; i < entry_count; ++i) {
unsigned long paddr;
unsigned long filesz;
unsigned long offset;
if (ph[i].type != ELF_PT_LOAD)
continue;
paddr = (unsigned long)ph[i].paddr;
offset = (unsigned long)ph[i].offset;
filesz = (unsigned long)ph[i].file_size;
wolfBoot_printf("Writing section at address %lx offset %lx\n", paddr, offset);
#ifdef EXT_FLASH
if (ext_flash) {
ext_flash_unlock();
ext_flash_erase(paddr + BASE_OFF, filesz);
ext_flash_write(paddr + BASE_OFF, image + offset, filesz);
ext_flash_lock();
}
else
#endif
{
hal_flash_unlock();
hal_flash_erase(paddr + BASE_OFF, filesz);
hal_flash_write(paddr + BASE_OFF, image + offset, filesz);
hal_flash_lock();
}
}
}
return 0;
}
#endif /* !defined(MMU) && !defined(WOLFBOOT_FSP) && !defined(ARCH_PPC) && defined (WOLFBOOT_ELF_SCATTERED) */
int elf_load_image(uint8_t *image, uintptr_t *entry, int ext_flash)
{
#ifdef MMU
return elf_load_image_mmu(image, entry, NULL);
#else
return elf_store_image_scattered(image, (unsigned long *)entry, ext_flash);
#endif
}
#endif /* WOLFBOOT_ELF */

View File

@ -818,6 +818,36 @@ static uint8_t *get_img_hdr(struct wolfBoot_image *img)
#if defined(WOLFBOOT_HASH_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
/* Initialize and hash the header part */
static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
{
uint8_t *stored_sha, *end_sha;
uint16_t stored_sha_len;
uint8_t *p;
int blksz;
if (!img)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
(void)wc_InitSha256_ex(sha256_ctx, NULL, hsmClientDevIdHash);
#else
wc_InitSha256(sha256_ctx);
#endif
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha256Update(sha256_ctx, p, blksz);
p += blksz;
}
return 0;
}
/**
* @brief Calculate the SHA256 hash of the image.
*
@ -827,33 +857,13 @@ static uint8_t *get_img_hdr(struct wolfBoot_image *img)
*/
static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *stored_sha, *end_sha;
uint16_t stored_sha_len;
uint32_t position = 0;
uint8_t *p;
int blksz;
uint32_t position = 0;
wc_Sha256 sha256_ctx;
if (!img)
if (header_sha256(&sha256_ctx, img) != 0)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
(void)wc_InitSha256_ex(&sha256_ctx, NULL, hsmClientDevIdHash);
#else
wc_InitSha256(&sha256_ctx);
#endif
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha256Update(&sha256_ctx, p, blksz);
p += blksz;
}
do {
p = get_sha_block(img, position);
if (p == NULL)
@ -899,6 +909,37 @@ static void key_sha256(uint8_t key_slot, uint8_t *hash)
#if defined(WOLFBOOT_HASH_SHA384)
#include <wolfssl/wolfcrypt/sha512.h>
/* Initialize and hash the header part */
static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
{
uint16_t stored_sha_len;
uint8_t *stored_sha, *end_sha;
uint8_t *p;
int blksz;
if (!img)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA384, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
(void)wc_InitSha384_ex(sha384_ctx, NULL, hsmClientDevIdHash);
#else
wc_InitSha384(sha384_ctx);
#endif
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha384Update(sha384_ctx, p, blksz);
p += blksz;
}
return 0;
}
/**
* @brief Calculate SHA-384 hash of the image.
*
@ -910,29 +951,13 @@ static void key_sha256(uint8_t key_slot, uint8_t *hash)
*/
static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *stored_sha, *end_sha;
uint16_t stored_sha_len;
uint32_t position = 0;
uint8_t *p;
int blksz;
uint32_t position = 0;
wc_Sha384 sha384_ctx;
if (!img)
if (header_sha384(&sha384_ctx, img) != 0)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA384, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
wc_InitSha384(&sha384_ctx);
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha384Update(&sha384_ctx, p, blksz);
p += blksz;
}
do {
p = get_sha_block(img, position);
if (p == NULL)
@ -983,6 +1008,33 @@ static void key_sha384(uint8_t key_slot, uint8_t *hash)
#include <wolfssl/wolfcrypt/sha3.h>
/* Initialize and hash the header part */
static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
{
uint16_t stored_sha_len;
uint8_t *stored_sha, *end_sha;
uint8_t *p;
int blksz;
if (!img)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA3_384, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
wc_InitSha3_384(sha3_ctx, NULL, INVALID_DEVID);
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha3_384_Update(sha3_ctx, p, blksz);
p += blksz;
}
return 0;
}
/**
* @brief Calculate SHA3-384 hash of the image.
*
@ -994,29 +1046,13 @@ static void key_sha384(uint8_t key_slot, uint8_t *hash)
*/
static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *stored_sha, *end_sha;
uint16_t stored_sha_len;
uint8_t *p;
int blksz;
uint32_t position = 0;
wc_Sha3 sha3_ctx;
if (!img)
if (header_sha3_384(&sha3_ctx, img) != 0)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA3_384, &stored_sha);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
wc_InitSha3_384(&sha3_ctx, NULL, INVALID_DEVID);
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
p += blksz;
}
do {
p = get_sha_block(img, position);
if (p == NULL)
@ -1291,6 +1327,287 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
return 0;
}
#ifdef WOLFBOOT_ELF_SCATTERED
#include "elf.h"
#define PADDING_BLOCK_SIZE 64
#ifdef ARCH_SIM
#define BASE_OFF ARCH_FLASH_OFFSET
#else
#define BASE_OFF 0
#endif
int elf_check_image_scattered(uint8_t part, unsigned long *entry_out)
{
/* Open the partition containing the image */
struct wolfBoot_image boot;
uint8_t *elf_h, *p;
int elf_hdr_sz = 0;
int len;
int is_elf32;
unsigned short entry_count;
unsigned short entry_size;
unsigned long entry_off;
long final_offset = -1;
uint8_t calc_digest[WOLFBOOT_SHA_DIGEST_SIZE];
uint8_t *exp_digest;
int stored_sha_len;
int i;
uint8_t padding_block[PADDING_BLOCK_SIZE];
int entry_out_set = 0;
wolfBoot_hash_t ctx;
if (wolfBoot_open_image(&boot, part) < 0)
return -1;
p = get_img_hdr(&boot);
/* Initialize hash, feed the manifest header to it */
if (header_hash(&ctx, &boot) < 0)
return -1;
stored_sha_len = get_header(&boot, HDR_HASH, &exp_digest);
if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE)
return -1;
/* Get the elf header size */
elf_h = p + IMAGE_HEADER_SIZE;
if (elf_open(elf_h, &is_elf32) < 0)
return -1;
elf_hdr_sz = elf_hdr_size(elf_h);
wolfBoot_printf("Elf header size: %d\n", elf_hdr_sz);
memset(padding_block, 0, PADDING_BLOCK_SIZE);
/* Feed the elf header to the hash function */
len = elf_hdr_sz;
p = elf_h;
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, p, WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, p, len);
break;
}
p += WOLFBOOT_SHA_BLOCK_SIZE;
}
wolfBoot_printf("Hashed ELF header.\n");
/* Feed the program headers to the hash function */
if (is_elf32) {
elf32_header *eh = (elf32_header *)elf_h;
elf32_program_header *ph;
entry_count = eh->ph_entry_count;
entry_size = eh->ph_entry_size;
entry_off = eh->ph_offset;
if (!entry_out_set) {
*entry_out = eh->entry;
entry_out_set = 1;
}
wolfBoot_printf("EH entry offset: %d\n", (int)entry_off);
ph = (elf32_program_header *)(elf_h + entry_off);
/* Add padding until the first program header into hash function */
len = ph[0].offset - elf_hdr_sz;
wolfBoot_printf("Adding %d bytes padding\n", (int)len);
while (len > 0) {
if (len > PADDING_BLOCK_SIZE) {
update_hash(&ctx, padding_block, PADDING_BLOCK_SIZE);
len -= PADDING_BLOCK_SIZE;
} else {
update_hash(&ctx, padding_block, len);
break;
}
}
for (i = 0; i < entry_count; i++) {
unsigned long paddr;
unsigned long filesz;
unsigned long offset;
paddr = (unsigned long)ph[i].paddr;
offset = (unsigned long)ph[i].offset;
filesz = (unsigned long)ph[i].file_size;
wolfBoot_printf("Paddr: 0x%lx offset: %lu, size: %lu\n", paddr,
offset, filesz);
/* Feed any non-loaded parts to the hash function */
if (ph[i].type != ELF_PT_LOAD) {
len = filesz;
//wolfBoot_printf("Feeding ghost segment, len %d\n", len);
continue;
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, elf_h + offset, WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
paddr += WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, elf_h + offset, len);
break;
}
}
} else {
/* Feed the loaded parts to the hash function */
len = filesz;
wolfBoot_printf("Feeding stored segment, len %d\n", len);
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, (void *)(paddr + BASE_OFF),
WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
paddr += WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, (void *)(paddr + BASE_OFF),
len);
break;
}
}
}
/* Add padding until next program header, if any. */
if ((i < entry_count - 1) && (ph[i+1].offset > (offset + filesz))) {
unsigned long padding = ph[i+1].offset - (offset + filesz);
wolfBoot_printf("Adding padding: %lu (from %lx to %lx)\n", padding, (unsigned long)offset + filesz, (unsigned long)ph[i+1].offset);
while (padding > 0) {
if (padding > PADDING_BLOCK_SIZE) {
update_hash(&ctx, padding_block, PADDING_BLOCK_SIZE);
padding -= PADDING_BLOCK_SIZE;
} else {
update_hash(&ctx, padding_block, padding);
break;
}
}
} else {
final_offset = offset + filesz;
}
}
} else { /* 64-bit ELF */
elf64_header *eh = (elf64_header *)elf_h;
elf64_program_header *ph;
entry_count = eh->ph_entry_count;
entry_size = eh->ph_entry_size;
entry_off = eh->ph_offset;
if (!entry_out_set) {
*entry_out = eh->entry;
entry_out_set = 1;
}
wolfBoot_printf("EH entry offset: %d\n", (int)entry_off);
ph = (elf64_program_header *)(elf_h + entry_off);
/* Add padding until the first program header into hash function */
len = ph[0].offset - elf_hdr_sz;
wolfBoot_printf("Adding %d bytes padding\n", len);
while (len > 0) {
if (len > PADDING_BLOCK_SIZE) {
update_hash(&ctx, padding_block, PADDING_BLOCK_SIZE);
len -= PADDING_BLOCK_SIZE;
} else {
update_hash(&ctx, padding_block, len);
break;
}
}
for (i = 0; i < entry_count; i++) {
unsigned long paddr;
unsigned long filesz;
unsigned long offset;
paddr = (unsigned long)ph[i].paddr;
offset = (unsigned long)ph[i].offset;
filesz = (unsigned long)ph[i].file_size;
wolfBoot_printf("Paddr: 0x%lx offset: %lu, size: %lu\n", paddr,
offset, filesz);
/* Feed any non-loaded parts to the hash function */
if (ph[i].type != ELF_PT_LOAD) {
len = filesz;
//wolfBoot_printf("Feeding ghost segment, len %d\n", len);
continue;
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, elf_h + offset, WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
paddr += WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, elf_h + offset, len);
break;
}
}
} else {
/* Feed the loaded parts to the hash function */
len = filesz;
wolfBoot_printf("Feeding stored segment, len %d\n", len);
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, (void *)(paddr + BASE_OFF),
WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
paddr += WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, (void *)(paddr + BASE_OFF),
len);
break;
}
}
}
/* Add padding until next program header, if any. */
if ((i < entry_count - 1) && (ph[i+1].offset > (offset + filesz))) {
unsigned long padding = ph[i+1].offset - (offset + filesz);
wolfBoot_printf("Adding padding: %lu\n", padding);
while (padding > 0) {
if (padding > PADDING_BLOCK_SIZE) {
update_hash(&ctx, padding_block, PADDING_BLOCK_SIZE);
padding -= PADDING_BLOCK_SIZE;
} else {
update_hash(&ctx, padding_block, padding);
break;
}
}
} else {
final_offset = offset + filesz;
}
}
}
if (final_offset < 0)
return -1;
if (final_offset + IMAGE_HEADER_SIZE > (long)boot.fw_size)
return -1;
len = boot.fw_size - final_offset;
p = boot.hdr + IMAGE_HEADER_SIZE + final_offset;
p = get_img_hdr(&boot) + IMAGE_HEADER_SIZE + final_offset;
wolfBoot_printf("Appending %d bytes of data from image, from position %lu...(0x%p)\n", len, IMAGE_HEADER_SIZE + final_offset, p);
while (len > 0) {
if (len > WOLFBOOT_SHA_BLOCK_SIZE) {
update_hash(&ctx, p, WOLFBOOT_SHA_BLOCK_SIZE);
len -= WOLFBOOT_SHA_BLOCK_SIZE;
p += WOLFBOOT_SHA_BLOCK_SIZE;
} else {
update_hash(&ctx, p, len);
break;
}
}
/* Finalize SHA calculation */
final_hash(&ctx, calc_digest);
if (memcmp(calc_digest, exp_digest, WOLFBOOT_SHA_DIGEST_SIZE) != 0) {
wolfBoot_printf("SHA failed for scattered ELF!\n");
wolfBoot_printf("Expected %02x%02x%02x%02x%02x%02x%02x%02x\n",
exp_digest[0], exp_digest[1], exp_digest[2], exp_digest[3],
exp_digest[4], exp_digest[5], exp_digest[6], exp_digest[7]);
wolfBoot_printf("Calculated %02x%02x%02x%02x%02x%02x%02x%02x\n",
calc_digest[0], calc_digest[1], calc_digest[2], calc_digest[3],
calc_digest[4], calc_digest[5], calc_digest[6], calc_digest[7]);
return -2;
}
wolfBoot_printf("Scattered ELF verified.\n");
return 0;
}
#undef BASE_OFF
#endif
#ifdef WOLFBOOT_NO_SIGN
/**
* @brief Verify the authenticity of the image using a digital signature.

View File

@ -38,6 +38,11 @@
int WP11_Library_Init(void);
#endif
/* Support for ELF scatter/gather format */
#ifdef WOLFBOOT_ELF_SCATTERED
#include "elf.h"
#endif
#ifdef RAM_CODE
#ifndef TARGET_rp2350
extern unsigned int _start_text;
@ -211,12 +216,34 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
# define TRAILER_OFFSET_WORDS 0
#endif
/**
* @brief Performs the final swap and erase operations during a secure update,
* ensuring that if power is lost during the update, the process can be resumed
* on next boot.
*
* This function handles the final phase of the three-way swap update process.
* It ensures that the update is atomic and power-fail safe by:
* 1. Saving the last sector of the boot partition to the swap area
* 2. Setting a magic trailer value to mark the swap as in progress
* 3. Erasing the last sector(s) of the boot partition
* 4. Restoring the saved sector from swap back to boot
* 5. Setting the boot partition state to TESTING
* 6. Erasing the last sector(s) of the update partition
*
* The function can be called in two modes:
* - Normal mode (resume=0): Initiates the swap and erase process
* - Resume mode (resume=1): Checks if a swap was interrupted and completes it
*
* @param resume If 1, checks for interrupted swap and resumes it; if 0, starts
* new swap
* @return 0 on success, negative value if no swap needed or on error
*/
static int wolfBoot_swap_and_final_erase(int resume)
{
struct wolfBoot_image boot[1];
struct wolfBoot_image update[1];
struct wolfBoot_image swap[1];
uint8_t st;
uint8_t updateState;
int eraseLen = (WOLFBOOT_SECTOR_SIZE
#ifdef NVM_FLASH_WRITEONCE /* need to erase the redundant sector too */
* 2
@ -231,7 +258,7 @@ static int wolfBoot_swap_and_final_erase(int resume)
wolfBoot_open_image(boot, PART_BOOT);
wolfBoot_open_image(update, PART_UPDATE);
wolfBoot_open_image(swap, PART_SWAP);
wolfBoot_get_partition_state(PART_UPDATE, &st);
wolfBoot_get_partition_state(PART_UPDATE, &updateState);
/* read trailer */
#if defined(EXT_FLASH) && PARTN_IS_EXT(PART_BOOT)
@ -247,7 +274,9 @@ static int wolfBoot_swap_and_final_erase(int resume)
swapDone = 1;
}
/* if resuming, quit if swap isn't done */
if ((resume == 1) && (swapDone == 0) && (st != IMG_STATE_FINAL_FLAGS)) {
if ((resume == 1) && (swapDone == 0) &&
(updateState != IMG_STATE_FINAL_FLAGS)
) {
return -1;
}
@ -257,7 +286,7 @@ static int wolfBoot_swap_and_final_erase(int resume)
#endif
/* IMG_STATE_FINAL_FLAGS allows re-entry without blowing away swap */
if (st != IMG_STATE_FINAL_FLAGS) {
if (updateState != IMG_STATE_FINAL_FLAGS) {
/* store the sector at tmpBootPos into swap */
wolfBoot_copy_sector(boot, swap, tmpBootPos / WOLFBOOT_SECTOR_SIZE);
/* set FINAL_SWAP for re-entry */
@ -291,9 +320,11 @@ static int wolfBoot_swap_and_final_erase(int resume)
else {
wb_flash_erase(boot, tmpBootPos, WOLFBOOT_SECTOR_SIZE);
}
/* mark boot as TESTING */
wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_TESTING);
/* erase the last sector(s) of update */
/* erase the last sector(s) of update. This resets the update partition state
* to IMG_STATE_NEW */
wb_flash_erase(update, WOLFBOOT_PARTITION_SIZE - eraseLen, eraseLen);
#ifdef EXT_FLASH
@ -784,6 +815,21 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
wolfBoot_swap_and_final_erase(0);
#else /* DISABLE_BACKUP */
#ifdef WOLFBOOT_ELF_SCATTERED
unsigned long entry;
void *base = (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
wolfBoot_printf("ELF Scattered image digest check\n");
if (elf_check_image_scattered(PART_BOOT, &entry) < 0) {
wolfBoot_printf("ELF Scattered image digest check: failed. Restoring scattered image...\n");
elf_store_image_scattered(base, &entry, PART_IS_EXT(boot));
if (elf_check_image_scattered(PART_BOOT, &entry) < 0) {
wolfBoot_printf("Fatal: Could not verify digest after scattering. Panic().\n");
wolfBoot_panic();
}
}
wolfBoot_printf("Scattered image correctly verified. Setting entry point to %lx\n", entry);
boot.fw_base = (void *)entry;
#endif
/* Direct Swap without power fail safety */
hal_flash_unlock();
@ -811,6 +857,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
wb_flash_erase(&boot, sector * sector_size, sector_size);
sector++;
}
wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_SUCCESS);
#ifdef EXT_FLASH
@ -1017,7 +1065,8 @@ void RAMFUNCTION wolfBoot_start(void)
/* Emergency update successful, try to re-open boot image */
if (likely(((wolfBoot_open_image(&boot, PART_BOOT) < 0) ||
(wolfBoot_verify_integrity(&boot) < 0) ||
(wolfBoot_verify_authenticity(&boot) < 0)))) {
(wolfBoot_verify_authenticity(&boot) < 0)
))) {
wolfBoot_printf("Boot (try 2) failed: Hdr %d, Hash %d, Sig %d\n",
boot.hdr_ok, boot.sha_ok, boot.signature_ok);
/* panic: something went wrong after the emergency update */
@ -1029,6 +1078,24 @@ void RAMFUNCTION wolfBoot_start(void)
}
}
PART_SANITY_CHECK(&boot);
#ifdef WOLFBOOT_ELF_SCATTERED
unsigned long entry;
void *base = (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS;
wolfBoot_printf("ELF Scattered image digest check\n");
if (elf_check_image_scattered(PART_BOOT, &entry) < 0) {
wolfBoot_printf("ELF Scattered image digest check: failed. Restoring scattered image...\n");
elf_store_image_scattered(base, &entry, PART_IS_EXT(boot));
if (elf_check_image_scattered(PART_BOOT, &entry) < 0) {
wolfBoot_printf("Fatal: Could not verify digest after scattering. Panic().\n");
wolfBoot_panic();
}
}
wolfBoot_printf("Scattered image correctly verified. Setting entry point to %lx\n", entry);
boot.fw_base = (void *)entry;
#endif
#ifdef WOLFBOOT_TPM
wolfBoot_tpm2_deinit();
#endif

View File

@ -271,7 +271,7 @@ backup_on_failure:
#ifdef WOLFBOOT_ELF
/* Load elf */
if (elf_load_image((uint8_t*)load_address, (uintptr_t*)&load_address) != 0){
if (elf_load_image_mmu((uint8_t*)load_address, (uintptr_t*)&load_address, NULL) != 0){
wolfBoot_printf("Invalid elf, falling back to raw binary\n");
}
#endif

View File

@ -227,7 +227,6 @@ ifeq ($(TARGET),ti_hercules)
endif
ifeq ($(TARGET),sim)
APP_OBJS=app_$(TARGET).o ../test-app/libwolfboot.o ../hal/$(TARGET).o
# LD on MacOS does not support "-Map="
LDMAPSUPPORTED=$(shell $(CC) -Wl,-Map=image.map 2>&1 | grep 'unknown option')
LDFLAGS=
@ -239,6 +238,15 @@ ifeq ($(TARGET),sim)
# Override linker flags
LDFLAGS+=-Wl,-Map=image.map
endif
ifeq ($(ELF_SCATTERED),1)
LSCRIPT_TEMPLATE=sim_scattered.ld
APP_OBJS=app_sim_scattered.o ../src/string.o
CFLAGS+=-D"WOLFBOOT_ELF_SCATTERED=1" -nostartfiles -ffreestanding -static -nostdlib
LDFLAGS+=-ffreestanding -nostartfiles -static -T$(LSCRIPT) -nostdlib
else
APP_OBJS=app_sim.o
APP_OBJS+=../test-app/libwolfboot.o ../hal/$(TARGET).o
endif
endif
ifeq ($(EXT_FLASH),1)

View File

@ -0,0 +1,49 @@
/* app_sim_scattered.c
*
* Test bare-metal boot-led-on application
*
* Copyright (C) 2025 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
*/
#include "target.h"
#include "wolfboot/wolfboot.h"
#ifdef TARGET_sim
__attribute__((section(".r3text")))
int do_cmd(const char *cmd)
{
/* Do nothing */
return 0;
}
__attribute__((section(".r2text")))
int do_exec_cmd(char *name)
{
return do_cmd(name);
}
__attribute__((section(".r1text")))
int main(int argc, char *argv[]) {
do_exec_cmd((void *)0);
return 0;
}
#endif /** TARGET_sim **/

View File

@ -0,0 +1,28 @@
ENTRY(main)
SECTIONS
{
. = 0x100000;
__r1_start = .;
.r1text : { *(.r1text) }
.r1data : { *(.r1data) }
__r1_end = .;
. = 0x140000;
__r2_start = .;
.r2text : { *(.r2text) }
.r2data : { *(.r2data) }
__r2_end = .;
. = 0x180000;
__r3_start = .;
.r3text : { *(.r3text) }
.r3data : { *(.r3data) }
.text : { *(.text*) }
.rodata : { *(.rodata*) }
__r3_end = .;
PROVIDE(__image_start = 0x100000);
PROVIDE(__image_end = .);
}

View File

@ -4,7 +4,7 @@
CC=gcc
CFLAGS=-Wall -g -ggdb
CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DPRINTF_ENABLED
CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DPRINTF_ENABLED -DMMU -DARCH_FLASH_OFFSET=0
EXE=elf-parser
LIBS=

View File

@ -70,7 +70,7 @@ int main(int argc, char *argv[])
fclose(f);
if (ret == 0) {
ret = elf_load_image(image, &entry);
ret = elf_load_image_mmu(image, &entry, NULL);
}
printf("Return %d, Load %p\n", ret, (void*)entry);