mt_vpu.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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 MPU_REGION_ID_VPU (21)
  108. #define VPU_MAX_PART_SIZE (0x00F00000)
  109. #define VPU_ADDR_MASK (0xFFF00000)
  110. #define VPU_ALIGN_MASK (0x0000000F) // 16 bytes alignment for algo bin and iram prog so that vpu core can use DMA to copy
  111. static char *vpu_part_name[] = {"cam_vpu1", "cam_vpu2", "cam_vpu3"};
  112. static int vpu_part_size[] = {0x000C00000, 0x000F00000, 0x000F00000};
  113. static void *vpu_m4u_base_addr[] = {0x7DA00000, 0x7DB00000, 0x7FF00000}; // m4u address, pre-defined
  114. static void *vpu2_m4u_base_addr[] = {0x7E300000, 0x7E400000, 0x7FF00000}; // m4u address, pre-defined
  115. static void *vpu3_m4u_base_addr[] = {0x7EC00000, 0x7ED00000, 0x7FF00000}; // m4u address, pre-defined
  116. #ifndef MUINT32
  117. #define MUINT32 u32
  118. #endif
  119. /*---------------------------------------------------------------------------*/
  120. /* VPU Image file definition */
  121. /*---------------------------------------------------------------------------*/
  122. #define VPU_PARTITION_FILE_HEADER_VERSION (0x17102311) //chanage core index to bitwise presentation.
  123. #define VPU_CODE_SEGMENT_MAX_NUM (50)
  124. #define VPU_ALG_MAX_NUM (50)
  125. #define VPU_ALG_MAX_NAME_CHAR (32)
  126. #define VPU_HEADER_STR_SIZE (32)
  127. /*---------------------------------------------------------------------------*/
  128. /* VPU Image file emum */
  129. /*---------------------------------------------------------------------------*/
  130. typedef enum _VPU_CORE_ENUM_{
  131. //0x60 stands for VP6
  132. VPU_CORE_0 = ( 0x60 | (0x01 << 0) ), /* bitwise to represent core index */
  133. VPU_CORE_1 = ( 0x60 | (0x01 << 1) ),
  134. VPU_CORE_2 = ( 0x60 | (0x01 << 2) ),
  135. //
  136. VPU_CORE_MAX = 0x03,
  137. }VPU_CORE_ENUM;
  138. /*---------------------------------------------------------------------------*/
  139. /* VPU Image file structure */
  140. /*---------------------------------------------------------------------------*/
  141. typedef struct _VPU_CODE_SEGMENT_INFO_ {
  142. MUINT32 vpu_core; /* core index */
  143. MUINT32 off; /* offset */
  144. MUINT32 pAddr; /* destination */
  145. MUINT32 memsz_byt; /* mem. size byte to occupied */
  146. MUINT32 filesz_byt; /* file size byte to copy */
  147. } VPU_CODE_SEGMENT_INFO;
  148. typedef struct _VPU_ALG_INFO_ {
  149. MUINT32 vpu_core; /* core index */
  150. MUINT32 off; /* offset */
  151. MUINT32 filesz_byt; /* file size byte to copy */
  152. char name[VPU_ALG_MAX_NAME_CHAR ];
  153. } VPU_ALG_INFO;
  154. typedef struct _VPU_IMAGEFILE_HEADER_ {
  155. int version;
  156. int build_date;
  157. int hdr_str[VPU_HEADER_STR_SIZE / 4];
  158. int size_byt_hdr; /* header size */
  159. int size_byt_img; /* binary code size */
  160. //
  161. int segment_num;
  162. VPU_CODE_SEGMENT_INFO segment[VPU_CODE_SEGMENT_MAX_NUM];
  163. //
  164. int alg_num;
  165. VPU_ALG_INFO alg[VPU_ALG_MAX_NUM ];
  166. //reserved
  167. int reserved[VPU_HEADER_STR_SIZE];
  168. } VPU_IMAGEFILE_HEADER;
  169. int mt_load_vpu(void)
  170. {
  171. int i, j, len = 0, ret = 0;
  172. int part_offset = 0;
  173. int read_size = 0;
  174. u32 iram_num = 0;
  175. u32 iram_bin_offset = 0;
  176. u32 vpu_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  177. u32 vpu2_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  178. u32 vpu3_iram_bin_offset = ((4 + VPU_CODE_SEGMENT_MAX_NUM * 12) + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK;
  179. u32 *pIramNum, *pIram;
  180. void *part = NULL;
  181. VPU_IMAGEFILE_HEADER *part_hdr = NULL;
  182. char *part_name;
  183. int part_size;
  184. u32 dstHdrBase;
  185. u32 dstBase;
  186. u32 dst;
  187. u32 dstAlg;
  188. #ifdef DEVICE_TREE_SUPPORT
  189. u64 value;
  190. u32 size;
  191. int nodeoffset;
  192. #endif
  193. void *kernel_fdt = get_kernel_fdt();
  194. if (kernel_fdt == NULL)
  195. panic("kernel fdt is NULL!\n");
  196. // get physical address
  197. dstBase = (u32)mblock_reserve_ext(&g_boot_arg->mblock_info, VPU_DRAM_SIZE, VPU_DRAM_ADDR_ALIGN, VPU_DRAM_ADDR_MAX, 0, "vpu_binary");
  198. dprintf(INFO, "[%s] phyAddr of Allocation: 0x%x\n", MODULE_NAME, dstBase);
  199. if (!dstBase) {
  200. dprintf(CRITICAL, "[%s] vpu memory allocation failed.\n", MODULE_NAME);
  201. return -ENOMEM;
  202. }
  203. // get header base address
  204. dstHdrBase = dstBase + VPU_DRAM_HEADER_OFFSET;
  205. dprintf(INFO, "[%s] Base PhyAddr of Header: 0x%x\n", MODULE_NAME, dstHdrBase);
  206. // get alg base address
  207. dstAlg = dstBase + VPU_DRAM_ALGO_OFFSET;
  208. dprintf(INFO, "[%s] Base PhyAddr of Alg: 0x%x\n", MODULE_NAME, dstAlg);
  209. if (SCRATCH_SIZE < VPU_MAX_PART_SIZE) {
  210. dprintf(CRITICAL, "[%s] SCRATCH_SIZE(0x%x) < VPU_MAX_PART_SIZE(0x%x) .\n", MODULE_NAME, SCRATCH_SIZE, VPU_MAX_PART_SIZE);
  211. return -ENOMEM;
  212. }
  213. part = (void *)((UINT32) SCRATCH_ADDR + SCRATCH_SIZE - VPU_DRAM_SIZE); // Not to mess with kernel zimage, use tail
  214. #ifdef DEVICE_TREE_SUPPORT
  215. // set phyaddress to device tree
  216. nodeoffset = fdt_node_offset_by_compatible(kernel_fdt, -1, "mediatek,vpu_core0"); // get vpu node offset
  217. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  218. if (nodeoffset < 0) { // node add sub-node to /
  219. int offset;
  220. offset = fdt_path_offset(kernel_fdt, "/");
  221. dprintf(INFO, "[%s] root offset %d\n", MODULE_NAME, offset);
  222. if (offset < 0) {
  223. dprintf(CRITICAL, "[%s] fail to get fdt offset\n", MODULE_NAME);
  224. ret = -EINVAL;
  225. goto exit;
  226. } else {
  227. nodeoffset = fdt_add_subnode(kernel_fdt, offset, "vpu_core0");
  228. dprintf(INFO, "[%s] nodeoffset %d\n", MODULE_NAME, nodeoffset);
  229. if (nodeoffset < 0) {
  230. ret = -EINVAL;
  231. dprintf(CRITICAL, "[%s] fail to add subnode to fdt\n", MODULE_NAME);
  232. goto exit;
  233. } else {
  234. fdt_setprop_string(kernel_fdt, nodeoffset, "compatible", "mediatek,vpu_core0");
  235. }
  236. }
  237. }
  238. value = cpu_to_fdt32(dstBase);
  239. fdt_setprop(kernel_fdt, nodeoffset, "bin-phy-addr", (char *)&value, sizeof(u32));
  240. size = cpu_to_fdt32(VPU_DRAM_SIZE);
  241. fdt_setprop(kernel_fdt, nodeoffset, "bin-size", (char *)&size, sizeof(u32));
  242. #endif
  243. //initialization
  244. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  245. *pIramNum = 0;
  246. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  247. *pIramNum = 0;
  248. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  249. *pIramNum = 0;
  250. for (i = 0 ; i < (sizeof(vpu_part_name)/sizeof(*vpu_part_name)) ; i++) {
  251. #ifdef MTK_SECURITY_SW_SUPPORT
  252. unsigned int sec_feature_mask = 0;
  253. unsigned int policy_entry_idx = 0;
  254. unsigned int img_auth_required = 0;
  255. unsigned int vpu_vfy_time= 0;
  256. #endif
  257. part_name = vpu_part_name[i];
  258. part_size = vpu_part_size[i];
  259. #ifdef MTK_SECURITY_SW_SUPPORT
  260. policy_entry_idx = get_policy_entry_idx(part_name);
  261. img_auth_required = get_vfy_policy(policy_entry_idx);
  262. if (img_auth_required) {
  263. mtk_wdt_restart();
  264. vpu_vfy_time = get_timer(0);
  265. ret = (int)sec_img_auth_init(part_name, part_name, 0);
  266. if (ret) {
  267. dprintf(CRITICAL, "[%s] fail to verify %s cert (0x%x)\n", MODULE_NAME, part_name, ret);
  268. assert(0);
  269. }
  270. dprintf(CRITICAL, "[SBC] %s cert vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  271. #ifdef MTK_SECURITY_ANTI_ROLLBACK
  272. ret = sec_rollback_check(1);
  273. if (ret) {
  274. dprintf(CRITICAL, "[%s] fail to check %s version (0x%x)\n", MODULE_NAME, part_name, ret);
  275. assert(0);
  276. }
  277. #endif
  278. }
  279. #endif
  280. if ((len = mboot_common_load_part(part_name, part_name, (unsigned long)part)) < 0) {
  281. dprintf(CRITICAL, "[%s] vpu %s partition read error. len = %d\n", MODULE_NAME, part_name, len);
  282. ret = -EINVAL;
  283. goto exit;
  284. }
  285. dprintf(INFO, "[%s] sync arch_sync_cache_range lens = %d\n", MODULE_NAME, len);
  286. if (!len)
  287. continue;
  288. arch_sync_cache_range(part, len);
  289. #ifdef MTK_SECURITY_SW_SUPPORT
  290. if (img_auth_required) {
  291. mtk_wdt_restart();
  292. vpu_vfy_time = get_timer(0);
  293. ret = (int)sec_img_auth(part, len);
  294. if (ret) {
  295. dprintf(CRITICAL, "[%s] fail to check %s hash (0x%x)\n", MODULE_NAME, part_name, ret);
  296. assert(0);
  297. }
  298. dprintf(CRITICAL, "[SBC] %s vfy pass(%d ms)\n", part_name, (unsigned int)get_timer(vpu_vfy_time));
  299. }
  300. #endif
  301. // 1. read partition header
  302. part_offset = 0;
  303. read_size = sizeof(VPU_IMAGEFILE_HEADER);
  304. part_hdr = (VPU_IMAGEFILE_HEADER *)((u8*)part + part_offset);
  305. dprintf(INFO, "[%s] ============== part_name %s, len 0x%x ================= \n", MODULE_NAME, part_name, read_size);
  306. if (part_hdr->version != VPU_PARTITION_FILE_HEADER_VERSION) {
  307. dprintf(CRITICAL, "[%s] vpu version 0x%x != 0x%x\n", MODULE_NAME, part_hdr->version, VPU_PARTITION_FILE_HEADER_VERSION);
  308. }
  309. if (part_hdr->size_byt_hdr != sizeof(VPU_IMAGEFILE_HEADER)) {
  310. dprintf(CRITICAL, "[%s] vpu header size 0x%x != 0x%x\n", MODULE_NAME, part_hdr->size_byt_hdr, sizeof(VPU_IMAGEFILE_HEADER));
  311. ret = -EINVAL;
  312. goto exit;
  313. }
  314. part_hdr->hdr_str[VPU_HEADER_STR_SIZE/4 -1] = 0;
  315. dprintf(INFO, "[%s] version 0x%x, build_date 0x%x, hdr_str %s, size 0x%x, numOfSeg %d\n",
  316. MODULE_NAME, part_hdr->version, part_hdr->build_date, (char *)part_hdr->hdr_str, part_hdr->size_byt_img, part_hdr->segment_num);
  317. if (part_hdr->size_byt_img > part_size || part_hdr->segment_num > VPU_CODE_SEGMENT_MAX_NUM) {
  318. dprintf(CRITICAL, "[%s] invalid parameter !! part size 0x%x, numOfSeg %d\n", MODULE_NAME, part_hdr->size_byt_img, part_hdr->segment_num);
  319. ret = -EINVAL;
  320. goto exit;
  321. }
  322. // 2. write segment to ddr for each segment from partition
  323. for (j = 0 ; j < part_hdr->segment_num ; j++) {
  324. VPU_CODE_SEGMENT_INFO *seg = &part_hdr->segment[j];
  325. 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);
  326. if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[1]) {
  327. dst = dstBase + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[1]);
  328. 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);
  329. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[1]) {
  330. dst = dstBase + VPU_CORE_RESVEC_SHIFT + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu2_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 + VPU_DRAM_PROG_OFFSET, (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[1]), dst);
  332. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[1]) {
  333. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + VPU_DRAM_PROG_OFFSET + (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[1]);
  334. 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);
  335. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[0]) {
  336. dst = dstBase + (int)((uchar*)seg->pAddr - (uchar*)vpu_m4u_base_addr[0]);
  337. 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);
  338. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu2_m4u_base_addr[0]) {
  339. dst = dstBase + VPU_CORE_RESVEC_SHIFT + (int)((uchar*)seg->pAddr - (uchar*)vpu2_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, (int)((uchar*)seg->pAddr - (uchar*)vpu2_m4u_base_addr[0]), dst);
  341. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu3_m4u_base_addr[0]) {
  342. dst = dstBase + (VPU_CORE_RESVEC_SHIFT << 1) + (int)((uchar*)seg->pAddr - (uchar*)vpu3_m4u_base_addr[0]);
  343. 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);
  344. } else if ((seg->pAddr & VPU_ADDR_MASK) == (MUINT32)vpu_m4u_base_addr[2]) {
  345. switch (seg->vpu_core) {
  346. case VPU_CORE_0:
  347. dst = dstBase + VPU_DRAM_IRAM_OFFSET + vpu_iram_bin_offset;
  348. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET);
  349. iram_bin_offset = vpu_iram_bin_offset;
  350. vpu_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  351. break;
  352. case VPU_CORE_1:
  353. dst = dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT + vpu2_iram_bin_offset;
  354. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + VPU_CORE_IRAM_SHIFT);
  355. iram_bin_offset = vpu2_iram_bin_offset;
  356. vpu2_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  357. break;
  358. case VPU_CORE_2:
  359. dst = dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1) + vpu3_iram_bin_offset;
  360. pIramNum = (u32 *)(dstBase + VPU_DRAM_IRAM_OFFSET + (VPU_CORE_IRAM_SHIFT << 1));
  361. iram_bin_offset = vpu3_iram_bin_offset;
  362. vpu3_iram_bin_offset += ((seg->memsz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  363. break;
  364. default:
  365. dprintf(CRITICAL, "[%s] wrong seg->core info %d\n", MODULE_NAME, seg->vpu_core);
  366. break;
  367. }
  368. dprintf(INFO, "[%s] iram[%d/%d] offset 0x%x, dst_addr 0x%x, size 0x%x, dst 0x%x\n", MODULE_NAME, \
  369. seg->vpu_core, iram_num, iram_bin_offset, seg->pAddr, seg->memsz_byt, dst);
  370. //update iram descriptor
  371. dprintf(INFO, "[%s] (*pIramNum)[%d]\n", MODULE_NAME, (*pIramNum));
  372. //shift starting position of iram info in descriptor for same core
  373. pIram = (pIramNum + 1) + (3 * (*pIramNum));
  374. *pIram++= iram_bin_offset;
  375. *pIram++= seg->pAddr;
  376. *pIram++= seg->memsz_byt;
  377. iram_num++;
  378. *pIramNum = ((*pIramNum) + 1);
  379. } else {
  380. dprintf(CRITICAL, "[%s] invalid parameter !! seg->pAddr 0x%x\n", MODULE_NAME, seg->pAddr);
  381. ret = -EINVAL;
  382. goto exit;
  383. }
  384. part_offset = seg->off;
  385. read_size = seg->filesz_byt;
  386. 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);
  387. if (seg->filesz_byt > 0) {
  388. if (part_offset + read_size > part_size) {
  389. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size, part_size);
  390. ret = -EINVAL;
  391. goto exit;
  392. } else {
  393. memcpy((void *)dst,(void *)((u8*)part + part_offset) , read_size);
  394. }
  395. }
  396. len = seg->memsz_byt - seg->filesz_byt;
  397. if (len > 0) {
  398. dprintf(INFO, "[%s] seg[%d]: memset size 0x%x from dst 0x%x\n", MODULE_NAME, j, len, dst);
  399. memset((void*)(dst + seg->filesz_byt), 0, len);
  400. }
  401. }
  402. // 3. write algo to ddr
  403. dprintf(INFO, "[%s] part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  404. if (part_hdr->alg_num > VPU_ALG_MAX_NUM) {
  405. dprintf(CRITICAL, "[%s] invalid parameter !! part_hdr->alg_num %d\n", MODULE_NAME, part_hdr->alg_num);
  406. ret = -EINVAL;
  407. goto exit;
  408. }
  409. for (j = 0 ; j < part_hdr->alg_num ; j++) {
  410. VPU_ALG_INFO *alg = &part_hdr->alg[j];
  411. part_offset = alg->off;
  412. read_size = alg->filesz_byt;
  413. 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);
  414. if (part_offset + read_size > part_size) {
  415. dprintf(CRITICAL, "[%s] %s partition offset error, offset 0x%x, read_size 0x%x\n", MODULE_NAME, part_name, part_offset, read_size, part_size);
  416. ret = -EINVAL;
  417. goto exit;
  418. } else {
  419. memcpy((void *)dstAlg,(void *)((u8*)part + part_offset) , read_size);
  420. }
  421. // 3.1. modify alg offset in partition header, let driver to get real offset from start vpu addr in ddr
  422. alg->off = (int)(dstAlg - dstBase);
  423. 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);
  424. dstAlg += ((alg->filesz_byt + VPU_ALIGN_MASK) & ~VPU_ALIGN_MASK);
  425. }
  426. // 4. write partition header to ddr
  427. dprintf(INFO, "[%s] copy partition header to 0x%x\n", MODULE_NAME, dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i);
  428. memcpy((void *)(dstHdrBase + sizeof(VPU_IMAGEFILE_HEADER)*i),(void *)part_hdr , sizeof(VPU_IMAGEFILE_HEADER));
  429. }
  430. exit:
  431. if (!ret) {
  432. struct emi_region_info_t region_info;
  433. /* cache operation before config EMIMPU */
  434. arch_sync_cache_range((addr_t)dstBase, VPU_DRAM_SIZE);
  435. region_info.start = (unsigned long long)dstBase;
  436. region_info.end = (unsigned long long)(dstBase + VPU_DRAM_SIZE - 0x1);
  437. dprintf(INFO, "[%s] prot region [0x%X:0x%X]\n", MODULE_NAME, dstBase, VPU_DRAM_SIZE);
  438. region_info.region = MPU_REGION_ID_VPU;
  439. SET_ACCESS_PERMISSION(region_info.apc, UNLOCK,
  440. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  441. NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  442. FORBIDDEN, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
  443. FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW_NSEC_R);
  444. emi_mpu_set_protection(&region_info);
  445. }
  446. return ret;
  447. }