/***************************************************************************** DownFiles.C *****************************************************************************/ #include "includes.h" #include "DownFiles.h" #include "IAP.h" unsigned short newListIndex[FILE_COUNT_MAX];//临时保存置换位置后的索引 //static SUT_FILE_LIST sutFileList;//临时文件列表 只用于传输文件用,注意不要与FileSys.c定义的g_sutFilesList混淆! static uint16_t sFileIndex; //当前传输的文件在文件列表中的索引位置 static uint32_t sFileDataOffset; //当前传输的文件偏移 static uint32_t sFileDataLength; //当前传输的文件长度 /***************************************************************************************** MakePCTFlistReq 生成请求文件列表数据 ******************************************************************************************/ int MakePctflistReq(char *txbuf) { SUT_DF_LIST_REQ *pDFListReq; pDFListReq=(SUT_DF_LIST_REQ *)txbuf; memset(pDFListReq,0,sizeof(SUT_DF_LIST_REQ)); pDFListReq->Head.magic=PCTA_MAGIC; pDFListReq->Head.protocol=UPDATE_PROTOCOL_RFILE; pDFListReq->Head.code=DOWNLOAD_FILE_LIST_REQ; pDFListReq->Head.tid=0; pDFListReq->Head.count=sizeof(SUT_DF_LIST_REQ)-sizeof(SUT_DF_HEAD); pDFListReq->FileCountMax=FILE_COUNT_MAX; pDFListReq->FileNameLenMax=FILE_NAME_LEN_MAX; pDFListReq->FileAllDataLenMax=FILE_ALL_DATA_LEN_MAX; return sizeof(SUT_DF_LIST_REQ); } /***************************************************************************************** DFGetFileList 请求文件列表 ******************************************************************************************/ void DFGetFileList(void) { int len; len=MakePctflistReq((char *)TxBuffer1); Uart1Send((char *)TxBuffer1,len); } /***************************************************************************************** MakePCTFlistReq 生成请求文件列表数据 ******************************************************************************************/ int MakePctfFileDataReq(char *txbuf,uint16_t FileIndex,uint32_t offset,uint32_t length) { SUT_DF_DATA_REQ *pFileDataReq; pFileDataReq=(SUT_DF_DATA_REQ *)txbuf; memset(pFileDataReq,0,sizeof(SUT_DF_DATA_REQ)); pFileDataReq->Head.magic=PCTA_MAGIC; pFileDataReq->Head.protocol=UPDATE_PROTOCOL_RFILE; pFileDataReq->Head.code=DOWNLOAD_FILE_DATA_REQ; pFileDataReq->Head.tid=0; pFileDataReq->Head.count=sizeof(SUT_DF_DATA_REQ)-sizeof(SUT_DF_HEAD); #ifdef USE_NEW_FILE_SYSTEM pFileDataReq->FileIndex=newListIndex[FileIndex]; #else pFileDataReq->FileIndex=FileIndex; #endif memcpy(&pFileDataReq->FileInfo,&g_sutFilesList.FileInfo[FileIndex],sizeof(SUT_FILE_INFO)); pFileDataReq->length=length; pFileDataReq->offset=offset; return sizeof(SUT_DF_DATA_REQ); } /***************************************************************************************** DFGetFileData 请求文件数据 ******************************************************************************************/ void DFGetFileData(uint16_t FileIndex,uint32_t offset,uint32_t length) { int len; len=MakePctfFileDataReq((char *)TxBuffer1,FileIndex,offset,length); Uart1Send((char *)TxBuffer1,len); } /************************************************************************************ *找出第一个不同的文件索引 *************************************************************************************/ int FindFirstDiffIndex(SUT_FILE_LIST *FileList) { int i; int j; for(i=0;iFileInfo[i].FileLen)break; for(j=0;j<16;j++){ if(g_sutFilesList.FileInfo[i].FileMD5[j]!=FileList->FileInfo[i].FileMD5[j])break; } if(j!=16)break; if(0!=strcmp(g_sutFilesList.FileInfo[i].FileName,FileList->FileInfo[i].FileName))break; } return i; } void RerangeList(SUT_FILE_LIST *FileList) { int i,j,w; SUT_FILE_INFO temp; for(w=0;wFileCount;w++) newListIndex[w]=w; for(i=0;iFileCount-1;i++){//如果刚好是最后那个是SYS_CONFIG,那不用置换了,故减1操作 if(0==strcmp(FileList->FileInfo[i].FileName, SYS_CONFIG)){//找到了后,放在最后 memcpy((unsigned char *)&temp, (unsigned char *)&FileList->FileInfo[i], sizeof(SUT_FILE_INFO));//备份 for(j=i;jFileCount-1;j++) memcpy((unsigned char *)&FileList->FileInfo[j], (unsigned char *)&FileList->FileInfo[j+1], sizeof(SUT_FILE_INFO));//结构体前移1 memcpy((unsigned char *)&FileList->FileInfo[FileList->FileCount-1], (unsigned char *)&temp, sizeof(SUT_FILE_INFO));//备份的放最后 for(w=i;wFileCount-1;w++) newListIndex[w] = newListIndex[w+1];//文件索引前移1 newListIndex[FileList->FileCount-1]=i;//备份索引放最后 return; } } } void MakeTheEndFileIndicator(void) { //清除未使用的页,防止影响恢复逻辑 SUT_FILE_PAGE_HEAD pageInfo; u32 endAddr; endAddr=g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileAddr+4096; endAddr += g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileLen; endAddr +=4096-(endAddr%4096) ; if(endAddr >= FILE_DATA_ADDR_END) return;//已到文件结尾,则不需要再生成结束标识 pageInfo.mark=FILE_HEAD_END; sFlash_Write((unsigned char *)&pageInfo, endAddr, sizeof(SUT_FILE_PAGE_HEAD)); } unsigned char buf[1024];//1024 void CopyConfiToBckupFile(void) { unsigned int sourceAddr, desAddr, i,j; char ret=0; if(0 !=strcmp(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileName, SYS_CONFIG)) ret=1; else if(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileLen > 4096) ret=2; if(ret != 0){ while(1){ IapTrace("sys.ini err, stop\r\n"); DelayMs(500); } } for(j=0;j<2;j++){ sourceAddr=g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileAddr; desAddr=FILE_DATA_ADDR_END+1; if(j==0){//先拷贝数据区 sourceAddr += 4096; desAddr += 4096; } for(i=0;i<4;i++){ sFlash_Read(buf, sourceAddr, 1024); sFlash_Write(buf, desAddr, 1024); sourceAddr += 1024; desAddr += 1024; } } } /************************************************************************************ IapRecvMsgHandle 处理接收到的数据 *************************************************************************************/ int DFRecvMsgHandle(unsigned char *pData, unsigned short DataLen) { int i,temp; unsigned short crc,CRC16; unsigned short ReadBuf[4]; uint32_t addr,len,offset; unsigned char code; unsigned short count; #ifdef USE_NEW_FILE_SYSTEM SUT_FILE_PAGE_HEAD pageInfo; #endif SUT_DF_HEAD *pHeader; SUT_DF_LIST_RSP *pListRsp; SUT_DF_DATA_RSP *pDataRsp; pHeader=(SUT_DF_HEAD *)pData; if(pHeader->magic != PCTA_MAGIC)return -1; if(pHeader->protocol != UPDATE_PROTOCOL_RFILE )return -2; code= pHeader->code; count= pHeader->count; if(code==DOWNLOAD_FILE_LIST_REQ){//PC响应文件列表 if(count!=(sizeof(SUT_DF_LIST_RSP)-sizeof(SUT_DF_HEAD)))return -4; pListRsp= (SUT_DF_LIST_RSP *)pData; CRC16=pListRsp->FileListCRC; crc=crc16_calc(0,(uint8_t *)&pListRsp->FileList,sizeof(SUT_FILE_LIST)); if(crc!=CRC16)return -5; if(pListRsp->FileList.FileCount==0)return 0;//文件个数为0,不用更新,直接完成 #ifdef USE_NEW_FILE_SYSTEM //重新对PC响应过来的文件列表进行排序,将SYS_CONFIG_A与SYS_CONFIG_B放在最后 RerangeList(&pListRsp->FileList); #endif #ifdef DOWNLOAD_DIFFERENT_FILE_ONLY //跳过前面相同的文件,只从第一个不相同的文件开始更新 sFileIndex=FindFirstDiffIndex(&pListRsp->FileList);//即将更新文件的索引 if(sFileIndex >= pListRsp->FileList.FileCount){//没有需要更新的,结束 g_sutFilesList.FileCount=pListRsp->FileList.FileCount; g_sutFilesList.Mark=STORAGE_MARK; FileSysSaveIndex();//保存索引 return 0; } g_sutFilesList.FileCount=pListRsp->FileList.FileCount; #ifndef USE_NEW_FILE_SYSTEM memcpy(&g_sutFilesList.FileInfo[sFileIndex],&pListRsp->FileList.FileInfo[sFileIndex],(pListRsp->FileList.FileCount-sFileIndex)*sizeof(SUT_FILE_INFO)); #endif #else //不判断是否文件相同都更新 sFileIndex=0; #ifndef USE_NEW_FILE_SYSTEM memcpy(&g_sutFilesList,&pListRsp->FileList,sizeof(SUT_FILE_LIST)); #endif #endif #ifdef USE_NEW_FILE_SYSTEM for(i=sFileIndex;iFileList.FileInfo[i].FileLen; memcpy(g_sutFilesList.FileInfo[i].FileMD5, pListRsp->FileList.FileInfo[i].FileMD5, sizeof(g_sutFilesList.FileInfo[i].FileMD5)); memcpy(g_sutFilesList.FileInfo[i].FileName, pListRsp->FileList.FileInfo[i].FileName, sizeof(g_sutFilesList.FileInfo[i].FileName)); } #endif sFileDataOffset=0;//即将更新文件数据的位置 sprintf(buf,"RFile Count=%lu\r\n",g_sutFilesList.FileCount); IapTrace(buf); sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); return 1; }else if(code == DOWNLOAD_FILE_DATA_REQ){//PC响应文件数据申请 pDataRsp = (SUT_DF_DATA_RSP*)pData; //sprintf(buf, "flen=%ld,%ld,index=%d,%d,%d,name=%s\r\n",pDataRsp->FileInfo.FileLen,g_sutFilesList.FileInfo[pDataRsp->FileIndex].FileLen,sFileIndex,newListIndex[sFileIndex],pDataRsp->FileIndex,pDataRsp->FileInfo.FileName); //IapTrace(buf); #ifdef USE_NEW_FILE_SYSTEM if(pDataRsp->FileInfo.FileLen!=g_sutFilesList.FileInfo[sFileIndex].FileLen || #else if(pDataRsp->FileInfo.FileLen!=g_sutFilesList.FileInfo[pDataRsp->FileIndex].FileLen || #endif pDataRsp->offset != sFileDataOffset || newListIndex[sFileIndex]!=pDataRsp->FileIndex){//文件长度or 索引 or 偏移 不对?重新更新 IapTrace("FLen or Offset err!ReDO!\r\n"); DFGetFileData(sFileIndex,sFileDataOffset,4096); return -6; } len=pDataRsp->length; len-=2;//实际数据长度应去掉2字节的CRC //CRC校验 CRC16=crc16_calc(0,pDataRsp->data,len); crc=((unsigned short)pDataRsp->data[len+1]&0xff)<<8; crc+=(unsigned short)pDataRsp->data[len]&0xff; if(crc!=CRC16){ //校验错误,申请重新下载 IapTrace("CRC err!ReDO!\r\n"); DFGetFileData(sFileIndex,sFileDataOffset,4096); return -8; } //==CRC校验成功,更新FLASH === #ifndef USE_NEW_FILE_SYSTEM sFlash_Write(pDataRsp->data,g_sutFilesList.FileInfo[sFileIndex].FileAddr+sFileDataOffset,len); #else sFlash_Write(pDataRsp->data,g_sutFilesList.FileInfo[sFileIndex].FileAddr+4096+sFileDataOffset,len);//数据内容要偏移出页头 #endif if((len+sFileDataOffset)>=pDataRsp->FileInfo.FileLen){//完成当前文件下载 #ifdef USE_NEW_FILE_SYSTEM //校验本文件的MD5码,看是否正确,如果不正确则重新下载本文件,如正确则切换下一文件 if(0==FileCheckMD5(sFileIndex)){//MD5错误 //重新下载 sFileDataOffset=0;//即将更新文件数据的位置 sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); }else{ //MD5正确 //更新信息页头并保存起来 pageInfo.fLength=g_sutFilesList.FileInfo[sFileIndex].FileLen; memcpy(pageInfo.fName, g_sutFilesList.FileInfo[sFileIndex].FileName, sizeof(pageInfo.fName)); memcpy(pageInfo.md5, g_sutFilesList.FileInfo[sFileIndex].FileMD5, sizeof(pageInfo.md5)); pageInfo.mark=FILE_HEAD_MARK; if(sFileIndex==0) pageInfo.nextFileHeadAddr=FILE_INDEX_ADDR; else pageInfo.nextFileHeadAddr=g_sutFilesList.FileInfo[sFileIndex].FileAddr; temp=pageInfo.fLength%4096; pageInfo.nextFileHeadAddr += (pageInfo.fLength+4096); if(temp != 0) pageInfo.nextFileHeadAddr += (4096-temp); if((sFileIndex+1) >= g_sutFilesList.FileCount) pageInfo.nextFileHeadAddr=0; sFlash_Write((uint8_t *)&pageInfo, g_sutFilesList.FileInfo[sFileIndex].FileAddr, sizeof(SUT_FILE_PAGE_HEAD)); if(++sFileIndex >= g_sutFilesList.FileCount){//判断所有文件是否下载完毕? //下载完毕,拷贝复制配置文件到备份区 //CopyConfiToBckupFile(); //结束 return 0; } //未结束,启动下一个文件传输 sFileDataOffset=0;//即将更新文件数据的位置 sprintf(buf,"RFile[%d]:%s len=%lu\r\n",newListIndex[sFileIndex],g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); } #else //旧文件格式时有一个问题:最后一个文件没有校验MD5的正确性 if(sFileIndex==(g_sutFilesList.FileCount-1)){//判断所有文件是否下载完毕? //所有文件下载完毕,结束 g_sutFilesList.Mark=STORAGE_MARK; FileSysSaveIndex();//保存索引 return 0; }else{ //校验本文件的MD5码,看是否正确,如不正确则重新下载本文件,如正确则切换下一文件 if(0==FileCheckMD5(sFileIndex)){//MD5错误 //重新下载 sFileDataOffset=0;//即将更新文件数据的位置 sprintf(buf,"RFile[%d]:%s len=%lu\r\n",sFileIndex,g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); }else{//MD5正确 //启动下一文件传输 sFileIndex++; //下一个文件地址为上一个文件地址加上一个文件的长度 g_sutFilesList.FileInfo[sFileIndex].FileAddr=g_sutFilesList.FileInfo[sFileIndex-1].FileAddr+g_sutFilesList.FileInfo[sFileIndex-1].FileLen; sFileDataOffset=0;//即将更新文件数据的位置 sprintf(buf,"RFile[%d]:%s len=%lu\r\n",sFileIndex,g_sutFilesList.FileInfo[sFileIndex].FileName,g_sutFilesList.FileInfo[sFileIndex].FileLen); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); } } #endif }else{ //本文件传输未结束,启动下一包下载 sFileDataOffset+=len; sprintf(buf,"offset=%d %d%%\r\n",sFileDataOffset,100*sFileDataOffset/g_sutFilesList.FileInfo[sFileIndex].FileLen); //sprintf(buf,"offset=%d\r\n",sFileDataOffset); IapTrace(buf); DFGetFileData(sFileIndex,sFileDataOffset,4096); } return 2; } }