/********************************************************************* * @fn OADTarget_imgBlockWrite * * @brief Process the Image Block Write. * * @param connHandle - connection message was received on * @param pValue - pointer to data to be written * * @return status */ bStatus_t OADTarget_imgBlockWrite(uint16_t connHandle, uint8_t *pValue) { volatile uint16_t blkNum; blkNum = BUILD_UINT16(pValue[0], pValue[1]); // First block of OAD which included image header and CRC and CRC shadow // values. Do a sanity check on the received image header if (blkNum == 0) { img_hdr_t ImgHdr; uint16_t blkTot; blkTot = BUILD_UINT16(pValue[8], pValue[9]) / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE); // Read out running image's header. uint8_t *flashAddr = (uint8_t *)(APP_IMAGE_START + OAD_IMG_HDR_OSET); memcpy(&ImgHdr,flashAddr,sizeof(img_hdr_t)); // Note: if additional customer criteria was checked in the Image // Identification step, it may be important to check again here. if ((oadBlkNum != blkNum) || (oadBlkTot != blkTot) ) { // Cancel download OADTarget_rejectImage(connHandle, &ImgHdr); // NB! This is meaningless for a WriteNoResp operation return (ATT_ERR_WRITE_NOT_PERMITTED); } #ifdef POWER_SAVING Power_setConstraint(Power_SB_DISALLOW); #endif } // Check that this is the expected block number. if (oadBlkNum == blkNum && flashOk) { uint32_t addr; // Calculate address to write as (start of OAD range) + (offset) addr = APP_IMAGE_START + oadBlkNum * OAD_BLOCK_SIZE; // If address starts a new page, erase that page first. if ((addr % HAL_FLASH_PAGE_SIZE) == 0) { flashOk = extFlashErase(addr, HAL_FLASH_PAGE_SIZE); } // Write a 16 byte block to Flash. if (flashOk) { flashOk = extFlashWrite(addr, OAD_BLOCK_SIZE, pValue+2); // Increment received block count. if (flashOk) oadBlkNum++; } // Toggle Green LED for every 8th block if ( (oadBlkNum % 8) == 0) { GPIO_toggle(Board_LED2); } } else { img_hdr_t ImgHdr; // Toggle RED LED and sound buzzer when overflow GPIO_toggle(Board_LED1); GPIO_toggle(Board_BUZZER); #ifdef POWER_SAVING Power_releaseConstraint(Power_SB_DISALLOW); #endif // Cancel download ImgHdr.len = 0; // Don't care content OADTarget_rejectImage(connHandle, &ImgHdr); } // Check if the OAD Image is complete. if (oadBlkNum == oadBlkTot) { extFlashClose(); // Run CRC check on new image. if (checkDL()) { HAL_SYSTEM_RESET(); } else { GPIO_toggle(Board_LED1); } #ifdef POWER_SAVING Power_releaseConstraint(Power_SB_DISALLOW); #endif } else { // Request the next OAD Image block. OADTarget_getNextBlockReq(connHandle, oadBlkNum); } return (SUCCESS); }
/********************************************************************* * @fn oadImgBlockWrite * * @brief Process the Image Block Write. * * @param connHandle - connection message was received on * @param pValue - pointer to data to be written * * @return status */ static bStatus_t oadImgBlockWrite( uint16 connHandle, uint8 *pValue ) { uint16 blkNum = BUILD_UINT16( pValue[0], pValue[1] ); // make sure this is the image we're expecting if ( blkNum == 0 ) { img_hdr_t ImgHdr; uint16 ver = BUILD_UINT16( pValue[6], pValue[7] ); uint16 blkTot = BUILD_UINT16( pValue[8], pValue[9] ) / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE); HalFlashRead(OAD_IMG_R_PAGE, OAD_IMG_HDR_OSET, (uint8 *)&ImgHdr, sizeof(img_hdr_t)); if ( ( oadBlkNum != blkNum ) || ( oadBlkTot != blkTot ) || ( OAD_IMG_ID( ImgHdr.ver ) == OAD_IMG_ID( ver ) ) ) { return ( ATT_ERR_WRITE_NOT_PERMITTED ); } } if (oadBlkNum == blkNum) { uint16 addr = oadBlkNum * (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE) + (OAD_IMG_D_PAGE * OAD_FLASH_PAGE_MULT); oadBlkNum++; #if defined FEATURE_OAD_SECURE if (blkNum == 0) { // Stop attack with crc0==crc1 by forcing crc1=0xffff. pValue[4] = 0xFF; pValue[5] = 0xFF; } #endif #if defined HAL_IMAGE_B // Skip the Image-B area which lies between the lower & upper Image-A parts. if (addr >= (OAD_IMG_B_PAGE * OAD_FLASH_PAGE_MULT)) { addr += OAD_IMG_B_AREA * OAD_FLASH_PAGE_MULT; } #endif if ((addr % OAD_FLASH_PAGE_MULT) == 0) { HalFlashErase(addr / OAD_FLASH_PAGE_MULT); } HalFlashWrite(addr, pValue+2, (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE)); } if (oadBlkNum == oadBlkTot) // If the OAD Image is complete. { #if defined FEATURE_OAD_SECURE HAL_SYSTEM_RESET(); // Only the secure OAD boot loader has the security key to decrypt. #else if (checkDL()) { #if !defined HAL_IMAGE_A // The BIM always checks for a valid Image-B before Image-A, // so Image-A never has to invalidate itself. uint16 crc[2] = { 0x0000, 0xFFFF }; uint16 addr = OAD_IMG_R_PAGE * OAD_FLASH_PAGE_MULT + OAD_IMG_CRC_OSET / HAL_FLASH_WORD_SIZE; HalFlashWrite(addr, (uint8 *)crc, 1); #endif HAL_SYSTEM_RESET(); } #endif } else // Request the next OAD Image block. { oadImgBlockReq(connHandle, oadBlkNum); } return ( SUCCESS ); }