Beispiel #1
0
static int qihoo_init_wmac(void)
{
	struct mtd_info * mtd;
	size_t nb = 0;
	u8 *art;
	int ret;

	if (!qihoo_c301_board)
		return 0;

	mtd = get_mtd_device_nm("radiocfg");
	if (IS_ERR(mtd))
		return PTR_ERR(mtd);

	if (mtd->size != 0x10000)
		return -1;

	art = kzalloc(0x1000, GFP_KERNEL);
	if (!art)
		return -1;

	ret = mtd_read(mtd, QIHOO_C301_WMAC_CALDATA_OFFSET, 0x1000, &nb, art);
	if (nb != 0x1000)
	{
		kfree(art);
		return ret;
	}

	ath79_register_wmac(art, wlan24mac);

	return 0;
}
Beispiel #2
0
void do_mount_mainfs(void)
{
#ifdef CONFIG_MTD
	struct mtd_info *mtd = NULL;
	char mtd_name[32];

	mtd = get_mtd_device_nm(CONFIG_RG_MAINFS_MTDPART_NAME);
	if (IS_ERR(mtd))
	{
	    panic("Can not find %s MTD partition",
		CONFIG_RG_MAINFS_MTDPART_NAME);
	}

	sprintf(mtd_name, "/dev/mtdblock%d", mtd->index);

	printk("Found device %s on mtdblock%d\n",
	    CONFIG_RG_MAINFS_MTDPART_NAME, mtd->index);

	if (do_mount(mtd_name, "/mnt/cramfs", "cramfs", MS_RDONLY, 0))
	    printk("Warning: unable to mount cramfs\n");
#else
	if (do_mount("cramfs", "/mnt/cramfs", "cramfs_mainfs", MS_RDONLY, 0))
	    printk("Warning: unable to mount cramfs\n");
#endif
}
/* nothing to init, always read! */
void rtcnvet_init(void)
{
#ifdef DEBUGME
    printk(KERN_ERR\
        "********* %s called! ***********\n",\
        __func__);
#endif /*DEBUGME*/
    return;
}
#else /*CONFIG_CIRRUS_DUAL_MTD_ENV*/
void rtcnvet_init(void)
{
    size_t retlen = 0;
    int _crc32;

    rtcnved_mtd = get_mtd_device_nm(UBOOTENV_MTD_NAME);

    if (IS_ERR(rtcnved_mtd)) {
        printk(KERN_ERR \
        "Not found this MTD(%s)\r\n", UBOOTENV_MTD_NAME);
        return;
    }

    /*
        #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)
        Assume mtd->size is CONFIG_ENV_SIZE in uboot
     */
    config_env_size = rtcnved_mtd->size;
    env_size = config_env_size - ENV_HEADER_SIZE;
    env_buf = kmalloc(config_env_size, GFP_KERNEL);
    MTD_READ(rtcnved_mtd, 0, config_env_size, &retlen, env_buf);

    _crc32 = ubcrc32(0, &env_buf[ENV_HEADER_SIZE], env_size);
    if (*((uint32_t *)&env_buf[0]) != _crc32) {
        printk(KERN_ERR \
            "%s: invalid env, crc check failed! 08%x vs ", \
            __func__, _crc32);
        dump_hex_f((uint8_t *)&env_buf[0], 4, DUMP_HEX);
    } else
        env_valid = 1;

    return;
}
Beispiel #4
0
int ubi_part(char *part_name, const char *vid_header_offset)
{
	struct mtd_info *mtd;
	int err = 0;

	ubi_detach();

	mtd_probe_devices();
	mtd = get_mtd_device_nm(part_name);
	if (IS_ERR(mtd)) {
		printf("Partition %s not found!\n", part_name);
		return 1;
	}
	put_mtd_device(mtd);

	err = ubi_dev_scan(mtd, vid_header_offset);
	if (err) {
		printf("UBI init error %d\n", err);
		printf("Please check, if the correct MTD partition is used (size big enough?)\n");
		return err;
	}

	ubi = ubi_devices[0];

	return 0;
}
static int nvram_init(void)
{
#ifdef CONFIG_MTD
	struct mtd_info *mtd;
	struct nvram_header header;
	size_t bytes_read;
	int err;

	mtd = get_mtd_device_nm("nvram");
	if (IS_ERR(mtd))
		return -ENODEV;

	err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header);
	if (!err && header.magic == NVRAM_MAGIC &&
	    header.len > sizeof(header)) {
		nvram_len = header.len;
		if (nvram_len >= NVRAM_SPACE) {
			pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
				header.len, NVRAM_SPACE);
			nvram_len = NVRAM_SPACE - 1;
		}

		err = mtd_read(mtd, 0, nvram_len, &nvram_len,
			       (u8 *)nvram_buf);
		return err;
	}
#endif

	return -ENXIO;
}
/*
* Function   : sc_bakup
* Discription: c core nv init,this phase build upon the a core kernel init,
*              this phase after icc init,this phase ensure to use all nv api normal
*              start at this phase ,ops global ddr need spinlock
* Parameter  : none
* Output     : result
* History    : 
*/
s32  sc_bakup(s8 *pdata, u32 len)
{
    s32 sc_fp       = 0;
    s32 wlen        = 0;
    u32 sc_mtd_len  = 0;
    struct mtd_info* mtd;
    
    sc_fp = bsp_open((char *)SC_PACKET_TRANS_FILE,(RFILE_RDONLY),0660);
    if(!sc_fp)
    {   
        sc_error_printf("bsp_open error, chanid :0x%x sc_fp :0x%x\n",SC_ICC_CHAN_ID,sc_fp);
        return BSP_ERR_SC_NO_FILE;
    }
    else
    {
        sc_debug_printf("bsp_open ok, file is 0x%x!\n",sc_fp);
    }

    wlen = bsp_read(sc_fp, pdata, len);
    if(wlen != len)
    {
        sc_error_printf("bsp_read error, opt_len :0x%x sc_ram_len :0x%x\n", wlen, len);
        bsp_close(sc_fp);
        return BSP_ERR_SC_READ_FILE_FAIL;
    }
    else
    {
        sc_debug_printf("bsp_read ok, len is 0x%x!\n",(u32)(wlen));
    }
    
    bsp_close(sc_fp);
    
    mtd = get_mtd_device_nm((char*)SC_BACKUP_SEC_NAME);
    if (IS_ERR(mtd))
    {
        sc_error_printf("get mtd device err! %s\n",mtd);
        return BSP_ERR_READ_MTD_FAIL;
    }
    sc_mtd_len = mtd->size;
    sc_debug_printf("mtd len: 0x%x\n",sc_mtd_len);
    put_mtd_device(mtd);
    
    if((sc_mtd_len < SC_MTD_PTABLE_OFFSET) || (len >= SC_MTD_PTABLE_OFFSET))
    {
        sc_error_printf("mtd length err! sc_mtd_len: 0x%x, len: 0x%x\n",sc_mtd_len, len);
        return BSP_ERR_READ_LGTH_FAIL;
    }

    wlen = bsp_nand_write((char*)SC_BACKUP_SEC_NAME, (sc_mtd_len - SC_MTD_PTABLE_OFFSET), pdata, len);
    if(wlen != BSP_OK)
    {
        sc_error_printf("mtd length err! wlen 0x%x, len is 0x%x\n",wlen,len);
        return BSP_ERR_SC_WRITE_FILE_FAIL;
    }
    
    sc_debug_printf("sc write to nand ok, len is 0x%x!\n",(u32)(wlen));
    
    return SC_OK;
}
Beispiel #7
0
int save_param_value(void)
{
	unsigned int err = 0;
	unsigned char *addr = NULL;
	struct mtd_info *mtd;
	unsigned int ret = 0;
	unsigned int retlen;

        printk("%s start\n", __func__);

	addr = vmalloc(PARAM_LEN);
	if (!addr)
		return -ENOMEM;

        preempt_enable();

	printk("%s get_mtd_device\n", __func__);
	mtd = get_mtd_device_nm("param");
	if (IS_ERR(mtd)) {
		printk("(%s)Cannot find param partition.\n",__func__);
		goto fail;
	}

	printk("%s read\n", __func__);
	ret = mtd->read(mtd, 0x30000,
					PARAM_LEN, &retlen, addr);
	if (ret || retlen != PARAM_LEN) {
		printk("(%s)Failed to read param block.\n", __func__);
		put_mtd_device(mtd);
		goto fail;
	}

	// update MAIN
	memset(addr, 0, PARAM_LEN);
	memcpy(addr, &param_status, sizeof(param_status_t));

	printk("%s write\n", __func__);
	ret = mtd->write(mtd, 0x30000,
					PARAM_LEN, &retlen, addr);
	if (ret || retlen != PARAM_LEN) {
		printk("(%s)Failed to write param block.\n", __func__);
		put_mtd_device(mtd);
		goto fail;
	}
	printk("%s put\n", __func__);

	put_mtd_device(mtd);

fail:
	vfree(addr);
        preempt_disable();
	printk("%s end\n", __func__);

	return err;
}
Beispiel #8
0
static int
mt76_get_of_eeprom(struct mt76_dev *dev, int len)
{
#ifdef CONFIG_OF
	struct device_node *np = dev->dev->of_node;
	struct mtd_info *mtd;
	const __be32 *list;
	const char *part;
	phandle phandle;
	int offset = 0;
	int size;
	size_t retlen;
	int ret;

	if (!np)
		return -ENOENT;

	list = of_get_property(np, "mediatek,mtd-eeprom", &size);
	if (!list)
		return -ENOENT;

	phandle = be32_to_cpup(list++);
	if (!phandle)
		return -ENOENT;

	np = of_find_node_by_phandle(phandle);
	if (!np)
		return -EINVAL;

	part = of_get_property(np, "label", NULL);
	if (!part)
		part = np->name;

	mtd = get_mtd_device_nm(part);
	if (IS_ERR(mtd))
		return PTR_ERR(mtd);

	if (size <= sizeof(*list))
		return -EINVAL;

	offset = be32_to_cpup(list);
	ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
	put_mtd_device(mtd);
	if (ret)
		return ret;

	if (retlen < len)
		return -EINVAL;

	return 0;
#else
	return -ENOENT;
#endif
}
int saveenv(void)
{
	struct mtd_info * mtd=get_mtd_device_nm(NAND_NORMAL_NAME);
	if (IS_ERR(mtd))
		return 1;
	struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
	size_t total;
	size_t offset = CONFIG_ENV_OFFSET;
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	offset = (1024 * aml_chip->page_size * (mtd->writesize / (aml_chip->plane_num * aml_chip->page_size)));
	if (CONFIG_ENV_OFFSET < offset)
		_debug ("env define offset must larger than 1024 page size: %d \n", mtd->writesize);
	else
		offset = CONFIG_ENV_OFFSET;

	env_ptr->flags++;
	total = CONFIG_ENV_SIZE;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	if(gd->env_valid == 1) {
		puts ("Erasing redundant Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(mtd, &nand_erase_options))
			return 1;

		puts ("Writing to redundant Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr);
	} else {
		puts ("Erasing Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(mtd, &nand_erase_options))
			return 1;

		puts ("Writing to Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
	return ret;
}
/*===========================================================================
 
FUNCTION  FLASH_NAND_OPER_REGION_INIT
 
DESCRIPTION
    Initilize user partition info,and get the handle of nand flash
RETURN VALUE
    TRUE if Op Succeed
    FALSE if Op Failure
 
SIDE EFFECTS
  None
 
===========================================================================*/
oper_region_struct_t *flash_nand_oper_region_init(  oper_region_type  oper_region_idx)
{
    uint8                idx              = (uint8)oper_region_idx;
    char                 *parent_name_ptr = NULL;
    unsigned int               offset           = 0;
    
    /* 范围保护 */
    if (idx >= REGION_MAX)
    {
        printk(KERN_ERR "Parm error: idx = %d max_ids = %d\n",idx,REGION_MAX);
        return NULL;
    }
 
    /*lint -e662*/
    parent_name_ptr = (char *)child_region[idx].parent_name;
    printk(KERN_DEBUG "parent_name_ptr =%s \n",parent_name_ptr);
    /*lint +e662*/
    /*lint -e661*/
    offset          = child_region[idx].offset;
    /*lint +e661*/

    /* get mtd device */
    g_mtd = get_mtd_device_nm(parent_name_ptr);
    if (NULL == g_mtd)
    {
        printk(KERN_ERR "get_mtd_device_nm error\n");
        return NULL;
    }

    printk(" info :mtd->erasesize = %d ,mtd->writesize = %d \n",
           g_mtd->erasesize,g_mtd->writesize);
    
    /* get the flash address */
    operation_region[idx].block_size = g_mtd->erasesize;
    operation_region[idx].page_size = g_mtd->writesize;
    operation_region[idx].start_addr = (offset * operation_region[idx].block_size);
    operation_region[idx].buffer = himalloc(operation_region[idx].page_size); 

    printk(KERN_DEBUG "operation_region[%d] = %u \n", idx, (unsigned int)operation_region[idx].start_addr);
    
    if (NULL == operation_region[idx].buffer)
    {
        put_mtd_device(g_mtd);
        return NULL;
    }

    /* 初始化读写flash时使用的缓冲区 */
    memset((void *)operation_region[idx].buffer, NAND_FILL_CHAR_APP,
           operation_region[idx].page_size);
    
    return &operation_region[idx];
}
static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
{
	int ret = -EINVAL;
#ifdef CONFIG_OF
	static struct firmware mtd_fw;
	struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
	size_t retlen, len = rt2x00dev->ops->eeprom_size;
	int size, offset = 0;
	struct mtd_info *mtd;
	const char *part;
	const __be32 *list;
	phandle phandle;

	list = of_get_property(np, "ralink,mtd-eeprom", &size);
	if (!list) {
		dev_err(rt2x00dev->dev, "failed to load eeprom property\n");
		return -ENOENT;
	}

	phandle = be32_to_cpup(list++);
	if (phandle)
		mtd_np = of_find_node_by_phandle(phandle);
	if (!mtd_np) {
		dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
		return -EINVAL;
	}

	part = of_get_property(mtd_np, "label", NULL);
	if (!part)
		part = mtd_np->name;

	mtd = get_mtd_device_nm(part);
	if (IS_ERR(mtd)) {
		dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
		return PTR_ERR(mtd);
	}

	if (size > sizeof(*list))
		offset = be32_to_cpup(list);

	ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
	put_mtd_device(mtd);

	if (!ret) {
		rt2x00dev->eeprom_file = &mtd_fw;
		mtd_fw.size = len;
		mtd_fw.data = (const u8 *) rt2x00dev->eeprom;
	}
#endif

	return ret;
}
Beispiel #12
0
static int spectra_open(struct inode *inode, struct file *file)
{
	struct spectra_device *dev;
	struct mtd_info *mtd;
	int err;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (unlikely(!dev))
		return -ENOMEM;

	dev->mtd = mtd = get_mtd_device_nm(CEFDK_CFG_PARTITION);
	if (unlikely(IS_ERR(mtd))) {
		printk(KERN_ERR DRV_NAME
		       ": mtd partition '" CEFDK_CFG_PARTITION "' not found\n");
		err = -ENXIO;
		goto out_free;
	}

	if (unlikely(mtd->type != MTD_NANDFLASH)) {
		printk(KERN_ERR DRV_NAME ": not a NAND partition\n");
		err = -ENXIO;
		goto out_put;
	}

	BUG_ON(mtd->writesize > sizeof(dev->buf));

	dev->device_info.writesize = mtd->writesize;
	dev->device_info.oobsize = mtd->oobsize;
	dev->device_info.pagesize = mtd->writesize + mtd->oobsize;

	dev->device_info.erasesize = mtd->erasesize;
	dev->device_info.blockpages = mtd_div_by_ws(mtd->erasesize, mtd);
	dev->device_info.blocksize =
	    dev->device_info.pagesize * dev->device_info.blockpages;

	dev->device_info.blocks = CEFDK_CFG_PARTITION_OFFSET +
	    mtd_div_by_eb(mtd->size, mtd);

	DBG("sizeof(device_info) 0x%x\n", sizeof(dev->device_info));

	file->private_data = dev;
	return 0;

      out_put:
	put_mtd_device(dev->mtd);
      out_free:
	kfree(dev);
	return err;
}
void nv_def_bad_block_flag(u32 num)
{
    struct mtd_info* mtd;
    u32 sec_off;

    mtd = get_mtd_device_nm((char*)NV_DEF_SEC_NAME);
    if(!mtd)
    {
        return;
    }
    sec_off = num*mtd->erasesize;

    mtd_block_markbad(mtd,sec_off);
    put_mtd_device(mtd);
}
u32 nv_get_emmc_info(const s8* name,struct nv_emmc_info_stru* emmc_info)
{
    struct mtd_info* mtd;

    mtd = get_mtd_device_nm(name);
    if (IS_ERR(mtd))
    {
        printf("[%s]:get mtd device err! %s\n",__func__,name);
        return NV_ERROR;
    }
    emmc_info->page_size  = (u32)mtd->writesize;
    emmc_info->block_size = (u32)mtd->erasesize;
    emmc_info->total_size = (u32)mtd->size;
    put_mtd_device(mtd);

    return NV_OK;
}
/*****************************************************************************
 函 数 名  : mount_early_partition
 功能描述  : 挂载列表中的分区
 输入参数  : mount_item:挂载列表
 输出参数  :
 返 回 值  : 成功/失败
 调用函数  :
 被调函数  :
*****************************************************************************/
static int mount_early_partition(mount_early *mount_item)
{
    struct mtd_info *mtd;
    int rt = 0;
    char mount_name[32] ={0};
    struct ST_PART_TBL *part = NULL;

    part = find_early_partition(mount_item->img_type);
    if(part != NULL){
        mtd = get_mtd_device_nm(part->name);
    	if (IS_ERR(mtd)) {
        	printk("get_mtd_device_nm error.\n");
        	return PTR_ERR(mtd);
        }

        snprintf(mount_name, sizeof(mount_name) - 1, "/dev/block/mtdblock%d", mtd->index);
        printk(KERN_DEBUG "going to mount %s  mount point %s\n", mount_name, mount_item->mount_point);

        if((rt = sys_mkdir(mount_item->mount_point, S_IRUSR | S_IRGRP)) < 0)
        {
            printk(KERN_ERR "create dir failed %s ret 0x%x\n", mount_item->mount_point, rt);
            return rt ;
        }

        rt = sys_mknod(mount_name, S_IFBLK|S_IRWXU|S_IRWXG|S_IRWXO, MDEV_FS(31, mtd->index));
        if(rt < 0)
        {
            printk(KERN_ERR "mknod failed %s ret 0x%x\n", mount_name, rt);
            return rt ;
        }

        rt = sys_mount(mount_name, mount_item->mount_point, "yaffs2", 0, NULL);
        if(rt < 0)
        {
            printk(KERN_ERR "mount failed %s  %s ret 0x%x 0x%x\n", mount_name, \
                mount_item->mount_point, rt, MKDEV(31,mtd->index));
            return rt ;
        }

        return 0;
    }else{
        printk(KERN_ERR "no find nv dload partition!!!\n");
        return 1 ;
    }
}
int kerSysFlashSizeGet(void)
{
    int ret = 0;

    if( bootFromNand )
    {
        struct mtd_info *mtd;

        if( (mtd = get_mtd_device_nm("rootfs")) != NULL )
        {
            ret = mtd->size;
            put_mtd_device(mtd);
        }
    }
    else
        ret = flash_get_total_size();

    return ret;
}
Beispiel #17
0
/*
 * NAND Read API for Calibration data
 *
 */
int
ath_nand_local_read(u_char *cal_part,loff_t from, size_t len,
		size_t *retlen, u_char *buf)
{
	int	ret;
	struct mtd_info *mtd;

	if (!len || !retlen) return (0);

	printk("Reading Flash for Calibraton data from 0x%llx and partition name is %s\n",from,cal_part);

	mtd = get_mtd_device_nm(cal_part);
	if (mtd == ERR_PTR(-ENODEV)) {
		printk("MTD partition doesn't exist \n");
		ret = -EIO;
		return ret;
	}
	ret = mtd->read(mtd, from, len, retlen, buf);
	return ret;
}
Beispiel #18
0
int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
{
	int ret;
	size_t rdlen = 0;
	struct mtd_info *mtd;

	mtd = get_mtd_device_nm(name);
	if (IS_ERR(mtd))
		return (int)mtd;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
	ret = mtd_read(mtd, from, len, &rdlen, buf);
#else
	ret = mtd->read(mtd, from, len, &rdlen, buf);
#endif
	if (rdlen != len)
		printk("warning: ra_mtd_read_nm: rdlen is not equal to len\n");

	put_mtd_device(mtd);
	return ret;
}
Beispiel #19
0
static int load_param_value(void)
{
	unsigned char *addr = NULL;
	unsigned int ret = 0;
	struct mtd_info *mtd;
	unsigned int retlen;
	addr = vmalloc(PARAM_LEN);

	if (!addr)
		return -ENOMEM;

        preempt_enable();
	mtd = get_mtd_device_nm("param");
	if (IS_ERR(mtd)) {
		printk("(%s)Cannot find param partition.\n",__func__);
		goto fail;
	}

	ret = mtd->read(mtd, 0x30000,
					PARAM_LEN, &retlen, addr);
	if (ret || retlen != PARAM_LEN) {
		printk("(%s)Failed to read param block.\n", __func__);
		put_mtd_device(mtd);
		goto fail;
	}

	if (is_valid_param((param_status_t *)addr)) {
		printk("param is valid\n");
		memcpy(&param_status, addr, sizeof(param_status_t));
	}

	put_mtd_device(mtd);
fail:
	vfree(addr);
        preempt_disable();

	return ret;
}
Beispiel #20
0
static int 
nvram_proc_version_read(char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
	int len = 0;
	struct mtd_info *nvram_mtd = get_mtd_device_nm(MTD_NVRAM_NAME);

	len += snprintf (buf+len, count-len, "nvram driver : v" NVRAM_DRIVER_VERSION "\n");
	len += snprintf (buf+len, count-len, "nvram space  : 0x%x\n", NVRAM_SPACE);
	len += snprintf (buf+len, count-len, "major number : %d\n", nvram_major);
	if (nvram_mtd)
	{
		len += snprintf (buf+len, count-len, "MTD            \n");
		len += snprintf (buf+len, count-len, "  name       : %s\n", nvram_mtd->name);
		len += snprintf (buf+len, count-len, "  index      : %d\n", nvram_mtd->index);
		len += snprintf (buf+len, count-len, "  flags      : 0x%x\n", nvram_mtd->flags);
		len += snprintf (buf+len, count-len, "  size       : 0x%llx\n", nvram_mtd->size);
		len += snprintf (buf+len, count-len, "  erasesize  : 0x%x\n", nvram_mtd->erasesize);
		
		put_mtd_device(nvram_mtd);
	}

	*eof = 1;
	return len;
}
Beispiel #21
0
int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	size_t size = 0;
	ulong addr = 0;
	int err = 0;
	size_t vol_offset = 0;

	if (argc < 2) {
		printf("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (mtdparts_init() != 0) {
		printf("Error initializing mtdparts!\n");
		return 1;
	}

	if (strcmp(argv[1], "part") == 0) {
		char mtd_dev[16];
		struct mtd_device *dev;
		struct part_info *part;
		const char *vid_header_offset = NULL;
		u8 pnum;

		/* Print current partition */
		if (argc == 2) {
			if (!ubi_dev.selected) {
				printf("Error, no UBI device/partition selected!\n");
				return 1;
			}

			printf("Device %d: %s, partition %s\n",
			       ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name);
			return 0;
		}

		if (argc < 3) {
			printf("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		/* todo: get dev number for NAND... */
		ubi_dev.nr = 0;

		/*
		 * Call ubi_exit() before re-initializing the UBI subsystem
		 */
		if (ubi_initialized) {
			ubi_exit();
			del_mtd_partitions(ubi_dev.mtd_info);
		}

		/*
		 * Search the mtd device number where this partition
		 * is located
		 */
		if (find_dev_and_part(argv[2], &dev, &pnum, &part)) {
			printf("Partition %s not found!\n", argv[2]);
			return 1;
		}
		sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num);
		ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev);
		if (IS_ERR(ubi_dev.mtd_info)) {
			printf("Partition %s not found on device %s!\n", argv[2], mtd_dev);
			return 1;
		}

		ubi_dev.selected = 1;

		if (argc > 3)
			vid_header_offset = argv[3];
		strcpy(ubi_dev.part_name, argv[2]);
		err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name,
				vid_header_offset);
		if (err) {
			printf("UBI init error %d\n", err);
			ubi_dev.selected = 0;
			return err;
		}

		ubi = ubi_devices[0];

		return 0;
	}

	if (strcmp(argv[1], "detach") == 0) {
		if (ubi_initialized) {
			ubi_exit();
			del_mtd_partitions(ubi_dev.mtd_info);
			ubi_initialized = 0;
			ubi_dev.selected = 0;
			if (ubi)
				memset(ubi, 0, sizeof(*ubi));
		}

		return 0;
	}

	if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) {
		printf("Error, no UBI device/partition selected!\n");
		return 1;
	}

	if (strcmp(argv[1], "info") == 0) {
		int layout = 0;
		if (argc > 2 && !strncmp(argv[2], "l", 1))
			layout = 1;
		if (argc > 2 && !strncmp(argv[2], "w", 1))
			layout = 2;
		return ubi_info(layout);
	}

	if (strncmp(argv[1], "create", 6) == 0) {
		int dynamic = 1;	/* default: dynamic volume */

		/* Use maximum available size */
		size = 0;

		/* E.g., create volume size type */
		if (argc == 5) {
			if (strncmp(argv[4], "s", 1) == 0)
				dynamic = 0;
			else if (strncmp(argv[4], "d", 1) != 0) {
				printf("Incorrect type\n");
				return 1;
			}
			argc--;
		}
		/* E.g., create volume size */
		if (argc == 4) {
			size = simple_strtoul(argv[3], NULL, 16);
			argc--;
		}
		/* Use maximum available size */
		if (!size) {
			if (ubi->avail_pebs < MIN_AVAILABLE_PEB) {
				ubi_err("available_pebs %d < MIN_AVAILABLE_PEB %d\n",
					ubi->avail_pebs, MIN_AVAILABLE_PEB);
				return 1;
			}
			size = (ubi->avail_pebs - MIN_AVAILABLE_PEB) * ubi->leb_size;
			printf("No size specified -> Using max size (0x%x)\n", size);
		}
		/* E.g., create volume */
		if (argc == 3)
			return ubi_create_vol(argv[2], size, dynamic);
	}

	if (strncmp(argv[1], "remove", 6) == 0) {
		/* E.g., remove volume */
		if (argc == 3)
			return ubi_remove_vol(argv[2]);
	}

	if (strncmp(argv[1], "write", 5) == 0) {
		if (argc < 5) {
			printf("Please see usage\n");
			return 1;
		}

		addr = simple_strtoul(argv[2], NULL, 16);
		size = simple_strtoul(argv[4], NULL, 16);

		return ubi_volume_write(argv[3], (void *)addr, size);
	}

	if (strncmp(argv[1], "read", 4) == 0) {
		size = 0;
		vol_offset = 0;

		/* E.g., offset in volume */
		if (argc == 6) {
			vol_offset = simple_strtoul(argv[5], NULL, 16);
			argc--;
		}

		/* E.g., read volume size */
		if (argc == 5) {
			size = simple_strtoul(argv[4], NULL, 16);
			argc--;
		}

		/* E.g., read volume */
		if (argc == 4) {
			addr = simple_strtoul(argv[2], NULL, 16);
			argc--;
		}

		if (argc == 3)
			return ubi_volume_read(argv[3], (char *)addr, size, vol_offset);
	}

	printf("Please see usage\n");
	return 1;
}
// NAND flash bcm image 
// return: 
// 0 - ok
// !0 - the sector number fail to be flashed (should not be 0)
static int nandImageSet( int flash_start_addr, char *string, int img_size)
{
    int sts = -1;
    int blk = 0;
    int i;
    struct mtd_info *mtd  = NULL;
    struct mtd_info *mtd0 = get_mtd_device_nm("rootfs");
    struct mtd_info *mtd1 = get_mtd_device_nm("nvram");

    if( mtd0 && mtd1 )
    {
        // Disable other tasks from this point on
#if defined(CONFIG_SMP)
        smp_send_stop();
        udelay(20);
#endif
        local_bh_disable();

        if( *(unsigned short *) string == JFFS2_MAGIC_BITMASK )
            mtd = mtd0; /* only flash file system */
        else
        {
            mtd = mtd1; /* flash first boot block and then file system */

            /* Copy NVRAM data to block to be flashed so it is preserved. */
            memcpy(string + NVRAM_DATA_OFFSET, (unsigned char *)&bootNvramData,
                sizeof(NVRAM_DATA));
        }

        sts = blk = 0;
        while( sts == 0 )
        {
            /* block_is bad returns 0 if block is not bad */
            if( mtd->block_isbad(mtd, blk) == 0 )
            {
                unsigned char oobbuf[64]; /* expected to be a max size */
                struct mtd_oob_ops ops;

                ops.ooblen = mtd->oobsize;
                ops.ooboffs = 0;
                ops.datbuf = NULL;
                ops.oobbuf = oobbuf;
                ops.len = 0;
                ops.mode = MTD_OOB_PLACE;

                /* Read and save the spare area. */
                sts = mtd->read_oob(mtd, blk, &ops);
                if( sts == 0 )
                {
                    struct erase_info erase;

                    /* Erase the flash block. */
                    memset(&erase, 0x00, sizeof(erase));
                    erase.addr = blk;
                    erase.len = mtd->erasesize;
                    erase.mtd = mtd;

                    sts = mtd->erase(mtd, &erase);
                    if( sts == 0 )
                    {
                        /* Function local_bh_disable has been called and this
                         * is the only operation that should be occurring.
                         * Therefore, spin waiting for erase to complete.
                         */
                        for(i = 0; i < 10000 && erase.state != MTD_ERASE_DONE &&
                            erase.state != MTD_ERASE_FAILED; i++ )
                        {
                            udelay(100);
                        }

                        if( erase.state != MTD_ERASE_DONE )
                            sts = -1;
                    }

                    if( sts == 0 )
                    {
                        ops.ooblen = mtd->oobsize;
                        ops.ooboffs = 0;
                        ops.datbuf = NULL;
                        ops.oobbuf = oobbuf;
                        ops.len = 0;
                        ops.mode = MTD_OOB_PLACE;

                        /* Restore the spare area. */
                        sts = mtd->write_oob(mtd, blk, &ops);

                        /* Write out a block of the image if there is still
                         * image left to flash.
                         */
                        if( sts == 0 && blk < img_size )
                        {
                            int retlen = 0;

                            /* Write a block of the image to flash. */
                            sts = mtd->write(mtd, blk, mtd->erasesize, &retlen,
                                string);

                            string += mtd->erasesize;
                            printk(".");

                            if( retlen != mtd->erasesize )
                                sts = -1;

                            if( sts )
                                printk("nandImageSet - Block 0x%8.8x. Error writing"
                                    " block.\n", blk);
                        }
                        else
                            if( sts )
                                printk("nandImageSet - Block 0x%8.8x. Error writing"
                                    " spare area.\n", blk);
                    }
                    else
                        printk("nandImageSet - Block 0x%8.8x. Error erasing "
                            "block.\n", blk);
                }
                else
                    printk("nandImageSet - Block 0x%8.8x. Error read spare area.\n",
                        blk);
            }

            if( mtd == mtd1 )
            {
                /* The first raw, boot block was flashed.  Change to rootfs. */
                img_size -= mtd->erasesize;
                mtd = mtd0;
                blk = 0;
            }
            else
            {
                /* Update to next block, stop when all blocks flashed. */
                blk += mtd->erasesize;
                if( blk >= mtd->size )
                    break;
            }
        }

        local_bh_enable();

        if( sts )
            sts = (blk > mtd->erasesize) ? blk / mtd->erasesize : 1;
    }

    if( mtd0 )
        put_mtd_device(mtd0);

    if( mtd1 )
        put_mtd_device(mtd1);

    return sts;
}
Beispiel #23
0
dev_t name_to_dev_t(char *name)
{
	char s[32];
	char *p;
	dev_t res = 0;
	int part;

#ifdef CONFIG_SYSFS
	int mkdir_err = sys_mkdir("/sys", 0700);
	if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
		goto out;
#endif

	if (strncmp(name, "/dev/", 5) != 0) {
		unsigned maj, min;

		if (sscanf(name, "%u:%u", &maj, &min) == 2) {
			res = MKDEV(maj, min);
			if (maj != MAJOR(res) || min != MINOR(res))
				goto fail;
		} else {
			res = new_decode_dev(simple_strtoul(name, &p, 16));
			if (*p)
				goto fail;
		}
		goto done;
	}
	name += 5;
	res = Root_NFS;
	if (strcmp(name, "nfs") == 0)
		goto done;
	res = Root_RAM0;
	if (strcmp(name, "ram") == 0)
		goto done;

#if defined(CONFIG_MTD_BLOCK) || defined(CONFIG_MTD_BLOCK_RO)
	/* Allow specification of MTD device by name, e.g.
	 *   root=/dev/mtdblock:foo
	 * Similar to JFFS2-specific hack in prepare_namespace(),
	 * but more generic.
	 */
	if (strncmp(name, "mtdblock:", sizeof("mtdblock:") - 1) == 0) {
		struct mtd_info *mtd =
		   get_mtd_device_nm(name + sizeof("mtdblock:") - 1);
		if (unlikely(!mtd))
			goto fail;

		sprintf(name, "mtdblock%d", mtd->index);
		put_mtd_device(mtd);
	}
#endif

	if (strlen(name) > 31)
		goto fail;
	strcpy(s, name);
	for (p = s; *p; p++)
		if (*p == '/')
			*p = '!';
	res = try_name(s, 0);
	if (res)
		goto done;

	while (p > s && isdigit(p[-1]))
		p--;
	if (p == s || !*p || *p == '0')
		goto fail;
	part = simple_strtoul(p, NULL, 10);
	*p = '\0';
	res = try_name(s, part);
	if (res)
		goto done;

	if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
		goto fail;
	p[-1] = '\0';
	res = try_name(s, part);
done:
#ifdef CONFIG_SYSFS
	sys_umount("/sys", 0);
out:
	if (!mkdir_err)
		sys_rmdir("/sys");
#endif
	return res;
fail:
	res = 0;
	goto done;
}
Beispiel #24
0
static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	size_t size = 0;
	ulong addr = 0;
	int err = 0;

	if (argc < 2) {
		cmd_usage(cmdtp);
		return 1;
	}

	if (strcmp(argv[1], "part") == 0) {
		/* Print current partition */
		if (argc == 2) {
			if (ubi_dev.type == DEV_TYPE_NONE) {
				printf("Error, no UBI device/partition selected!\n");
				return 1;
			}

			printf("%s Device %d: %s, partition %s\n", ubi_dev.dev_name,
			       ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_name);
			return 0;
		}

		if (argc < 4) {
			cmd_usage(cmdtp);
			return 1;
		}

		/* todo: get dev number for NAND... */
		ubi_dev.nr = 0;

		/*
		 * Call ubi_exit() before re-initializing the UBI subsystem
		 */
		if (ubi_initialized) {
			ubi_exit();
			del_mtd_partitions(ubi_dev.mtd_info);
		}

		/*
		 * Check for nand|onenand selection
		 */
#if defined(CONFIG_CMD_NAND)
		if (strcmp(argv[2], "nand") == 0) {
			strcpy(ubi_dev.dev_name, "NAND");
			ubi_dev.type = DEV_TYPE_NAND;
			ubi_dev.mtd_info = &nand_info[ubi_dev.nr];
		}
#endif
#if defined(CONFIG_FLASH_CFI_MTD)
		if (strcmp(argv[2], "nor") == 0) {
			strcpy(ubi_dev.dev_name, "NOR");
			ubi_dev.type = DEV_TYPE_NOR;
			ubi_dev.mtd_info = get_mtd_device_nm(CFI_MTD_DEV_NAME);
		}
#endif
#if defined(CONFIG_CMD_ONENAND)
		if (strcmp(argv[2], "onenand") == 0) {
			strcpy(ubi_dev.dev_name, "OneNAND");
			ubi_dev.type = DEV_TYPE_ONENAND;
			ubi_dev.mtd_info = &onenand_mtd;
		}
#endif

		if (ubi_dev.type == DEV_TYPE_NONE) {
			printf("Error, no UBI device/partition selected!\n");
			return 1;
		}

		strcpy(ubi_dev.part_name, argv[3]);
		err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name);
		if (err) {
			printf("UBI init error %d\n", err);
			ubi_dev.type = DEV_TYPE_NONE;
			return err;
		}

		ubi = ubi_devices[0];

		return 0;
	}

	if ((strcmp(argv[1], "part") != 0) && (ubi_dev.type == DEV_TYPE_NONE)) {
		printf("Error, no UBI device/partition selected!\n");
		return 1;
	}

	if (strcmp(argv[1], "info") == 0) {
		int layout = 0;
		if (argc > 2 && !strncmp(argv[2], "l", 1))
			layout = 1;
		return ubi_info(layout);
	}

	if (strncmp(argv[1], "create", 6) == 0) {
		int dynamic = 1;	/* default: dynamic volume */

		/* Use maximum available size */
		size = 0;

		/* E.g., create volume size type */
		if (argc == 5) {
			if (strncmp(argv[4], "s", 1) == 0)
				dynamic = 0;
			else if (strncmp(argv[4], "d", 1) != 0) {
				printf("Incorrect type\n");
				return 1;
			}
			argc--;
		}
		/* E.g., create volume size */
		if (argc == 4) {
			size = simple_strtoul(argv[3], NULL, 16);
			argc--;
		}
		/* Use maximum available size */
		if (!size)
			size = ubi->avail_pebs * ubi->leb_size;
		/* E.g., create volume */
		if (argc == 3)
			return ubi_create_vol(argv[2], size, dynamic);
	}

	if (strncmp(argv[1], "remove", 6) == 0) {
		/* E.g., remove volume */
		if (argc == 3)
			return ubi_remove_vol(argv[2]);
	}

	if (strncmp(argv[1], "write", 5) == 0) {
		if (argc < 5) {
			printf("Please see usage\n");
			return 1;
		}

		addr = simple_strtoul(argv[2], NULL, 16);
		size = simple_strtoul(argv[4], NULL, 16);

		return ubi_volume_write(argv[3], (void *)addr, size);
	}

	if (strncmp(argv[1], "read", 4) == 0) {
		size = 0;

		/* E.g., read volume size */
		if (argc == 5) {
			size = simple_strtoul(argv[4], NULL, 16);
			argc--;
		}

		/* E.g., read volume */
		if (argc == 4) {
			addr = simple_strtoul(argv[2], NULL, 16);
			argc--;
		}

		if (argc == 3)
			return ubi_volume_read(argv[3], (char *)addr, size);
	}

	printf("Please see usage\n");
	return -1;
}
Beispiel #25
0
/*
 * set up an MTD-based superblock
 */
struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
	       const char *dev_name, void *data,
	       int (*fill_super)(struct super_block *, void *, int))
{
#ifdef CONFIG_BLOCK
	struct block_device *bdev;
	int ret, major;
#endif
	int mtdnr;

	if (!dev_name)
		return ERR_PTR(-EINVAL);

	DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);

	/* the preferred way of mounting in future; especially when
	 * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
	 * by name, so that we don't require block device support to be present
	 * in the kernel. */
	if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
		if (dev_name[3] == ':') {
			struct mtd_info *mtd;

			/* mount by MTD device name */
			DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n",
			      dev_name + 4);

			mtd = get_mtd_device_nm(dev_name + 4);
			if (!IS_ERR(mtd))
				return mount_mtd_aux(
					fs_type, flags,
					dev_name, data, mtd,
					fill_super);

//			printk(KERN_NOTICE "MTD:"
//			       " MTD device with name \"%s\" not found.\n",
;

		} else if (isdigit(dev_name[3])) {
			/* mount by MTD device number name */
			char *endptr;

			mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
			if (!*endptr) {
				/* It was a valid number */
				DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
				      mtdnr);
				return mount_mtd_nr(fs_type, flags,
						     dev_name, data,
						     mtdnr, fill_super);
			}
		}
	}

#ifdef CONFIG_BLOCK
	/* try the old way - the hack where we allowed users to mount
	 * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
	 */
	bdev = lookup_bdev(dev_name);
	if (IS_ERR(bdev)) {
		ret = PTR_ERR(bdev);
		DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret);
		return ERR_PTR(ret);
	}
	DEBUG(1, "MTDSB: lookup_bdev() returned 0\n");

	ret = -EINVAL;

	major = MAJOR(bdev->bd_dev);
	mtdnr = MINOR(bdev->bd_dev);
	bdput(bdev);

	if (major != MTD_BLOCK_MAJOR)
		goto not_an_MTD_device;

	return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super);

not_an_MTD_device:
#endif /* CONFIG_BLOCK */

	if (!(flags & MS_SILENT))
//		printk(KERN_NOTICE
//		       "MTD: Attempt to mount non-MTD device \"%s\"\n",
;
	return ERR_PTR(-EINVAL);
}
/*
* Function   : sc_restore
* Discription: c core nv init,this phase build upon the a core kernel init,
*              this phase after icc init,this phase ensure to use all nv api normal
*              start at this phase ,ops global ddr need spinlock
* Parameter  : none
* Output     : result
* History    : 
*/
s32  sc_restore(s8 *pdata, u32 len)
{
    s32 sc_fp       = 0;
    s32 rlen        = 0;
    s32 wlen        = 0;
    u32 sc_mtd_len  = 0;
    struct mtd_info* mtd;

    mtd = get_mtd_device_nm((char*)SC_BACKUP_SEC_NAME);
    if (IS_ERR(mtd))
    {
        sc_error_printf("get mtd device err! %s\n",mtd);
        return BSP_ERR_READ_MTD_FAIL;
    }
    sc_mtd_len = mtd->size;
    put_mtd_device(mtd);
    
    if((sc_mtd_len < SC_MTD_PTABLE_OFFSET) || (len >= SC_MTD_PTABLE_OFFSET))
    {
        sc_error_printf("mtd length err! size 0x%x\n",mtd->size);
        return BSP_ERR_READ_LGTH_FAIL;
    }

    rlen = bsp_nand_read((char*)SC_BACKUP_SEC_NAME, (sc_mtd_len - SC_MTD_PTABLE_OFFSET), pdata, len, NULL);
    if(rlen != BSP_OK)
    {
        sc_error_printf("mtd length err! read_ret 0x%x, len is 0x%x\n",rlen,len);
        return BSP_ERR_SC_READ_FILE_FAIL;
    }
    else
    {
        sc_debug_printf("mtd length read ok len is 0x%x\n",rlen);
    }

    /* write to file */
    sc_fp = bsp_open((char*)SC_PACKET_TRANS_FILE,(RFILE_CREAT|RFILE_RDWR),0660);
    if(!sc_fp)
    {   
        sc_error_printf("bsp_open error, chanid :0x%x sc_fp :0x%x\n",SC_ICC_CHAN_ID,sc_fp);
        return BSP_ERR_SC_NO_FILE;
    }
    else
    {
        sc_debug_printf("bsp_open ok, file is 0x%x!\n",sc_fp);
    }

    /* write to file */
    wlen = bsp_write(sc_fp, pdata, len);
    if(wlen != len)
    {
        sc_error_printf("bsp_write error, chanid :0x%x wlen :0x%x, len : 0x%x\n",SC_ICC_CHAN_ID,wlen,len);
        bsp_close(sc_fp);
        return BSP_ERR_SC_WRITE_FILE_FAIL;
    }
    else
    {
        sc_debug_printf("bsp_write ok,wlen is 0x%x",wlen);
    }

    bsp_close(sc_fp);

    return SC_OK;
}
Beispiel #27
0
/*
 * Flash API: ra_mtd_read, ra_mtd_write
 * Arguments:
 *   - num: specific the mtd number
 *   - to/from: the offset to read from or written to
 *   - len: length
 *   - buf: data to be read/written
 * Returns:
 *   - return -errno if failed
 *   - return the number of bytes read/written if successed
 */
int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf)
{
	int ret = -1;
	size_t rdlen, wrlen;
	struct mtd_info *mtd;
	struct erase_info ei;
	u_char *bak = NULL;

	mtd = get_mtd_device_nm(name);

	if (IS_ERR(mtd)) {
		ret = (int)mtd;
		goto out;
	}

	if (len > mtd->erasesize) {
		put_mtd_device(mtd);
		ret = -E2BIG;
		goto out;
	}

	bak = kzalloc(mtd->erasesize, GFP_KERNEL);
	if (bak == NULL) {
		put_mtd_device(mtd);
		ret = -ENOMEM;
		goto out;
	}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
	ret = mtd_read(mtd, 0, mtd->erasesize, &rdlen, bak);
#else
	ret = mtd->read(mtd, 0, mtd->erasesize, &rdlen, bak);
#endif
	if (ret) {
		goto free_out;
	}

	if (rdlen != mtd->erasesize)
		printk("warning: ra_mtd_write_nm: rdlen is not equal to erasesize\n");

	memcpy(bak + to, buf, len);

	ei.mtd = mtd;
	ei.callback = NULL;
	ei.addr = 0;
	ei.len = mtd->erasesize;
	ei.priv = 0;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
	ret = mtd_erase(mtd, &ei);
#else
	ret = mtd->erase(mtd, &ei);
#endif
	if (ret != 0)
		goto free_out;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
	ret = mtd_write(mtd, 0, mtd->erasesize, &wrlen, bak);
#else
	ret = mtd->write(mtd, 0, mtd->erasesize, &wrlen, bak);
#endif

	udelay(10); /* add delay after write */

free_out:
	if (mtd)
		put_mtd_device(mtd);

	if (bak)
		kfree(bak);
out:
	return ret;
}
FILE* nv_emmc_open(const s8* path,const s8* mode)
{

    u32 ret = NV_ERROR;
    u32 i = 0;
    struct nv_emmc_file_header_stru* fd = NULL;
    u32 offset = 0;
    u32 len = 0;
    struct mtd_info* mtd = NULL;

    nv_file_debug(NV_FILE_OPEN_API,0,0,0,0);

    for(i=0; i<NV_FILE_BUTT; i++)
    {
        if(0 == strcmp(path,g_nv_file[i].path))
        {
            fd = &g_nv_file[i];
            mtd = get_mtd_device_nm(fd->name);
            if(IS_ERR(mtd))
            {
                printf("[%s]:get mtd device err! %s\n",__func__,fd->name);
                return NULL;
            }
            g_nv_file[i].mtd = mtd;
            break;
        }
    }
    if(NULL == fd)
    {
        nv_file_debug(NV_FILE_OPEN_API,1,0,0,0);
        return NULL;
    }
    osl_sem_down(&fd->file_sem);
    switch(fd->emmc_type)
    {
        case NV_FILE_DLOAD:
            ret = nv_get_nvbin_info(mode,&offset,&len);
            break;
        case NV_FILE_BACKUP:
            ret = nv_sec_file_info_init(g_nv_file[NV_FILE_BACKUP].name,&g_emmc_info.bak_sec);
            ret |= nv_get_back_info(mode,&offset,&len);
            break;
        case NV_FILE_XNV_CARD_1:
            ret = nv_get_xnv_info(NV_USIMM_CARD_1,&offset,&len);
            break;
        case NV_FILE_CUST_CARD_1:
            ret = nv_get_cust_info(NV_USIMM_CARD_1,&offset,&len);
            break;
        case NV_FILE_XNV_CARD_2:
            ret = nv_get_xnv_info(NV_USIMM_CARD_2,&offset,&len);
            break;
        case NV_FILE_CUST_CARD_2:
            ret = nv_get_cust_info(NV_USIMM_CARD_2,&offset,&len);
            break;
        case NV_FILE_SYS_NV:
            ret = nv_get_sys_nv_info(mode,&offset,&len);
            break;
        case NV_FILE_DEFAULT:
            ret = nv_get_default_info(mode,&offset,&len);
            break;
        case NV_FILE_XNV_MAP_CARD_1:
            ret = nv_get_xnv_map_info(NV_USIMM_CARD_1,&offset,&len);
            break;
        case NV_FILE_XNV_MAP_CARD_2:
            ret = nv_get_xnv_map_info(NV_USIMM_CARD_2,&offset,&len);
            break;
        default:
            ret = BSP_ERR_NV_INVALID_PARAM;
    }

    if(NV_OK != ret)
    {
        put_mtd_device(fd->mtd);
        osl_sem_up(&fd->file_sem);
        nv_file_debug(NV_FILE_OPEN_API,3,fd->emmc_type,ret,0);
        return NULL;
    }

    fd->ops ++;
    fd->seek   = 0;
    fd->length = len;
    fd->off    = offset;
    fd->fp     = fd;

    return fd;
}
Beispiel #29
0
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	int i, dev, ret = 0;
	ulong addr;
	loff_t off, size;
	char *cmd, *s;
	nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
	int quiet = CONFIG_SYS_NAND_QUIET;
#else
	int quiet = 0;
#endif
	const char *quiet_str = getenv("quiet");

#if ((defined CONFIG_AML_NAND_KEY) || (defined MX_REVD) || (defined CONFIG_SECURE_NAND))
	int chip_num , tmp_chip_num, error;
	nand = nand_info[nand_curr_device];
	struct mtd_info *mtd =nand;
	struct aml_nand_chip *aml_chip = mtd_to_nand_chip(nand);
#endif

	/* at least two arguments please */
	if (argc < 2)
		goto usage;

	if (quiet_str)
		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;

	cmd = argv[1];
#ifdef CONFIG_AML_NAND_KEY
	if (strcmp(cmd, "key") == 0){
		aml_chip->key_protect = 1;		//force nand key can be erased 
		return 0;
	}
#endif
#ifdef CONFIG_SECURE_NAND
	if (strcmp(cmd, "secure") == 0){
		aml_chip->secure_protect = 1;		//force nand key can be erased
		return 0;
	}
#endif

#ifdef CONFIG_SECURE_NAND
		if (strcmp(cmd, "secure") == 0){
			aml_chip->secure_protect = 1;		//force nand key can be erased 
			return 0;
		}
#endif

	if(strcmp(cmd, "exist") == 0){
		if(nand_info[1]){
			printf("nand exist return 0\n");
			return 0;
		}
		else{
			printf("nand exist return 1\n");
			return 1;
		}
	}
#ifdef MX_REVD
	if (strcmp(cmd, "errstat") == 0){
	    printk("checking chiprev here\n");
        if(aml_chip->err_sts == NAND_CHIP_REVB_HY_ERR){
            printk("Must use RevD chip for Hynix 26nm/20nm nand boot without SPI!!!\n");
            return NAND_CHIP_REVB_HY_ERR;
        }
		return 0;
	}
#endif
#ifdef CONFIG_SECURE_NAND
		if (strcmp(cmd, "secure") == 0){
			aml_chip->secure_protect = 1;		//force nand key can be erased 
			return 0;
		}
#endif

	if (strcmp(cmd, "info") == 0) {
	#ifdef CONFIG_AML_NAND_KEY
		aml_chip->key_protect = 0;		//protect nand key can not be erased
	#endif
	#ifdef CONFIG_SECURE_NAND
		aml_chip->secure_protect = 0;		//protect nand secure can not be erased
	#endif

		putc('\n');
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			nand = nand_info[i];
			if (!nand) {
				nand_init();
				if (!nand)
					return -1;
			}
			if (nand->name)
				nand_print_info(i);
		}
		return 0;
	}
	if (strcmp(cmd, "init") == 0) {
		nand_init();
		return 0;
	}	
//cmd for nand test , if nand is ok , then trigger power off
	if (strcmp(cmd, "test") == 0) {
		int ret=-1;
		puts("\ntest the nand flash ***\n");
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			nand = nand_info[i];
			if (!nand) {
				ret=nand_test_init();
				printf("\n***nand_test_init()in NAND DEVICE %d returned:%d***\n ", i,ret);
				if (ret)
					return -1;	
			}
		}		
		return 0;
	}

	if (strcmp(cmd, "scrub_detect") == 0) {

		if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) {
			puts("\nno devices available\n");
			return 1;
		}
		nand = nand_info[nand_curr_device];

		aml_nand_stupid_dectect_badblock(nand);
		return 0;

	}

	if (strcmp(cmd, "device") == 0) {

		if (argc < 3) {
			putc('\n');
			if ((nand_curr_device < 0) ||
			    (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
				puts("no devices available\n");
			else
				nand_print_info(nand_curr_device);
			return 0;
		}
		dev = (int)simple_strtoul(argv[2], NULL, 10);
		if (dev < 0 || dev >= (CONFIG_SYS_MAX_NAND_DEVICE+1) || !nand_info[dev]->name) {
			puts("No such device\n");
			return 1;
		}
		printf("Device %d: %s", dev, nand_info[dev]->name);
		puts("... is now current device\n");
		nand_curr_device = dev;

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
		/*
		 * Select the chip in the board/cpu specific driver
		 */
		board_nand_select_device(nand_info[dev]->priv, dev);
#endif

		return 0;
	}

	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
	    strncmp(cmd, "dump", 4) != 0 &&
	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
	    strcmp(cmd, "biterr") != 0 && strncmp(cmd, "rom_protect", 11) != 0 &&
	    strncmp(cmd, "wr_rd_cmp", 9) != 0 && strncmp(cmd, "rom_write", 9) != 0 && (strncmp(cmd, "rom_read", 8) != 0) &&
	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 &&
	    strcmp(cmd, "factory_info") != 0 && strcmp(cmd, "show_para_page")&& strncmp(cmd, "scrub_safe", 10) != 0) //my_
	
			goto usage;

	/* the following commands operate on the current device */
	if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) {
		puts("\nno devices available\n");
		return 1;
	}

	nand = nand_info[nand_curr_device];
	if (!nand)
		return -1;

	if (strcmp(cmd, "bad") == 0) {
		printf("\nDevice %d bad blocks:\n", nand_curr_device);
		for (off = 0; off < nand->size; off += nand->erasesize)
			if (nand_block_isbad(nand, off))
				printf("  %09llx\n", off);
		return 0;
	}

	/*
	 * Syntax is:
	 *   0    1     2       3    4
	 *   nand erase [clean] [off size]
	 */
	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0 || strcmp(cmd, "scrub_safe") == 0) { 
		nand_erase_options_t opts;
		int argc_cnt = 2;
        //printk("%s\n", argv[2]);
        /*
		if (isstring(argv[2])) {
			nand = get_mtd_device_nm(argv[2]);
			if (IS_ERR(nand)){
                printf("get nand device err\n");
				return 1;
			}
			argc_cnt++;
		}
		*/
		/* "clean" at index 2 means request to write cleanmarker */
		int clean = argc > argc_cnt && !strcmp("clean", argv[argc_cnt]);
		if (clean) 
			argc_cnt++;
		int o = argc_cnt;

		int scrub = !strncmp(cmd, "scrub",10);
		int scrub_safe =  !strncmp(cmd, "scrub_safe",10);
		
		if(scrub_safe)			
			printf("\nNAND %s: ", scrub_safe ? "scrub_safe" : "erase"); 
		else
			printf("\nNAND %s: ", scrub ? "scrub" : "erase");
		
		if (argv[argc_cnt])
		{
			if(!strcmp(argv[argc_cnt], "whole"))
			{
				off = 0;
				size = nand->size;
				printf("whole chip.\n");
			}
		}
		else
		{
			/* skip first two or three arguments, look for offset and size */
			if ((strcmp(cmd, "erase") == 0) && (argc < 3))
			{
				goto usage;
			}
                    if ((arg_off_size(argc - o, argv + o, nand, &off, &size) != 0))
                    {
                        return  1;
                    }
		}

		memset(&opts, 0, sizeof(opts));
		opts.offset = off;
		opts.length = size;
		opts.jffs2  = clean;
		opts.quiet  = quiet;

		if (scrub) {
			puts("Warning: "
			     "scrub option will erase all factory set "
			     "bad blocks!\n"
			     "         "
			     "There is no reliable way to recover them.\n"
			     "         "
			     "Use this command only for testing purposes "
			     "if you\n"
			     "         "
			     "are sure of what you are doing!\n"
			     "\nReally scrub this NAND flash? <y/N>\n");
			if(nand_protect)
			{
				if (getc() == 'y') {
					puts("y");
					if (getc() == '\r')
						opts.scrub = 1;
					else {
						puts("scrub aborted\n");
						return -1;
					}
				} else {
					puts("scrub aborted\n");
					return -1;
				}
			}
			else
			{
				opts.scrub = 1;
			}
		}
		else if(scrub_safe){
			puts("Warning: "
			     "scrub_safe option will erase all "
			     "bad blocks except factory bad blocks!\n");
			opts.scrub = 2; 	// indicate scrub_safe
		}
		ret = nand_erase_opts(nand, &opts);
		printf("%s\n", ret ? "ERROR" : "OK");
	#ifdef CONFIG_AML_NAND_KEY
		aml_chip->key_protect = 0;		//protect nand key can not be erased 
	#endif
	#ifdef CONFIG_SECURE_NAND
		aml_chip->secure_protect = 0;		//protect nand secure can not be erased 
	#endif

		return ret == 0 ? 0 : 1;
	}

	if (strncmp(cmd, "dump", 4) == 0) {
		if (argc < 3)
			goto usage;

		s = strchr(cmd, '.');
		//off = (loff_t)simple_strtoul(argv[2], NULL, 16);
		if (!(str2longlong(argv[2], (unsigned long long*)(&off))))
			return -1;

		if (s != NULL && strcmp(s, ".oob") == 0)
			ret = nand_dump(nand, off, 1);
		else
			ret = nand_dump(nand, off, 0);

		return ret == 0 ? 1 : 0;

	}

	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
		int read;

		if (argc < 4)
			goto usage;

		if (isstring(argv[2])) {
			nand = get_mtd_device_nm(argv[2]);
			if (IS_ERR(nand))
				goto usage;
			addr = (ulong)simple_strtoul(argv[3], NULL, 16);
			read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
			printf("\nNAND %s: %s ", read ? "read" : "write", argv[2]);
			if (argc == 4) {
				extern unsigned int get_mtd_size(char *name);
				off = 0;
				size = get_mtd_size(argv[2]);
			} else {
				if (arg_off_size(argc - 4, argv + 4, nand, &off, &size) != 0)
					return 1;
			}
		}
		else {
			addr = (ulong)simple_strtoul(argv[2], NULL, 16);
			read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
			printf("\nNAND %s: ", read ? "read" : "write");
			if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
				return 1;
		}

#ifdef CONFIG_AMLROM_NANDBOOT
	if((read==0) && ((off)<(1024* nand->writesize)) && (nand_curr_device == 0)){
		printf("offset 0x%llx in aml-boot area ,abort\n", off);
		return -1;
	}	
#endif


		s = strchr(cmd, '.');
		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(nand, off, &size,
							 (u_char *)addr, 0);
			else
				ret = nand_write_skip_bad(nand, off, &size,
							  (u_char *)addr, 0);
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (u8 *)addr,
				.ooblen = size,
				.mode = MTD_OOB_RAW
			};

			if (read)
				ret = nand->read_oob(nand, off, &ops);
			else
				ret = nand->write_oob(nand, off, &ops);
		} else if (!strcmp(s, ".raw")) {
s32 nv_emmc_remove(const s8* path)
{

    s32 ret = -1;
    struct nv_emmc_file_header_stru* fd = NULL;
    struct erase_info erase = {0,};
    struct mtd_info* mtd = NULL;
    u32 i = 0;

    nv_file_debug(NV_FILE_REMOVE_API,0,0,0,0);

    for(i=0;i<NV_FILE_BUTT;i++)
    {
        if(0 == strcmp(path,g_nv_file[i].path))
        {
            fd = &g_nv_file[i];
            break;
        }
    }

    if(NULL == fd)
    {
        nv_file_debug(NV_FILE_REMOVE_API,1,0,0,0);
        return -1;
    }
    switch(fd->emmc_type)
    {
        case NV_FILE_DLOAD:
            g_emmc_info.nv_dload.nv_bin.magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_BACKUP:
            memset(&g_emmc_info.bak_sec,NV_FLASH_FILL,sizeof(struct nv_file_info_stru));
            goto flash_erase;
        case NV_FILE_CUST_CARD_1:
            g_emmc_info.nv_dload.cust_xml[0].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_XNV_CARD_1:
            g_emmc_info.nv_dload.xnv_xml[0].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_CUST_CARD_2:
            g_emmc_info.nv_dload.cust_xml[1].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_XNV_CARD_2:
            g_emmc_info.nv_dload.xnv_xml[1].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_XNV_MAP_CARD_1:
            g_emmc_info.nv_dload.xnv_map[0].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_XNV_MAP_CARD_2:
            g_emmc_info.nv_dload.xnv_map[1].magic_num = NV_FLASH_NULL;
            break;
        case NV_FILE_DEFAULT:
            memset(&g_emmc_info.def_sec,NV_FLASH_FILL,sizeof(struct nv_file_info_stru));
            goto flash_erase;
        case NV_FILE_SYS_NV:
            memset(&g_emmc_info.sys_nv,NV_FLASH_FILL,sizeof(g_emmc_info.sys_nv));
            goto flash_erase;
        default:
            return BSP_ERR_NV_INVALID_PARAM;
    }
    if(true == nv_dload_exist_file())
    {
        return NV_OK;
    }
flash_erase:
    mtd = get_mtd_device_nm(fd->name);
    if(IS_ERR(mtd))
    {
        printf("[%s]:get mtd device err! %s\n",__func__,fd->name);
        return -1;
    }
    erase.addr = 0;
    erase.mtd = mtd;
    erase.len = mtd->size;
    erase.callback = NULL;
    erase.priv     = 0;
    erase.time     = 10000;
    erase.retries  = 2;

    ret = mtd_erase(mtd,&erase);
    mtd_sync(mtd);
    put_mtd_device(mtd);
    if(ret)
    {
        nv_file_debug(NV_FILE_REMOVE_API,2,(u32)ret,fd->emmc_type,0);
        printf("[%s]:ret 0x%x,mtd->name %s\n",__func__,ret,mtd->name);
        return ret;
    }

    return NV_OK;
 }