| /* |
| * (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> |
| |
| |
| /* |
| ****************************************************************************** |
| * 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) |
| int read_flags_image(uint8_t *name) |
| { |
| T_BOOT_FOTA_FLAG *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_BOOT_FOTA_FLAG); |
| 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_BOOT_FOTA_FLAG *)(CFG_TEMP_ADDR); |
| |
| if(fotaFlag->magic != 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_BOOT_FOTA_FLAG *)(CFG_TEMP_ADDR); |
| if(fotaFlag->magic != 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; |
| } |
| |
| |