Exemple #1
0
static int load_cipher_firmware_v2(	int md_id, 
					int fp_id, 
					struct ccci_image_info *img,
					unsigned int cipher_img_offset, 
					unsigned int cipher_img_len)
{
	int ret;
	void *addr = ioremap_nocache(img->address,cipher_img_len);
	void *addr_bak = addr;
	unsigned int data_offset;

	if (addr==NULL) {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "ioremap image fialed!\n");
		ret = -CCCI_ERR_LOAD_IMG_NO_ADDR;
		goto out;
	}

	if(SEC_OK != masp_ccci_decrypt_cipherfmt(fp_id, cipher_img_offset, (char*)addr, cipher_img_len, &data_offset) ) {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher image decrypt fail!\n");
		ret = -CCCI_ERR_LOAD_IMG_CIPHER_FAIL;
		goto unmap_out;
	}

	img->size = cipher_img_len;
	img->offset += data_offset;	
	addr+=cipher_img_len;

	ret = check_md_header(md_id, addr, img);

unmap_out:
	iounmap(addr_bak);
out:
	return ret;
}
static void cal_md_settings(int md_id)
{
	unsigned int tmp;
	unsigned int md_en = 0;
	char tmp_buf[30];
	char* node_name = NULL;
	struct device_node *node=NULL; 
	snprintf(tmp_buf,sizeof(tmp_buf),"MTK_ENABLE_MD%d",(md_id+1));
	// MTK_ENABLE_MD*
	if(ccci_get_fo_setting(tmp_buf, &tmp) == 0) {
		if(tmp > 0)
			md_en = 1;
	}
	if(!(md_en && (md_usage_case&(1<<md_id)))){
		CCCI_UTIL_INF_MSG_WITH_ID(md_id,"md%d is disabled\n",(md_id+1));
		return;
	}
	// MTK_MD*_SUPPORT
	snprintf(tmp_buf,sizeof(tmp_buf),"MTK_MD%d_SUPPORT",(md_id+1));
	if(ccci_get_fo_setting(tmp_buf, &tmp) == 0) {
		md_support[md_id] = tmp;
	}
	// MD*_SMEM_SIZE
	if(md_id==MD_SYS1){
		node_name = "mediatek,MDCLDMA";
	}else if(md_id==MD_SYS2){
		node_name= "mediatek,AP_CCIF1";
	}else{
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d id is not supported,need to check\n",(md_id+1));
		md_usage_case &= ~(1<<md_id);
		return;
	}
	node = of_find_compatible_node(NULL, NULL, node_name);
	if(node){
		of_property_read_u32(node, "md_smem_size", &md_resv_smem_size[md_id]);
	}else{
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d smem size is not set in device tree,need to check\n",(md_id+1));
		md_usage_case &= ~(1<<md_id);
		return;
	}
	// MD ROM start address should be 32M align as remap hardware limitation
	md_resv_mem_addr[md_id] = md_resv_mem_list[md_id];
	/*
	 * for legacy CCCI: make share memory start address to be 2MB align, as share 
	 * memory size is 2MB - requested by MD MPU.
	 * for ECCCI: ROM+RAM size will be align to 1M, and share memory is 2K,
	 * 1M alignment is also 2K alignment.
	 */	
	md_resv_mem_size[md_id]= round_up(modem_size_list[md_id] - md_resv_smem_size[md_id], get_md_smem_align(md_id));
	md_resv_smem_addr[md_id] = md_resv_mem_list[md_id] + md_resv_mem_size[md_id];
	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"md%d modem_total_size=0x%x,md_size=0x%x, smem_size=0x%x\n",(md_id+1),modem_size_list[md_id],md_resv_mem_size[md_id],md_resv_smem_size[md_id]);	
	if ((md_usage_case&(1<<md_id)) && ((md_resv_mem_addr[md_id]&(CCCI_MEM_ALIGN - 1)) != 0))
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d memory addr is not 32M align!!!\n",(md_id+1));

	if ((md_usage_case&(1<<md_id)) && ((md_resv_smem_addr[md_id]&(CCCI_SMEM_ALIGN_MD1 - 1)) != 0))
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d share memory addr %pa is not 0x%x align!!\n", (md_id+1),&md_resv_smem_addr[md_id], CCCI_SMEM_ALIGN_MD1);

	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"MemStart: 0x%pa, MemSize:0x%08X\n",&md_resv_mem_addr[md_id], md_resv_mem_size[md_id]);
	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"SMemStart: 0x%pa, SMemSize:0x%08X\n",&md_resv_smem_addr[md_id], md_resv_smem_size[md_id]);
}
int scan_image_list(int md_id, char fmt[], int out_img_list[], int img_list_size)
{
	int i;
	int img_num = 0;
	char full_path[64] = { 0 };
	char img_name[32] = { 0 };
	struct file *filp = NULL;
	for (i = 0; i < (sizeof(type_str) / sizeof(char *)); i++) {
		snprintf(img_name, 32, fmt, md_id + 1, type_str[i]);
		/* Find at CIP first */
		snprintf(full_path, 64, "%s%s", CONFIG_MODEM_FIRMWARE_CIP_PATH, img_name);
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find:%s\n", full_path);
		filp = filp_open(full_path, O_RDONLY, 0644);
		if (IS_ERR(filp)) {
			/* Find at default */
			snprintf(full_path, 64, "%s%s", CONFIG_MODEM_FIRMWARE_PATH, img_name);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find:%s\n", full_path);
			filp = filp_open(full_path, O_RDONLY, 0644);
			if (IS_ERR(filp)) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "%s not found(%d,%d)\n", full_path, img_num, i);
				continue;
			}
		}
		/* Run here means open image success */
		filp_close(filp, NULL);
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Image:%s found\n", full_path);
		if (img_num < img_list_size)
			out_img_list[img_num] = i;
		img_num++;
	}
	return img_num;
}
/*---------------------------------------------------------------------------------------------------*/
static int signature_check_v2(int md_id, char *file_path, unsigned int *sec_tail_length)
{
	unsigned int bypass_sec_header_offset = 0;
	unsigned int sec_total_len = 0;

	if (masp_ccci_signfmt_verify_file(file_path, &bypass_sec_header_offset, &sec_total_len) == 0) {
		/*signature lib check success */
		/*-- check return value */
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check ret value 0x%x, 0x%x!\n", bypass_sec_header_offset,
					  sec_total_len);
		if (bypass_sec_header_offset > sec_total_len) {
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check fail(0x%x, 0x%x!)!\n", bypass_sec_header_offset,
						  sec_total_len);
			return -CCCI_ERR_LOAD_IMG_SIGN_FAIL;
		} else {
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check success(0x%x, 0x%x)!\n", bypass_sec_header_offset,
						  sec_total_len);
			*sec_tail_length = sec_total_len - bypass_sec_header_offset;
			return (int)bypass_sec_header_offset;	/* Note here, offset is more than 2G is not hoped  */
		}
	} else {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "sign check fail!\n");
		return -CCCI_ERR_LOAD_IMG_SIGN_FAIL;
	}
}
Exemple #5
0
int ccci_load_firmware(int md_id, void* img_inf, char img_err_str[], char post_fix[])
{
	int ret = 0;
	struct ccci_image_info *img_ptr = (struct ccci_image_info*)img_inf;
	char *img_str;

	img_str = md_img_info_str[md_id];

	//step1: clear modem protection when start to load firmware
	//ccci_clear_md_region_protection(md_id);

	//step2: load image
	if((ret=load_image(md_id, img_ptr, post_fix)) < 0){
		// if load_image failed, md->img_info won't have valid file name
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "fail to load firmware!\n");
	}

	/* Construct image information string */
	if(img_ptr->type == IMG_MD) {
		sprintf(img_str, "MD:%s*%s*%s*%s*%s\nAP:%s*%s*%08x (MD)%08x\n",
				img_ptr->img_info.image_type, img_ptr->img_info.platform, 
				img_ptr->img_info.build_ver, img_ptr->img_info.build_time,
				img_ptr->img_info.product_ver, img_ptr->ap_info.image_type,
				img_ptr->ap_info.platform, img_ptr->ap_info.mem_size,
				img_ptr->img_info.mem_size);
	}

	// Prepare error string if needed
	if(img_err_str != NULL) {
		if(ret == -CCCI_ERR_LOAD_IMG_SIGN_FAIL) {
			snprintf(img_err_str, IMG_ERR_STR_LEN, "%s Signature check fail\n", img_ptr->file_name);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature check fail!\n");
		} else if(ret == -CCCI_ERR_LOAD_IMG_CIPHER_FAIL) {
			snprintf(img_err_str, IMG_ERR_STR_LEN, "%s Cipher chekc fail\n", img_ptr->file_name);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher check fail!\n");
		} else if(ret == -CCCI_ERR_LOAD_IMG_FILE_OPEN) {
			snprintf(img_err_str, IMG_ERR_STR_LEN, "Modem image not exist\n");
		} else if( ret == -CCCI_ERR_LOAD_IMG_MD_CHECK) {
			snprintf(img_err_str, IMG_ERR_STR_LEN, "Modem mismatch to AP\n");
		}
	}
	if(ret < 0)
		ret = -CCCI_ERR_LOAD_IMG_LOAD_FIRM;
	return ret;
}
int ccci_reserve_mem_of_init(struct reserved_mem * rmem, unsigned long node, const char * uname)
{
  phys_addr_t rptr = 0;
  unsigned int rsize= 0;
  int md_id = -1;
  rptr = rmem->base;
  rsize= (unsigned int)rmem->size;	
  if(strcmp(uname, CCCI_MD1_MEM_RESERVED_KEY) == 0){
      md_id = MD_SYS1;
  }
  if(strcmp(uname, CCCI_MD2_MEM_RESERVED_KEY) == 0){
    md_id = MD_SYS2;
  }
  if(md_id<0){
    CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"memory reserve key %s not support\n",uname);  
    return 0;
  }
  CCCI_UTIL_INF_MSG_WITH_ID(md_id,"reserve_mem_of_init, rptr=0x%pa, rsize=0x%x\n", &rptr, rsize);
  md_resv_mem_list[md_id] = rptr;  	
  modem_size_list[md_id]= rsize;
  md_usage_case |= (1<<md_id);
  return 0;
}
Exemple #7
0
static int check_md_header_v3(int md_id, void *parse_addr, struct ccci_image_info *image)
{
	int ret;
	bool md_type_check = false;
	bool md_plat_check = false;
	bool md_sys_match  = false;
	bool md_size_check = false;
	unsigned int md_size;

	struct md_check_header_v3 *head = &md_img_header_v3[md_id];
	get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);

	memcpy(head, (void*)(parse_addr - sizeof(struct md_check_header_v3)), sizeof(struct md_check_header_v3));

	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3 %d***************************\n", sizeof(struct md_check_header_v3));
	ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
	if(ret) {
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist!\n");
		ret = 0;
	}
	else {
		if(head->header_verno > MD_HEADER_VER_NO) {
			CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n", 
				head->header_verno);
		} else {
#ifdef ENABLE_2G_3G_CHECK
			if((head->image_type != 0) && (head->image_type == md->config.load_type)) {
				md_type_check = true;
			}
#else
			md_type_check = true;
#endif

#ifdef ENABLE_CHIP_VER_CHECK
			if(!strncmp(head->platform, ap_platform, AP_PLATFORM_LEN)) {
				md_plat_check = true;
			}
#else
			md_plat_check = true;
#endif

			if(head->bind_sys_id == (md_id+1)) {
				md_sys_match = true;
			}

#ifdef ENABLE_MEM_SIZE_CHECK
			if(head->header_verno >= 2) {
				//md_size = md->mem_layout.md_region_size;
				if (head->mem_size == md_size) {
					md_size_check = true;
				} else if(head->mem_size < md_size) {
					md_size_check = true;
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
						head->mem_size, md_size);
				}
				image->img_info.mem_size = head->mem_size;
				image->ap_info.mem_size = md_size;
			} else {
				md_size_check = true;
			}
#else
			md_size_check = true;
#endif

			image->ap_info.image_type = type_str[head->image_type];
			image->ap_info.platform = ap_platform;
			image->img_info.image_type = type_str[head->image_type];
			image->img_info.platform = head->platform;
			image->img_info.build_time = head->build_time;
			image->img_info.build_ver = head->build_ver;
			image->img_info.product_ver = product_str[head->product_ver];
			image->img_info.version = head->product_ver;

			if(md_type_check && md_plat_check && md_sys_match && md_size_check) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
			} else {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
				if(!md_type_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");

				if(!md_plat_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");

				if(!md_sys_match)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n", md_id+1);

				if(!md_size_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD mem size mis-match to AP setting!\n");

				ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
			}

			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type, image->ap_info.image_type);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform, image->ap_info.platform);
			if(head->header_verno >= 2) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",image->img_info.mem_size, image->ap_info.mem_size);
				if (head->md_img_size) {
					if (image->size >= head->md_img_size)
						image->size = head->md_img_size;
					else {
						CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image size mis-match to AP!\n");
						ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
					}
					image->ap_info.md_img_size = image->size;
					image->img_info.md_img_size = head->md_img_size;
				}
				// else {image->size -= 0x1A0;} //workaround for md not check in check header
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n", head->md_img_size, image->size);
			}
			if(head->header_verno >= 3) {
				image->dsp_offset = head->dsp_img_offset;
				image->dsp_size = head->dsp_img_size;
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset=%x size=%x\n", image->dsp_offset, image->dsp_size);
				if(image->dsp_offset == 0xCDCDCDAA) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP on EMI disabled\n");
				} else if(image->dsp_offset&0xFFFF != 0) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset not 64KB align\n");
					ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
				} else if(image->dsp_offset+image->dsp_size > md_size) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image size too large %x\n", md_size);
					ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
				}
			} else {
				image->dsp_offset = 0;
			}
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",image->img_info.build_ver, image->img_info.build_time);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n",image->img_info.product_ver);
		}
	}
	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3***************************\n");

	return ret;
}
Exemple #8
0
/*
 * this function should be universal to both MD image and DSP image
 */
static int load_image(int md_id, struct ccci_image_info* img_inf, char post_fix[])
{
	struct file		*filp = NULL;
	int			fp_id;
	int			ret=0;
	int			offset=0;
	unsigned int		sec_tail_length = 0;
	struct ccci_image_info	*img = NULL;
	MD_IMG_TYPE		img_type;
#ifdef ENABLE_MD_IMG_SECURITY_FEATURE
	unsigned int		img_len=0;
#endif

	img = img_inf;
	img_type = img->type;
	if (find_img_to_open(md_id, img_type, img->file_name, post_fix)<0) {
		ret = -CCCI_ERR_LOAD_IMG_FILE_OPEN;
		filp = NULL;
		goto out;
	}

	filp = open_img_file(img->file_name, &fp_id);
	if (IS_ERR(filp)) {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "open %s fail: %ld\n", img->file_name, PTR_ERR(filp));
		ret = -CCCI_ERR_LOAD_IMG_FILE_OPEN;
		filp = NULL;
		goto out;
	} else {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "open %s OK\n", img->file_name);
	}

	//Begin to check header, only modem.img need check signature and cipher header
	sec_tail_length = 0;
	if(img_type == IMG_MD) {
		//step1:check if need to signature
#ifdef ENABLE_MD_IMG_SECURITY_FEATURE
		offset = signature_check_v2(md_id, img->file_name, &sec_tail_length);
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature_check offset:%d, tail:%d\n", offset, sec_tail_length);
		if (offset<0) {
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "signature_check failed ret=%d\n",offset);
			ret=offset;
			goto out;
		}
#endif
		img->offset=offset;
		img->tail_length = sec_tail_length;

		//step2:check if need to cipher
#ifdef ENABLE_MD_IMG_SECURITY_FEATURE       
		if (masp_ccci_is_cipherfmt(fp_id, offset, &img_len)) {
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "cipher image\n");
			ret=load_cipher_firmware_v2(md_id, fp_id, img, offset, img_len);
			if(ret<0) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_cipher_firmware failed:ret=%d!\n",ret);
				goto out;
			}
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_cipher_firmware done! (=%d)\n",ret);
		} else {
#endif
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Not cipher image\n");
			ret=load_std_firmware(md_id, filp, img);
			if(ret<0) {
   				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_firmware failed: ret=%d!\n",ret);
				goto out;
    		}
#ifdef ENABLE_MD_IMG_SECURITY_FEATURE           
		}
#endif        
	} else if(img_type == IMG_DSP) {
		//dsp image check signature during uboot, and ccci not need check for dsp.
		ret=load_std_firmware(md_id, filp, img);
		if(ret<0) {
   			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "load_firmware for %s failed:ret=%d!\n",img->file_name,ret);
			goto out;
    	}
	}

out:
	if(filp != NULL){ 
		close_img_file(filp, fp_id);
	}
	return ret;
}
Exemple #9
0
static int load_std_firmware(	int md_id, 
				struct file *filp, 
				struct ccci_image_info *img)
{
	void __iomem *	start;
	int		ret = 0;
	int		check_ret = 0;
	int		read_size = 0;
	mm_segment_t	curr_fs;
	phys_addr_t	load_addr;
	void *		end_addr;
	const int	size_per_read = 1024 * 1024;
	const int	size = 1024;

	curr_fs = get_fs();
	set_fs(KERNEL_DS);

	load_addr = img->address;
	filp->f_pos = img->offset;

	while (1) {
		// Map 1M memory
		start = ioremap_nocache((load_addr + read_size), size_per_read);
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "map %08x --> %08x\n", (unsigned int)(load_addr+read_size), (unsigned int)start);
		if (start <= 0) {
			CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image ioremap fail: %p\n", start);
			set_fs(curr_fs);
			return -CCCI_ERR_LOAD_IMG_NOMEM;
		}

		ret = filp->f_op->read(filp, start, size_per_read, &filp->f_pos);
		if ((ret < 0) || (ret > size_per_read) || ((ret == 0) && (read_size == 0))) { //make sure image size isn't 0
			CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "image read fail: size=%d\n", ret);
			ret = -CCCI_ERR_LOAD_IMG_FILE_READ;
			goto error;
		} else if(ret == size_per_read) {
			read_size += ret;
			iounmap(start);
		} else {
			read_size += ret;
			img->size = read_size - img->tail_length; /* Note here, signatured image has file tail info. */
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "%s, image size=0x%x, read size:%d, tail:%d\n", 
							img->file_name, img->size, read_size, img->tail_length);
			iounmap(start);
			break;
		}
	}

	if(img->type == IMG_MD) {
		start = ioremap_nocache(round_down(load_addr + img->size - 0x4000, 0x4000), 0x4000*2 ); // Make sure in one scope
		end_addr = start + 0x4000 + (img->size - round_down(img->size, 0x4000));
		if((check_ret = check_md_header(md_id, end_addr, img)) < 0) {
			ret = check_ret;
			goto error;
		}
		iounmap(start);
	} else if(img->type == IMG_DSP) {
		start = ioremap_nocache(load_addr, size);
		if((check_ret = check_dsp_header(md_id, start, img))<0){
			ret = check_ret;
			goto error;	
		}
		iounmap(start);
	}

	set_fs(curr_fs);
	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Load %s (size=0x%x) to 0x%llx\n", img->file_name, read_size, (unsigned long long)load_addr);
	return read_size;

error:
	iounmap(start);
	set_fs(curr_fs);
	return ret;
}
Exemple #10
0
static int find_img_to_open(int md_id, MD_IMG_TYPE img_type, char active_file_path[], char active_post_fix[])
{
	char img_name[3][IMG_NAME_LEN];
	char full_path[IMG_PATH_LEN];
	int i;
	char post_fix[IMG_POSTFIX_LEN];
	char post_fix_ex[IMG_POSTFIX_LEN];
	struct file *filp = NULL;

	// Gen file name
	get_md_postfix(md_id, NULL, post_fix, post_fix_ex);

	if(img_type == IMG_MD){ // Gen MD image name
		snprintf(img_name[0], IMG_NAME_LEN, "modem_%s.img", post_fix); 
		snprintf(img_name[1], IMG_NAME_LEN, "modem_%s.img", post_fix_ex);
		snprintf(img_name[2], IMG_NAME_LEN, "%s", MOEDM_IMAGE_NAME); 
	} else if (img_type == IMG_DSP) { // Gen DSP image name
		snprintf(img_name[0], IMG_NAME_LEN, "dsp_%s.bin", post_fix); 
		snprintf(img_name[1], IMG_NAME_LEN, "dsp_%s.bin", post_fix_ex);
		snprintf(img_name[2], IMG_NAME_LEN, "%s", DSP_IMAGE_NAME);
	} else {
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "Invalid img type%d\n", img_type);
		return -CCCI_ERR_INVALID_PARAM;
	}

	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find img @CIP\n");
	for(i=0; i<3; i++) {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "try to open %s\n", img_name[i]);
		snprintf(full_path, IMG_PATH_LEN, "%s%s", CONFIG_MODEM_FIRMWARE_CIP_PATH, img_name[i]);
		filp = filp_open(full_path, O_RDONLY, 0644);
		if (IS_ERR(filp)) {
			continue;
		} else { // Open image success
			snprintf(active_file_path, IMG_PATH_LEN, full_path);
			filp_close(filp, current->files);
			if(i==0) {
				snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix);
			} else if(i==1) {
				snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix_ex);
			} else {
				active_post_fix[0] = '\0';
			}
			return 0;
		}
	}

	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Find img @default\n");
	for(i=0; i<3; i++) {
		CCCI_UTIL_INF_MSG_WITH_ID(md_id, "try to open %s\n", img_name[i]);
		snprintf(full_path, IMG_PATH_LEN, "%s%s", CONFIG_MODEM_FIRMWARE_PATH, img_name[i]);
		filp = filp_open(full_path, O_RDONLY, 0644);
		if (IS_ERR(filp)) {
			continue;
		} else { // Open image success
			snprintf(active_file_path, IMG_PATH_LEN, full_path);
			filp_close(filp, current->files);
			if(i==0) {
				snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix);
			} else if(i==1) {
				snprintf(active_post_fix, IMG_POSTFIX_LEN, "%s", post_fix_ex);
			} else {
				active_post_fix[0] = '\0';
			}
			return 0;
		}
	}
	
	active_post_fix[0] = '\0';
	CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"No Image file found\n");
	return -CCCI_ERR_LOAD_IMG_NOT_FOUND;
}
static int check_md_header(int md_id, void *parse_addr, struct ccci_image_info *image)
{
	int ret;
	bool md_type_check = false;
	bool md_plat_check = false;
	bool md_sys_match = false;
	bool md_size_check = false;
	unsigned int md_size;
	unsigned int header_size;
	int idx;
	unsigned char *start, *ptr;
	struct md_check_header *head = &md_img_header[md_id];
	get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);

	header_size = *(((unsigned int *)parse_addr) - 1);
	CCCI_UTIL_DBG_MSG_WITH_ID(md_id, "MD image header size = %d\n", header_size);
	if (header_size == sizeof(struct md_check_header_v3))
		return check_md_header_v3(md_id, parse_addr, image);

	/*memcpy(head, (void*)(parse_addr - sizeof(struct md_check_header)), sizeof(struct md_check_header)); */
	start = (unsigned char *)(head);
	ptr = (unsigned char *)(parse_addr - sizeof(struct md_check_header));
	for (idx = 0; idx < sizeof(struct md_check_header); idx++)
		*start++ = *ptr++;

	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check %d***************************\n",
				  (int)sizeof(struct md_check_header));
	ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
	if (ret) {
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist!\n");
		ret = 0;
	} else {
		if (head->header_verno > 2) {
			CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n",
						  head->header_verno);
		} else {
#ifdef ENABLE_2G_3G_CHECK
			if ((head->image_type != 0) && (head->image_type == md->config.load_type))
				md_type_check = true;
#else
			md_type_check = true;
#endif

#ifdef ENABLE_CHIP_VER_CHECK
			if (!strncmp(head->platform, ccci_get_ap_platform(), AP_PLATFORM_LEN))
				md_plat_check = true;
#else
			md_plat_check = true;
#endif

			if (head->bind_sys_id == (md_id + 1))
				md_sys_match = true;
#ifdef ENABLE_MEM_SIZE_CHECK
			if (head->header_verno == 2) {
				/*md_size = md->mem_layout.md_region_size; */
				if (head->mem_size == md_size) {
					md_size_check = true;
				} else if (head->mem_size < md_size) {
					md_size_check = true;
					CCCI_UTIL_INF_MSG_WITH_ID(md_id,
								  "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
								  head->mem_size, md_size);
				}
				image->img_info.mem_size = head->mem_size;
				image->ap_info.mem_size = md_size;
			} else {
				md_size_check = true;
			}
#else
			md_size_check = true;
#endif

			image->ap_info.image_type = type_str[head->image_type];
			image->ap_info.platform = ccci_get_ap_platform();
			image->img_info.image_type = type_str[head->image_type];
			image->img_info.platform = head->platform;
			image->img_info.build_time = head->build_time;
			image->img_info.build_ver = head->build_ver;
			image->img_info.product_ver = product_str[head->product_ver];
			image->img_info.version = head->product_ver;

			if (md_type_check && md_plat_check && md_sys_match && md_size_check) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
			} else {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
				if (!md_type_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");

				if (!md_plat_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");

				if (!md_sys_match)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n",
								  md_id + 1);

				if (!md_size_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id,
								  "[Reason]MD mem size mis-match to AP setting!\n");

				ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
			}

			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type,
						  image->ap_info.image_type);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform,
						  image->ap_info.platform);
			if (head->header_verno >= 2) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",
							  image->img_info.mem_size, image->ap_info.mem_size);
				if (head->md_img_size) {
					if (image->size >= head->md_img_size)
						image->size = head->md_img_size;
					else {
						CCCI_UTIL_INF_MSG_WITH_ID(md_id,
									  "[Reason]MD image size mis-match to AP!\n");
						ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
					}
					image->ap_info.md_img_size = image->size;
					image->img_info.md_img_size = head->md_img_size;
				}
				/* else {image->size -= 0x1A0;}  workaround for md not check in check header */
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n",
							  head->md_img_size, image->size);
			}
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",
						  image->img_info.build_ver, image->img_info.build_time);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n", image->img_info.product_ver);
		}
	}
	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check***************************\n");

	return ret;
}
static int check_md_header_v3(int md_id, void *parse_addr, struct ccci_image_info *image)
{
	int ret;
	bool md_type_check = false;
	bool md_plat_check = false;
	bool md_sys_match = false;
	bool md_size_check = false;
	int idx;
	unsigned int md_size;
	unsigned char *start, *ptr;

	struct md_check_header_v3 *head = &md_img_header_v3[md_id];
	get_md_resv_mem_info(md_id, NULL, &md_size, NULL, NULL);

	/*memcpy(head, (void*)(parse_addr - sizeof(struct md_check_header_v3)), sizeof(struct md_check_header_v3)); */
	start = (unsigned char *)(head);
	ptr = (unsigned char *)(parse_addr - sizeof(struct md_check_header_v3));
	for (idx = 0; idx < sizeof(struct md_check_header_v3); idx++)
		*start++ = *ptr++;

	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3 %d***************************\n",
				  (int)sizeof(struct md_check_header_v3));
	ret = strncmp(head->check_header, MD_HEADER_MAGIC_NO, 12);
	if (ret) {
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "md check header not exist!\n");
		ret = 0;
	} else {
		if (head->header_verno < 3) {
			CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "[Error]md check header version mis-match to AP:[%d]!\n",
						  head->header_verno);
		} else {
#ifdef ENABLE_2G_3G_CHECK
			if ((head->image_type != 0) && (head->image_type == md->config.load_type))
				md_type_check = true;
#else
			md_type_check = true;
#endif

#ifdef ENABLE_CHIP_VER_CHECK
			if (!strncmp(head->platform, ccci_get_ap_platform(), AP_PLATFORM_LEN))
				md_plat_check = true;
#else
			md_plat_check = true;
#endif

			if (head->bind_sys_id == (md_id + 1))
				md_sys_match = true;
#ifdef ENABLE_MEM_SIZE_CHECK
			if (head->header_verno >= 2) {
				/*md_size = md->mem_layout.md_region_size; */
				if (head->mem_size == md_size) {
					md_size_check = true;
				} else if (head->mem_size < md_size) {
					md_size_check = true;
					CCCI_UTIL_INF_MSG_WITH_ID(md_id,
								  "[Warning]md size in md header isn't sync to DFO setting: (%08x, %08x)\n",
								  head->mem_size, md_size);
				}
				image->img_info.mem_size = head->mem_size;
				image->ap_info.mem_size = md_size;
			} else {
				md_size_check = true;
			}
#else
			md_size_check = true;
#endif

			image->ap_info.image_type = type_str[head->image_type];
			image->ap_info.platform = ccci_get_ap_platform();
			image->img_info.image_type = type_str[head->image_type];
			image->img_info.platform = head->platform;
			image->img_info.build_time = head->build_time;
			image->img_info.build_ver = head->build_ver;
			image->img_info.product_ver = product_str[head->product_ver];
			image->img_info.version = head->product_ver;

			if (md_type_check && md_plat_check && md_sys_match && md_size_check) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "Modem header check OK!\n");
			} else {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Error]Modem header check fail!\n");
				if (!md_type_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD type(2G/3G) mis-match to AP!\n");

				if (!md_plat_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD platform mis-match to AP!\n");

				if (!md_sys_match)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "[Reason]MD image is not for MD SYS%d!\n",
								  md_id + 1);

				if (!md_size_check)
					CCCI_UTIL_INF_MSG_WITH_ID(md_id,
								  "[Reason]MD mem size mis-match to AP setting!\n");

				ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
			}

			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[type]=%s, (AP)[type]=%s\n", image->img_info.image_type,
						  image->ap_info.image_type);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[plat]=%s, (AP)[plat]=%s\n", image->img_info.platform,
						  image->ap_info.platform);
			if (head->header_verno >= 2) {
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[size]=%x, (AP)[size]=%x\n",
							  image->img_info.mem_size, image->ap_info.mem_size);
				if (head->md_img_size) {
					if (image->size >= head->md_img_size)
						image->size = head->md_img_size;
					else {
						char title[50];
						char info[100];
						snprintf(title, sizeof(title),
							 "MD%d mem size smaller than image header setting", md_id + 1);
						snprintf(info, sizeof(info),
							 "MD%d mem cfg size(0x%x)<header size(0x%x),please check memory config in <chip>.dtsi",
							 md_id + 1, image->size, head->md_img_size);
#if defined(CONFIG_MTK_AEE_FEATURE)
						aed_md_exception_api(NULL, 0, (const int *)info, sizeof(info), (const char *)title,
								     DB_OPT_DEFAULT);
#endif
						CCCI_UTIL_INF_MSG_WITH_ID(md_id,
									  "[Reason]MD image size mis-match to AP!\n");
						ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
					}
					image->ap_info.md_img_size = image->size;
					image->img_info.md_img_size = head->md_img_size;
				}
				/* else {image->size -= 0x1A0;} workaround for md not check in check header */
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[img_size]=%x, (AP)[img_size]=%x\n",
							  head->md_img_size, image->size);
			}
			if (head->header_verno >= 3) {
				image->dsp_offset = head->dsp_img_offset;
				image->dsp_size = head->dsp_img_size;
				CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset=%x size=%x\n", image->dsp_offset,
							  image->dsp_size);
				if (image->dsp_offset == 0xCDCDCDAA) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP on EMI disabled\n");
				} else if ((image->dsp_offset & 0xFFFF) != 0) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image offset not 64KB align\n");
					ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
				} else if (image->dsp_offset + image->dsp_size > md_size) {
					CCCI_UTIL_INF_MSG_WITH_ID(md_id, "DSP image size too large %x\n", md_size);
					ret = -CCCI_ERR_LOAD_IMG_MD_CHECK;
				}
			} else {
				image->dsp_offset = 0;
			}
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[build_ver]=%s, [build_time]=%s\n",
						  image->img_info.build_ver, image->img_info.build_time);
			CCCI_UTIL_INF_MSG_WITH_ID(md_id, "(MD)[product_ver]=%s\n", image->img_info.product_ver);
		}
	}
	CCCI_UTIL_INF_MSG_WITH_ID(md_id, "**********************MD image check V3***************************\n");

	return ret;
}