transfer_parallel.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include <stdlib.h>
  2. #include <app.h>
  3. #include <debug.h>
  4. #include <arch/arm.h>
  5. #include <dev/udc.h>
  6. #include <string.h>
  7. #include <kernel/thread.h>
  8. #include <kernel/event.h>
  9. #include <arch/ops.h>
  10. #include <target.h>
  11. #include <platform.h>
  12. #include <platform/mt_gpt.h>
  13. #include "dl_commands.h"
  14. #include "sparse_format.h"
  15. #include "transfer.h"
  16. #include "sparse_state_machine.h"
  17. #include "bulk_process.h"
  18. #if defined MTK_ULTRA_FLASH
  19. #define TIME_STAMP gpt4_tick2time_ms(gpt4_get_current_tick())
  20. #define CACHE_PADDING_SIZE STORAGE_BLOCK_SIZE
  21. #define SYSOB_CACHE_PAGE 2*1024*1024U
  22. #define SYSOB_BIG_CACHE 2*1024*1024U
  23. #define SIGNAL_RESCHEDULE 0 //true; active. 0 passive.
  24. /***********************************************************************************
  25. * DOWNLOAD ENGINE
  26. ***********************************************************************************/
  27. typedef enum engine_op_part
  28. {
  29. EOP_DATA_PROVIDER,
  30. EOP_DATA_CONSUMER,
  31. }engine_part_e;
  32. typedef struct cache
  33. {
  34. uint8* padding_buf;
  35. uint8* cache_buf;
  36. uint32 padding_length; //sparse image boundary problem.
  37. uint32 content_length; //if this is 0, indicate this the last package.
  38. event_t content_available;
  39. event_t cache_available;
  40. }cache_t;
  41. typedef struct engine_context
  42. {
  43. uint8* cache_base;
  44. cache_t dual_cache[2];
  45. uint32 flipIdxR; //receive buffer shift
  46. uint32 flipIdxW; //write buffer shift
  47. event_t thrR_end_ev; // recieve thread exit sync.
  48. event_t thrW_end_ev; // write thread exit sync.
  49. status_t status_usb ; // if something is wrong, should exit.
  50. status_t status_storage ; // if something is wrong, should exit.
  51. }engine_context_t;
  52. static engine_context_t* ctx;
  53. #define ALIGN_SZ (64)
  54. #define MM_BASE get_available_ram_base()
  55. #define MM_1ST_16M (((uint8*)get_available_ram_base())+3*SYSOB_BIG_CACHE)
  56. extern uint8* get_global_cache1()
  57. {
  58. return MM_1ST_16M;
  59. }
  60. void init_engine_context(engine_context_t* tx)
  61. {
  62. /*dual cache pattern: | PADDING1 | CACHE1 || PADDING2 | CACHE2 |*/
  63. uint32 CACHE_PAGE_SIZE = SYSOB_CACHE_PAGE;
  64. //uint32 DCACHE_SIZE = (2*CACHE_PAGE_SIZE+2*CACHE_PADDING_SIZE);
  65. tx->cache_base = (uint8*)get_available_ram_base();
  66. tx->dual_cache[0].padding_buf = tx->cache_base;
  67. tx->dual_cache[0].cache_buf = tx->cache_base+CACHE_PADDING_SIZE;
  68. tx->dual_cache[1].padding_buf = tx->cache_base+CACHE_PADDING_SIZE+CACHE_PAGE_SIZE;
  69. tx->dual_cache[1].cache_buf = tx->cache_base+CACHE_PADDING_SIZE+CACHE_PAGE_SIZE+CACHE_PADDING_SIZE;
  70. tx->dual_cache[0].padding_length = tx->dual_cache[1].padding_length = 0;
  71. event_init(&tx->dual_cache[0].content_available, 0, EVENT_FLAG_AUTOUNSIGNAL);//no data in cache
  72. event_init(&tx->dual_cache[1].content_available, 0, EVENT_FLAG_AUTOUNSIGNAL);//no data in cache
  73. event_init(&tx->dual_cache[0].cache_available, 1, EVENT_FLAG_AUTOUNSIGNAL); //can receive from usb
  74. event_init(&tx->dual_cache[1].cache_available, 1, EVENT_FLAG_AUTOUNSIGNAL); //can receive from usb
  75. event_init(&tx->thrR_end_ev, 0, EVENT_FLAG_AUTOUNSIGNAL);//do not end.
  76. event_init(&tx->thrW_end_ev, 0, EVENT_FLAG_AUTOUNSIGNAL);//do not end.
  77. tx->status_usb = STATUS_OK;
  78. tx->status_storage = STATUS_OK;
  79. tx->flipIdxR = tx->flipIdxW = 0;
  80. }
  81. inline uint32 cache_shift(uint32 pre)
  82. {
  83. return pre ^ 0x01;
  84. }
  85. void stop_engine(engine_context_t * tx, engine_part_e part)
  86. {
  87. if(part == EOP_DATA_CONSUMER)
  88. {
  89. event_signal(&tx->dual_cache[0].cache_available, SIGNAL_RESCHEDULE);
  90. event_signal(&tx->dual_cache[1].cache_available, SIGNAL_RESCHEDULE);
  91. event_signal(&tx->thrR_end_ev, SIGNAL_RESCHEDULE);
  92. }
  93. else if(part == EOP_DATA_PROVIDER)
  94. {
  95. event_signal(&tx->dual_cache[0].content_available, SIGNAL_RESCHEDULE);
  96. event_signal(&tx->dual_cache[1].content_available, SIGNAL_RESCHEDULE);
  97. event_signal(&tx->thrW_end_ev, SIGNAL_RESCHEDULE);
  98. }
  99. }
  100. void destroy_engine(engine_context_t* tx)
  101. {
  102. event_destroy(&tx->dual_cache[0].cache_available);
  103. event_destroy(&tx->dual_cache[1].cache_available);
  104. event_destroy(&tx->dual_cache[0].content_available);
  105. event_destroy(&tx->dual_cache[1].content_available);
  106. event_destroy(&tx->thrR_end_ev);
  107. event_destroy(&tx->thrW_end_ev);
  108. tx->cache_base = 0;
  109. }
  110. /***********************************************************************************
  111. * DOWNLOAD
  112. ***********************************************************************************/
  113. static download_data_context_t* write_data_ctx = 0;
  114. status_t write_data(uint8* data, uint32 length)
  115. {
  116. int next_flip = 0;
  117. static unsparse_status_t unsparse_status; //sparse image parsing used.
  118. static bulk_status_t bulk_status; //bulk image parsing used.
  119. static bool is_sparse = false;
  120. uint64 total_image_length = 0;//if sparse image, it should be size after unsparsed.
  121. if(data == 0)
  122. {
  123. return STATUS_INVALID_PARAMETERS;
  124. }
  125. if(write_data_ctx->first_run)
  126. {
  127. is_sparse = is_sparse_image(data, length);
  128. total_image_length = write_data_ctx->length_to_write;
  129. if(is_sparse)
  130. {
  131. init_unsparse_status(&(unsparse_status), write_data_ctx->part_info);
  132. total_image_length = unspared_size(data);
  133. }
  134. else
  135. {
  136. init_bulk_process_status(&(bulk_status), write_data_ctx->part_info);
  137. total_image_length = write_data_ctx->length_to_write;
  138. }
  139. if (total_image_length> write_data_ctx->part_info->max_size)
  140. {
  141. LOGE( "size too large, space small. image length[0x%llx], partition max size[0x%llx]\n",
  142. total_image_length, write_data_ctx->part_info->max_size);
  143. return STATUS_TOO_LARGE;
  144. }
  145. //The first run flag will be reset later after erase_before_download finished.
  146. write_data_ctx->first_run = 0;
  147. }
  148. if (is_sparse)
  149. {
  150. next_flip = cache_shift(ctx->flipIdxR);
  151. if(length != 0)
  152. {
  153. write_sparse_data(&unsparse_status, data, length);
  154. if (unsparse_status.handle_status == STATUS_SPARSE_INCOMPLETE)
  155. {
  156. memcpy(ctx->dual_cache[next_flip].padding_buf +(CACHE_PADDING_SIZE-unsparse_status.byte_to_process)
  157. , unsparse_status.buf
  158. , unsparse_status.byte_to_process);
  159. ctx->dual_cache[next_flip].padding_length = unsparse_status.byte_to_process;
  160. unsparse_status.handle_status = STATUS_OK;
  161. }
  162. else if (unsparse_status.handle_status== STATUS_OK)
  163. {
  164. ctx->dual_cache[next_flip].padding_length = 0;
  165. }
  166. }
  167. else
  168. {
  169. //the last package.
  170. end_write_sparse_data(&unsparse_status);
  171. }
  172. }
  173. else
  174. {
  175. if (length != 0)
  176. {
  177. write_bulk_data(&bulk_status, data, length);
  178. }
  179. else
  180. {//the last package.
  181. end_write_bulk(&bulk_status);
  182. }
  183. }
  184. return unsparse_status.handle_status;
  185. }
  186. int write_storage_proc(void *arg)
  187. {
  188. uint8* data = 0;
  189. uint32 data_len = 0;
  190. //LOGI("\nin write_storage_proc\n");
  191. for (;;)
  192. {
  193. event_wait(&(ctx->dual_cache[ctx->flipIdxR].content_available));
  194. if(FAIL(ctx->status_usb))
  195. {
  196. goto exit;
  197. }
  198. //if has something to write
  199. data = (uint8*)(ctx->dual_cache[ctx->flipIdxR].cache_buf);
  200. data_len = ctx->dual_cache[ctx->flipIdxR].content_length;
  201. data -= ctx->dual_cache[ctx->flipIdxR].padding_length;
  202. data_len += ctx->dual_cache[ctx->flipIdxR].padding_length;
  203. ctx->status_storage = write_data(data, data_len);
  204. if(ctx->status_storage != STATUS_OK)
  205. {
  206. //error
  207. LOGE("write data failed. handle_status(%d)\n", ctx->status_storage);
  208. goto exit;
  209. }
  210. //last package, should return;
  211. if (ctx->dual_cache[ctx->flipIdxR].content_length == 0)
  212. {
  213. break;
  214. }
  215. event_signal(&ctx->dual_cache[ctx->flipIdxR].cache_available, SIGNAL_RESCHEDULE); //make this cache writeable again.
  216. ctx->flipIdxR = cache_shift(ctx->flipIdxR); //change next buffer.
  217. }
  218. exit:
  219. stop_engine(ctx, EOP_DATA_CONSUMER);
  220. thread_exit(0);
  221. //never arrive here.
  222. return 0;
  223. }
  224. extern int usb_read(void *_buf, unsigned len);
  225. void read_usb_proc(uint64 data_length)
  226. {
  227. uint64 bytes_already_read = 0;
  228. uint64 bytes_to_read = 0;
  229. uint32 CACHE_PAGE_SIZE = SYSOB_CACHE_PAGE;
  230. uint32 TOTAL_CACHE_PAGE_SIZE = SYSOB_BIG_CACHE;
  231. while (bytes_already_read < data_length)
  232. {
  233. event_wait(&(ctx->dual_cache[ctx->flipIdxW].cache_available));
  234. ctx->dual_cache[ctx->flipIdxW].content_length = 0;
  235. uint32 cache_offset = 0;
  236. while((cache_offset < TOTAL_CACHE_PAGE_SIZE) && (bytes_already_read < data_length))
  237. {
  238. bytes_to_read = data_length - bytes_already_read;
  239. bytes_to_read = bytes_to_read >= CACHE_PAGE_SIZE ? CACHE_PAGE_SIZE : bytes_to_read;
  240. //LOGI("$$ Read usb length 0x%llx, buf addr at 0x%x\n", bytes_to_read, ctx->dual_cache[ctx->flipIdxW].cache_buf+cache_offset);
  241. int r = usb_read(ctx->dual_cache[ctx->flipIdxW].cache_buf+cache_offset, (unsigned int)bytes_to_read);
  242. if ((r < 0) || ((unsigned int) r != (unsigned int)bytes_to_read))
  243. {
  244. ctx->status_usb = STATUS_USB_ERR;
  245. LOGE("Read usb error. code 0x%x\n", ctx->status_usb);
  246. goto exit;
  247. }
  248. ctx->dual_cache[ctx->flipIdxW].content_length += bytes_to_read;
  249. bytes_already_read += bytes_to_read;
  250. cache_offset += bytes_to_read;
  251. if(FAIL(ctx->status_usb) || FAIL(ctx->status_storage))
  252. {
  253. // storage write error.
  254. goto exit;
  255. }
  256. display_progress("\rFlash: ", bytes_already_read, write_data_ctx->length_to_write);
  257. }
  258. event_signal(&ctx->dual_cache[ctx->flipIdxW].content_available, SIGNAL_RESCHEDULE);
  259. ctx->flipIdxW = cache_shift(ctx->flipIdxW); //change next buffer.
  260. }
  261. //last package.
  262. //must wait for this can write again. wait for storage write finish.
  263. event_wait(&(ctx->dual_cache[ctx->flipIdxW].cache_available));
  264. //notify finish info to storage write thread with zero length packet.
  265. ctx->dual_cache[ctx->flipIdxW].content_length = 0;
  266. event_signal(&ctx->dual_cache[ctx->flipIdxW].content_available, SIGNAL_RESCHEDULE);
  267. exit:
  268. stop_engine(ctx, EOP_DATA_PROVIDER);
  269. return;
  270. }
  271. status_t download_data(uint64 data_length, partition_info_struct_t* part_info)//Big image and parallel transfer.
  272. {
  273. thread_t *thr;
  274. download_data_context_t data_ctx;
  275. engine_context_t engine_ctx;
  276. #ifdef DUMP_SPEED
  277. uint32 time_start = 0;
  278. uint32 time_end = 0;
  279. #endif
  280. write_data_ctx = &data_ctx;
  281. ctx = &engine_ctx;
  282. init_engine_context(ctx);
  283. init_download_data_context(write_data_ctx, data_length, part_info);
  284. #ifdef DUMP_SPEED
  285. time_start = TIME_STAMP;
  286. #endif
  287. thr = thread_create("write_storage_proc", write_storage_proc, 0, HIGHEST_PRIORITY, 16*1024);
  288. if (!thr)
  289. {
  290. LOGE("create write_storage_proc thread failed.");
  291. return STATUS_THREAD;
  292. }
  293. thread_resume(thr);
  294. read_usb_proc(data_length);
  295. //wait for thread end.
  296. event_wait(&ctx->thrR_end_ev);
  297. event_wait(&ctx->thrW_end_ev);
  298. #ifdef DUMP_SPEED
  299. time_end = TIME_STAMP;
  300. #endif
  301. destroy_engine(ctx);
  302. LOGI("Process download_data Finish.\n");
  303. return FAIL(ctx->status_storage) ? ctx->status_storage : ctx->status_usb;
  304. }
  305. #endif