OAD

来源:互联网 发布:个人相册网站源码 编辑:程序博客网 时间:2024/04/30 16:31

一.查询版本信息

     1.注册imagidentify通知

     2.往其中写0x00(基本上是任意值都可以).

     3.设备notify当前image header :如:0200007c 41414141(版本为A)

image header的格式:

typedef struct {
#if defined FEATURE_OAD_SECURE
  // Secure OAD uses the Signature for image validation instead of calculating a CRC, but the use
  // of CRC==CRC-Shadow for quick boot-up determination of a validated image is still used.
  uint16 crc0;       // CRC must not be 0x0000 or 0xFFFF.CRC校验
#endif
  uint16 crc1;       // CRC-shadow must be 0xFFFF.
  // User-defined Image Version Number - default logic uses simple a '!=' comparison to start an OAD.
  uint16 ver;//版本
  uint16 len;        // Image length in 4-byte blocks (i.e. HAL_FLASH_WORD_SIZE blocks).长度
  uint8  uid[4];     // User-defined Image Identification bytes.
  uint8  res[4];     // Reserved space for future use.
} img_hdr_t;


二.传输过程

1.写新的image 信息到identify,获得版本信息,大小等信息用来确认是否真的需要跟新,以及为下一步和bin文件内容比对校验。

2.将bin文件拆包发送到到block。

3.完成接受之后重启系统



代码分析:

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.
       //版本信息要不一样
      //(rxHdr.ver!=0)&&//jia
      (oadBlkTot <= OAD_BLOCK_MAX) &&//7936
        //长度小于最大长度
       (oadBlkTot != 0) )
    //且不为0
  {
    oadBlkNum = 0;
    oadImgBlockReq(connHandle, 0);//请求一个块 从0开始,并notify oadBlkNum
  }
  else
  {
    oadImgIdentifyReq(connHandle, &ImgHdr);//否则发送当前版本信息
  }


  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确定这个image是想要的
  if ( blkNum == 0 )
    //这个要参考bin文件的格式组成,
    /*组成:标记(7)+Image开始地址(1)+Image长度(1) 
           记录0地址+记录0长+记录0校验和+记录0内容(文件内容)
        记录1地址+记录1长+记录1校验和+记录1内容(文件内容)*/
  {
    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));
     //以下为比对之前从Img Identify中获取到的内容,若有不相同,则说明信息不对,返回错误
    if ( ( oadBlkNum != blkNum ) ||
         ( oadBlkTot != blkTot ) ||
         ( OAD_IMG_ID( ImgHdr.ver ) == OAD_IMG_ID( ver ) ) )//版本信息一样
    {
      return ( ATT_ERR_WRITE_NOT_PERMITTED );
    }
  }


  if (oadBlkNum == blkNum)//之后每次判断传的包数量是否一致
  {


   //计算方式:page*2048/4 =addr
    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.跳过中间存放imageA 的部分
    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);//调用notify,将oadBlkNum通知上去
  }


  return ( SUCCESS );
}


    

0 0
原创粉丝点击