int ubi_node_type(libubi_t desc, const char *node) { struct stat st; struct ubi_info info; int i, fd, major, minor; struct libubi *lib = (struct libubi *)desc; char file[strlen(lib->ubi_vol) + 100]; if (lstat(node, &st)) return -1; if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return -1; } major = major(st.st_rdev); minor = minor(st.st_rdev); if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; return -1; } if (major1 == major) break; } if (i > info.highest_dev_num) { /* * The character device node does not correspond to any * existing UBI device or volume, but we do not want to return * any error number in this case, to indicate the fact that it * could be a UBI device/volume, but it doesn't. */ errno = 0; return -1; } if (minor == 0) return 1; /* This is supposdely an UBI volume device node */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) { errno = 0; return -1; } return 2; }
void ubi_init(void) { struct flash_description *nand = get_flash_info(); int err; libubi_t libubi; libubi = libubi_open(); if (!libubi) { if (errno == 0) ERROR("UBI is not present in the system"); ERROR("cannot open libubi"); return; } nand->libubi = libubi; err = ubi_get_info(libubi, &nand->ubi_info); if (err) { ERROR("cannot get UBI information"); return; } if (nand->ubi_info.ctrl_major == -1) { ERROR("MTD attach/detach feature is not supported by your kernel"); } }
int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num) { struct ubi_info info; int i, ret, mtd_num1; struct libubi *lib = desc; if (ubi_get_info(desc, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1); if (ret) { if (errno == ENOENT) continue; return -1; } if (mtd_num1 == mtd_num) { errno = 0; *dev_num = i; return 0; } } errno = 0; return -1; }
/** * vol_node2nums - find UBI device number and volume ID by volume device node * file. * @lib: UBI library descriptor * @node: UBI character device node name * @dev_num: UBI device number is returned here * @vol_id: volume ID is returned hers * * This function returns zero in case of succes and %-1 in case of failure. */ static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, int *vol_id) { struct stat st; struct ubi_info info; int i, fd, major, minor; char file[strlen(lib->ubi_vol) + 100]; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } major = major(st.st_rdev); minor = minor(st.st_rdev); if (minor == 0) { errno = EINVAL; return errmsg("\"%s\" is not a volume character device", node); } if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; return -1; } if (major1 == major) break; } if (i > info.highest_dev_num) { errno = ENODEV; return -1; } /* Make sure this UBI volume exists */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) { errno = ENODEV; return -1; } *dev_num = i; *vol_id = minor - 1; errno = 0; return 0; }
static void scan_for_ubi_devices(void) { struct flash_description *flash = get_flash_info(); libubi_t libubi = flash->libubi; struct ubi_info ubi_info; struct ubi_dev_info dev_info; struct mtd_ubi_info *mtd_info; int err, i, mtd; if (!libubi) return; /* * if not yet an attached device, return and try later * to attach them */ printf("%s\n", __func__); err = ubi_get_info(libubi, &ubi_info); if (err) return; for (i = ubi_info.lowest_dev_num; i <= ubi_info.highest_dev_num; i++) { err = ubi_get_dev_info1(libubi, i, &dev_info); if (err == -1) { continue; } mtd = dev_info.mtd_num; mtd_info = &flash->mtd_info[mtd]; if (mtd < 0 || mtd > MAX_MTD_DEVICES || flash->mtd_info[mtd].skipubi) continue; memcpy(&mtd_info->dev_info, &dev_info, sizeof(struct ubi_dev_info)); scan_ubi_volumes(mtd_info); } }
int ubi_probe_node(libubi_t desc, const char *node) { struct stat st; struct ubi_info info; int i, fd, major, minor; struct libubi *lib = (struct libubi *)desc; char file[strlen(lib->ubi_vol) + 100]; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errmsg("\"%s\" is not a character device", node); errno = EINVAL; return -1; } major = major(st.st_rdev); minor = minor(st.st_rdev); if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; if (!errno) goto out_not_ubi; return -1; } if (major1 == major) break; } if (i > info.highest_dev_num) goto out_not_ubi; if (minor == 0) return 1; /* This is supposdely an UBI volume device node */ sprintf(file, lib->ubi_vol, i, minor - 1); fd = open(file, O_RDONLY); if (fd == -1) goto out_not_ubi; return 2; out_not_ubi: errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to " "any existing UBI device or volume", node, major, minor); errno = ENODEV; return -1; }
/** * dev_node2num - find UBI device number by its character device node. * @lib: UBI library descriptor * @node: UBI character device node name * * This function returns positive UBI device number in case of success and %-1 * in case of failure. */ static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) { struct stat st; struct ubi_info info; int i, major, minor; if (stat(node, &st)) return sys_errmsg("cannot get information about \"%s\"", node); if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } major = major(st.st_rdev); minor = minor(st.st_rdev); if (minor != 0) { errno = EINVAL; return errmsg("\"%s\" is not an UBI character device", node); } if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; ret = dev_get_major(lib, i, &major1, &minor1); if (ret) { if (errno == ENOENT) continue; return -1; } if (major1 == major) { if (minor1 != 0) { errmsg("UBI character device minor number is " "%d, but must be 0", minor1); errno = EINVAL; return -1; } errno = 0; *dev_num = i; return 0; } } errno = ENODEV; return -1; }
/** * find_dev_num - find UBI device number by its character device node. * * @lib UBI library descriptor * @node UBI character device node name * * This function returns positive UBI device number in case of success and %-1 * in case of failure. */ static int find_dev_num(struct libubi *lib, const char *node) { struct stat stat; struct ubi_info info; int i, major, minor; if (lstat(node, &stat)) return -1; if (!S_ISCHR(stat.st_mode)) { errno = EINVAL; return -1; } major = major(stat.st_rdev); minor = minor(stat.st_rdev); if (minor != 0) { errno = -EINVAL; return -1; } if (ubi_get_info((libubi_t *)lib, &info)) return -1; for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { int major1, minor1, ret; char buf[50]; ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); if (ret < 0) return -1; ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); if (ret != 2) { fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); errno = EINVAL; return -1; } if (minor1 == minor && major1 == major) return i; } errno = ENOENT; return -1; }
int scan_ubi(libubi_t lib_ubi) { struct ubi_dev_info dev_info; struct ubi_info info; int i, j; if (ubi_get_info(lib_ubi, &info)) return -1; if (!info.dev_count) return 0; ubi_dev = xcalloc(info.dev_count, sizeof(ubi_dev[0])); for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) { if (!ubi_dev_present(lib_ubi, i)) continue; if (ubi_get_dev_info1(lib_ubi, i, &dev_info)) { perror("ubi_get_dev_info1"); return -1; } for (j = 0; j < num_mtd_devices; ++j) { if (mtd_dev[j].info.mtd_num == dev_info.mtd_num) break; } if (j == num_mtd_devices) { fprintf(stderr, "Cannot find mtd device %d refered to " "by ubi device %d\n", dev_info.mtd_num, dev_info.dev_num); return -1; } ubi_dev[num_ubi_devices].info = dev_info; mtd_dev[j].ubi = ubi_dev + num_ubi_devices; if (scan_ubi_device(lib_ubi, ubi_dev + num_ubi_devices)) return -1; ++num_ubi_devices; } return 0; }