sparse_state_machine.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #if (defined(MTK_UFS_SUPPORT) || defined(MTK_EMMC_SUPPORT))
  2. #include <debug.h>
  3. #include "sparse_format.h"
  4. #include "sparse_state_machine.h"
  5. #include "pal_log.h"
  6. typedef unsigned int u32;
  7. typedef unsigned long long u64;
  8. extern u64 emmc_write(u32 part_id, u64 offset, void *data, u64 size);
  9. extern void * memset(void *s, int c, size_t count);
  10. extern void *memcpy(void *dest, const void *src, size_t count);
  11. //only engine data structure.
  12. static unsparse_data_t m_unsparse_data;
  13. static void write_sparse_data_internal(unsparse_status_t* status);
  14. static void set_unsparse_status( unsparse_status_t* status,
  15. status_t handle_status,
  16. unsparse_phase_t wait_phase,
  17. uint32 size,
  18. uint8 *buf )
  19. {
  20. status->handle_status = handle_status;
  21. status->wait_phase = wait_phase;
  22. status->byte_to_process = size;
  23. status->buf = buf;
  24. }
  25. void init_unsparse_status(unsparse_status_t* status, partition_info_struct_t* partition)
  26. {
  27. memset(status, 0, sizeof(unsparse_status_t));
  28. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_SPARSE_HEADER, 0, 0);
  29. status->partition = partition;
  30. }
  31. void end_write_sparse_data(unsparse_status_t* status)
  32. {
  33. //for the last package
  34. }
  35. static void memsetint(void* p, int i, int len)
  36. {
  37. int idx=0;
  38. int count = len>>2;
  39. int* buf = (int*)p;
  40. while(idx < count)
  41. {
  42. buf[idx++] = i;
  43. }
  44. }
  45. inline uint64 emmc_write_wp(uint32 part_id, uint64 offset, void *data, uint64 size)
  46. {
  47. return emmc_write(part_id, offset, data, size);
  48. }
  49. static void write_sparse_data_internal(unsparse_status_t* status)
  50. {
  51. uint32 size = status->byte_to_process;
  52. uint8 *buf = status->buf;
  53. uint32 sizeOfX=0;
  54. int filled_seed = 0;
  55. uint8* filled_data_cache = 0;
  56. uint32 filled_data_len= 0 ;
  57. if (size==0)
  58. {
  59. return ;
  60. }
  61. switch (status->wait_phase)
  62. {
  63. case UNSPARSE_WAIT_SPARSE_HEADER:
  64. {
  65. if (size >=sizeof (sparse_header_t))
  66. {
  67. memset((void*)&m_unsparse_data, 0x00, sizeof(unsparse_data_t));
  68. memcpy((void*)&m_unsparse_data.sparse_hdr, buf, sizeof (sparse_header_t));
  69. // for real sparse header larger than sparse_header_t struct
  70. // for titan ext4_sparse_header_8byte_align: sparse_header_t 8byte align, chunk_header_t 8byte align
  71. size -= m_unsparse_data.sparse_hdr.file_hdr_sz;
  72. buf+= m_unsparse_data.sparse_hdr.file_hdr_sz;
  73. m_unsparse_data.unhandle_buf_size = 0;
  74. m_unsparse_data.chunks_processed = 0;
  75. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  76. }
  77. break;
  78. }
  79. case UNSPARSE_WAIT_CHUNK_HEADER:
  80. {
  81. if(m_unsparse_data.chunks_processed >= m_unsparse_data.sparse_hdr.total_chunks)
  82. {
  83. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, 0, buf);
  84. return;
  85. }
  86. if (m_unsparse_data.unhandle_buf_size + size >=( m_unsparse_data.sparse_hdr.chunk_hdr_sz))
  87. {
  88. if (m_unsparse_data.unhandle_buf_size > 0) {
  89. uint32 sizeOfUsedBuf = m_unsparse_data.sparse_hdr.chunk_hdr_sz - m_unsparse_data.unhandle_buf_size;
  90. memcpy(&m_unsparse_data.chunk_hdr, m_unsparse_data.unhandle_buf, m_unsparse_data.unhandle_buf_size);
  91. // for real sparse header larger than sparse_header_t struct
  92. if((m_unsparse_data.sparse_hdr.chunk_hdr_sz>sizeof(chunk_header_t)))
  93. {
  94. memcpy( ((uint8*)&m_unsparse_data.chunk_hdr) + m_unsparse_data.unhandle_buf_size, buf, sizeOfUsedBuf-(m_unsparse_data.sparse_hdr.chunk_hdr_sz-sizeof(chunk_header_t)));
  95. }else{
  96. memcpy( ((uint8*)&m_unsparse_data.chunk_hdr) + m_unsparse_data.unhandle_buf_size, buf, sizeOfUsedBuf);
  97. }
  98. size -= sizeOfUsedBuf;
  99. buf+= sizeOfUsedBuf;
  100. m_unsparse_data.unhandle_buf_size = 0;
  101. }
  102. else
  103. {
  104. // for real sparse header larger than sparse_header_t struct
  105. memcpy(&m_unsparse_data.chunk_hdr, buf, sizeof(chunk_header_t));
  106. size -= m_unsparse_data.sparse_hdr.chunk_hdr_sz;
  107. buf+= m_unsparse_data.sparse_hdr.chunk_hdr_sz;
  108. }
  109. m_unsparse_data.chunk_remain_data_size = (uint64)m_unsparse_data.chunk_hdr.chunk_sz*m_unsparse_data.sparse_hdr.blk_sz;
  110. switch (m_unsparse_data.chunk_hdr.chunk_type)
  111. {
  112. case CHUNK_TYPE_RAW:
  113. {
  114. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_DATA, size, buf);
  115. break;
  116. }
  117. case CHUNK_TYPE_DONT_CARE:
  118. {
  119. m_unsparse_data.image_address_offset+=m_unsparse_data.chunk_remain_data_size;
  120. m_unsparse_data.chunk_remain_data_size = 0;
  121. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  122. break;
  123. }
  124. case CHUNK_TYPE_FILL:
  125. {
  126. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_FILL, size, buf);
  127. break;
  128. }
  129. case CHUNK_TYPE_CRC:
  130. {
  131. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_CRC, size, buf);
  132. break;
  133. }
  134. default:
  135. pal_log_err("@: CHUNK_TYPE_UNKNOWN: 0x%x\n", m_unsparse_data.chunk_hdr.chunk_type);
  136. status->handle_status = STATUS_UNKNOWN_SPARSE_CHUNK_TYPE;
  137. return;
  138. }
  139. ++m_unsparse_data.chunks_processed;
  140. }
  141. else
  142. {
  143. m_unsparse_data.unhandle_buf_size = size;
  144. memcpy(m_unsparse_data.unhandle_buf, buf, size);
  145. size = 0; // force to jump out while loop
  146. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  147. }
  148. break;
  149. }
  150. case UNSPARSE_WAIT_CHUNK_FILL:
  151. {
  152. filled_seed = *(int*)buf;
  153. buf += sizeof(uint32);
  154. size -= sizeof(uint32);
  155. #define FILLED_DATA_CACHE_SIZE 2*1024*1024
  156. filled_data_cache = (uint8*)get_global_cache1();;
  157. memsetint(filled_data_cache, filled_seed, FILLED_DATA_CACHE_SIZE);
  158. while(true)
  159. {
  160. filled_data_len = (m_unsparse_data.chunk_remain_data_size > FILLED_DATA_CACHE_SIZE) ?
  161. FILLED_DATA_CACHE_SIZE : m_unsparse_data.chunk_remain_data_size;
  162. if(filled_data_len == 0)
  163. {
  164. break;
  165. }
  166. if (emmc_write_wp(status->partition->part_id, status->partition->base_addr+m_unsparse_data.image_address_offset , filled_data_cache, filled_data_len) != filled_data_len)
  167. {
  168. status->handle_status = STATUS_EMMC_ERR;
  169. }
  170. //status->handle_status = storage_interface.write(status->image_base_addr+m_unsparse_data.image_address_offset, filled_data_cache, kk, status->arg);
  171. if (status->handle_status != STATUS_OK)
  172. {
  173. pal_log_err("[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d, size=%d\n",__LINE__, status->handle_status, status->byte_to_process);
  174. return;
  175. }
  176. m_unsparse_data.image_address_offset += filled_data_len;
  177. m_unsparse_data.chunk_remain_data_size -= filled_data_len;
  178. }
  179. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  180. break;
  181. }
  182. case UNSPARSE_WAIT_CHUNK_CRC:
  183. {
  184. filled_seed = *(uint32*)buf;
  185. buf += sizeof(uint32);
  186. size -= sizeof(uint32);
  187. m_unsparse_data.chunk_remain_data_size = 0;
  188. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  189. break;
  190. }
  191. case UNSPARSE_WAIT_CHUNK_DATA:
  192. {
  193. if (size >= m_unsparse_data.chunk_remain_data_size)
  194. {
  195. if (emmc_write_wp(status->partition->part_id, status->partition->base_addr+m_unsparse_data.image_address_offset , buf, m_unsparse_data.chunk_remain_data_size) != m_unsparse_data.chunk_remain_data_size)
  196. {
  197. status->handle_status = STATUS_EMMC_ERR;
  198. }
  199. //status->handle_status = storage_interface.write(status->image_base_addr+m_unsparse_data.image_address_offset, buf, m_unsparse_data.chunk_remain_data_size, status->arg);
  200. if (status->handle_status != STATUS_OK)
  201. {
  202. pal_log_err("[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d, size=%d\n",__LINE__, status->handle_status, status->byte_to_process);
  203. return;
  204. }
  205. buf += m_unsparse_data.chunk_remain_data_size;
  206. size -= m_unsparse_data.chunk_remain_data_size;
  207. m_unsparse_data.image_address_offset += m_unsparse_data.chunk_remain_data_size;
  208. m_unsparse_data.chunk_remain_data_size = 0;
  209. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_HEADER, size, buf);
  210. }
  211. else
  212. { //big trunk, so it need more than 1 package.
  213. sizeOfX = size;
  214. if(size & (STORAGE_BLOCK_SIZE-1)) //not 512 aligned.
  215. {
  216. if(size < STORAGE_BLOCK_SIZE) //last fragment in a package. this package must have successive package that contain the identical trunk.
  217. {
  218. set_unsparse_status(status, STATUS_SPARSE_INCOMPLETE, UNSPARSE_WAIT_CHUNK_DATA, size, buf);
  219. break;
  220. }
  221. else
  222. {
  223. size &= ~(STORAGE_BLOCK_SIZE-1);
  224. }
  225. }
  226. if (emmc_write_wp(status->partition->part_id, status->partition->base_addr+m_unsparse_data.image_address_offset , buf, size) != size)
  227. {
  228. status->handle_status = STATUS_EMMC_ERR;
  229. }
  230. // status->handle_status = storage_interface.write(status->image_base_addr+m_unsparse_data.image_address_offset, buf, size, status->arg);
  231. if (status->handle_status != STATUS_OK)
  232. {
  233. pal_log_err( "[UNSPARSE] S_STORAGE_WRITE_FAILED:%d, status=%d\n",__LINE__, status->handle_status);
  234. return;
  235. }
  236. m_unsparse_data.image_address_offset += size;
  237. m_unsparse_data.chunk_remain_data_size -= size;
  238. buf += size;
  239. size = sizeOfX & (STORAGE_BLOCK_SIZE-1); // size = 0 org
  240. set_unsparse_status(status, STATUS_OK, UNSPARSE_WAIT_CHUNK_DATA, size, buf);
  241. }
  242. break;
  243. }
  244. default:
  245. pal_log_info("sparse do nothing.\n");
  246. break;
  247. }
  248. return ;
  249. }
  250. void write_sparse_data(unsparse_status_t* status, uint8* data, uint32 length)
  251. {
  252. status->buf = data;
  253. status->byte_to_process = length;
  254. do
  255. {
  256. write_sparse_data_internal(status);
  257. if (status->handle_status != STATUS_OK)
  258. {
  259. return;
  260. }
  261. } while (status->byte_to_process > 0);
  262. return;
  263. }
  264. inline bool is_sparse_image(uint8* data, uint32 length)
  265. {
  266. sparse_header_t *sparse_header = (sparse_header_t *) data;
  267. return (sparse_header->magic == SPARSE_HEADER_MAGIC) ;
  268. }
  269. inline uint64 unspared_size(uint8* data)
  270. {
  271. uint64 size = 0;
  272. sparse_header_t *sparse_header = (sparse_header_t *) data;
  273. size = (uint64)sparse_header->blk_sz * sparse_header->total_blks;
  274. return size;
  275. }
  276. inline bool support_sparse_image(void)
  277. {
  278. return true;
  279. }
  280. #endif