View this page on MeshCore Docs.
# nRF52 bootloader updates over LoRa For **1.17.1.5**, use the exact board/storage profile from [OTAFIX 2.4.6](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases/tag/0.11.0-OTAFIX2.4.6) for nRF52 OTAFIX installations. New internal-flash hybrid receivers require its 64 KiB retained-RAM handoff; QSPI and microSD targets require their own matching bootloader profiles. Earlier preview versions mentioned below describe compatibility/migration history, not the current recommended download. Full Companion is a MOTA source and normally updates itself over USB. Selected nRF52840 repeater LoRa-OTA builds can replace their matching OTAFIX bootloader without replacing the running application. This is a privileged maintenance path, not a normal firmware update. A stock bootloader must first be replaced with the exact ABI-3 self-update-capable OTAFIX build over USB/BLE DFU or SWD. MeshTower SD also requires the BLM2 retained-auth version to be provisioned locally before either application or bootloader OTA. The released adaptive RAK3401 and RAK4631 OTAFIX 2.4.8/2.4.9 profiles support application full and delta updates, but not bootloader self-update over LoRa. USB UF2 and local Bluetooth/serial Legacy DFU bootloader updates still work. Their running bootloader protects `0xF4000..0x100000` with the nRF52840 ACL before starting MeshCore. This includes the MBR parameter page at `0xFE000`, so an application cannot initiate `COPY_BL` even after verifying a signed bootloader package. Hardware testing on a RAK3401 confirmed the MBR SVC enters a bus fault and leaves the installed bootloader unchanged. For new RAK installations use the normal [OTAFIX 2.4.10](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases/tag/v0.11.0-OTAFIX2.4.10) compatible `*_auto` bootloader. Existing standard `3401_DFU` / `4631_DFU` devices can receive its signed bootloader `.mota` over LoRa. Devices already running `3401_AUTO_DFU` / `4631_AUTO_DFU` need the matching 2.4.10 recovery bridge installed locally before switching to the normal image. ## Storage layouts | Layout | Application limit | Staged boot package | Work area | Handoff / capability | | --- | ---: | ---: | ---: | --- | | XIAO-module raw QSPI | below `0xE0000` | external QSPI offset 0 | dedicated internal `0xE0000..0xEA000` scratch | source `0x51`, flags `0x0E` | | Qualified internal-flash target | normal `0xED000` flash limit; top 64 KiB SRAM reserved for application-delta staging | shared internal slot, exact start `0xE2000` | the same eleven-page slot; no second flash reservation | source `0xED`, flags `0x0A` | | MeshTower V2 microSD | normal `0xED000` limit | contiguous `/meshcore-ota.mota` | dynamic internal `0xE0000..0xEA000` scratch; live image must end by `0xE0000` | source `0x53`, flags `0x09` | The exact SD target is `Heltec_tower_v2_sdcard_repeater_lora_ota_no_external_sensors`. Its normal application FULL and delta updates continue to use the SD file without the bootloader-update scratch restriction. For a bootloader package only, both MeshCore and OTAFIX require a hash-valid live `EndF` proving the complete running image ends at or below `0xE0000`. If boot settings carry a nonzero app bank CRC, the recorded bank size must also cover that full EndF-inclusive image and stop by `0xE0000`; erased or explicitly CRC-disabled settings remain valid. OTAFIX then copies the verified 40 KiB payload from SD into `0xE0000..0xEA000` and uses the MBR copy operation to replace `0xF4000..0xFE000`. The application linker remains at `0xED000`; a future application extending above `0xE0000` can still use application mOTA but must update its bootloader through local DFU/SWD. The removable SD authorization is fail-closed for both application and bootloader packages. MeshCore directly authenticates one exact signed manifest, requires the streamed copy to remain byte-identical, verifies all leaves/payload/image bytes, and computes a normalized full-container SHA-256 in that same pass (`APRV` bytes are treated as zero). After syncing `APRV`, it publishes a 72-byte `MOTASDA2` record in reset-retained RAM at `0x20006008`. That record binds purpose/format, first LBA, sector count, total length, card sector count, and the normalized digest. OTAFIX copies, validates, and clears the record before SD access. A card swap/mutation or a power cycle therefore fails closed; there is no general sector-1 ownership inference. For fmt3, MeshCore also writes and readback-verifies a 64-byte `MOTASDBL` token at `0xE0000`. That token contains the exact container length and the exact authenticated signed manifest `image_hash`. OTAFIX requires the same hash in the parsed manifest, streamed payload, and final scratch image. The page is consumed as scratch during success and is not permanently reserved. The first BLM2-capable MeshTower bootloader cannot be delivered to preview.12 through the retained-RAM protocol that preview.12 predates. MeshCore does not write a raw-sector compatibility record because a blank sector is not proof of ownership. Upgrade preview.12 through USB/BLE DFU or SWD. Both fmt2 application and fmt3 bootloader OTA then require the installed BLM2 metadata to match the live SoftDevice/application layout; neither MeshCore nor OTAFIX uses sector 1. The internal path does not change the application's `0xED000` flash limit or permanently set aside separate app-OTA, boot-package, and flash-scratch regions. Qualified applications do use a dedicated linker that reserves the top 64 KiB of SRAM for hybrid application-delta staging and a retained authorization record. That SRAM is never part of a bootloader-update package. The ordinary bottom-aligned internal flash store holds one container prefix at a time: either an application delta or the complete bootloader package. The exact bootloader container is 41,330 bytes: 365 bytes of signed mOTA metadata, a 40 KiB payload, and the five-byte trailer. Below the normal `0xED000` store ceiling it bottom-aligns at `0xE2000`. Admission requires a hash-valid live `EndF` proving the current application, including its trailer, ends at or before `0xE2000`. OTAFIX then reads each source window before erasing and compacts the payload forward in place to the page-aligned raw range `0xE2000..0xEC000`; it verifies every page and the whole image before asking the MBR to copy that image over `0xF4000..0xFE000`. An ordinary application delta can be smaller or larger than this eleven-page shape. On the qualified profile, a delta larger than one page uses the minimum page-aligned flash prefix ending at `0xED000` and keeps up to 64 KiB of its logical tail in reset-retained SRAM; its detools workspace must stop at the actual flash-prefix start. A one-page-or-smaller delta stays wholly in flash. In either case the reconstructed application must stop below `0xED000`. The two package kinds are mutually exclusive because they use the same flash store, and a bootloader package never uses the volatile SRAM suffix. For internal-self-update builds, an absent or corrupt live `EndF` disables **all** internal staging before the first erase. The older 608 KiB rescue estimate is unsafe when a normally linked application may extend to `0xED000`. Builds without this feature retain the legacy rescue behavior. ## Internal-flash target inventory The release builder consumes the allowlist in `tools/mota/nrf52_internal_bootloader_targets.txt`. Ten names are also literal PlatformIO environments and are enabled automatically when built directly. The other eleven are release aliases assembled from a base environment plus the lean OTA overlay; build them through `build.sh`, which passes the same allowlist decision to the common pre-build guard. These lean repeater/bridge targets have no OTA-owned SD/QSPI store and have an exact curated OTAFIX manifest identity: | Build target(s) | Installed OTAFIX identity | Boot target ID | | --- | --- | ---: | | `Heltec_tower_v2_repeater_lora_ota_no_external_sensors` | `239A0071 / TOWER_V2_OTA` | `1150F50E` | | T096 lean repeater and RS232 bridge | `239A0071 / T096_DFU` | `42354C85` | | `Heltec_t1_repeater_lora_ota_no_external_sensors` | `239A0071 / T1_DFU` | `FC556FFC` | | T114 display and without-display lean repeaters | `239A0071 / T114_DFU` | `0C3F2902` | | `Mesh_pocket_repeater_lora_ota_no_external_sensors` | `239A0071 / MESH_POCKET_OTA` | `059277F4` | | `KeepteenLT1_repeater_lora_ota_no_external_sensors` | `239A00B3 / KeepteenLT1_OTA` | `DB2E7B51` | | `Minewsemi_me25ls01_repeater_lora_ota_no_external_sensors` | `239A0029 / MX25_DFU` | `026AA982` | | `ProMicro_repeater_lora_ota_no_external_sensors` | `239A00B3 / PROM_DFU` | `AF79E8CC` | | `t1000e_repeater_lora_ota_no_external_sensors` | `28860057 / T1KE_DFU` | `E6F5F03F` | | `ThinkNode_M3_repeater_lora_ota_no_external_sensors` | `239A00DA / TNM3_DFU` | `0CA41DB2` | | `RAK_3401_repeater_lora_ota_no_external_sensors` | `239A0029 / 3401_DFU` | `23818A80` | | RAK4631 lean repeater and both lean RS232 bridges | `239A0029 / 4631_DFU` | `2D0DF000` | | GAT562 30S/Tracker Pro/EVB Pro lean targets | `239A0029 / GAT562_DFU` | `D50D2D44` | | `R1Neo_repeater_lora_ota_no_external_sensors` | `239A0029 / 4631_DFU` | `2D0DF000` | | `RAK_WisMesh_Tag_repeater_lora_ota_no_external_sensors` | `239A0029 / RTAG_DFU` | `C72E9C9C` | Board IDs are not globally unique. For generic targets, the signed hardware ID is the exact NUL-padded 32-byte value `NRF_BL_