Skip to content

Commit 27882cd

Browse files
committed
fixed the bootloader start address for simplicity and prevent bricking device
1 parent afeb645 commit 27882cd

File tree

4 files changed

+74
-103
lines changed

4 files changed

+74
-103
lines changed

src/usb/msc_uf2.c

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -191,44 +191,30 @@ void tud_msc_write10_complete_cb(uint8_t lun)
191191
dfu_update_status_t update_status;
192192
memset(&update_status, 0, sizeof(dfu_update_status_t ));
193193

194-
if ( _wr_state.boot_addr_ucir )
194+
if ( _wr_state.update_bootloader )
195195
{
196-
// update bootloader
196+
// update bootloader always end with reset
197197
update_status.status_code = DFU_RESET;
198198

199-
if ( 0 == memcmp((uint8_t*) _wr_state.boot_stored_addr, (uint8_t*) BOOTLOADER_ADDR_START, _wr_state.boot_size) )
200-
{
201-
// skip if there is no bootloader change
202-
}else
203-
{
204-
PRINTF("Coyping bootloader to 0x%08lX from 0x%08lX with size = 0x%lX\r\n",
205-
_wr_state.boot_addr_ucir, _wr_state.boot_stored_addr, _wr_state.boot_size);
199+
// Location of current stored new bootloader
200+
uint32_t * new_bootloader = (uint32_t *) BOOTLOADER_ADDR_NEW_RECIEVED;
201+
202+
PRINT_HEX(new_bootloader);
206203

207-
// erase an change UCIR bootloader
208-
// if ( )
204+
// skip if there is no bootloader change
205+
if ( memcmp(new_bootloader, (uint8_t*) BOOTLOADER_ADDR_START, DFU_BL_IMAGE_MAX_SIZE) )
206+
{
207+
PRINTF("Coyping new bootloader\r\n");
209208

210209
sd_mbr_command_t command =
211210
{
212211
.command = SD_MBR_COMMAND_COPY_BL,
213-
.params.copy_bl.bl_src = (uint32_t*) _wr_state.boot_stored_addr,
214-
.params.copy_bl.bl_len = _wr_state.boot_size/4 // size in words
212+
.params.copy_bl.bl_src = new_bootloader,
213+
.params.copy_bl.bl_len = DFU_BL_IMAGE_MAX_SIZE/4 // size in words
215214
};
216215

217-
if ( NRF_SUCCESS != sd_mbr_command(&command) )
218-
{
219-
PRINTF("Failed to execute SD_MBR_COMMAND_COPY_BL, we are about to bricked\r\n");
220-
}else
221-
{
222-
PRINTF("SD_MBR_COMMAND_COPY_BL successfully\r\n");
223-
}
224-
225-
NRFX_DELAY_MS(10);
226-
// update_status.status_code = DFU_UPDATE_BOOT_COMPLETE;
227-
// update_status.bl_size = _wr_state.boot_size;
228-
//
229-
// // Reuse the DFU combined SD + Bootloader with SD Size = 0
230-
// update_status.sd_image_start = _wr_state.boot_stored_addr;
231-
// update_status.sd_size = 0;
216+
// on success, COPY_BL won't return but run the new bootloader right away.
217+
sd_mbr_command(&command);
232218
}
233219

234220
PRINTF("bootloader update complete\r\n");

src/usb/uf2/ghostfat.c

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -160,19 +160,7 @@ static inline bool in_app_space (uint32_t addr)
160160
// used when upgrading bootloader
161161
static inline bool in_bootloader_space (uint32_t addr)
162162
{
163-
return BOOTLOADER_LOWEST_ADDR <= addr && addr < BOOTLOADER_ADDR_END;
164-
}
165-
166-
static inline uint32_t get_new_bootloader_size(uint32_t numblocks)
167-
{
168-
// -1 for UCIR block
169-
uint32_t new_size = (numblocks-1)*256;
170-
171-
// round up to 4K
172-
uint32_t mod4k = new_size & 0xFFFUL;
173-
if ( mod4k ) new_size += 4096 - mod4k;
174-
175-
return new_size;
163+
return BOOTLOADER_ADDR_START <= addr && addr < BOOTLOADER_ADDR_END;
176164
}
177165

178166
// used when upgrading bootloader
@@ -324,13 +312,13 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
324312
*
325313
* ------------- -------------
326314
* | | | |
327-
* | Bootloader | | Bootloader |
315+
* | Bootloader | | Bootloader |
328316
* BOOTLOADER_ADDR_START--|-------------| |-------------|
317+
* | App Data | | App Data |
318+
* USER_FLASH_END ---|-------------| |-------------|
329319
* | | | |
330-
* | | | |
331-
* | Application | ---> | New |
332-
* | | | Application |
333-
* | | | |
320+
* | | | New |
321+
* | Application | ----> | Application |
334322
* | | | |
335323
* USER_FLASH_START--|-------------| |-------------|
336324
* | MBR | | MBR |
@@ -354,18 +342,16 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
354342
case CFG_UF2_BOOTLOADER_ID:
355343
/* Upgrading Bootloader
356344
*
357-
* Along with bootloader code, UCIR (at 0x1000100) is also included containing
358-
* 0x10001014 (bootloader address), and 0x10001018 (MBR Params address).
345+
* - For simplicity, the Bootloader Start Address is fixed for now.
346+
*
347+
* - Since SoftDevice is not part of Bootloader, it MUST NOT be included as part of uf2 file.
359348
*
360-
* Since SoftDevice is not part of Bootloader, it must not be included as part of uf2 file.
361-
* To prevent generating uf2 from incorrect bin/hex. Bootloader imposes a hard code limit size
362-
* of 64 KB (end address is fixed at MBR Params). If uf2 contains any address lower than this
363-
* (except UCIR) the update is aborted.
349+
* - To prevent corruption/disconnection while transferring we don't directly write over Bootloader.
350+
* Instead it is written to highest possible address in Application region. Once everything is received
351+
* and verified, it is safely activated using MBR COPY BL command.
364352
*
365-
* To prevent corruption/disconnection while transferring we don't directly write over
366-
* Bootloader. Instead it is written to highest possible address in Application
367-
* region. Once everything is received and verified, it is safely activated using
368-
* MBR COPY BL command.
353+
* - Along with bootloader code, UCIR (at 0x1000100) is also included containing
354+
* 0x10001014 (bootloader address), and 0x10001018 (MBR Params address).
369355
*
370356
* Note: part of the existing application can be affected when updating bootloader.
371357
* TODO May be worth to have some kind crc/application integrity checking
@@ -374,11 +360,11 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
374360
* | | | | + | New |
375361
* | Bootloader | | Bootloader | + | Bootloader |
376362
* BOOTLOADER_ADDR_START--|-------------| |-------------| + |-------------|
377-
* | | | New | + | |
378-
* | | | Bootloader | + | |
379-
* | | | ++++++++ | | |
380-
* | | ---> | | | |
381-
* | | | | | |
363+
* | App Data | | App Data | + | App Data |
364+
* USER_FLASH_END --|-------------| | ---------- | + |------------ |
365+
* | | | New |+ | |
366+
* | | ---> | Bootloader | | |
367+
* | | | ++++++ | | |
382368
* | Application | | Application | | Application |
383369
* | | | | | |
384370
* | | | | | |
@@ -388,54 +374,53 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
388374
*/
389375
PRINTF("addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks);
390376

391-
uint32_t const new_boot_size = get_new_bootloader_size(bl->numBlocks);
392-
393-
// Offset write the new bootloader address.
394-
// The offset is the current bootloader size or the new size whichever is larger
395-
uint32_t const offset_addr = max32(new_boot_size, BOOTLOADER_ADDR_END-BOOTLOADER_ADDR_START);
396-
377+
state->update_bootloader = true;
397378
if ( in_uicr_space(bl->targetAddr) )
398379
{
399380
/* UCIR contains bootloader & MBR address as follow:
400-
* - 0x10001014 bootloader address: only change if bootloader size changes
381+
* - 0x10001014 bootloader address
401382
* - 0x10001018 MBR Params: mostly fixed
402383
*
403-
* WARNING: incorrect value of these UCIR will brick device
384+
* Since the bootloader start address is fixed, we only use this for verification
404385
*/
405-
uint32_t ucir_boot_addr;
406-
uint32_t ucir_mbr_param;
386+
uint32_t uicr_boot_addr;
387+
uint32_t uicr_mbr_param;
407388

408-
memcpy(&ucir_boot_addr, bl->data + 0x14, 4);
409-
memcpy(&ucir_mbr_param, bl->data + 0x18, 4);
410-
411-
PRINT_HEX(ucir_boot_addr);
412-
PRINT_HEX(ucir_mbr_param);
413-
414-
PRINT_HEX(new_boot_size);
389+
memcpy(&uicr_boot_addr, bl->data + 0x14, 4);
390+
memcpy(&uicr_mbr_param, bl->data + 0x18, 4);
415391

416392
// Check MBR params is fixed and prohibited to change and
417393
// Bootloader address against its new size
418-
if ( (ucir_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) ||
419-
(ucir_boot_addr != BOOTLOADER_ADDR_END - new_boot_size) )
394+
if ( (uicr_boot_addr != BOOTLOADER_ADDR_START) ||
395+
(uicr_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) )
420396
{
421-
PRINTF("Incorrect UCIR value");
397+
PRINTF("Incorrect UICR value");
398+
PRINT_HEX(uicr_boot_addr);
399+
PRINT_HEX(uicr_mbr_param);
400+
422401
state->aborted = true;
423402
return -1;
424-
}else
425-
{
426-
// Good to go, save the boot address
427-
state->boot_addr_ucir = ucir_boot_addr;
428-
state->boot_size = new_boot_size;
429-
state->boot_stored_addr = BOOTLOADER_ADDR_END - (new_boot_size + offset_addr);
430-
431-
PRINT_HEX(state->boot_stored_addr);
432403
}
404+
405+
state->has_uicr = true;
433406
}
434-
else if ( in_bootloader_space(bl->targetAddr) && (bl->targetAddr >= BOOTLOADER_LOWEST_ADDR) )
407+
else if ( in_bootloader_space(bl->targetAddr) )
435408
{
436-
// PRINT_HEX(offset_addr);
409+
// Offset to write the new bootloader address (skipping the App Data)
410+
uint32_t const offset_addr = BOOTLOADER_ADDR_END-USER_FLASH_END;
437411
flash_nrf5x_write(bl->targetAddr-offset_addr, bl->data, bl->payloadSize, true);
438412
}
413+
#if 0 // don't allow bundle SoftDevice to prevent confusion
414+
else if ( in_app_space(bl->targetAddr) )
415+
{
416+
// Should be Softdevice
417+
flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true);
418+
}
419+
else if ( bl->targetAddr < USER_FLASH_START )
420+
{
421+
PRINTF("skip writing to MBR\r\n");
422+
}
423+
#endif
439424
else
440425
{
441426
state->aborted = true;
@@ -478,7 +463,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
478463
flash_nrf5x_flush(true);
479464

480465
// Failed if update bootloader without UCIR value
481-
if ( (bl->familyID == CFG_UF2_BOOTLOADER_ID) && !state->boot_addr_ucir )
466+
if ( state->update_bootloader && !state->has_uicr )
482467
{
483468
state->aborted = true;
484469
}

src/usb/uf2/uf2.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,8 @@ typedef struct {
5454
uint32_t numWritten;
5555

5656
bool aborted; // aborting update and reset
57-
uint32_t boot_addr_ucir; // if ucir bootloader address value
58-
uint32_t boot_size; // new bootloader size
59-
uint32_t boot_stored_addr; // temporary base address storing new bootloader
57+
bool update_bootloader; // if updating bootloader (else app)
58+
bool has_uicr; // if containing uicr data
6059

6160
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
6261
} WriteState;

src/usb/uf2/uf2cfg.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex
1212
#define USER_FLASH_END 0xAD000
1313

14-
// Current Bootloader start address
15-
#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START
14+
// Due to SD_MBR_COMMAND_COPY_BL, bootloader start address cannot
15+
// be changed with DFU, and only done with a debugger
1616

17-
// Bootloader end address which is always fixed
18-
#define BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS
17+
// Bootloader start address
18+
#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START
1919

20-
// 64 KB is hard coded limit size for bootloader when updating.
21-
// This is used as sanity check to make sure user doesn't make mistake
22-
// converting wrong bin/hex into uf2 file for bootloader.
23-
#define BOOTLOADER_LOWEST_ADDR (BOOTLOADER_ADDR_END - 64*1024)
20+
// Bootloader end address
21+
#define BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS
22+
23+
// Address where new bootloader is written before activation (skip application data)
24+
#define BOOTLOADER_ADDR_NEW_RECIEVED (USER_FLASH_END-DFU_BL_IMAGE_MAX_SIZE)

0 commit comments

Comments
 (0)