mt_vpu.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  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 <ctype.h>
  32. #include <debug.h>
  33. #ifdef DEVICE_TREE_SUPPORT
  34. #include <fdt_op.h>
  35. #include <libfdt.h>
  36. #endif
  37. #include <malloc.h>
  38. #include <part_interface.h>
  39. #include <platform/errno.h>
  40. #include <platform/mt_gpt.h>
  41. #include <platform/verified_boot.h>
  42. #include <platform/boot_mode.h>
  43. #include <platform/partition.h>
  44. #include <stdlib.h>
  45. #include <platform/mt_vpu.h>
  46. /*The buffer layout in DDR is as follows:
  47. * The total is 45MBs.
  48. * [phyaddr offset]
  49. * 0x00000000 +---------------------------+ 0
  50. * | Core#0 reset vector |
  51. * 0x00100000 +---------------------------+ DSP_RST_VEC_SZ * 1
  52. * | Core#0 main program |
  53. * 0x00400000 +---------------------------+ DSP_RST_VEC_SZ * 1 + DSP_PROG_SZ * 1
  54. * | Core#1 reset vector |
  55. * 0x00500000 +---------------------------+ DSP_RST_VEC_SZ * 2 + DSP_PROG_SZ * 1
  56. * | Core#1 main program |
  57. * 0x00800000 +---------------------------+ DSP_RST_VEC_SZ * 2 + DSP_PROG_SZ * 2
  58. * | Core#2 reset vector |
  59. * 0x00900000 +---------------------------+ DSP_RST_VEC_SZ * 3 + DSP_PROG_SZ * 2
  60. * | Core#2 main program |
  61. * 0x00C00000 +---------------------------+ DSP_RST_VEC_SZ * 3 + DSP_PROG_SZ * 3
  62. * | Algo area |
  63. * 0x02950000 +---------------------------+ default IRAM_OFFSET
  64. * | main program#0 IRAM data |
  65. * 0x02980000 +---------------------------+
  66. * | main program#1 IRAM data |
  67. * 0x029B0000 +---------------------------+
  68. * | main program#2 IRAM data |
  69. * 0x029E0000 +---------------------------+
  70. * | Merged image header |
  71. * 0x02A10000 +---------------------------+
  72. * | PRELOAD |
  73. * +---------------------------+
  74. *
  75. * the layout of main program IRAM data
  76. *
  77. * +--------------------------+
  78. * | total iram segment num |
  79. * +--------------------------+
  80. * | offset to iram#0 |
  81. * +--------------------------+
  82. * | dest of iram#0 |
  83. * +--------------------------+
  84. * | size of iram#0 |
  85. * +--------------------------+
  86. * | offset to iram#1 |
  87. * +--------------------------+
  88. * | dest of iram#1 |
  89. * +--------------------------+
  90. * | size of iram#1 |
  91. * +--------------------------+
  92. * | offset to iram#2 |
  93. * +--------------------------+
  94. * | dest of iram#2 |
  95. * +--------------------------+
  96. * | size of iram#2 |
  97. * +--------------------------+
  98. * | iram#0 data |
  99. * +--------------------------+
  100. * | iram#1 data |
  101. * +--------------------------+
  102. * | iram#2 data |
  103. * +--------------------------+
  104. *
  105. * num: number of segment for IRAM program
  106. * off: bin data offset from start of Main Prog. IRAM
  107. * dst: the dst address of bin data at IRAM
  108. * size: size of bin data
  109. * seg_data: bin data
  110. *
  111. *
  112. * layout of Preload
  113. * +-----------------------+
  114. * | preload#0 program |
  115. * +-----------------------+
  116. * | preload#0 IRAM data |
  117. * +-----------------------+
  118. * | preload#1 program |
  119. * +-----------------------+
  120. * | preload#1 IRAM data |
  121. * +-----------------------+
  122. * | ... |
  123. * +-----------------------+
  124. *
  125. *
  126. */
  127. extern int mboot_common_load_part(char *part_name,
  128. char *img_name, unsigned long addr);
  129. extern void mtk_wdt_restart(void);
  130. /*****************************************************************************
  131. * Constants/Macros *
  132. *****************************************************************************/
  133. #define MODULE_NAME "[LK_BOOT_VPU] "
  134. /*
  135. * VERSION: Character layout: 00.000.000 : major.minor.reserved
  136. */
  137. #define VERSION (0x21006000)
  138. #define ADDR_ALIGN (0x00010000)
  139. #define ADDR_MAX (0xC0000000)
  140. #define DEF_RSRV_SIZE (0x02A10000) // default reserved ddr size for vpu
  141. #define PROG_OFFSET (0x00100000) // start address of main program (core0)
  142. #define DSP_RST_VEC_SZ (0x00100000) // Reset vector for 1 VPU: 1MB
  143. #define DSP_PROG_SZ (0x00300000) // Main program for 1 VPU: 3MB
  144. #define DEF_ALG_SZ (0x01D50000) // default algo bank size for 3 VPUs
  145. #define IRAM_SEG_SZ (0x00010000) // max 64k for each iram region
  146. #define DSP_BOOT_SZ (DSP_RST_VEC_SZ + DSP_PROG_SZ)
  147. #define SPARE_SZ (0x00001000) // spare size for VPU
  148. #define MAX_PART_SIZE (0x00F00000)
  149. #define ADDR_MASK (0xFFF00000)
  150. #define ALIGN_16 (0x00000010) // 16 bytes alignment for algo bin and iram prog so that vpu core can use DMA to copy
  151. #define ALIGN_32 (0x00000020)
  152. #define ALIGN_4K (0x00001000)
  153. #define ALIGN_64K (0x00010000)
  154. #define ALIGN_2M (0x00200000)
  155. #define MAIN_SEG_MAX (50)
  156. #define ALG_NAME_SIZE (32)
  157. #define HDR_STR_SIZE (32)
  158. #define VP6_MAGIC (0x60)
  159. #define PROP_LEN (16)
  160. #define MAX_DSP_NUM (3)
  161. #define NODE_CONT_LEN (3)
  162. #define MAJOR_VER(x) (x & 0xFF000000)
  163. #define IRAM_MAIN_HDR_SIZE (4 + MAIN_SEG_MAX * sizeof(struct iram_desc))
  164. #define MAIN_IRAM_DESC_HDR_SIZE ALIGN(IRAM_MAIN_HDR_SIZE, ALIGN_16)
  165. #define LOG_CRI(format, args...) dprintf(CRITICAL, MODULE_NAME format, ##args)
  166. #define LOG_INF(format, args...) dprintf(INFO, MODULE_NAME format, ##args)
  167. #define DT_ID "id"
  168. #define DT_IRAM_DAT "iram-data"
  169. #define DT_ALGO "algo"
  170. #define DT_COMP "compatible"
  171. #define DT_BIN "bin-phy-addr"
  172. #define DT_BIN_SZ "bin-size"
  173. #define DT_HEAD "img-head"
  174. #define DT_PRE_BIN "pre-bin"
  175. #if (SCRATCH_SIZE < MAX_PART_SIZE)
  176. #error SCRATCH_SIZE < MAX_PART_SIZE
  177. #endif
  178. /*****************************************************************************
  179. * Type declarations *
  180. *****************************************************************************/
  181. enum CORE_NUM {
  182. CORE0 = 0,
  183. CORE1,
  184. CORE2,
  185. CORE_MAX,
  186. };
  187. enum _VPU_CORE_ENUM_ {
  188. VPU_CORE_0 = (VP6_MAGIC | (1 << CORE0)), /* bitwise to represent core index */
  189. VPU_CORE_1 = (VP6_MAGIC | (1 << CORE1)),
  190. VPU_CORE_2 = (VP6_MAGIC | (1 << CORE2)),
  191. VPU_CORE_MAX = 0x03,
  192. };
  193. enum auth_cmd {
  194. AUTH_INIT,
  195. AUTH_DO,
  196. };
  197. enum dt_prop {
  198. PROP_INIT,
  199. PRE_BIN,
  200. };
  201. enum DSP_ADDR {
  202. RESET_VEC = 0,
  203. MAIN_PROG = 1,
  204. IRAM = 2,
  205. };
  206. enum pre_flag {
  207. EXE_SEG = (1 << 0),
  208. ZERO_SEG = (1 << 1),
  209. };
  210. enum {
  211. TOTAL_DSP,
  212. TOTAL_ALG_SZ,
  213. RESERVE_VAR2,
  214. RESERVE_VAR3,
  215. RESERVE_TOTAL,
  216. };
  217. struct iram_desc {
  218. unsigned int offset;
  219. unsigned int addr;
  220. unsigned int size;
  221. };
  222. struct seg_info {
  223. u32 vpu_core; /* core index */
  224. u32 off; /* offset */
  225. u32 pAddr; /* destination */
  226. u32 mem_sz; /* mem. size byte to occupied */
  227. u32 file_sz; /* file size byte to copy */
  228. };
  229. struct addr_param {
  230. int is_preload;
  231. int core;
  232. int iram_segment;
  233. int iram_num;
  234. u32 iram_hdr;
  235. u32 mblock;
  236. u32 iram_off;
  237. u32 phys_addr;
  238. u32 mem_sz;
  239. u32 ihdr_size;
  240. u32 preload_base;
  241. u32 preload_sz;
  242. };
  243. struct alg_info {
  244. u32 vpu_core; /* core index */
  245. u32 off; /* offset */
  246. u32 file_sz; /* file size byte to copy */
  247. char name[ALG_NAME_SIZE];
  248. };
  249. struct pre_info {
  250. u32 vpu_core;
  251. u32 off;
  252. u32 pAddr;
  253. u32 mem_sz;
  254. u32 file_sz;
  255. u32 flag;
  256. u32 info; // already aligned (to 4k or 64k) at packing stage
  257. u32 reserve;
  258. char name[ALG_NAME_SIZE];
  259. };
  260. struct img_info {
  261. int total_num;
  262. int hdr_size;
  263. int img_max;
  264. int pre_cnt;
  265. u32 dsp_num;
  266. u32 total_extra_sz;
  267. u32 total_alg_sz;
  268. void *head;
  269. char *name;
  270. };
  271. struct install_params {
  272. int img_max;
  273. u32 mblock;
  274. u32 alg_dst;
  275. u32 pre_dst;
  276. u32 iram_off;
  277. char *name;
  278. int *overlap;
  279. struct img_header *part_hdr;
  280. };
  281. struct prop_params {
  282. u32 dsp_num;
  283. u32 mblock;
  284. u32 aligned_size;
  285. u32 head_offset;
  286. u32 preload_offset;
  287. u32 iram_off;
  288. u32 alg_offset;
  289. u32 total_alg_sz;
  290. };
  291. struct img_header {
  292. int version;
  293. int build_date;
  294. int hdr_str[HDR_STR_SIZE / 4];
  295. int hdr_size;
  296. int img_size;
  297. int mem_size; // total preload segments size
  298. int segment_num;
  299. int seg_info; // offset
  300. int seg_size;
  301. int pre_num;
  302. int pre_info; // offset
  303. int pre_size;
  304. int alg_num;
  305. int alg_info; // offset
  306. int reserved[RESERVE_TOTAL];
  307. };
  308. /*****************************************************************************
  309. * Global variables *
  310. *****************************************************************************/
  311. static char *part_name[] = {"cam_vpu1", "cam_vpu2", "cam_vpu3"};
  312. static u32 vpu_m4u_addr[3][3] = {
  313. {0x7DA00000, 0x7DB00000, 0x7FF00000},
  314. {0x7E300000, 0x7E400000, 0x7FF00000},
  315. {0x7EC00000, 0x7ED00000, 0x7FF00000}
  316. };
  317. /*****************************************************************************
  318. * Functions/Interfaces *
  319. *****************************************************************************/
  320. static int is_dsp_addr(unsigned int addr, unsigned int core, unsigned int block)
  321. {
  322. return (addr & ADDR_MASK) == vpu_m4u_addr[core][block];
  323. }
  324. static inline int ascen(const int a, const int b)
  325. {
  326. return a == b ? 0 : a < b ? -1 : 1;
  327. }
  328. static inline int descen(const int a, const int b)
  329. {
  330. return -ascen(a, b);
  331. }
  332. static inline void swap(int *const a, int *const b)
  333. {
  334. int tmp;
  335. tmp = *a;
  336. *a = *b;
  337. *b = tmp;
  338. }
  339. int check_overlap(int *addr, int len)
  340. {
  341. int cnt = 0, i, cmp;
  342. int (*compare)(const int, const int);
  343. for (i = 0; i < len; ++i) {
  344. cmp = ascen(addr[i - 1], addr[i]);
  345. if (cmp == 0) {
  346. return true;
  347. }
  348. cnt += cmp;
  349. }
  350. compare = cnt <= 0 ? ascen : descen;
  351. for (i = 1; i < len; i+= cmp == -1 || i == 1 ? 1 : -1) {
  352. cmp = compare(addr[i - 1], addr[i]);
  353. if (cmp == 0) {
  354. return true;
  355. }
  356. if (cmp == 1) {
  357. swap(&addr[i], &addr[i - 1]);
  358. }
  359. }
  360. return false;
  361. }
  362. #ifdef DEVICE_TREE_SUPPORT
  363. static void vpu_prop(void *t, int offset, const char *type, unsigned int prop)
  364. {
  365. u64 value;
  366. value = cpu_to_fdt32(prop);
  367. fdt_setprop(t, offset, type, (char *)&value, sizeof(u32));
  368. }
  369. static void vpu_prop_array(void *t, int offset, const char *type, void *prop)
  370. {
  371. fdt_setprop(t, offset, type, (char *)prop,
  372. sizeof(fdt32_t) * NODE_CONT_LEN);
  373. }
  374. static int vpu_prop_subnode(void *fdt, int parent, char *name)
  375. {
  376. int offset;
  377. offset = fdt_subnode_offset(fdt, parent, name);
  378. if (offset < 0)
  379. offset = fdt_add_subnode(fdt, parent, name);
  380. if (offset < 0)
  381. LOG_CRI("fail to add subnode to fdt: %s\n", name);
  382. return offset;
  383. }
  384. #define COMP_MAX 32 // maximum length of VPU's compatible name at DTS
  385. // v1: legacy, kernel-4.x
  386. static int vpu_prop_create_v1(void *fdt, char *name, int core)
  387. {
  388. int offset = 0;
  389. char comp[COMP_MAX];
  390. // compatible name: "mediatek,vpu_core[012]"
  391. if (snprintf(comp, COMP_MAX, "mediatek,vpu_core%d", core) <= 0)
  392. return -EINVAL;
  393. LOG_INF("vpu%d: create \"%s\", \"%s\"\n", core, name, comp);
  394. offset = fdt_path_offset(fdt, "/");
  395. if (offset < 0) {
  396. LOG_CRI("fail to get fdt offset: %d\n", offset);
  397. return -EINVAL;
  398. }
  399. // kernel-4.x device nodes are located at "/"
  400. offset = vpu_prop_subnode(fdt, offset, name);
  401. if (offset < 0)
  402. return -EINVAL;
  403. fdt_setprop_string(fdt, offset, DT_COMP, comp);
  404. vpu_prop(fdt, offset, DT_ID, core);
  405. return offset;
  406. }
  407. // v2: common kernel, kernel-5.x
  408. static int vpu_prop_create_v2(void *fdt, char *name, int core)
  409. {
  410. int offset = 0;
  411. char comp[COMP_MAX];
  412. int i;
  413. // compatible name: "mediatek,mt68xx-vpu_core"
  414. if (snprintf(comp, COMP_MAX, "mediatek,%s-vpu_core", PLATFORM) <= 0)
  415. return -EINVAL;
  416. for (i = 0; i < COMP_MAX && comp[i]; i++)
  417. comp[i] = tolower(comp[i]);
  418. LOG_INF("vpu%d: create \"%s\", \"%s\"\n", core, name, comp);
  419. offset = fdt_path_offset(fdt, "/");
  420. if (offset < 0) {
  421. LOG_CRI("fail to get fdt offset: %d\n", offset);
  422. return -EINVAL;
  423. }
  424. // kernel-5.x (common kernel) device nodes are located at "/soc/"
  425. offset = vpu_prop_subnode(fdt, offset, "soc");
  426. offset = vpu_prop_subnode(fdt, offset, name);
  427. if (offset < 0)
  428. return -EINVAL;
  429. fdt_setprop_string(fdt, offset, DT_COMP, comp);
  430. vpu_prop(fdt, offset, DT_ID, core);
  431. return offset;
  432. }
  433. static int vpu_prop_off(void *t, int core)
  434. {
  435. bool soc = true;
  436. int off;
  437. char name[16];
  438. off = fdt_path_offset(t, "/soc");
  439. if (off < 0) {
  440. soc = false;
  441. off = fdt_path_offset(t, "/");
  442. if (off < 0)
  443. return -1;
  444. }
  445. snprintf(name, 16, "vpu_core%d", core);
  446. off = fdt_subnode_offset(t, off, name);
  447. if (off < 0) {
  448. LOG_INF("%s was not found, try to create\n", name);
  449. if (soc)
  450. off = vpu_prop_create_v2(t, name, core);
  451. else
  452. off = vpu_prop_create_v1(t, name, core);
  453. if (off < 0)
  454. LOG_INF("unable to create %s\n", name);
  455. }
  456. return off;
  457. }
  458. #endif
  459. static int set_property(struct prop_params *prop)
  460. {
  461. #ifdef DEVICE_TREE_SUPPORT
  462. void *fdt = NULL;
  463. unsigned int i = 0, j, dsp_num = 0;
  464. int offset;
  465. fdt32_t iram_prop[3][NODE_CONT_LEN] = {{0}, {0}, {0}};
  466. fdt32_t alg_prop[NODE_CONT_LEN] = {0};
  467. u32 vpu_iram_data[3][NODE_CONT_LEN] = {
  468. {0x00000000, IRAM_SEG_SZ, 0x02950000},
  469. {0x00000000, IRAM_SEG_SZ, 0x02950000 + IRAM_SEG_SZ},
  470. {0x00000000, IRAM_SEG_SZ, 0x02950000 + (IRAM_SEG_SZ * 2)}
  471. };
  472. u32 vpu_alg[NODE_CONT_LEN] = {
  473. 0x00000000, DEF_ALG_SZ, (DSP_BOOT_SZ * 3)};
  474. fdt = get_kernel_fdt();
  475. if (!fdt) {
  476. LOG_CRI("Null fdt\n");
  477. return -EINVAL;
  478. }
  479. dsp_num = prop->dsp_num;
  480. offset =vpu_prop_off(fdt, 0);
  481. if (offset < 0)
  482. return 0;
  483. vpu_alg[1] = prop->total_alg_sz;
  484. vpu_alg[2] = prop->alg_offset;
  485. for (i = 0; i < NODE_CONT_LEN; i++)
  486. alg_prop[i] = cpu_to_fdt32(vpu_alg[i]);
  487. for (i = 0; i < dsp_num; i++) {
  488. vpu_iram_data[i][2] =
  489. prop->alg_offset + prop->total_alg_sz + (i * IRAM_SEG_SZ);
  490. for (j = 0; j < NODE_CONT_LEN; j++)
  491. iram_prop[i][j] = cpu_to_fdt32(vpu_iram_data[i][j]);
  492. }
  493. vpu_prop(fdt, offset, DT_BIN, prop->mblock);
  494. vpu_prop(fdt, offset, DT_BIN_SZ, prop->aligned_size);
  495. vpu_prop(fdt, offset, DT_HEAD, prop->head_offset);
  496. vpu_prop(fdt, offset, DT_PRE_BIN, prop->preload_offset);
  497. vpu_prop_array(fdt, offset, DT_ALGO, (char *)&alg_prop);
  498. for (i = 0; i < dsp_num; i++) {
  499. offset = vpu_prop_off(fdt, i);
  500. if (offset < 0)
  501. continue;
  502. vpu_prop_array(fdt, offset, DT_IRAM_DAT,
  503. (char *)&iram_prop[i][0]);
  504. }
  505. #endif
  506. return 0;
  507. }
  508. static int img_auth(unsigned int cmd, char *name, void *addr, int len)
  509. {
  510. int ret = 0;
  511. #ifdef MTK_SECURITY_SW_SUPPORT
  512. unsigned int idx = 0;
  513. unsigned int time = 0;
  514. switch (cmd) {
  515. case AUTH_INIT:
  516. idx = get_policy_entry_idx(name);
  517. ret = get_vfy_policy(idx);
  518. if (ret) {
  519. mtk_wdt_restart();
  520. time = get_timer(0);
  521. ret = (int)sec_img_auth_init(name, name, 0);
  522. if (ret) {
  523. LOG_CRI("fail to verify %s cert (0x%x)\n",
  524. name, ret);
  525. assert(0);
  526. }
  527. LOG_CRI("[SBC] %s cert vfy pass(%d ms)\n",
  528. name, (unsigned int)get_timer(time));
  529. #ifdef MTK_SECURITY_ANTI_ROLLBACK
  530. ret = sec_rollback_check(1);
  531. if (ret) {
  532. LOG_CRI("fail to check %s version (0x%x)\n",
  533. name, ret);
  534. assert(0);
  535. }
  536. #endif
  537. }
  538. break;
  539. case AUTH_DO:
  540. mtk_wdt_restart();
  541. time = get_timer(0);
  542. ret = (int)sec_img_auth(addr, len);
  543. if (ret) {
  544. LOG_CRI("fail to check %s hash (0x%x)\n", name, ret);
  545. assert(0);
  546. }
  547. LOG_CRI("[SBC] %s vfy pass(%d ms)\n", name,
  548. (unsigned int)get_timer(time));
  549. break;
  550. default :
  551. break;
  552. }
  553. #endif
  554. return ret;
  555. }
  556. static unsigned int get_addr(struct addr_param *param)
  557. {
  558. int offset = 0;
  559. u32 addr = param->phys_addr;
  560. u32 mblock = param->mblock;
  561. u32 *iram_num = NULL;
  562. struct iram_desc *desc = NULL;
  563. static u32 iram1_seg = MAIN_IRAM_DESC_HDR_SIZE;
  564. static u32 iram2_seg = MAIN_IRAM_DESC_HDR_SIZE;
  565. static u32 iram3_seg = MAIN_IRAM_DESC_HDR_SIZE;
  566. static u32 pre_seg = 0;
  567. if (is_dsp_addr(addr, CORE0, MAIN_PROG)) {
  568. offset = (int)(addr - vpu_m4u_addr[CORE0][MAIN_PROG]);
  569. mblock += DSP_RST_VEC_SZ;
  570. } else if (is_dsp_addr(addr, CORE1, MAIN_PROG)) {
  571. offset = (int)(addr - vpu_m4u_addr[CORE1][MAIN_PROG]);
  572. mblock += (DSP_BOOT_SZ + DSP_RST_VEC_SZ);
  573. } else if (is_dsp_addr(addr, CORE2, MAIN_PROG)) {
  574. offset = (int)(addr - vpu_m4u_addr[CORE2][MAIN_PROG]);
  575. mblock += ((DSP_BOOT_SZ << 1) + DSP_RST_VEC_SZ);
  576. } else if (is_dsp_addr(addr, CORE0, RESET_VEC)) {
  577. offset = (int)(addr - vpu_m4u_addr[CORE0][RESET_VEC]);
  578. } else if (is_dsp_addr(addr, CORE1, RESET_VEC)) {
  579. offset = (int)(addr - vpu_m4u_addr[CORE1][RESET_VEC]);
  580. mblock += DSP_BOOT_SZ;
  581. } else if (is_dsp_addr(addr, CORE2, RESET_VEC)) {
  582. offset = (int)(addr - vpu_m4u_addr[CORE2][RESET_VEC]);
  583. mblock += (DSP_BOOT_SZ << 1);
  584. } else if (is_dsp_addr(addr, CORE0, IRAM) && !param->is_preload) {
  585. param->iram_segment = 1;
  586. switch (param->core) {
  587. case VPU_CORE_0:
  588. offset = iram1_seg;
  589. mblock += param->iram_off;
  590. iram_num = (u32 *)mblock;
  591. iram1_seg += ALIGN(param->mem_sz, ALIGN_16);
  592. break;
  593. case VPU_CORE_1:
  594. offset = iram2_seg;
  595. mblock += (param->iram_off + IRAM_SEG_SZ);
  596. iram_num = (u32 *)mblock;
  597. iram2_seg += ALIGN(param->mem_sz, ALIGN_16);
  598. break;
  599. case VPU_CORE_2:
  600. offset = iram3_seg;
  601. mblock += param->iram_off + (IRAM_SEG_SZ << 1);
  602. iram_num = (u32 *)mblock;
  603. iram3_seg += ALIGN(param->mem_sz, ALIGN_16);
  604. break;
  605. default:
  606. LOG_CRI("invalid segment core 0x%x\n", param->core);
  607. return 0;
  608. }
  609. param->iram_num = (*iram_num);
  610. //update iram descriptor
  611. desc = (void *)(mblock + sizeof(int));
  612. desc[param->iram_num].offset = offset;
  613. desc[param->iram_num].addr = addr;
  614. desc[param->iram_num].size = param->mem_sz;
  615. *iram_num = (param->iram_num + 1);
  616. } else if (param->is_preload) {
  617. if (is_dsp_addr(addr, CORE0, IRAM)) {
  618. param->iram_segment = 1;
  619. mblock += param->iram_off;
  620. param->iram_off += param->mem_sz;
  621. } else {
  622. param->iram_segment = 0;
  623. if (addr == 0xFFFFFFFF) {
  624. pre_seg += param->preload_sz;
  625. mblock += pre_seg;
  626. param->iram_off = pre_seg + param->ihdr_size;
  627. pre_seg += param->mem_sz;
  628. } else {
  629. mblock += (pre_seg +
  630. (addr - param->preload_base));
  631. }
  632. }
  633. if (param->iram_hdr && param->iram_segment) {
  634. iram_num = (unsigned int *)param->iram_hdr;
  635. param->iram_num = (*iram_num);
  636. desc = (void *)(param->iram_hdr + sizeof(int));
  637. }
  638. } else {
  639. LOG_CRI("invalid segment addr 0x%x\n", addr);
  640. return 0;
  641. }
  642. return (mblock + offset);
  643. }
  644. static int install_main(struct install_params *install)
  645. {
  646. struct img_header *part_hdr = install->part_hdr;
  647. struct addr_param param;
  648. int j, ret = 0;
  649. int offset = 0, read_size = 0, zero = 0, info = part_hdr->seg_info;
  650. u32 dst = 0;
  651. struct seg_info *seg = (void *)((unsigned long)part_hdr + info);
  652. memset(&param, 0, sizeof(struct addr_param));
  653. for (j = 0; j < part_hdr->segment_num; j++) {
  654. offset = seg->off + part_hdr->hdr_size;
  655. read_size = seg->file_sz;
  656. param.core = seg->vpu_core;
  657. param.phys_addr = seg->pAddr;
  658. param.mem_sz = seg->mem_sz;
  659. param.mblock = install->mblock;
  660. param.iram_off = install->iram_off;
  661. param.iram_segment = 0;
  662. if (!(dst = get_addr(&param))) {
  663. ret = -EINVAL;
  664. break;
  665. }
  666. if (param.iram_segment) {
  667. LOG_INF("seg[%2d] [0x%05x:0x%05x] -> [0x%x/0x%x]: iram[0x%x:%d]\n",
  668. j, offset, read_size, seg->pAddr, dst,
  669. seg->vpu_core, param.iram_num);
  670. } else {
  671. LOG_INF("seg[%2d] [0x%05x:0x%05x] -> [0x%x/0x%x]\n",
  672. j, offset, read_size, seg->pAddr, dst);
  673. }
  674. if (seg->file_sz > 0) {
  675. if (offset + read_size > install->img_max) {
  676. LOG_CRI("%s partition offset error, offset 0x%x, read_size 0x%x\n",
  677. install->name, offset, read_size);
  678. ret = -EINVAL;
  679. break;
  680. } else {
  681. memcpy((void *)dst,
  682. (void *)((u8 *)part_hdr + offset),
  683. read_size);
  684. }
  685. }
  686. zero = seg->mem_sz - seg->file_sz;
  687. if (zero) {
  688. dst += seg->file_sz;
  689. LOG_INF("%-7s [0x%x:0x%x]\n", "zero", dst, zero);
  690. memset((void *)(dst), 0, zero);
  691. }
  692. seg++;
  693. }
  694. return ret;
  695. }
  696. static int install_preload(struct install_params *install)
  697. {
  698. struct img_header *part_hdr = install->part_hdr;
  699. struct addr_param param;
  700. int j, ret = 0, idx = install->overlap[0];
  701. int offset = 0, read_size = 0, zero = 0, info = part_hdr->pre_info;
  702. u32 dst = 0;
  703. struct pre_info *pre = (void *)((unsigned long)part_hdr + info);
  704. memset(&param, 0, sizeof(struct addr_param));
  705. for (j = 0; j < part_hdr->pre_num; j++) {
  706. offset = pre->off + part_hdr->hdr_size + part_hdr->seg_size;
  707. read_size = (pre->pAddr == (unsigned int)0xFFFFFFFF) ?
  708. pre->mem_sz : pre->file_sz;
  709. param.is_preload = true;
  710. param.core = pre->vpu_core;
  711. param.phys_addr = pre->pAddr;
  712. param.mem_sz = pre->file_sz;
  713. param.mblock = install->pre_dst;
  714. param.iram_segment = 0;
  715. param.iram_hdr = 0;
  716. param.ihdr_size = (pre->pAddr == (unsigned int)0xFFFFFFFF) ?
  717. pre->mem_sz : 0;
  718. if ((pre->flag & EXE_SEG) == EXE_SEG) {
  719. param.phys_addr = pre->pAddr & 0xFFF00000;
  720. param.preload_base = param.phys_addr;
  721. param.preload_sz = pre->info;
  722. install->overlap[idx] = pre->pAddr & 0xFFF00000;
  723. install->overlap[0] = ++idx;
  724. }
  725. if (!(dst = get_addr(&param))) {
  726. ret = -EINVAL;
  727. break;
  728. }
  729. if (param.iram_segment) {
  730. LOG_INF("pre[%2d] [0x%05x:0x%06x] -> [0x%x/0x%x]: iram[0x%x:%d]\n",
  731. j, offset, read_size, pre->pAddr, dst,
  732. pre->vpu_core, param.iram_num);
  733. } else {
  734. if (pre->pAddr == 0xFFFFFFFF) {
  735. param.iram_hdr = dst;
  736. LOG_INF("pre[%2d] [0x%05x:0x%06x] -> [0x%x/0x%x]: iram[0x%x] head\n",
  737. j, offset, pre->file_sz, pre->pAddr,
  738. dst, pre->vpu_core);
  739. } else {
  740. param.iram_hdr = 0;
  741. LOG_INF("pre[%2d] [0x%05x:0x%06x] -> [0x%x/0x%x]\n",
  742. j, offset, read_size, pre->pAddr, dst);
  743. }
  744. }
  745. if (pre->file_sz > 0) {
  746. if (offset + read_size > install->img_max) {
  747. LOG_CRI("%s partition offset error, offset 0x%x, read_size 0x%x\n",
  748. install->name, offset, read_size);
  749. ret = -EINVAL;
  750. break;
  751. } else {
  752. memcpy((void *)dst,
  753. (void *)((u8 *)part_hdr + offset),
  754. read_size);
  755. }
  756. }
  757. zero = pre->mem_sz - pre->file_sz;
  758. pre->off = dst - install->mblock;
  759. if (zero && pre->pAddr != 0xFFFFFFFF) {
  760. dst += pre->file_sz;
  761. LOG_INF("%-7s [0x%x:0x%x]\n", "zero", dst, zero);
  762. memset((void *)(dst), 0, zero);
  763. }
  764. pre++;
  765. }
  766. return ret;
  767. }
  768. static int install_algo(struct install_params *install)
  769. {
  770. struct img_header *part_hdr = install->part_hdr;
  771. int j, ret = 0;
  772. int offset = 0, read_size = 0, info = part_hdr->alg_info;
  773. u32 dst = install->alg_dst;
  774. struct alg_info *alg = (void *)((unsigned long)part_hdr + info);
  775. for (j = 0; j < part_hdr->alg_num; j++) {
  776. int new_offset = (int)(dst - install->mblock);
  777. offset = alg->off + part_hdr->hdr_size;
  778. read_size = alg->file_sz;
  779. LOG_INF("alg[%2d] [0x%06x:0x%06x] -> [0x%x] => 0x%x\n",
  780. j, offset, read_size, dst, new_offset);
  781. if (offset + read_size > install->img_max) {
  782. LOG_CRI("%s partition offset error, offset 0x%x, read_size 0x%x\n",
  783. install->name, offset, read_size);
  784. ret = -EINVAL;
  785. break;
  786. } else {
  787. memcpy((void *)dst,
  788. (void *)((u8 *)part_hdr + offset),
  789. read_size);
  790. }
  791. // change alg offset in partition header for driver to get real offset
  792. alg->off = new_offset;
  793. dst += ALIGN(alg->file_sz, ALIGN_16);
  794. alg++;
  795. }
  796. install->alg_dst = dst;
  797. return ret;
  798. }
  799. void *read_img(void)
  800. {
  801. int i, len, need_auth = 0, pre_cnt = 0, alg_sum = 0, dsp_num = 0;
  802. int total_num = countof(part_name);
  803. char *name = NULL;
  804. int max = 0;
  805. unsigned long bin_size = 0, hdr_total = 0;
  806. struct img_header *head = NULL;
  807. struct img_info *info = calloc(total_num, sizeof(struct img_info));
  808. unsigned int img_buf = (unsigned int)SCRATCH_ADDR +
  809. SCRATCH_SIZE - DEF_RSRV_SIZE; //start from tail to avoid polluting kernel zimage
  810. void *part = (void *)img_buf;
  811. if (!info) {
  812. LOG_CRI("calloc fail\n");
  813. return NULL;
  814. }
  815. for (i = 0; i < total_num; i++) {
  816. info[i].total_num = total_num;
  817. name = part_name[i];
  818. max = partition_get_size_by_name(name);
  819. need_auth = img_auth(AUTH_INIT, name, NULL, 0);
  820. if ((len = mboot_common_load_part(
  821. name, name, (unsigned long)part)) < 0) {
  822. LOG_CRI("%s partition read error. len = %d\n",
  823. name, len);
  824. free(info);
  825. return NULL;
  826. }
  827. if (need_auth)
  828. img_auth(AUTH_DO, name, part, len);
  829. head = part;
  830. head->hdr_str[HDR_STR_SIZE/4 - 1] = 0;
  831. if (head->img_size > max) {
  832. LOG_CRI("img size(0x%x) exceeds!\n", head->img_size);
  833. free(info);
  834. return NULL;
  835. }
  836. if (MAJOR_VER(VERSION) != MAJOR_VER(head->version)) {
  837. LOG_CRI("version mismatch (%x/[%d]%x)\n",
  838. VERSION, i, head->version);
  839. free(info);
  840. return NULL;
  841. }
  842. info[i].head = head;
  843. info[i].name = name;
  844. info[i].img_max = max;
  845. bin_size += head->mem_size;
  846. LOG_INF("total preload mem size: 0x%x\n", head->mem_size);
  847. hdr_total += head->hdr_size;
  848. pre_cnt += head->pre_num;
  849. part += max;
  850. // cam_vpu1.img carries only main program & preload and does not carry normal libraries
  851. if (i)
  852. alg_sum += head->reserved[TOTAL_ALG_SZ];
  853. else
  854. dsp_num = head->reserved[TOTAL_DSP];
  855. }
  856. info[0].hdr_size = ALIGN(hdr_total, ALIGN_32);
  857. info[0].pre_cnt = pre_cnt;
  858. info[0].dsp_num = dsp_num ? dsp_num : 3;
  859. info[0].total_alg_sz = ALIGN(alg_sum, ALIGN_64K);
  860. bin_size = ALIGN(bin_size, ALIGN_4K);
  861. info[0].total_extra_sz = bin_size;
  862. return info;
  863. }
  864. int mt_load_vpu(void)
  865. {
  866. int i, ret = 0, num;
  867. int *overlap = NULL;
  868. u32 *pIramNum;
  869. u32 mblock, head_dst, iram_off = 0, offset = 0, pre_dst = 0;
  870. u32 extra_size = 0, mblock_size = 0, aligned_size = 0;
  871. u32 alg_offset = 0;
  872. struct img_info *img = NULL;
  873. struct img_header *head = NULL;
  874. struct install_params params;
  875. struct prop_params prop;
  876. if (!(img = read_img())) {
  877. ret = -EINVAL;
  878. goto exit;
  879. }
  880. overlap = calloc((img->pre_cnt + 1), sizeof(int));
  881. extra_size = img->total_extra_sz;
  882. LOG_INF("extra_size: 0x%x\n", extra_size);
  883. mblock_size = (DSP_BOOT_SZ + IRAM_SEG_SZ) * img->dsp_num +
  884. img->total_alg_sz + img->hdr_size + extra_size + SPARE_SZ;
  885. aligned_size = ALIGN(mblock_size, ALIGN_64K);
  886. if (IS_ALIGNED(aligned_size, ALIGN_2M))
  887. aligned_size += ALIGN_64K;
  888. mblock = (u32)mblock_reserve_ext(&g_boot_arg->mblock_info,
  889. (u64)aligned_size, ADDR_ALIGN, ADDR_MAX, 0, "vpu_binary");
  890. if (!mblock || !overlap) {
  891. LOG_CRI("vpu memory allocation failed.\n");
  892. ret = -ENOMEM;
  893. goto exit;
  894. }
  895. memset((void *)(mblock), 0, mblock_size);
  896. alg_offset = img->dsp_num * DSP_BOOT_SZ;
  897. iram_off = alg_offset + img->total_alg_sz;
  898. offset = mblock_size - img->hdr_size - extra_size;
  899. head_dst = mblock + offset;
  900. pre_dst = ALIGN(mblock + mblock_size, ALIGN_64K) - extra_size;
  901. LOG_INF("lk ver: %x\n", VERSION);
  902. LOG_INF("mblk:[0x%x:0x%x] | head:0x%x | alg: 0x%x | pre: 0x%x\n",
  903. mblock, mblock_size, head_dst, mblock + alg_offset,
  904. pre_dst);
  905. pIramNum = (u32 *)(mblock + iram_off);
  906. *pIramNum = 0;
  907. pIramNum = (u32 *)(mblock + iram_off + IRAM_SEG_SZ);
  908. *pIramNum = 0;
  909. pIramNum = (u32 *)(mblock + iram_off + (IRAM_SEG_SZ << 1));
  910. *pIramNum = 0;
  911. num = img->total_num;
  912. memset(&params, 0, sizeof(struct install_params));
  913. memset(&prop, 0, sizeof(struct prop_params));
  914. overlap[0] = 1;
  915. params.mblock = mblock;
  916. params.iram_off = iram_off;
  917. params.pre_dst = pre_dst;
  918. params.alg_dst = mblock + alg_offset;
  919. params.overlap = overlap;
  920. memset(&prop, 0, sizeof(struct prop_params));
  921. prop.dsp_num = img->dsp_num;
  922. prop.iram_off = iram_off;
  923. prop.alg_offset = alg_offset;
  924. prop.total_alg_sz = img->total_alg_sz;
  925. prop.mblock = mblock;
  926. prop.aligned_size = aligned_size;
  927. prop.head_offset = offset;
  928. prop.preload_offset = pre_dst - mblock;
  929. if ((ret = set_property(&prop)) < 0)
  930. goto exit;
  931. for (i = 0 ; i < num ; i++) {
  932. params.img_max = img[i].img_max;
  933. params.name = img[i].name;
  934. head = params.part_hdr = img[i].head;
  935. LOG_INF("%s| v:%x str:%s sz:0x%x/0x%x s:%d a:%d v:%d\n",
  936. params.name, head->version, (char *)head->hdr_str,
  937. head->hdr_size, head->mem_size, head->segment_num,
  938. head->alg_num, head->pre_num);
  939. if ((ret = install_main(&params)))
  940. goto exit;
  941. if ((ret = install_preload(&params)))
  942. goto exit;
  943. if ((ret = install_algo(&params)))
  944. goto exit;
  945. LOG_INF("copy %s header(0x%X) to 0x%x\n",
  946. params.name, head->hdr_size, head_dst);
  947. memcpy((void *)head_dst, head, head->hdr_size);
  948. head_dst += head->hdr_size;
  949. }
  950. if (overlap[0] - 1) {
  951. if (check_overlap(&overlap[1], overlap[0] - 1))
  952. LOG_CRI("preload overlap\n");
  953. }
  954. #if ENABLE_VPU_EMI_PROTECTION
  955. /*
  956. * setup EMI MPU
  957. * domain 0: AP
  958. * domain 5: VPU
  959. */
  960. /*clean dcache & icache before set up EMI MPU*/
  961. arch_sync_cache_range((addr_t)mblock, aligned_size);
  962. struct emi_region_info_t region_info;
  963. region_info.start = (unsigned long long)mblock;
  964. region_info.end = (unsigned long long)(mblock + aligned_size - 1);
  965. region_info.region = VPU_EMI_REGION_ID;
  966. SET_ACCESS_PERMISSION(region_info.apc, UNLOCK,
  967. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  968. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  969. FORBIDDEN, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
  970. FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW_NSEC_R);
  971. emi_mpu_set_protection(&region_info);
  972. #endif
  973. exit:
  974. if (img)
  975. free(img);
  976. if (overlap)
  977. free(overlap);
  978. return ret;
  979. }