Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

874 righe
26 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief WINC Flash Interface.
  6. *
  7. * Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Subject to your compliance with these terms, you may use Microchip
  14. * software and any derivatives exclusively with Microchip products.
  15. * It is your responsibility to comply with third party license terms applicable
  16. * to your use of third party software (including open source software) that
  17. * may accompany Microchip software.
  18. *
  19. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  21. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  22. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  23. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  24. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  25. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  26. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  27. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  28. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  29. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  30. *
  31. * \asf_license_stop
  32. *
  33. */
  34. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  35. INCLUDES
  36. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  37. #include "driver/include/m2m_flash.h"
  38. #include "driver/source/nmflash.h"
  39. #include "spi_flash/include/spi_flash.h"
  40. #include "nmdrv.h"
  41. //#include "main.h"
  42. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  43. GLOBALS
  44. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  45. static uint32 gu32LocationId = MEM_ID_NONE;
  46. static uint8 *gpu8Location = NULL;
  47. uint16 gu16LastAccessId = 0;
  48. uint8 gu8Success = 0;
  49. uint8 gu8Changed = 0;
  50. uint8 gu8Init = 0;
  51. uint8 gu8Reset = 0;
  52. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  53. FUNCTIONS
  54. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  55. static sint8 winc_flash_compare(uint8 *pu8Buf, uint32 u32Offset, uint32 u32Size)
  56. {
  57. sint8 ret = M2M_SUCCESS;
  58. uint8 buf[128];
  59. uint32 offset = 0;
  60. while (offset < u32Size)
  61. {
  62. uint32 chunk_sz = sizeof(buf);
  63. if (chunk_sz > u32Size - offset)
  64. chunk_sz = u32Size - offset;
  65. ret = spi_flash_read(buf, u32Offset + offset, chunk_sz);
  66. if (ret != M2M_SUCCESS)
  67. break;
  68. ret = m2m_memcmp(buf, pu8Buf + offset, chunk_sz);
  69. if (ret != 0)
  70. break;
  71. offset += chunk_sz;
  72. }
  73. return ret;
  74. }
  75. sint8 winc_flash_write_verify(uint8 *pu8Buf, uint32 u32Offset, uint32 u32Size)
  76. {
  77. sint8 ret = M2M_ERR_FAIL;
  78. uint8 count = 20;
  79. while ((ret != M2M_SUCCESS) && (count-- > 0))
  80. {
  81. ret = spi_flash_write(pu8Buf, u32Offset, u32Size);
  82. if (ret == M2M_SUCCESS)
  83. ret = winc_flash_compare(pu8Buf, u32Offset, u32Size);
  84. }
  85. return ret;
  86. }
  87. static sint8 set_changed_flag(tstrFlashAccessPersistent *pstrPersistentInfo)
  88. {
  89. sint8 ret = FLASH_RETURN_OK;
  90. if (pstrPersistentInfo->u8ModeFlags & FLASH_MODE_FLAGS_UNCHANGED)
  91. {
  92. pstrPersistentInfo->u8ModeFlags &= ~FLASH_MODE_FLAGS_UNCHANGED;
  93. if (winc_flash_write_verify((uint8*)pstrPersistentInfo, HOST_CONTROL_FLASH_OFFSET, sizeof(tstrFlashAccessPersistent)) == M2M_SUCCESS)
  94. gu8Changed = 1;
  95. else
  96. ret = FLASH_ERR_WINC_ACCESS;
  97. }
  98. return ret;
  99. }
  100. static uint8 crc7(uint8 crc, const uint8 *buff, uint16 len)
  101. {
  102. uint8 reg = crc;
  103. uint16 i;
  104. for(i = 0; i < len; i++)
  105. {
  106. uint16 g;
  107. for(g = 0; g < 8; g++)
  108. {
  109. uint8 inv = (((buff[i] << g) & 0x80) >> 7) ^ ((reg >> 6) & 1);
  110. reg = ((reg << 1) & 0x7f) ^ (9 * inv);
  111. }
  112. }
  113. return reg;
  114. }
  115. static sint8 read_control_sector(tstrOtaControlSec *pstrControlSec, uint32 u32Offset)
  116. {
  117. sint8 s8Ret = spi_flash_read((uint8*)pstrControlSec, u32Offset, sizeof(tstrOtaControlSec));
  118. if (s8Ret == M2M_SUCCESS)
  119. {
  120. if (pstrControlSec->u32OtaMagicValue != OTA_MAGIC_VALUE)
  121. s8Ret = M2M_ERR_FAIL;
  122. if (pstrControlSec->u32OtaControlSecCrc != crc7(0x7f, (uint8*)pstrControlSec, sizeof(tstrOtaControlSec) - 4))
  123. s8Ret = M2M_ERR_FAIL;
  124. }
  125. return s8Ret;
  126. }
  127. static sint8 update_control_sector(tstrOtaControlSec *pstrControlSec)
  128. {
  129. sint8 ret = M2M_ERR_FAIL;
  130. ret = spi_flash_erase(M2M_BACKUP_FLASH_OFFSET, M2M_BACKUP_FLASH_SZ);
  131. if (ret == M2M_SUCCESS)
  132. {
  133. pstrControlSec->u32OtaSequenceNumber++;
  134. pstrControlSec->u32OtaControlSecCrc = crc7(0x7f, (uint8*)pstrControlSec, sizeof(tstrOtaControlSec) - 4);
  135. ret = winc_flash_write_verify((uint8*)pstrControlSec, M2M_BACKUP_FLASH_OFFSET, sizeof(tstrOtaControlSec));
  136. if (ret == M2M_SUCCESS)
  137. {
  138. ret = spi_flash_erase(M2M_CONTROL_FLASH_OFFSET, M2M_CONTROL_FLASH_SZ);
  139. if (ret == M2M_SUCCESS)
  140. {
  141. pstrControlSec->u32OtaSequenceNumber++;
  142. pstrControlSec->u32OtaControlSecCrc = crc7(0x7f, (uint8*)pstrControlSec, sizeof(tstrOtaControlSec) - 4);
  143. ret = winc_flash_write_verify((uint8*)pstrControlSec, M2M_CONTROL_FLASH_OFFSET, sizeof(tstrOtaControlSec));
  144. }
  145. }
  146. }
  147. return ret;
  148. }
  149. static sint8 access_control_sector(tenuCSOp enuOp, uint32 *param)
  150. {
  151. static tstrOtaControlSec strControlSec = {0};
  152. sint8 s8Ret = M2M_SUCCESS;
  153. uint8 bUpdate = false;
  154. if ((enuOp != CS_INITIALIZE) && (strControlSec.u32OtaMagicValue != OTA_MAGIC_VALUE))
  155. {
  156. if (param != NULL)
  157. *param = 0;
  158. return M2M_ERR_FAIL;
  159. }
  160. switch (enuOp)
  161. {
  162. case CS_INITIALIZE:
  163. s8Ret = read_control_sector(&strControlSec, M2M_CONTROL_FLASH_OFFSET);
  164. if (s8Ret != M2M_SUCCESS)
  165. {
  166. s8Ret = read_control_sector(&strControlSec, M2M_BACKUP_FLASH_OFFSET);
  167. if (s8Ret == M2M_SUCCESS)
  168. {
  169. /*
  170. * Reinstate the control sector from backup.
  171. */
  172. s8Ret = spi_flash_erase(M2M_CONTROL_FLASH_OFFSET, M2M_CONTROL_FLASH_SZ);
  173. if (s8Ret == M2M_SUCCESS)
  174. s8Ret = winc_flash_write_verify((uint8*)&strControlSec, M2M_CONTROL_FLASH_OFFSET, sizeof(tstrOtaControlSec));
  175. }
  176. }
  177. break;
  178. case CS_INVALIDATE_RB:
  179. // Update trashes the backup sector, so we need to avoid unnecessary updates.
  180. if (strControlSec.u32OtaRollbackImageValidStatus != OTA_STATUS_INVALID)
  181. {
  182. strControlSec.u32OtaRollbackImageValidStatus = OTA_STATUS_INVALID;
  183. bUpdate = true;
  184. }
  185. break;
  186. case CS_VALIDATE_RB:
  187. // Update trashes the backup sector, so we need to avoid unnecessary updates.
  188. if (strControlSec.u32OtaRollbackImageValidStatus != OTA_STATUS_VALID)
  189. {
  190. strControlSec.u32OtaRollbackImageValidStatus = OTA_STATUS_VALID;
  191. bUpdate = true;
  192. }
  193. break;
  194. case CS_VALIDATE_SWITCH:
  195. strControlSec.u32OtaRollbackImageValidStatus = OTA_STATUS_VALID;
  196. // intentional fallthrough.
  197. case CS_SWITCH:
  198. if (strControlSec.u32OtaRollbackImageValidStatus == OTA_STATUS_VALID)
  199. {
  200. uint32 tmp = strControlSec.u32OtaCurrentworkingImagOffset;
  201. strControlSec.u32OtaCurrentworkingImagOffset = strControlSec.u32OtaRollbackImageOffset;
  202. strControlSec.u32OtaRollbackImageOffset = tmp;
  203. bUpdate = true;
  204. }
  205. else
  206. s8Ret = M2M_ERR_FAIL;
  207. break;
  208. case CS_GET_ACTIVE:
  209. if (param == NULL)
  210. s8Ret = M2M_ERR_FAIL;
  211. else
  212. *param = strControlSec.u32OtaCurrentworkingImagOffset;
  213. break;
  214. case CS_GET_INACTIVE:
  215. if (param == NULL)
  216. s8Ret = M2M_ERR_FAIL;
  217. else
  218. *param = strControlSec.u32OtaRollbackImageOffset;
  219. break;
  220. case CS_DEINITIALIZE:
  221. m2m_memset((uint8*)&strControlSec, 0, sizeof(tstrOtaControlSec));
  222. break;
  223. default:
  224. s8Ret = M2M_ERR_FAIL;
  225. }
  226. if (bUpdate)
  227. {
  228. s8Ret = update_control_sector(&strControlSec);
  229. M2M_INFO("CS update:%d %s\n", enuOp, (s8Ret==M2M_SUCCESS)?"":"Failed");
  230. }
  231. return s8Ret;
  232. }
  233. static sint8 local_access_ptr(tenuFlashDataFnCtl enuCtl, void *pvStr)
  234. {
  235. sint8 s8Ret = M2M_ERR_FAIL;
  236. static uint8 *pu8Location = NULL;
  237. static uint8 u8Flags = 0;
  238. switch (enuCtl)
  239. {
  240. case FLASH_DATA_FN_INITIALIZE:
  241. {
  242. tstrDataAccessInitParams *init_params = (tstrDataAccessInitParams*)pvStr;
  243. u8Flags = init_params->u8Flags;
  244. pu8Location = gpu8Location;
  245. s8Ret = M2M_SUCCESS;
  246. }
  247. break;
  248. case FLASH_DATA_FN_DATA:
  249. if (pu8Location != NULL)
  250. {
  251. tstrDataAccessParams *params = (tstrDataAccessParams*)pvStr;
  252. if (u8Flags & FLASH_FN_FLAGS_WRITE)
  253. m2m_memcpy(pu8Location, params->pu8Buf + params->u32DataOffset, params->u32DataSize);
  254. if (u8Flags & FLASH_FN_FLAGS_READ)
  255. m2m_memcpy(params->pu8Buf + params->u32DataOffset, pu8Location, params->u32DataSize);
  256. pu8Location += params->u32DataSize;
  257. s8Ret = M2M_SUCCESS;
  258. }
  259. break;
  260. case FLASH_DATA_FN_TERMINATE:
  261. case FLASH_DATA_FN_COMPLETE:
  262. u8Flags = 0;
  263. pu8Location = NULL;
  264. s8Ret = M2M_SUCCESS;
  265. break;
  266. }
  267. return s8Ret;
  268. }
  269. static sint8 winc_flash_access(tenuFlashDataFnCtl enuCtl, void *pvStr)
  270. {
  271. sint8 s8Ret = M2M_ERR_FAIL;
  272. static uint32 u32CurrentAddr = 0;
  273. static uint8 u8Flags = 0;
  274. switch (enuCtl)
  275. {
  276. case FLASH_DATA_FN_INITIALIZE:
  277. {
  278. tstrDataAccessInitParams *init_params = (tstrDataAccessInitParams*)pvStr;
  279. printf("FA Init: 0x%lx Fg 0x%02x Sz 0x%lx \n", gu32LocationId, init_params->u8Flags, init_params->u32TotalSize);
  280. u8Flags = init_params->u8Flags;
  281. switch (gu32LocationId)
  282. {
  283. case MEM_ID_WINC_FLASH:
  284. u32CurrentAddr = 0;
  285. break;
  286. case MEM_ID_WINC_ACTIVE:
  287. s8Ret = access_control_sector(CS_GET_ACTIVE, &u32CurrentAddr);
  288. break;
  289. case MEM_ID_WINC_INACTIVE:
  290. s8Ret = access_control_sector(CS_GET_INACTIVE, &u32CurrentAddr);
  291. /* If we're about to write to the inactive partition, mark it as invalid. */
  292. if ((s8Ret == M2M_SUCCESS) && (u8Flags & (FLASH_FN_FLAGS_WRITE | FLASH_FN_FLAGS_ERASE)))
  293. s8Ret = access_control_sector(CS_INVALIDATE_RB, NULL);
  294. break;
  295. case MEM_ID_NONE:
  296. s8Ret = M2M_ERR_FAIL;
  297. break;
  298. default:
  299. u32CurrentAddr = gu32LocationId;
  300. break;
  301. }
  302. if (u8Flags & FLASH_FN_FLAGS_READ_SURROUNDING)
  303. {
  304. init_params->u32AlignmentSize = FLASH_SECTOR_SZ;
  305. init_params->u32StartAlignment = u32CurrentAddr & (FLASH_SECTOR_SZ - 1);
  306. }
  307. s8Ret = M2M_SUCCESS;
  308. }
  309. break;
  310. case FLASH_DATA_FN_DATA:
  311. {
  312. tstrDataAccessParams *params = (tstrDataAccessParams*)pvStr;
  313. if (u8Flags & FLASH_FN_FLAGS_COMPARE_BEFORE)
  314. {
  315. printf("c-");
  316. // If contents match already, return success
  317. s8Ret = winc_flash_compare(params->pu8Buf + params->u32DataOffset, u32CurrentAddr, params->u32DataSize);
  318. if (s8Ret == M2M_SUCCESS)
  319. goto END;
  320. }
  321. if (u8Flags & FLASH_FN_FLAGS_READ_SURROUNDING)
  322. {
  323. uint32 prefill_sz = params->u32DataOffset;
  324. uint32 postfill_sz = params->u32BufSize - (params->u32DataOffset + params->u32DataSize);
  325. if (prefill_sz > 0)
  326. {
  327. printf("r-");
  328. s8Ret = spi_flash_read(params->pu8Buf, u32CurrentAddr - prefill_sz, prefill_sz);
  329. if (s8Ret != M2M_SUCCESS)
  330. goto END;
  331. }
  332. if (postfill_sz > 0)
  333. {
  334. printf("-r");
  335. s8Ret = spi_flash_read(params->pu8Buf + params->u32BufSize - postfill_sz, u32CurrentAddr + params->u32DataSize, postfill_sz);
  336. if (s8Ret != M2M_SUCCESS)
  337. goto END;
  338. }
  339. }
  340. if (u8Flags & FLASH_FN_FLAGS_BACKUP)
  341. {
  342. if (params->u32BufSize > params->u32DataSize)
  343. {
  344. printf("b");
  345. s8Ret = winc_flash_write_verify(params->pu8Buf, M2M_BACKUP_FLASH_OFFSET, params->u32BufSize);
  346. if (s8Ret == M2M_SUCCESS)
  347. s8Ret = prepare_backup(u32CurrentAddr - params->u32DataOffset);
  348. if (s8Ret != M2M_SUCCESS)
  349. goto END;
  350. }
  351. }
  352. if (u8Flags & FLASH_FN_FLAGS_ERASE)
  353. {
  354. printf("e");
  355. s8Ret = spi_flash_erase(u32CurrentAddr, params->u32DataSize);
  356. if (s8Ret != M2M_SUCCESS)
  357. goto END;
  358. }
  359. if (u8Flags & FLASH_FN_FLAGS_WRITE)
  360. {
  361. printf("W");
  362. if (u8Flags & FLASH_FN_FLAGS_READ_SURROUNDING)
  363. s8Ret = spi_flash_write(params->pu8Buf, u32CurrentAddr - params->u32DataOffset, params->u32BufSize);
  364. else
  365. s8Ret = spi_flash_write(params->pu8Buf + params->u32DataOffset, u32CurrentAddr, params->u32DataSize);
  366. if (s8Ret != M2M_SUCCESS)
  367. goto END;
  368. }
  369. if (u8Flags & FLASH_FN_FLAGS_COMPARE_AFTER)
  370. {
  371. printf("-c");
  372. // If contents do not match, return failure
  373. if (u8Flags & FLASH_FN_FLAGS_READ_SURROUNDING)
  374. s8Ret = winc_flash_compare(params->pu8Buf, u32CurrentAddr - params->u32DataOffset, params->u32BufSize);
  375. else
  376. s8Ret = winc_flash_compare(params->pu8Buf + params->u32DataOffset, u32CurrentAddr, params->u32DataSize);
  377. if (s8Ret != M2M_SUCCESS)
  378. goto END;
  379. }
  380. if (u8Flags & FLASH_FN_FLAGS_READ)
  381. {
  382. printf("R");
  383. s8Ret = spi_flash_read(params->pu8Buf + params->u32DataOffset, u32CurrentAddr, params->u32DataSize);
  384. if (s8Ret != M2M_SUCCESS)
  385. goto END;
  386. }
  387. END:
  388. u32CurrentAddr += params->u32DataSize;
  389. }
  390. break;
  391. case FLASH_DATA_FN_TERMINATE:
  392. case FLASH_DATA_FN_COMPLETE:
  393. printf(" FA End 0x%lx\n", u32CurrentAddr);
  394. u8Flags = 0;
  395. u32CurrentAddr = 0;
  396. s8Ret = M2M_SUCCESS;
  397. break;
  398. }
  399. return s8Ret;
  400. }
  401. void set_internal_info_ptr(tpfDataAccessFn *ppfFn, uint8 *pu8Ptr)
  402. {
  403. if (ppfFn != NULL)
  404. *ppfFn = local_access_ptr;
  405. gpu8Location = pu8Ptr;
  406. }
  407. void set_internal_info(tpfDataAccessFn *ppfFn, uint32 u32LocationId)
  408. {
  409. if (ppfFn != NULL)
  410. *ppfFn = winc_flash_access;
  411. gu32LocationId = u32LocationId;
  412. }
  413. uint8 is_internal_info(tpfDataAccessFn pfFn)
  414. {
  415. if (pfFn == winc_flash_access)
  416. return true;
  417. return false;
  418. }
  419. sint8 recover_backup(void)
  420. {
  421. sint8 ret = FLASH_RETURN_OK;
  422. uint32 u32BackupAddr = FLASH_BACKUP_STORE_OFFSET;
  423. tstrBackup strBackup;
  424. while (u32BackupAddr < FLASH_BACKUP_STORE_OFFSET + FLASH_BACKUP_STORE_SZ)
  425. {
  426. sint8 status = spi_flash_read((uint8*)&strBackup, u32BackupAddr, sizeof(tstrBackup));
  427. if ((status == M2M_SUCCESS) && (strBackup.enuTransferStatus == BACKUP_STATUS_ACTIVE))
  428. {
  429. uint8 *pu8Buff = malloc(strBackup.u32Size);
  430. if (pu8Buff == NULL)
  431. {
  432. ret = FLASH_ERR_INTERNAL;
  433. goto ERR;
  434. }
  435. status = spi_flash_read(pu8Buff, strBackup.u32SourceAddr, strBackup.u32Size);
  436. if (status == M2M_SUCCESS)
  437. {
  438. status = spi_flash_erase(strBackup.u32DestinationAddr, strBackup.u32Size);
  439. if (status == M2M_SUCCESS)
  440. {
  441. status = winc_flash_write_verify(pu8Buff, strBackup.u32DestinationAddr, strBackup.u32Size);
  442. if (status == M2M_SUCCESS)
  443. {
  444. strBackup.enuTransferStatus = BACKUP_STATUS_DONE;
  445. status = winc_flash_write_verify((uint8*)&strBackup.enuTransferStatus, u32BackupAddr, FLASH_BACKUP_STA_SZ);
  446. }
  447. }
  448. }
  449. free(pu8Buff);
  450. }
  451. if (status != M2M_SUCCESS)
  452. {
  453. ret = FLASH_ERR_WINC_ACCESS;
  454. goto ERR;
  455. }
  456. u32BackupAddr += sizeof(tstrBackup);
  457. }
  458. ERR:
  459. return ret;
  460. }
  461. sint8 prepare_backup(uint32 u32Target)
  462. {
  463. sint8 s8Ret = M2M_ERR_FAIL;
  464. uint32 u32BackupAddr = FLASH_BACKUP_STORE_OFFSET;
  465. tenuBackupStatus enuStatus = BACKUP_STATUS_EMPTY;
  466. s8Ret = spi_flash_read((uint8*)&enuStatus, u32BackupAddr, sizeof(enuStatus));
  467. if ((s8Ret != M2M_SUCCESS) || (enuStatus != BACKUP_STATUS_EMPTY))
  468. {
  469. u32BackupAddr += sizeof(tstrBackup);
  470. s8Ret = spi_flash_read((uint8*)&enuStatus, u32BackupAddr, sizeof(enuStatus));
  471. if ((s8Ret == M2M_SUCCESS) && (enuStatus != BACKUP_STATUS_EMPTY))
  472. s8Ret = M2M_ERR_FAIL;
  473. }
  474. if (s8Ret == M2M_SUCCESS)
  475. {
  476. tstrBackup strBackup = {BACKUP_STATUS_NOT_ACTIVE, u32Target, M2M_BACKUP_FLASH_OFFSET, M2M_BACKUP_FLASH_SZ};
  477. s8Ret = winc_flash_write_verify((uint8*)&strBackup.enuTransferStatus, u32BackupAddr, FLASH_BACKUP_STA_SZ);
  478. if (s8Ret == M2M_SUCCESS)
  479. {
  480. s8Ret = winc_flash_write_verify((uint8*)&strBackup, u32BackupAddr, sizeof(strBackup));
  481. if (s8Ret == M2M_SUCCESS)
  482. {
  483. strBackup.enuTransferStatus = BACKUP_STATUS_ACTIVE;
  484. s8Ret = winc_flash_write_verify((uint8*)&strBackup.enuTransferStatus, u32BackupAddr, FLASH_BACKUP_STA_SZ);
  485. }
  486. }
  487. }
  488. return s8Ret;
  489. }
  490. sint8 image_get_target(uint8 *pu8Target)
  491. {
  492. sint8 s8Ret = M2M_ERR_FAIL;
  493. uint32 u32OffsetActive = 0;
  494. uint32 u32OffsetInactive = 0;
  495. s8Ret = access_control_sector(CS_INITIALIZE, NULL);
  496. if (s8Ret == M2M_SUCCESS)
  497. {
  498. s8Ret = access_control_sector(CS_GET_ACTIVE, &u32OffsetActive);
  499. if (s8Ret == M2M_SUCCESS)
  500. {
  501. s8Ret = access_control_sector(CS_GET_INACTIVE, &u32OffsetInactive);
  502. if (s8Ret == M2M_SUCCESS)
  503. *pu8Target = (u32OffsetInactive > u32OffsetActive) ? 1 : 0;
  504. }
  505. access_control_sector(CS_DEINITIALIZE, NULL);
  506. }
  507. return s8Ret;
  508. }
  509. sint8 rootcert_get_size(tstrRootCertEntryHeader *pstrHdr, uint16 *pu16Size)
  510. {
  511. sint8 s8Ret = M2M_ERR_FAIL;
  512. if ((pstrHdr == NULL) || (pu16Size == NULL))
  513. goto ERR;
  514. /* Set default size out to maximum. */
  515. *pu16Size = 0xFFFF;
  516. switch (pstrHdr->strPubKey.u32PubKeyType)
  517. {
  518. case ROOT_CERT_PUBKEY_RSA:
  519. if (pstrHdr->strPubKey.strRsaKeyInfo.u16NSz > M2M_TLS_ROOTCER_FLASH_SZ)
  520. goto ERR;
  521. if (pstrHdr->strPubKey.strRsaKeyInfo.u16ESz > M2M_TLS_ROOTCER_FLASH_SZ)
  522. goto ERR;
  523. *pu16Size = sizeof(tstrRootCertEntryHeader) + ((pstrHdr->strPubKey.strRsaKeyInfo.u16NSz + 0x3) & ~0x3) + ((pstrHdr->strPubKey.strRsaKeyInfo.u16ESz + 0x3) & ~0x3);
  524. s8Ret = M2M_SUCCESS;
  525. break;
  526. case ROOT_CERT_PUBKEY_ECDSA:
  527. if (pstrHdr->strPubKey.strEcsdaKeyInfo.u16KeySz > M2M_TLS_ROOTCER_FLASH_SZ)
  528. goto ERR;
  529. *pu16Size = sizeof(tstrRootCertEntryHeader) + ((pstrHdr->strPubKey.strEcsdaKeyInfo.u16KeySz + 0x3) & ~0x3) * 2;
  530. s8Ret = M2M_SUCCESS;
  531. break;
  532. case 0xFFFFFFFF:
  533. // Invalid. May indicate end of list. Fail with size set to 0.
  534. *pu16Size = 0;
  535. break;
  536. default:
  537. // Corrupt header.
  538. break;
  539. }
  540. ERR:
  541. return s8Ret;
  542. }
  543. sint8 rootcert_access(tenuFlashAccessItemMode enuMode, tstrRootCertEntryHeader *pstrReferenceHdr, uint16 *pu16EntrySize, uint8 *pu8Buff, uint32 *pu32Offset)
  544. {
  545. sint8 ret = FLASH_RETURN_OK;
  546. sint8 status = M2M_SUCCESS;
  547. uint8 au8RootCertSig[] = M2M_TLS_ROOTCER_FLASH_SIG;
  548. tstrRootCertEntryHeader strEntryHeader;
  549. /* Previous version used 0-identifiers to indicate removed entries. Use last 20 bytes of pu8Buff to help us check for them. */
  550. uint8 *pu8Zero = pu8Buff + M2M_TLS_ROOTCER_FLASH_SZ - sizeof(pstrReferenceHdr->au8SHA1NameHash);
  551. uint32 u32StoreOffset = 0;
  552. uint32 u32Entries = 0;
  553. m2m_memset(pu8Zero, 0, sizeof(pstrReferenceHdr->au8SHA1NameHash));
  554. /* Use pu8SectionBuffer to read signature. */
  555. status = spi_flash_read(pu8Buff, M2M_TLS_ROOTCER_FLASH_OFFSET, sizeof(au8RootCertSig));
  556. if ((status != M2M_SUCCESS) || m2m_memcmp(pu8Buff, au8RootCertSig, sizeof(au8RootCertSig)))
  557. {
  558. /*
  559. * Root certificate section is not initialized. We could try to initialize it
  560. * here, but for now just fail.
  561. */
  562. ret = FLASH_ERR_WINC_ACCESS;
  563. goto ERR;
  564. }
  565. /*
  566. * By default assume we'll get to the end of the flash store without finding what we need
  567. * (matching entry or space to add new entry). If we break while loop before reaching end of
  568. * store then we'll change ret accordingly. */
  569. if (enuMode == FLASH_ITEM_ADD)
  570. ret = FLASH_ERR_SIZE;
  571. else
  572. ret = FLASH_ERR_WINC_CONFLICT;
  573. u32StoreOffset = *pu32Offset = sizeof(tstrRootCertFlashHeader);
  574. while (u32StoreOffset + sizeof(tstrRootCertEntryHeader) < M2M_TLS_ROOTCER_FLASH_SZ)
  575. {
  576. uint16 u16EntrySize = 0;
  577. status = spi_flash_read((uint8*)&strEntryHeader, M2M_TLS_ROOTCER_FLASH_OFFSET + u32StoreOffset, sizeof(tstrRootCertEntryHeader));
  578. if (status != M2M_SUCCESS)
  579. {
  580. ret = FLASH_ERR_WINC_ACCESS;
  581. break;
  582. }
  583. status = rootcert_get_size(&strEntryHeader, &u16EntrySize);
  584. if (status != M2M_SUCCESS)
  585. {
  586. // Found the end of the list. We are done. If we are adding an entry, check the space here.
  587. if ((enuMode == FLASH_ITEM_ADD) && ((*pu32Offset + *pu16EntrySize) <= M2M_TLS_ROOTCER_FLASH_SZ))
  588. {
  589. u32Entries++;
  590. ret = FLASH_RETURN_OK;
  591. }
  592. break;
  593. }
  594. // If we are here we know that u32EntrySize is sane.
  595. if (m2m_memcmp(pu8Zero, (uint8*)pstrReferenceHdr, sizeof(strEntryHeader.au8SHA1NameHash)))
  596. {
  597. // Entry is not empty.
  598. status = spi_flash_read(pu8Buff + *pu32Offset, M2M_TLS_ROOTCER_FLASH_OFFSET + u32StoreOffset, u16EntrySize);
  599. if (status != M2M_SUCCESS)
  600. {
  601. ret = FLASH_ERR_WINC_ACCESS;
  602. break;
  603. }
  604. if (enuMode == FLASH_ITEM_READIDX)
  605. {
  606. if (u32Entries == *(uint32*)pstrReferenceHdr)
  607. {
  608. // Found entry. pu16EntrySize is used to output size.
  609. *pu16EntrySize = u16EntrySize;
  610. ret = FLASH_RETURN_OK;
  611. break;
  612. }
  613. }
  614. else if (!m2m_memcmp(strEntryHeader.au8SHA1NameHash, (uint8*)pstrReferenceHdr, sizeof(strEntryHeader.au8SHA1NameHash)))
  615. {
  616. if (enuMode == FLASH_ITEM_ADD)
  617. {
  618. // Found a match. Cannot add.
  619. ret = FLASH_ERR_WINC_CONFLICT;
  620. break;
  621. }
  622. if (enuMode == FLASH_ITEM_READ)
  623. {
  624. // Found a match. pu16EntrySize is used to output size.
  625. *pu16EntrySize = u16EntrySize;
  626. ret = FLASH_RETURN_OK;
  627. break;
  628. }
  629. if (enuMode == FLASH_ITEM_REMOVE)
  630. {
  631. // Found a match. Continue, to complete entry count.
  632. ret = FLASH_RETURN_OK;
  633. // Cancel out increment of u32BuffOffset.
  634. *pu32Offset -= u16EntrySize;
  635. }
  636. }
  637. *pu32Offset += u16EntrySize;
  638. u32Entries++;
  639. }
  640. u32StoreOffset += u16EntrySize;
  641. }
  642. if (ret == FLASH_RETURN_OK)
  643. ((tstrRootCertFlashHeader*)pu8Buff)->u32nCerts = u32Entries;
  644. ERR:
  645. return ret;
  646. }
  647. sint8 transfer_run(tstrFlashAccess *pstrFlashAccess)
  648. {
  649. /*
  650. * Errors before start of first transfer will be reported as parameter errors.
  651. * This means the information is insufficient to allow us to begin.
  652. */
  653. sint8 ret = FLASH_RETURN_OK;
  654. sint8 status = M2M_ERR_FAIL;
  655. tpfDataAccessFn pfWriteFn = pstrFlashAccess->pfDestinationFn;
  656. tpfDataAccessFn pfReadFn = pstrFlashAccess->pfSourceFn;
  657. tstrDataAccessInitParams read_init_params = {pstrFlashAccess->u32Size, FLASH_FN_FLAGS_READ, 0, 0};
  658. tstrDataAccessInitParams write_init_params = {pstrFlashAccess->u32Size, FLASH_FN_FLAGS_WRITE, 0, 0};
  659. uint32 u32BytesTransferred = 0;
  660. uint32 u32BytesRemaining = pstrFlashAccess->u32Size;
  661. uint8 *pu8Buff = NULL;
  662. if (pstrFlashAccess->strPersistentInfo.u8AccessFlags & FLASH_ACCESS_OPTION_COMPARE_BEFORE)
  663. write_init_params.u8Flags |= FLASH_FN_FLAGS_COMPARE_BEFORE;
  664. if (pstrFlashAccess->strPersistentInfo.u8AccessFlags & FLASH_ACCESS_OPTION_ERASE_FIRST)
  665. {
  666. write_init_params.u8Flags |= FLASH_FN_FLAGS_ERASE;
  667. if (pstrFlashAccess->strPersistentInfo.u8AccessFlags & FLASH_ACCESS_OPTION_KEEP_SURROUNDING)
  668. {
  669. write_init_params.u8Flags |= FLASH_FN_FLAGS_READ_SURROUNDING;
  670. if (pstrFlashAccess->strPersistentInfo.u8AccessFlags & FLASH_ACCESS_OPTION_USE_BACKUP)
  671. write_init_params.u8Flags |= FLASH_FN_FLAGS_BACKUP;
  672. }
  673. }
  674. if (pstrFlashAccess->strPersistentInfo.u8AccessFlags & FLASH_ACCESS_OPTION_COMPARE_AFTER)
  675. write_init_params.u8Flags |= FLASH_FN_FLAGS_COMPARE_AFTER;
  676. if (pstrFlashAccess->strPersistentInfo.u8ModeFlags & FLASH_MODE_FLAGS_DATA_IN_BACKUP)
  677. {
  678. if (prepare_backup(gu32LocationId) != M2M_SUCCESS)
  679. {
  680. ret = FLASH_ERR_WINC_ACCESS;
  681. goto ERR;
  682. }
  683. set_changed_flag(&pstrFlashAccess->strPersistentInfo);
  684. ret = recover_backup();
  685. if (ret < 0)
  686. goto ERR;
  687. }
  688. /*
  689. * Initialize control sector. Even if we don't need to access it, this at
  690. * least ensures that the control sector is not relying on the flash backup sector.
  691. */
  692. status = access_control_sector(CS_INITIALIZE, NULL);
  693. if (status != M2M_SUCCESS && (pstrFlashAccess->strPersistentInfo.u8ModeFlags & FLASH_MODE_FLAGS_CS))
  694. {
  695. ret = FLASH_ERR_WINC_ACCESS;
  696. goto ERR;
  697. }
  698. if (pfReadFn != NULL)
  699. {
  700. /* Prepare for read. */
  701. status = pfReadFn(FLASH_DATA_FN_INITIALIZE, &read_init_params);
  702. if (status != M2M_SUCCESS)
  703. {
  704. if (is_internal_info(pfReadFn))
  705. ret = FLASH_ERR_WINC_ACCESS;
  706. else
  707. ret = FLASH_ERR_LOCAL_ACCESS;
  708. pfReadFn(FLASH_DATA_FN_TERMINATE, NULL);
  709. goto ERR;
  710. }
  711. }
  712. if (pfWriteFn != NULL)
  713. {
  714. /* Prepare for write. */
  715. status = pfWriteFn(FLASH_DATA_FN_INITIALIZE, &write_init_params);
  716. if (status != M2M_SUCCESS)
  717. {
  718. if (is_internal_info(pfWriteFn))
  719. ret = FLASH_ERR_WINC_ACCESS;
  720. else
  721. ret = FLASH_ERR_LOCAL_ACCESS;
  722. goto TERMINATE;
  723. }
  724. }
  725. if (u32BytesRemaining > 0)
  726. {
  727. if (u32BytesRemaining > FLASH_SECTOR_SIZE)
  728. pu8Buff = malloc(FLASH_SECTOR_SIZE);
  729. else if (write_init_params.u32AlignmentSize > 1)
  730. pu8Buff = malloc(write_init_params.u32AlignmentSize);
  731. else
  732. pu8Buff = malloc(u32BytesRemaining);
  733. if (pu8Buff == NULL)
  734. {
  735. ret = FLASH_ERR_INTERNAL;
  736. goto TERMINATE;
  737. }
  738. }
  739. while (u32BytesRemaining > 0)
  740. {
  741. tstrDataAccessParams params = {pu8Buff, FLASH_SECTOR_SIZE, 0, FLASH_SECTOR_SIZE};
  742. if (u32BytesTransferred > 0)
  743. write_init_params.u32StartAlignment = 0;
  744. if (write_init_params.u32AlignmentSize > 1)
  745. {
  746. params.u32DataOffset = write_init_params.u32StartAlignment & (write_init_params.u32AlignmentSize-1);
  747. params.u32DataSize = write_init_params.u32AlignmentSize - params.u32DataOffset;
  748. }
  749. if (params.u32DataSize > u32BytesRemaining)
  750. params.u32DataSize = u32BytesRemaining;
  751. /* Read. */
  752. if (pfReadFn != NULL)
  753. {
  754. status = pfReadFn(FLASH_DATA_FN_DATA, &params);
  755. if (status != M2M_SUCCESS)
  756. {
  757. if (is_internal_info(pfReadFn))
  758. ret = FLASH_ERR_WINC_ACCESS;
  759. else
  760. ret = FLASH_ERR_LOCAL_ACCESS;
  761. break;
  762. }
  763. }
  764. /* Write. */
  765. if (pfWriteFn != NULL)
  766. {
  767. if (is_internal_info(pfWriteFn))
  768. {
  769. ret = set_changed_flag(&pstrFlashAccess->strPersistentInfo);
  770. if (ret < 0)
  771. break;
  772. }
  773. status = pfWriteFn(FLASH_DATA_FN_DATA, &params);
  774. if (status != M2M_SUCCESS)
  775. {
  776. if (is_internal_info(pfWriteFn))
  777. ret = FLASH_ERR_WINC_ACCESS;
  778. else
  779. ret = FLASH_ERR_LOCAL_ACCESS;
  780. break;
  781. }
  782. }
  783. u32BytesTransferred += params.u32DataSize;
  784. u32BytesRemaining -= params.u32DataSize;
  785. }
  786. if (u32BytesRemaining > 0)
  787. {
  788. TERMINATE:
  789. if (pfReadFn != NULL)
  790. pfReadFn(FLASH_DATA_FN_TERMINATE, NULL);
  791. if (pfWriteFn != NULL)
  792. pfWriteFn(FLASH_DATA_FN_TERMINATE, NULL);
  793. goto ERR;
  794. }
  795. else
  796. {
  797. if (pfReadFn != NULL)
  798. pfReadFn(FLASH_DATA_FN_COMPLETE, NULL);
  799. if (pfWriteFn != NULL)
  800. pfWriteFn(FLASH_DATA_FN_COMPLETE, NULL);
  801. }
  802. if (pstrFlashAccess->strPersistentInfo.u8ModeFlags & (FLASH_MODE_FLAGS_CS_VALIDATE_IMAGE | FLASH_MODE_FLAGS_CS_SWITCH))
  803. {
  804. tenuCSOp enuOp;
  805. ret = set_changed_flag(&pstrFlashAccess->strPersistentInfo);
  806. if (ret < 0)
  807. goto ERR;
  808. if (pstrFlashAccess->strPersistentInfo.u8ModeFlags & FLASH_MODE_FLAGS_CS_VALIDATE_IMAGE)
  809. {
  810. if (pstrFlashAccess->strPersistentInfo.u8ModeFlags & FLASH_MODE_FLAGS_CS_SWITCH)
  811. enuOp = CS_VALIDATE_SWITCH;
  812. else
  813. enuOp = CS_VALIDATE_RB;
  814. }
  815. else
  816. enuOp = CS_SWITCH;
  817. status = access_control_sector(enuOp, NULL);
  818. if (status != M2M_SUCCESS)
  819. {
  820. ret = FLASH_ERR_WINC_ACCESS;
  821. goto ERR;
  822. }
  823. }
  824. pstrFlashAccess->strPersistentInfo.enuTransferStatus = FLASH_STATUS_DONE;
  825. status = winc_flash_write_verify((uint8*)pstrFlashAccess, HOST_CONTROL_FLASH_OFFSET, sizeof(tstrFlashAccessPersistent));
  826. gu8Success = 1;
  827. ERR:
  828. if (pu8Buff != NULL)
  829. free(pu8Buff);
  830. access_control_sector(CS_DEINITIALIZE, NULL);
  831. return ret;
  832. }