예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
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;
}
예제 #4
0
파일: build.c 프로젝트: AubrCool/barebox
/**
 * 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;
}
예제 #5
0
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;
}