sparse_state_machine_nand.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include <debug.h>
  2. #include "sparse_format.h"
  3. #include "sparse_state_machine.h"
  4. #include "transfer.h"
  5. #include "pal_log.h"
  6. #if (!defined(MTK_UFS_SUPPORT) && !defined(MTK_EMMC_SUPPORT))
  7. #include <platform/mtk_nand.h>
  8. #if defined(MTK_MLC_NAND_SUPPORT) || defined(MTK_TLC_NAND_SUPPORT)
  9. extern int nand_write_img(u64 addr, void *data, u32 img_sz,u64 partition_size,int partition_type);
  10. extern int nand_write_img_ex(u64 addr, void *data, u32 length,u64 total_size, u32 *next_offset, u64 partition_start,u64 partition_size, int img_type);
  11. #else
  12. extern int nand_write_img(u32 addr, void *data, u32 img_sz,u32 partition_size,int partition_type);
  13. extern int nand_write_img_ex(u32 addr, void *data, u32 length,u32 total_size, u32 *next_offset, u32 partition_start,u32 partition_size, int img_type);
  14. #endif
  15. //only engine data structure.
  16. static unsparse_data_t m_unsparse_data;
  17. static void write_sparse_data_internal(unsparse_status_t* status);
  18. static void set_unsparse_status( unsparse_status_t* status,
  19. status_t handle_status,
  20. unsparse_phase_t wait_phase,
  21. uint32 size,
  22. uint8 *buf )
  23. {
  24. status->handle_status = handle_status;
  25. status->wait_phase = wait_phase;
  26. status->byte_to_process = size;
  27. status->buf = buf;
  28. }
  29. static void init_cache_context(unsparse_status_t* status);
  30. void init_unsparse_status(unsparse_status_t* status, partition_info_struct_t* partition)
  31. {
  32. memset(status, 0, sizeof(unsparse_status_t));
  33. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_SPARSE_HEADER, 0, 0);
  34. status->partition = partition;
  35. init_cache_context(status);
  36. }
  37. extern int nand_get_alignment();
  38. static void adjust_cache_size(struct cache_ctx* ctx)
  39. {
  40. uint32 size = nand_get_alignment();
  41. ctx->c_base = get_global_cache1();
  42. ctx->c_size = size;
  43. ctx->c_offset = 0;
  44. }
  45. static void init_cache_context(unsparse_status_t* status)
  46. {
  47. adjust_cache_size(&status->ctx);
  48. }
  49. extern int get_nand_image_type(const char* arg);
  50. void end_write_sparse_data(unsparse_status_t* status)
  51. {
  52. status->wait_phase = UNSPARSE_WAIT_CHUNK_NOT_CARE;
  53. m_unsparse_data.chunk_remain_data_size = status->ctx.c_size - status->ctx.c_offset;
  54. write_sparse_data_internal(status);
  55. }
  56. static void memsetint(void* p, int i, int len)
  57. {
  58. int idx=0;
  59. int count = len>>2;
  60. int* buf = (int*)p;
  61. while(idx < count)
  62. {
  63. buf[idx++] = i;
  64. }
  65. }
  66. #define LOGDBG(...)
  67. static void write_sparse_data_internal(unsparse_status_t* status)
  68. {
  69. uint32 size = status->byte_to_process;
  70. uint8 *buf = status->buf;
  71. int filled_seed = 0;
  72. LOGDBG("+++++++++++++++++++++++++++\n");
  73. LOGDBG(" slot base:[0x%x]\n", status->ctx.c_base);
  74. switch (status->wait_phase)
  75. {
  76. case UNSPARSE_WAIT_SPARSE_HEADER:
  77. {
  78. LOGDBG("+ SPARSE_HEADER\n");
  79. if (size >=sizeof (sparse_header_t))
  80. {
  81. memset((void*)&m_unsparse_data, 0x00, sizeof(unsparse_data_t));
  82. memcpy((void*)&m_unsparse_data.sparse_hdr, buf, sizeof (sparse_header_t));
  83. size -= sizeof (sparse_header_t);
  84. buf+= sizeof (sparse_header_t);
  85. m_unsparse_data.unhandle_buf_size = 0;
  86. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  87. }
  88. LOGDBG("- SPARSE_HEADER\n");
  89. break;
  90. }
  91. case UNSPARSE_WAIT_CHUNK_HEADER:
  92. {
  93. LOGDBG("+ CHUNK_HEADER\n");
  94. if (m_unsparse_data.unhandle_buf_size + size >= m_unsparse_data.sparse_hdr.chunk_hdr_sz)
  95. {
  96. if (m_unsparse_data.unhandle_buf_size > 0)
  97. {
  98. uint32 sizeOfUsedBuf = m_unsparse_data.sparse_hdr.chunk_hdr_sz - m_unsparse_data.unhandle_buf_size;
  99. memcpy(&m_unsparse_data.chunk_hdr, m_unsparse_data.unhandle_buf, m_unsparse_data.unhandle_buf_size);
  100. memcpy( ((uint8*)&m_unsparse_data.chunk_hdr) + m_unsparse_data.unhandle_buf_size, buf, sizeOfUsedBuf);
  101. size -= sizeOfUsedBuf;
  102. buf+= sizeOfUsedBuf;
  103. m_unsparse_data.unhandle_buf_size = 0;
  104. }
  105. else
  106. {
  107. memcpy(&m_unsparse_data.chunk_hdr, buf, m_unsparse_data.sparse_hdr.chunk_hdr_sz);
  108. size -= m_unsparse_data.sparse_hdr.chunk_hdr_sz;
  109. buf+= m_unsparse_data.sparse_hdr.chunk_hdr_sz;
  110. }
  111. m_unsparse_data.chunk_remain_data_size = (uint64)m_unsparse_data.chunk_hdr.chunk_sz*m_unsparse_data.sparse_hdr.blk_sz;
  112. LOGDBG(" INFO: chunk size:[0x%llx]\n", m_unsparse_data.chunk_remain_data_size);
  113. switch (m_unsparse_data.chunk_hdr.chunk_type)
  114. {
  115. case CHUNK_TYPE_RAW:
  116. {
  117. LOGDBG(" RAW\n");
  118. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_DATA, size, buf);
  119. break;
  120. }
  121. case CHUNK_TYPE_DONT_CARE:
  122. {
  123. LOGDBG(" DONT_CARE\n");
  124. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_NOT_CARE, size, buf);
  125. break;
  126. }
  127. case CHUNK_TYPE_FILL:
  128. {
  129. LOGDBG(" FILL\n");
  130. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_FILL, size, buf);
  131. break;
  132. }
  133. case CHUNK_TYPE_CRC:
  134. {
  135. LOGDBG(" CRC\n");
  136. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_CRC, size, buf);
  137. break;
  138. }
  139. default:
  140. LOGI("@: CHUNK_TYPE_UNKNOWN: 0x%x\n", m_unsparse_data.chunk_hdr.chunk_type);
  141. status->handle_status = STATUS_UNKNOWN_SPARSE_CHUNK_TYPE;
  142. return;
  143. }
  144. }
  145. else
  146. {
  147. LOGDBG(" HEADER SPLIT\n");
  148. // LOGI("????: CHUNK_HEADER splitted.\n");
  149. m_unsparse_data.unhandle_buf_size = size;
  150. memcpy(m_unsparse_data.unhandle_buf, buf, size);
  151. size = 0; // force to jump out while loop
  152. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  153. }
  154. LOGDBG("- CHUNK_HEADER\n");
  155. break;
  156. }
  157. case UNSPARSE_WAIT_CHUNK_FILL:
  158. {
  159. LOGDBG("+ CHUNK_FILL\n");
  160. filled_seed = *(int*)buf;
  161. buf += sizeof(uint32);
  162. size -= sizeof(uint32);
  163. while(m_unsparse_data.chunk_remain_data_size != 0)
  164. {
  165. uint32 slot_len = status->ctx.c_size - status->ctx.c_offset;
  166. if(m_unsparse_data.chunk_remain_data_size >= slot_len)
  167. {
  168. //cache is full, so write it.
  169. memsetint(status->ctx.c_base + status->ctx.c_offset, filled_seed, slot_len);
  170. if (nand_write_img((u64)(status->partition->base_addr+m_unsparse_data.image_address_offset), (char*)status->ctx.c_base, status->ctx.c_size
  171. ,(u64)status->partition->max_size, get_nand_image_type(status->partition->name)))
  172. {
  173. status->handle_status = STATUS_NAND_ERR;
  174. }
  175. if (status->handle_status != STATUS_OK)
  176. {
  177. LOGDBG("[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d, size=%d\n",__LINE__, status->handle_status, status->byte_to_process);
  178. return;
  179. }
  180. status->ctx.c_offset = 0;// reset cache.
  181. m_unsparse_data.chunk_remain_data_size -= slot_len;
  182. m_unsparse_data.image_address_offset += status->ctx.c_size;
  183. }
  184. else
  185. {
  186. //fill the space with 0xFF.
  187. memsetint(status->ctx.c_base + status->ctx.c_offset, filled_seed, m_unsparse_data.chunk_remain_data_size);
  188. status->ctx.c_offset += m_unsparse_data.chunk_remain_data_size;
  189. m_unsparse_data.chunk_remain_data_size = 0;
  190. }
  191. }
  192. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  193. LOGDBG("- CHUNK_FILL\n");
  194. break;
  195. }
  196. case UNSPARSE_WAIT_CHUNK_CRC:
  197. {
  198. LOGDBG("+ CHUNK_CRC\n");
  199. filled_seed = *(uint32*)buf;
  200. buf += sizeof(uint32);
  201. size -= sizeof(uint32);
  202. m_unsparse_data.chunk_remain_data_size = 0;
  203. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  204. LOGDBG("- CHUNK_CRC\n");
  205. break;
  206. }
  207. case UNSPARSE_WAIT_CHUNK_NOT_CARE:
  208. {
  209. LOGDBG("+ CHUNK_NOT_CARE\n");
  210. LOGDBG(" INFO: chunk remain size:[0x%llx]\n", m_unsparse_data.chunk_remain_data_size);
  211. while(m_unsparse_data.chunk_remain_data_size != 0)
  212. {
  213. uint32 slot_len = status->ctx.c_size - status->ctx.c_offset;
  214. LOGDBG(" INFO: slot len:[0x%x]\n", slot_len);
  215. if(m_unsparse_data.chunk_remain_data_size >= slot_len)
  216. {
  217. //cache is full, so write it.
  218. if(status->ctx.c_offset != 0)
  219. {
  220. LOGDBG(" Write at offset:[0x%llx]\n", m_unsparse_data.image_address_offset);
  221. memset(status->ctx.c_base + status->ctx.c_offset, 0xFF, slot_len);
  222. if (nand_write_img((u64)(status->partition->base_addr+m_unsparse_data.image_address_offset), (char*)status->ctx.c_base, status->ctx.c_size
  223. ,(u64)status->partition->max_size, get_nand_image_type(status->partition->name)))
  224. {
  225. status->handle_status = STATUS_NAND_ERR;
  226. }
  227. if (status->handle_status != STATUS_OK)
  228. {
  229. pal_log_err("[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d, size=%d\n",__LINE__, status->handle_status, status->byte_to_process);
  230. return;
  231. }
  232. }
  233. else
  234. {
  235. //cache is empty, do nothing to prevent from writing void data.
  236. }
  237. status->ctx.c_offset = 0;// reset cache.
  238. m_unsparse_data.chunk_remain_data_size -= slot_len;
  239. m_unsparse_data.image_address_offset += status->ctx.c_size;
  240. }
  241. else
  242. {
  243. //fill the space with 0xFF.
  244. LOGDBG(" Set 0xff:[0x%llx]\n", m_unsparse_data.chunk_remain_data_size);
  245. memset(status->ctx.c_base + status->ctx.c_offset, 0xFF, m_unsparse_data.chunk_remain_data_size);
  246. status->ctx.c_offset += m_unsparse_data.chunk_remain_data_size;
  247. m_unsparse_data.chunk_remain_data_size = 0;
  248. }
  249. }
  250. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  251. LOGDBG("- CHUNK_NOT_CARE\n");
  252. break;
  253. }
  254. case UNSPARSE_WAIT_CHUNK_DATA:
  255. {
  256. LOGDBG("+ CHUNK_DATA\n");
  257. uint64 this_process_len = 0;
  258. if(size >= m_unsparse_data.chunk_remain_data_size)
  259. {
  260. this_process_len = m_unsparse_data.chunk_remain_data_size;
  261. }
  262. else
  263. {
  264. this_process_len = size;
  265. }
  266. uint32 slot_len = status->ctx.c_size - status->ctx.c_offset;
  267. LOGDBG(" data left [0x%x], slot[0x%x], chunk remain [0x%llx]\n", size, slot_len, m_unsparse_data.chunk_remain_data_size);
  268. if(slot_len <= this_process_len)
  269. {
  270. LOGDBG(" Write at [0x%llx]\n", m_unsparse_data.image_address_offset);
  271. //cache is full.
  272. memcpy(status->ctx.c_base + status->ctx.c_offset, buf, slot_len);
  273. if (nand_write_img((u64)(status->partition->base_addr+m_unsparse_data.image_address_offset), (char*)status->ctx.c_base, status->ctx.c_size
  274. ,(u64)status->partition->max_size,get_nand_image_type(status->partition->name)))
  275. {
  276. status->handle_status = STATUS_NAND_ERR;
  277. }
  278. if (status->handle_status != STATUS_OK)
  279. {
  280. LOGDBG("[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d, size=%d\n",__LINE__, status->handle_status, status->byte_to_process);
  281. return;
  282. }
  283. buf += slot_len;
  284. size -= slot_len;
  285. m_unsparse_data.image_address_offset += status->ctx.c_size;
  286. m_unsparse_data.chunk_remain_data_size -= slot_len;
  287. status->ctx.c_offset = 0;// reset cache.
  288. }
  289. else
  290. {
  291. LOGDBG(" copy to slot[0x%x] OF data[0x%x]\n",slot_len, this_process_len);
  292. //cache is not full.
  293. memcpy(status->ctx.c_base + status->ctx.c_offset, buf, this_process_len);
  294. status->ctx.c_offset += this_process_len;
  295. buf += this_process_len;
  296. size -= this_process_len;
  297. m_unsparse_data.chunk_remain_data_size -= this_process_len;
  298. LOGDBG(" copy to slot end\n");
  299. }
  300. if(m_unsparse_data.chunk_remain_data_size == 0)
  301. {
  302. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  303. }
  304. else
  305. {
  306. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_DATA, size, buf);
  307. }
  308. LOGDBG("- CHUNK_DATA\n");
  309. break;
  310. }
  311. default:
  312. pal_log_info("sparse image do nothing.\n");
  313. break;
  314. }
  315. LOGDBG("---------------------------------\n");
  316. return ;
  317. }
  318. void write_sparse_data(unsparse_status_t* status, uint8* data, uint32 length)
  319. {
  320. status->buf = data;
  321. status->byte_to_process = length;
  322. do
  323. {
  324. write_sparse_data_internal(status);
  325. if (status->handle_status != STATUS_OK)
  326. {
  327. return;
  328. }
  329. } while (status->byte_to_process > 0);
  330. return;
  331. }
  332. inline bool is_sparse_image(uint8* data, uint32 length)
  333. {
  334. sparse_header_t *sparse_header = (sparse_header_t *) data;
  335. return (sparse_header->magic == SPARSE_HEADER_MAGIC) ;
  336. }
  337. inline uint64 unspared_size(uint8* data)
  338. {
  339. uint64 size = 0;
  340. sparse_header_t *sparse_header = (sparse_header_t *) data;
  341. size = sparse_header->blk_sz * sparse_header->total_blks;
  342. return size;
  343. }
  344. inline bool support_sparse_image(void)
  345. {
  346. return true;
  347. }
  348. #endif