blob: 09c296ad8b4f9bbe3f8b0c6f10953509de068d83 [file] [log] [blame]
/*
* (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;
}