static int scan_ubi_device(libubi_t lib_ubi, struct ubi_node *dev) { int lo = dev->info.lowest_vol_id, hi = dev->info.highest_vol_id; int i, idx = 0, dev_num = dev->info.dev_num; struct ubi_vol_info vol_info; if (!dev->info.vol_count) return 0; dev->vol_info = xcalloc(dev->info.vol_count, sizeof(dev->vol_info[0])); for (i = lo; i <= hi; ++i) { if (ubi_get_vol_info1(lib_ubi, dev_num, i, &vol_info)) { if (errno == ENOENT) continue; perror("ubi_get_vol_info1"); return -1; } dev->vol_info[idx++] = vol_info; } if (sort_by) qsort(dev->vol_info, idx, sizeof(vol_info), compare_ubi_vol); return 0; }
int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name, struct ubi_vol_info *info) { int i, err; unsigned int nlen = strlen(name); struct ubi_dev_info dev_info; if (nlen == 0) { errmsg("bad \"name\" input parameter"); errno = EINVAL; return -1; } err = ubi_get_dev_info1(desc, dev_num, &dev_info); if (err) return err; for (i = dev_info.lowest_vol_id; i <= dev_info.highest_vol_id; i++) { err = ubi_get_vol_info1(desc, dev_num, i, info); if (err == -1) { if (errno == ENOENT) continue; return -1; } if (nlen == strlen(info->name) && !strcmp(name, info->name)) return 0; } errno = ENOENT; return -1; }
static void scan_ubi_volumes(struct mtd_ubi_info *info) { struct flash_description *flash = get_flash_info(); libubi_t libubi = flash->libubi; struct ubi_part *ubi_part; int i, err; for (i = info->dev_info.lowest_vol_id; i <= 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"); return; } err = ubi_get_vol_info1(libubi, info->dev_info.dev_num, i, &ubi_part->vol_info); if (err == -1) { if (errno == ENOENT) continue; ERROR("libubi failed to probe volume %d on ubi%d", i, info->dev_info.dev_num); return; } LIST_INSERT_HEAD(&info->ubi_partitions, ubi_part, next); TRACE("mtd%d:\tVolume found : \t%s", info->dev_info.mtd_num, ubi_part->vol_info.name); } info->scanned = 1; }
/** * __check_volume - check volume information. * * @libubi libubi descriptor * @dev_info UBI device description * @test test name * @func function name * @line line number * @vol_id ID of existing volume to check * @req volume creation request to compare with * * This function checks if a volume created using @req request has exactly the * requested characteristics. Returns 0 in case of success and %-1 in case of * error. */ int __check_volume(libubi_t libubi, struct ubi_dev_info *dev_info, const char *test, const char *func, int line, int vol_id, const struct ubi_mkvol_request *req) { int ret; struct ubi_vol_info vol_info; int leb_size; long long rsvd_bytes; ret = ubi_get_vol_info1(libubi, dev_info->dev_num, vol_id, &vol_info); if (ret) { __failed(test, func, line, "ubi_get_vol_info"); return -1; } if (req->alignment != vol_info.alignment) { __err_msg(test, func, line, "bad alignment: requested %d, got %d", req->alignment, vol_info.alignment); return -1; } if (req->vol_type != vol_info.type) { __err_msg(test, func, line, "bad type: requested %d, got %d", req->vol_type, vol_info.type); return -1; } if (strlen(req->name) != strlen(vol_info.name) || strcmp(req->name, vol_info.name) != 0) { __err_msg(test, func, line, "bad name: requested \"%s\", got \"%s\"", req->name, vol_info.name); return -1; } if (vol_info.corrupted) { __err_msg(test, func, line, "corrupted new volume"); return -1; } leb_size = dev_info->leb_size - (dev_info->leb_size % req->alignment); if (leb_size != vol_info.leb_size) { __err_msg(test, func, line, "bad usable LEB size %d, should be %d", vol_info.leb_size, leb_size); return -1; } rsvd_bytes = req->bytes; if (rsvd_bytes % leb_size) rsvd_bytes += leb_size - (rsvd_bytes % leb_size); if (rsvd_bytes != vol_info.rsvd_bytes) { __err_msg(test, func, line, "bad reserved bytes %lld, should be %lld", vol_info.rsvd_bytes, rsvd_bytes); return -1; } return 0; }
/** * mkvol_multiple - test multiple volumes creation * * Thus function returns %0 if the test passed and %-1 if not. */ static int mkvol_multiple(void) { struct ubi_mkvol_request req; int i, ret, max = dev_info.max_vol_count; const char *name = PROGRAM_NAME ":mkvol_multiple()"; /* Create maximum number of volumes */ for (i = 0; i < max; i++) { char nm[strlen(name) + 50]; req.vol_id = UBI_VOL_NUM_AUTO; req.alignment = 1; req.bytes = 1; req.vol_type = UBI_STATIC_VOLUME; sprintf(nm, "%s:%d", name, i); req.name = nm; if (ubi_mkvol(libubi, node, &req)) { if (errno == ENFILE) { max = i; break; } failed("ubi_mkvol"); errorm("vol_id %d", i); goto remove; } if (check_volume(req.vol_id, &req)) { errorm("vol_id %d", i); goto remove; } } for (i = 0; i < max; i++) { struct ubi_vol_info vol_info; if (ubi_rmvol(libubi, node, i)) { failed("ubi_rmvol"); return -1; } /* Make sure volume does not exist */ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); if (ret == 0) { errorm("removed volume %d exists", i); goto remove; } } return 0; remove: for (i = 0; i < dev_info.max_vol_count + 1; i++) ubi_rmvol(libubi, node, i); return -1; }
int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) { int vol_id, dev_num; struct libubi *lib = (struct libubi *)desc; if (vol_node2nums(lib, node, &dev_num, &vol_id)) return -1; return ubi_get_vol_info1(desc, dev_num, vol_id, info); }
int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) { int vol_id, dev_num; struct libubi *lib = (struct libubi *)desc; dev_num = find_dev_num_vol(lib, node); if (dev_num == -1) return -1; vol_id = find_vol_num(lib, dev_num, node); if (vol_id == -1) return -1; return ubi_get_vol_info1(desc, dev_num, vol_id, info); }
int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) { int err, vol_id, dev_num; struct libubi *lib = (struct libubi *)desc; err = ubi_probe_node(desc, node); if (err != 2) { if (err == 1) errno = ENODEV; return -1; } if (vol_node2nums(lib, node, &dev_num, &vol_id)) return -1; return ubi_get_vol_info1(desc, dev_num, vol_id, info); }
static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info, char *name) { int err, i; struct ubi_vol_info vol_info; for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) { err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info); if (err == -1) { if (errno == ENOENT) continue; return -1; } if (strcmp(name, vol_info.name) == 0) return vol_info.vol_id; } return -1; }
/** * mkvol_basic - simple test that checks basic volume creation capability. * * Thus function returns %0 in case of success and %-1 in case of failure. */ static int mkvol_basic(void) { struct ubi_mkvol_request req; struct ubi_vol_info vol_info; int vol_id, ret; const char *name = PROGRAM_NAME ":mkvol_basic()"; /* Create dynamic volume of maximum size */ req.vol_id = UBI_VOL_NUM_AUTO; req.alignment = 1; req.bytes = dev_info.avail_bytes; req.vol_type = UBI_DYNAMIC_VOLUME; req.name = name; if (ubi_mkvol(libubi, node, &req)) { failed("ubi_mkvol"); return -1; } vol_id = req.vol_id; if (check_volume(vol_id, &req)) goto remove; if (ubi_rmvol(libubi, node, vol_id)) { failed("ubi_rmvol"); return -1; } /* Create static volume of maximum size */ req.vol_id = UBI_VOL_NUM_AUTO; req.alignment = 1; req.bytes = dev_info.avail_bytes; req.vol_type = UBI_STATIC_VOLUME; req.name = name; if (ubi_mkvol(libubi, node, &req)) { failed("ubi_mkvol"); return -1; } vol_id = req.vol_id; if (check_volume(vol_id, &req)) goto remove; if (ubi_rmvol(libubi, node, vol_id)) { failed("ubi_rmvol"); return -1; } /* Make sure volume does not exist */ ret = ubi_get_vol_info1(libubi, dev_info.dev_num, vol_id, &vol_info); if (ret == 0) { errorm("removed volume %d exists", vol_id); goto remove; } return 0; remove: ubi_rmvol(libubi, node, vol_id); return -1; }
/* * Helper function for test_rsvol(). */ static int test_rsvol1(struct ubi_vol_info *vol_info) { long long bytes; struct ubi_vol_info vol_info1; char vol_node[strlen(UBI_VOLUME_PATTERN) + 100]; unsigned char buf[vol_info->rsvd_bytes]; int fd, i, ret; /* Make the volume smaller and check basic volume I/O */ bytes = vol_info->rsvd_bytes - vol_info->leb_size; if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes - 1)) { failed("ubi_rsvol"); return -1; } if (ubi_get_vol_info1(libubi, vol_info->dev_num, vol_info->vol_id, &vol_info1)) { failed("ubi_get_vol_info"); return -1; } if (vol_info1.rsvd_bytes != bytes) { errorm("rsvd_bytes %lld, must be %lld", vol_info1.rsvd_bytes, bytes); return -1; } if (vol_info1.rsvd_lebs != vol_info->rsvd_lebs - 1) { errorm("rsvd_lebs %d, must be %d", vol_info1.rsvd_lebs, vol_info->rsvd_lebs - 1); return -1; } /* Write data to the volume */ sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, vol_info->vol_id); fd = open(vol_node, O_RDWR); if (fd == -1) { failed("open"); errorm("cannot open \"%s\"\n", vol_node); return -1; } bytes = vol_info->rsvd_bytes - vol_info->leb_size - 1; if (ubi_update_start(libubi, fd, bytes)) { failed("ubi_update_start"); goto close; } for (i = 0; i < bytes; i++) buf[i] = (unsigned char)i; ret = write(fd, buf, bytes); if (ret != bytes) { failed("write"); goto close; } close(fd); if (ubi_rsvol(libubi, node, vol_info->vol_id, bytes)) { failed("ubi_rsvol"); return -1; } if (ubi_rsvol(libubi, node, vol_info->vol_id, (long long)vol_info->leb_size * dev_info.avail_lebs)) { failed("ubi_rsvol"); return -1; } fd = open(vol_node, O_RDWR); if (fd == -1) { failed("open"); errorm("cannot open \"%s\"\n", vol_node); return -1; } /* Read data back */ if (lseek(fd, 0, SEEK_SET) != 0) { failed("seek"); goto close; } memset(buf, 0, bytes); ret = read(fd, buf, bytes); if (ret != bytes) { failed("read"); goto close; } for (i = 0; i < bytes; i++) { if (buf[i] != (unsigned char)i) { errorm("bad data"); goto close; } } close(fd); return 0; close: close(fd); return -1; }
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; }