mt_vpu.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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. /*The buffer layout in DDR is as follows:
  39. * The total is 45MBs.
  40. * [phyaddr offset] [mapping mva]
  41. * 0x00000000 +-----------------------+
  42. * | Reset vector of core0 |
  43. * | code |
  44. * 0x00100000 +-----------------------+
  45. * | Main Program of core0 |
  46. * | |
  47. * 0x00400000 +-----------------------+
  48. * | Reset vector of core1 |
  49. * | code |
  50. * 0x00500000 +-----------------------+
  51. * | Main Program of core1 |
  52. * | |
  53. * 0x00800000 +-----------------------+
  54. * | Reset vector of core2 |
  55. * | code |
  56. * 0x00900000 +-----------------------+
  57. * | Main Program of core2 |
  58. * | |
  59. * 0x00C00000 +-----------------------+
  60. * | Algo Area |
  61. * | |
  62. * 0x02950000 +-----------------------+
  63. * | Main Prog. IRAM of core0|
  64. * | binary data |
  65. * 0x02980000 +-----------------------+
  66. * | Main Prog. IRAM of core1|
  67. * | binary data |
  68. * 0x029B0000 +-----------------------+
  69. * | Main Prog. IRAM of core2|
  70. * | binary data |
  71. * 0x029E0000 +-----------------------+
  72. * | Merged image header |
  73. * | |
  74. * +-----------------------+
  75. *
  76. *
  77. * the layout of Main Prog. IRAM
  78. * +-----------------------+
  79. * | num | off0| dst0|size0|
  80. * | off1| dst1|size1| off2|
  81. * | dst2|size2| ... | |
  82. * ...
  83. * | seg0_data |
  84. * | seg0_data |
  85. * | seg1_data |
  86. * ...
  87. * +-----------------------+
  88. * num: number of segment for IRAM program
  89. * off: bin data offset from start of Main Prog. IRAM
  90. * dst: the dst address of bin data at IRAM
  91. * size: size of bin data
  92. * seg_data: bin data
  93. */
  94. extern int mboot_common_load_part(char *part_name, char *img_name, unsigned long addr);
  95. extern void mtk_wdt_restart(void);
  96. #define MODULE_NAME "LK_BOOT_VPU"
  97. #define VPU_DRAM_ADDR_ALIGN (0x00010000)
  98. #define VPU_DRAM_ADDR_MAX (0xC0000000)
  99. #define VPU_DRAM_SIZE (0x02A10000) // total ddr size we apply for vpu
  100. #define VPU_DRAM_PROG_OFFSET (0x00100000) // start address of main program (core0)
  101. #define VPU_DRAM_ALGO_OFFSET (0x00C00000) // start address of algo, after 3*(reset vector+main program)
  102. #define VPU_DRAM_IRAM_OFFSET (VPU_DRAM_SIZE - 0xC0000) // start address of main program IRAM binary data (core0)
  103. #define VPU_DRAM_HEADER_OFFSET (VPU_DRAM_SIZE - 0x30000) // start address of header
  104. #define VPU_CORE_RESVEC_SHIFT (0x00400000) //1MB reset vector + 3 MB main program data
  105. #define VPU_CORE_IRAM_SHIFT (0x0030000) //max 192k for each iram region
  106. #define VPU_MAX_PART_SIZE (0x00F00000)
  107. #define VPU_ADDR_MASK (0xFFF00000)
  108. #define VPU_ALIGN_MASK (0x0000000F) // 16 bytes alignment for algo bin and iram prog so that vpu core can use DMA to copy
  109. static char *vpu_part_name[] = {"cam_vpu1", "cam_vpu2", "cam_vpu3"};
  110. static int vpu_part_size[] = {0x000C00000, 0x000F00000, 0x000F00000};
  111. static void *vpu_m4u_base_addr[] = {0x7DA00000, 0x7DB00000, 0x7FF00000}; // m4u address, pre-defined
  112. static void *vpu2_m4u_base_addr[] = {0x7E300000, 0x7E400000, 0x7FF00000}; // m4u address, pre-defined
  113. static void *vpu3_m4u_base_addr[] = {0x7EC00000, 0x7ED00000, 0x7FF00000}; // m4u address, pre-defined
  114. #ifndef MUINT32
  115. #define MUINT32 u32
  116. #endif
  117. /*---------------------------------------------------------------------------*/
  118. /* VPU Image file definition */
  119. /*---------------------------------------------------------------------------*/
  120. #define VPU_PARTITION_FILE_HEADER_VERSION (0x17102311) //chanage core index to bitwise presentation.
  121. #define VPU_CODE_SEGMENT_MAX_NUM (50)
  122. #define VPU_ALG_MAX_NUM (50)
  123. #define VPU_ALG_MAX_NAME_CHAR (32)
  124. #define VPU_HEADER_STR_SIZE (32)
  125. /*---------------------------------------------------------------------------*/
  126. /* VPU Image file emum */
  127. /*---------------------------------------------------------------------------*/
  128. typedef enum _VPU_CORE_ENUM_{
  129. //0x60 stands for VP6
  130. VPU_CORE_0 = ( 0x60 | (0x01 << 0) ), /* bitwise to represent core index */
  131. VPU_CORE_1 = ( 0x60 | (0x01 << 1) ),
  132. VPU_CORE_2 = ( 0x60 | (0x01 << 2) ),
  133. //
  134. VPU_CORE_MAX = 0x03,
  135. }VPU_CORE_ENUM;
  136. /*---------------------------------------------------------------------------*/
  137. /* VPU Image file structure */
  138. /*---------------------------------------------------------------------------*/
  139. typedef struct _VPU_CODE_SEGMENT_INFO_ {
  140. MUINT32 vpu_core; /* core index */
  141. MUINT32 off; /* offset */
  142. MUINT32 pAddr; /* destination */
  143. MUINT32 memsz_byt; /* mem. size byte to occupied */
  144. MUINT32 filesz_byt; /* file size byte to copy */
  145. } VPU_CODE_SEGMENT_INFO;
  146. typedef struct _VPU_ALG_INFO_ {
  147. MUINT32 vpu_core; /* core index */
  148. MUINT32 off; /* offset */
  149. MUINT32 filesz_byt; /* file size byte to copy */
  150. char name[VPU_ALG_MAX_NAME_CHAR ];
  151. } VPU_ALG_INFO;
  152. typedef struct _VPU_IMAGEFILE_HEADER_ {
  153. int version;
  154. int build_date;
  155. int hdr_str[VPU_HEADER_STR_SIZE / 4];
  156. int size_byt_hdr; /* header size */
  157. int size_byt_img; /* binary code size */
  158. //
  159. int segment_num;
  160. VPU_CODE_SEGMENT_INFO segment[VPU_CODE_SEGMENT_MAX_NUM];
  161. //
  162. int alg_num;
  163. VPU_ALG_INFO alg[VPU_ALG_MAX_NUM ];
  164. //reserved
  165. int reserved[VPU_HEADER_STR_SIZE];
  166. } VPU_IMAGEFILE_HEADER;
  167. int mt_load_vpu(void)
  168. {
  169. int i, j, len, ret = 0;
  170. int part_offset;
  171. int read_size;
  172. u32 iram_num = 0;
  173. u32 iram_bin_offset = 0;
  174. u32 vpu_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  175. u32 vpu2_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  176. u32 vpu3_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  177. u32 *pIramNum, *pIram;
  178. void *part = NULL;
  179. VPU_IMAGEFILE_HEADER *part_hdr = NULL;
  180. char *part_name;
  181. int part_size;
  182. u32 dstHdrBase;
  183. u32 dstBase;
  184. u32 dst;
  185. u32 dstAlg;
  186. #ifdef DEVICE_TREE_SUPPORT
  187. u64 value;
  188. u32 size;
  189. int nodeoffset;
  190. void *kernel_fdt = get_kernel_fdt();
  191. if (kernel_fdt == NULL)
  192. panic("kernel fdt is NULL!\n");
  193. #endif
  194. // get physical address
  195. dstBase = (u32)mblock_reserve_ext(&g_boot_arg->mblock_info, VPU_DRAM_SIZE, VPU_DRAM_ADDR_ALIGN, VPU_DRAM_ADDR_MAX, 0, "vpu_binary");
  196. dprintf(INFO, "[%s] phyAddr of Allocation: 0x%x\n", MODULE_NAME, dstBase);
  197. if (!dstBase) {
  198. dprintf(CRITICAL, "[%s] vpu memory allocation failed.\n", MODULE_NAME);
  199. return -ENOMEM;
  200. }
  201. // get header base address
  202. dstHdrBase = dstBase + VPU_DRAM_HEADER_OFFSET;
  203. dprintf(INFO, "[%s] Base PhyAddr of Header: 0x%x\n", MODULE_NAME, dstHdrBase);
  204. // get alg base address
  205. dstAlg = dstBase + VPU_DRAM_ALGO_OFFSET;
  206. dprintf(INFO, "[%s] Base PhyAddr of Alg: 0x%x\n", MODULE_NAME, dstAlg);
  207. if (SCRATCH_SIZE < VPU_MAX_PART_SIZE) {
  208. dprintf(CRITICAL, "[%s] SCRATCH_SIZE(0x%x) < VPU_MAX_PART_SIZE(0x%x) .\n", MODULE_NAME, SCRATCH_SIZE, VPU_MAX_PART_SIZE);
  209. return -ENOMEM;
  210. }
  211. part = (void *)((UINT32) SCRATCH_ADDR + SCRATCH_SIZE - VPU_DRAM_SIZE); // Not to mess with kernel zimage, use tail
  212. #ifdef DEVICE_TREE_SUPPORT
  213. // set phyaddress to device tree
  214. nodeoffset = fdt_node_offset_by_compatible(kernel_fdt, -1, "mediatek,vpu_core0"); // get vpu node offset
  215. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  216. if (nodeoffset < 0) { // node add sub-node to /
  217. int offset;
  218. offset = fdt_path_offset(kernel_fdt, "/");
  219. dprintf(INFO, "[%s] root offset %d\n", MODULE_NAME, offset);
  220. if (offset < 0) {
  221. dprintf(CRITICAL, "[%s] fail to get fdt offset\n", MODULE_NAME);
  222. ret = -EINVAL;
  223. goto exit;
  224. } else {
  225. nodeoffset = fdt_add_subnode(kernel_fdt, offset, "vpu_core0");
  226. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  227. if (nodeoffset < 0) {
  228. ret = -EINVAL;
  229. dprintf(CRITICAL, "[%s] fail to add subnode to fdt\n", MODULE_NAME);
  230. goto exit;
  231. } else {
  232. fdt_setprop_string(kernel_fdt, nodeoffset, "compatible", "mediatek,vpu_core0");
  233. }
  234. }
  235. }
  236. value = cpu_to_fdt32(dstBase);
  237. fdt_setprop(kernel_fdt, nodeoffset, "bin-phy-addr", (char *)&value, sizeof(u32));
  238. size = cpu_to_fdt32(VPU_DRAM_SIZE);
  239. fdt_setprop(kernel_fdt, nodeoffset, "bin-size", (char *)&size, sizeof(u32));
  240. #endif
  241. //initialization
  242. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  243. *pIramNum = 0;
  244. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  245. *pIramNum = 0;
  246. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  247. *pIramNum = 0;
  248. for (i = 0 ; i < (sizeof(vpu_part_name)/sizeof(*vpu_part_name)) ; i++) {
  249. #ifdef MTK_SECURITY_SW_SUPPORT
  250. unsigned int sec_feature_mask = 0;
  251. unsigned int policy_entry_idx = 0;
  252. unsigned int img_auth_required = 0;
  253. unsigned int vpu_vfy_time= 0;
  254. #endif
  255. part_name = vpu_part_name[i];
  256. part_size = vpu_part_size[i];
  257. #ifdef MTK_SECURITY_SW_SUPPORT
  258. policy_entry_idx = get_policy_entry_idx(part_name);
  259. img_auth_required = get_vfy_policy(policy_entry_idx);
  260. if (img_auth_required) {
  261. mtk_wdt_restart();
  262. vpu_vfy_time = get_timer(0);
  263. ret = (int)sec_img_auth_init(part_name, part_name, 0);
  264. if (ret) {
  265. dprintf(CRITICAL, "[%s] fail to verify %s cert (0x%x)\n", MODULE_NAME, part_name, ret);
  266. assert(0);
  267. }
  268. dprintf(CRITICAL, "[SBC] %s cert vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  269. #ifdef MTK_SECURITY_ANTI_ROLLBACK
  270. ret = sec_rollback_check(1);
  271. if (ret) {
  272. dprintf(CRITICAL, "[%s] fail to check %s version (0x%x)\n", MODULE_NAME, part_name, ret);
  273. assert(0);
  274. }
  275. #endif
  276. }
  277. #endif
  278. if ((len = mboot_common_load_part(part_name, part_name, (unsigned long)part)) < 0) {
  279. dprintf(CRITICAL, "[%s] vpu %s partition read error. len = %d\n", MODULE_NAME, part_name, len);
  280. ret = -EINVAL;
  281. goto exit;
  282. }
  283. #ifdef MTK_SECURITY_SW_SUPPORT
  284. if (img_auth_required) {
  285. mtk_wdt_restart();
  286. vpu_vfy_time = get_timer(0);
  287. ret = (int)sec_img_auth(part, len);
  288. if (ret) {
  289. dprintf(CRITICAL, "[%s] fail to check %s hash (0x%x)\n", MODULE_NAME, part_name, ret);
  290. assert(0);
  291. }
  292. dprintf(CRITICAL, "[SBC] %s vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  293. }
  294. #endif
  295. // 1. read partition header
  296. part_offset = 0;
  297. read_size = sizeof(VPU_IMAGEFILE_HEADER);
  298. part_hdr = (VPU_IMAGEFILE_HEADER *)((u8*)part + part_offset);
  299. dprintf(INFO, "[%s] ============== part_name %s, len 0x%x ================= \n", MODULE_NAME, part_name, read_size);
  300. if (part_hdr->version != VPU_PARTITION_FILE_HEADER_VERSION) {
  301. dprintf(CRITICAL, "[%s] vpu version 0x%x != 0x%x\n", MODULE_NAME, part_hdr->version, VPU_PARTITION_FILE_HEADER_VERSION);
  302. }
  303. if (part_hdr->size_byt_hdr != sizeof(VPU_IMAGEFILE_HEADER)) {
  304. dprintf(CRITICAL, "[%s] vpu header size 0x%x != 0x%x\n", MODULE_NAME, part_hdr->size_byt_hdr, sizeof(VPU_IMAGEFILE_HEADER));
  305. ret = -EINVAL;
  306. goto exit;
  307. }
  308. part_hdr->hdr_str[VPU_HEADER_STR_SIZE/4 -1] = 0;
  309. dprintf(INFO, "[%s] version 0x%x, build_date 0x%x, hdr_str %s, size 0x%x, numOfSeg %d\n",
  310. MODULE_NAME, part_hdr->version, part_hdr->build_date, (char *)part_hdr->hdr_str, part_hdr->size_byt_img, part_hdr->segment_num);
  311. if (part_hdr->size_byt_img > part_size || part_hdr->segment_num > VPU_CODE_SEGMENT_MAX_NUM) {
  312. dprintf(CRITICAL, "[%s] invalid parameter !! part size 0x%x, numOfSeg %d\n", MODULE_NAME, part_hdr->size_byt_img, part_hdr->segment_num);
  313. ret = -EINVAL;
  314. goto exit;
  315. }
  316. // 2. write segment to ddr for each segment from partition
  317. for (j = 0 ; j < part_hdr->segment_num ; j++) {
  318. VPU_CODE_SEGMENT_INFO *seg = &part_hdr->segment[j];
  319. 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);
  320. if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[1]) {
  321. dst = dstBase + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[1]);
  322. 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);
  323. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[1]) {
  324. dst = dstBase + VPU_CORE_RESVEC_SHIFT + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[1]);
  325. 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);
  326. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[1]) {
  327. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu3_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 << 1) + VPU_DRAM_PROG_OFFSET, (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[1]), dst);
  329. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[0]) {
  330. dst = dstBase + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[0]);
  331. 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);
  332. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[0]) {
  333. dst = dstBase + VPU_CORE_RESVEC_SHIFT + (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[0]);
  334. 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);
  335. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[0]) {
  336. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + (int)((uchar*)seg->pAddr - (uchar*)vpu3_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 << 1), (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[0]), dst);
  338. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[2]) {
  339. switch (seg->vpu_core) {
  340. case VPU_CORE_0:
  341. dst = dstBase + VPU_DRAM_IRAM_OFFSET + vpu_iram_bin_offset;
  342. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  343. iram_bin_offset = vpu_iram_bin_offset;
  344. vpu_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  345. break;
  346. case VPU_CORE_1:
  347. dst = dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT + vpu2_iram_bin_offset;
  348. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  349. iram_bin_offset = vpu2_iram_bin_offset;
  350. vpu2_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  351. break;
  352. case VPU_CORE_2:
  353. dst = dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1) + vpu3_iram_bin_offset;
  354. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  355. iram_bin_offset = vpu3_iram_bin_offset;
  356. vpu3_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  357. break;
  358. default:
  359. dprintf(CRITICAL, "[%s] wrong seg->core info %d\n", MODULE_NAME, seg->vpu_core);
  360. break;
  361. }
  362. dprintf(INFO, "[%s] iram[%d/%d] offset 0x%x, dst_addr 0x%x, size 0x%x, dst 0x%x\n", MODULE_NAME, \
  363. seg->vpu_core, iram_num, iram_bin_offset, seg->pAddr, seg->memsz_byt, dst);
  364. //update iram descriptor
  365. dprintf(INFO, "[%s] (*pIramNum)[%d]\n", MODULE_NAME, (*pIramNum));
  366. //shift starting position of iram info in descriptor for same core
  367. pIram = (pIramNum + 1) + (3 * (*pIramNum));
  368. *pIram++= iram_bin_offset;
  369. *pIram++= seg->pAddr;
  370. *pIram++= seg->memsz_byt;
  371. iram_num++;
  372. *pIramNum = ((*pIramNum) + 1);
  373. } else {
  374. dprintf(CRITICAL, "[%s] invalid parameter !! seg->pAddr 0x%x\n", MODULE_NAME, seg->pAddr);
  375. ret = -EINVAL;
  376. goto exit;
  377. }
  378. part_offset = seg->off;
  379. read_size = seg->filesz_byt;
  380. 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);
  381. if (seg->filesz_byt > 0) {
  382. if (part_offset + read_size > part_size) {
  383. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size);
  384. ret = -EINVAL;
  385. goto exit;
  386. } else {
  387. memcpy((void *)dst,(void *)((u8*)part + part_offset) , read_size);
  388. }
  389. }
  390. len = seg->memsz_byt - seg->filesz_byt;
  391. if (len > 0) {
  392. dprintf(INFO, "[%s] seg[%d]: memset size 0x%x from dst 0x%x\n", MODULE_NAME, j, len, dst);
  393. memset((void*)(dst + seg->filesz_byt), 0, len);
  394. }
  395. }
  396. // 3. write algo to ddr
  397. dprintf(INFO, "[%s] part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  398. if (part_hdr->alg_num > VPU_ALG_MAX_NUM) {
  399. dprintf(CRITICAL, "[%s] invalid parameter !! part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  400. ret = -EINVAL;
  401. goto exit;
  402. }
  403. for (j = 0 ; j < part_hdr->alg_num ; j++) {
  404. VPU_ALG_INFO *alg = &part_hdr->alg[j];
  405. part_offset = alg->off;
  406. read_size = alg->filesz_byt;
  407. 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);
  408. if (part_offset + read_size > part_size) {
  409. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size);
  410. ret = -EINVAL;
  411. goto exit;
  412. } else {
  413. memcpy((void *)dstAlg,(void *)((u8*)part + part_offset) , read_size);
  414. }
  415. // 3.1. modify alg offset in partition header, let driver to get real offset from start vpu addr in ddr
  416. alg->off = (int)(dstAlg - dstBase);
  417. 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);
  418. dstAlg += ((alg->filesz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  419. }
  420. // 4. write partition header to ddr
  421. dprintf(INFO, "[%s] copy partition header to 0x%x\n", MODULE_NAME, dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i);
  422. memcpy((void *)(dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i),(void *)part_hdr , sizeof(VPU_IMAGEFILE_HEADER));
  423. }
  424. exit:
  425. return ret;
  426. }