static enum dfu_status finish_write( void *buf, size_t off, size_t len ) { void *target; if (len == 0) return (DFU_STATUS_OK); target = flash_get_staging_area(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE); if (!target) return (DFU_STATUS_errADDRESS); memcpy(target, buf, len); if (flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) != 0) return (DFU_STATUS_errADDRESS); return (DFU_STATUS_OK); }
int flash_program_sector(const uint8_t *buf, uintptr_t addr, size_t len) { int ret = 0; ret = ret || (len != FLASH_SECTOR_SIZE); ret = ret || ((addr & (FLASH_SECTOR_SIZE - 1)) != 0); ret = ret || flash_erase_sector(addr); for (int i = FLASH_SECTOR_SIZE / FLASH_SECTION_SIZE; i > 0; --i) { memcpy(flash_get_staging_area(addr, FLASH_SECTION_SIZE), buf, FLASH_SECTION_SIZE); ret = ret || flash_program_section(addr, FLASH_SECTION_SIZE); buf += FLASH_SECTION_SIZE; addr += FLASH_SECTION_SIZE; } return (ret); }
static enum dfu_status finish_write( void *buf, size_t off, size_t len ) { void *target; // If nothing left to flash, this is still ok if ( len == 0 ) { return DFU_STATUS_OK; } if ( off == 0 && dfu_ctx.verified == DFU_VALIDATION_UNKNOWN ) { // Reset offset dfu_ctx.off = 0; // First block, if using Chip_validation, skip flashing this block and use for key validation // When key disabled, we supported a key'd file OR a non-key'd file switch ( Chip_validation( (uint8_t*)buf ) ) { // Key disabled, no key case 0: dfu_ctx.verified = DFU_VALIDATION_OK; break; // Invalid key case -1: dfu_ctx.verified = DFU_VALIDATION_FAILED; return DFU_STATUS_errFILE; // Valid key, or Key disabled and a key. default: dfu_ctx.verified = DFU_VALIDATION_PENDING; print( "Valid firmware key" NL ); // Do not use this block return DFU_STATUS_OK; } } // If the binary is larger than the internal flash, error if ( off + (uintptr_t)&_app_rom + len > (uintptr_t)&_app_rom_end ) { return DFU_STATUS_errADDRESS; } target = flash_get_staging_area( off + (uintptr_t)&_app_rom, USB_DFU_TRANSFER_SIZE ); if ( !target ) { return DFU_STATUS_errADDRESS; } memcpy( target, buf, len ); // Depending on the error return a different status switch ( flash_program_sector( off + (uintptr_t)&_app_rom, USB_DFU_TRANSFER_SIZE ) ) { /* case FTFL_FSTAT_RDCOLERR: // Flash Read Collision Error case FTFL_FSTAT_ACCERR: // Flash Access Error case FTFL_FSTAT_FPVIOL: // Flash Protection Violation Error return DFU_STATUS_errADDRESS; case FTFL_FSTAT_MGSTAT0: // Memory Controller Command Completion Error return DFU_STATUS_errADDRESS; */ case 0: default: // No error return DFU_STATUS_OK; } }