mirror of https://github.com/wolfSSL/wolfBoot.git
PolarFire SoC: address PR review
- wolfBoot_fit_memcpy: return int so a failed PDMA copy propagates instead of being swallowed. The weak default (memcpy) returns 0; the MPFS250 PDMA override returns -1 if any chunk's mpfs_pdma_memcpy() fails. Callers now fail closed: fit_load_image_inner returns NULL (kernel load then panics via update_disk.c), the update_disk DTS copy panics, and hal_dts_fixup returns an error on a failed L2->DDR copy-back. - options.mk: gate -DSTACK_SIZE_PER_HART behind RISC-V arch (RISCV/RISCV64). The macro is only consumed by the RISC-V startup asm and the mpfs250-m.ld sed token, so it is no longer emitted for PPC/ARM/other targets. The unconditional default (?= 0) is kept because the linker sed always needs a value to substitute.pull/844/head
parent
6b3612f4b9
commit
5f40400e57
|
|
@ -477,7 +477,7 @@ void hal_init(void)
|
|||
* inner retry inside mpfs_ddr_init() exhausts (typically because
|
||||
* MTC wedged after the first failure), come back here for a full
|
||||
* controller re-init. Empirical: per-attempt failure rate ~30%, so
|
||||
* 3 outer attempts cover ~99.7% of boots. */
|
||||
* MPFS_DDR_MAX_OUTER_RETRY (6) outer attempts cover ~99.9% of boots. */
|
||||
for (outer_retry = 0; outer_retry < MPFS_DDR_MAX_OUTER_RETRY;
|
||||
outer_retry++) {
|
||||
if (outer_retry > 0) {
|
||||
|
|
@ -752,12 +752,18 @@ static int mpfs_dts_fixup_inplace(void* dts_addr)
|
|||
* through the PDMA master. A DDR source is read via its non-cached alias so
|
||||
* PDMA sees real DDR; mpfs_pdma_memcpy remaps the dst 0x8x->0xCx and flushes
|
||||
* L2. Chunked + WDT-petted for kernel-sized copies. */
|
||||
void wolfBoot_fit_memcpy(void *dst, const void *src, uint32_t len)
|
||||
int wolfBoot_fit_memcpy(void *dst, const void *src, uint32_t len)
|
||||
{
|
||||
uintptr_t d = (uintptr_t)dst;
|
||||
uintptr_t s = (uintptr_t)src;
|
||||
volatile const uint8_t *ncd;
|
||||
const uint8_t *ncs;
|
||||
uint32_t off = 0;
|
||||
uint32_t chunk;
|
||||
uint32_t k;
|
||||
int retry;
|
||||
int mism;
|
||||
int rc = 0;
|
||||
|
||||
if ((s & 0xF0000000UL) == 0x80000000UL) {
|
||||
s |= 0x40000000UL; /* non-cached source alias */
|
||||
|
|
@ -767,17 +773,51 @@ void wolfBoot_fit_memcpy(void *dst, const void *src, uint32_t len)
|
|||
if (chunk > (1024U * 1024U)) {
|
||||
chunk = 1024U * 1024U;
|
||||
}
|
||||
(void)mpfs_pdma_memcpy((void *)(d + off),
|
||||
(const void *)(s + off), chunk);
|
||||
/* Refresh all five MSS watchdogs (they always count and reset the
|
||||
* chip and cannot be disabled) during the multi-MB kernel copy. */
|
||||
MSS_WDT_REFRESH(MSS_WDT_E51_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_1_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_2_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_3_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_4_BASE) = 0xDEADC0DEU;
|
||||
/* mpfs_pdma_memcpy always returns 0, so the read-back verify below is
|
||||
* the authoritative success check for this chunk. The PDMA->DDR write
|
||||
* intermittently drops a block, so re-PDMA on a mismatch (same pattern
|
||||
* as sdhci_platform_block_copy). A DDR destination (0x8xxxxxxx) is
|
||||
* read back through its non-cached alias (| 0x40000000) so we compare
|
||||
* what actually landed in DDR, not stale L2; this makes the caller's
|
||||
* fail-closed rc real for the signature-uncovered kernel/dtb copies.
|
||||
* A non-DDR destination (e.g. an L2 scratch buffer) lands directly, so
|
||||
* a single copy suffices. */
|
||||
mism = 1;
|
||||
for (retry = 0; retry < 8 && mism != 0; retry++) {
|
||||
(void)mpfs_pdma_memcpy((void *)(d + off),
|
||||
(const void *)(s + off), chunk);
|
||||
/* Refresh all five MSS watchdogs (they always count and reset the
|
||||
* chip and cannot be disabled) during the multi-MB kernel copy
|
||||
* and its read-back verify. */
|
||||
MSS_WDT_REFRESH(MSS_WDT_E51_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_1_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_2_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_3_BASE) = 0xDEADC0DEU;
|
||||
MSS_WDT_REFRESH(MSS_WDT_U54_4_BASE) = 0xDEADC0DEU;
|
||||
if ((d & 0xF0000000UL) != 0x80000000UL) {
|
||||
mism = 0; /* non-DDR dst lands on the first copy */
|
||||
break;
|
||||
}
|
||||
__asm__ volatile("fence iorw,iorw" ::: "memory");
|
||||
ncd = (volatile const uint8_t *)((d + off) | 0x40000000UL);
|
||||
ncs = (const uint8_t *)(s + off);
|
||||
mism = 0;
|
||||
for (k = 0; k < chunk; k++) {
|
||||
if (ncd[k] != ncs[k]) {
|
||||
mism = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mism != 0) {
|
||||
/* Copy could not be verified within the retry budget; remember the
|
||||
* failure so the caller fails closed rather than boot corrupt,
|
||||
* no-longer-signature-covered data. */
|
||||
rc = -1;
|
||||
}
|
||||
off += chunk;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* L2 round-trip wrapper around mpfs_dts_fixup_inplace(). The dtb lives in DDR
|
||||
|
|
@ -816,7 +856,11 @@ int hal_dts_fixup(void* dts_addr)
|
|||
/* fixup in the CPU-writable L2 buffer */
|
||||
ret = mpfs_dts_fixup_inplace(l2_dtb);
|
||||
/* L2 -> DDR via PDMA (expanded totalsize) */
|
||||
wolfBoot_fit_memcpy(dts_addr, l2_dtb, (uint32_t)fdt_totalsize(l2_dtb));
|
||||
if (wolfBoot_fit_memcpy(dts_addr, l2_dtb,
|
||||
(uint32_t)fdt_totalsize(l2_dtb)) != 0) {
|
||||
wolfBoot_printf("FDT: dtb copy-back to DDR failed\n");
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ extern "C" {
|
|||
#if defined(MMU) || defined(WOLFBOOT_FDT)
|
||||
extern void do_boot(const uint32_t *app_offset, const uint32_t* dts_offset);
|
||||
/* Weak copy hook for FIT subimages (kernel/dtb): default memcpy; boards where
|
||||
* CPU writes to the load address don't land override it with a DMA copy. */
|
||||
extern void wolfBoot_fit_memcpy(void *dst, const void *src, uint32_t len);
|
||||
* CPU writes to the load address don't land override it with a DMA copy.
|
||||
* Returns 0 on success or a negative value if the copy failed, so callers can
|
||||
* fail closed instead of running on stale data. */
|
||||
extern int wolfBoot_fit_memcpy(void *dst, const void *src, uint32_t len);
|
||||
#else
|
||||
extern void do_boot(const uint32_t *app_offset);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1440,9 +1440,13 @@ endif
|
|||
# Per-hart secondary stack size: single source of truth shared by the
|
||||
# startup asm (via this -D) and the linker script (via @STACK_SIZE_PER_HART@
|
||||
# substitution in the LSCRIPT rule). Set in the target .config; defaults to
|
||||
# 0 (no secondary park/wake stacks).
|
||||
# 0 (no secondary park/wake stacks). The concept (and the consuming startup
|
||||
# asm) is RISC-V only, so gate the -D to RISC-V; the default is kept
|
||||
# unconditional because the LSCRIPT sed always needs a value to substitute.
|
||||
STACK_SIZE_PER_HART ?= 0
|
||||
CFLAGS+=-DSTACK_SIZE_PER_HART=$(STACK_SIZE_PER_HART)
|
||||
ifneq (,$(filter RISCV RISCV64,$(ARCH)))
|
||||
CFLAGS+=-DSTACK_SIZE_PER_HART=$(STACK_SIZE_PER_HART)
|
||||
endif
|
||||
|
||||
CFLAGS+=$(CFLAGS_EXTRA)
|
||||
OBJS+=$(OBJS_EXTRA)
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ int WEAKFUNCTION hal_dts_fixup(void* dts_addr)
|
|||
*
|
||||
*/
|
||||
|
||||
#ifdef MMU
|
||||
#if defined(MMU) || defined(WOLFBOOT_FDT)
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
||||
#else
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ void boot_entry_C(void)
|
|||
*
|
||||
*/
|
||||
|
||||
#ifdef MMU
|
||||
#if defined(MMU) || defined(WOLFBOOT_FDT)
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
||||
#else
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ void RAMFUNCTION wolfBoot_os64bit_jump(os64bit_entry_t entry,
|
|||
}
|
||||
#endif /* ENABLE_OS64BIT */
|
||||
|
||||
#ifdef MMU
|
||||
#if defined(MMU) || defined(WOLFBOOT_FDT)
|
||||
void do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
||||
#else
|
||||
void do_boot(const uint32_t *app_offset)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ extern unsigned int *END_STACK;
|
|||
|
||||
extern void RAMFUNCTION x86_64_efi_do_boot(uint8_t *kernel);
|
||||
|
||||
#ifdef MMU
|
||||
#if defined(MMU) || defined(WOLFBOOT_FDT)
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
||||
#else
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
|
|
|
|||
13
src/fdt.c
13
src/fdt.c
|
|
@ -1135,11 +1135,14 @@ int fit_load_ramdisk(void* fit, const char* ramdisk_node, void* dts_addr)
|
|||
/* Weak copy hook for FIT subimages (kernel/dtb). Default is a plain memcpy;
|
||||
* boards where CPU writes to the load destination do not land (e.g. the
|
||||
* PolarFire MPFS250 DDR, where cached writes thrash L2 Scratch) override this
|
||||
* with a DMA-based copy (see hal/mpfs250.c). */
|
||||
void __attribute__((weak)) wolfBoot_fit_memcpy(void *dst, const void *src,
|
||||
* with a DMA-based copy (see hal/mpfs250.c). Returns 0 on success or a
|
||||
* negative value if the copy failed, so callers can fail closed rather than
|
||||
* run on a partially written destination. */
|
||||
int __attribute__((weak)) wolfBoot_fit_memcpy(void *dst, const void *src,
|
||||
uint32_t len)
|
||||
{
|
||||
memcpy(dst, src, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Inner implementation shared by fit_load_image_ex and fit_load_image_to.
|
||||
|
|
@ -1236,7 +1239,11 @@ static void* fit_load_image_inner(void* fdt, const char* image, int* lenp,
|
|||
}
|
||||
wolfBoot_printf("Loading Image %s: %p -> %p "
|
||||
"(%d bytes)\n", image, data, load, len);
|
||||
wolfBoot_fit_memcpy(load, data, (uint32_t)len);
|
||||
if (wolfBoot_fit_memcpy(load, data, (uint32_t)len) != 0) {
|
||||
wolfBoot_printf("FIT: copy of %s to %p failed\n",
|
||||
image, load);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* No per-image hash-1 re-verification here. Per the
|
||||
|
|
|
|||
|
|
@ -631,7 +631,10 @@ void RAMFUNCTION wolfBoot_start(void)
|
|||
dts_addr = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS;
|
||||
wolfBoot_printf("Loading DTS: %p -> %p (%d bytes)\n",
|
||||
dts_ptr, dts_addr, dts_size);
|
||||
wolfBoot_fit_memcpy(dts_addr, dts_ptr, dts_size);
|
||||
if (wolfBoot_fit_memcpy(dts_addr, dts_ptr, dts_size) != 0) {
|
||||
wolfBoot_printf("FIT: failed to load DTS\r\n");
|
||||
wolfBoot_panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WOLFBOOT_FIT_RAMDISK
|
||||
|
|
|
|||
Loading…
Reference in New Issue