ccci_util_lib_load_img.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  1. #include <linux/module.h>
  2. #include <linux/device.h>
  3. #include <linux/fs.h>
  4. #include <linux/cdev.h>
  5. #include <linux/interrupt.h>
  6. #include <linux/spinlock.h>
  7. #include <linux/uaccess.h>
  8. #include <linux/mm.h>
  9. #include <linux/kfifo.h>
  10. #include <linux/firmware.h>
  11. #include <linux/syscalls.h>
  12. #include <linux/uaccess.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/proc_fs.h>
  15. #include <linux/seq_file.h>
  16. #include <linux/of.h>
  17. #ifdef CONFIG_OF
  18. #include <linux/of_fdt.h>
  19. #endif
  20. #include <asm/setup.h>
  21. #include <linux/atomic.h>
  22. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  23. #include <sec_osal.h>
  24. #include <sec_export.h>
  25. #endif
  26. #include <mt-plat/mt_boot_common.h>
  27. #include <mt-plat/mt_ccci_common.h>
  28. #include "ccci_util_log.h"
  29. #include "ccci_util_lib_main.h"
  30. #if defined(CONFIG_MTK_AEE_FEATURE)
  31. #include <mt-plat/aee.h>
  32. #endif
  33. #define ENABLE_MEM_SIZE_CHECK
  34. #define MAX_MD_NUM (6) /* Max 4 internal + Max 2 exteranl */
  35. /*==================================================== */
  36. /* Image process section */
  37. /*==================================================== */
  38. #define IMG_POST_FIX_LEN (32)
  39. #define AP_PLATFORM_LEN (16)
  40. /*Note: must sync with sec lib, if ccci and sec has dependency change */
  41. #define CURR_SEC_CCCI_SYNC_VER (1)
  42. static char *type_str[] = {[md_type_invalid] = "invalid",
  43. [modem_2g] = "2g",
  44. [modem_3g] = "3g",
  45. [modem_wg] = "wg",
  46. [modem_tg] = "tg",
  47. [modem_lwg] = "lwg",
  48. [modem_ltg] = "ltg",
  49. [modem_sglte] = "sglte",
  50. [modem_ultg] = "ultg",
  51. [modem_ulwg] = "ulwg",
  52. [modem_ulwtg] = "ulwtg",
  53. [modem_ulwcg] = "ulwcg",
  54. [modem_ulwctg] = "ulwctg",
  55. [modem_ulttg] = "ulttg",
  56. [modem_ulfwg] = "ulfwg",
  57. [modem_ulfwcg] = "ulfwcg"
  58. };
  59. static int curr_ubin_id;
  60. static char *product_str[] = {[INVALID_VARSION] = INVALID_STR,
  61. [DEBUG_VERSION] = DEBUG_STR,
  62. [RELEASE_VERSION] = RELEASE_STR
  63. };
  64. static struct md_check_header md_img_header[MAX_MD_NUM];
  65. /*static struct md_check_header_v3 md_img_header_v3[MAX_MD_NUM];*/
  66. static struct md_check_header_v4 md_img_header_v4[MAX_MD_NUM];
  67. static struct md_check_header_v5 md_img_header_v5[MAX_MD_NUM];
  68. /*static struct ccci_image_info img_info[MAX_MD_NUM][IMG_NUM]; */
  69. char md_img_info_str[MAX_MD_NUM][256];
  70. /*--- MD header check ------------ */
  71. static int check_dsp_header(int md_id, void *parse_addr, struct ccci_image_info *image)
  72. {
  73. return 0;
  74. }
  75. int scan_image_list(int md_id, char fmt[], int out_img_list[], int img_list_size)
  76. {
  77. int i;
  78. int img_num = 0;
  79. char full_path[64] = { 0 };
  80. char img_name[32] = { 0 };
  81. struct file *filp = NULL;
  82. for (i = 0; i < (sizeof(type_str) / sizeof(char *)); i++) {
  83. snprintf(img_name, 32, fmt, md_id + 1, type_str[i]);
  84. /* Find at CIP first */
  85. snprintf(full_path, 64, "%s%s", CONFIG_MODEM_FIRMWARE_CIP_PATH, img_name);
  86. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find:%s\n", full_path);
  87. filp = filp_open(full_path, O_RDONLY, 0644);
  88. if (IS_ERR(filp)) {
  89. /* Find at default */
  90. snprintf(full_path, 64, "%s%s", CONFIG_MODEM_FIRMWARE_PATH, img_name);
  91. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find:%s\n", full_path);
  92. filp = filp_open(full_path, O_RDONLY, 0644);
  93. if (IS_ERR(filp)) {
  94. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "%s not found(%d,%d)\n", full_path, img_num, i);
  95. continue;
  96. }
  97. }
  98. /* Run here means open image success */
  99. filp_close(filp, NULL);
  100. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Image:%s found\n", full_path);
  101. if (img_num < img_list_size)
  102. out_img_list[img_num] = i;
  103. img_num++;
  104. }
  105. return img_num;
  106. }
  107. static int check_md_header_v3(int md_id, void *parse_addr, struct ccci_image_info *image)
  108. {
  109. int ret;
  110. bool md_type_check = false;
  111. bool md_plat_check = false;
  112. bool md_sys_match = false;
  113. bool md_size_check = false;
  114. int idx;
  115. unsigned int md_size;
  116. unsigned char *start, *ptr;
  117. int region_id, domain_id; /* add for v4 v5 */
  118. /* struct md_check_header_v3 *head = &md_img_header_v3[md_id]; */
  119. struct md_check_header_v4 *head = &md_img_header_v4[md_id];
  120. get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);
  121. /*memcpy(head, (void*)(parse_addr - sizeof(struct md_check_header_v3)), sizeof(struct md_check_header_v3)); */
  122. start = (unsigned char *)(head);
  123. ptr = (unsigned char *)(parse_addr - sizeof(struct md_check_header_v3));
  124. for (idx = 0; idx < sizeof(struct md_check_header_v3); idx++)
  125. *start++ = *ptr++;
  126. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3 %d***************************\n",
  127. (int)sizeof(struct md_check_header_v3));
  128. ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
  129. if (ret) {
  130. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist!\n");
  131. ret = -CCCI_ERR_LOAD_IMG_CHECK_HEAD;
  132. } else {
  133. if (head->header_verno < 3) {
  134. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n",
  135. head->header_verno);
  136. } else {
  137. #ifdef ENABLE_2G_3G_CHECK
  138. if ((head->image_type != 0) && (head->image_type == md->config.load_type))
  139. md_type_check = true;
  140. #else
  141. md_type_check = true;
  142. #endif
  143. #ifdef ENABLE_CHIP_VER_CHECK
  144. if (!strncmp(head->platform, ccci_get_ap_platform(), AP_PLATFORM_LEN))
  145. md_plat_check = true;
  146. #else
  147. md_plat_check = true;
  148. #endif
  149. if (head->bind_sys_id == (md_id + 1))
  150. md_sys_match = true;
  151. #ifdef ENABLE_MEM_SIZE_CHECK
  152. if (head->header_verno >= 2) {
  153. /*md_size = md->mem_layout.md_region_size; */
  154. if (head->mem_size == md_size) {
  155. md_size_check = true;
  156. } else if (head->mem_size < md_size) {
  157. md_size_check = true;
  158. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  159. "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
  160. head->mem_size, md_size);
  161. }
  162. image->img_info.mem_size = head->mem_size;
  163. image->ap_info.mem_size = md_size;
  164. } else {
  165. md_size_check = true;
  166. }
  167. #else
  168. md_size_check = true;
  169. #endif
  170. if ((md_id == MD_SYS1) && (head->image_type >= modem_ultg) && (head->image_type <= MAX_IMG_NUM))
  171. curr_ubin_id = head->image_type;
  172. image->ap_info.image_type = type_str[head->image_type];
  173. image->ap_info.platform = ccci_get_ap_platform();
  174. image->img_info.image_type = type_str[head->image_type];
  175. image->img_info.platform = head->platform;
  176. image->img_info.build_time = head->build_time;
  177. image->img_info.build_ver = head->build_ver;
  178. image->img_info.product_ver = product_str[head->product_ver];
  179. image->img_info.version = head->product_ver;
  180. image->img_info.header_verno = head->header_verno;
  181. if (md_type_check && md_plat_check && md_sys_match && md_size_check) {
  182. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
  183. } else {
  184. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
  185. if (!md_type_check)
  186. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");
  187. if (!md_plat_check)
  188. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");
  189. if (!md_sys_match)
  190. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n",
  191. md_id + 1);
  192. if (!md_size_check)
  193. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  194. "[Reason]MD mem size mis-match to AP setting!\n");
  195. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  196. }
  197. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type,
  198. image->ap_info.image_type);
  199. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform,
  200. image->ap_info.platform);
  201. if (head->header_verno >= 2) {
  202. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",
  203. image->img_info.mem_size, image->ap_info.mem_size);
  204. if (head->md_img_size) {
  205. if (image->size >= head->md_img_size)
  206. image->size = head->md_img_size;
  207. else {
  208. char title[50];
  209. char info[100];
  210. snprintf(title, sizeof(title),
  211. "MD%d mem size smaller than image header setting", md_id + 1);
  212. snprintf(info, sizeof(info),
  213. "MD%d mem size(0x%x)<header size(0x%x),please check memory config in <chip>.dtsi",
  214. md_id + 1, image->size, head->md_img_size);
  215. #if defined(CONFIG_MTK_AEE_FEATURE)
  216. aed_md_exception_api(NULL, 0, (const int *)info, sizeof(info),
  217. (const char *)title, DB_OPT_DEFAULT);
  218. #endif
  219. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  220. "[Reason]MD image size mis-match to AP!\n");
  221. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  222. }
  223. image->ap_info.md_img_size = image->size;
  224. image->img_info.md_img_size = head->md_img_size;
  225. }
  226. /* else {image->size -= 0x1A0;} workaround for md not check in check header */
  227. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n",
  228. head->md_img_size, image->size);
  229. }
  230. if (head->header_verno >= 3) {
  231. image->dsp_offset = head->dsp_img_offset;
  232. image->dsp_size = head->dsp_img_size;
  233. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset=%x size=%x\n", image->dsp_offset,
  234. image->dsp_size);
  235. if (image->dsp_offset == 0xCDCDCDAA) {
  236. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP on EMI disabled\n");
  237. } else if (((image->dsp_offset&0xFFFF) != 0) && (head->header_verno == 3)) {
  238. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset not 64KB align\n");
  239. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  240. } else if (image->dsp_offset + image->dsp_size > md_size) {
  241. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image size too large %x\n", md_size);
  242. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  243. }
  244. } else {
  245. image->dsp_offset = 0;
  246. }
  247. if (head->header_verno >= 4) { /* RMPU only avilable after check header v4 */
  248. for (region_id = 0; region_id <= MPU_REGION_INFO_ID_LAST; region_id++) {
  249. image->rmpu_info.region_info[region_id].region_offset =
  250. head->region_info[region_id].region_offset;
  251. image->rmpu_info.region_info[region_id].region_size =
  252. head->region_info[region_id].region_size;
  253. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  254. "[CCCI_UTIL] load_image: check_header_v4, region(%d): size = %x , offset = %x\n",
  255. region_id, head->region_info[region_id].region_size,
  256. head->region_info[region_id].region_offset);
  257. }
  258. for (domain_id = 0; domain_id < MPU_DOMAIN_INFO_ID_TOTAL_NUM; domain_id++) {
  259. image->rmpu_info.domain_attr[domain_id] = head->domain_attr[domain_id];
  260. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  261. "[CCCI_UTIL] load_image: check_header_v4, domain(%d): attr = %x\n",
  262. domain_id, head->domain_attr[domain_id]);
  263. }
  264. }
  265. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",
  266. image->img_info.build_ver, image->img_info.build_time);
  267. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n", image->img_info.product_ver);
  268. }
  269. }
  270. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3***************************\n");
  271. return ret;
  272. }
  273. static int md_check_header_parser(int md_id, void *parse_addr, struct ccci_image_info *image)
  274. {
  275. int ret;
  276. bool md_type_check = false;
  277. bool md_plat_check = false;
  278. bool md_sys_match = false;
  279. bool md_size_check = false;
  280. unsigned int md_size;
  281. unsigned int header_size;
  282. int idx, header_up;
  283. unsigned char *start, *ptr;
  284. int region_id, domain_id; /* add for v4 v5 */
  285. struct md_check_header_struct *head = NULL;
  286. struct md_check_header *headv12 = NULL;
  287. struct md_check_header_v4 *headv34 = NULL;
  288. struct md_check_header_v5 *headv5 = NULL;
  289. get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);
  290. header_size = *(((unsigned int *)parse_addr) - 1);
  291. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "MD image header size = %d\n", header_size);
  292. if (header_size == sizeof(struct md_check_header_v3)) { /* v3, v4 */
  293. headv34 = &md_img_header_v4[md_id];
  294. headv12 = (struct md_check_header *)headv34;
  295. head = (struct md_check_header_struct *)headv34;
  296. header_up = 4;
  297. } else if (header_size == sizeof(struct md_check_header_v5)) {/* v5 */
  298. headv5 = &md_img_header_v5[md_id];
  299. headv34 = (struct md_check_header_v4 *)headv5;
  300. headv12 = (struct md_check_header *)headv5;
  301. head = (struct md_check_header_struct *)headv5;
  302. header_up = 5;
  303. } else { /* Default Load v1/2 */
  304. /* if (header_size == sizeof(struct md_check_header)) {*//* v1, v2 */
  305. headv12 = &md_img_header[md_id];
  306. head = (struct md_check_header_struct *)headv12;
  307. header_up = 2;
  308. }
  309. start = (unsigned char *)(head);
  310. ptr = (unsigned char *)(parse_addr - header_size);
  311. for (idx = 0; idx < header_size; idx++)
  312. *start++ = *ptr++;
  313. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check v%d %d***************************\n",
  314. (int)head->header_verno, (int)header_size);
  315. ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
  316. if (ret) {
  317. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist!\n");
  318. ret = -CCCI_ERR_LOAD_IMG_CHECK_HEAD;
  319. } else if (head->header_verno > header_up) {
  320. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n",
  321. head->header_verno);
  322. ret = -CCCI_ERR_LOAD_IMG_CHECK_HEAD;
  323. } else {
  324. #ifdef ENABLE_2G_3G_CHECK
  325. if ((head->image_type != 0) && (head->image_type == md->config.load_type))
  326. md_type_check = true;
  327. #else
  328. md_type_check = true;
  329. #endif
  330. #ifdef ENABLE_CHIP_VER_CHECK
  331. if (!strncmp(head->platform, ccci_get_ap_platform(), AP_PLATFORM_LEN))
  332. md_plat_check = true;
  333. #else
  334. md_plat_check = true;
  335. #endif
  336. if (head->bind_sys_id == (md_id + 1))
  337. md_sys_match = true;
  338. #ifdef ENABLE_MEM_SIZE_CHECK
  339. if (head->header_verno >= 2) {
  340. /*md_size = md->mem_layout.md_region_size; */
  341. if (head->mem_size == md_size) {
  342. md_size_check = true;
  343. } else if (head->mem_size < md_size) {
  344. md_size_check = true;
  345. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  346. "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
  347. head->mem_size, md_size);
  348. }
  349. image->img_info.mem_size = head->mem_size;
  350. image->ap_info.mem_size = md_size;
  351. } else {
  352. md_size_check = true;
  353. }
  354. #else
  355. md_size_check = true;
  356. #endif
  357. if ((md_id == MD_SYS1) && (head->image_type >= modem_ultg) && (head->image_type <= MAX_IMG_NUM))
  358. curr_ubin_id = head->image_type;
  359. image->ap_info.image_type = type_str[head->image_type];
  360. image->ap_info.platform = ccci_get_ap_platform();
  361. image->img_info.image_type = type_str[head->image_type];
  362. image->img_info.platform = head->platform;
  363. image->img_info.build_time = head->build_time;
  364. image->img_info.build_ver = head->build_ver;
  365. image->img_info.product_ver = product_str[head->product_ver];
  366. image->img_info.version = head->product_ver;
  367. image->img_info.header_verno = head->header_verno;
  368. if (md_type_check && md_plat_check && md_sys_match && md_size_check) {
  369. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
  370. } else {
  371. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
  372. if (!md_type_check)
  373. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");
  374. if (!md_plat_check)
  375. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");
  376. if (!md_sys_match)
  377. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n",
  378. md_id + 1);
  379. if (!md_size_check)
  380. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  381. "[Reason]MD mem size mis-match to AP setting!\n");
  382. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  383. }
  384. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type,
  385. image->ap_info.image_type);
  386. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform,
  387. image->ap_info.platform);
  388. if (head->header_verno >= 2) {
  389. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",
  390. image->img_info.mem_size, image->ap_info.mem_size);
  391. if (head->md_img_size) {
  392. if (image->size >= head->md_img_size)
  393. image->size = head->md_img_size;
  394. else {
  395. char title[50];
  396. char info[100];
  397. snprintf(title, sizeof(title),
  398. "MD%d mem size smaller than image header setting", md_id + 1);
  399. snprintf(info, sizeof(info),
  400. "MD%d mem cfg size(0x%x)<header size(0x%x),please check memory config in <chip>.dtsi",
  401. md_id + 1, image->size, head->md_img_size);
  402. #if defined(CONFIG_MTK_AEE_FEATURE)
  403. aed_md_exception_api(NULL, 0, (const int *)info, sizeof(info),
  404. (const char *)title, DB_OPT_DEFAULT);
  405. #endif
  406. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  407. "[Reason]MD image size mis-match to AP!\n");
  408. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  409. }
  410. image->ap_info.md_img_size = image->size;
  411. image->img_info.md_img_size = head->md_img_size;
  412. }
  413. /* else {image->size -= 0x1A0;} workaround for md not check in check header */
  414. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n",
  415. head->md_img_size, image->size);
  416. }
  417. if (head->header_verno >= 3) { /* dsp offset && size */
  418. image->dsp_offset = headv34->dsp_img_offset;
  419. image->dsp_size = headv34->dsp_img_size;
  420. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset=%x size=%x\n", image->dsp_offset,
  421. image->dsp_size);
  422. if (image->dsp_offset == 0xCDCDCDAA) {
  423. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP on EMI disabled\n");
  424. } else if (((image->dsp_offset&0xFFFF) != 0) && (head->header_verno == 3)) {
  425. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset not 64KB align\n");
  426. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  427. } else if (image->dsp_offset + image->dsp_size > md_size) {
  428. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image size too large %x\n", md_size);
  429. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  430. }
  431. } else {
  432. image->dsp_offset = 0;
  433. }
  434. if (head->header_verno >= 4) { /* RMPU only avilable after check header v4 */
  435. for (region_id = 0; region_id <= MPU_REGION_INFO_ID_LAST; region_id++) {
  436. image->rmpu_info.region_info[region_id].region_offset =
  437. headv34->region_info[region_id].region_offset;
  438. image->rmpu_info.region_info[region_id].region_size =
  439. headv34->region_info[region_id].region_size;
  440. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  441. "[CCCI_UTIL] load_image: check_header_v4, region(%d): size = %x , offset = %x\n",
  442. region_id, headv34->region_info[region_id].region_size,
  443. headv34->region_info[region_id].region_offset);
  444. }
  445. for (domain_id = 0; domain_id < MPU_DOMAIN_INFO_ID_TOTAL_NUM; domain_id++) {
  446. image->rmpu_info.domain_attr[domain_id] = headv34->domain_attr[domain_id];
  447. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  448. "[CCCI_UTIL] load_image: check_header_v4, domain(%d): attr = %x\n", domain_id,
  449. headv34->domain_attr[domain_id]);
  450. }
  451. }
  452. if (head->header_verno >= 5) { /* ARM7 only avilable after check header v5 */
  453. image->arm7_offset = headv5->arm7_img_offset;
  454. image->arm7_size = headv5->arm7_img_size;
  455. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  456. "[CCCI_UTIL] load_image: check_header_v5, arm7_offset = 0x%08X, arm_size = 0x%08X\n",
  457. image->arm7_offset, image->arm7_size);
  458. }
  459. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",
  460. image->img_info.build_ver, image->img_info.build_time);
  461. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n", image->img_info.product_ver);
  462. }
  463. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check end***************************\n");
  464. return ret;
  465. }
  466. static int check_md_header(int md_id, void *parse_addr, struct ccci_image_info *image)
  467. {
  468. int ret;
  469. bool md_type_check = false;
  470. bool md_plat_check = false;
  471. bool md_sys_match = false;
  472. bool md_size_check = false;
  473. unsigned int md_size;
  474. unsigned int header_size;
  475. int idx;
  476. unsigned char *start, *ptr;
  477. struct md_check_header *head = &md_img_header[md_id];
  478. get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);
  479. header_size = *(((unsigned int *)parse_addr) - 1);
  480. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "MD image header size = %d\n", header_size);
  481. if (header_size == sizeof(struct md_check_header_v3)) /* v3, v4 */
  482. return check_md_header_v3(md_id, parse_addr, image);
  483. else if (header_size == sizeof(struct md_check_header_v5))
  484. return md_check_header_parser(md_id, parse_addr, image);
  485. /*memcpy(head, (void*)(parse_addr - sizeof(struct md_check_header)), sizeof(struct md_check_header)); */
  486. start = (unsigned char *)(head);
  487. ptr = (unsigned char *)(parse_addr - sizeof(struct md_check_header));
  488. for (idx = 0; idx < sizeof(struct md_check_header); idx++)
  489. *start++ = *ptr++;
  490. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check %d***************************\n",
  491. (int)sizeof(struct md_check_header));
  492. ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
  493. if (ret) {
  494. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist! %d\n", header_size);
  495. ret = -CCCI_ERR_LOAD_IMG_CHECK_HEAD;
  496. } else {
  497. if (head->header_verno > 2) {
  498. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n",
  499. head->header_verno);
  500. } else {
  501. #ifdef ENABLE_2G_3G_CHECK
  502. if ((head->image_type != 0) && (head->image_type == md->config.load_type))
  503. md_type_check = true;
  504. #else
  505. md_type_check = true;
  506. #endif
  507. #ifdef ENABLE_CHIP_VER_CHECK
  508. if (!strncmp(head->platform, ccci_get_ap_platform(), AP_PLATFORM_LEN))
  509. md_plat_check = true;
  510. #else
  511. md_plat_check = true;
  512. #endif
  513. if (head->bind_sys_id == (md_id + 1))
  514. md_sys_match = true;
  515. #ifdef ENABLE_MEM_SIZE_CHECK
  516. if (head->header_verno == 2) {
  517. /*md_size = md->mem_layout.md_region_size; */
  518. if (head->mem_size == md_size) {
  519. md_size_check = true;
  520. } else if (head->mem_size < md_size) {
  521. md_size_check = true;
  522. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  523. "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
  524. head->mem_size, md_size);
  525. }
  526. image->img_info.mem_size = head->mem_size;
  527. image->ap_info.mem_size = md_size;
  528. } else {
  529. md_size_check = true;
  530. }
  531. #else
  532. md_size_check = true;
  533. #endif
  534. image->ap_info.image_type = type_str[head->image_type];
  535. image->ap_info.platform = ccci_get_ap_platform();
  536. image->img_info.image_type = type_str[head->image_type];
  537. image->img_info.platform = head->platform;
  538. image->img_info.build_time = head->build_time;
  539. image->img_info.build_ver = head->build_ver;
  540. image->img_info.product_ver = product_str[head->product_ver];
  541. image->img_info.version = head->product_ver;
  542. if (md_type_check && md_plat_check && md_sys_match && md_size_check) {
  543. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
  544. } else {
  545. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
  546. if (!md_type_check)
  547. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");
  548. if (!md_plat_check)
  549. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");
  550. if (!md_sys_match)
  551. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n",
  552. md_id + 1);
  553. if (!md_size_check)
  554. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  555. "[Reason]MD mem size mis-match to AP setting!\n");
  556. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  557. }
  558. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type,
  559. image->ap_info.image_type);
  560. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform,
  561. image->ap_info.platform);
  562. if (head->header_verno >= 2) {
  563. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",
  564. image->img_info.mem_size, image->ap_info.mem_size);
  565. if (head->md_img_size) {
  566. if (image->size >= head->md_img_size)
  567. image->size = head->md_img_size;
  568. else {
  569. CCCI_UTIL_INF_MSG_WITH_ID(md_id,
  570. "[Reason]MD image size mis-match to AP!\n");
  571. ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
  572. }
  573. image->ap_info.md_img_size = image->size;
  574. image->img_info.md_img_size = head->md_img_size;
  575. }
  576. /* else {image->size -= 0x1A0;} workaround for md not check in check header */
  577. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n",
  578. head->md_img_size, image->size);
  579. }
  580. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",
  581. image->img_info.build_ver, image->img_info.build_time);
  582. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n", image->img_info.product_ver);
  583. }
  584. }
  585. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check***************************\n");
  586. return ret;
  587. }
  588. char *ccci_get_md_info_str(int md_id)
  589. {
  590. return md_img_info_str[md_id];
  591. }
  592. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  593. static int sec_lib_version_check(void)
  594. {
  595. int ret = 0;
  596. int sec_lib_ver = masp_ccci_version_info();
  597. if (sec_lib_ver != CURR_SEC_CCCI_SYNC_VER) {
  598. CCCI_UTIL_ERR_MSG("[Error]sec lib for ccci mismatch: sec_ver:%d, ccci_ver:%d\n", sec_lib_ver,
  599. CURR_SEC_CCCI_SYNC_VER);
  600. ret = -1;
  601. }
  602. return ret;
  603. }
  604. /*--------------------------------------------------------------------------------------------------*/
  605. /* New signature check version. 2012-2-2. */
  606. /* Change to use masp_ccci_signfmt_verify_file */
  607. /* (char *file_path, unsigned int *data_offset, unsigned int *data_sec_len) */
  608. /* masp_ccci_signfmt_verify_file parameter description */
  609. /* @ file_path: such as etc/firmware/modem.img */
  610. /* @ data_offset: the offset address that bypass signature header */
  611. /* @ data_sec_len: length of signature header + tail */
  612. /* @ return value: 0-success; */
  613. /*---------------------------------------------------------------------------------------------------*/
  614. static int signature_check_v2(int md_id, char *file_path, unsigned int *sec_tail_length)
  615. {
  616. unsigned int bypass_sec_header_offset = 0;
  617. unsigned int sec_total_len = 0;
  618. if (masp_ccci_signfmt_verify_file(file_path, &bypass_sec_header_offset, &sec_total_len) == 0) {
  619. /*signature lib check success */
  620. /*-- check return value */
  621. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check ret value 0x%x, 0x%x!\n", bypass_sec_header_offset,
  622. sec_total_len);
  623. if (bypass_sec_header_offset > sec_total_len) {
  624. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check fail(0x%x, 0x%x!)!\n", bypass_sec_header_offset,
  625. sec_total_len);
  626. return -CCCI_ERR_LOAD_IMG_SIGN_FAIL;
  627. }
  628. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check success(0x%x, 0x%x)!\n", bypass_sec_header_offset,
  629. sec_total_len);
  630. *sec_tail_length = sec_total_len - bypass_sec_header_offset;
  631. /* Note here, offset is more than 2G is not hoped */
  632. return (int)bypass_sec_header_offset;
  633. }
  634. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check fail!\n");
  635. return -CCCI_ERR_LOAD_IMG_SIGN_FAIL;
  636. }
  637. static int load_cipher_firmware_v2(int md_id,
  638. int fp_id,
  639. struct ccci_image_info *img,
  640. unsigned int cipher_img_offset, unsigned int cipher_img_len)
  641. {
  642. int ret;
  643. void *addr = ioremap_nocache(img->address, cipher_img_len);
  644. void *addr_bak = addr;
  645. unsigned int data_offset;
  646. if (addr == NULL) {
  647. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "ioremap image fialed!\n");
  648. ret = -CCCI_ERR_LOAD_IMG_NO_ADDR;
  649. goto out;
  650. }
  651. if (SEC_OK !=
  652. masp_ccci_decrypt_cipherfmt(fp_id, cipher_img_offset, (char *)addr, cipher_img_len, &data_offset)) {
  653. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher image decrypt fail!\n");
  654. ret = -CCCI_ERR_LOAD_IMG_CIPHER_FAIL;
  655. goto unmap_out;
  656. }
  657. img->size = cipher_img_len;
  658. img->offset += data_offset;
  659. addr += cipher_img_len;
  660. ret = check_md_header(md_id, addr, img);
  661. unmap_out:
  662. iounmap(addr_bak);
  663. out:
  664. return ret;
  665. }
  666. #endif
  667. static void get_md_postfix(int md_id, char k[], char buf[], char buf_ex[])
  668. {
  669. /* name format: modem_X_YY_K_Ex.img */
  670. int X, Ex = 0;
  671. char YY_K[IMG_POSTFIX_LEN];
  672. unsigned int feature_val = 0;
  673. if ((md_id < 0) || (md_id > MAX_MD_NUM)) {
  674. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "wrong MD ID to get postfix\n");
  675. return;
  676. }
  677. /* X */
  678. X = md_id + 1;
  679. if ((curr_ubin_id != 0) && (md_id == MD_SYS1)) {
  680. if (buf) {
  681. snprintf(buf, IMG_POSTFIX_LEN, "%d_%s_n", X, type_str[curr_ubin_id]);
  682. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "MD%d image postfix=%s\n", md_id + 1, buf);
  683. }
  684. if (buf_ex) {
  685. snprintf(buf_ex, IMG_POSTFIX_LEN, "%d_%s_n_E%d", X, type_str[curr_ubin_id], Ex);
  686. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "MD%d image postfix=%s\n", md_id + 1, buf_ex);
  687. }
  688. return;
  689. }
  690. /* YY_ */
  691. YY_K[0] = '\0';
  692. switch (md_id) {
  693. case MD_SYS1:
  694. feature_val = get_modem_support_cap(MD_SYS1);
  695. break;
  696. case MD_SYS2:
  697. feature_val = get_modem_support_cap(MD_SYS2);
  698. break;
  699. case MD_SYS3:
  700. feature_val = get_modem_support_cap(MD_SYS3);
  701. break;
  702. case MD_SYS5:
  703. feature_val = get_modem_support_cap(MD_SYS5);
  704. break;
  705. default:
  706. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "request MD ID %d not supported\n", md_id);
  707. break;
  708. }
  709. if ((feature_val == 0) || (feature_val >= MAX_IMG_NUM)) {
  710. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "request MD type %d not supported\n", feature_val);
  711. feature_val = md_type_invalid;
  712. }
  713. /* K */
  714. if (k == NULL)
  715. snprintf(YY_K, IMG_POSTFIX_LEN, "_%s_n", type_str[feature_val]);
  716. else
  717. snprintf(YY_K, IMG_POSTFIX_LEN, "_%s_%s", type_str[feature_val], k);
  718. /* [_Ex] Get chip version */
  719. #if 0
  720. if (get_chip_version() == CHIP_SW_VER_01)
  721. Ex = 1;
  722. else if (get_chip_version() == CHIP_SW_VER_02)
  723. Ex = 2;
  724. #else
  725. Ex = 1;
  726. #endif
  727. /* Gen post fix */
  728. if (buf) {
  729. snprintf(buf, IMG_POSTFIX_LEN, "%d%s", X, YY_K);
  730. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "MD%d image postfix=%s\n", md_id + 1, buf);
  731. }
  732. if (buf_ex) {
  733. snprintf(buf_ex, IMG_POSTFIX_LEN, "%d%s_E%d", X, YY_K, Ex);
  734. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "MD%d image postfix=%s\n", md_id + 1, buf_ex);
  735. }
  736. }
  737. static struct file *open_img_file(char *name, int *sec_fp_id)
  738. {
  739. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  740. int fp_id = OSAL_FILE_NULL;
  741. fp_id = osal_filp_open_read_only(name);
  742. CCCI_UTIL_DBG_MSG("sec_open fd = (%d)!\n", fp_id);
  743. if (sec_fp_id != NULL)
  744. *sec_fp_id = fp_id;
  745. CCCI_UTIL_DBG_MSG("sec_open file ptr = (%p)!\n", osal_get_filp_struct(fp_id));
  746. return (struct file *)osal_get_filp_struct(fp_id);
  747. #else
  748. CCCI_UTIL_DBG_MSG("std_open!\n");
  749. return filp_open(name, O_RDONLY, 0644);
  750. #endif
  751. }
  752. static void close_img_file(struct file *filp_id, int sec_fp_id)
  753. {
  754. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  755. CCCI_UTIL_DBG_MSG("sec_close (%d)!\n", sec_fp_id);
  756. osal_filp_close(sec_fp_id);
  757. #else
  758. CCCI_UTIL_DBG_MSG("std_close!\n");
  759. filp_close(filp_id, current->files);
  760. #endif
  761. }
  762. static int find_img_to_open(int md_id, MD_IMG_TYPE img_type, char active_file_path[], char active_post_fix[])
  763. {
  764. char img_name[3][IMG_NAME_LEN];
  765. char full_path[IMG_PATH_LEN];
  766. int i;
  767. char post_fix[IMG_POSTFIX_LEN];
  768. char post_fix_ex[IMG_POSTFIX_LEN];
  769. struct file *filp = NULL;
  770. /* Gen file name */
  771. get_md_postfix(md_id, NULL, post_fix, post_fix_ex);
  772. if (img_type == IMG_MD) { /* Gen MD image name */
  773. snprintf(img_name[0], IMG_NAME_LEN, "modem_%s.img", post_fix);
  774. snprintf(img_name[1], IMG_NAME_LEN, "modem_%s.img", post_fix_ex);
  775. snprintf(img_name[2], IMG_NAME_LEN, "%s", MOEDM_IMAGE_NAME);
  776. } else if (img_type == IMG_DSP) { /* Gen DSP image name */
  777. snprintf(img_name[0], IMG_NAME_LEN, "dsp_%s.bin", post_fix);
  778. snprintf(img_name[1], IMG_NAME_LEN, "dsp_%s.bin", post_fix_ex);
  779. snprintf(img_name[2], IMG_NAME_LEN, "%s", DSP_IMAGE_NAME);
  780. } else if (img_type == IMG_ARMV7) { /* Gen ARMV7 image name */
  781. snprintf(img_name[0], IMG_NAME_LEN, "armv7_%s.bin", post_fix);
  782. snprintf(img_name[1], IMG_NAME_LEN, "armv7_%s.bin", post_fix_ex);
  783. snprintf(img_name[2], IMG_NAME_LEN, "%s", "armv7.bin");
  784. } else {
  785. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "Invalid img type%d\n", img_type);
  786. return -CCCI_ERR_INVALID_PARAM;
  787. }
  788. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "Find img @CIP\n");
  789. for (i = 0; i < 3; i++) {
  790. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "try to open %s\n", img_name[i]);
  791. snprintf(full_path, IMG_PATH_LEN, "%s%s", CONFIG_MODEM_FIRMWARE_CIP_PATH, img_name[i]);
  792. filp = filp_open(full_path, O_RDONLY, 0644);
  793. if (IS_ERR(filp)) {
  794. continue;
  795. } else { /* Open image success */
  796. snprintf(active_file_path, IMG_PATH_LEN, full_path);
  797. filp_close(filp, current->files);
  798. if (i == 0)
  799. snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix);
  800. else if (i == 1)
  801. snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix_ex);
  802. else
  803. active_post_fix[0] = '\0';
  804. return 0;
  805. }
  806. }
  807. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "Find img @default\n");
  808. for (i = 0; i < 3; i++) {
  809. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "try to open %s\n", img_name[i]);
  810. snprintf(full_path, IMG_PATH_LEN, "%s%s", CONFIG_MODEM_FIRMWARE_PATH, img_name[i]);
  811. filp = filp_open(full_path, O_RDONLY, 0644);
  812. if (IS_ERR(filp)) {
  813. continue;
  814. } else { /* Open image success */
  815. snprintf(active_file_path, IMG_PATH_LEN, full_path);
  816. filp_close(filp, current->files);
  817. if (i == 0)
  818. snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix);
  819. else if (i == 1)
  820. snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix_ex);
  821. else
  822. active_post_fix[0] = '\0';
  823. return 0;
  824. }
  825. }
  826. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find ubin img @default\n");
  827. for (i = modem_ultg; i <= MAX_IMG_NUM; i++) {
  828. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Curr i:%d\n", i);
  829. if (img_type == IMG_MD)
  830. snprintf(img_name[0], IMG_NAME_LEN, "modem_%d_%s_n.img", md_id+1, type_str[i]);
  831. else if (img_type == IMG_DSP)
  832. snprintf(img_name[0], IMG_NAME_LEN, "dsp_%d_%s_n.bin", md_id+1, type_str[i]);
  833. else if (img_type == IMG_ARMV7)
  834. snprintf(img_name[0], IMG_NAME_LEN, "armv7_%d_%s_n.bin", md_id+1, type_str[i]);
  835. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "try to open %s\n", img_name[0]);
  836. snprintf(full_path, IMG_PATH_LEN, "%s%s", CONFIG_MODEM_FIRMWARE_PATH, img_name[0]);
  837. filp = filp_open(full_path, O_RDONLY, 0644);
  838. if (IS_ERR(filp)) {
  839. continue;
  840. } else { /* Open image success */
  841. snprintf(active_file_path, IMG_PATH_LEN, full_path);
  842. filp_close(filp, current->files);
  843. snprintf(active_post_fix, IMG_POSTFIX_LEN, "%d_%s_n", md_id + 1, type_str[i]);
  844. return 0;
  845. }
  846. }
  847. active_post_fix[0] = '\0';
  848. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "No Image file found\n");
  849. {
  850. char title[100];
  851. char info[100];
  852. snprintf(title, sizeof(title), "MD%d image not exist:%s", md_id + 1, img_name[0]);
  853. snprintf(info, sizeof(info), "Modem %d image name: %s,please check CUSTOM_MODME in projectconfig.mk!",
  854. md_id + 1, img_name[0]);
  855. #if defined(CONFIG_MTK_AEE_FEATURE)
  856. aed_md_exception_api(NULL, 0, (const int *)info, sizeof(info), (const char *)title, DB_OPT_DEFAULT);
  857. #endif
  858. }
  859. return -CCCI_ERR_LOAD_IMG_NOT_FOUND;
  860. }
  861. static inline void dump_md_image(int md_id, void *start_addr, u32 offset, u32 len)
  862. {
  863. u32 i, _16_fix_num;
  864. unsigned int *curr_p = (unsigned int *)(start_addr + offset);
  865. if (NULL == start_addr || len == 0)
  866. return;
  867. CCCI_UTIL_NOTICE_MSG_WITH_ID(md_id, "dump image start at %p, offset 0x%x, len 0x%x\n",
  868. start_addr, offset, len);
  869. _16_fix_num = len / 16;
  870. for (i = 0; i < _16_fix_num; i++) {
  871. CCCI_UTIL_NOTICE_MSG_WITH_ID(md_id, "%03X: %08X %08X %08X %08X\n",
  872. i * 16, *curr_p, *(curr_p + 1), *(curr_p + 2), *(curr_p + 3));
  873. curr_p += 4;
  874. }
  875. }
  876. static int check_if_bypass_header(struct file *filp, int *img_size);
  877. static int load_std_firmware(int md_id, struct file *filp, struct ccci_image_info *img)
  878. {
  879. void __iomem *start;
  880. int ret = 0;
  881. int check_ret = 0;
  882. int read_size = 0;
  883. mm_segment_t curr_fs;
  884. phys_addr_t load_addr;
  885. void *end_addr;
  886. const int size_per_read = 1024 * 1024;
  887. const int size = 1024;
  888. int img_size = 0;
  889. int hdr_size = 0;
  890. int curr_read;
  891. curr_fs = get_fs();
  892. set_fs(KERNEL_DS);
  893. load_addr = img->address;
  894. if (img->offset != 0)
  895. filp->f_pos = img->offset;
  896. else {
  897. hdr_size = check_if_bypass_header(filp, &img_size);
  898. if (hdr_size != 0) {
  899. img->size = img_size;
  900. filp->f_pos = hdr_size;
  901. } else
  902. filp->f_pos = 0; /* move offset back to 0 */
  903. }
  904. if (hdr_size) {
  905. CCCI_UTIL_ERR_MSG("read size according to header(%d)\n", img_size);
  906. while (1) {
  907. /* Map 1M memory */
  908. start = ioremap_nocache((load_addr + read_size), size_per_read);
  909. if (start == NULL) {
  910. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image ioremap fail: %p\n", start);
  911. set_fs(curr_fs);
  912. return -CCCI_ERR_LOAD_IMG_NOMEM;
  913. }
  914. if (size_per_read > (img_size-read_size))
  915. curr_read = img_size-read_size;
  916. else
  917. curr_read = size_per_read;
  918. ret = (int)filp->f_op->read(filp, start, curr_read, &filp->f_pos);
  919. /*make sure image size isn't 0 */
  920. if ((ret < 0) || (ret > curr_read) || ((ret == 0) && (read_size == 0))) {
  921. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image read fail: size=%d+\n", ret);
  922. ret = -CCCI_ERR_LOAD_IMG_FILE_READ;
  923. goto error;
  924. } else if (ret == curr_read) {
  925. read_size += ret;
  926. iounmap(start);
  927. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image read num %d\n", ret);
  928. if (ret == 0)
  929. break;
  930. } else {
  931. iounmap(start);
  932. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image read num %d--\n", ret);
  933. break;
  934. }
  935. }
  936. } else {
  937. CCCI_UTIL_ERR_MSG("legacy load\n");
  938. while (1) {
  939. /* Map 1M memory */
  940. start = ioremap_nocache((load_addr + read_size), size_per_read);
  941. if (start == NULL) {
  942. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image ioremap fail: %p\n", start);
  943. set_fs(curr_fs);
  944. return -CCCI_ERR_LOAD_IMG_NOMEM;
  945. }
  946. ret = (int)filp->f_op->read(filp, start, size_per_read, &filp->f_pos);
  947. /*make sure image size isn't 0 */
  948. if ((ret < 0) || (ret > size_per_read) || ((ret == 0) && (read_size == 0))) {
  949. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image read fail: size=%d\n", ret);
  950. ret = -CCCI_ERR_LOAD_IMG_FILE_READ;
  951. goto error;
  952. } else if (ret == size_per_read) {
  953. read_size += ret;
  954. iounmap(start);
  955. } else {
  956. read_size += ret;
  957. /* Note here, signatured image has file tail info. */
  958. img->size = read_size - img->tail_length;
  959. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "%s, image size=0x%x, read size:%d, tail:%d\n",
  960. img->file_name, img->size, read_size, img->tail_length);
  961. iounmap(start);
  962. break;
  963. }
  964. }
  965. }
  966. if (img->type == IMG_MD) {
  967. /* Make sure in one scope */
  968. start = ioremap_nocache(round_down(load_addr + img->size - 0x4000, 0x4000), 0x4000 * 2);
  969. end_addr = start + 0x4000 + (img->size - round_down(img->size, 0x4000));
  970. check_ret = check_md_header(md_id, end_addr, img);
  971. if (check_ret < 0) {
  972. ret = check_ret;
  973. goto error;
  974. }
  975. iounmap(start);
  976. } else if (img->type == IMG_DSP) {
  977. start = ioremap_nocache(load_addr, size);
  978. check_ret = check_dsp_header(md_id, start, img);
  979. if (check_ret < 0) {
  980. ret = check_ret;
  981. goto error;
  982. }
  983. iounmap(start);
  984. }
  985. set_fs(curr_fs);
  986. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Load %s (size=0x%x) to 0x%pa\n", img->file_name, read_size, &load_addr);
  987. return read_size;
  988. error:
  989. iounmap(start);
  990. set_fs(curr_fs);
  991. return ret;
  992. }
  993. /*
  994. * this function should be universal to both MD image and DSP image
  995. */
  996. static int load_image(int md_id, struct ccci_image_info *img_inf, char post_fix[])
  997. {
  998. struct file *filp = NULL;
  999. int fp_id;
  1000. int ret = 0;
  1001. int offset = 0;
  1002. unsigned int sec_tail_length = 0;
  1003. struct ccci_image_info *img = NULL;
  1004. MD_IMG_TYPE img_type;
  1005. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  1006. unsigned int img_len = 0;
  1007. #endif
  1008. img = img_inf;
  1009. img_type = img->type;
  1010. if (find_img_to_open(md_id, img_type, img->file_name, post_fix) < 0) {
  1011. ret = -CCCI_ERR_LOAD_IMG_FILE_OPEN;
  1012. filp = NULL;
  1013. goto out;
  1014. }
  1015. filp = open_img_file(img->file_name, &fp_id);
  1016. if (IS_ERR(filp)) {
  1017. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "open %s fail: %ld\n", img->file_name, PTR_ERR(filp));
  1018. ret = -CCCI_ERR_LOAD_IMG_FILE_OPEN;
  1019. filp = NULL;
  1020. goto out;
  1021. } else {
  1022. CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "open %s OK\n", img->file_name);
  1023. }
  1024. /*Begin to check header, only modem.img need check signature and cipher header */
  1025. sec_tail_length = 0;
  1026. if (img_type == IMG_MD) {
  1027. /*step1:check if need to signature */
  1028. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  1029. offset = signature_check_v2(md_id, img->file_name, &sec_tail_length);
  1030. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature_check offset:%d, tail:%d\n", offset, sec_tail_length);
  1031. if (offset < 0) {
  1032. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature_check failed ret=%d\n", offset);
  1033. ret = offset;
  1034. goto out;
  1035. }
  1036. #endif
  1037. img->offset = offset;
  1038. img->tail_length = sec_tail_length;
  1039. /*step2:check if need to cipher */
  1040. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  1041. if (masp_ccci_is_cipherfmt(fp_id, offset, &img_len)) {
  1042. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher image\n");
  1043. ret = load_cipher_firmware_v2(md_id, fp_id, img, offset, img_len);
  1044. if (ret < 0) {
  1045. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_cipher_firmware failed:ret=%d!\n", ret);
  1046. goto out;
  1047. }
  1048. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_cipher_firmware done! (=%d)\n", ret);
  1049. } else {
  1050. #endif
  1051. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Not cipher image\n");
  1052. ret = load_std_firmware(md_id, filp, img);
  1053. if (ret < 0) {
  1054. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_firmware failed: ret=%d!\n", ret);
  1055. goto out;
  1056. }
  1057. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  1058. }
  1059. #endif
  1060. } else if (img_type == IMG_DSP) {
  1061. /*dsp image check signature during uboot, and ccci not need check for dsp. */
  1062. ret = load_std_firmware(md_id, filp, img);
  1063. if (ret < 0) {
  1064. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_firmware for %s failed:ret=%d!\n", img->file_name, ret);
  1065. goto out;
  1066. }
  1067. } else if (img_type == IMG_ARMV7) {
  1068. /* load armv7 */
  1069. ret = load_std_firmware(md_id, filp, img);
  1070. if (ret < 0) {
  1071. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_firmware for %s failed:ret=%d!\n", img->file_name, ret);
  1072. goto out;
  1073. }
  1074. }
  1075. out:
  1076. if (filp != NULL)
  1077. close_img_file(filp, fp_id);
  1078. return ret;
  1079. }
  1080. int ccci_load_firmware(int md_id, void *img_inf, char img_err_str[], char post_fix[])
  1081. {
  1082. int ret = 0;
  1083. struct ccci_image_info *img_ptr = (struct ccci_image_info *)img_inf;
  1084. char *img_str;
  1085. img_str = md_img_info_str[md_id];
  1086. /*step1: clear modem protection when start to load firmware */
  1087. /*ccci_clear_md_region_protection(md_id); */
  1088. /*step2: load image */
  1089. ret = load_image(md_id, img_ptr, post_fix);
  1090. if (ret < 0) {
  1091. /* if load_image failed, md->img_info won't have valid file name */
  1092. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "fail to load firmware!\n");
  1093. }
  1094. /* Construct image information string */
  1095. if (img_ptr->type == IMG_MD) {
  1096. sprintf(img_str, "MD:%s*%s*%s*%s*%s\nAP:%s*%s*%08x (MD)%08x\n",
  1097. img_ptr->img_info.image_type, img_ptr->img_info.platform,
  1098. img_ptr->img_info.build_ver, img_ptr->img_info.build_time,
  1099. img_ptr->img_info.product_ver, img_ptr->ap_info.image_type,
  1100. img_ptr->ap_info.platform, img_ptr->ap_info.mem_size, img_ptr->img_info.mem_size);
  1101. }
  1102. /* Prepare error string if needed */
  1103. if (img_err_str != NULL) {
  1104. if (ret == -CCCI_ERR_LOAD_IMG_SIGN_FAIL) {
  1105. snprintf(img_err_str, IMG_ERR_STR_LEN, "%s Signature check fail\n", img_ptr->file_name);
  1106. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature check fail!\n");
  1107. } else if (ret == -CCCI_ERR_LOAD_IMG_CIPHER_FAIL) {
  1108. snprintf(img_err_str, IMG_ERR_STR_LEN, "%s Cipher chekc fail\n", img_ptr->file_name);
  1109. CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher check fail!\n");
  1110. } else if (ret == -CCCI_ERR_LOAD_IMG_FILE_OPEN) {
  1111. snprintf(img_err_str, IMG_ERR_STR_LEN, "Modem image not exist\n");
  1112. } else if (ret == -CCCI_ERR_LOAD_IMG_MD_CHECK) {
  1113. snprintf(img_err_str, IMG_ERR_STR_LEN, "Modem mismatch to AP\n");
  1114. }
  1115. }
  1116. if (ret < 0)
  1117. ret = -CCCI_ERR_LOAD_IMG_LOAD_FIRM;
  1118. return ret;
  1119. }
  1120. #if 0
  1121. int get_img_info(int md_id, int img_type, struct ccci_image_info *info_ptr)
  1122. {
  1123. if ((md_id >= MAX_MD_NUM) || (info_ptr == NULL) || (img_type >= IMG_NUM))
  1124. return -1;
  1125. info_ptr->type = img_info[md_id][img_type].type;
  1126. memcpy(info_ptr->file_name, img_info[md_id][img_type].file_name, IMG_PATH_LEN);
  1127. info_ptr->address = img_info[md_id][img_type].address;
  1128. info_ptr->size = img_info[md_id][img_type].size;
  1129. info_ptr->offset = img_info[md_id][img_type].offset;
  1130. info_ptr->tail_length = img_info[md_id][img_type].tail_length;
  1131. info_ptr->ap_platform = img_info[md_id][img_type].ap_platform;
  1132. info_ptr->img_info.product_ver = img_info[md_id][img_type].img_info.product_ver;
  1133. info_ptr->img_info.image_type = img_info[md_id][img_type].img_info.image_type;
  1134. info_ptr->img_info.platform = img_info[md_id][img_type].img_info.platform;
  1135. info_ptr->img_info.build_time = img_info[md_id][img_type].img_info.build_time;
  1136. info_ptr->img_info.build_ver = img_info[md_id][img_type].img_info.build_ver;
  1137. info_ptr->img_info.mem_size = img_info[md_id][img_type].img_info.mem_size;
  1138. info_ptr->ap_info.product_ver = img_info[md_id][img_type].ap_info.product_ver;
  1139. info_ptr->ap_info.image_type = img_info[md_id][img_type].ap_info.image_type;
  1140. info_ptr->ap_info.platform = img_info[md_id][img_type].ap_info.platform;
  1141. info_ptr->ap_info.build_time = img_info[md_id][img_type].ap_info.build_time;
  1142. info_ptr->ap_info.build_ver = img_info[md_id][img_type].ap_info.build_ver;
  1143. info_ptr->ap_info.mem_size = img_info[md_id][img_type].ap_info.mem_size;
  1144. return 0;
  1145. }
  1146. #endif
  1147. int ccci_init_security(void)
  1148. {
  1149. int ret = 0;
  1150. #ifdef ENABLE_MD_IMG_SECURITY_FEATURE
  1151. static int security_init; /* for multi-modem support */
  1152. if (security_init)
  1153. return ret;
  1154. security_init = 1;
  1155. ret = masp_boot_init();
  1156. if (ret != 0) {
  1157. CCCI_UTIL_ERR_MSG("masp_boot_init fail: %d\n", ret);
  1158. ret = -EIO;
  1159. }
  1160. if (sec_lib_version_check() != 0) {
  1161. CCCI_UTIL_ERR_MSG("sec lib version check error\n");
  1162. ret = -EIO;
  1163. }
  1164. CCCI_UTIL_INF_MSG("security is on!\n");
  1165. #else
  1166. CCCI_UTIL_INF_MSG("security is off!\n");
  1167. #endif
  1168. return ret;
  1169. }
  1170. static const int md1_capability_array[] = {
  1171. 0, 0, 0, 0, 0, 0, 0, 0,
  1172. /* ultg */
  1173. ((1 << modem_ulwtg) | (1 << modem_ultg) | (0 << modem_ulwg) | (0 << modem_ulwcg) | (1 << modem_ulwctg)),
  1174. /* ulwg */
  1175. ((1 << modem_ulwtg) | (0 << modem_ultg) | (1 << modem_ulwg) | (1 << modem_ulwcg) | (1 << modem_ulwctg)),
  1176. /* ulwtg */
  1177. ((1 << modem_ulwtg) | (0 << modem_ultg) | (1 << modem_ulwg) | (1 << modem_ulwcg) | (1 << modem_ulwctg)),
  1178. /* ulwcg */
  1179. ((0 << modem_ulwtg) | (0 << modem_ultg) | (0 << modem_ulwg) | (1 << modem_ulwcg) | (1 << modem_ulwctg)),
  1180. /* ulwctg */
  1181. ((0 << modem_ulwtg) | (0 << modem_ultg) | (0 << modem_ulwg) | (0 << modem_ulwcg) | (1 << modem_ulwctg)),
  1182. /* ulttg */
  1183. ((1 << modem_ulwtg) | (1 << modem_ultg) | (0 << modem_ulwg) | (0 << modem_ulwcg) | (1 << modem_ulwctg)),
  1184. /* ulfwg */
  1185. ((1 << modem_ulwtg) | (0 << modem_ultg) | (1 << modem_ulwg) | (1 << modem_ulwcg) | (1 << modem_ulwctg)),
  1186. /* ulfwcg */
  1187. ((0 << modem_ulwtg) | (0 << modem_ultg) | (0 << modem_ulwg) | (1 << modem_ulwcg) | (1 << modem_ulwctg)),
  1188. };
  1189. static const int ap_md_wm_id_map_array[] = { 0x0, /* 0-invalid */
  1190. 0x0, /* 1-2g */
  1191. 0x0, /* 2-3g */
  1192. 0x0, /* 3-wg */
  1193. 0x0, /* 4-tg */
  1194. 0x0, /* 5-lwg */
  1195. 0x0, /* 6-ltg */
  1196. 0x0, /* 7-sglte */
  1197. 0x33, /* 8-ultg */
  1198. 0x39, /* 9-ulwg */
  1199. 0x3B, /* 10-ulwtg */
  1200. 0x3D, /* 11-ulwcg */
  1201. 0x3F, /* 12-ulwctg */
  1202. 0x13, /* 13-ulttg */
  1203. 0x29, /* 14-ulfwg */
  1204. 0x2D, /* 15-ulfwcg */
  1205. };
  1206. int get_md_wm_id_map(int ap_wm_id)
  1207. {
  1208. if (ap_wm_id < (sizeof(ap_md_wm_id_map_array) / sizeof(int)))
  1209. return ap_md_wm_id_map_array[ap_wm_id];
  1210. return 0;
  1211. }
  1212. int md_capability(int md_id, int wm_id, int curr_md_type)
  1213. {
  1214. if (curr_md_type >= MAX_IMG_NUM)
  1215. return -1;
  1216. if (wm_id >= MAX_IMG_NUM)
  1217. return -2;
  1218. if (md_id == MD_SYS1) {
  1219. if (md1_capability_array[wm_id] & (1 << curr_ubin_id)) /* Note here, curr_md_type not used */
  1220. return 1;
  1221. return 0;
  1222. }
  1223. return -3;
  1224. }
  1225. #define IMG_MAGIC 0x58881688
  1226. #define EXT_MAGIC 0x58891689
  1227. #define IMG_NAME_SIZE 32
  1228. #define IMG_HDR_SIZE 512
  1229. typedef union {
  1230. struct {
  1231. unsigned int magic; /* always IMG_MAGIC */
  1232. unsigned int dsize; /* image size, image header and padding are not included */
  1233. char name[IMG_NAME_SIZE];
  1234. unsigned int maddr; /* image load address in RAM */
  1235. unsigned int mode; /* maddr is counted from the beginning or end of RAM */
  1236. /* extension */
  1237. unsigned int ext_magic; /* always EXT_MAGIC */
  1238. unsigned int hdr_size; /* header size is 512 bytes currently, but may extend in the future */
  1239. unsigned int hdr_version; /* see HDR_VERSION */
  1240. unsigned int img_type; /* please refer to #define beginning with SEC_IMG_TYPE_ */
  1241. unsigned int img_list_end; /* end of image list? 0: this image is followed by another image 1: end */
  1242. unsigned int align_size; /* image size alignment setting in bytes, 16 by default for AES encryption */
  1243. unsigned int dsize_extend; /* high word of image size for 64 bit address support */
  1244. unsigned int maddr_extend; /* high word of image load address in RAM for 64 bit address support */
  1245. } info;
  1246. unsigned char data[IMG_HDR_SIZE];
  1247. } prt_img_hdr_t;
  1248. int check_if_bypass_header(struct file *filp, int *img_size)
  1249. {
  1250. char buf[64];
  1251. int ret;
  1252. prt_img_hdr_t *hdr_ptr;
  1253. filp->f_pos = 0; /* make sure read from 0 */
  1254. ret = (int)filp->f_op->read(filp, buf, 64, &filp->f_pos);
  1255. if (ret != 64) {
  1256. CCCI_UTIL_ERR_MSG("Can't read enough data(%d)\n", ret);
  1257. return 0;
  1258. }
  1259. hdr_ptr = (prt_img_hdr_t *)buf;
  1260. if ((hdr_ptr->info.magic == IMG_MAGIC) && (hdr_ptr->info.ext_magic == EXT_MAGIC)) {
  1261. CCCI_UTIL_ERR_MSG("This image has header, bypass %d bytes\n", (int)hdr_ptr->info.hdr_size);
  1262. if (img_size)
  1263. *img_size = hdr_ptr->info.dsize;
  1264. return (int)hdr_ptr->info.hdr_size;
  1265. }
  1266. CCCI_UTIL_ERR_MSG("This image does not find header, no need bypass\n");
  1267. return 0;
  1268. }