diff --git a/changelog.md b/changelog.md index 520294b0..3eb80f1c 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,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`. +- 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/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index b09c9f7e..7fd1c943 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -495,8 +495,21 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * | MBR | | MBR | * ------------- ------------- */ + // An image carrying a SoftDevice starts at or below its first page; an app-only image must + // start exactly at the app start. One built for another SoftDevice starts above or below it, + // so every block of that file is rejected and nothing is written. Block 0 opens a new file + // whatever its address (an MBR block at 0x0 included). Assumes the host writes front to back. + if ( bl->blockNo == 0 ) + { + state->sd_start_seen = false; + state->wrong_layout = (bl->targetAddr > DFU_BANK_0_REGION_START); + } if ( in_app_space(bl->targetAddr) ) { + if ( bl->targetAddr == USER_FLASH_START ) state->sd_start_seen = true; + if ( !state->sd_start_seen && bl->targetAddr < DFU_BANK_0_REGION_START ) state->wrong_layout = true; + if ( state->wrong_layout ) goto reject; + screen_set_title(NULL); // a good block after a rejected one clears WRONG FILE PRINTF("Write addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks); flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 6fe0e9e1..b2114679 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -59,6 +59,8 @@ typedef struct { bool has_uicr; // if containing uicr data bool boot_id_matches; // if bootloader id in cf2 config matches our VID/PID bool factory_erase; // if a CFG_UF2_MESHTASTIC_ERASE_ID block was received + bool sd_start_seen; // if the SoftDevice's first page (USER_FLASH_START) was received + bool wrong_layout; // if this file was built for another SoftDevice layout uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; } WriteState;