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; }
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; }
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; }
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, ¶m_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; }
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; }
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; }
/* * 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; }
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; }
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(¶m_status, addr, sizeof(param_status_t)); } put_mtd_device(mtd); fail: vfree(addr); preempt_disable(); return ret; }
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; }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
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; }