mt_vpu.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <stdlib.h>
  32. #include <platform/errno.h>
  33. #include <debug.h>
  34. #include <platform/boot_mode.h>
  35. #include <platform/partition.h>
  36. #include <libfdt.h>
  37. #include <fdt_op.h>
  38. #include <arch/ops.h>
  39. /*The buffer layout in DDR is as follows:
  40. * The total is 45MBs.
  41. * [phyaddr offset] [mapping mva]
  42. * 0x00000000 +-----------------------+
  43. * | Reset vector of core0 |
  44. * | code |
  45. * 0x00100000 +-----------------------+
  46. * | Main Program of core0 |
  47. * | |
  48. * 0x00400000 +-----------------------+
  49. * | Reset vector of core1 |
  50. * | code |
  51. * 0x00500000 +-----------------------+
  52. * | Main Program of core1 |
  53. * | |
  54. * 0x00800000 +-----------------------+
  55. * | Reset vector of core2 |
  56. * | code |
  57. * 0x00900000 +-----------------------+
  58. * | Main Program of core2 |
  59. * | |
  60. * 0x00C00000 +-----------------------+
  61. * | Algo Area |
  62. * | |
  63. * 0x02950000 +-----------------------+
  64. * | Main Prog. IRAM of core0|
  65. * | binary data |
  66. * 0x02980000 +-----------------------+
  67. * | Main Prog. IRAM of core1|
  68. * | binary data |
  69. * 0x029B0000 +-----------------------+
  70. * | Main Prog. IRAM of core2|
  71. * | binary data |
  72. * 0x029E0000 +-----------------------+
  73. * | Merged image header |
  74. * | |
  75. * +-----------------------+
  76. *
  77. *
  78. * the layout of Main Prog. IRAM
  79. * +-----------------------+
  80. * | num | off0| dst0|size0|
  81. * | off1| dst1|size1| off2|
  82. * | dst2|size2| ... | |
  83. * ...
  84. * | seg0_data |
  85. * | seg0_data |
  86. * | seg1_data |
  87. * ...
  88. * +-----------------------+
  89. * num: number of segment for IRAM program
  90. * off: bin data offset from start of Main Prog. IRAM
  91. * dst: the dst address of bin data at IRAM
  92. * size: size of bin data
  93. * seg_data: bin data
  94. */
  95. extern int mboot_common_load_part(char *part_name, char *img_name, unsigned long addr);
  96. extern void mtk_wdt_restart(void);
  97. #define MODULE_NAME "LK_BOOT_VPU"
  98. #define VPU_DRAM_ADDR_ALIGN (0x00010000)
  99. #define VPU_DRAM_ADDR_MAX (0xC0000000)
  100. #define VPU_DRAM_SIZE (0x02A10000) // total ddr size we apply for vpu
  101. #define VPU_DRAM_PROG_OFFSET (0x00100000) // start address of main program (core0)
  102. #define VPU_DRAM_ALGO_OFFSET (0x00C00000) // start address of algo, after 3*(reset vector+main program)
  103. #define VPU_DRAM_IRAM_OFFSET (VPU_DRAM_SIZE - 0xC0000) // start address of main program IRAM binary data (core0)
  104. #define VPU_DRAM_HEADER_OFFSET (VPU_DRAM_SIZE - 0x30000) // start address of header
  105. #define VPU_CORE_RESVEC_SHIFT (0x00400000) //1MB reset vector + 3 MB main program data
  106. #define VPU_CORE_IRAM_SHIFT (0x0030000) //max 192k for each iram region
  107. #define VPU_MAX_PART_SIZE (0x00F00000)
  108. #define VPU_ADDR_MASK (0xFFF00000)
  109. #define VPU_ALIGN_MASK (0x0000000F) // 16 bytes alignment for algo bin and iram prog so that vpu core can use DMA to copy
  110. static char *vpu_part_name[] = {"cam_vpu1", "cam_vpu2", "cam_vpu3"};
  111. static int vpu_part_size[] = {0x000C00000, 0x000F00000, 0x000F00000};
  112. static void *vpu_m4u_base_addr[] = {0x7DA00000, 0x7DB00000, 0x7FF00000}; // m4u address, pre-defined
  113. static void *vpu2_m4u_base_addr[] = {0x7E300000, 0x7E400000, 0x7FF00000}; // m4u address, pre-defined
  114. static void *vpu3_m4u_base_addr[] = {0x7EC00000, 0x7ED00000, 0x7FF00000}; // m4u address, pre-defined
  115. #ifndef MUINT32
  116. #define MUINT32 u32
  117. #endif
  118. /*---------------------------------------------------------------------------*/
  119. /* VPU Image file definition */
  120. /*---------------------------------------------------------------------------*/
  121. #define VPU_PARTITION_FILE_HEADER_VERSION (0x17102311) //chanage core index to bitwise presentation.
  122. #define VPU_CODE_SEGMENT_MAX_NUM (50)
  123. #define VPU_ALG_MAX_NUM (50)
  124. #define VPU_ALG_MAX_NAME_CHAR (32)
  125. #define VPU_HEADER_STR_SIZE (32)
  126. /*---------------------------------------------------------------------------*/
  127. /* VPU Image file emum */
  128. /*---------------------------------------------------------------------------*/
  129. typedef enum _VPU_CORE_ENUM_{
  130. //0x60 stands for VP6
  131. VPU_CORE_0 = ( 0x60 | (0x01 << 0) ), /* bitwise to represent core index */
  132. VPU_CORE_1 = ( 0x60 | (0x01 << 1) ),
  133. VPU_CORE_2 = ( 0x60 | (0x01 << 2) ),
  134. //
  135. VPU_CORE_MAX = 0x03,
  136. }VPU_CORE_ENUM;
  137. /*---------------------------------------------------------------------------*/
  138. /* VPU Image file structure */
  139. /*---------------------------------------------------------------------------*/
  140. typedef struct _VPU_CODE_SEGMENT_INFO_ {
  141. MUINT32 vpu_core; /* core index */
  142. MUINT32 off; /* offset */
  143. MUINT32 pAddr; /* destination */
  144. MUINT32 memsz_byt; /* mem. size byte to occupied */
  145. MUINT32 filesz_byt; /* file size byte to copy */
  146. } VPU_CODE_SEGMENT_INFO;
  147. typedef struct _VPU_ALG_INFO_ {
  148. MUINT32 vpu_core; /* core index */
  149. MUINT32 off; /* offset */
  150. MUINT32 filesz_byt; /* file size byte to copy */
  151. char name[VPU_ALG_MAX_NAME_CHAR ];
  152. } VPU_ALG_INFO;
  153. typedef struct _VPU_IMAGEFILE_HEADER_ {
  154. int version;
  155. int build_date;
  156. int hdr_str[VPU_HEADER_STR_SIZE / 4];
  157. int size_byt_hdr; /* header size */
  158. int size_byt_img; /* binary code size */
  159. //
  160. int segment_num;
  161. VPU_CODE_SEGMENT_INFO segment[VPU_CODE_SEGMENT_MAX_NUM];
  162. //
  163. int alg_num;
  164. VPU_ALG_INFO alg[VPU_ALG_MAX_NUM ];
  165. //reserved
  166. int reserved[VPU_HEADER_STR_SIZE];
  167. } VPU_IMAGEFILE_HEADER;
  168. int mt_load_vpu(void)
  169. {
  170. int i, j, len = 0, ret = 0;
  171. int part_offset = 0;
  172. int read_size = 0;
  173. u32 iram_num = 0;
  174. u32 iram_bin_offset = 0;
  175. u32 vpu_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  176. u32 vpu2_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  177. u32 vpu3_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  178. u32 *pIramNum, *pIram;
  179. void *part = NULL;
  180. VPU_IMAGEFILE_HEADER *part_hdr = NULL;
  181. char *part_name;
  182. int part_size;
  183. u32 dstHdrBase;
  184. u32 dstBase;
  185. u32 dst;
  186. u32 dstAlg;
  187. #ifdef DEVICE_TREE_SUPPORT
  188. u64 value;
  189. u32 size;
  190. int nodeoffset;
  191. #endif
  192. void *kernel_fdt = get_kernel_fdt();
  193. if (kernel_fdt == NULL)
  194. panic("kernel fdt is NULL!\n");
  195. // get physical address
  196. dstBase = (u32)mblock_reserve_ext(&g_boot_arg->mblock_info, VPU_DRAM_SIZE, VPU_DRAM_ADDR_ALIGN, VPU_DRAM_ADDR_MAX, 0, "vpu_binary");
  197. dprintf(INFO, "[%s] phyAddr of Allocation: 0x%x\n", MODULE_NAME, dstBase);
  198. if (!dstBase) {
  199. dprintf(CRITICAL, "[%s] vpu memory allocation failed.\n", MODULE_NAME);
  200. return -ENOMEM;
  201. }
  202. // get header base address
  203. dstHdrBase = dstBase + VPU_DRAM_HEADER_OFFSET;
  204. dprintf(INFO, "[%s] Base PhyAddr of Header: 0x%x\n", MODULE_NAME, dstHdrBase);
  205. // get alg base address
  206. dstAlg = dstBase + VPU_DRAM_ALGO_OFFSET;
  207. dprintf(INFO, "[%s] Base PhyAddr of Alg: 0x%x\n", MODULE_NAME, dstAlg);
  208. if (SCRATCH_SIZE < VPU_MAX_PART_SIZE) {
  209. dprintf(CRITICAL, "[%s] SCRATCH_SIZE(0x%x) < VPU_MAX_PART_SIZE(0x%x) .\n", MODULE_NAME, SCRATCH_SIZE, VPU_MAX_PART_SIZE);
  210. return -ENOMEM;
  211. }
  212. part = (void *)((UINT32) SCRATCH_ADDR + SCRATCH_SIZE - VPU_DRAM_SIZE); // Not to mess with kernel zimage, use tail
  213. #ifdef DEVICE_TREE_SUPPORT
  214. // set phyaddress to device tree
  215. nodeoffset = fdt_node_offset_by_compatible(kernel_fdt, -1, "mediatek,vpu_core0"); // get vpu node offset
  216. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  217. if (nodeoffset < 0) { // node add sub-node to /
  218. int offset;
  219. offset = fdt_path_offset(kernel_fdt, "/");
  220. dprintf(INFO, "[%s] root offset %d\n", MODULE_NAME, offset);
  221. if (offset < 0) {
  222. dprintf(CRITICAL, "[%s] fail to get fdt offset\n", MODULE_NAME);
  223. ret = -EINVAL;
  224. goto exit;
  225. } else {
  226. nodeoffset = fdt_add_subnode(kernel_fdt, offset, "vpu_core0");
  227. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  228. if (nodeoffset < 0) {
  229. ret = -EINVAL;
  230. dprintf(CRITICAL, "[%s] fail to add subnode to fdt\n", MODULE_NAME);
  231. goto exit;
  232. } else {
  233. fdt_setprop_string(kernel_fdt, nodeoffset, "compatible", "mediatek,vpu_core0");
  234. }
  235. }
  236. }
  237. value = cpu_to_fdt32(dstBase);
  238. fdt_setprop(kernel_fdt, nodeoffset, "bin-phy-addr", (char *)&value, sizeof(u32));
  239. size = cpu_to_fdt32(VPU_DRAM_SIZE);
  240. fdt_setprop(kernel_fdt, nodeoffset, "bin-size", (char *)&size, sizeof(u32));
  241. #endif
  242. //initialization
  243. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  244. *pIramNum = 0;
  245. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  246. *pIramNum = 0;
  247. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  248. *pIramNum = 0;
  249. for (i = 0 ; i < (sizeof(vpu_part_name)/sizeof(*vpu_part_name)) ; i++) {
  250. #ifdef MTK_SECURITY_SW_SUPPORT
  251. unsigned int sec_feature_mask = 0;
  252. unsigned int policy_entry_idx = 0;
  253. unsigned int img_auth_required = 0;
  254. unsigned int vpu_vfy_time= 0;
  255. #endif
  256. part_name = vpu_part_name[i];
  257. part_size = vpu_part_size[i];
  258. #ifdef MTK_SECURITY_SW_SUPPORT
  259. policy_entry_idx = get_policy_entry_idx(part_name);
  260. img_auth_required = get_vfy_policy(policy_entry_idx);
  261. if (img_auth_required) {
  262. mtk_wdt_restart();
  263. vpu_vfy_time = get_timer(0);
  264. ret = (int)sec_img_auth_init(part_name, part_name, 0);
  265. if (ret) {
  266. dprintf(CRITICAL, "[%s] fail to verify %s cert (0x%x)\n", MODULE_NAME, part_name, ret);
  267. assert(0);
  268. }
  269. dprintf(CRITICAL, "[SBC] %s cert vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  270. #ifdef MTK_SECURITY_ANTI_ROLLBACK
  271. ret = sec_rollback_check(1);
  272. if (ret) {
  273. dprintf(CRITICAL, "[%s] fail to check %s version (0x%x)\n", MODULE_NAME, part_name, ret);
  274. assert(0);
  275. }
  276. #endif
  277. }
  278. #endif
  279. if ((len = mboot_common_load_part(part_name, part_name, (unsigned long)part)) < 0) {
  280. dprintf(CRITICAL, "[%s] vpu %s partition read error. len = %d\n", MODULE_NAME, part_name, len);
  281. ret = -EINVAL;
  282. goto exit;
  283. }
  284. arch_sync_cache_range(part, len);
  285. dprintf(INFO, "[%s] sync arch_sync_cache_range lens = %d\n", MODULE_NAME, len);
  286. #ifdef MTK_SECURITY_SW_SUPPORT
  287. if (img_auth_required) {
  288. mtk_wdt_restart();
  289. vpu_vfy_time = get_timer(0);
  290. ret = (int)sec_img_auth(part, len);
  291. if (ret) {
  292. dprintf(CRITICAL, "[%s] fail to check %s hash (0x%x)\n", MODULE_NAME, part_name, ret);
  293. assert(0);
  294. }
  295. dprintf(CRITICAL, "[SBC] %s vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  296. }
  297. #endif
  298. // 1. read partition header
  299. part_offset = 0;
  300. read_size = sizeof(VPU_IMAGEFILE_HEADER);
  301. part_hdr = (VPU_IMAGEFILE_HEADER *)((u8*)part + part_offset);
  302. dprintf(INFO, "[%s] ============== part_name %s, len 0x%x ================= \n", MODULE_NAME, part_name, read_size);
  303. if (part_hdr->version != VPU_PARTITION_FILE_HEADER_VERSION) {
  304. dprintf(CRITICAL, "[%s] vpu version 0x%x != 0x%x\n", MODULE_NAME, part_hdr->version, VPU_PARTITION_FILE_HEADER_VERSION);
  305. }
  306. if (part_hdr->size_byt_hdr != sizeof(VPU_IMAGEFILE_HEADER)) {
  307. dprintf(CRITICAL, "[%s] vpu header size 0x%x != 0x%x\n", MODULE_NAME, part_hdr->size_byt_hdr, sizeof(VPU_IMAGEFILE_HEADER));
  308. ret = -EINVAL;
  309. goto exit;
  310. }
  311. part_hdr->hdr_str[VPU_HEADER_STR_SIZE/4 -1] = 0;
  312. dprintf(INFO, "[%s] version 0x%x, build_date 0x%x, hdr_str %s, size 0x%x, numOfSeg %d\n",
  313. MODULE_NAME, part_hdr->version, part_hdr->build_date, (char *)part_hdr->hdr_str, part_hdr->size_byt_img, part_hdr->segment_num);
  314. if (part_hdr->size_byt_img > part_size || part_hdr->segment_num > VPU_CODE_SEGMENT_MAX_NUM) {
  315. dprintf(CRITICAL, "[%s] invalid parameter !! part size 0x%x, numOfSeg %d\n", MODULE_NAME, part_hdr->size_byt_img, part_hdr->segment_num);
  316. ret = -EINVAL;
  317. goto exit;
  318. }
  319. // 2. write segment to ddr for each segment from partition
  320. for (j = 0 ; j < part_hdr->segment_num ; j++) {
  321. VPU_CODE_SEGMENT_INFO *seg = &part_hdr->segment[j];
  322. dprintf(INFO, "[%s] Seg[%d] offset 0x%x, size 0x%x, dst 0x%x\n", MODULE_NAME, j, seg->off, seg->filesz_byt, seg->pAddr);
  323. if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[1]) {
  324. dst = dstBase + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[1]);
  325. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase + VPU_DRAM_PROG_OFFSET, (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[1]), dst);
  326. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[1]) {
  327. dst = dstBase + VPU_CORE_RESVEC_SHIFT + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[1]);
  328. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase + VPU_CORE_RESVEC_SHIFT + VPU_DRAM_PROG_OFFSET, (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[1]), dst);
  329. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[1]) {
  330. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[1]);
  331. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + VPU_DRAM_PROG_OFFSET, (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[1]), dst);
  332. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[0]) {
  333. dst = dstBase + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[0]);
  334. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase, (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[0]), dst);
  335. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[0]) {
  336. dst = dstBase + VPU_CORE_RESVEC_SHIFT + (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[0]);
  337. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase + VPU_CORE_RESVEC_SHIFT, (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[0]), dst);
  338. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[0]) {
  339. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[0]);
  340. dprintf(INFO, "[%s] base 0x%x, offset 0x%x, dst 0x%x\n", MODULE_NAME, dstBase + (VPU_CORE_RESVEC_SHIFT << 1), (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[0]), dst);
  341. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[2]) {
  342. switch (seg->vpu_core) {
  343. case VPU_CORE_0:
  344. dst = dstBase + VPU_DRAM_IRAM_OFFSET + vpu_iram_bin_offset;
  345. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  346. iram_bin_offset = vpu_iram_bin_offset;
  347. vpu_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  348. break;
  349. case VPU_CORE_1:
  350. dst = dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT + vpu2_iram_bin_offset;
  351. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  352. iram_bin_offset = vpu2_iram_bin_offset;
  353. vpu2_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  354. break;
  355. case VPU_CORE_2:
  356. dst = dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1) + vpu3_iram_bin_offset;
  357. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  358. iram_bin_offset = vpu3_iram_bin_offset;
  359. vpu3_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  360. break;
  361. default:
  362. dprintf(CRITICAL, "[%s] wrong seg->core info %d\n", MODULE_NAME, seg->vpu_core);
  363. break;
  364. }
  365. dprintf(INFO, "[%s] iram[%d/%d] offset 0x%x, dst_addr 0x%x, size 0x%x, dst 0x%x\n", MODULE_NAME, \
  366. seg->vpu_core, iram_num, iram_bin_offset, seg->pAddr, seg->memsz_byt, dst);
  367. //update iram descriptor
  368. dprintf(INFO, "[%s] (*pIramNum)[%d]\n", MODULE_NAME, (*pIramNum));
  369. //shift starting position of iram info in descriptor for same core
  370. pIram = (pIramNum + 1) + (3 * (*pIramNum));
  371. *pIram++= iram_bin_offset;
  372. *pIram++= seg->pAddr;
  373. *pIram++= seg->memsz_byt;
  374. iram_num++;
  375. *pIramNum = ((*pIramNum) + 1);
  376. } else {
  377. dprintf(CRITICAL, "[%s] invalid parameter !! seg->pAddr 0x%x\n", MODULE_NAME, seg->pAddr);
  378. ret = -EINVAL;
  379. goto exit;
  380. }
  381. part_offset = seg->off;
  382. read_size = seg->filesz_byt;
  383. dprintf(INFO, "[%s] seg[%d]: copy size 0x%x from part_offset 0x%x to dst 0x%x\n", MODULE_NAME, j, seg->filesz_byt, seg->off, dst);
  384. if (seg->filesz_byt > 0) {
  385. if (part_offset + read_size > part_size) {
  386. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size);
  387. ret = -EINVAL;
  388. goto exit;
  389. } else {
  390. memcpy((void *)dst,(void *)((u8*)part + part_offset) , read_size);
  391. }
  392. }
  393. len = seg->memsz_byt - seg->filesz_byt;
  394. if (len > 0) {
  395. dprintf(INFO, "[%s] seg[%d]: memset size 0x%x from dst 0x%x\n", MODULE_NAME, j, len, dst);
  396. memset((void*)(dst + seg->filesz_byt), 0, len);
  397. }
  398. }
  399. // 3. write algo to ddr
  400. dprintf(INFO, "[%s] part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  401. if (part_hdr->alg_num > VPU_ALG_MAX_NUM) {
  402. dprintf(CRITICAL, "[%s] invalid parameter !! part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  403. ret = -EINVAL;
  404. goto exit;
  405. }
  406. for (j = 0 ; j < part_hdr->alg_num ; j++) {
  407. VPU_ALG_INFO *alg = &part_hdr->alg[j];
  408. part_offset = alg->off;
  409. read_size = alg->filesz_byt;
  410. dprintf(INFO, "[%s] alg[%d]: copy size 0x%x from part_offset 0x%x to dstAlg 0x%x\n", MODULE_NAME, j, alg->filesz_byt, alg->off, dstAlg);
  411. if (part_offset + read_size > part_size) {
  412. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size);
  413. ret = -EINVAL;
  414. goto exit;
  415. } else {
  416. memcpy((void *)dstAlg,(void *)((u8*)part + part_offset) , read_size);
  417. }
  418. // 3.1. modify alg offset in partition header, let driver to get real offset from start vpu addr in ddr
  419. alg->off = (int)(dstAlg - dstBase);
  420. dprintf(INFO, "[%s] alg[%d], modify alg offset to 0x%x, dstAlg 0x%x, dstBase 0x%x\n", MODULE_NAME, j, alg->off, dstAlg, dstBase);
  421. dstAlg += ((alg->filesz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  422. }
  423. // 4. write partition header to ddr
  424. dprintf(INFO, "[%s] copy partition header to 0x%x\n", MODULE_NAME, dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i);
  425. memcpy((void *)(dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i),(void *)part_hdr , sizeof(VPU_IMAGEFILE_HEADER));
  426. }
  427. exit:
  428. return ret;
  429. }