FileSys.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*****************************************************************************
  2. FileSys.c
  3. *****************************************************************************/
  4. #define THIS_FILE_ID 20
  5. /* Includes ------------------------------------------------------------------*/
  6. #include "includes.h"
  7. SUT_FILE_LIST g_sutFilesList;
  8. unsigned char tempBuf[1024];
  9. void BackupFileToTemp(SUT_FILE_INFO *fileinfo, char type);
  10. void UpdateBackFileMD5(SUT_FILE_INFO *fileinfo);
  11. unsigned char isFileFileGood(unsigned int addr)
  12. {
  13. SUT_FILE_PAGE_HEAD pageInfo;
  14. MD5_CTX mdContext;
  15. unsigned int RAddr;
  16. unsigned int len;
  17. unsigned char data[1024];
  18. sFlash_Read((uint8_t *)&pageInfo, addr, sizeof(SUT_FILE_PAGE_HEAD));
  19. if(pageInfo.mark != FILE_HEAD_MARK) return 1;//文件非法
  20. if(pageInfo.fLength > 4096) return 2;//文件也算非法
  21. //计算md5
  22. RAddr=addr+4096;
  23. len=pageInfo.fLength;
  24. MD5Init(&mdContext);//初始化MD5
  25. while(len){
  26. if(len>1024){
  27. sFlash_Read(data,RAddr,1024);
  28. MD5Update(&mdContext,data,1024);
  29. RAddr+=1024;
  30. len-=1024;
  31. }else{
  32. sFlash_Read(data,RAddr,len);
  33. MD5Update(&mdContext,data,len);
  34. len=0;
  35. }
  36. }
  37. MD5Final(&mdContext);
  38. if(0 != memcmp(mdContext.digest, pageInfo.md5, 16)) return 3;//文件内容与MD5对不上
  39. else return 0;//正常
  40. }
  41. /*****************************************************************
  42. FileSysReadIndex
  43. ******************************************************************/
  44. int FileSysReadIndex(void)
  45. {
  46. #if((FILE_INDEX_ADDR%4096)||(FILE_DATA_ADDR_END+1)%4096)
  47. #error "文件列表存储区首地址必须为页首(4K的整数倍)"
  48. #endif
  49. /*
  50. 因为涉及到PC工具,这里不对PC工具作修改,因此,只修改IAP(后续APP也要修改),PC传输协议不变更;
  51. 以前是先从存储区读出文件列表信息,同时存储区也是有实际的文件列表信息区域的;
  52. 变更后,存储区没有总体的文件列表信息区域了,这里读取出来的文件信息区域则是能过扫描整个文件列表区来获取并整理出文件列表信息结构体;
  53. 具体新的文件存储结构则是N个文件依次存储起来,每个文件的存储格式如下:
  54. 每个文件分页头(PAGE HEAD)及页身(PAGE BODY),页头只有一个,页身有N个,每个页占4K;
  55. 页头:
  56. unsigned char fName[];本页头所描述的文件名字
  57. unsigned char md5[16];本页头所描述的文件内容的md5
  58. unsigned int fLength;//本页所描述的文件内容共占多少个字节数
  59. unsigned int nextFileHeadAddr;//如果本页为有效文件的页头,且本值不为0时,则指向的是一下个文件的页头地址
  60. unsigned int mark; 表示此页是否是合法的页头信息,否则为数据页或无效页
  61. */
  62. unsigned char sysFileStatus,backupFileStatus;
  63. unsigned int addr;
  64. int i,fnum,tmp;
  65. char tempFileExist=0;//0 备份文件不存在,即无效 1 备份文件存在且合法的 2 备份文件在文件使用区中已完整存在,并未丢失 3 备份文件在文件使用区中匹配到,且不一致,需要恢复
  66. SUT_FILE_PAGE_HEAD pageInfo;
  67. //检测备份区是否有正确的备份文件
  68. memset(&g_sutFilesList,0,sizeof(SUT_FILE_LIST));
  69. fnum=0;
  70. for(i=FILE_INDEX_ADDR;i<FILE_DATA_ADDR_END;){
  71. sFlash_Read((uint8_t *)&pageInfo, i, sizeof(SUT_FILE_PAGE_HEAD));
  72. if(pageInfo.mark == FILE_HEAD_MARK){//这是一个有效的文件页
  73. memcpy(g_sutFilesList.FileInfo[fnum].FileName, pageInfo.fName, sizeof(g_sutFilesList.FileInfo[fnum].FileName));
  74. memcpy(g_sutFilesList.FileInfo[fnum].FileMD5, pageInfo.md5, sizeof(g_sutFilesList.FileInfo[fnum].FileMD5));
  75. g_sutFilesList.FileInfo[fnum].FileLen=pageInfo.fLength;
  76. g_sutFilesList.FileInfo[fnum].FileAddr=i;
  77. fnum++;
  78. if(pageInfo.nextFileHeadAddr != 0) i=pageInfo.nextFileHeadAddr;
  79. else break;
  80. }else if(pageInfo.mark == FILE_HEAD_END){
  81. break;
  82. }else{//此页可能是损坏的文件页,有可能是最后的未使用页
  83. i += 4096;
  84. }
  85. }
  86. g_sutFilesList.FileCount=fnum;
  87. if(fnum<1){//没有检测到资源文件
  88. printf("No res files\r\n");
  89. return 1;
  90. }
  91. g_sutFilesList.Mark=STORAGE_MARK;
  92. //sys.ini文件是否存在
  93. sysFileStatus=4;//0 文件正常, 1/2/3 文件存在但非法或MD5错误 4 文件丢失
  94. if(0==strcmp(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileName, SYS_CONFIG)){
  95. sysFileStatus=isFileFileGood(g_sutFilesList.FileInfo[g_sutFilesList.FileCount-1].FileAddr);
  96. }
  97. //检查备份文件是否正确
  98. backupFileStatus=4;//0 文件正常, 1/2/3 文件存在但非法或MD5错误 4 文件丢失
  99. backupFileStatus=isFileFileGood(FILE_DATA_ADDR_END+1);
  100. if(sysFileStatus ==0){//文件正常
  101. printf("%s ok\r\n", SYS_CONFIG);
  102. return 0;
  103. }else if(backupFileStatus==0){//文件不正常,但备份文件正常,恢复之
  104. if(sysFileStatus==4){//文件丢失了,当前文件列表中没有此文件,恢复时需要在最后添加一个文件
  105. printf("%s lost, recover\r\n", SYS_CONFIG);
  106. i=0;
  107. }else{//文件损坏,当前文件列表中有此文件,恢复时不需要添加文件
  108. printf("%s invalid, recover\r\n", SYS_CONFIG);
  109. i=1;
  110. }
  111. sFlash_Read((uint8_t *)&pageInfo, FILE_DATA_ADDR_END+1, sizeof(SUT_FILE_PAGE_HEAD));
  112. memcpy(g_sutFilesList.FileInfo[fnum].FileName, pageInfo.fName, sizeof(g_sutFilesList.FileInfo[fnum].FileName));
  113. memcpy(g_sutFilesList.FileInfo[fnum].FileMD5, pageInfo.md5, sizeof(g_sutFilesList.FileInfo[fnum].FileMD5));
  114. g_sutFilesList.FileInfo[fnum].FileLen=pageInfo.fLength;
  115. sFlash_Read((uint8_t *)&pageInfo, g_sutFilesList.FileInfo[fnum-1-i].FileAddr, sizeof(SUT_FILE_PAGE_HEAD));
  116. g_sutFilesList.FileInfo[fnum].FileAddr=pageInfo.nextFileHeadAddr;
  117. BackupFileToTemp(&g_sutFilesList.FileInfo[fnum-i],1);
  118. if(sysFileStatus==4) g_sutFilesList.FileCount++;
  119. return 0;
  120. }else{//文件与备份文件都不正常,按设计是不会存在,也不会跑到这里
  121. printf("%s error, status:%d,%d\r\n", SYS_CONFIG,sysFileStatus,backupFileStatus);
  122. return 2;
  123. }
  124. }
  125. /******************************************************************
  126. FileSysSaveIndex
  127. *******************************************************************/
  128. void FileSysSaveIndex(void)
  129. {
  130. u8 *pBuf;
  131. pBuf=(u8 *)&g_sutFilesList;
  132. sFlash_Write(pBuf,FILE_INDEX_ADDR,sizeof(SUT_FILE_LIST));
  133. }
  134. /******************************************************************
  135. FileSysInit
  136. 检查是否需要格式化,需要则格式化之,否则不格式化
  137. return:
  138. 1--format
  139. 0--no format
  140. *******************************************************************/
  141. int FileSysInit()
  142. {
  143. return FileSysReadIndex();//读索引
  144. }
  145. void UCharToStrByHex(char *str,unsigned char *data,int len)
  146. {
  147. int i;
  148. for(i=0;i<len;i++){
  149. sprintf(&str[i*2],"%02X",data[i]);
  150. }
  151. }
  152. int FileCheckMD5(int FileIndex)
  153. {
  154. MD5_CTX mdContext;
  155. unsigned char data[1024];
  156. int i;
  157. uint32_t FileLen;
  158. uint32_t FileAddr;
  159. uint32_t Addr,len;
  160. FileLen=g_sutFilesList.FileInfo[FileIndex].FileLen;
  161. FileAddr=g_sutFilesList.FileInfo[FileIndex].FileAddr;
  162. //读取文件数据并计算MD5
  163. Addr=FileAddr;
  164. len=FileLen;
  165. MD5Init(&mdContext);//初始化MD5
  166. while(len){
  167. if(len>1024){
  168. sFlash_Read(data,Addr,1024);
  169. MD5Update(&mdContext,data,1024);
  170. Addr+=1024;
  171. len-=1024;
  172. }else{
  173. sFlash_Read(data,Addr,len);
  174. MD5Update(&mdContext,data,len);
  175. len=0;
  176. }
  177. }
  178. MD5Final(&mdContext);
  179. //比较文件数据的MD5计数值是否与文件信息头的MD5相同
  180. for(i=0;i<16;i++){
  181. if(g_sutFilesList.FileInfo[FileIndex].FileMD5[i]!=mdContext.digest[i]){
  182. //不同的部分打印出来
  183. UCharToStrByHex((char *)data,g_sutFilesList.FileInfo[FileIndex].FileMD5,16);
  184. printf("Check File[%d] %s <> ",FileIndex,(char *)data);
  185. UCharToStrByHex((char *)data,mdContext.digest,16);
  186. printf("%s\r\n",(char *)data);
  187. return 0;
  188. }
  189. }
  190. //不同的部分打印出来
  191. // UCharToStrByHex((char *)data,g_sutFilesList.FileInfo[FileIndex].FileMD5,16);
  192. // printf("Check File[%d] %s == ",FileIndex,(char *)data);
  193. // UCharToStrByHex((char *)data,mdContext.digest,16);
  194. // printf("%s\r\n",(char *)data);
  195. return 1;
  196. }
  197. /***********************************************************
  198. *获取文件索引
  199. ************************************************************/
  200. int GetFileIndex(const char *filename)
  201. {
  202. int i;
  203. for(i=0;i<g_sutFilesList.FileCount;i++){
  204. if(0==strcmp(g_sutFilesList.FileInfo[i].FileName,filename)){
  205. return i;
  206. }
  207. }
  208. return -1;
  209. }
  210. /***********************************************************
  211. *获取文件长度
  212. ************************************************************/
  213. int GetFileLen(int FileIndex)
  214. {
  215. int len;
  216. if(FileIndex<0)return 0;
  217. len=g_sutFilesList.FileInfo[FileIndex].FileLen;
  218. if(len<0 || len>(FILE_DATA_ADDR_END-FILE_DATA_ADDR))return 0;
  219. else return len;
  220. }
  221. /***********************************************************
  222. 读取文件数据
  223. 返回实际读取字节数
  224. ************************************************************/
  225. int ReadFileData(int FileIndex,u32 startAddr,u32 readLen,unsigned char *pData)
  226. {
  227. int len;
  228. u32 addr;
  229. if(FileIndex<0)return 0;
  230. if(FileIndex>=g_sutFilesList.FileCount)return 0;
  231. if((startAddr+readLen)>g_sutFilesList.FileInfo[FileIndex].FileLen){
  232. len=g_sutFilesList.FileInfo[FileIndex].FileLen-startAddr;
  233. }else{
  234. len=readLen;
  235. }
  236. addr=g_sutFilesList.FileInfo[FileIndex].FileAddr + startAddr;
  237. addr += 4096;
  238. sFlash_Read(pData,addr,len);
  239. return len;
  240. }
  241. /***************************************************************
  242. UpdateFileMD5
  243. *****************************************************************/
  244. void UpdateFileMD5(int FileIndex)
  245. {
  246. MD5_CTX mdContext;
  247. unsigned char data[1024];
  248. int i;
  249. uint32_t FileLen;
  250. uint32_t FileAddr;
  251. uint32_t Addr,len;
  252. FileLen=g_sutFilesList.FileInfo[FileIndex].FileLen;
  253. FileAddr=g_sutFilesList.FileInfo[FileIndex].FileAddr;
  254. //读取文件数据并计算MD5
  255. Addr=FileAddr;
  256. len=FileLen;
  257. MD5Init(&mdContext);//初始化MD5
  258. while(len){
  259. if(len>1024){
  260. sFlash_Read(data,Addr,1024);
  261. MD5Update(&mdContext,data,1024);
  262. Addr+=1024;
  263. len-=1024;
  264. }else{
  265. sFlash_Read(data,Addr,len);
  266. MD5Update(&mdContext,data,len);
  267. len=0;
  268. }
  269. }
  270. MD5Final(&mdContext);
  271. //比较文件数据的MD5计数值是否与文件信息头的MD5相同
  272. if(g_sutFilesList.FileInfo[FileIndex].FileMD5[FileIndex]!=mdContext.digest[FileIndex]){
  273. //更新文件索引对应文件的MD5
  274. for(i=0;i<16;i++){
  275. g_sutFilesList.FileInfo[FileIndex].FileMD5[i]=mdContext.digest[i];
  276. }
  277. FileSysSaveIndex();
  278. }
  279. return;
  280. }
  281. //修改备份区内容
  282. void ModifyTempFile(SUT_FILE_INFO *fileinfo, u32 startAddr,u32 writeLen,unsigned char *pData)
  283. {
  284. u32 addr;
  285. addr=FILE_DATA_ADDR_END+1+4096+startAddr;
  286. sFlash_Write(pData, addr, writeLen);
  287. }
  288. /*****************************************************************
  289. 修改文件
  290. *****************************************************************/
  291. int ModifyConfigureFile(char showInfo)
  292. {//此版本中的此函数不能随便调用了,基本只要修改sysini文件才调
  293. int FileIndex;
  294. u32 startAddr,writeLen;
  295. unsigned char *pData;
  296. int len=0;
  297. u32 addr;
  298. FileIndex=newSysiniIndex;
  299. startAddr=0;
  300. writeLen=sizeof(SYSINI_HS191X_DEF);
  301. pData=(unsigned char *)&newPara;
  302. PWR_EN_HIGH;//锁住电源
  303. if(FileIndex<0) goto M_END;
  304. if(FileIndex>=g_sutFilesList.FileCount)goto M_END;
  305. if(showInfo != 0) speciallShow(0);
  306. if((startAddr+writeLen)>g_sutFilesList.FileInfo[FileIndex].FileLen){
  307. len=g_sutFilesList.FileInfo[FileIndex].FileLen-startAddr;
  308. }else len=writeLen;
  309. IWDG_ReloadCounter();
  310. //1、写之前先将当前文件拷贝到备份区(注意最好设计成可以修改的文件不在太大,尽量在4K之内,否则操作时间可能比较久)
  311. BackupFileToTemp(&g_sutFilesList.FileInfo[FileIndex],0);
  312. //2、然后修改备份区
  313. ModifyTempFile(&g_sutFilesList.FileInfo[FileIndex], startAddr, len, pData);
  314. UpdateBackFileMD5(&g_sutFilesList.FileInfo[FileIndex]);
  315. //3、拷贝备份区回使用区
  316. BackupFileToTemp(&g_sutFilesList.FileInfo[FileIndex],1);
  317. if(showInfo != 0) speciallShow(1);
  318. M_END:
  319. //PWR_EN_LOW;//释放电源
  320. return len;
  321. }
  322. //文件与备份区相互拷贝
  323. void BackupFileToTemp(SUT_FILE_INFO *fileinfo, char type)
  324. {
  325. unsigned int sourceAddr, desAddr, copyLen;
  326. unsigned char *tempBufx=tempBuf,i;
  327. if(type==0){//从文件拷贝到备份区
  328. //先拷贝数据页,再拷贝文件头页,其实从文件到备份区谁先后无所谓
  329. sourceAddr=fileinfo->FileAddr+4096;
  330. desAddr=FILE_DATA_ADDR_END+1+4096;
  331. for(i=0;i<4;i++){
  332. sFlash_Read(tempBufx, sourceAddr, 1024);
  333. sFlash_Write(tempBufx, desAddr, 1024);
  334. sourceAddr += 1024;
  335. desAddr += 1024;
  336. }
  337. sourceAddr=fileinfo->FileAddr;
  338. desAddr=FILE_DATA_ADDR_END+1;
  339. for(i=0;i<4;i++){
  340. sFlash_Read(tempBufx, sourceAddr, 1024);
  341. sFlash_Write(tempBufx, desAddr, 1024);
  342. sourceAddr += 1024;
  343. desAddr += 1024;
  344. }
  345. }else{//从备份区拷贝回文件区
  346. //先拷贝数据页,再拷贝文件头页
  347. sourceAddr=FILE_DATA_ADDR_END+1+4096;
  348. desAddr=fileinfo->FileAddr+4096;
  349. for(i=0;i<4;i++){
  350. sFlash_Read(tempBufx, sourceAddr, 1024);
  351. sFlash_Write(tempBufx, desAddr, 1024);
  352. sourceAddr += 1024;
  353. desAddr += 1024;
  354. }
  355. sourceAddr=FILE_DATA_ADDR_END+1;
  356. desAddr=fileinfo->FileAddr;
  357. for(i=0;i<4;i++){
  358. sFlash_Read(tempBufx, sourceAddr, 1024);
  359. sFlash_Write(tempBufx, desAddr, 1024);
  360. sourceAddr += 1024;
  361. desAddr += 1024;
  362. }
  363. }
  364. }
  365. void UpdateBackFileMD5(SUT_FILE_INFO *fileinfo)
  366. {
  367. MD5_CTX mdContext;
  368. unsigned char *data=tempBuf;
  369. uint32_t Addr,len;
  370. SUT_FILE_PAGE_HEAD *pageInfo;
  371. //读取文件数据并计算MD5
  372. Addr=FILE_DATA_ADDR_END+1+4096;
  373. len=fileinfo->FileLen;
  374. MD5Init(&mdContext);//初始化MD5
  375. while(len){
  376. if(len>1024){
  377. sFlash_Read(data,Addr,1024);
  378. MD5Update(&mdContext,data,1024);
  379. Addr+=1024;
  380. len-=1024;
  381. }else{
  382. sFlash_Read(data,Addr,len);
  383. MD5Update(&mdContext,data,len);
  384. len=0;
  385. }
  386. }
  387. MD5Final(&mdContext);
  388. //比较文件数据的MD5计数值是否与文件信息头的MD5相同
  389. pageInfo=(SUT_FILE_PAGE_HEAD *)data;
  390. sFlash_Read(data, FILE_DATA_ADDR_END+1, sizeof(SUT_FILE_PAGE_HEAD));
  391. if(0!=memcmp(pageInfo->md5, mdContext.digest, 16)){
  392. memcpy(pageInfo->md5, mdContext.digest, sizeof(pageInfo->md5));
  393. sFlash_Write(data, FILE_DATA_ADDR_END+1, sizeof(SUT_FILE_PAGE_HEAD));
  394. }
  395. memcpy(fileinfo->FileMD5, mdContext.digest, sizeof(fileinfo->FileMD5));
  396. return;
  397. }
  398. /********************************************
  399. *串口打印所有资源文件信息
  400. **********************************************/
  401. void PrintfAllRFileInfo(void)
  402. {
  403. char strMD5[35];
  404. int i;
  405. printf("=============================RFile list============================\r\n");
  406. printf("FilesNumber=%lu\r\n",g_sutFilesList.FileCount);
  407. printf("FileName Address Length FileMD5\r\n");
  408. printf("-------------------------------------------------------------------\r\n");
  409. for(i=0;i<g_sutFilesList.FileCount;i++){
  410. UCharToStrByHex(strMD5,g_sutFilesList.FileInfo[i].FileMD5,16);
  411. printf("%-16s0x%06x %-8lu%-s\r\n",g_sutFilesList.FileInfo[i].FileName,\
  412. (unsigned int)g_sutFilesList.FileInfo[i].FileAddr,g_sutFilesList.FileInfo[i].FileLen,strMD5);
  413. }
  414. printf("====================================================================\r\n");
  415. }