blob: 7f632ed2065a4202b6f4193729bda1ab4fe0be99 [file] [log] [blame]
/*********************************************************************
Copyright 2016 by ZIXC Corporation.
*
* FileName:: partition.c
* File Mark:
* Description:
* Others:
* Version: v1.0
* Author: zhouqi
* Date: 2014-1-15
* History 1:
* Date:
* Version:
* Author:
* Modification:
* History 2:
**********************************************************************/
#include <common.h>
#include <errno.h>
#include <command.h>
#include <malloc.h>
#include <jffs2/load_kernel.h>
#include <linux/list.h>
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
#include <nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <load_image.h>
#include <boot_mode.h>
#include <config.h>
#define DEFINE_PARTITION_TABLE
#include <partition_table.h>
#include <boot_mode.h>
#if defined(CONFIG_CMD_NAND)
#include <linux/mtd/nand.h>
#include <nand.h>
#endif
#include <linux/mtd/nor_spifc.h>
u_char * g_table = NULL; /* ¶ÁÈ¡µÄ·ÖÇø±íÐÅÏ¢ 2k+64 */
partition_table_t * g_partition_table = NULL; /* Ö¸Ïò·ÖÇø±íÐÅÏ¢ */
extern partition_table_t * g_partition_table_dl;
extern struct fsl_qspi spi_nor_flash;
#ifdef CONFIG_ZX297520V3E_MDL_AB
extern int imagefs_flag;
#endif
/* ================================================================================
* add_partition_to_bootargs : Ôö¼Ó·ÖÇøÐÅÏ¢µ½ bootargs
*/
#ifdef CONFIG_ZX297520V3E_MDL_AB
void add_partition_to_bootargs( void )
{
int ret = 0;
uint32_t part_nums = 0;
uint32_t i = 0;
uint32_t start_entry = 0; /* Æô¶¯·ÖÇøºÅ */
uchar bootargs_cmd[1024] = {0};
uchar boot_reason_para[32] = {0};
uchar boot_mode_para[16] = {0};
unsigned int *poweron_type = (unsigned int *)POWERON_TYPE_ADDR; //ÁÙʱʹÓÃ
part_nums = g_partition_table->entrys;
partition_entry_t * entry = &g_partition_table->table[0];
/* console=ttyS1,115200 no_console_suspend */
sprintf((char *)bootargs_cmd, "console=ttyS1,921600 no_console_suspend");
/* denali-nand: */
if(read_boot_flashtype() == IF_TYPE_NAND)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=denali-nand:");
}
else if (read_boot_flashtype() == IF_TYPE_SPI_NAND)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=spi-nand:");
}
else if (read_boot_flashtype() == IF_TYPE_NOR)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=spi-nor-dt:");
}
/* È¥³ý×îºóµÄ2¸ö·ÖÇø ddr raw */
for( i=0; i<part_nums-VIRTUAL_PART_NUM-1; i++ )
{
if( (entry->part_size >= 0x100000) && (entry->part_size%0x100000 == 0) )
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dm@0x%lx(%s),",
(entry->part_size) >> 20, (entry->part_offset), (entry->part_name));
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dk@0x%lx(%s),",
(entry->part_size) >> 10, (entry->part_offset), (entry->part_name));
}
/* »ñÈ¡Æô¶¯·ÖÇøºÅ */
//if(read_fota_update_flag())
if(imagefs_flag == 1)
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_ROOTFS_IMAGE ) )
{
start_entry = i;
}
}
else if(imagefs_flag == 2)
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_ROOTFS2_IMAGE ) )
{
start_entry = i;
}
}
entry++;
}
/* »ñÈ¡Æô¶¯·ÖÇøºÅ */
if(imagefs_flag == 1)
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_ROOTFS_IMAGE) )
{
start_entry = i + 1;
}
}
else if(imagefs_flag == 2)
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_ROOTFS2_IMAGE ) )
{
start_entry = i + 1;
}
}
/* ×îºóÒ»¸ö·ÖÇø */
if( (entry->part_size >= 0x100000) && (entry->part_size%0x100000 == 0) )
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dm@0x%lx(%s)",
(entry->part_size) >> 20, (entry->part_offset), (entry->part_name));
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dk@0x%lx(%s)",
(entry->part_size) >> 10, (entry->part_offset), (entry->part_name));
}
/* rootfs=/dev/mtdblock7 rootfs2=/dev/mtdblock8 */
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd),
" root=/dev/mtdblock%d ro rootfstype=jffs2", start_entry);
printf("rootfs%d entry...\n",start_entry);
if(RB_AMT == read_boot_reason())
{
*poweron_type = POWER_ON_AMT;
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " boot_reason=%d", *poweron_type);
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " bootmode=amt");
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " boot_reason=%d", *poweron_type);
}
BOOT_PRINTF(UBOOT_INFO, "CONFIG_SYS_START_FLAG_ADDR = 0x%x, poweron_type = 0x%x.\n",
POWERON_TYPE_ADDR, *poweron_type);
if(imagefs_flag == 1)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " system=system_a");
}
else if(imagefs_flag == 2)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " system=system_b");
}
/* save */
setenv("bootargs", (char *)bootargs_cmd);
}
#else
void add_partition_to_bootargs( void )
{
int ret = 0;
uint32_t part_nums = 0;
uint32_t i = 0;
uint32_t start_entry = 0; /* Æô¶¯·ÖÇøºÅ */
uchar bootargs_cmd[1024] = {0};
uchar boot_reason_para[32] = {0};
uchar boot_mode_para[16] = {0};
unsigned int *poweron_type = (unsigned int *)POWERON_TYPE_ADDR; //ÁÙʱʹÓÃ
part_nums = g_partition_table->entrys;
partition_entry_t * entry = &g_partition_table->table[0];
/* console=ttyS1,115200 no_console_suspend */
sprintf((char *)bootargs_cmd, "console=ttyS1,921600 no_console_suspend");
/* denali-nand: */
if(read_boot_flashtype() == IF_TYPE_NAND)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=denali-nand:");
}
else if (read_boot_flashtype() == IF_TYPE_SPI_NAND)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=spi-nand:");
}
else if (read_boot_flashtype() == IF_TYPE_NOR)
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " mtdparts=spi-nor-dt:");
}
/* È¥³ý×îºóµÄ2¸ö·ÖÇø ddr raw */
for( i=0; i<part_nums-VIRTUAL_PART_NUM-1; i++ )
{
if( (entry->part_size >= 0x100000) && (entry->part_size%0x100000 == 0) )
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dm@0x%lx(%s),",
(entry->part_size) >> 20, (entry->part_offset), (entry->part_name));
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dk@0x%lx(%s),",
(entry->part_size) >> 10, (entry->part_offset), (entry->part_name));
}
/* »ñÈ¡Æô¶¯·ÖÇøºÅ */
if(read_fota_update_flag())
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_RECOVERY_USERDATA_IMAGE ) )
{
start_entry = i;
}
}
else
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_USERDATA_IMAGE ) )
{
start_entry = i;
}
}
entry++;
}
/* »ñÈ¡Æô¶¯·ÖÇøºÅ */
if(read_fota_update_flag()) /* 3±íʾFOTA-RECOVERY */
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_RECOVERY_USERDATA_IMAGE) )
{
start_entry = i + 1;
}
}
else /* Õý³£Æô¶¯Á÷³Ì */
{
if ( 0 == strcmp( (char *)entry->part_name, (char *)ARM_USERDATA_IMAGE ) )
{
start_entry = i + 1;
}
}
/* ×îºóÒ»¸ö·ÖÇø */
if( (entry->part_size >= 0x100000) && (entry->part_size%0x100000 == 0) )
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dm@0x%lx(%s)",
(entry->part_size) >> 20, (entry->part_offset), (entry->part_name));
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), "%dk@0x%lx(%s)",
(entry->part_size) >> 10, (entry->part_offset), (entry->part_name));
}
if(RB_AMT == read_boot_reason())
{
*poweron_type = POWER_ON_AMT;
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " boot_reason=%d", *poweron_type);
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " bootmode=amt");
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " boot_reason=%d", *poweron_type);
}
BOOT_PRINTF(UBOOT_INFO, "CONFIG_SYS_START_FLAG_ADDR = 0x%x, poweron_type = 0x%x.\n",
POWERON_TYPE_ADDR, *poweron_type);
if(read_fota_update_flag())
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " system=recovery");
}
else
{
sprintf((char *)bootargs_cmd + strlen(bootargs_cmd), " system=normal");
}
/* save */
setenv("bootargs", (char *)bootargs_cmd);
}
#endif
/*******************************************************************************
* Function: read_partition_and_check
* Description: ´ÓFLASHÖжÁÈ¡·ÖÇø±í
* Parameters:
* Input:
*
* Output:
*
* @return 0 : ¶ÁÈ¡·ÖÇø±íÓÐЧ
* @return 1 : ¶ÁÈ¡·ÖÇø±íÎÞЧ
*
* Others:
********************************************************************************/
int read_partition_and_check( void )
{
struct flash_ops *flash = NULL;
nand_info_t *nand = &nand_info[nand_curr_device];
int table_size = 2048;
int ret = 0;
int type = 0;
int buf_size = 0;
struct fsl_qspi *nor;
nor = &spi_nor_flash;
flash = get_flash_ops();
type = read_boot_flashtype();
if(type == IF_TYPE_NAND || type == IF_TYPE_SPI_NAND)
{
buf_size = nand->writesize + nand->oobsize;
}
else if(type == IF_TYPE_NOR)
{
buf_size = table_size;
}
g_table = (u_char *)kzalloc(buf_size, GFP_KERNEL);
if ( g_table == NULL )
{
BOOT_PRINTF(UBOOT_ERR, "kzalloc Failed!\n");
return -EIO;
}
/* ¶ÁÈ¡·ÖÇø±í */
/*
+------------------------------------------------------------+
| z-load.bin | partition_table.bin |
+------------------------------------------------------------+
8k one page 10k
*/
if(type == IF_TYPE_NAND || type == IF_TYPE_SPI_NAND)
{
ret = flash->read_with_ecc(nand, (loff_t)8*1024, &table_size, g_table);
if(ret)
{
BOOT_PRINTF(UBOOT_ERR, "read_no_ecc Failed! ret = %d.\n", ret);
return -1;
}
}
else if(type == IF_TYPE_NOR)
{
ret = nand_read(&(nor->nor[0].mtd), (loff_t)8*1024, &table_size, g_table);
if(ret)
{
BOOT_PRINTF(UBOOT_ERR, "nand_read error! ret = %d.\n", ret);
return -1;
}
}
g_partition_table = (partition_table_t *)g_table;
if( g_partition_table->magic != PARTITION_MAGIC )
{
BOOT_PRINTF(UBOOT_ERR, "Partition Table Invalid! ret = %d.\n", ret);
return -EIO;
}
return SUCCESS;
}
/*******************************************************************************
* Function: find_partition_para
* Description: ͨ¹ý·ÖÇøÃû²éÕÒ·ÖÇøÊ×µØÖ·
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
partition_entry_t * find_partition_para( uchar * name )
{
partition_entry_t *entry = NULL;
uint32_t entry_nums = 0;
if(get_load_mode() == TLOAD_MODE)
{
entry = &g_partition_table_dl->table[0];
entry_nums = g_partition_table_dl->entrys;
}
else
{
entry = &g_partition_table->table[0];
entry_nums = g_partition_table->entrys;
}
while( entry_nums-- )
{
if ( strcmp( (char *)entry->part_name, (char *)name ) == 0 )
{
return entry;
}
entry++;
}
return NULL;
}
/*******************************************************************************
* Function: partition_init
* Description: ͨ¹ý·ÖÇøÃû²éÕÒ·ÖÇøÊ×µØÖ·
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int partition_init(void)
{
int ret = 0;
ret = read_partition_and_check();
if( ret != 0 )
{
BOOT_PRINTF(UBOOT_ERR, "read_partition ERROR !!!\n");
return -1;
}
return 0;
}