Exemple #1
0
/**
* 作用:读取分区相对偏移地址的标志值,主要是为NV模块用,查询此分区的偏移地址的标志位的值
*
* 参数:
* @partition_name         	---分区名
* @partition_offset         ---分区的相对偏移
* @flag                     ---把检测的分区的标志值存放在此flag中
* 描述:NV模块把一个分区的一个block的最后一页的OOB中存放特定标记值,读此标记值存放在flag中
*/
u32 bsp_nand_read_flag_nv(const char *partition_name, u32 partition_offset, unsigned char *flag)
{
    u32 flash_addr;
    u32 ret = NANDC_ERROR;
    static unsigned char *buffer = NULL;
    struct nand_spec spec;
    struct ST_PART_TBL * ptable = find_partition_by_name((char *)partition_name);
	/*参数不对*/
    if(!ptable)
    {
        goto ERRO;
    }
    if(!flag)
    {
        NAND_TRACE(("argu error.\n"));
        goto ERRO;
    }
	/*得到此分区的nandflash的规格参数*/
    ret = bsp_get_nand_info(&spec);
    if(ret)
    {
        goto ERRO;
    }
	/*没有内存时分配内存*/
    if(!buffer)
    {
        buffer = (unsigned char *)himalloc(spec.pagesize + YAFFS_BYTES_PER_SPARE);
        if(!buffer)
        {
    		NAND_TRACE(("get ram buffer failed!\n"));
    		goto ERRO;
        }
    }

    memset(buffer, 0xFF, spec.pagesize + YAFFS_BYTES_PER_SPARE);

    flash_addr = ptable->offset + partition_offset;
	/*使能ECC功能的带OOB读数据功能*/
    ret = nand_read_oob((flash_addr + spec.blocksize - spec.pagesize),
          (unsigned int)buffer, (spec.pagesize + YAFFS_BYTES_PER_SPARE),YAFFS_BYTES_PER_SPARE ,NULL);
    if(ret)
    {
		NAND_TRACE(("nand read oob failed!\n"));
		goto ERRO;
    }
    *flag = (*(buffer + spec.pagesize) == NV_WRITE_SUCCESS) ? NV_WRITE_SUCCESS : (~NV_WRITE_SUCCESS);

    return NANDC_OK;
ERRO:
    return ret;
}
Exemple #2
0
/**
* 作用:nandc模块按分区名的使能ECC功能的读数据操作,注意此函数的读操作不能读OOB数据
*
* 参数:
* @partition_name          		---要读的分区名
* @partition_offset      	    ---要读分区的相对偏移地址
* @ptr_ram_addr      	        ---读到内存的地址
* @length      	        		---读的数据长度
* @skip_len                     ---过滤的长度,当在读的过程中遇到坏块时跳过要读的块,此结构记录跳过的长度
*
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,把读到的数据存放在ptr_ram_addr中去
*/
int bsp_nand_read(const char *partition_name, u32 partition_offset, void* ptr_ram_addr, u32 length, u32 *skip_len)
{
    u32 flash_addr;
    u32 ret = NANDC_ERROR;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);

    if(!ptable)
    {
        goto ERRO;
    }
	/*通过分区名来转到Flash的地址*/
    flash_addr = ptable->offset + partition_offset;
	/*要Flash的数据到内存中*/
	return nand_read(flash_addr, (u32)ptr_ram_addr, length, skip_len);
ERRO:
    return ret;
}
Exemple #3
0
/**
* 作用:nandc模块按分区名和分区相对偏移来确定此块是不是坏块
*
* 参数:
* @partition_name          		---查询数据块的分区名
* @partition_offset      	    ---查询数据块的分区相对偏移地址
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来判断此block是不是坏块
返回值:
* 0表示此块是好块
* 1表示是坏块
* 其他的表示有错误
*/
int bsp_nand_isbad(const char *partition_name, u32 partition_offset)
{
    u32 flash_addr;
    u32 bad_flag;
    u32 ret = NANDC_ERROR;
	struct nandc_host  * host   = NULL;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);

    if(!ptable)
    {
        goto ERRO;
    }

    /*得到Flash地址*/
    flash_addr = ptable->offset + partition_offset;

    host = nandc_nand_host;
    if(!host)
    {
        NAND_TRACE(("ERROR: function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }
	/*判断此block是否是坏块*/
	ret = nand_isbad(flash_addr / host->nandchip->spec.blocksize, &bad_flag);
    if(ret == 1)
    {
        return -6;
    }
    else if(ret > 1)
    {
        return ret;
    }

    if(bad_flag == 1)  /* bad block */
    {
        return 1;
    }
    else               /* good block */
    {
        return 0;
    }

ERRO:
    return ret;
}
Exemple #4
0
/**
* 作用:nandc模块按分区名和分区相对偏移来使能ECC功能的写数据操作,注意此函数的写操作带OOB数据且在写的过程中会擦除nandflash
*
* 参数:
* @partition_name          		---要写数据的分区名
* @partition_offset      	    ---要写数据的分区相对偏移地址
* @ptr_ram_addr          		---要写数据的地址
* @length      	    			---要写数据的长度
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来写Flash操作
*/
s32 bsp_nand_write(const char *partition_name, u32 partition_offset, void* ptr_ram_addr, u32 length)
{
    u32 flash_addr, ret = NANDC_ERROR;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);

    if(!ptable)
    {
        goto ERRO;
    }

    /*得到要写Flash的地址*/
    flash_addr = ptable->offset + partition_offset;
	/*在写的过程中会擦除nandflash,因此不需要调用者再来擦除一次*/
	return nand_write(flash_addr, (u32)ptr_ram_addr, length, NULL);

 ERRO:
    return ret;
}
Exemple #5
0
/**
* 作用:nandc模块按分区名和分区偏移地址来擦除flash操作
*
* 参数:
* @partition_name          		---要擦除的分区名
* @partition_offset      	    ---要擦除的相对偏移地址
*
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来擦除一个block,注意是擦除一个block数据块
*/
int bsp_nand_erase(const char *partition_name, u32 partition_offset)
{
    u32 flash_addr;
    u32 block_id, bad_flag;
    u32 ret = NANDC_ERROR;
	struct nandc_host  * host   = NULL;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);
	/*参数不正确*/
    if(!ptable)
    {
        goto ERRO;
    }

    /*得到flash的地址信息*/
    flash_addr = ptable->offset + partition_offset;

    host = nandc_nand_host;
    if(!host)
    {
        NAND_TRACE(("ERROR: function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }

    /*得到块号并判断是否是坏块*/
    block_id = flash_addr / host->nandchip->spec.blocksize;
    ret = nand_isbad(block_id, &bad_flag);
    if(ret)
    {
        NAND_TRACE(("ERROR: nand quary bad failed, function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }

    if(NANDC_BAD_BLOCK == bad_flag)
    {
        NAND_TRACE(("ERROR: try to erase a bad block, function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }
	/*擦除flash操作*/
	return nand_erase(block_id);

ERRO:
    return ret;
}
Exemple #6
0
static struct mi_root* ds_mi_reload(struct mi_root* cmd_tree, void* param)
{
	struct mi_node* node = cmd_tree->node.kids;
	if(node != NULL){
		ds_partition_t *partition = find_partition_by_name(&node->value);
		if (partition == NULL)
			return init_mi_tree(500, MI_SSTR(MI_UNK_PARTITION) );
		if (ds_reload_db(partition) < 0)
			return init_mi_tree(500, MI_SSTR(MI_ERR_RELOAD));
		else
			return init_mi_tree(200, MI_SSTR(MI_OK_S) );
	}

	ds_partition_t *part_it;
	for (part_it = partitions; part_it; part_it = part_it->next)
		if (ds_reload_db(part_it)<0)
			return init_mi_tree(500, MI_SSTR(MI_ERR_RELOAD));

	return init_mi_tree(200, MI_SSTR(MI_OK_S));
}
Exemple #7
0
/****************************************************************
函数功能: 在fastboot阶段获取分区大小
输入参数: partition_name-分区名称
输出参数: none
返回参数: 分区size
注意事项: 在fastboot阶段调用
****************************************************************/
unsigned int bsp_get_part_cap( const char *partition_name )
{
    unsigned int ret_size = 0;
    struct ST_PART_TBL * ptable = ( void* )( 0 );

    if ( ( void* )( 0 ) == partition_name )
    {
        cprintf( "fastboot: nv dload partition_name is NULL!\n" );
        goto ERRO;
    }

    ptable = find_partition_by_name(partition_name);
    if(!ptable)
    {
        cprintf( "fastboot: nv dload get ptable fail!\n" );
        goto ERRO;
    }

    ret_size = ptable->capacity;
    cprintf( "fastboot: nv dload cap is 0x%x.\n", ret_size );

ERRO:
    return ret_size;
}
Exemple #8
0
/******************************************************************************************
 * FUNC NAME:
 * @bsp_update_size_of_lastpart() - external API:
 *
 * PARAMETER:
 * @new_ptable - addr of new ptable
 *
 * RETURN:
 *    null
 *
 * DESCRIPTION:
 *    update the size of last partition to shared memory
 *    分区表最后一个分区将flash最后一块空间完全占有,从而导致静态编译的ptable.bin与软件实际使用的ptable不一样,
 *    升级分区表的时候就认为两个分区不一样,从而导致对yaffs分区的擦除。此处用实际使用的分区表最后一个分区大小
 *    覆盖新ptable最后分区大小
 *
 * CALL FUNC:
 *
 *****************************************************************************************/
void bsp_update_size_of_lastpart(struct ST_PART_TBL *new_ptable)
{
    struct ST_PART_TBL * old_ptable = NULL;
    if(!new_ptable)
    {
        NAND_TRACE(("[%s]argu error\n", __FUNCTION__));
        return;
    }

    /*根据分区名得到分区数据结构*/
    while(0 != strcmp(PTABLE_END_STR, new_ptable->name))
    {
        new_ptable++;
    }

    new_ptable--;

    old_ptable = find_partition_by_name(new_ptable->name);
    if(old_ptable)
    {
        new_ptable->capacity = old_ptable->capacity;
    }

}
Exemple #9
0
static int __init his_modem_probe(struct platform_device *pdev)
{
    int ret = 0;
#ifdef BSP_CONFIG_HI3630
    u32 image_load_addr = 0;
    u32 image_length = 0;

extern unsigned int is_load_modem(void);

	/* 如果是升级模式,则不激活modem */
	if(!is_load_modem())
	{
        hi_trace(HI_ERR, "upload or charge mode, will not start modem.\r\n");
		return 0;
	}

    if (readl((void*)SHM_MEM_LOADM_ADDR) != LOAD_MODEM_OK_FLAG)
    {
        hi_trace(HI_ERR, "modem image not found\r\n");
        return -1;
    }

    image_load_addr = readl((void*)SHM_MEM_LOADM_ADDR + 4);
    image_length = readl((void*)SHM_MEM_LOADM_ADDR + 8);

    g_ccore_entry = (u32)ioremap_nocache(image_load_addr, image_length);
    if(!g_ccore_entry)
    {
        hi_trace(HI_ERR, "ioremap failed. image size: 0x%X\r\n", image_length);
        return NAND_ERROR;
    }

#else
    struct ST_PART_TBL * mc_part = NULL;

    hi_trace(HI_DEBUG, "his_modem_probe.\r\n");

    mc_part = find_partition_by_name(PTABLE_VXWORKS_NM);
    if(NULL == mc_part)
    {
        hi_trace(HI_ERR, "load ccore image succeed\r\n");
        return -EAGAIN;
    }

    if(NAND_OK == his_modem_load_vxworks(mc_part->name))
    {
        hi_trace(HI_DEBUG, "load ccore image succeed\r\n");
    }
    else
    {
        hi_trace(HI_ERR, "load ccore image failed\r\n");
        return -EAGAIN;
    }

    ret = sysfs_create_group(&pdev->dev.kobj, &his_modem_group);
    if (0 != ret)
    {
        hi_trace(HI_ERR,"create his modem sys filesystem node failed.\n");
        return -ENXIO;
    }

#endif

    ret = his_modem_ipc_send();
    if (ret)
    {
        hi_trace(HI_ERR, "load ccore image failed, ret=0x%x\r\n", ret);
    }
    else
    {
        hi_trace(HI_ERR, "load ccore image succeed\r\n");
    }

    return ret;

}
Exemple #10
0
static struct mi_root* ds_mi_set(struct mi_root* cmd_tree, void* param)
{
	str sp, partition_name;
	int ret;
	unsigned int group, state;
	struct mi_node* node;
	ds_partition_t *partition;

	node = cmd_tree->node.kids;
	if(node == NULL)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
	sp = node->value;
	if(sp.len<=0 || !sp.s)
	{
		LM_ERR("bad state value\n");
		return init_mi_tree( 500, MI_SSTR("Bad state value") );
	}

	if(sp.s[0]=='0' || sp.s[0]=='I' || sp.s[0]=='i')
		state = 0;
	else if(sp.s[0]=='p' || sp.s[0]=='P' || sp.s[0]=='2')
		state = 2;
	else if(sp.s[0]=='a' || sp.s[0]=='A' || sp.s[0]=='1')
		state = 1;
	else
		return init_mi_tree( 500, MI_SSTR("Bad state value") );

	node = node->next;
	if(node == NULL)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
	sp = node->value;
	if(sp.s == NULL)
	{
		return init_mi_tree(500, MI_SSTR("group not found"));
	}

	if (split_partition_argument(&sp, &partition_name) != 0) {
		LM_ERR("bad group format\n");
		return init_mi_tree(500, MI_SSTR("bad group format"));
	}

	partition = find_partition_by_name(&partition_name);
	if (partition == NULL) {
		LM_ERR("partition does not exist\n");
		return init_mi_tree(404, MI_SSTR(MI_UNK_PARTITION) );
	}

	if(str2int(&sp, &group))
	{
		LM_ERR("bad group value\n");
		return init_mi_tree( 500, MI_SSTR("bad group value"));
	}

	node= node->next;
	if(node == NULL)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

	sp = node->value;
	if(sp.s == NULL)
	{
		return init_mi_tree(500, MI_SSTR("address not found"));
	}

	if (state==1) {
		/* set active */
		ret = ds_set_state(group, &sp, DS_INACTIVE_DST|DS_PROBING_DST,
			0, partition);
	} else if (state==2) {
		/* set probing */
		ret = ds_set_state(group, &sp, DS_PROBING_DST, 1, partition);
		if (ret==0)
			ret = ds_set_state(group, &sp, DS_INACTIVE_DST, 0, partition);
	} else {
		/* set inactive */
		ret = ds_set_state(group, &sp, DS_INACTIVE_DST, 1, partition);
		if (ret == 0)
			ret = ds_set_state(group, &sp, DS_PROBING_DST, 0, partition);
	}

	if(ret!=0)
		return init_mi_tree(404, MI_SSTR("destination not found"));

	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
}