mirror of https://github.com/wolfSSL/wolfBoot.git
add asymmetric partition sizing for monolithic updates
parent
d42109c843
commit
25aa151f0b
2
Makefile
2
Makefile
|
|
@ -302,6 +302,7 @@ endif
|
|||
# Environment variables for sign tool
|
||||
SIGN_ENV=IMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) \
|
||||
WOLFBOOT_PARTITION_SIZE=$(WOLFBOOT_PARTITION_SIZE) \
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE=$(WOLFBOOT_PARTITION_UPDATE_SIZE) \
|
||||
WOLFBOOT_SECTOR_SIZE=$(WOLFBOOT_SECTOR_SIZE) \
|
||||
NVM_FLASH_WRITEONCE=$(NVM_FLASH_WRITEONCE) \
|
||||
ML_DSA_LEVEL=$(ML_DSA_LEVEL) \
|
||||
|
|
@ -760,6 +761,7 @@ distclean: clean keysclean utilsclean
|
|||
include/target.h: $(TARGET_H_TEMPLATE) FORCE
|
||||
$(Q)cat $(TARGET_H_TEMPLATE) | \
|
||||
sed -e "s/@WOLFBOOT_PARTITION_SIZE@/$(WOLFBOOT_PARTITION_SIZE)/g" | \
|
||||
sed -e "s|@WOLFBOOT_PARTITION_UPDATE_SIZE_DEFINE@|$(if $(strip $(WOLFBOOT_PARTITION_UPDATE_SIZE)),#define WOLFBOOT_PARTITION_UPDATE_SIZE $(WOLFBOOT_PARTITION_UPDATE_SIZE),/* WOLFBOOT_PARTITION_UPDATE_SIZE not set */)|g" | \
|
||||
sed -e "s/@WOLFBOOT_SECTOR_SIZE@/$(WOLFBOOT_SECTOR_SIZE)/g" | \
|
||||
sed -e "s/@WOLFBOOT_NSC_ADDRESS@/$(WOLFBOOT_NSC_ADDRESS)/g" | \
|
||||
sed -e "s/@WOLFBOOT_NSC_SIZE@/$(WOLFBOOT_NSC_SIZE)/g" | \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
ARCH?=AURIX_TC3
|
||||
TARGET?=aurix_tc3xx
|
||||
AURIX_TC3_HSM=1
|
||||
SIGN?=RSA4096
|
||||
HASH?=SHA256
|
||||
DEBUG?=0
|
||||
WOLFBOOT_VERSION?=1
|
||||
V?=0
|
||||
SPMATH?=1
|
||||
RAM_CODE?=1
|
||||
SELF_UPDATE_MONOLITHIC=1
|
||||
EXT_FLASH?=1
|
||||
EXT_BOOT=1
|
||||
EXT_UPDATE=1
|
||||
EXT_SWAP=1
|
||||
FLAGS_INVERT=1
|
||||
FLASH_MULTI_SECTOR_ERASE=1
|
||||
DEBUG_UART=1
|
||||
PRINTF_ENABLED=1
|
||||
WOLFBOOT_IMG_HASH_ONESHOT=1
|
||||
|
||||
# wolfHSM options
|
||||
WOLFHSM_SERVER=1
|
||||
|
||||
# Cert chain options
|
||||
CERT_CHAIN_VERIFY=1
|
||||
|
||||
# RSA4096 cert chains need the larger header and stack
|
||||
WOLFBOOT_HUGE_STACK=1
|
||||
IMAGE_HEADER_SIZE=4096
|
||||
|
||||
# self-header feature (persist header in external flash)
|
||||
WOLFBOOT_SELF_HEADER=1
|
||||
SELF_HEADER_EXT=1
|
||||
|
||||
# Asymmetric monolithic layout: BOOT (0x28000) only holds the app; UPDATE
|
||||
# (0x38000) stages the monolithic payload. UPDATE matches the install span
|
||||
# (bootloader region 0x10000 + BOOT 0x28000), so staging overhead
|
||||
# (IMAGE_HEADER_SIZE plus one trailer sector) comes out of the app's
|
||||
# share; see "Independent partition sizing" in docs/firmware_update.md.
|
||||
# No SWAP partition in monolithic mode; 0 marks it not present.
|
||||
ARCH_FLASH_OFFSET=0x80028000
|
||||
WOLFBOOT_SECTOR_SIZE=0x4000
|
||||
WOLFBOOT_PARTITION_SIZE=0x28000
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE=0x38000
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80038000
|
||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80060000
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS=0
|
||||
WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS=0x8009C000
|
||||
|
|
@ -9,12 +9,16 @@ RAM_CODE=1
|
|||
SELF_UPDATE_MONOLITHIC=1
|
||||
WOLFBOOT_VERSION=1
|
||||
|
||||
# Partition size 512KB so the monolithic payload (bootloader region + app)
|
||||
# fits in the UPDATE partition.
|
||||
WOLFBOOT_PARTITION_SIZE=0x80000
|
||||
# Asymmetric layout: BOOT only holds the app; UPDATE stages the monolithic
|
||||
# payload. UPDATE (0x80000) matches the install span (bootloader region
|
||||
# 0x20000 + BOOT 0x60000), so staging overhead (IMAGE_HEADER_SIZE plus one
|
||||
# trailer sector) comes out of the app's share; see "Independent partition
|
||||
# sizing" in docs/firmware_update.md.
|
||||
WOLFBOOT_PARTITION_SIZE=0x60000
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE=0x80000
|
||||
WOLFBOOT_SECTOR_SIZE=0x1000
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
|
||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0xA0000
|
||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80000
|
||||
|
||||
# required for keytools
|
||||
WOLFBOOT_FIXED_PARTITIONS=1
|
||||
|
|
|
|||
|
|
@ -100,7 +100,19 @@ of its addressable space.
|
|||
|
||||
- `WOLFBOOT_PARTITION_SIZE`
|
||||
|
||||
The size of the BOOT and UPDATE partition. The size is the same for both partitions.
|
||||
The size of the BOOT and UPDATE partitions. The size is the same for both partitions unless using the monolithic
|
||||
self-update mode, in which case the UPDATE partition can optionally be sized independently.
|
||||
|
||||
- `WOLFBOOT_PARTITION_UPDATE_SIZE`
|
||||
|
||||
Optional. Sizes the UPDATE partition independently of BOOT; defaults to
|
||||
`WOLFBOOT_PARTITION_SIZE`. A different value is only allowed together with
|
||||
`SELF_UPDATE_MONOLITHIC=1`, so the UPDATE partition can stage a monolithic
|
||||
payload (bootloader region + application) without inflating the BOOT
|
||||
partition. The staged payload also needs `IMAGE_HEADER_SIZE` plus one
|
||||
trailer sector of room on top — see the sizing guide in
|
||||
[firmware_update.md](firmware_update.md#independent-partition-sizing).
|
||||
Not supported with `ENCRYPT` or `PULL_LINKER_DEFINES`.
|
||||
|
||||
## Bootloader features
|
||||
|
||||
|
|
|
|||
|
|
@ -274,11 +274,111 @@ partition.
|
|||
|
||||
- **Payload must fit in the UPDATE partition.** The signed monolithic
|
||||
image (header + bootloader + signed application) plus the 5-byte
|
||||
`pBOOT` trailer must not exceed `WOLFBOOT_PARTITION_SIZE`.
|
||||
`pBOOT` trailer must not exceed the UPDATE partition size
|
||||
(`WOLFBOOT_PARTITION_SIZE`, or `WOLFBOOT_PARTITION_UPDATE_SIZE` when
|
||||
set — see below). When the update is triggered with
|
||||
`wolfBoot_update_trigger()`, the trigger erases the whole last sector
|
||||
of the UPDATE partition, so the staged payload must also leave that
|
||||
sector free.
|
||||
|
||||
- **Payload must not reach the BOOT trailer sector when installed.** The
|
||||
installed span (`fw_size` bytes written at `ARCH_FLASH_OFFSET`) must
|
||||
not exceed the bootloader region plus the BOOT partition minus the
|
||||
BOOT partition's last sector, which is reserved for the partition
|
||||
state trailer (and, with `FLAGS_HOME`, the UPDATE partition flags).
|
||||
wolfBoot rejects larger payloads before erasing anything.
|
||||
|
||||
##### Independent partition sizing
|
||||
|
||||
In monolithic mode the BOOT partition only ever holds the application,
|
||||
but the UPDATE partition has to stage the whole payload (bootloader
|
||||
region + application). By default both partitions share
|
||||
`WOLFBOOT_PARTITION_SIZE`, which forces BOOT to be as large as the
|
||||
payload. Set `WOLFBOOT_PARTITION_UPDATE_SIZE` to size the UPDATE
|
||||
partition independently and keep BOOT small:
|
||||
|
||||
```
|
||||
WOLFBOOT_PARTITION_SIZE=0x60000 # BOOT: just the application slot
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE=0x80000 # UPDATE: bootloader region + BOOT
|
||||
```
|
||||
|
||||
###### Sizing the UPDATE partition
|
||||
|
||||
Just like with a regular application update, a staged monolithic update needs
|
||||
more room than the installed payload, because two extra regions share the
|
||||
UPDATE partition with it:
|
||||
|
||||
```
|
||||
UPDATE partition layout while an update is staged
|
||||
(total size = WOLFBOOT_PARTITION_UPDATE_SIZE):
|
||||
|
||||
+---------------------+--------------------------------+----------------+
|
||||
| signed image header | payload: bootloader region | trailer sector |
|
||||
| (IMAGE_HEADER_SIZE) | + application image | (last sector) |
|
||||
+---------------------+--------------------------------+----------------+
|
||||
```
|
||||
|
||||
- **Signed image header** (`IMAGE_HEADER_SIZE`): the signing tool
|
||||
prepends the signed manifest to the payload. It is not part of the
|
||||
installed span (with `WOLFBOOT_SELF_HEADER` it is persisted
|
||||
separately), but it occupies staging space while the update is
|
||||
pending.
|
||||
- **Trailer sector** (one `WOLFBOOT_SECTOR_SIZE`): the last sector of
|
||||
the partition holds the partition state trailer, and
|
||||
`wolfBoot_update_trigger()` erases the whole sector when arming the
|
||||
update. The staged image must not extend into it.
|
||||
|
||||
The largest payload that can be staged is therefore:
|
||||
|
||||
```
|
||||
max_staged_payload = WOLFBOOT_PARTITION_UPDATE_SIZE
|
||||
- IMAGE_HEADER_SIZE - WOLFBOOT_SECTOR_SIZE
|
||||
```
|
||||
|
||||
while the largest payload that can be installed (the install span:
|
||||
bootloader region plus BOOT partition, minus BOOT's own trailer
|
||||
sector) is:
|
||||
|
||||
```
|
||||
max_install = (WOLFBOOT_PARTITION_BOOT_ADDRESS - ARCH_FLASH_OFFSET)
|
||||
+ WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE
|
||||
```
|
||||
|
||||
The last sector of the BOOT partition is reserved for the partition
|
||||
state trailer (with `FLAGS_HOME` it also holds the UPDATE partition
|
||||
flags, and `wolfBoot_update_trigger()` erases the whole sector), so
|
||||
wolfBoot's oversize check rejects any payload that would reach it.
|
||||
|
||||
To be able to deliver any payload the install span allows, including
|
||||
an application as large as the BOOT partition can hold, size the
|
||||
UPDATE partition so that `max_staged_payload >= max_install`:
|
||||
|
||||
```
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE >=
|
||||
(WOLFBOOT_PARTITION_BOOT_ADDRESS - ARCH_FLASH_OFFSET)
|
||||
+ WOLFBOOT_PARTITION_SIZE + IMAGE_HEADER_SIZE
|
||||
```
|
||||
|
||||
(the UPDATE trailer sector and the BOOT trailer sector cancel out:
|
||||
staging reserves one extra sector, installing needs one less.)
|
||||
|
||||
Notes:
|
||||
|
||||
- Only valid together with `SELF_UPDATE_MONOLITHIC=1`; the swap-based
|
||||
update modes require equal-size partitions and fail to compile
|
||||
otherwise.
|
||||
- Not supported with `ENCRYPT` or `PULL_LINKER_DEFINES`.
|
||||
- The partition state trailer sits at the end of the (now larger) UPDATE
|
||||
partition (with `FLAGS_HOME` it stays at the end of the BOOT
|
||||
partition), so the bootloader and the application must be built from
|
||||
the same configuration to agree on its location.
|
||||
|
||||
##### Simulator test
|
||||
|
||||
A simulator test is provided in `tools/test.mk` to exercise this use case:
|
||||
A simulator test is provided in `tools/test.mk` to exercise this use case.
|
||||
The example config uses the asymmetric layout shown above: the UPDATE
|
||||
partition is sized for the monolithic payload while BOOT stays
|
||||
application-sized:
|
||||
|
||||
```
|
||||
cp config/examples/sim-self-update-monolithic.config .config
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ For this reason, before proceeding with partitioning on a target system, the
|
|||
following aspects must be considered:
|
||||
|
||||
- BOOT partition and UPDATE partition must have the same size, and be able to contain the running system
|
||||
- exception: in monolithic self-update mode the UPDATE partition may be larger than BOOT, see
|
||||
`WOLFBOOT_PARTITION_UPDATE_SIZE` in [firmware_update.md](firmware_update.md#independent-partition-sizing)
|
||||
- SWAP partition must be as big as the largest sector in both BOOT and UPDATE partition.
|
||||
|
||||
The flash memory of the target is partitioned into the following areas:
|
||||
|
|
@ -20,7 +22,8 @@ The flash memory of the target is partitioned into the following areas:
|
|||
- Bootloader partition, at the beginning of the flash, generally very small (16-32KB)
|
||||
- Primary slot (BOOT partition) starting at address `WOLFBOOT_PARTITION_BOOT_ADDRESS`
|
||||
- Secondary slot (UPDATE partition) starting at address `WOLFBOOT_PARTITION_UPDATE_ADDRESS`
|
||||
- both partitions share the same size, defined as `WOLFBOOT_PARTITION_SIZE`
|
||||
- both partitions share the same size, defined as `WOLFBOOT_PARTITION_SIZE` (unless
|
||||
`WOLFBOOT_PARTITION_UPDATE_SIZE` is set, only allowed in monolithic self-update mode)
|
||||
- Swapping space (SWAP partition) starting at address `WOLFBOOT_PARTITION_SWAP_ADDRESS`
|
||||
- the swap space size is defined as `WOLFBOOT_SECTOR_SIZE` and must be as big as the
|
||||
largest sector used in either BOOT/UPDATE partitions.
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ EOF
|
|||
```
|
||||
|
||||
Change `WOLFBOOT_PARTITION_SIZE` accordingly. `wolfBoot_open_image_address()` will discard images larger than
|
||||
`WOLFBOOT_PARTITION_SIZE` - `IMAGE_HEADER_SIZE`.
|
||||
the target slot size (`WOLFBOOT_PARTITION_SIZE`, or `WOLFBOOT_PARTITION_UPDATE_SIZE` for the update slot)
|
||||
minus `IMAGE_HEADER_SIZE`.
|
||||
|
||||
|
||||
Step 3: compile keytools and create keys.
|
||||
|
|
|
|||
|
|
@ -95,6 +95,15 @@
|
|||
#ifndef WOLFBOOT_PARTITION_SIZE
|
||||
#define WOLFBOOT_PARTITION_SIZE @WOLFBOOT_PARTITION_SIZE@
|
||||
#endif
|
||||
/* Optional independently sized UPDATE partition (requires
|
||||
* WOLFBOOT_SELF_UPDATE_MONOLITHIC when different from
|
||||
* WOLFBOOT_PARTITION_SIZE) */
|
||||
#ifndef WOLFBOOT_PARTITION_UPDATE_SIZE
|
||||
@WOLFBOOT_PARTITION_UPDATE_SIZE_DEFINE@
|
||||
#endif
|
||||
#ifndef WOLFBOOT_PARTITION_UPDATE_SIZE
|
||||
#define WOLFBOOT_PARTITION_UPDATE_SIZE WOLFBOOT_PARTITION_SIZE
|
||||
#endif
|
||||
#ifdef WOLFBOOT_SELF_HEADER
|
||||
#if defined(WOLFBOOT_PART_USE_ARCH_OFFSET)
|
||||
#if !defined(EXT_FLASH) || (defined(EXT_FLASH) && !defined(WOLFBOOT_SELF_HEADER_EXT))
|
||||
|
|
@ -122,7 +131,7 @@
|
|||
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0) > \
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0)) && \
|
||||
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0) < \
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0))
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_UPDATE_SIZE + 0))
|
||||
#error "Boot and update partitions overlap"
|
||||
#endif
|
||||
|
||||
|
|
@ -138,7 +147,7 @@
|
|||
#if !defined(PART_UPDATE_EXT) && !defined(PART_SWAP_EXT) && \
|
||||
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0) != 0) && \
|
||||
((WOLFBOOT_PARTITION_SWAP_ADDRESS + 0) != 0) && \
|
||||
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0) > \
|
||||
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_UPDATE_SIZE + 0) > \
|
||||
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0)) && \
|
||||
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0) < \
|
||||
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0 + WOLFBOOT_SECTOR_SIZE))
|
||||
|
|
@ -173,7 +182,7 @@
|
|||
WOLFBOOT_DIAGNOSTICS_SECTORS * WOLFBOOT_SECTOR_SIZE) > \
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0)) && \
|
||||
((WOLFBOOT_DIAGNOSTICS_ADDRESS + 0) < \
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0))
|
||||
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_UPDATE_SIZE + 0))
|
||||
#error "Diagnostics region overlaps the update partition"
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -547,6 +547,21 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* The UPDATE partition may be sized independently of BOOT, but only in
|
||||
* monolithic self-update mode: the swap-based update machinery requires
|
||||
* equal-size partitions. Defaults to the symmetric layout. */
|
||||
#ifndef WOLFBOOT_PARTITION_UPDATE_SIZE
|
||||
#define WOLFBOOT_PARTITION_UPDATE_SIZE WOLFBOOT_PARTITION_SIZE
|
||||
#endif
|
||||
#if !defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && \
|
||||
((WOLFBOOT_PARTITION_UPDATE_SIZE + 0) != (WOLFBOOT_PARTITION_SIZE + 0))
|
||||
#error "WOLFBOOT_PARTITION_UPDATE_SIZE != WOLFBOOT_PARTITION_SIZE requires SELF_UPDATE_MONOLITHIC=1"
|
||||
#endif
|
||||
#if defined(EXT_ENCRYPTED) && \
|
||||
((WOLFBOOT_PARTITION_UPDATE_SIZE + 0) != (WOLFBOOT_PARTITION_SIZE + 0))
|
||||
#error "Asymmetric WOLFBOOT_PARTITION_UPDATE_SIZE is not supported with ENCRYPT"
|
||||
#endif
|
||||
|
||||
#if defined(DISABLE_BACKUP) && defined(DELTA_UPDATES)
|
||||
#error "DELTA_UPDATES requires swap partition (incompatible with DISABLE_BACKUP)"
|
||||
#endif
|
||||
|
|
|
|||
28
src/image.c
28
src/image.c
|
|
@ -1482,6 +1482,11 @@ uint32_t wolfBoot_image_size(uint8_t *image)
|
|||
int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image)
|
||||
{
|
||||
uint32_t *magic = (uint32_t *)(image);
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
/* The UPDATE slot may be larger than BOOT (monolithic self-update) */
|
||||
uint32_t part_size = (img->part == PART_UPDATE) ?
|
||||
WOLFBOOT_PARTITION_UPDATE_SIZE : WOLFBOOT_PARTITION_SIZE;
|
||||
#endif
|
||||
if (*magic != WOLFBOOT_MAGIC) {
|
||||
wolfBoot_printf("Partition %d header magic 0x%08x invalid at %p\n",
|
||||
img->part, (unsigned int)*magic, img->hdr);
|
||||
|
|
@ -1490,17 +1495,17 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image)
|
|||
img->fw_size = wolfBoot_image_size(image);
|
||||
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
if (img->fw_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
|
||||
if (img->fw_size > (part_size - IMAGE_HEADER_SIZE)) {
|
||||
wolfBoot_printf("Image size %u > max %u\n",
|
||||
(unsigned int)img->fw_size,
|
||||
(unsigned int)(WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE));
|
||||
img->fw_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
|
||||
(unsigned int)(part_size - IMAGE_HEADER_SIZE));
|
||||
img->fw_size = part_size - IMAGE_HEADER_SIZE;
|
||||
return -1;
|
||||
}
|
||||
if (!img->hdr_ok) {
|
||||
img->hdr = image;
|
||||
}
|
||||
img->trailer = img->hdr + WOLFBOOT_PARTITION_SIZE;
|
||||
img->trailer = img->hdr + part_size;
|
||||
#else
|
||||
#ifdef WOLFBOOT_RAMBOOT_MAX_SIZE
|
||||
if (img->fw_size > WOLFBOOT_RAMBOOT_MAX_SIZE) {
|
||||
|
|
@ -1792,10 +1797,25 @@ int wolfBoot_open_self_address(struct wolfBoot_image* img, uint8_t* hdr,
|
|||
img->hdr = hdr;
|
||||
img->fw_size = wolfBoot_image_size(hdr);
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
#ifdef WOLFBOOT_SELF_UPDATE_MONOLITHIC
|
||||
/* A monolithic self image spans the bootloader region and the BOOT
|
||||
* partition minus its trailer sector (header persisted separately,
|
||||
* not part of the span) */
|
||||
{
|
||||
uint32_t max_span = (uint32_t)(WOLFBOOT_PARTITION_BOOT_ADDRESS -
|
||||
ARCH_FLASH_OFFSET) + WOLFBOOT_PARTITION_SIZE -
|
||||
WOLFBOOT_SECTOR_SIZE;
|
||||
if (img->fw_size > max_span) {
|
||||
img->fw_size = max_span;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (img->fw_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
|
||||
img->fw_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
wolfBoot_image_set_fw_base(img, image);
|
||||
img->part = PART_SELF;
|
||||
|
|
|
|||
|
|
@ -138,9 +138,15 @@ int wolfBoot_initialize_encryption(void)
|
|||
|
||||
|
||||
|
||||
/* Despite the name, ENCRYPT_TMP_SECRET_OFFSET* set the end-of-partition
|
||||
* trailer position for all builds (PART_*_ENDFLAGS derive from them); only
|
||||
* encrypted builds also keep the tmp key/nonce there. */
|
||||
#if defined(EXT_FLASH) && defined(EXT_ENCRYPTED)
|
||||
#define ENCRYPT_TMP_SECRET_OFFSET (WOLFBOOT_PARTITION_SIZE - \
|
||||
(TRAILER_SKIP + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE))
|
||||
/* Same trailer layout at the end of the (possibly larger) UPDATE slot */
|
||||
#define ENCRYPT_TMP_SECRET_OFFSET_UPDATE (WOLFBOOT_PARTITION_UPDATE_SIZE - \
|
||||
(TRAILER_SKIP + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE))
|
||||
#define TRAILER_OVERHEAD (4 + 1 + (WOLFBOOT_PARTITION_SIZE / \
|
||||
(2 * WOLFBOOT_SECTOR_SIZE)))
|
||||
/* MAGIC (4B) + PART_FLAG (1B) + (N_SECTORS / 2) */
|
||||
|
|
@ -150,6 +156,8 @@ int wolfBoot_initialize_encryption(void)
|
|||
/* MAGIC (4B) + PART_FLAG (1B) + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE */
|
||||
#else
|
||||
#define ENCRYPT_TMP_SECRET_OFFSET (WOLFBOOT_PARTITION_SIZE - (TRAILER_SKIP))
|
||||
#define ENCRYPT_TMP_SECRET_OFFSET_UPDATE \
|
||||
(WOLFBOOT_PARTITION_UPDATE_SIZE - (TRAILER_SKIP))
|
||||
#define SECTOR_FLAGS_SIZE (WOLFBOOT_SECTOR_SIZE - (4 + 1))
|
||||
/* MAGIC (4B) + PART_FLAG (1B) */
|
||||
#endif /* EXT_FLASH && EXT_ENCRYPTED */
|
||||
|
|
@ -232,7 +240,7 @@ static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
|
|||
#define FLAGS_UPDATE_EXT() PARTN_IS_EXT(PART_BOOT)
|
||||
#else
|
||||
/* FLAGS are at the end of each partition */
|
||||
#define PART_UPDATE_ENDFLAGS (WOLFBOOT_PARTITION_UPDATE_ADDRESS + ENCRYPT_TMP_SECRET_OFFSET)
|
||||
#define PART_UPDATE_ENDFLAGS (WOLFBOOT_PARTITION_UPDATE_ADDRESS + ENCRYPT_TMP_SECRET_OFFSET_UPDATE)
|
||||
#define FLAGS_UPDATE_EXT() PARTN_IS_EXT(PART_UPDATE)
|
||||
#endif
|
||||
|
||||
|
|
@ -828,7 +836,7 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
|
|||
break;
|
||||
case PART_UPDATE:
|
||||
address = (uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
size = WOLFBOOT_PARTITION_SIZE;
|
||||
size = WOLFBOOT_PARTITION_UPDATE_SIZE;
|
||||
break;
|
||||
case PART_SWAP:
|
||||
address = (uintptr_t)WOLFBOOT_PARTITION_SWAP_ADDRESS;
|
||||
|
|
@ -2583,7 +2591,7 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a)
|
|||
(a >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
|
||||
#endif
|
||||
#endif
|
||||
(a < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE))
|
||||
(a < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_UPDATE_SIZE))
|
||||
return PART_UPDATE;
|
||||
if ( 1 &&
|
||||
#if !defined(WOLFBOOT_PART_USE_ARCH_OFFSET) && !defined(PULL_LINKER_DEFINES)
|
||||
|
|
@ -2980,9 +2988,9 @@ int wolfBoot_nsc_erase_update(uint32_t address, uint32_t len)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (address > WOLFBOOT_PARTITION_SIZE)
|
||||
if (address > WOLFBOOT_PARTITION_UPDATE_SIZE)
|
||||
return -1;
|
||||
if (len > WOLFBOOT_PARTITION_SIZE - address)
|
||||
if (len > WOLFBOOT_PARTITION_UPDATE_SIZE - address)
|
||||
return -1;
|
||||
|
||||
#ifdef PART_UPDATE_EXT
|
||||
|
|
@ -3002,9 +3010,9 @@ int wolfBoot_nsc_write_update(uint32_t address, const uint8_t *buf, uint32_t len
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (address > WOLFBOOT_PARTITION_SIZE)
|
||||
if (address > WOLFBOOT_PARTITION_UPDATE_SIZE)
|
||||
return -1;
|
||||
if (len > WOLFBOOT_PARTITION_SIZE - address)
|
||||
if (len > WOLFBOOT_PARTITION_UPDATE_SIZE - address)
|
||||
return -1;
|
||||
if (len > 0 && WOLFBOOT_NSC_NS_RW(buf, len) == NULL)
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -236,6 +236,18 @@ void RAMFUNCTION wolfBoot_check_self_update(void)
|
|||
wolfBoot_erase_partition(PART_UPDATE);
|
||||
return;
|
||||
}
|
||||
#ifdef WOLFBOOT_SELF_UPDATE_MONOLITHIC
|
||||
/* Payload installs at ARCH_FLASH_OFFSET and may spill into the BOOT
|
||||
* partition, but must never reach BOOT's last sector (reserved for
|
||||
* the state trailer) or the UPDATE partition staging it */
|
||||
if (update.fw_size > (uint32_t)(WOLFBOOT_PARTITION_BOOT_ADDRESS -
|
||||
ARCH_FLASH_OFFSET) + WOLFBOOT_PARTITION_SIZE -
|
||||
WOLFBOOT_SECTOR_SIZE) {
|
||||
wolfBoot_printf("Self update image too large: %u\n",
|
||||
(unsigned int)update.fw_size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (wolfBoot_verify_integrity(&update) < 0) {
|
||||
#ifdef WOLFBOOT_PERSIST_FAILURE_STATUS
|
||||
wolfBoot_record_verify_failure(WOLFBOOT_FAILURE_PHASE_SELF_UPDATE,
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
|
|||
sed -e "s/@WOLFBOOT_DTS_UPDATE_ADDRESS@/$(WOLFBOOT_DTS_UPDATE_ADDRESS)/g" | \
|
||||
sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \
|
||||
sed -e "s/@WOLFBOOT_LOAD_DTS_ADDRESS@/$(WOLFBOOT_LOAD_DTS_ADDRESS)/g" | \
|
||||
sed -e "s|@WOLFBOOT_PARTITION_UPDATE_SIZE_DEFINE@|$(if $(strip $(WOLFBOOT_PARTITION_UPDATE_SIZE)),#define WOLFBOOT_PARTITION_UPDATE_SIZE $(WOLFBOOT_PARTITION_UPDATE_SIZE),/* WOLFBOOT_PARTITION_UPDATE_SIZE not set */)|g" | \
|
||||
sed -e "s|@WOLFBOOT_RAMBOOT_MAX_SIZE_DEFINE@|$(if $(strip $(WOLFBOOT_RAMBOOT_MAX_SIZE)),#define WOLFBOOT_RAMBOOT_MAX_SIZE $(WOLFBOOT_RAMBOOT_MAX_SIZE),/* WOLFBOOT_RAMBOOT_MAX_SIZE undefined */)|g" \
|
||||
> $@
|
||||
|
||||
|
|
|
|||
|
|
@ -1947,6 +1947,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
pos += read_sz;
|
||||
}
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
if (ret == 0) {
|
||||
wc_Sha256Final(&sha, digest);
|
||||
digest_sz = HDR_SHA256_LEN;
|
||||
|
|
@ -2023,6 +2024,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
pos += read_sz;
|
||||
}
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
if (ret == 0) {
|
||||
wc_Sha384Final(&sha, digest);
|
||||
digest_sz = HDR_SHA384_LEN;
|
||||
|
|
@ -2097,6 +2099,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
pos += read_sz;
|
||||
}
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
if (ret == 0) {
|
||||
ret = wc_Sha3_384_Final(&sha, digest);
|
||||
digest_sz = HDR_SHA3_384_LEN;
|
||||
|
|
@ -2311,8 +2314,18 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
|
||||
/* Check if signed image fits in partition */
|
||||
{
|
||||
const char *psize_name = "WOLFBOOT_PARTITION_SIZE";
|
||||
const char *env_psize = getenv("WOLFBOOT_PARTITION_SIZE");
|
||||
const char *env_ssize = getenv("WOLFBOOT_SECTOR_SIZE");
|
||||
if (CMD.self_update) {
|
||||
/* self-update images are staged in the UPDATE partition, which
|
||||
* may be larger than BOOT (monolithic self-update) */
|
||||
const char *env_usize = getenv("WOLFBOOT_PARTITION_UPDATE_SIZE");
|
||||
if (env_usize && *env_usize) {
|
||||
env_psize = env_usize;
|
||||
psize_name = "WOLFBOOT_PARTITION_UPDATE_SIZE";
|
||||
}
|
||||
}
|
||||
if (env_psize && *env_psize) {
|
||||
char *endptr;
|
||||
unsigned long tmp;
|
||||
|
|
@ -2325,8 +2338,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
tmp = strtoul(env_psize, &endptr, 0);
|
||||
if (endptr == env_psize || *endptr != '\0' ||
|
||||
errno == ERANGE || tmp == 0 || tmp > UINT32_MAX) {
|
||||
printf("Error: Invalid WOLFBOOT_PARTITION_SIZE '%s'\n",
|
||||
env_psize);
|
||||
printf("Error: Invalid %s '%s'\n", psize_name, env_psize);
|
||||
ret = -1;
|
||||
goto failure;
|
||||
}
|
||||
partition_sz = (uint32_t)tmp;
|
||||
|
|
@ -2338,6 +2351,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
errno == ERANGE || tmp == 0 || tmp > UINT32_MAX) {
|
||||
printf("Error: Invalid WOLFBOOT_SECTOR_SIZE '%s'\n",
|
||||
env_ssize);
|
||||
ret = -1;
|
||||
goto failure;
|
||||
}
|
||||
sector_sz = (uint32_t)tmp;
|
||||
|
|
@ -2359,17 +2373,18 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz,
|
|||
if (total_img_sz > max_img_sz) {
|
||||
if (sector_sz < partition_sz) {
|
||||
printf("Error: Image size %u (header %u + firmware %u) "
|
||||
"exceeds max %u (partition %u - %d x sector %u)\n",
|
||||
"exceeds max %u (%s %u - %d x sector %u)\n",
|
||||
total_img_sz, CMD.header_sz, image_sz,
|
||||
max_img_sz, partition_sz,
|
||||
max_img_sz, psize_name, partition_sz,
|
||||
nvm_writeonce ? 2 : 1,
|
||||
sector_sz);
|
||||
} else {
|
||||
printf("Error: Image size %u (header %u + firmware %u) "
|
||||
"exceeds max %u (partition %u)\n",
|
||||
"exceeds max %u (%s %u)\n",
|
||||
total_img_sz, CMD.header_sz, image_sz,
|
||||
max_img_sz, partition_sz);
|
||||
max_img_sz, psize_name, partition_sz);
|
||||
}
|
||||
ret = -1;
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,9 +279,9 @@ test-sim-self-update-monolithic: wolfboot.bin test-app/image_v1_signed.bin FORCE
|
|||
@# Sign monolithic payload as wolfBoot self-update v2
|
||||
$(Q)$(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) --wolfboot-update monolithic_payload.bin $(PRIVATE_KEY) 2
|
||||
@# Create update partition with signed monolithic image and "pBOOT" trailer
|
||||
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
|
||||
$(Q)dd if=/dev/zero bs=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE),$(WOLFBOOT_PARTITION_SIZE)))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
|
||||
$(Q)dd if=monolithic_payload_v2_signed.bin of=update_part.dd bs=1 conv=notrunc
|
||||
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(WOLFBOOT_PARTITION_SIZE) - 5)) conv=notrunc
|
||||
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE),$(WOLFBOOT_PARTITION_SIZE)) - 5)) conv=notrunc
|
||||
@# Create erased boot partition
|
||||
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > boot_part.dd
|
||||
@# Assemble flash: wolfboot.bin at 0, empty boot partition, update partition
|
||||
|
|
@ -315,9 +315,9 @@ test-sim-self-update-monolithic-self-header: wolfboot.bin test-app/image_v1_sign
|
|||
$(Q)$(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) --wolfboot-update monolithic_payload.bin $(PRIVATE_KEY) 2
|
||||
$(Q)$(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) --wolfboot-update --header-only monolithic_payload.bin $(PRIVATE_KEY) 2
|
||||
@# Create update partition with signed monolithic image and "pBOOT" trailer
|
||||
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
|
||||
$(Q)dd if=/dev/zero bs=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE),$(WOLFBOOT_PARTITION_SIZE)))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
|
||||
$(Q)dd if=monolithic_payload_v2_signed.bin of=update_part.dd bs=1 conv=notrunc
|
||||
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(WOLFBOOT_PARTITION_SIZE) - 5)) conv=notrunc
|
||||
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE),$(WOLFBOOT_PARTITION_SIZE)) - 5)) conv=notrunc
|
||||
@# Create erased boot partition and self-header sector
|
||||
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > boot_part.dd
|
||||
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_SECTOR_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > self_hdr.dd
|
||||
|
|
|
|||
Loading…
Reference in New Issue