static void scan_ubi_partitions(int mtd) { struct flash_description *flash = get_flash_info(); libubi_t libubi = flash->libubi; int err; struct mtd_ubi_info *mtd_info; if (mtd < 0 || mtd > MAX_MTD_DEVICES) { ERROR("wrong MTD device /dev/mtd%d", mtd); return; } mtd_info = &flash->mtd_info[mtd]; /* * The program is called directly after a boot, * and a detach is not required. However, * detaching at the beginning allows consecutive * start of the program itself */ mtd_info->req.dev_num = UBI_DEV_NUM_AUTO; mtd_info->req.mtd_num = mtd; #if defined(CONFIG_UBIVIDOFFSET) mtd_info->req.vid_hdr_offset = CONFIG_UBIVIDOFFSET; #else mtd_info->req.vid_hdr_offset = 0; #endif mtd_info->req.mtd_dev_node = NULL; /* * Check if the MTD was alrady attached * and tries to get information, if not found * try to attach. */ err = ubi_attach(libubi, DEFAULT_CTRL_DEV, &mtd_info->req); if (err) { ERROR("cannot attach mtd%d - maybe not a NAND or raw device", mtd); return; } err = ubi_get_dev_info1(libubi, mtd_info->req.dev_num, &mtd_info->dev_info); if (err) { ERROR("cannot get information about UBI device %d", mtd_info->req.dev_num); return; } scan_ubi_volumes(mtd_info); }
int do_ubiattach(int nargs, char **args) { char *source = args[1]; int mtd_num, ubi_num = -1; if (nargs >= 3) { ubi_num = strtol(args[2], 0, 0); } if (!strncmp(source, "mtd@", 4)) { mtd_num = mtd_name_to_number(source + 4); if (mtd_num < 0) { return -1; } } else { mtd_num = strtoul(source, 0, 0); } if (ubi_attach("/dev/ubi_ctrl", mtd_num, ubi_num)) { return -1; } return 0; }
int scan_devices(struct params_t *params) { struct charlist *fl; struct bootconf_t *bootconf; struct device_t dev; struct cfgdata_t cfgdata; int rc,n; FILE *f; char mount_dev[16]; char mount_fstype[16]; char str_mtd_id[3]; #ifdef USE_ICONS kx_cfg_section *sc; int i; int rows; char **xpm_data; #endif bootconf = create_bootcfg(4); if (NULL == bootconf) { DPRINTF("Can't allocate bootconf structure"); return -1; } f = devscan_open(&fl); if (NULL == f) { log_msg(lg, "Can't initiate device scan"); return -1; } #ifdef USE_ZAURUS struct zaurus_partinfo_t pinfo; int zaurus_error = 0; zaurus_error = zaurus_read_partinfo(&pinfo); if (0 == zaurus_error) { /* Fix mtdparts tag */ dispose(params->cfg->mtdparts); params->cfg->mtdparts = zaurus_mtdparts(&pinfo); } #endif for (;;) { rc = devscan_next(f, fl, &dev); if (rc < 0) continue; /* Error */ if (0 == rc) break; /* EOF */ /* initialize with defaults */ strcpy(mount_dev, dev.device); strcpy(mount_fstype, dev.fstype); /* We found an ubi erase counter */ if (!strncmp(dev.fstype, "ubi",3)) { /* attach ubi boot device - mtd id [0-15] */ if(isdigit(atoi(dev.device+strlen(dev.device)-2))) { strcpy(str_mtd_id, dev.device+strlen(dev.device)-2); strcat(str_mtd_id, dev.device+strlen(dev.device)-1); } else { strcpy(str_mtd_id, dev.device+strlen(dev.device)-1); } n = ubi_attach(str_mtd_id); /* we have attached ubiX and we mount /dev/ubiX_0 */ sprintf(mount_dev, "/dev/ubi%d", n); /* HARDCODED: first volume */ strcat(mount_dev, "_0"); /* HARDCODED: we assume it's ubifs */ strcpy(mount_fstype, "ubifs"); } /* Mount device */ if (-1 == mount(mount_dev, MOUNTPOINT, mount_fstype, MS_RDONLY, NULL)) { log_msg(lg, "+ can't mount device %s: %s", mount_dev, ERRMSG); goto free_device; } /* NOTE: Don't go out before umount'ing */ /* Search boot method and return boot info */ rc = get_bootinfo(&cfgdata); if (-1 == rc) { /* Error */ goto umount; } #ifdef USE_ICONS /* Iterate over sections found */ if (params->gui) { for (i = 0; i < cfgdata.count; i++) { sc = cfgdata.list[i]; if (!sc) continue; /* Load custom icon */ if (sc->iconpath) { rows = xpm_load_image(&xpm_data, sc->iconpath); if (-1 == rows) { log_msg(lg, "+ can't load xpm icon %s", sc->iconpath); continue; } sc->icondata = xpm_parse_image(xpm_data, rows); if (!sc->icondata) { log_msg(lg, "+ can't parse xpm icon %s", sc->iconpath); continue; } xpm_destroy_image(xpm_data, rows); } } } #endif umount: /* Umount device */ if (-1 == umount(MOUNTPOINT)) { log_msg(lg, "+ can't umount device: %s", ERRMSG); goto free_cfgdata; } if (-1 == rc) { /* Error */ goto free_cfgdata; } #ifdef USE_ZAURUS /* Fix partition sizes. We can have kernel in root and home partitions on NAND */ /* HACK: mtdblock devices are hardcoded */ if (0 == zaurus_error) { if (0 == strcmp(dev.device, "/dev/mtdblock2")) { /* root */ log_msg(lg, "+ [zaurus root] size of %s will be changed from %llu to %lu", dev.device, dev.blocks, pinfo.root); dev.blocks = pinfo.root; } else if (0 == strcmp(dev.device, "/dev/mtdblock3")) { /* home */ log_msg(lg, "+ [zaurus home] size of %s will be changed from %llu to %lu", dev.device, dev.blocks, pinfo.home); dev.blocks = pinfo.home; } } #endif /* Now we have something in cfgdata */ rc = addto_bootcfg(bootconf, &dev, &cfgdata); free_cfgdata: destroy_cfgdata(&cfgdata); free_device: free(dev.device); } free_charlist(fl); params->bootcfg = bootconf; return 0; }
/** * ubi_attach_mtd_dev - attach an MTD device. * @mtd: MTD device description object * @ubi_num: number to assign to the new UBI device * @vid_hdr_offset: VID header offset * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in * which case this function finds a vacant device number and assigns it * automatically. Returns the new UBI device number in case of success and a * negative error code in case of failure. * * Note, the invocations of this function has to be serialized by the * @ubi_devices_mutex. */ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset, int max_beb_per1024) { struct ubi_device *ubi; int i, err, ref = 0; if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT) return -EINVAL; if (!max_beb_per1024) max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT; /* * Check if we already have the same MTD device attached. * * Note, this function assumes that UBI devices creations and deletions * are serialized, so it does not take the &ubi_devices_lock. */ for (i = 0; i < UBI_MAX_DEVICES; i++) { ubi = ubi_devices[i]; if (ubi && mtd == ubi->mtd) { ubi_err("mtd%d is already attached to ubi%d", mtd->index, i); return -EEXIST; } } /* * Make sure this MTD device is not emulated on top of an UBI volume * already. Well, generally this recursion works fine, but there are * different problems like the UBI module takes a reference to itself * by attaching (and thus, opening) the emulated MTD device. This * results in inability to unload the module. And in general it makes * no sense to attach emulated MTD devices, so we prohibit this. */ if (mtd->type == MTD_UBIVOLUME) { ubi_err("refuse attaching mtd%d - it is already emulated on top of UBI", mtd->index); return -EINVAL; } if (ubi_num == UBI_DEV_NUM_AUTO) { /* Search for an empty slot in the @ubi_devices array */ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) if (!ubi_devices[ubi_num]) break; if (ubi_num == UBI_MAX_DEVICES) { ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES); return -ENFILE; } } else { if (ubi_num >= UBI_MAX_DEVICES) return -EINVAL; /* Make sure ubi_num is not busy */ if (ubi_devices[ubi_num]) { ubi_err("ubi%d already exists", ubi_num); return -EEXIST; } } ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); if (!ubi) return -ENOMEM; ubi->mtd = mtd; ubi->ubi_num = ubi_num; ubi->vid_hdr_offset = vid_hdr_offset; ubi->autoresize_vol_id = -1; #ifdef CONFIG_MTD_UBI_FASTMAP ubi->fm_pool.used = ubi->fm_pool.size = 0; ubi->fm_wl_pool.used = ubi->fm_wl_pool.size = 0; /* * fm_pool.max_size is 5% of the total number of PEBs but it's also * between UBI_FM_MAX_POOL_SIZE and UBI_FM_MIN_POOL_SIZE. */ ubi->fm_pool.max_size = min(((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) / 100) * 5, UBI_FM_MAX_POOL_SIZE); if (ubi->fm_pool.max_size < UBI_FM_MIN_POOL_SIZE) ubi->fm_pool.max_size = UBI_FM_MIN_POOL_SIZE; ubi->fm_wl_pool.max_size = UBI_FM_WL_POOL_SIZE; ubi->fm_disabled = !fm_autoconvert; if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { ubi_err("More than %i PEBs are needed for fastmap, sorry.", UBI_FM_MAX_START); ubi->fm_disabled = 1; } ubi_debug("default fastmap pool size: %d", ubi->fm_pool.max_size); ubi_debug("default fastmap WL pool size: %d", ubi->fm_wl_pool.max_size); #else ubi->fm_disabled = 1; #endif ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); err = io_init(ubi, max_beb_per1024); if (err) goto out_free; err = -ENOMEM; ubi->peb_buf = vmalloc(ubi->peb_size); if (!ubi->peb_buf) goto out_free; #ifdef CONFIG_MTD_UBI_FASTMAP ubi->fm_size = ubi_calc_fm_size(ubi); ubi->fm_buf = kzalloc(ubi->fm_size, GFP_KERNEL); if (!ubi->fm_buf) goto out_free; #endif err = ubi_attach(ubi, 0); if (err) { ubi_err("failed to attach mtd%d, error %d", mtd->index, err); goto out_free; } if (ubi->autoresize_vol_id != -1) { err = autoresize(ubi, ubi->autoresize_vol_id); if (err) goto out_detach; } err = uif_init(ubi, &ref); if (err) goto out_detach; ubi_msg("attached mtd%d (name \"%s\", size %llu MiB) to ubi%d", mtd->index, mtd->name, ubi->flash_size >> 20, ubi_num); ubi_debug("PEB size: %d bytes (%d KiB), LEB size: %d bytes", ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size); ubi_debug("min./max. I/O unit sizes: %d/%d, sub-page size %d", ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size); ubi_debug("VID header offset: %d (aligned %d), data offset: %d", ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start); ubi_debug("good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d", ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count); ubi_debug("user volume: %d, internal volumes: %d, max. volumes count: %d", ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT, ubi->vtbl_slots); ubi_debug("max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u", ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD, ubi->image_seq); ubi_debug("available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d", ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs); dev_add_param_int_ro(&ubi->dev, "peb_size", ubi->peb_size, "%d"); dev_add_param_int_ro(&ubi->dev, "leb_size", ubi->leb_size, "%d"); dev_add_param_int_ro(&ubi->dev, "vid_header_offset", ubi->vid_hdr_offset, "%d"); dev_add_param_int_ro(&ubi->dev, "min_io_size", ubi->min_io_size, "%d"); dev_add_param_int_ro(&ubi->dev, "sub_page_size", ubi->hdrs_min_io_size, "%d"); dev_add_param_int_ro(&ubi->dev, "good_peb_count", ubi->good_peb_count, "%d"); dev_add_param_int_ro(&ubi->dev, "bad_peb_count", ubi->bad_peb_count, "%d"); dev_add_param_int_ro(&ubi->dev, "max_erase_counter", ubi->max_ec, "%d"); dev_add_param_int_ro(&ubi->dev, "mean_erase_counter", ubi->mean_ec, "%d"); dev_add_param_int_ro(&ubi->dev, "available_pebs", ubi->avail_pebs, "%d"); dev_add_param_int_ro(&ubi->dev, "reserved_pebs", ubi->rsvd_pebs, "%d"); /* * The below lock makes sure we do not race with 'ubi_thread()' which * checks @ubi->thread_enabled. Otherwise we may fail to wake it up. */ ubi->thread_enabled = 1; wake_up_process(ubi->bgt_thread); ubi_devices[ubi_num] = ubi; return ubi_num; out_detach: ubi_wl_close(ubi); ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); out_free: vfree(ubi->peb_buf); vfree(ubi->fm_buf); kfree(ubi); return err; }
void scan_ubi_partitions(int mtd) { struct flash_description *nand = get_flash_info(); int err; libubi_t libubi = nand->libubi; struct ubi_part *ubi_part; struct mtd_ubi_info *mtd_info; int i; if (mtd < 0 || mtd > MAX_MTD_DEVICES) ERROR("wrong MTD device /dev/mtd%d", mtd); mtd_info = &nand->mtd_info[mtd]; LIST_INIT(&mtd_info->ubi_partitions); /* * The program is called directly after a boot, * and a detach is not required. However, * detaching at the beginning allows consecutive * start of the program itself */ ubi_detach_mtd(libubi, DEFAULT_CTRL_DEV, mtd); mtd_info->req.dev_num = UBI_DEV_NUM_AUTO; mtd_info->req.mtd_num = mtd; #if CONFIG_UBIVIDOFFSET mtd_info->req.vid_hdr_offset = CONFIG_UBIVIDOFFSET; #else mtd_info->req.vid_hdr_offset = 0; #endif mtd_info->req.mtd_dev_node = NULL; err = ubi_attach(libubi, DEFAULT_CTRL_DEV, &mtd_info->req); if (err) { TRACE("cannot attach mtd%d - maybe not a NAND or raw device", mtd); return; } err = ubi_get_dev_info1(libubi, mtd_info->req.dev_num, &mtd_info->dev_info); if (err) { TRACE("cannot get information about UBI device %d", mtd_info->req.dev_num); return; } for (i = mtd_info->dev_info.lowest_vol_id; i <= mtd_info->dev_info.highest_vol_id; i++) { ubi_part = (struct ubi_part *)calloc(1, sizeof(struct ubi_part)); if (!ubi_part) ERROR("No memory: malloc failed\n"); err = ubi_get_vol_info1(libubi, mtd_info->dev_info.dev_num, i, &ubi_part->vol_info); if (err == -1) { if (errno == ENOENT) continue; TRACE("libubi failed to probe volume %d on ubi%d", i, mtd_info->dev_info.dev_num); return; } LIST_INSERT_HEAD(&mtd_info->ubi_partitions, ubi_part, next); TRACE("mtd%d:\tVolume found : \t%s", mtd, ubi_part->vol_info.name); } mtd_info->scanned = 1; }