Skip to content

Commit 8577188

Browse files
authored
Merge pull request #663 from bigbrett/sim-self-update
basic simulator self-update test
2 parents 4ff0e0a + e31755b commit 8577188

File tree

6 files changed

+182
-0
lines changed

6 files changed

+182
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Simulator self-update test
2+
3+
on:
4+
push:
5+
branches: [ 'master', 'main', 'release/**' ]
6+
pull_request:
7+
branches: [ '*' ]
8+
9+
jobs:
10+
self_update_simulator_test:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 15
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
submodules: true
18+
19+
- name: Workaround for sources.list
20+
run: |
21+
# Replace sources
22+
23+
set -euxo pipefail
24+
25+
# Peek (what repos are active now)
26+
apt-cache policy
27+
grep -RInE '^(deb|Types|URIs)' /etc/apt || true
28+
29+
# Enable nullglob so *.list/*.sources that don't exist don't break sed
30+
shopt -s nullglob
31+
32+
echo "Replace sources.list (legacy)"
33+
sudo sed -i \
34+
-e "s|https\?://azure\.archive\.ubuntu\.com/ubuntu/?|http://mirror.arizona.edu/ubuntu/|g" \
35+
/etc/apt/sources.list || true
36+
37+
echo "Replace sources.list.d/*.list (legacy)"
38+
for f in /etc/apt/sources.list.d/*.list; do
39+
sudo sed -i \
40+
-e "s|https\?://azure\.archive\.ubuntu\.com/ubuntu/?|http://mirror.arizona.edu/ubuntu/|g" \
41+
"$f"
42+
done
43+
44+
echo "Replace sources.list.d/*.sources (deb822)"
45+
for f in /etc/apt/sources.list.d/*.sources; do
46+
sudo sed -i \
47+
-e "s|https\?://azure\.archive\.ubuntu\.com/ubuntu/?|http://mirror.arizona.edu/ubuntu/|g" \
48+
-e "s|https\?://azure\.archive\.ubuntu\.com|http://mirror.arizona.edu|g" \
49+
"$f"
50+
done
51+
52+
echo "Fix /etc/apt/apt-mirrors.txt (used by URIs: mirror+file:...)"
53+
if grep -qE '^[[:space:]]*https?://azure\.archive\.ubuntu\.com/ubuntu/?' /etc/apt/apt-mirrors.txt; then
54+
# Replace azure with our mirror (idempotent)
55+
sudo sed -i 's|https\?://azure\.archive\.ubuntu\.com/ubuntu/|http://mirror.arizona.edu/ubuntu/|g' /etc/apt/apt-mirrors.txt
56+
fi
57+
58+
# Peek (verify changes)
59+
grep -RIn "azure.archive.ubuntu.com" /etc/apt || true
60+
grep -RInE '^(deb|Types|URIs)' /etc/apt || true
61+
echo "--- apt-mirrors.txt ---"
62+
cat /etc/apt/apt-mirrors.txt || true
63+
64+
- name: Run self-update test (internal flash)
65+
run: |
66+
cp config/examples/sim-self-update.config .config
67+
make test-sim-self-update
68+
69+
- name: Run self-update test (external flash)
70+
run: |
71+
make clean
72+
cp config/examples/sim-self-update-ext.config .config
73+
make test-sim-self-update-ext
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
ARCH=sim
2+
TARGET=sim
3+
SIGN?=ED25519
4+
HASH?=SHA256
5+
WOLFBOOT_SMALL_STACK?=0
6+
SPI_FLASH=0
7+
EXT_FLASH=1
8+
DEBUG=1
9+
RAM_CODE=1
10+
WOLFBOOT_VERSION=1
11+
12+
# sizes should be multiple of system page size
13+
WOLFBOOT_PARTITION_SIZE=0x40000
14+
WOLFBOOT_SECTOR_SIZE=0x1000
15+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
16+
# Update and swap on external flash (address 0x00000)
17+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x00000
18+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x40000
19+
20+
# required for keytools
21+
WOLFBOOT_FIXED_PARTITIONS=1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
ARCH=sim
2+
TARGET=sim
3+
SIGN?=ED25519
4+
HASH?=SHA256
5+
WOLFBOOT_SMALL_STACK?=0
6+
SPI_FLASH=0
7+
DEBUG=1
8+
RAM_CODE=1
9+
WOLFBOOT_VERSION=1
10+
11+
# sizes should be multiple of system page size
12+
WOLFBOOT_PARTITION_SIZE=0x40000
13+
WOLFBOOT_SECTOR_SIZE=0x1000
14+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000
15+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x100000
16+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x180000
17+
18+
# required for keytools
19+
WOLFBOOT_FIXED_PARTITIONS=1

hal/sim.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,11 @@ int wolfBoot_dualboot_candidate(void)
596596
}
597597
#endif
598598

599+
void arch_reboot(void)
600+
{
601+
exit(0);
602+
}
603+
599604
#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT
600605

601606
int hal_hsm_init_connect(void)

src/update_flash.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ static void RAMFUNCTION wolfBoot_self_update(struct wolfBoot_image *src)
8484
while (pos < src->fw_size) {
8585
uint8_t buffer[FLASHBUFFER_SIZE];
8686
if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
87+
#ifdef ARCH_SIM
88+
/* Use ARCH_FLASH_OFFSET for simulator: flash is mmap'd at runtime,
89+
* so the linker symbol _start_text does not point to simulated flash */
90+
uintptr_t opos = pos + ARCH_FLASH_OFFSET;
91+
#else
8792
uintptr_t opos = pos + ((uintptr_t)&_start_text);
93+
#endif
8894
ext_flash_check_read((uintptr_t)(src->hdr) + src_offset + pos, (void*)buffer, FLASHBUFFER_SIZE);
8995
hal_flash_write(opos, buffer, FLASHBUFFER_SIZE);
9096
}
@@ -96,7 +102,13 @@ static void RAMFUNCTION wolfBoot_self_update(struct wolfBoot_image *src)
96102
while (pos < src->fw_size) {
97103
if (src_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
98104
uint8_t *orig = (uint8_t*)(src->hdr + src_offset + pos);
105+
#ifdef ARCH_SIM
106+
/* Use ARCH_FLASH_OFFSET for simulator: flash is mmap'd at runtime,
107+
* so the linker symbol _start_text does not point to simulated flash */
108+
hal_flash_write(pos + ARCH_FLASH_OFFSET, orig, FLASHBUFFER_SIZE);
109+
#else
99110
hal_flash_write(pos + (uintptr_t)&_start_text, orig, FLASHBUFFER_SIZE);
111+
#endif
100112
}
101113
pos += FLASHBUFFER_SIZE;
102114
}

tools/test.mk

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,58 @@ test-sim-rollback-flash: wolfboot.elf test-sim-internal-flash-with-update FORCE
240240
$(Q)(test `./wolfboot.elf success get_version` -eq 1)
241241
$(Q)(test `./wolfboot.elf get_version` -eq 1)
242242

243+
# Test bootloader self-update mechanism using simulator. Since simulator memmaps runtime addresses
244+
# the best we can do is ensure the self-update copies the intact self-update image to the expected location
245+
test-sim-self-update: wolfboot.bin FORCE
246+
@echo "=== Simulator Self-Update Test ==="
247+
@# Create dummy payload (0xAA pattern) and sign as wolfBoot update v2
248+
$(Q)dd if=/dev/zero bs=$$(wc -c < wolfboot.bin | awk '{print $$1}') count=1 2>/dev/null | tr '\000' '\252' > dummy_update.bin
249+
$(Q)$(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) --wolfboot-update dummy_update.bin $(PRIVATE_KEY) 2
250+
@# Create update partition with signed update and "pBOOT" trailer. Necessary since there is no running
251+
@# app to trigger an initial update
252+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
253+
$(Q)dd if=dummy_update_v2_signed.bin of=update_part.dd bs=1 conv=notrunc
254+
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(WOLFBOOT_PARTITION_SIZE) - 5)) conv=notrunc
255+
@# Create erased boot and swap partitions
256+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > boot_part.dd
257+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_SECTOR_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > erased_sec.dd
258+
@# Assemble flash: wolfboot.bin at 0, empty boot partition, update partition, swap
259+
$(Q)$(BINASSEMBLE) internal_flash.dd \
260+
0 wolfboot.bin \
261+
$$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET))) boot_part.dd \
262+
$$(($(WOLFBOOT_PARTITION_UPDATE_ADDRESS) - $(ARCH_FLASH_OFFSET))) update_part.dd \
263+
$$(($(WOLFBOOT_PARTITION_SWAP_ADDRESS) - $(ARCH_FLASH_OFFSET))) erased_sec.dd
264+
@# Run simulator - self-update runs before app boot, writes dummy to offset 0, then reboots
265+
$(Q)./wolfboot.elf get_version || true
266+
@# Verify dummy payload was written to bootloader region, indicating the self update swapped images as expected
267+
$(Q)cmp -n $$(wc -c < dummy_update.bin | awk '{print $$1}') dummy_update.bin internal_flash.dd && echo "=== Self-update test PASSED ==="
268+
269+
# Test bootloader self-update mechanism with external flash
270+
test-sim-self-update-ext: wolfboot.bin FORCE
271+
@echo "=== Simulator Self-Update Test (External Flash) ==="
272+
@# Create dummy payload (0xAA pattern) and sign as wolfBoot update v2
273+
$(Q)dd if=/dev/zero bs=$$(wc -c < wolfboot.bin | awk '{print $$1}') count=1 2>/dev/null | tr '\000' '\252' > dummy_update.bin
274+
$(Q)$(SIGN_ENV) $(SIGN_TOOL) $(SIGN_OPTIONS) --wolfboot-update dummy_update.bin $(PRIVATE_KEY) 2
275+
@# Create update partition with signed update and "pBOOT" trailer
276+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > update_part.dd
277+
$(Q)dd if=dummy_update_v2_signed.bin of=update_part.dd bs=1 conv=notrunc
278+
$(Q)printf "pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(WOLFBOOT_PARTITION_SIZE) - 5)) conv=notrunc
279+
@# Create erased boot and swap partitions
280+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > boot_part.dd
281+
$(Q)dd if=/dev/zero bs=$$(($(WOLFBOOT_SECTOR_SIZE))) count=1 2>/dev/null | tr '\000' '\377' > erased_sec.dd
282+
@# Assemble internal flash: wolfboot.bin at 0, empty boot partition
283+
$(Q)$(BINASSEMBLE) internal_flash.dd \
284+
0 wolfboot.bin \
285+
$$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET))) boot_part.dd
286+
@# Assemble external flash: update partition, swap sector
287+
$(Q)$(BINASSEMBLE) external_flash.dd \
288+
0 update_part.dd \
289+
$(WOLFBOOT_PARTITION_SIZE) erased_sec.dd
290+
@# Run simulator - self-update reads from external, writes to internal at offset 0
291+
$(Q)./wolfboot.elf get_version || true
292+
@# Verify dummy payload was written to bootloader region
293+
$(Q)cmp -n $$(wc -c < dummy_update.bin | awk '{print $$1}') dummy_update.bin internal_flash.dd && echo "=== Self-update test (External Flash) PASSED ==="
294+
243295
test-self-update: FORCE
244296
@mv $(PRIVATE_KEY) private_key.old
245297
@make clean factory.bin RAM_CODE=1 WOLFBOOT_VERSION=1 SIGN=$(SIGN)

0 commit comments

Comments
 (0)