diff --git a/changelog.md b/changelog.md index 9c4b5bbe..1033984b 100644 --- a/changelog.md +++ b/changelog.md @@ -18,6 +18,7 @@ it and is upstream Adafruit history, kept for provenance. - A DFU session started after a SoftDevice update no longer ends before it begins. - Build change, no behavior change: the bootloader is now compiled with `-flto`, which shrinks every image by about 3.3 KB of flash. Section addresses and SoftDevice call sites are unchanged. - The lazy-erase packet buffer holds 16 packets instead of 8. Costs about 2 KB of `.bss`. +- Hardening, no behavior change: `flash_nrf5x_write` splits a write that crosses a 4 KB page instead of running past its page buffer. The UF2 path accepts only 256 B blocks at 256 B-aligned addresses, so no current caller crosses a page. - A UF2 whose application blocks start below the installed SoftDevice's end and carry no SoftDevice (no block at 0x1000) is now rejected as WRONG FILE: every block of the file is rejected and nothing is written. An app-only image built for a different SoftDevice would have overwritten the last page of the installed one. SoftDevice+app images, app-only images at the application start, and `CURRENT.UF2` restores are unaffected; the check assumes the host writes the file front to back. ## OTAFIX 2.5 diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c index 12c6797e..6bbfe257 100644 --- a/src/flash_nrf5x.c +++ b/src/flash_nrf5x.c @@ -60,14 +60,25 @@ void flash_nrf5x_flush (bool need_erase) void flash_nrf5x_write (uint32_t dst, void const *src, int len, bool need_erase) { - uint32_t newAddr = dst & ~(FLASH_PAGE_SIZE - 1); - - if ( newAddr != _fl_addr ) + while ( len > 0 ) { - flash_nrf5x_flush(need_erase); - _fl_addr = newAddr; - memcpy(_fl_buf, (void *) newAddr, FLASH_PAGE_SIZE); + uint32_t newAddr = dst & ~(FLASH_PAGE_SIZE - 1); + + if ( newAddr != _fl_addr ) + { + flash_nrf5x_flush(need_erase); + _fl_addr = newAddr; + memcpy(_fl_buf, (void *) newAddr, FLASH_PAGE_SIZE); + } + + uint32_t offset = dst & (FLASH_PAGE_SIZE - 1); + uint32_t n = FLASH_PAGE_SIZE - offset; + if ( n > (uint32_t) len ) n = (uint32_t) len; + + memcpy(_fl_buf + offset, src, n); + + dst += n; + src = (uint8_t const *) src + n; + len -= (int) n; } - memcpy(_fl_buf + (dst & (FLASH_PAGE_SIZE - 1)), src, len); } -