mirror of https://github.com/wolfSSL/wolfBoot.git
Merge pull request #562 from danielinux/update-flash-elf
Scatter/gather ELF files according to segments `paddr`pull/568/head
commit
60b208e5e1
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
|
||||
jobs:
|
||||
renode_automated_fastmath:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
|
||||
jobs:
|
||||
renode_automated_noasm:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
|
||||
jobs:
|
||||
renode_automated_base:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
|
||||
jobs:
|
||||
renode_automated_smallstack:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
6
arch.mk
6
arch.mk
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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--;
|
||||
|
|
26
hal/sim.c
26
hal/sim.c
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
164
src/elf.c
|
@ -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 */
|
||||
|
|
431
src/image.c
431
src/image.c
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 **/
|
|
@ -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 = .);
|
||||
}
|
|
@ -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=
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue