mirror of https://github.com/wolfSSL/wolfBoot.git
Condense the verbose comments
The test file headers ran to 20-40 lines of prose before the licence, restating the whole finding and the harness design. Cut them to a short paragraph on what broke and a short one on how the test reaches the code. Same for the long inline blocks in the HAL and libwolfboot changes. Comments only; no functional change.pull/862/head
parent
640ee478e4
commit
502a69e9df
|
|
@ -678,12 +678,10 @@ static int hal_fman_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the container before uploading (the T10xx
|
||||
* qe_check_firmware() path checks the same things): version,
|
||||
* microcode count, self-consistent length, every code range inside
|
||||
* the declared image, and the whole image inside the remaining NOR
|
||||
* bank. 64-bit arithmetic so the sums cannot wrap. Fail closed:
|
||||
* FMan stays unconfigured on any mismatch. */
|
||||
/* Validate before uploading, as the T10xx qe_check_firmware() path
|
||||
* does: version, count, self-consistent length, every code range
|
||||
* inside the image, the image inside the NOR bank. 64-bit so the
|
||||
* sums cannot wrap; FMan stays unconfigured on any mismatch. */
|
||||
if (hdr->version != 1) {
|
||||
wolfBoot_printf("FMAN: version %d unsupported\n", hdr->version);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -246,9 +246,8 @@ static int open_kernel_image(EFI_FILE_HANDLE vol, CHAR16 *filename,
|
|||
if (file == NULL)
|
||||
return -1;
|
||||
|
||||
/* FileSize() is 64-bit; the rest of the loader (header parsing, LoadImage
|
||||
* size) works in uint32_t. Reject a size that would not fit rather than
|
||||
* silently truncating it into *sz. */
|
||||
/* FileSize() is 64-bit but the loader works in uint32_t; reject a
|
||||
* size that would not fit rather than truncating it. */
|
||||
filesz = FileSize(file);
|
||||
if (filesz == 0 || filesz > 0xFFFFFFFFULL) {
|
||||
wolfBoot_printf("Invalid file size: 0x%lx\n", (unsigned long)filesz);
|
||||
|
|
@ -273,12 +272,9 @@ static int open_kernel_image(EFI_FILE_HANDLE vol, CHAR16 *filename,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* EFI_FILE_PROTOCOL.Read() takes a UINTN *BufferSize (64 bits on
|
||||
* x86-64) and writes the bytes actually read through it. Passing the
|
||||
* caller's uint32_t *sz would let an ordinary read store eight bytes
|
||||
* through a four-byte stack object, and the 64-bit read of
|
||||
* *BufferSize would see adjacent stack bytes. Same contract as the
|
||||
* AArch64 sibling. */
|
||||
/* Read() takes a UINTN *BufferSize (64-bit here) and writes the
|
||||
* byte count back through it; passing the caller's uint32_t *sz
|
||||
* would store eight bytes through a four-byte object. */
|
||||
readsz = (UINTN)*sz;
|
||||
status = uefi_call_wrapper(file->Read, 3, file, &readsz,
|
||||
(void *)(uintptr_t)*_addr);
|
||||
|
|
|
|||
|
|
@ -58,23 +58,18 @@ extern int tolower(int c);
|
|||
#endif
|
||||
|
||||
#ifdef USE_FAST_MATH
|
||||
/* WC_NO_HARDEN is intended only for verify-only builds: the image
|
||||
* verification path performs public-key operations only, so timing
|
||||
* resistance and hardening are not required there. Software DICE
|
||||
* (WOLFCRYPT_TZ_PSA without WOLFBOOT_DICE_HW) is not verify-only:
|
||||
* it signs the attestation claims with the private IAK via
|
||||
* wc_CoseSign1_Sign_ex() and must keep the timing hardening, so
|
||||
* exclude it. Hardware DICE (WOLFBOOT_DICE_HW) keeps the signing
|
||||
* in the crypto engine and stays verify-only in fast math. */
|
||||
/* WC_NO_HARDEN suits verify-only builds, which do public-key
|
||||
* operations only. Software DICE (WOLFCRYPT_TZ_PSA without
|
||||
* WOLFBOOT_DICE_HW) signs the attestation claims with the private
|
||||
* IAK, so it is excluded; hardware DICE keeps signing in the crypto
|
||||
* engine and stays verify-only. */
|
||||
# if !defined(WOLFCRYPT_TZ_PSA) || defined(WOLFBOOT_DICE_HW)
|
||||
# define WC_NO_HARDEN
|
||||
# else
|
||||
/* Turn the hardening on rather than only dropping
|
||||
* WC_NO_HARDEN: tfm.c never tests WC_NO_HARDEN, so removing it
|
||||
* changes no code -- it only un-silences the advisory in
|
||||
* settings.h, which -Werror then turns into a build failure.
|
||||
* TFM_TIMING_RESISTANT is what actually makes tfm.c constant
|
||||
* time (ECC_TIMING_RESISTANT is already set with HAVE_ECC). */
|
||||
/* tfm.c never tests WC_NO_HARDEN, so dropping it alone changes
|
||||
* no code and only un-silences an advisory that -Werror turns
|
||||
* into a build failure. TFM_TIMING_RESISTANT is what makes
|
||||
* tfm.c constant time. */
|
||||
# define TFM_TIMING_RESISTANT
|
||||
# endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -256,14 +256,11 @@ static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
|
|||
static uint8_t NVM_CACHE[NVM_CACHE_SIZE] XALIGNED(16);
|
||||
static int nvm_cached_sector = 0;
|
||||
|
||||
/* Scrub the staging buffer without depending on wolfCrypt. ForceZero()
|
||||
* would drag <wolfssl/wolfcrypt/types.h> and <wolfcrypt/src/misc.c>
|
||||
* into every NVM_FLASH_WRITEONCE build of this file, including the two
|
||||
* that cannot supply them: tools/check_config (no wolfSSL include
|
||||
* path) and the STM32Cube test-app (no stm32*_hal_conf.h). A volatile
|
||||
* byte loop is also the right shape for a RAMFUNCTION caller, since
|
||||
* ForceZero() itself lives in flash and must not be called while the
|
||||
* flash is being programmed. */
|
||||
/* Scrub the staging buffer without depending on wolfCrypt: ForceZero()
|
||||
* would pull wolfSSL headers into every NVM_FLASH_WRITEONCE build,
|
||||
* including tools/check_config and the STM32Cube test-app, which cannot
|
||||
* supply them. A volatile byte loop also suits the RAMFUNCTION callers,
|
||||
* since ForceZero() lives in flash. */
|
||||
static void RAMFUNCTION nvm_cache_scrub(void)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)NVM_CACHE;
|
||||
|
|
|
|||
14
src/sdhci.c
14
src/sdhci.c
|
|
@ -1541,15 +1541,11 @@ static int sdhci_transfer(int dir, uint32_t cmd_index, uint32_t block_addr,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check for errors.
|
||||
*
|
||||
* An earlier failure (e.g. the SDMA wait above timing out) must survive
|
||||
* this block. A wolfBoot-side wait timeout does not necessarily set an
|
||||
* SRS12 error bit, so without preserving `status` the CMD12 / wait-busy
|
||||
* results below would overwrite it and sdhci_transfer() would report
|
||||
* success for a transfer that never completed. The caller then uses a
|
||||
* partially filled buffer, which surfaces much later as a bogus image
|
||||
* integrity failure rather than as the I/O error it actually is. */
|
||||
/* Check for errors. An earlier failure (e.g. the SDMA wait timing
|
||||
* out) must survive this block: a wolfBoot-side timeout need not set
|
||||
* an SRS12 error bit, so without preserving `status` the CMD12 and
|
||||
* wait-busy results below would report success for a transfer that
|
||||
* never completed. */
|
||||
reg = SDHCI_REG(SDHCI_SRS12);
|
||||
if ((reg & SDHCI_SRS12_ERR_STAT) == 0) {
|
||||
/* If multi-block, send CMD12 to stop transfer. This is issued even
|
||||
|
|
|
|||
|
|
@ -1,23 +1,16 @@
|
|||
/* unit-aurix-erased-fill.c
|
||||
*
|
||||
* Regression test: cacheSector() and
|
||||
* programBytesToErasedFlash() in hal/aurix_tc3xx.c filled their
|
||||
* uint32_t page buffers with the byte-valued FLASH_BYTE_ERASED, so in
|
||||
* the default (non-inverted) build every 32-bit word became
|
||||
* 0x000000FF instead of 0xFFFFFFFF. A one-byte write into an
|
||||
* erased page then programmed zeroes into the unrelated bytes of the
|
||||
* same word, and the sector-cache path corrupted logically-erased
|
||||
* pages during read-modify-write.
|
||||
*
|
||||
* The test extracts the real cacheSector() and
|
||||
* programBytesToErasedFlash() from hal/aurix_tc3xx.c (generated by
|
||||
* the Makefile) and runs them against an emulated tc3_flash_* API on
|
||||
* a host flash array. The assertions use FLASH_BYTE_ERASED /
|
||||
* FLASH_WORD_ERASED from include/wolfboot/wolfboot.h, so the same
|
||||
* source is built twice: default polarity (erased = 0xFF, where the
|
||||
* pre-fix bug shows) and WOLFBOOT_FLAGS_INVERT (erased = 0x00, where
|
||||
* the fix must not change the fill value).
|
||||
* Regression test: cacheSector() and programBytesToErasedFlash() in
|
||||
* hal/aurix_tc3xx.c filled uint32_t page buffers with the byte-valued
|
||||
* FLASH_BYTE_ERASED, so each word became 0x000000FF instead of
|
||||
* 0xFFFFFFFF. A one-byte write into an erased page then programmed
|
||||
* zeroes into the rest of the word.
|
||||
*
|
||||
* Extracts both functions (generated by the Makefile) and runs them
|
||||
* against an emulated tc3_flash_* API. Built twice, once per flag
|
||||
* polarity: default (erased = 0xFF), where the bug shows, and
|
||||
* WOLFBOOT_FLAGS_INVERT (erased = 0x00), where the fill must not
|
||||
* change.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,23 +1,17 @@
|
|||
/* unit-efi-x86-open-image.c
|
||||
*
|
||||
* Regression test: open_kernel_image() in hal/x86_64_efi.c passed
|
||||
* the caller's uint32_t *sz directly as the BufferSize argument of
|
||||
* EFI_FILE_PROTOCOL.Read(). That parameter is a UINTN, which is 64 bits on
|
||||
* x86-64, and the UEFI spec requires the firmware to write the number of
|
||||
* bytes actually read back through it. An ordinary successful read therefore
|
||||
* stored eight bytes through the four-byte object, corrupting the stack bytes
|
||||
* immediately after kernel_size/update_size in efi_main on every image load.
|
||||
*
|
||||
* The fix passes a local UINTN to Read() and copies the completed byte count
|
||||
* back into *sz, exactly as the AArch64 sibling (hal/aarch64_efi.c) does.
|
||||
*
|
||||
* hal/x86_64_efi.c is normally only built by the CMake x86_64_efi target
|
||||
* (gnu-efi headers, -lgnuefi -lefi), so this test doubles as its only host
|
||||
* build coverage: it includes the HAL file directly and stands in for the
|
||||
* gnu-efi runtime with host mocks (BS, LibFileInfo, the x86-64 efi_callN()
|
||||
* trampolines, wolfBoot_start). The mock Read() follows the spec'd BufferSize
|
||||
* contract, so this test fails against the pre-fix code.
|
||||
* Regression test: open_kernel_image() in hal/x86_64_efi.c passed the
|
||||
* caller's uint32_t *sz as the BufferSize argument of
|
||||
* EFI_FILE_PROTOCOL.Read(). That is a UINTN -- 64 bits on x86-64 --
|
||||
* and the firmware writes the byte count back through it, so every
|
||||
* successful read stored eight bytes through a four-byte object and
|
||||
* corrupted the stack after it. The fix passes a local UINTN and copies
|
||||
* the count back, as the AArch64 sibling does.
|
||||
*
|
||||
* hal/x86_64_efi.c is normally built only by the CMake x86_64_efi
|
||||
* target, so this doubles as its host build coverage: it includes the
|
||||
* HAL directly and mocks the gnu-efi runtime. The mock Read() follows
|
||||
* the spec'd BufferSize contract, so it fails against the pre-fix code.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,28 +1,17 @@
|
|||
/* unit-ls1028a-xspi-write.c
|
||||
*
|
||||
* Regression test: hal_flash_write() and ext_flash_write() in
|
||||
* hal/nxp_ls1028a.c issue xspi_write_en() once before xspi_flash_write(),
|
||||
* but xspi_flash_write() issues one Page Program command per 256-byte
|
||||
* chunk when len > XSPI_IP_BUF_SIZE. NOR flash clears its
|
||||
* write-enable latch after each program operation, so with a single WEN
|
||||
* only the first page of the request is actually programmed; the
|
||||
* remaining Page Programs are rejected by the flash while the wrapper
|
||||
* still reports success.
|
||||
*
|
||||
* The fix issues Write Enable for every page inside xspi_flash_write(),
|
||||
* after the prior program has completed and before the Page Program
|
||||
* command.
|
||||
*
|
||||
* The LS1028A XSPI driver is plain C register access apart from a few
|
||||
* bare `asm volatile("...")` barrier statements (DDR init, delay), so
|
||||
* the test includes the HAL file via nxp_ls1028a_host.c (generated by
|
||||
* the Makefile, identical except those statements are blanked out),
|
||||
* rebases XSPI_BASE onto host memory, and emulates the FlexSPI
|
||||
* controller at the XSPI_IPCMD_START() boundary. The emulated NOR keeps
|
||||
* a write-enable latch exactly like real NOR: set by WEN, consumed by
|
||||
* each Page Program / Sector Erase, and a program or erase attempted
|
||||
* without WEN is rejected.
|
||||
* Regression test: hal_flash_write()/ext_flash_write() in
|
||||
* hal/nxp_ls1028a.c issued one Write Enable before xspi_flash_write(),
|
||||
* which programs a page per chunk. NOR clears the write-enable latch
|
||||
* after each program, so only the first page landed while the wrapper
|
||||
* still reported success. The fix enables writes for every page.
|
||||
*
|
||||
* The HAL is plain register access apart from a few barrier asm
|
||||
* statements, so the test includes it via nxp_ls1028a_host.c (generated
|
||||
* by the Makefile with those blanked), rebases XSPI_BASE onto host
|
||||
* memory, and emulates the controller at the XSPI_IPCMD_START()
|
||||
* boundary. The emulated NOR keeps a real write-enable latch and a busy
|
||||
* window, so a dropped WEN or a missing wait shows up as a rejection.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,24 +1,15 @@
|
|||
/* unit-nvm-cache-scrub.c
|
||||
*
|
||||
* Regression test: under NVM_FLASH_WRITEONCE the
|
||||
* partition-trailer read-modify-write helpers stage a full flash
|
||||
* sector into the file-scope buffer NVM_CACHE. In EXT_ENCRYPTED
|
||||
* builds that same sector is where the firmware key/nonce live
|
||||
* (ENCRYPT_CACHE is a macro alias of NVM_CACHE in this
|
||||
* configuration), and neither trailer_write() nor
|
||||
* partition_magic_write() scrubbed NVM_CACHE on return - the only
|
||||
* ForceZero of the buffer is compiled out precisely for
|
||||
* NVM_FLASH_WRITEONCE. A normal boot therefore leaves the plaintext
|
||||
* key/nonce in .bss at a fixed address across the handoff to the
|
||||
* Regression test: under NVM_FLASH_WRITEONCE the trailer helpers stage
|
||||
* a whole flash sector into NVM_CACHE, which in EXT_ENCRYPTED builds is
|
||||
* also where the firmware key and nonce live (ENCRYPT_CACHE aliases it).
|
||||
* Neither trailer_write() nor partition_magic_write() scrubbed it on
|
||||
* return, leaving the plaintext key in .bss across the handoff to the
|
||||
* application.
|
||||
*
|
||||
* The test extracts the real trailer_write() and
|
||||
* partition_magic_write() from src/libwolfboot.c (generated by the
|
||||
* Makefile) and runs them with a test-owned NVM_CACHE, a staged
|
||||
* sector image carrying a key/nonce pattern, and stubbed
|
||||
* hal_flash_write/erase. After each call the whole buffer must be
|
||||
* scrubbed; pre-fix the staged sector (key bytes included) remained.
|
||||
*
|
||||
* Extracts the real helpers (generated by the Makefile) and runs them
|
||||
* with a test-owned NVM_CACHE, a staged sector carrying a key pattern
|
||||
* and stubbed flash calls; the buffer must be zero after each call.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -3,41 +3,17 @@
|
|||
* Regression tests for the FCM byte helpers and page loops in
|
||||
* hal/nxp_p1021.c.
|
||||
*
|
||||
* hal_flash_read_bytes() and hal_flash_write_bytes() loop on
|
||||
* `while (flash_idx < len)`, comparing the FCM buffer index (which
|
||||
* hal_flash_set_addr() initializes to the page column, `flash_idx = col`)
|
||||
* against the caller's relative byte count. With col != 0:
|
||||
*
|
||||
* - if len <= col the loop runs zero times, so the page program proceeds
|
||||
* with stale FCM buffer contents (write) or the caller's buffer is left
|
||||
* unchanged (read);
|
||||
* - if len > col only len - col bytes are copied;
|
||||
* - a final one-to-three byte remainder is copied as a full word, reading
|
||||
* or writing outside the requested range.
|
||||
*
|
||||
* The fix computes an absolute end (flash_idx + len) and copies exactly
|
||||
* len bytes, handling the tail byte-wise.
|
||||
*
|
||||
* the ext_flash_write()/ext_flash_read() page loops size every
|
||||
* iteration from the total request length instead of the remaining
|
||||
* length, do not cap it to the page, and program ELBC_FBCR with the
|
||||
* column offset - so the byte-count field (FBCR[BC], P1021RM 12.3.30
|
||||
* bits 20-31 MSB-first, i.e. the low 12 bits) carries the column rather
|
||||
* than a count: a nonsense transfer size whenever col is non-zero.
|
||||
* The fix uses chunk = min(len - pos, page_size - col), programs the BC
|
||||
* field (0 only for a full page from column 0 - the only
|
||||
* ECC-generating/checking setting) and advances by chunk.
|
||||
*
|
||||
* hal/nxp_p1021.c is PowerPC code, but the FCM helpers under test are
|
||||
* plain byte copies. The test includes the HAL file (via nxp_p1021_host.c,
|
||||
* generated by the Makefile) and drives the static helpers directly, with
|
||||
* flash_buf backed by a host array standing in for the eLBC FCM region.
|
||||
* The host copy differs from the real file only in that the three bare
|
||||
* `__asm__ __volatile__("..." )` cache-barrier statements (DDR init and
|
||||
* multi-core boot) are blanked out: they cannot assemble on x86. The
|
||||
* PowerPC-asm accessors from nxp_ppc.h are shadowed with host versions
|
||||
* below, so they are never emitted either.
|
||||
* The helpers looped on `flash_idx < len`, comparing the FCM buffer
|
||||
* index (which starts at the page column) against a relative byte
|
||||
* count, so with col != 0 they copied too few bytes and rounded the
|
||||
* tail up to a whole word. The page loops sized every iteration from
|
||||
* the total length instead of the remainder, did not cap to the page,
|
||||
* and programmed FBCR with the column instead of a byte count.
|
||||
*
|
||||
* The HAL is PowerPC but the helpers are plain byte copies, so the test
|
||||
* includes it via nxp_p1021_host.c (generated by the Makefile, with the
|
||||
* cache-barrier asm blanked) and drives the statics directly against a
|
||||
* host array standing in for the FCM region.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,26 +1,18 @@
|
|||
/* unit-p1021-qe-firmware.c
|
||||
*
|
||||
* Regression test (bounds part): qe_upload_firmware() in
|
||||
* hal/nxp_p1021.c validated only the self-declared consistency of the
|
||||
* QE microcode blob (magic, version, count range, length == computed
|
||||
* size, optional CRC32). The per-microcode code_offset/count fields and
|
||||
* the total length were never bounded to the 64 KiB buffer actually
|
||||
* read from NAND (which, on the shipped p1021 config, sits in the
|
||||
* update partition). A structurally consistent blob with a large
|
||||
* code_offset or word count made the upload loop read (and copy into
|
||||
* QE instruction RAM) arbitrarily far past the buffer.
|
||||
* hal/nxp_p1021.c checked only the blob's self-consistency (magic,
|
||||
* version, count, length, optional CRC32). The per-microcode
|
||||
* code_offset/count and the total length were never bounded to the
|
||||
* 64 KiB buffer read from NAND, so a structurally valid blob could make
|
||||
* the upload loop read arbitrarily far past it.
|
||||
*
|
||||
* Note: the full recommendation also calls for cryptographic
|
||||
* authentication of the microcode before activation. That is a design
|
||||
* decision (keys, signed manifest, build flow) beyond a minimal patch
|
||||
* and is tracked as a note on the finding; this test covers the
|
||||
* fail-closed bounding that can be fixed in the code.
|
||||
*
|
||||
* The test compiles the real hal/nxp_p1021.c (as nxp_p1021_host.c,
|
||||
* generated by the Makefile) with the PowerPC accessors shadowed by
|
||||
* host equivalents, and drives qe_upload_firmware() directly with
|
||||
* crafted blobs.
|
||||
* Authenticating the microcode before activation is a separate design
|
||||
* question (keys, signed manifest, build flow); this covers only the
|
||||
* fail-closed bounding.
|
||||
*
|
||||
* Compiles the real HAL via nxp_p1021_host.c with the PowerPC accessors
|
||||
* shadowed, and drives qe_upload_firmware() with crafted blobs.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
/* unit-sdhci-dma-error.c
|
||||
*
|
||||
* Regression test: a failed SDMA data transfer must be reported as an error.
|
||||
*
|
||||
* sdhci_transfer() waits for Transfer Complete on the SDMA path and sets
|
||||
* status = -1 if that wait times out. The post-transfer "check for errors"
|
||||
* block then runs unconditionally, and a wolfBoot-side wait timeout does not
|
||||
* necessarily leave an error bit set in SRS12. Before the fix, the CMD12
|
||||
* (stop transmission) result overwrote that -1, so the function returned
|
||||
* success for a transfer that never moved any data.
|
||||
*
|
||||
* The caller then treats a partially filled buffer as a good read. On a
|
||||
* verified-boot target that surfaces much later as an image integrity
|
||||
* failure rather than as the I/O error it actually is -- and where
|
||||
* anti-rollback is enabled, the good lower-versioned slot is refused too,
|
||||
* leaving nothing bootable.
|
||||
* Regression test: a failed SDMA data transfer must be reported as an
|
||||
* error. sdhci_transfer() sets status = -1 when the Transfer Complete
|
||||
* wait times out, but the error-check block that follows runs
|
||||
* unconditionally and a wolfBoot-side timeout need not leave an error
|
||||
* bit in SRS12, so the CMD12 result overwrote the -1 and the function
|
||||
* returned success for a transfer that moved nothing.
|
||||
*
|
||||
* The caller then treats a partially filled buffer as a good read,
|
||||
* which surfaces later as an integrity failure rather than the I/O
|
||||
* error it is -- and with anti-rollback on, the good lower-versioned
|
||||
* slot is refused too.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,26 +1,12 @@
|
|||
/* unit-sdhci-uhs-recover.c
|
||||
*
|
||||
* Regression test: disk_read() called sdhci_uhs_recover()
|
||||
* after any nonzero status from a data transfer, which permanently
|
||||
* switched the host to 1.8V signaling (SDHCI_SRS15_V18SE) on a plain
|
||||
* 3.3V cold boot whenever the first transfer failed for any reason
|
||||
* (CRC, DMA, media, controller). If the retry also failed, the voltage
|
||||
* setting was never rolled back and g_uhs_recovered prevented further
|
||||
* recovery - so a transient error left the host with a signaling level
|
||||
* the card is not using, for the rest of the boot and the stage that
|
||||
* follows it.
|
||||
*
|
||||
* The test compiles the real src/sdhci.c (as sdhci_host.c, generated by
|
||||
* the Makefile). The generated copy differs from the real file only in:
|
||||
* - three `asm volatile` barrier/nop statements blanked (cannot
|
||||
* assemble on x86);
|
||||
* - the real sdhci_read() renamed to sdhci_read_hw() so this file can
|
||||
* provide a scripted sdhci_read() that stands in for the command /
|
||||
* data-transfer state machine.
|
||||
* Register access goes through the platform-provided sdhci_reg_read()/
|
||||
* sdhci_reg_write(), backed here by a host register array, so the test
|
||||
* asserts directly on the SDHCI_SRS15 / SDHCI_SRS11 state.
|
||||
* Regression test: disk_read() called sdhci_uhs_recover() on any read
|
||||
* error, switching the host to 1.8V signaling permanently even when
|
||||
* the retry did not help.
|
||||
*
|
||||
* The controller is scripted through a host register file and
|
||||
* sdhci_read() returns a per-call result from a test-supplied script,
|
||||
* so a chunk can fail, succeed on retry, or fail twice.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,29 +1,13 @@
|
|||
/* unit-sdhci-wait-busy.c
|
||||
*
|
||||
* Regression test: sdhci_wait_busy() had no timeout in
|
||||
* either its DATA0 polling loop or its repeated CMD13 loop (the
|
||||
* in-code TODO acknowledged it). A removed card, a controller fault,
|
||||
* or a card stuck in the programming state left wolfBoot spinning
|
||||
* forever instead of returning an I/O error.
|
||||
*
|
||||
* The test compiles the real src/sdhci.c (as sdhci_host.c, generated
|
||||
* by the Makefile: asm blanked, sdhci_read renamed to sdhci_read_hw)
|
||||
* and scripts the controller through the host register file:
|
||||
* - the DATA0 level (SDHCI_SRS09_DAT0_LVL) stays low for the
|
||||
* data-line timeout case;
|
||||
* - the command always "completes" (SDHCI_SRS12_CC preset) with the
|
||||
* READY_FOR_DATA bit (bit 8) of the response register
|
||||
* (SDHCI_SRS04) cleared, so every CMD13 reports DEVICE_BUSY.
|
||||
* The emulated hal_get_timer_us() advances by a settable step per read,
|
||||
* so the shipped SDHCI_WAIT_BUSY_TIMEOUT_MS is exercised as built --
|
||||
* a 1 ms step reaches the 30 s budget in ~30k iterations -- rather than
|
||||
* against a shrunken stand-in value. Pre-fix, both timeout cases never
|
||||
* return (the test runner's timeout kills them).
|
||||
*
|
||||
* The stub also counts sdhci_platform_wdt_pet() calls: a bounded wait
|
||||
* this long must service the watchdog or it becomes a reset rather than
|
||||
* the clean I/O error it is meant to be.
|
||||
* Regression test: sdhci_wait_busy() had no timeout in either the DAT0
|
||||
* or the CMD13 loop, so a stuck or removed card spun forever.
|
||||
*
|
||||
* The timer stub advances by a settable step, so the shipped
|
||||
* SDHCI_WAIT_BUSY_TIMEOUT_MS is exercised as built rather than against
|
||||
* a shrunken stand-in, and it counts sdhci_platform_wdt_pet() calls: a
|
||||
* wait this long must service the watchdog or it becomes a reset
|
||||
* instead of the clean I/O error it is meant to be.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,27 +1,18 @@
|
|||
/* unit-stm32l5-write.c
|
||||
*
|
||||
* Regression test: hal_flash_write() in hal/stm32l5.c
|
||||
* looped while (i < len) but each iteration unconditionally read both
|
||||
* 32-bit words of the 8-byte program unit (src[i>>2] and
|
||||
* src[(i>>2)+1]) and programmed both, regardless of how many bytes
|
||||
* remained. A write whose length is not a multiple of 8 therefore
|
||||
* read up to 4 bytes past the caller's buffer (which the NSC update
|
||||
* path validates for exactly len) and wrote those bytes to flash.
|
||||
* Regression test: hal_flash_write() in hal/stm32l5.c read both words
|
||||
* of the 8-byte program unit regardless of the remaining length, so a
|
||||
* write not a multiple of 8 read up to 4 bytes past the caller's
|
||||
* buffer and programmed them.
|
||||
*
|
||||
* The test extracts the real hal_flash_wait_complete(),
|
||||
* hal_flash_clear_errors() and hal_flash_write() from hal/stm32l5.c
|
||||
* (generated by the Makefile) and runs them with the FLASH_SR/CR
|
||||
* registers on a host register file and the destination flash at a
|
||||
* host memory address pre-filled with stale data. The source buffer
|
||||
* is followed by a canary: pre-fix, a short write copies the canary
|
||||
* into the destination flash; post-fix the partial final unit is
|
||||
* read-modify-written -- bytes outside [i, len) come from the current
|
||||
* flash content and are stored back unchanged -- so nothing past len
|
||||
* is read or changed. Both words are always stored inside one PG
|
||||
* window, because the flash has no 32-bit program mode; that is a
|
||||
* hardware sequencing property this host model cannot observe, so it
|
||||
* is asserted by construction in hal/stm32l5.c, not here.
|
||||
* The fix read-modify-writes the whole unit: bytes outside [i, len)
|
||||
* come from flash and go back unchanged. Both words are always stored
|
||||
* in one PG window -- the flash has no 32-bit program mode -- which
|
||||
* this host model cannot observe, so that is asserted by construction
|
||||
* in the HAL, not here.
|
||||
*
|
||||
* Same harness as the STM32U5 twin: extracted functions, registers on
|
||||
* a host file, stale destination flash, canary after the source.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,30 +1,20 @@
|
|||
/* unit-stm32u5-write.c
|
||||
*
|
||||
* Regression test: hal_flash_write() in hal/stm32u5.c
|
||||
* looped while (i < len) but each iteration unconditionally read all
|
||||
* four 32-bit words of the 16-byte program unit (src[i>>2] through
|
||||
* src[(i>>2)+3]) and programmed the full quadword regardless of the
|
||||
* remaining length. A write whose length is not a multiple of 16
|
||||
* therefore read up to 12 bytes past the caller's buffer (validated
|
||||
* for exactly len by the NSC update path) and wrote those bytes to
|
||||
* flash.
|
||||
* Regression test: hal_flash_write() in hal/stm32u5.c read all four
|
||||
* words of the 16-byte program unit regardless of the remaining
|
||||
* length, so a write not a multiple of 16 read up to 12 bytes past the
|
||||
* caller's buffer and programmed them.
|
||||
*
|
||||
* The fix read-modify-writes the whole 128-bit unit: bytes outside
|
||||
* [i, len) come from the current flash content and are stored back
|
||||
* unchanged, so the source is never read past len and no flash byte
|
||||
* past len changes value. All four words are always stored, because
|
||||
* the controller only starts the program on the fourth -- that part
|
||||
* is a hardware sequencing property this host model cannot observe,
|
||||
* so it is asserted by construction in hal/stm32u5.c, not here.
|
||||
*
|
||||
* The test extracts the real hal_flash_wait_complete(),
|
||||
* hal_flash_clear_errors() and hal_flash_write() from hal/stm32u5.c
|
||||
* (generated by the Makefile) and runs them with the FLASH_NS_SR/CR
|
||||
* registers on a host register file and the destination flash at a
|
||||
* 32-bit host address pre-filled with stale data. The source buffer
|
||||
* is followed by a canary: pre-fix, a short write copies bytes past
|
||||
* len into the destination flash.
|
||||
* The fix read-modify-writes the whole unit: bytes outside [i, len)
|
||||
* come from flash and go back unchanged. All four words are always
|
||||
* stored -- the controller only starts the program on the fourth --
|
||||
* which this host model cannot observe, so that part is asserted by
|
||||
* construction in the HAL, not here.
|
||||
*
|
||||
* The real functions are extracted by the Makefile and run with the
|
||||
* FLASH registers on a host register file and the destination flash
|
||||
* pre-filled with stale data; a canary after the source buffer catches
|
||||
* any read past len.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,19 +1,14 @@
|
|||
/* unit-t10xx-dts-memac.c
|
||||
*
|
||||
* Regression test: the fsl,fman-memac loop in
|
||||
* hal_dts_fixup() (hal/nxp_t10xx.c) read the node's cell-index
|
||||
* straight from the device tree and used it to index the file-static
|
||||
* phydevs[5] with no bounds check - unlike the qman-portal loop right
|
||||
* above it. Standard NXP FMan device trees assign the 10G MACs
|
||||
* cell-index 8/9, so any such DTB read past the array and wrote the
|
||||
* result into the kernel device tree as a MAC address.
|
||||
*
|
||||
* The test compiles the real src/fdt.c (wolfBoot's libfdt subset) and
|
||||
* the real hal_dts_fixup() (extracted by the Makefile from
|
||||
* hal/nxp_t10xx.c, along with its liodn/qman static tables), feeds it
|
||||
* hand-built DTBs, and checks the resulting local-mac-address
|
||||
* properties.
|
||||
* Regression test: the fsl,fman-memac loop in hal_dts_fixup()
|
||||
* (hal/nxp_t10xx.c) took the node's cell-index straight from the device
|
||||
* tree and indexed the static phydevs[5] with it, unlike the qman-portal
|
||||
* loop above. NXP device trees give the 10G MACs cell-index 8/9, so such
|
||||
* a DTB read past the array and wrote the result back as a MAC address.
|
||||
*
|
||||
* Compiles the real src/fdt.c and hal_dts_fixup() (extracted by the
|
||||
* Makefile with its static tables), feeds it hand-built DTBs and checks
|
||||
* the resulting local-mac-address properties.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
/* unit-t10xx-qe-firmware.c
|
||||
*
|
||||
* Regression test: qe_check_firmware() in hal/nxp_t10xx.c
|
||||
* validated the QE microcode header for self-consistency (magic,
|
||||
* version, count, length == computed size) but never bounded the
|
||||
* Regression test: qe_check_firmware() in hal/nxp_t10xx.c validated the
|
||||
* microcode header for self-consistency but never bounded the
|
||||
* per-microcode code_offset against the declared image length.
|
||||
* qe_upload_firmware() then reads code_offset + 4*count bytes from
|
||||
* the firmware start and copies them into QE IRAM (and programs the
|
||||
* microcode's trap table), so a structurally valid blob with an
|
||||
* out-of-image offset makes wolfBoot copy arbitrary memory into the
|
||||
* engine and run unauthenticated microcode with serial DMA enabled
|
||||
* before the image is authenticated.
|
||||
*
|
||||
* The test extracts the real qe_* structures and qe_check_firmware()
|
||||
* from hal/nxp_t10xx.c (generated by the Makefile) and builds the
|
||||
* blobs in memory. The check-only path needs no register access.
|
||||
* qe_upload_firmware() then copies code_offset + 4*count bytes into QE
|
||||
* IRAM and programs the trap table, so a structurally valid blob with
|
||||
* an out-of-image offset runs unauthenticated microcode with serial DMA
|
||||
* enabled before the image is authenticated.
|
||||
*
|
||||
* Extracts the qe_* structures and qe_check_firmware() (generated by
|
||||
* the Makefile) and builds the blobs in memory; the check-only path
|
||||
* needs no register access.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
/* unit-t2080-fman-loader.c
|
||||
*
|
||||
* Regression test: hal_fman_init() in hal/nxp_t2080.c
|
||||
* checked only the NOR window guard and the QEF magic, then copied
|
||||
* fw->microcode[i].count words from fw + code_offset into FMan
|
||||
* instruction RAM and marked the engine ready. No version, count,
|
||||
* length self-consistency, or code-offset validation: a structurally
|
||||
* valid-looking blob with an out-of-image offset made the loader
|
||||
* copy arbitrary memory into FMan IRAM (and a count of zero was
|
||||
* accepted as a successful "upload" of nothing).
|
||||
*
|
||||
* The test extracts the real qe_* structures and hal_fman_init() from
|
||||
* hal/nxp_t2080.c (generated by the Makefile) and runs them against a
|
||||
* test-owned NOR image (the FMAN slot sits at a nonzero offset in the
|
||||
* bank, so the remaining-extent check is exercised) and an emulated
|
||||
* FMan IRAM data register (set32/get32 on a host register array).
|
||||
* Regression test: hal_fman_init() in hal/nxp_t2080.c checked only the
|
||||
* NOR window guard and the QEF magic, then copied microcode words into
|
||||
* FMan instruction RAM and marked the engine ready. With no version,
|
||||
* count, length or code-offset validation, a valid-looking blob with an
|
||||
* out-of-image offset copied arbitrary memory into IRAM, and a count of
|
||||
* zero counted as a successful upload of nothing.
|
||||
*
|
||||
* Extracts the qe_* structures and hal_fman_init() (generated by the
|
||||
* Makefile) and runs them against a test-owned NOR image, with the FMAN
|
||||
* slot at a nonzero bank offset so the extent check is exercised.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
/* unit-ti-hercules-write.c
|
||||
*
|
||||
* Regression test: the short-write path of hal_flash_write()
|
||||
* in hal/ti_hercules.c checked only len < WRITE_BLOCK_SIZE, not whether
|
||||
* (address % WRITE_BLOCK_SIZE) + len stayed inside the block. A short
|
||||
* write starting near the end of a block copied past the end of the
|
||||
* WRITE_BLOCK_SIZE stack staging buffer (memcpy(temp + off, data, len))
|
||||
* and programmed only the first block, losing the bytes intended for
|
||||
* the next block.
|
||||
*
|
||||
* hal/ti_hercules.c needs the TI FAPI vendor headers (board build tree)
|
||||
* and cannot be compiled on the host, but the bug is entirely in the
|
||||
* staging logic of hal_flash_write(), so the Makefile extracts
|
||||
* hal_flash_unlock_helper() and hal_flash_write() verbatim from
|
||||
* hal/ti_hercules.c (ti_hercules_write_extract.h) and runs them here
|
||||
* against emulated FAPI calls; Fapi_issueProgrammingCommand() performs
|
||||
* the program into a host flash array, so the test asserts on the
|
||||
* flash contents.
|
||||
* Regression test: the short-write path of hal_flash_write() in
|
||||
* hal/ti_hercules.c checked only len < WRITE_BLOCK_SIZE, not whether
|
||||
* the write stayed inside the block. A short write near a block end
|
||||
* copied past the staging buffer and programmed only the first block,
|
||||
* losing the bytes meant for the next one.
|
||||
*
|
||||
* The HAL needs the TI FAPI vendor headers and cannot be built on the
|
||||
* host, but the bug is in the staging logic, so the Makefile extracts
|
||||
* hal_flash_write() and its unlock helper and runs them against an
|
||||
* emulated FAPI. The emulated FSM stays busy for a few polls and holds
|
||||
* the data back until it drains, so a missing wait is observable.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
/* unit-versal-ext-write.c
|
||||
*
|
||||
* Regression test: ext_flash_write() in hal/versal.c
|
||||
* chunked the request into length-based FLASH_PAGE_SIZE transfers
|
||||
* (page 0, page 1, ...) without accounting for the start address's
|
||||
* offset inside the physical page. A write starting mid-page sent a
|
||||
* full-page Page Program across the boundary; NOR wraps the write
|
||||
* pointer at the page start, so the excess bytes clobbered the
|
||||
* beginning of the page.
|
||||
*
|
||||
* hal/versal.c cannot be compiled on the host in its entirety for
|
||||
* this test (the QspiDev_t typedef and the static qspi_* helpers are
|
||||
* file-local), so the Makefile extracts the QspiDev_t struct and the
|
||||
* real ext_flash_write() verbatim (versal_ext_write_extract.h) and
|
||||
* runs them against test-owned qspiDev/qspi_initialized state and
|
||||
* emulated qspi_write_enable()/qspi_transfer()/qspi_wait_ready()/
|
||||
* qspi_write_disable(). The emulated NOR models the real wrap: a
|
||||
* crossing program overwrites the page start it wraps into, so
|
||||
* pre-fix the corruption is observable in the flash image.
|
||||
* Regression test: ext_flash_write() in hal/versal.c chunked by length
|
||||
* alone, ignoring where the start address sat inside the physical page.
|
||||
* A write starting mid-page sent a full-page Page Program across the
|
||||
* boundary, and NOR wraps the write pointer, so the excess clobbered
|
||||
* the start of the page.
|
||||
*
|
||||
* The QspiDev_t typedef and the qspi_* helpers are file-local, so the
|
||||
* Makefile extracts the struct and ext_flash_write() verbatim and runs
|
||||
* them against emulated qspi_* calls. The emulated NOR models the wrap,
|
||||
* so pre-fix the corruption is visible in the flash image.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,25 +1,15 @@
|
|||
/* unit-versal-qspi-dma.c
|
||||
*
|
||||
* Regression test: the DMA RX path of qspi_transfer() in
|
||||
* hal/versal.c. For an unaligned destination or a length not divisible
|
||||
* by four, the transfer runs through the 4096-byte dma_tmpbuf. If the
|
||||
* requested rxLen exceeded the temp buffer, dmaLen was truncated to
|
||||
* sizeof(dma_tmpbuf) (so only that much was DMA'd), but the code then
|
||||
* copied the full rxLen out with memcpy(rxData, dmaPtr, rxLen) - reading
|
||||
* past the end of dma_tmpbuf and reporting the whole read as successful.
|
||||
*
|
||||
* The test compiles the real hal/versal.c (as versal_host.c, generated
|
||||
* by the Makefile). The generated copy differs from the real file only
|
||||
* in:
|
||||
* - ARM asm statements blanked (cannot assemble on x86; the cache
|
||||
* maintenance helpers become no-ops, which is harmless because the
|
||||
* DMA is emulated below);
|
||||
* - VERSAL_QSPI_BASE rebased onto g_vqspi_regs (real register
|
||||
* offsets are preserved);
|
||||
* - the real qspi_dma_wait() renamed to qspi_dma_wait_hw() so this
|
||||
* file can provide a qspi_dma_wait() that performs the DMA move the
|
||||
* hardware would do (flash -> GQSPIDMA_DST, GQSPIDMA_SIZE bytes).
|
||||
* Regression test: the DMA RX path of qspi_transfer() in hal/versal.c.
|
||||
* An unaligned or non-multiple-of-four read goes through a 4096-byte
|
||||
* temp buffer; when rxLen exceeded it, dmaLen was truncated but the
|
||||
* copy out still used the full rxLen, reading past the buffer and
|
||||
* reporting success.
|
||||
*
|
||||
* Compiles the real HAL via versal_host.c (generated by the Makefile),
|
||||
* which differs only in that ARM asm is blanked or rewritten, the QSPI
|
||||
* base is rebased onto a host array, and qspi_dma_wait() is renamed so
|
||||
* this file can supply one that performs the DMA move.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
/* unit-zynq-erase-loop.c
|
||||
*
|
||||
* Regression test: ext_flash_erase() in hal/zynq.c initializes
|
||||
* idx once before the multi-sector while (len > 0) loop and never resets
|
||||
* it, even though cmd is memset to zero each iteration. From the second
|
||||
* sector on, the erase command is written at cmd[idx] (past the start of
|
||||
* the buffer): in three-byte address mode the flash receives leading zero
|
||||
* bytes before the opcode (malformed command, erase silently fails); in
|
||||
* four-byte address mode the writes run past the end of the 8-byte cmd
|
||||
* buffer. The loop also kept going - and could return success - after a
|
||||
* failed write-enable, transfer, or ready wait.
|
||||
*
|
||||
* hal/zynq.c cannot be compiled on the host (it needs the Xilinx SDK
|
||||
* headers, which are provided by the board build tree), but the bug is
|
||||
* entirely in the ext_flash_erase() loop, so the Makefile extracts that
|
||||
* one function verbatim from hal/zynq.c (zynq_erase_extract.h) and runs
|
||||
* it here against emulated qspi_* functions that record every operation.
|
||||
* Regression test: ext_flash_erase() in hal/zynq.c set idx once before
|
||||
* the multi-sector loop and never reset it, though cmd is cleared each
|
||||
* iteration. From the second sector on the opcode landed at cmd[idx]:
|
||||
* malformed commands in three-byte address mode, writes past the 8-byte
|
||||
* buffer in four-byte mode. The loop also continued, and could return
|
||||
* success, after a failed write-enable, transfer or ready wait.
|
||||
*
|
||||
* hal/zynq.c needs the Xilinx SDK headers and cannot be built on the
|
||||
* host, so the Makefile extracts the one function and runs it against
|
||||
* emulated qspi_* calls that record every operation.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
/* unit-zynq-ext-write.c
|
||||
*
|
||||
* Regression test: ext_flash_write() in hal/zynq.c divided
|
||||
* the request into length-based FLASH_PAGE_SIZE chunks (page 0, page
|
||||
* 1, ...) without accounting for the start address's offset inside
|
||||
* the device page. A write starting mid-page sent a full-page Page
|
||||
* Program across the boundary; NOR wraps the write pointer at the
|
||||
* page start, so the excess bytes clobbered the beginning of the
|
||||
* page.
|
||||
*
|
||||
* As in unit-zynq-erase-loop, hal/zynq.c cannot be compiled on the
|
||||
* host (Xilinx SDK headers), so the Makefile extracts ext_flash_write()
|
||||
* verbatim (zynq_write_extract.h) and runs it against emulated
|
||||
* qspi_* functions. The emulated NOR models the real wrap: a Page
|
||||
* Program crossing the boundary overwrites the page start it wraps
|
||||
* into, so pre-fix the corruption is observable in the flash image.
|
||||
* Regression test: ext_flash_write() in hal/zynq.c chunked by length
|
||||
* alone, ignoring the start address's offset inside the device page. A
|
||||
* write starting mid-page sent a full-page Page Program across the
|
||||
* boundary, and NOR wraps the write pointer, so the excess clobbered
|
||||
* the start of the page.
|
||||
*
|
||||
* As with unit-zynq-erase-loop the HAL cannot be built on the host, so
|
||||
* the Makefile extracts ext_flash_write() and runs it against emulated
|
||||
* qspi_* calls. The emulated NOR models the wrap, so pre-fix the
|
||||
* corruption is visible in the flash image.
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
|
|
|
|||
Loading…
Reference in New Issue