/*********************************************************************
 * @fn      OADTarget_validateNewImage
 *
 * @brief   Determine if a new image should be downloaded or not based on
 *          target specific criteria.
 *
 * @param   pValue - pointer to new Image header information
 * @param   ImgHdr - pointer to contents of current image header
 * @param   blkTot - total number of blocks comprising new image.
 *
 * @return  TRUE to begin OAD otherwise FALSE to reject the image.
 */
uint8_t OADTarget_validateNewImage(uint8_t *pValue, img_hdr_t *ImgHdr, 
                                          uint16_t blkTot)
{
  uint8_t ret = FALSE;
  img_hdr_t rxHdr;
  
  rxHdr.ver = BUILD_UINT16(pValue[0], pValue[1]);
  rxHdr.len = BUILD_UINT16(pValue[2], pValue[3]);
  
  /* Requirements to begin OAD:
   * 1) LSB of image version cannot be the same, this would imply a code overlap
   *    between currently running image and new image.
   * 2) Total blocks of new image must not exceed maximum blocks supported, else
   *    the new image cannot fit.
   * 3) Block total must be greater than 0.
   * 4) Optional: Add additional criteria for initiating OAD here.
   */
  if ((OAD_IMG_ID(ImgHdr->ver) != OAD_IMG_ID(rxHdr.ver)) &&
      (blkTot <= OAD_BLOCK_MAX) &&
      (blkTot != 0))
  {
    ret = TRUE;
  }
  
  return ret;
}
Example #2
0
/*********************************************************************
 * @fn      oadImgIdentifyWrite
 *
 * @brief   Process the Image Identify Write.
 *
 * @param   connHandle - connection message was received on
 * @param   pValue - pointer to data to be written
 *
 * @return  status
 */
static bStatus_t oadImgIdentifyWrite( uint16 connHandle, uint8 *pValue )
{
  img_hdr_t rxHdr;
  img_hdr_t ImgHdr;

  rxHdr.ver = BUILD_UINT16( pValue[0], pValue[1] );
  rxHdr.len = BUILD_UINT16( pValue[2], pValue[3] );

  (void)osal_memcpy(rxHdr.uid, pValue+4, sizeof(rxHdr.uid));

  HalFlashRead(OAD_IMG_R_PAGE, OAD_IMG_HDR_OSET, (uint8 *)&ImgHdr, sizeof(img_hdr_t));

  oadBlkTot = rxHdr.len / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE);

  if ( (OAD_IMG_ID( ImgHdr.ver ) != OAD_IMG_ID( rxHdr.ver )) && // TBD: add customer criteria for initiating OAD here.
       (oadBlkTot <= OAD_BLOCK_MAX) &&
       (oadBlkTot != 0) )
  {
    oadBlkNum = 0;
    oadImgBlockReq(connHandle, 0);
  }
  else
  {
    oadImgIdentifyReq(connHandle, &ImgHdr);
  }

  return ( SUCCESS );
}
Example #3
0
/*********************************************************************
 * @fn      oadManagerHandleNoti
 *
 * @brief   Handle Notifications and Indications.
 *
 * @return  none
 */
static void oadManagerHandleNoti(attHandleValueNoti_t *pNoti)
{
  if (pNoti->handle == oadManagerHandles[OAD_CHAR_IMG_IDENTIFY])
  {
#if (defined HAL_LCD && (HAL_LCD == TRUE))
    uint16 ver = BUILD_UINT16(pNoti->value[0], pNoti->value[1]);
    uint8 userId[12] = "UserId ";

    osal_memcpy(&(userId[7]), &(pNoti->value[4]), 4);
    userId[11] = '\0';

    if ( OAD_IMG_ID( ver ) == 0 )
    {
        HalLcdWriteStringValueValue("ImgA Id", OAD_VER_NUM( ver ), 16,
                                               BUILD_UINT16(pNoti->value[2], pNoti->value[3]), 16,
                                               HAL_LCD_LINE_2);
    }
    else
    {
        HalLcdWriteStringValueValue("ImgB Id", OAD_VER_NUM( ver ), 16,
                                               BUILD_UINT16(pNoti->value[2], pNoti->value[3]), 16,
                                               HAL_LCD_LINE_2);
    }

    HalLcdWriteString((char*)userId, HAL_LCD_LINE_3);
#endif
  }
  else if (pNoti->handle == oadManagerHandles[OAD_CHAR_IMG_BLOCK])
  {
    oadBlkNum = BUILD_UINT16(pNoti->value[0], pNoti->value[1]);
    attWriteReq_t req;

    req.handle = oadManagerHandles[OAD_CHAR_IMG_BLOCK];
    req.len = 2 + OAD_BLOCK_SIZE;
    req.sig = FALSE;
    req.cmd = TRUE;

    req.value[0] = LO_UINT16(oadBlkNum);
    req.value[1] = HI_UINT16(oadBlkNum);

    uint8 page = oadBlkNum / OAD_BLOCKS_PER_PAGE;
    uint16 oset = (oadBlkNum - (OAD_BLOCKS_PER_PAGE * page)) * OAD_BLOCK_SIZE;
    HalFlashRead(page+OAD_IMG_B_PAGE, oset, req.value+2, OAD_BLOCK_SIZE);

#if (defined HAL_LCD) && (HAL_LCD == TRUE)
    if (oadBlkNum == 0)
    {
      HalLcdWriteString("", HAL_LCD_LINE_3);
    }
    HalLcdDisplayPercentBar( "OAD Progress...", (oadBlkNum / (oadBlkTot / 100)) );
#endif

    VOID GATT_WriteNoRsp(oadManagerConnHandle, &req);

    VOID osal_start_timerEx( oadManagerTaskId, OAD_DOWNLOAD_EVT, OAD_DOWNLOAD_TIMEOUT );
  }
}
Example #4
0
/*********************************************************************
 * @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 );
}