| /* | 
 |  * (C) Copyright 2016 ZXIC Inc. | 
 |  */ | 
 | #include <common.h>    | 
 | #include <asm/io.h> | 
 | #include <asm/string.h> | 
 |  | 
 | #include <image.h> | 
 | #include <linux/byteorder/generic.h> | 
 | #include <secure_verify.h> | 
 |  | 
 | #include "flash.h" | 
 | #include <bbt.h> | 
 | #include "pub_flags.h" | 
 |  | 
 | /* | 
 |  ****************************************************************************** | 
 |  * Function:      | 
 |  * Description:  | 
 |  * Parameters: | 
 |  *	 Input: | 
 |  *	 Output: | 
 |  * Returns: | 
 |  * Others: | 
 |  ******************************************************************************* | 
 |  */ | 
 | uint32_t page_align(uint32_t offset) | 
 | { | 
 |     uint32_t page_size = flash.page_size; | 
 |     if(offset & (page_size - 1)) | 
 |     { | 
 |         offset &= (~(page_size - 1)); | 
 |         offset += page_size; | 
 |     } | 
 |     return offset; | 
 | } | 
 |  | 
 |  | 
 | /* | 
 |  ****************************************************************************** | 
 |  * Function:      | 
 |  * Description:  | 
 |  * Parameters: | 
 |  *	 Input: | 
 |  *	 Output: | 
 |  * Returns: | 
 |  * Others: | 
 |  ******************************************************************************* | 
 |  */ | 
 | uint32_t find_partition_para(partition_entry_t *entry,  | 
 |  									   uint32_t entrys,  | 
 |  									   uint8_t *name) | 
 | { | 
 |     partition_entry_t *p_entry = entry; | 
 |     uint32_t entry_nums = entrys; | 
 |     while(entry_nums--) | 
 |     { | 
 |         if(memcmp( p_entry->part_name, name, strlen(name)) == 0) | 
 |             return p_entry->part_offset; | 
 |         p_entry++; | 
 |     } | 
 |     return -1; | 
 | } | 
 |  | 
 | /* | 
 |  ****************************************************************************** | 
 |  * Function:      | 
 |  * Description:  | 
 |  * Parameters: | 
 |  *	 Input: | 
 |  *	 Output: | 
 |  * Returns: | 
 |  * Others: | 
 |  ******************************************************************************* | 
 |  */ | 
 | int read_image_part_offset(uint8_t *name, uint32_t *offset) | 
 | { | 
 | 	int ret = 0; | 
 | 	uint32_t part_size = 0; | 
 |  | 
 | 	if(flash.flash_type == NOR_BOOT) | 
 | 	{ | 
 | 		part_size = 8*flash.page_size; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		part_size = flash.page_size;	 | 
 | 	} | 
 |  | 
 | 	ret = flash.read(0x2000, part_size, CFG_TEMP_ADDR); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		return -1; | 
 | 	} | 
 |              | 
 | 	partition_table_t *part = (partition_table_t  *)CFG_TEMP_ADDR;    | 
 | 	partition_entry_t *entry = &part->table[0]; | 
 | 	uint32_t entrys = part->entrys; | 
 |  | 
 | 	if(part->magic != CFG_PARTITION_MAGIC) | 
 | 	{ | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	*offset = find_partition_para(entry, entrys, name); | 
 | 	if(*offset == -1 ) | 
 | 	{ | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | //#ifdef CONFIG_ZX297520V3E_MDL_AB | 
 | #if defined(CONFIG_ZX297520V3E_MDL_AB) || defined(CONFIG_ZX297520V3E_VEHICLE_DC) || defined(CONFIG_ZX297520V3E_VEHICLE_DC_REF) | 
 | int read_flags_image(uint8_t *name) | 
 | { | 
 |     T_FLAGS_INFO *fotaFlag; | 
 | 	uint32_t uiPageSize = 0; | 
 |     uint32_t flags_offset = 0; | 
 | 	uint32_t off = 0; | 
 | 	uint32_t flags_size = 0x4E0000;/*flags·ÖÇø*/ | 
 | 	uint32_t blockNum = 0; | 
 | 	int32_t flag_one = 0; | 
 | 	uint32_t work_area_offset = 0; | 
 | 	uint32_t backup_area_offset = 0; | 
 | 	int32_t ret = 0; | 
 | 	int32_t fota_size = sizeof(T_FLAGS_INFO); | 
 | 	int32_t block_size = flash.block_size; | 
 |  | 
 | 	fota_size = page_align(fota_size); | 
 |  | 
 | 	ret = read_image_part_offset(name, &flags_offset); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("flags partition offset fail.\n"); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	/*È·¶¨¹¤×÷ÇøºÍ±¸·ÝÇøÆ«ÒÆµØÖ·*/ | 
 | 	for (off = flags_offset; off < flags_offset+flags_size; off += flash.block_size) | 
 | 	{ | 
 | 		if (!(nand_block_isbad(off))) | 
 | 		{ | 
 |             blockNum += 1; | 
 | 		}    | 
 | 		 | 
 | 		if((blockNum == 1) && (flag_one == 0)) | 
 | 		{ | 
 |             work_area_offset = off; | 
 | 			flag_one = 1; | 
 | 		} | 
 | 	 | 
 | 		else if(blockNum == 2) | 
 | 		{ | 
 |              backup_area_offset = off; | 
 | 			 break; | 
 | 		}		 | 
 | 	} | 
 |  | 
 | 	if(blockNum < 2) | 
 | 	{ | 
 |         printf("flags partition have not enough space!\n"); | 
 | 			 | 
 | 		return -1; | 
 | 	} | 
 | 	 | 
 | 	ret = flash.read(work_area_offset, fota_size, CFG_TEMP_ADDR); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("read flags work partition err.\n"); | 
 | 		 | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	fotaFlag = (T_FLAGS_INFO *)(CFG_TEMP_ADDR); | 
 | 	 | 
 | 	if(fotaFlag->magic_start != FLAGS_MAGIC || fotaFlag->magic_end != FLAGS_MAGIC) | 
 | 	{ | 
 |         ret = flash.read(backup_area_offset, fota_size, CFG_TEMP_ADDR); | 
 | 		if(ret != 0) | 
 | 		{ | 
 | 			printf("read flags backup partition err.\n"); | 
 | 			 | 
 | 			return -1; | 
 | 		} | 
 | 		fotaFlag = (T_FLAGS_INFO *)(CFG_TEMP_ADDR); | 
 | 		if(fotaFlag->magic_start != FLAGS_MAGIC || fotaFlag->magic_end != FLAGS_MAGIC) | 
 | 		{ | 
 |             printf("flags magic err.\n"); | 
 | 		    return -1; | 
 | 		}	 | 
 | 	} | 
 | 	 | 
 | 	return 0; | 
 |      | 
 | } | 
 | #endif | 
 | /* | 
 |  **************************************************************************** | 
 |  * Function:      | 
 |  * Description:  | 
 |  * Parameters: | 
 |  *	 Input: | 
 |  *	 Output: | 
 |  * Returns: | 
 |  * Others: | 
 |  ***************************************************************************** | 
 |  */ | 
 | int read_uboot_image(uint8_t *name, uint32_t *uboot_entry_point) | 
 | { | 
 | 	/* | 
 | 	 * +----------------------------------------------------------------+ | 
 | 	 * |  sImageHeader  |  image_header_t  |    u-boot.bin     |                 | 
 | 	 * +----------------------------------------------------------------+ | 
 | 	 * |    384 Bytes      |     64 Bytes         |    xxx Bytes       | | 
 | 	 *                                  | 
 | 	 */ | 
 |  | 
 | 	image_header_t *psImgHdrOld = NULL; | 
 |  | 
 | 	uint32_t uiPageSize = 0; | 
 |  | 
 | 	uint32_t uiImgHdrSizeOld = sizeof(image_header_t); | 
 | 	uint32_t uiImgHdrSizeNew = sizeof(sImageHeader); | 
 |  | 
 | 	uint32_t uiUBootSize = 0; | 
 | 	uint32_t uiUBootLoadAddr = 0; | 
 | 	uint32_t uiUBootIsReadSize = 0; | 
 |  | 
 | 	int32_t ret = 0; | 
 | 	uint32_t uboot_offset = 0; | 
 |  | 
 |  | 
 | 		 | 
 | 	if(flash.flash_type == NOR_BOOT) | 
 | 	{ | 
 | 		uiPageSize = 8*flash.page_size; | 
 | 	} | 
 | 	else  | 
 | 	{ | 
 | 		uiPageSize = flash.page_size;	 | 
 | 	} | 
 |  | 
 | 	ret = read_image_part_offset(name, &uboot_offset); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("offset fail.\n"); | 
 | 		return -1; | 
 | 	} | 
 | 	 | 
 | 	ret = flash.read(uboot_offset, uiPageSize, CFG_TEMP_ADDR); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("image header err.\n"); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	psImgHdrOld = (image_header_t *)(CFG_TEMP_ADDR + uiImgHdrSizeNew); | 
 | 	uiUBootSize = ___htonl(psImgHdrOld->ih_size);    | 
 | 	uiUBootLoadAddr = ___htonl(psImgHdrOld->ih_load); | 
 | 	*uboot_entry_point = ___htonl(psImgHdrOld->ih_ep); | 
 |  | 
 | 	if(___htonl(psImgHdrOld->ih_magic) != IH_MAGIC) | 
 | 	{ | 
 | 		printf("magic err.\n"); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	uiUBootIsReadSize = uiPageSize - uiImgHdrSizeOld - uiImgHdrSizeNew; | 
 | 	uiUBootSize -= uiUBootIsReadSize;			 | 
 | 	uiUBootSize = page_align(uiUBootSize);    | 
 |  | 
 | 	memcpy(uiUBootLoadAddr - uiImgHdrSizeOld,  | 
 | 			CFG_TEMP_ADDR + uiImgHdrSizeNew,  | 
 | 		   	uiUBootIsReadSize + uiImgHdrSizeOld); | 
 |  | 
 | 	ret = flash.read(uboot_offset + uiPageSize,  | 
 | 						uiUBootSize,  | 
 | 						uiUBootLoadAddr + uiUBootIsReadSize); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("image err.\n"); | 
 | 		return -1; | 
 | 	} | 
 | 	 | 
 | 	ret = SecureVerify(CFG_TEMP_ADDR); | 
 | 	if(ret != 0) | 
 | 	{ | 
 | 		printf("Secure verify fail!\n"); | 
 | 		return -1; | 
 | 	} | 
 | 	 | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  ****************************************************************************** | 
 |  * Function:      | 
 |  * Description:  | 
 |  * Parameters: | 
 |  *	 Input: | 
 |  *	 Output: | 
 |  * Returns: | 
 |  * Others: | 
 |  ******************************************************************************* | 
 |  */ | 
 |  int nand_read_m0(uint32_t *m0_entry_point) | 
 | { | 
 | 	int remap = 0; | 
 | 	image_header_t *header = NULL; | 
 | 	uint32_t image_header_size = sizeof(image_header_t); | 
 | 	uint32_t m0_size = 0; | 
 | 	uint32_t m0_load_addr = 0; | 
 | 	/* | 
 | 	 * +---------------------------------------------------------+ | 
 | 	 * |  image_header_t    |          m0                        |                 | 
 | 	 * +---------------------------------------------------------+ | 
 |                             m0.bin | 
 | 	 */ | 
 |  | 
 | 	/*1¡¢µÈ´ýBOOT°áÔËM0°æ±¾µ½CONFIG_SYS_SDRAM_TEMP_BASEÖÐ*/ | 
 | 	writel(0, M0_IMAGE_READY_FLAG_ADDR); | 
 | 	while(!readl(M0_IMAGE_READY_FLAG_ADDR)); | 
 |  | 
 | 	/*2¡¢M0µÄ0µØÖ·ÖØÓ³Éä*/ | 
 | 	remap = readl(0x140000); | 
 | 	remap |= 0x800000; | 
 | 	writel(remap,0x140000); | 
 |  | 
 | 	/*3¡¢½âÎöM0µÄ°æ±¾Í·£¬»ñÈ¡ÔËÐеØÖ·ÒÔ¼°´óС*/ | 
 | 	header = (image_header_t *)CONFIG_SYS_SDRAM_TEMP_BASE; | 
 | 	m0_size = ___htonl(header->ih_size);    /* m0.bin */ | 
 | 	m0_load_addr = ___htonl(header->ih_load); | 
 | 	*m0_entry_point = ___htonl(header->ih_ep);    | 
 |  | 
 | 	if(___htonl(header->ih_magic) != IH_MAGIC) | 
 | 	{ | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	/*4¡¢½«M0µÄ°æ±¾´ÓIRAM0¿½±´µ½load_addr*/ | 
 | 	memcpy(m0_load_addr, CONFIG_SYS_SDRAM_TEMP_BASE + image_header_size, m0_size);  | 
 |  | 
 | 	/*5¡¢ÐÞ¸ÄIRAM±ê¼Ç£¬Ê¹BOOT¼ÌÐøÍùÏÂÖ´ÐÐ*/ | 
 | 	writel(0, M0_IMAGE_READY_FLAG_ADDR); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 |  |