Peer review fixes

pull/759/head
David Garske 2026-04-15 13:10:27 -07:00 committed by Daniele Lacamera
parent 00313b3e43
commit bc454d9f4b
6 changed files with 107 additions and 6 deletions

View File

@ -336,7 +336,7 @@ wolfboot.bin: wolfboot.elf
$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@
ifeq ($(TARGET),nxp_lpc54s0xx)
@echo "\t[LPC] enhanced boot block"
$(Q)python3 -c "import struct,os;f=open('$@','r+b');sz=os.path.getsize('$@');f.seek(0x24);f.write(struct.pack('<2I',0xEDDC94BD,0x160));f.seek(0x160);f.write(struct.pack('<25I',0xFEEDA5A5,3,0x10000000,sz-4,0,0,0,0,0,0xEDDC94BD,0,0,0,0x001640EF,0,0,0x1301001D,0,0,0,0x00000100,0,0,0x04030050,0x14110D09));f.seek(0);d=f.read(28);w=struct.unpack('<7I',d);s=sum(w)&0xFFFFFFFF;ck=(0x100000000-s)&0xFFFFFFFF;f.seek(0x1C);f.write(struct.pack('<I',ck));f.close();print('\tvector checksum: 0x%08X'%ck)"
$(Q)python3 tools/scripts/lpc54s0xx_patch_boot_block.py $@
endif
@echo
@echo "\t[SIZE]"

View File

@ -4,7 +4,7 @@
# Boot: ROM boot loads wolfBoot from external SPIFI QSPI flash at 0x10000000
# HAL: Bare-metal (hal/nxp_lpc54s0xx.c) — no NXP MCUXpresso SDK required
#
# Flash layout (SPIFI QSPI, 16 MB total):
# Flash layout (SPIFI QSPI, 4 MB total — Winbond W25Q32JV):
# 0x10000000 wolfBoot (up to BOOT partition base)
# 0x10010000 BOOT partition (960 KB, signed application)
# 0x10100000 UPDATE partition (960 KB)

View File

@ -440,6 +440,9 @@ static void RAMFUNCTION spifi_wait_busy(void)
SPIFI_IDATA = 0x00; /* expect BUSY=0 */
SPIFI_CLIMIT = (saved_climit & 0xFFFFFF00) | W25Q_STATUS_BUSY; /* mask bit 0 */
/* Callers (hal_flash_write / hal_flash_erase) always issue a non-MCMD
* command before reaching here, so MCINIT is clear and the reset path in
* spifi_set_cmd() does not run IDATA/CLIMIT programmed above survive. */
spifi_set_cmd(CMD_READ_STATUS); /* POLL mode command */
/* SPIFI hardware polls flash status internally.

View File

@ -22,9 +22,15 @@
*/
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <sys/stat.h>
/* Forward declaration of vsnprintf. We intentionally do not include <stdio.h>
* because this file redefines stdout/stderr/fputs/fflush with bare-metal
* (void *) stubs that collide with the libc FILE-based prototypes. */
extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
/* Provide our own errno for bare-metal.
* Using the libc errno via <errno.h> can conflict with TLS-based errno
* on cross-toolchains (e.g. powerpc-linux-gnu glibc). */

View File

@ -0,0 +1,86 @@
#!/usr/bin/env python3
# lpc54s0xx_patch_boot_block.py
#
# Patch a wolfBoot binary for the NXP LPC540xx / LPC54S0xx SPIFI (XIP) boot
# ROM. The ROM expects an "enhanced boot block":
# - offset 0x1C: vector table checksum (negated sum of the first 7 words)
# - offset 0x24: boot block marker + offset to descriptor
# - offset 0x160: 25-word descriptor (magic, mode, image base, image size, ...)
#
# Usage: lpc54s0xx_patch_boot_block.py <wolfboot.bin>
#
# Copyright (C) 2025 wolfSSL Inc.
# This file is part of wolfBoot (GPL-2.0-or-later).
import os
import struct
import sys
HEADER_MARKER_OFFSET = 0x24
BOOT_BLOCK_OFFSET = 0x160
VECTOR_CHECKSUM_OFFSET = 0x1C
IMAGE_BASE_ADDR = 0x10000000 # SPIFI XIP base
HEADER_MARKER_FMT = "<2I" # 0xEDDC94BD, 0x160
BOOT_BLOCK_FMT = "<25I"
VECTOR_TABLE_FMT = "<7I" # first 7 words covered by checksum
def patch(path):
size = os.path.getsize(path)
header_marker_size = struct.calcsize(HEADER_MARKER_FMT)
boot_block_size = struct.calcsize(BOOT_BLOCK_FMT)
vector_table_size = struct.calcsize(VECTOR_TABLE_FMT)
min_size = max(
vector_table_size,
HEADER_MARKER_OFFSET + header_marker_size,
BOOT_BLOCK_OFFSET + boot_block_size,
)
if size < min_size:
raise SystemExit(
"error: %s is too small for LPC54S0xx boot block patching "
"(size=%d, need at least %d bytes)" % (path, size, min_size)
)
with open(path, "r+b") as f:
f.seek(HEADER_MARKER_OFFSET)
f.write(struct.pack(HEADER_MARKER_FMT, 0xEDDC94BD, BOOT_BLOCK_OFFSET))
f.seek(BOOT_BLOCK_OFFSET)
f.write(struct.pack(
BOOT_BLOCK_FMT,
0xFEEDA5A5, # magic
3, # image type
IMAGE_BASE_ADDR, # image base
size - 4, # image size (minus CRC slot)
0, 0, 0, 0, 0,
0xEDDC94BD, # header marker echo
0, 0, 0,
0x001640EF, # SPIFI config
0, 0,
0x1301001D, # clock/flash timing word
0, 0, 0,
0x00000100, # options
0, 0,
0x04030050, # PLL config
0x14110D09, # clock divider config
))
f.seek(0)
words = struct.unpack(VECTOR_TABLE_FMT, f.read(vector_table_size))
checksum = (0x100000000 - (sum(words) & 0xFFFFFFFF)) & 0xFFFFFFFF
f.seek(VECTOR_CHECKSUM_OFFSET)
f.write(struct.pack("<I", checksum))
print("\tvector checksum: 0x%08X" % checksum)
def main(argv):
if len(argv) != 2:
raise SystemExit("usage: %s <wolfboot.bin>" % argv[0])
patch(argv[1])
if __name__ == "__main__":
main(sys.argv)

View File

@ -30,6 +30,7 @@
#
set -e
set -o pipefail
# Configuration (can be overridden via environment variables)
CONFIG_FILE="${CONFIG_FILE:-config/examples/nxp_lpc54s0xx.config}"
@ -110,10 +111,15 @@ parse_config() {
exit 1
fi
# Helper function to extract config value
# Helper function to extract config value.
# Anchor the regex to `KEY=` or `KEY?=` so e.g. SIGN does not match SIGN_ALG.
# grep with --max-count=1 keeps the pipeline single-stage so pipefail catches
# a truly missing key (exit 1) rather than relying on `head` to mask it.
get_config_value() {
local key="$1"
grep -E "^${key}" "$config_file" | head -1 | sed -E "s/^${key}\??=//" | tr -d '[:space:]'
local line
line=$(grep -E "^${key}\\??=" "$config_file" --max-count=1) || return 0
printf '%s' "${line#*=}" | tr -d '[:space:]'
}
# Extract SIGN and HASH
@ -146,9 +152,9 @@ parse_config() {
# Ensure partition addresses have 0x prefix for bash arithmetic
for var in WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE; do
eval "val=\$$var"
local val="${!var}"
if [[ ! "$val" =~ ^0x ]]; then
eval "$var=\"0x\${val}\""
printf -v "$var" '0x%s' "$val"
fi
done