From 6ccd7242c4c1404dafb64cd937adc3c65ce02385 Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Wed, 21 Jun 2006 14:26:02 +0200 Subject: [MTD] UBI: Removed automake, autoconf, added ubi userspace headers. Signed-off-by: Frank Haverkamp --- ubi-utils/src/libubi.c | 773 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 773 insertions(+) create mode 100644 ubi-utils/src/libubi.c (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c new file mode 100644 index 0000000..9b9a793 --- /dev/null +++ b/ubi-utils/src/libubi.c @@ -0,0 +1,773 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * + * Author: Artem B. Bityutskiy + * Oliver Lohmann + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libubi.h" +#include "libubi_int.h" +#include "libubi_sysfs.h" + +/** + * struct ubi_lib - UBI library descriptor. + * + * @ubi general UBI information + * + * @sysfs_root sysfs root directory + * @ubi_root UBI root directory in sysfs + * + * @nlen_max full path to the "maximum volume name length" sysfs file + * @version full path to the "UBI version" sysfs file + * + * @cdev_path path pattern to UBI character devices + * @cdev_path_len maximum length of the @cdev_path string after substitution + * @udev_path path to sysfs directories corresponding to UBI devices + * @wear_path path to sysfs file containing UBI wear information + * @vol_count_path path to sysfs file containing the number of volumes in an + * UBI device + * @tot_ebs_path path to sysfs file containing the total number of + * eraseblock on an UBI device + * @avail_ebs_path path to sysfs file containing the number of unused + * eraseblocks on an UBI device, available for new volumes + * @eb_size_path path to sysfs file containing size of UBI eraseblocks + * @nums_path path to sysfs file containing major and minor number of an + * UBI device + * @vol_cdev_path path to UBI volume character devices + * @vdev_path path to sysfs directories corresponding to UBI volume + * devices + * @vol_nums_path path to sysfs file containing major and minor number of an + * UBI volume device + * @vol_bytes_path path to sysfs file containing size of an UBI volume device + * in bytes + * @vol_ebs_path path to sysfs file containing the number of eraseblocks in + * an UBI volume device + * @vol_type_path path to sysfs file containing type of an UBI volume + * @vol_name_path @FIXME: Describe me. + * + * This structure is created and initialized by 'ubi_init()' and is passed to + * all UBI library calls. + */ +struct ubi_lib +{ + struct ubi_info ubi; + + char *sysfs_root; + char *ubi_root; + + char *nlen_max; + char *version; + char *cdev_path; + int cdev_path_len; + char *udev_path; + char *wear_path; + char *vol_count_path; + char *tot_ebs_path; + char *avail_ebs_path; + char *eb_size_path; + char *nums_path; + int vol_cdev_path_len; + char *vol_cdev_path; + char *vdev_path; + char *vol_nums_path; + char *vol_bytes_path; + char *vol_ebs_path; + char *vol_type_path; + char *vol_name_path; +}; + + +/** + * mkpath - compose full path from 2 given components. + * + * @path first component @name second component + * + * Returns the resulting path in case of success and %NULL in case of failure. + * Callers have to take care the resulting path is freed. + */ +static char* +mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) + return NULL; + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + + +static int +get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) +{ + int err; + int n = 1; + char *path; + struct stat stat; + + err = sysfs_read_int(desc->version, (int*) &ubi->version); + if (err) + return -1; + + err = sysfs_read_int(desc->nlen_max, (int*) &ubi->nlen_max); + if (err) + return -1; + + /* Calculate number of UBI devices */ + do { + char dir[20]; + + sprintf(&dir[0], "ubi%d", n); + path = mkpath(desc->sysfs_root, dir); + if (!path) + return ENOMEM; + + err = lstat(path, &stat); + if (err == 0) + n += 1; + free(path); + } while (err == 0); + + if (errno != ENOENT) + return -1; + + if (n == 0) { + ubi_err("no UBI devices found"); + errno = EINVAL; + return -1; + } + + errno = 0; + ubi->dev_count = n; + return 0; +} + +void +ubi_dump_handler(ubi_lib_t desc) +{ + ubi_lib_t d = desc; + printf( "UBI Library Descriptor:\n" + "ubi_root: %s\n" + "nlen_max: %s\n" + "version: %s\n" + "cdev_path: %s\n" + "udev_path: %s\n" + "wear_path: %s\n" + "vol_count_path: %s\n" + "tot_ebs_path: %s\n" + "avail_ebs_path: %s\n" + "eb_size_path: %s\n" + "nums_path: %s\n" + "vol_cdev_path: %s\n" + "vdev_path: %s\n" + "vol_nums_path: %s\n" + "vol_bytes_path: %s\n" + "vol_ebs_path: %s\n" + "vol_type_path: %s\n" + "vol_name_path: %s\n" + "cdev_path_len: %d\n\n", + d->ubi_root, d->nlen_max, d->version, d->cdev_path, + d->udev_path, d->wear_path, d->vol_count_path, + d->tot_ebs_path, d->avail_ebs_path, d->eb_size_path, + d->nums_path, d->vol_cdev_path, d->vdev_path, + d->vol_nums_path, d->vol_bytes_path, d->vol_ebs_path, + d->vol_type_path, d->vol_name_path, d->cdev_path_len); +} + +int +ubi_set_cdev_pattern(ubi_lib_t desc, const char *pattern) +{ + char *patt; + + patt = strdup(pattern); + if (!patt) { + ubi_err("cannot allocate memory"); + return -1; + } + + if (desc->cdev_path) + free(desc->cdev_path); + + desc->cdev_path = patt; + desc->cdev_path_len = strlen(patt) + 1 + UBI_MAX_ID_SIZE; + + ubi_dbg("ubi dev pattern is now \"%s\"", patt); + + return 0; +} + +int +ubi_set_vol_cdev_pattern(ubi_lib_t desc, const char *pattern) +{ + char *patt; + + patt = strdup(pattern); + if (!patt) { + ubi_err("cannot allocate memory"); + return -1; + } + + free(desc->vol_cdev_path); + desc->vol_cdev_path = patt; + desc->vol_cdev_path_len = strlen(patt) + 1 + 2 * UBI_MAX_ID_SIZE; + + ubi_dbg("ubi volume dev pattern is now \"%s\"", patt); + + return 0; +} + +int +ubi_open(ubi_lib_t *desc) +{ + int err = -1; + ubi_lib_t res; + struct stat stat; + + res = calloc(1, sizeof(struct ubi_lib)); + if (!res) { + ubi_err("cannot allocate memory"); + return -1; + } + + res->cdev_path = NULL; + err = ubi_set_cdev_pattern(res, UBI_CDEV_PATH); + if (err) + goto error; + + /* TODO: this actually has to be discovered */ + res->sysfs_root = strdup(UBI_SYSFS_ROOT); + if (!res->sysfs_root) + goto error; + + res->ubi_root = mkpath(res->sysfs_root, UBI_ROOT); + if (!res->ubi_root) + goto error; + + res->nlen_max = mkpath(res->ubi_root, UBI_NLEN_MAX); + if (!res->nlen_max) + goto error; + + res->version = mkpath(res->ubi_root, UBI_VERSION); + if (!res->version) + goto error; + + res->udev_path = mkpath(res->ubi_root, "ubi%d/"); + if (!res->udev_path) + goto error; + + res->wear_path = mkpath(res->udev_path, UBI_WEAR); + if (!res->wear_path) + goto error; + + res->vol_count_path = mkpath(res->udev_path, UBI_VOL_COUNT); + if (!res->vol_count_path) + goto error; + + res->tot_ebs_path = mkpath(res->udev_path, UBI_AVAIL_EBS); + if (!res->tot_ebs_path) + goto error; + + res->avail_ebs_path = mkpath(res->udev_path, UBI_TOT_EBS); + if (!res->avail_ebs_path) + goto error; + + res->eb_size_path = mkpath(res->udev_path, UBI_EB_SIZE); + if (!res->eb_size_path) + goto error; + + res->nums_path = mkpath(res->udev_path, UBI_NUMS); + if (!res->nums_path) + goto error; + + err = ubi_set_vol_cdev_pattern(res, UBI_VOL_CDEV_PATH); + if (err) + goto error; + + res->vdev_path = mkpath(res->udev_path, "%d/"); + if (!res->vdev_path) + goto error; + + res->vol_nums_path = mkpath(res->vdev_path, UBI_NUMS); + if (!res->vol_nums_path) + goto error; + + res->vol_bytes_path = mkpath(res->vdev_path, UBI_VBYTES); + if (!res->vol_bytes_path) + goto error; + + res->vol_ebs_path = mkpath(res->vdev_path, UBI_VEBS); + if (!res->vol_ebs_path) + goto error; + + res->vol_type_path = mkpath(res->vdev_path, UBI_VTYPE); + if (!res->vol_type_path) + goto error; + + res->vol_name_path = mkpath(res->vdev_path, UBI_VNAME); + if (!res->vol_name_path) + goto error; + + /* Check if UBI exists in the system */ + err = lstat(res->ubi_root, &stat); + if (err) { + perror("lstat"); + fprintf(stderr, "%s\n", res->ubi_root); + err = UBI_ENOTFOUND; + goto error; + } + + err = get_ubi_info(res, &res->ubi); + if (err) + goto error; + + *desc = res; + + ubi_dbg("opened library successfully."); + + return 0; + +error: + ubi_close(&res); + + if (err == -1 && errno == ENOMEM) + ubi_err("Cannot allocate memory"); + + return err; +} + +int +ubi_close(ubi_lib_t *desc) +{ + ubi_lib_t tmp = *desc; + + free(tmp->vol_name_path); + free(tmp->vol_type_path); + free(tmp->vol_ebs_path); + free(tmp->vol_bytes_path); + free(tmp->vol_nums_path); + free(tmp->vdev_path); + free(tmp->vol_cdev_path); + free(tmp->nums_path); + free(tmp->eb_size_path); + free(tmp->avail_ebs_path); + free(tmp->tot_ebs_path); + free(tmp->vol_count_path); + free(tmp->wear_path); + free(tmp->udev_path); + free(tmp->cdev_path); + free(tmp->version); + free(tmp->nlen_max); + free(tmp->ubi_root); + free(tmp->sysfs_root); + free(tmp); + + *desc = NULL; + + return 0; +} + +void +ubi_perror(const char *prefix, int code) +{ + if (code == 0) + return; + + fprintf(stderr, "%s: ", prefix); + + switch (code) { + case UBI_ENOTFOUND: + fprintf(stderr, "UBI was not found in system\n"); + break; + case UBI_EBUG: + fprintf(stderr, "an UBI or UBI library bug\n"); + break; + case UBI_EINVAL: + fprintf(stderr, "invalid parameter\n"); + break; + case -1: + perror(prefix); + break; + default: + ubi_err("unknown error code %d", code); + break; + } +} + +int +ubi_get_dev_info(ubi_lib_t desc, unsigned int devn, struct ubi_dev_info *di) +{ + int err; + + if (devn >= desc->ubi.dev_count) { + ubi_err("bad device number, max is %d\n", + desc->ubi.dev_count - 1); + return UBI_EINVAL; + } + + err = sysfs_read_dev_subst(desc->nums_path, &di->major, + &di->minor, 1, devn); + if (err) + return -1; + + err = sysfs_read_ull_subst(desc->wear_path, &di->wear, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->vol_count_path, + &di->vol_count, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->eb_size_path, &di->eb_size, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->tot_ebs_path, &di->total_ebs, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->avail_ebs_path, + &di->avail_ebs, 1, devn); + if (err) + return -1; + +#if 0 + ubi_dbg("major:minor %d:%d, wear %llu, EB size %d, " + "vol. count %d, tot. EBs %d, avail. EBs %d", + di->major, di->minor, di->wear, di->eb_size, + di->vol_count, di->total_ebs, di->avail_ebs); +#endif + + return err; +} + +int +ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, + struct ubi_vol_info *req) +{ + int err; + int len; + char buf1[10]; + char buf2[desc->ubi.nlen_max]; + + err = sysfs_read_dev_subst(desc->vol_nums_path, &req->major, + &req->minor, 2, devn, vol_id); + if (err) + return -1; + + err = sysfs_read_ull_subst(desc->vol_bytes_path, + &req->bytes, 2, devn, vol_id); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->vol_ebs_path, + &req->eraseblocks, 2, devn, vol_id); + if (err) + return -1; + + len = sysfs_read_data_subst(desc->vol_type_path, &buf1[0], + 10, 2, devn, vol_id); + if (len == -1) + return -1; + + if (buf1[len - 1] != '\n') { + ubi_err("bad volume type"); + return UBI_EBUG; + } + + if (!strncmp(&buf1[0], "static", sizeof("static") - 1)) { + req->type = UBI_STATIC_VOLUME; + } else if (!strncmp(&buf1[0], "dynamic", sizeof("dynamic") - 1)) { + req->type = UBI_DYNAMIC_VOLUME; + } else { + ubi_err("bad type %s", &buf1[0]); + return -1; + } + + len = sysfs_read_data_subst(desc->vol_name_path, &buf2[0], + desc->ubi.nlen_max, 2, devn, vol_id); + if (len == -1) + return -1; + + if (buf2[len - 1] != '\n') { + ubi_err("bad volume name"); + return UBI_EBUG; + } + + req->name = malloc(len); + if (!req->name) { + ubi_err("cannot allocate memory"); + return -1; + } + + memcpy(req->name, &buf2[0], len - 1); + req->name[len - 1] = '\0'; + + return 0; +} + +/** + * ubi_cdev_open - open a UBI device + * + * @desc UBI library descriptor + * @devn Number of UBI device to open + * @flags Flags to pass to open() + * + * This function opens a UBI device by number and returns a file + * descriptor. In case of an error %-1 is returned and errno is set + * appropriately. + */ +static int +ubi_cdev_open(ubi_lib_t desc, int devn, int flags) +{ + char *buf; + int fd; + + ubi_dbg("desc=%p, devn=%d, flags=%08x\n", desc, devn, flags); + + if (desc == NULL) { + ubi_err("desc is NULL\n"); + return -1; + } + if (desc->vol_cdev_path_len == 0) { + ubi_err("path_len == 0\n"); + return -1; + } + buf = malloc(desc->cdev_path_len); + + sprintf(buf, desc->cdev_path, devn); + + fd = open(buf, flags); + if (fd == -1) + ubi_dbg("cannot open %s", buf); + + free(buf); + return fd; +} + +/** + * ubi_cdev_close - close a UBI device + * + * @dev_fd file descriptor of UBI device to close + * + * This function closes the given UBI device. + */ +static int +ubi_cdev_close(int dev_fd) +{ + return close(dev_fd); +} + +/** + * @size is now in bytes. + */ +int +ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, + long long bytes, int alignment, const char *name) +{ + int fd; + int err; + struct ubi_mkvol_req req; + + if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) + return -1; + + req.vol_id = vol_id; + req.bytes = bytes; + req.vol_type = vol_type; + req.alignment = alignment; + req.name_len = strlen(name); + req.name = name; + + /* printf("DBG: %s(vol_id=%d, bytes=%lld, type=%d, alig=%d, nlen=%d, " + "name=%s)\n", __func__, vol_id, bytes, vol_type, alignment, + strlen(name), name);*/ + + err = ioctl(fd, UBI_IOCMKVOL, &req); + if (err < 0) { + ubi_err("ioctl returned %d errno=%d\n", err, errno); + goto out_close; + } + + ubi_dbg("created volume %d, size %lld, name \"%s\" " + "at UBI dev %d\n", vol_id, bytes, name, devn); + + close(fd); + return err; + out_close: + ubi_cdev_close(fd); + return err; +} + +int +ubi_rmvol(ubi_lib_t desc, int devn, int vol_id) +{ + int fd; + int err; + + if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) + return -1; + + err = ioctl(fd, UBI_IOCRMVOL, &vol_id); + if (err < 0) + goto out_close; + + ubi_dbg("removed volume %d", vol_id); + + out_close: + ubi_cdev_close(fd); + return err; +} + +int +ubi_get_info(ubi_lib_t desc, struct ubi_info *ubi) +{ + memcpy(ubi, &desc->ubi, sizeof(struct ubi_info)); + return 0; +} + + +int +ubi_vol_open(ubi_lib_t desc, int devn, int vol_id, int flags) +{ + char *buf; + int fd; + + ubi_dbg("desc=%p, devn=%d, vol_id=%d, flags=%08x\n", + desc, devn, vol_id, flags); + + if (desc == NULL) { + ubi_err("desc is NULL\n"); + return -1; + } + if (desc->vol_cdev_path_len == 0) { + ubi_err("path_len == 0\n"); + return -1; + } + buf = malloc(desc->cdev_path_len); + + sprintf(buf, desc->vol_cdev_path, devn, vol_id); + + fd = open(buf, flags); + if (fd == -1) + ubi_dbg("cannot open %s", buf); + + free(buf); + return fd; +} + +int +ubi_vol_close(int vol_fd) +{ + return close(vol_fd); +} + + +int +ubi_vol_update(int vol_fd, unsigned long long bytes) +{ + int err; + + err = ioctl(vol_fd, UBI_IOCVOLUP, &bytes); + if (err) { + ubi_err("%s failure calling update ioctl\n" + " IOCTL(%08x) err=%d errno=%d\n", + __func__, UBI_IOCVOLUP, err, errno); + } + return err; +} + +FILE * +ubi_vol_fopen_read(ubi_lib_t desc, int devn, uint32_t vol_id) +{ + FILE *fp; + int fd; + + fd = ubi_vol_open(desc, devn, vol_id, O_RDONLY); + if (fd == -1) + return NULL; + + fp = fdopen(fd, "r"); + if (fp == NULL) + ubi_vol_close(fd); + + return fp; +} + +FILE * +ubi_vol_fopen_update(ubi_lib_t desc, int devn, uint32_t vol_id, + unsigned long long bytes) +{ + FILE *fp; + int fd; + int err; + + fd = ubi_vol_open(desc, devn, vol_id, O_RDWR); + if (fd == -1) + return NULL; + + fp = fdopen(fd, "r+"); + if (fp == NULL) { + printf("DBG: %s(errno=%d)\n", __func__, errno); + ubi_vol_close(fd); + return NULL; + } + err = ubi_vol_update(fd, bytes); + if (err < 0) { + printf("DBG: %s() fd=%d err=%d\n", __func__, fd, err); + fclose(fp); + return NULL; + } + return fp; +} + +int +ubi_vol_get_used_bytes(int vol_fd, unsigned long long *bytes) +{ + off_t res; + + res = lseek(vol_fd, 0, SEEK_END); + if (res == (off_t)-1) + return -1; + *bytes = (unsigned long long) res; + res = lseek(vol_fd, 0, SEEK_SET); + return res == (off_t)-1 ? -1 : 0; +} -- cgit v1.2.3 From faa7699bf15b9a08b1b2658745314ae8f63878a2 Mon Sep 17 00:00:00 2001 From: "dedekind@linutronix.de" Date: Fri, 30 Jun 2006 14:05:25 +0200 Subject: [MTD] UBI: Adaptations to new driver, reworked frontend --- include/mtd/ubi-header.h | 21 +-- include/mtd/ubi-user.h | 7 +- ubi-utils/src/config.h | 4 +- ubi-utils/src/libubi.c | 31 ++-- ubi-utils/src/libubi_int.h | 8 +- ubi-utils/src/ubimkvol.c | 405 ++++++++++++++++++++++++++----------------- ubi-utils/src/ubirmvol.c | 267 +++++++++++++++++----------- ubi-utils/src/ubiupdatevol.c | 50 +++--- 8 files changed, 470 insertions(+), 323 deletions(-) (limited to 'ubi-utils/src/libubi.c') diff --git a/include/mtd/ubi-header.h b/include/mtd/ubi-header.h index 12ce1c9..ca96fc9 100644 --- a/include/mtd/ubi-header.h +++ b/include/mtd/ubi-header.h @@ -41,7 +41,7 @@ /* The initial CRC32 value used when calculating CRC checksums */ #define UBI_CRC32_INIT 0xFFFFFFFFU -/** +/* * Magic numbers of the UBI headers. * * @UBI_EC_HDR_MAGIC: erase counter header magic number (ASCII "UBI#") @@ -52,7 +52,7 @@ enum { UBI_VID_HDR_MAGIC = 0x55424921 }; -/** +/* * Molume type constants used in volume identifier headers. * * @UBI_VID_DYNAMIC: dynamic volume @@ -63,23 +63,19 @@ enum { UBI_VID_STATIC = 2 }; -/** +/* * Compatibility constants used by internal volumes. * * @UBI_COMPAT_DELETE: delete this internal volume before anything is written * to the flash * @UBI_COMPAT_RO: attach this device in read-only mode - * @UBI_COMPAT_IGNORE: ignore this internal volume, but the UBI wear-leveling - * unit may still move these logical eraseblocks to ensure wear-leveling * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its - * physical eraseblocks, don't even allow the wear-leveling unit to move - * them + * physical eraseblocks, don't allow the wear-leveling unit to move them * @UBI_COMPAT_REJECT: reject this UBI image */ enum { UBI_COMPAT_DELETE = 1, UBI_COMPAT_RO = 2, - UBI_COMPAT_IGNORE = 3, UBI_COMPAT_PRESERVE = 4, UBI_COMPAT_REJECT = 5 }; @@ -281,7 +277,7 @@ struct ubi_vid_hdr { */ struct ubi_vid_hdr_upd_vol { ubi32_t vol_id; - uint8_t padding[UBI_VID_HDR_IVOL_DATA_SIZE - 4]; + uint8_t padding[UBI_VID_HDR_IVOL_DATA_SIZE-4]; } __attribute__ ((packed)); /* @@ -295,13 +291,13 @@ struct ubi_vid_hdr_upd_vol { */ #define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) -/** +/* * enum ubi_internal_volume_numbers - volume IDs of internal UBI volumes. * * %UBI_LAYOUT_VOL_ID: volume ID of the layout volume * %UBI_UPDATE_VOL_ID: volume ID of the update volume */ -enum ubi_internal_volume_ids { +enum { UBI_LAYOUT_VOL_ID = UBI_INTERNAL_VOL_START, UBI_UPDATE_VOL_ID = UBI_INTERNAL_VOL_START + 1 }; @@ -351,6 +347,7 @@ enum ubi_internal_volume_ids { * @alignment: volume alignment * @data_pad: how many bytes are not used at the end of the eraseblocks to * satisfy the requested alignment + * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) * @padding1: reserved, zeroes * @name_len: the volume name length * @name: the volume name @@ -382,7 +379,7 @@ struct ubi_vol_tbl_record { uint8_t vol_type; uint8_t padding1; ubi16_t name_len; - uint8_t name[UBI_VOL_NAME_MAX + 1]; + uint8_t name[UBI_VOL_NAME_MAX+1]; uint8_t padding2[24]; ubi32_t crc; } __attribute__ ((packed)); diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index 161f674..0eb1470 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h @@ -32,6 +32,9 @@ */ #define UBI_VOL_NUM_AUTO (-1) +/* Maximum volume name length */ +#define UBI_MAX_VOLUME_NAME 127 + /* * IOCTL commands of UBI character devices */ @@ -56,7 +59,7 @@ /* An eraseblock erasure command, used for debugging, disabled by dafault */ #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 0, int32_t) -/** +/* * UBI volume type constants. * * @UBI_DYNAMIC_VOLUME: dynamic volume @@ -113,7 +116,7 @@ struct ubi_mkvol_req { * * @vol_id: ID of the volume to re-size * @bytes: new size of the volume in bytes - * + * * Re-sizing is possible for both dynamic and static volumes. But while dynamic * volumes may be re-sized arbitrarily, static volumes cannot be made to be * smaller then the number of bytes they bear. To arbitrarily shrink a static diff --git a/ubi-utils/src/config.h b/ubi-utils/src/config.h index 746fa3c..b5bbd5b 100644 --- a/ubi-utils/src/config.h +++ b/ubi-utils/src/config.h @@ -20,8 +20,8 @@ * Author: Frank Haverkamp */ -#define PACKAGE_VERSION "1.0" -#define PACKAGE_BUGREPORT "dedekind@oktetlabs.ru, haver@vnet.ibm.com, or tglx@linutronix.de" +#define PACKAGE_VERSION "1.1" +#define PACKAGE_BUGREPORT "haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de" #define __unused __attribute__((unused)) diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c index 9b9a793..979f157 100644 --- a/ubi-utils/src/libubi.c +++ b/ubi-utils/src/libubi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "libubi.h" #include "libubi_int.h" @@ -47,7 +48,6 @@ * @sysfs_root sysfs root directory * @ubi_root UBI root directory in sysfs * - * @nlen_max full path to the "maximum volume name length" sysfs file * @version full path to the "UBI version" sysfs file * * @cdev_path path pattern to UBI character devices @@ -85,7 +85,6 @@ struct ubi_lib char *sysfs_root; char *ubi_root; - char *nlen_max; char *version; char *cdev_path; int cdev_path_len; @@ -147,10 +146,6 @@ get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) if (err) return -1; - err = sysfs_read_int(desc->nlen_max, (int*) &ubi->nlen_max); - if (err) - return -1; - /* Calculate number of UBI devices */ do { char dir[20]; @@ -186,7 +181,6 @@ ubi_dump_handler(ubi_lib_t desc) ubi_lib_t d = desc; printf( "UBI Library Descriptor:\n" "ubi_root: %s\n" - "nlen_max: %s\n" "version: %s\n" "cdev_path: %s\n" "udev_path: %s\n" @@ -204,12 +198,12 @@ ubi_dump_handler(ubi_lib_t desc) "vol_type_path: %s\n" "vol_name_path: %s\n" "cdev_path_len: %d\n\n", - d->ubi_root, d->nlen_max, d->version, d->cdev_path, - d->udev_path, d->wear_path, d->vol_count_path, - d->tot_ebs_path, d->avail_ebs_path, d->eb_size_path, - d->nums_path, d->vol_cdev_path, d->vdev_path, - d->vol_nums_path, d->vol_bytes_path, d->vol_ebs_path, - d->vol_type_path, d->vol_name_path, d->cdev_path_len); + d->ubi_root, d->version, d->cdev_path, d->udev_path, + d->wear_path, d->vol_count_path, d->tot_ebs_path, + d->avail_ebs_path, d->eb_size_path, d->nums_path, + d->vol_cdev_path, d->vdev_path, d->vol_nums_path, + d->vol_bytes_path, d->vol_ebs_path, d->vol_type_path, + d->vol_name_path, d->cdev_path_len); } int @@ -281,11 +275,7 @@ ubi_open(ubi_lib_t *desc) if (!res->ubi_root) goto error; - res->nlen_max = mkpath(res->ubi_root, UBI_NLEN_MAX); - if (!res->nlen_max) - goto error; - - res->version = mkpath(res->ubi_root, UBI_VERSION); + res->version = mkpath(res->ubi_root, UBI_VER); if (!res->version) goto error; @@ -394,7 +384,6 @@ ubi_close(ubi_lib_t *desc) free(tmp->udev_path); free(tmp->cdev_path); free(tmp->version); - free(tmp->nlen_max); free(tmp->ubi_root); free(tmp->sysfs_root); free(tmp); @@ -486,7 +475,7 @@ ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, int err; int len; char buf1[10]; - char buf2[desc->ubi.nlen_max]; + char buf2[UBI_MAX_VOLUME_NAME]; err = sysfs_read_dev_subst(desc->vol_nums_path, &req->major, &req->minor, 2, devn, vol_id); @@ -523,7 +512,7 @@ ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, } len = sysfs_read_data_subst(desc->vol_name_path, &buf2[0], - desc->ubi.nlen_max, 2, devn, vol_id); + UBI_MAX_VOLUME_NAME, 2, devn, vol_id); if (len == -1) return -1; diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h index ab387f5..830a682 100644 --- a/ubi-utils/src/libubi_int.h +++ b/ubi-utils/src/libubi_int.h @@ -1,5 +1,3 @@ -#ifndef __UBI_INT_H__ -#define __UBI_INT_H__ /* * Copyright (c) International Business Machines Corp., 2006 * @@ -24,6 +22,8 @@ * Author: Artem B. Bityutskiy */ +#ifndef __UBI_INT_H__ +#define __UBI_INT_H__ /* * Enable/disable UBI library debugging messages. */ @@ -58,7 +58,7 @@ * @def UBI_NLEN_MAX * @brief Name of syfs file containing the maximum UBI volume name length. * - * @def UBI_VERSION + * @def UBI_VER * @brief Name of sysfs file containing UBI version. * * @def UBI_WEAR @@ -98,7 +98,7 @@ **/ #define UBI_ROOT "ubi" #define UBI_NLEN_MAX "volume_name_max" -#define UBI_VERSION "version" +#define UBI_VER "version" #define UBI_WEAR "wear" #define UBI_VOL_COUNT "volumes_count" #define UBI_TOT_EBS "total_eraseblocks" diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c index 30c569c..d35d2f3 100644 --- a/ubi-utils/src/ubimkvol.c +++ b/ubi-utils/src/ubimkvol.c @@ -19,13 +19,16 @@ /* * An utility to create UBI volumes. * - * Author: Artem B. Bityutskiy + * Author: Artem B. Bityutskiy + * Frank Haverkamp * * 1.0 Initial release * 1.1 Does not support erase blocks anymore. This is replaced by * the number of bytes. + * 1.2 Reworked the user-interface to use argp. */ +#include #include #include #include @@ -33,178 +36,229 @@ #include #include -#include "config.h" +#include #include -static void usage(void); -static int param_sanity_check(ubi_lib_t lib); -static int parse_options(int argc, char * const argv[]); +#define VERSION "1.2" /* - * The variables below are set by command line arguments. + * The variables below are set by command line arguments. */ -static int vol_type = UBI_DYNAMIC_VOLUME; -static int devn = -1; -static long long bytes = 0; -static int alignment = 1; -static int vol_id = UBI_VOL_NUM_AUTO; -static char *name = NULL; -static int nlen = 0; +struct args { + int devn; + int vol_id; + int vol_type; + long long bytes; + int alignment; + char *name; + int nlen; -int main(int argc, char * const argv[]) -{ - int err; - ubi_lib_t lib; + /* special stuff needed to get additional arguments */ + char *arg1; + char **options; /* [STRING...] */ +}; - err = parse_options(argc, argv); - if (err) { - fprintf(stderr, "Wrong options ...\n"); - return err == 1 ? 0 : -1; - } +static struct args myargs = { + .vol_type = UBI_DYNAMIC_VOLUME, + .devn = -1, + .bytes = 0, + .alignment = 1, + .vol_id = UBI_VOL_NUM_AUTO, + .name = NULL, + .nlen = 0, +}; - if (devn == -1) { - fprintf(stderr, "Device number was not specified\n"); - fprintf(stderr, "Use -h option for help\n"); - return -1; - } +static int param_sanity_check(struct args *args, ubi_lib_t lib); +static error_t parse_opt(int key, char *optarg, struct argp_state *state); +const char *argp_program_bug_address = PACKAGE_BUGREPORT; - err = ubi_open(&lib); - if (err) { - perror("Cannot open libubi"); - return -1; - } +static char doc[] = "\nVersion: " VERSION "\n\t" + BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n" + "\nMake UBI Volume.\n"; - err = param_sanity_check(lib); - if (err) { - perror("Input parameters check"); - fprintf(stderr, "Use -h option for help\n"); - goto out_libubi; - } +static struct argp_option options[] = { + { .name = "devn", + .key = 'd', + .arg = "", + .flags = 0, + .doc = "UBI device", + .group = OPTION_ARG_OPTIONAL }, - err = ubi_mkvol(lib, devn, vol_id, vol_type, bytes, alignment, name); - if (err < 0) { - perror("Cannot create volume"); - fprintf(stderr, " err=%d\n", err); - goto out_libubi; - } + { .name = "vol_id", + .key = 'n', + .arg = "", + .flags = 0, + .doc = "UBI volume id, if not specified, the volume ID will be " + "assigned automatically", + .group = OPTION_ARG_OPTIONAL }, - /* printf("Created volume %d, %lld bytes, type %s, name %s\n", - vol_id, bytes, vol_type == UBI_DYNAMIC_VOLUME ? - "dynamic" : "static", name); */ + { .name = "type", + .key = 't', + .arg = "", + .flags = 0, + .doc = "volume type (dynamic, static), default is dynamic", + .group = OPTION_ARG_OPTIONAL }, - vol_id = err; - ubi_close(&lib); - return 0; + { .name = "size", + .key = 's', + .arg = "", + .flags = 0, + .doc = "volume size volume size in bytes, " + "kilobytes (KiB) or megabytes (MiB)", + .group = OPTION_ARG_OPTIONAL }, -out_libubi: - ubi_close(&lib); - return -1; -} + { .name = "name", + .key = 'N', + .arg = "", + .flags = 0, + .doc = "volume name", + .group = OPTION_ARG_OPTIONAL }, + + { .name = "alignment", + .key = 'a', + .arg = "", + .flags = 0, + .doc = "volume alignment (default is 1)", + .group = OPTION_ARG_OPTIONAL }, -/* 'getopt()' option string */ -static const char *optstring = "ht:s:n:N:d:a:"; + { .name = NULL, .key = 0, .arg = NULL, .flags = 0, + .doc = NULL, .group = 0 }, +}; -static int parse_options(int argc, char * const argv[]) +static struct argp argp = { + .options = options, + .parser = parse_opt, + .args_doc = 0, + .doc = doc, + .children = NULL, + .help_filter = NULL, + .argp_domain = NULL, +}; + +/* + * @brief Parse the arguments passed into the test case. + * + * @param key The parameter. + * @param arg Argument passed to parameter. + * @param state Location to put information on parameters. + * + * @return error + * + * Get the `input' argument from `argp_parse', which we know is a + * pointer to our arguments structure. + */ +static error_t +parse_opt(int key, char *optarg, struct argp_state *state) { - int opt = 0; - - while (opt != -1) { - char *endp; - - opt = getopt(argc, argv, optstring); - - switch (opt) { - case 'h': - usage(); - return 1; - case 't': - if (!strcmp(optarg, "dynamic")) - vol_type = UBI_DYNAMIC_VOLUME; - else if (!strcmp(optarg, "static")) - vol_type = UBI_STATIC_VOLUME; - else { - fprintf(stderr, "Bad volume type: \"%s\"\n", - optarg); - goto out; - } - break; - case 's': - bytes = strtoull(optarg, &endp, 0); - if (endp == optarg || bytes < 0) { - fprintf(stderr, "Bad volume size: \"%s\"\n", - optarg); - goto out; - } - if (endp != '\0') { - if (strcmp(endp, "KiB") == 0) - bytes *= 1024; - else if (strcmp(endp, "MiB") == 0) - bytes *= 1024*1024; - } - break; - case 'a': - alignment = strtoul(optarg, &endp, 0); - if (*endp != '\0' || endp == optarg || - alignment <= 0) { - fprintf(stderr, "Bad volume alignment: " - "\"%s\"\n", optarg); - goto out; - } - break; - case 'd': - devn = strtoul(optarg, &endp, 0); - if (*endp != '\0' || endp == optarg || devn < 0) { - fprintf(stderr, "Bad UBI device number: " - "\"%s\"\n", optarg); - goto out; - } - break; - case 'n': - vol_id = strtoul(optarg, &endp, 0); - if (*endp != '\0' || endp == optarg || - (vol_id < 0 && vol_id != UBI_DYNAMIC_VOLUME)) { - fprintf(stderr, "Bad volume ID: " - "\"%s\"\n", optarg); - goto out; - } - break; - case 'N': - name = optarg; - nlen = strlen(name); - break; - - case ':': - fprintf(stderr, "Parameter is missing\n"); + char *endp; + struct args *args = state->input; + + switch (key) { + case 't': + if (!strcmp(optarg, "dynamic")) + args->vol_type = UBI_DYNAMIC_VOLUME; + else if (!strcmp(optarg, "static")) + args->vol_type = UBI_STATIC_VOLUME; + else { + fprintf(stderr, "Bad volume type: \"%s\"\n", + optarg); goto out; - case '?': - fprintf(stderr, "Unknown parameter\n"); + } + break; + case 's': + args->bytes = strtoull(optarg, &endp, 0); + if (endp == optarg || args->bytes < 0) { + fprintf(stderr, "Bad volume size: \"%s\"\n", + optarg); goto out; - case -1: - break; - default: - fprintf(stderr, "Internal error\n"); + } + if (endp != '\0') { + if (strcmp(endp, "KiB") == 0) + args->bytes *= 1024; + else if (strcmp(endp, "MiB") == 0) + args->bytes *= 1024*1024; + } + break; + case 'a': + args->alignment = strtoul(optarg, &endp, 0); + if (*endp != '\0' || endp == optarg || + args->alignment <= 0) { + fprintf(stderr, "Bad volume alignment: " + "\"%s\"\n", optarg); goto out; } + break; + case 'd': /* --devn= */ + args->devn = strtoul(optarg, &endp, 0); + if (*endp != '\0' || endp == optarg || args->devn < 0) { + fprintf(stderr, "Bad UBI device number: " + "\"%s\"\n", optarg); + goto out; + } + break; + case 'n': /* --volid= */ + args->vol_id = strtoul(optarg, &endp, 0); + if (*endp != '\0' || endp == optarg || + (args->vol_id < 0 && args->vol_id != UBI_DYNAMIC_VOLUME)) { + fprintf(stderr, "Bad volume ID: " + "\"%s\"\n", optarg); + goto out; + } + break; + case 'N': + args->name = optarg; + args->nlen = strlen(args->name); + break; + + case ':': + fprintf(stderr, "Parameter is missing\n"); + goto out; + + case ARGP_KEY_NO_ARGS: + /* argp_usage(state); */ + break; + + case ARGP_KEY_ARG: + args->arg1 = optarg; + /* Now we consume all the rest of the arguments. + `state->next' is the index in `state->argv' of the + next argument to be parsed, which is the first STRING + we're interested in, so we can just use + `&state->argv[state->next]' as the value for + arguments->strings. + + _In addition_, by setting `state->next' to the end + of the arguments, we can force argp to stop parsing + here and return. */ + + args->options = &state->argv[state->next]; + state->next = state->argc; + break; + + case ARGP_KEY_END: + /* argp_usage(state); */ + break; + + default: + return(ARGP_ERR_UNKNOWN); } return 0; - out: - errno = EINVAL; - return -1; + return(ARGP_ERR_UNKNOWN); } -static int param_sanity_check(ubi_lib_t lib) +static int param_sanity_check(struct args *args, ubi_lib_t lib) { int err, len; struct ubi_info ubi; - if (bytes == 0) { + if (args->bytes == 0) { fprintf(stderr, "Volume size was not specified\n"); goto out; } - if (name == NULL) { + if (args->name == NULL) { fprintf(stderr, "Volume name was not specified\n"); goto out; } @@ -213,39 +267,72 @@ static int param_sanity_check(ubi_lib_t lib) if (err) return -1; - if (devn >= (int)ubi.dev_count) { - fprintf(stderr, "Device %d does not exist\n", devn); + if (args->devn >= (int)ubi.dev_count) { + fprintf(stderr, "Device %d does not exist\n", args->devn); goto out; } - len = strlen(name); - if (len > (int)ubi.nlen_max) { + len = strlen(args->name); + if (len > UBI_MAX_VOLUME_NAME) { fprintf(stderr, "Too long name (%d symbols), max is %d\n", - len, ubi.nlen_max); + len, UBI_MAX_VOLUME_NAME); goto out; } return 0; - out: errno = EINVAL; return -1; } -static void usage(void) +int main(int argc, char * const argv[]) { - printf("Usage: ubi_mkvol OPTIONS\n" - "Version: " PACKAGE_VERSION "\n" - "The command line options:\n" - "\t-h - this help message\n" - "\t-d - UBI device number\n" - "\t-t TYPE - volume type (dynamic, static) " - "(default is dynamic)\n" - "\t-n VOLID - volume ID to assign to the new volume. If not" - "specified, \n" - "\t the volume ID will be assigned automatically\n" - "\t-s BYTES - volume size in bytes, " - "kilobytes (KiB) or megabytes (MiB)\n" - "\t-N NAME - volume name\n" - "\t-a ALIGNMENT - volume alignment (default is 1)\n"); + int err; + ubi_lib_t lib; + + err = argp_parse(&argp, argc, (char **)argv, ARGP_IN_ORDER, 0, + &myargs); + if (err) { + fprintf(stderr, "Wrong options ...\n"); + return err == 1 ? 0 : -1; + } + + if (myargs.devn == -1) { + fprintf(stderr, "Device number was not specified\n"); + fprintf(stderr, "Use -h option for help\n"); + return -1; + } + + err = ubi_open(&lib); + if (err) { + perror("Cannot open libubi"); + return -1; + } + + err = param_sanity_check(&myargs, lib); + if (err) { + perror("Input parameters check"); + fprintf(stderr, "Use -h option for help\n"); + goto out_libubi; + } + + err = ubi_mkvol(lib, myargs.devn, myargs.vol_id, myargs.vol_type, + myargs.bytes, myargs.alignment, myargs.name); + if (err < 0) { + perror("Cannot create volume"); + fprintf(stderr, " err=%d\n", err); + goto out_libubi; + } + + /* printf("Created volume %d, %lld bytes, type %s, name %s\n", + vol_id, bytes, vol_type == UBI_DYNAMIC_VOLUME ? + "dynamic" : "static", name); */ + + myargs.vol_id = err; + ubi_close(&lib); + return 0; + +out_libubi: + ubi_close(&lib); + return -1; } diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c index cb47b6c..f810263 100644 --- a/ubi-utils/src/ubirmvol.c +++ b/ubi-utils/src/ubirmvol.c @@ -17,11 +17,15 @@ */ /* - * An utility to create UBI volumes. + * An utility to remove UBI volumes. * - * Autor: Artem B. Bityutskiy + * Author: Artem B. Bityutskiy + * Frank Haverkamp + * + * 1.1 Reworked the userinterface to use argp. */ +#include #include #include #include @@ -29,29 +33,180 @@ #include #include -#include "config.h" +#include #include -static void usage(void); -static int param_sanity_check(ubi_lib_t lib); -static int parse_options(int argc, char * const argv[]); +#define VERSION "1.1" /* * The below variables are set by command line options. */ -static int vol_id = -1; -static int devn = -1; +struct args { + int devn; + int vol_id; + + /* special stuff needed to get additional arguments */ + char *arg1; + char **options; /* [STRING...] */ +}; + +static struct args myargs = { + .devn = -1, + .vol_id = -1, + + .arg1 = NULL, + .options = NULL, +}; + +static int param_sanity_check(struct args *args, ubi_lib_t lib); +static error_t parse_opt(int key, char *optarg, struct argp_state *state); +const char *argp_program_bug_address = PACKAGE_BUGREPORT; + +static char doc[] = "\nVersion: " VERSION "\n\t" + BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n" + "\nMake UBI Volume.\n"; + +static struct argp_option options[] = { + { .name = "devn", + .key = 'd', + .arg = "", + .flags = 0, + .doc = "UBI device", + .group = OPTION_ARG_OPTIONAL }, + + { .name = "vol_id", + .key = 'n', + .arg = "", + .flags = 0, + .doc = "UBI volume id, if not specified, the volume ID will be " + "assigned automatically", + .group = OPTION_ARG_OPTIONAL }, + + { .name = NULL, .key = 0, .arg = NULL, .flags = 0, + .doc = NULL, .group = 0 }, +}; + +static struct argp argp = { + .options = options, + .parser = parse_opt, + .args_doc = 0, + .doc = doc, + .children = NULL, + .help_filter = NULL, + .argp_domain = NULL, +}; + +/* + * @brief Parse the arguments passed into the test case. + * + * @param key The parameter. + * @param arg Argument passed to parameter. + * @param state Location to put information on parameters. + * + * @return error + * + * Get the `input' argument from `argp_parse', which we know is a + * pointer to our arguments structure. + */ +static error_t +parse_opt(int key, char *optarg, struct argp_state *state) +{ + char *endp; + struct args *args = state->input; + + switch (key) { + case 'd': /* --devn= */ + args->devn = strtoul(optarg, &endp, 0); + if (*endp != '\0' || endp == optarg || args->devn < 0) { + fprintf(stderr, "Bad UBI device number: " + "\"%s\"\n", optarg); + goto out; + } + break; + case 'n': /* --volid= */ + args->vol_id = strtoul(optarg, &endp, 0); + if (*endp != '\0' || endp == optarg || + (args->vol_id < 0 && args->vol_id != UBI_DYNAMIC_VOLUME)) { + fprintf(stderr, "Bad volume ID: " + "\"%s\"\n", optarg); + goto out; + } + break; + case ':': + fprintf(stderr, "Parameter is missing\n"); + goto out; + + case ARGP_KEY_NO_ARGS: + /* argp_usage(state); */ + break; + + case ARGP_KEY_ARG: + args->arg1 = optarg; + /* Now we consume all the rest of the arguments. + `state->next' is the index in `state->argv' of the + next argument to be parsed, which is the first STRING + we're interested in, so we can just use + `&state->argv[state->next]' as the value for + arguments->strings. + + _In addition_, by setting `state->next' to the end + of the arguments, we can force argp to stop parsing + here and return. */ + + args->options = &state->argv[state->next]; + state->next = state->argc; + break; + + case ARGP_KEY_END: + /* argp_usage(state); */ + break; + + default: + return(ARGP_ERR_UNKNOWN); + } + + return 0; + out: + return(ARGP_ERR_UNKNOWN); +} + +static int param_sanity_check(struct args *args, ubi_lib_t lib) +{ + int err; + struct ubi_info ubi; + + if (args->vol_id == -1) { + fprintf(stderr, "Volume ID was not specified\n"); + goto out; + } + + err = ubi_get_info(lib, &ubi); + if (err) + return -1; + + if (args->devn >= (int)ubi.dev_count) { + fprintf(stderr, "Device %d does not exist\n", args->devn); + goto out; + } + + return 0; + +out: + errno = EINVAL; + return -1; +} int main(int argc, char * const argv[]) { int err, old_errno; ubi_lib_t lib; - err = parse_options(argc, argv); + err = argp_parse(&argp, argc, (char **)argv, ARGP_IN_ORDER, 0, + &myargs); if (err) return err == 1 ? 0 : -1; - if (devn == -1) { + if (myargs.devn == -1) { fprintf(stderr, "Device number was not specified\n"); fprintf(stderr, "Use -h option for help\n"); return -1; @@ -63,14 +218,14 @@ int main(int argc, char * const argv[]) return -1; } - err = param_sanity_check(lib); + err = param_sanity_check(&myargs, lib); if (err) { perror("Input parameters check"); fprintf(stderr, "Use -h option for help\n"); goto out_libubi; } - err = ubi_rmvol(lib, devn, vol_id); + err = ubi_rmvol(lib, myargs.devn, myargs.vol_id); old_errno = errno; if (err < 0) { perror("Cannot remove volume"); @@ -84,91 +239,3 @@ out_libubi: ubi_close(&lib); return -1; } - -/* 'getopt()' option string */ -static const char *optstring = "hd:n:"; - -static int parse_options(int argc, char * const argv[]) -{ - int opt = 0; - - while (opt != -1) { - char *endp; - - opt = getopt(argc, argv, optstring); - - switch (opt) { - case 'h': - usage(); - return 1; - case 'n': - vol_id = strtoul(optarg, &endp, 0); - if (*endp != '\0' || endp == optarg || vol_id < 0) { - fprintf(stderr, "Bad volume " - "number: \"%s\"\n", optarg); - goto out; - } - break; - case 'd': - devn = strtoul(optarg, &endp, 0); - if (*endp != '\0' || endp == optarg || devn < 0) { - fprintf(stderr, "Bad UBI device " - "number: \"%s\"\n", optarg); - goto out; - } - break; - case ':': - fprintf(stderr, "Parameter is missing\n"); - goto out; - case '?': - fprintf(stderr, "Unknown parameter\n"); - goto out; - case -1: - break; - default: - fprintf(stderr, "Internal error\n"); - goto out; - } - } - - return 0; - -out: - errno = EINVAL; - return -1; -} - -static int param_sanity_check(ubi_lib_t lib) -{ - int err; - struct ubi_info ubi; - - if (vol_id == -1) { - fprintf(stderr, "Volume ID was not specified\n"); - goto out; - } - - err = ubi_get_info(lib, &ubi); - if (err) - return -1; - - if (devn >= (int)ubi.dev_count) { - fprintf(stderr, "Device %d does not exist\n", devn); - goto out; - } - - return 0; - -out: - errno = EINVAL; - return -1; -} - -static void usage(void) -{ - printf("Usage: ubi_rmvol OPTIONS\n" - "Command line options:\n" - "\t-h - this help message\n" - "\t-d - UBI device number\n" - "\t-n VOLNUM - volume number to remove\n"); -} diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c index 28e1e8f..fd68dd8 100644 --- a/ubi-utils/src/ubiupdatevol.c +++ b/ubi-utils/src/ubiupdatevol.c @@ -14,14 +14,16 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * An utility to update UBI volumes. * * Author: Frank Haverkamp * - * An utility to update UBI volumes. + * 1.0 Reworked the userinterface to use argp. */ -#include - #include #include #include @@ -36,15 +38,18 @@ #include #include +#include #include +#define VERSION "1.0" + #define MAXPATH 1024 #define BUFSIZE 128 * 1024 #define MIN(x,y) ((x)<(y)?(x):(y)) struct args { - int device; - int volume; + int devn; + int vol_id; int truncate; int broken_update; int bufsize; @@ -55,8 +60,8 @@ struct args { }; static struct args myargs = { - .device = -1, - .volume = -1, + .devn = -1, + .vol_id = -1, .truncate = 0, .broken_update = 0, .bufsize = BUFSIZE, @@ -64,25 +69,24 @@ static struct args myargs = { .options = NULL, }; -static int verbose = 0; - static error_t parse_opt (int key, char *arg, struct argp_state *state); +static int verbose = 0; const char *argp_program_bug_address = PACKAGE_BUGREPORT; -static char doc[] = "\nVersion: " PACKAGE_VERSION "\n\t" +static char doc[] = "\nVersion: " VERSION "\n\t" BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n" "\nWrite to UBI Volume.\n"; static struct argp_option options[] = { - { .name = "device", + { .name = "devn", .key = 'd', - .arg = "", + .arg = "", .flags = 0, .doc = "UBI device", .group = OPTION_ARG_OPTIONAL }, - { .name = "volume", + { .name = "vol_id", .key = 'n', .arg = "", .flags = 0, @@ -139,8 +143,12 @@ parse_opt(int key, char *arg, struct argp_state *state) verbose = strtoul(arg, (char **)NULL, 0); break; - case 'd': /* --device= */ - args->device = strtol(arg, (char **)NULL, 0); + case 'n': /* --vol_id= */ + args->vol_id = strtol(arg, (char **)NULL, 0); + break; + + case 'd': /* --devn= */ + args->devn = strtol(arg, (char **)NULL, 0); break; case 'b': /* --bufsize= */ @@ -157,10 +165,6 @@ parse_opt(int key, char *arg, struct argp_state *state) args->broken_update = 1; break; - case 'n': /* --volume= */ - args->volume = strtol(arg, (char **)NULL, 0); - break; - case ARGP_KEY_NO_ARGS: /* argp_usage(state); */ break; @@ -175,8 +179,8 @@ parse_opt(int key, char *arg, struct argp_state *state) arguments->strings. _In addition_, by setting `state->next' to the end - of the arguments, we can force argp to stop parsing here and - return. */ + of the arguments, we can force argp to stop parsing + here and return. */ args->options = &state->argv[state->next]; state->next = state->argc; @@ -205,7 +209,7 @@ ubi_truncate_volume(struct args *args, int64_t bytes) char path[MAXPATH]; int old_errno; - snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->device, args->volume); + snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id); path[MAXPATH-1] = '\0'; ofd = open(path, O_RDWR); @@ -279,7 +283,7 @@ ubi_update_volume(struct args *args) if (!ifp) exit(EXIT_FAILURE); - snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->device, args->volume); + snprintf(path, MAXPATH-1, "/dev/ubi%d_%d", args->devn, args->vol_id); path[MAXPATH-1] = '\0'; ofd = open(path, O_RDWR); -- cgit v1.2.3 From 9fe86e65fb6bd77a02955d07d6f336ace4984e2d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Feb 2007 20:41:17 -0600 Subject: Fix several issues when compiling for 64bit systems Signed-off-by: Josh Boyer --- ubi-utils/src/hashmap.c | 2 +- ubi-utils/src/libubi.c | 4 ++-- ubi-utils/src/nand2bin.c | 2 +- ubi-utils/src/pfi.c | 2 +- ubi-utils/src/reader.c | 7 ++++--- ubi-utils/src/unubi.c | 2 +- ubi-utils/src/unubi_analyze.c | 20 ++++++++++---------- 7 files changed, 20 insertions(+), 19 deletions(-) (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/src/hashmap.c b/ubi-utils/src/hashmap.c index 250f71f..3511d56 100644 --- a/ubi-utils/src/hashmap.c +++ b/ubi-utils/src/hashmap.c @@ -323,7 +323,7 @@ hashmap_dump(hashmap_t map) for(i = 0; i < map->maxsize; i++) { if (map->data[i] != NULL) { - printf("[%d]: ", i); + printf("[%zd]: ", i); print_all(map->data[i]); } } diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c index 979f157..7cb74bf 100644 --- a/ubi-utils/src/libubi.c +++ b/ubi-utils/src/libubi.c @@ -698,8 +698,8 @@ ubi_vol_update(int vol_fd, unsigned long long bytes) err = ioctl(vol_fd, UBI_IOCVOLUP, &bytes); if (err) { ubi_err("%s failure calling update ioctl\n" - " IOCTL(%08x) err=%d errno=%d\n", - __func__, UBI_IOCVOLUP, err, errno); + " IOCTL(%08lx) err=%d errno=%d\n", + __func__, (long unsigned int)UBI_IOCVOLUP, err, errno); } return err; } diff --git a/ubi-utils/src/nand2bin.c b/ubi-utils/src/nand2bin.c index 636ee6f..b8e4ea3 100644 --- a/ubi-utils/src/nand2bin.c +++ b/ubi-utils/src/nand2bin.c @@ -203,7 +203,7 @@ process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize) case 2048: oobsize = 64; eccpoi = 64 / 2; break; case 512: oobsize = 16; eccpoi = 16 / 2; break; default: - fprintf(stderr, "Unsupported page size: %d\n", pagesize); + fprintf(stderr, "Unsupported page size: %zd\n", pagesize); return -EINVAL; } memset(oobbuf, 0xff, oobsize); diff --git a/ubi-utils/src/pfi.c b/ubi-utils/src/pfi.c index 7b57559..fa835e2 100644 --- a/ubi-utils/src/pfi.c +++ b/ubi-utils/src/pfi.c @@ -253,7 +253,7 @@ int pfi_header_setvalue (pfi_header head, { int key_id = find_key_by_name(key); - if ((uint32_t)value == (uint32_t)NULL) + if (value == NULL) return PFI_EINSUFF; if ((key_id < 0) || (key_id >= num_keys)) diff --git a/ubi-utils/src/reader.c b/ubi-utils/src/reader.c index 975caa1..7935a15 100644 --- a/ubi-utils/src/reader.c +++ b/ubi-utils/src/reader.c @@ -178,7 +178,8 @@ read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw, } rc = bootenv_list_to_num_vector(raw_start_list, - &(res->starts_size), &(res->starts)); + (void *) &(res->starts_size), + &(res->starts)); if (rc != 0) { EBUF_PFI("Cannot create numeric value array: %s", tmp_str); goto err; @@ -246,7 +247,7 @@ read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, goto err; } - rc = bootenv_list_to_num_vector(ubi_id_list, &(res->ids_size), + rc = bootenv_list_to_num_vector(ubi_id_list, (void *) &(res->ids_size), &(res->ids)); if (rc != 0) { EBUF_PFI("Cannot create numeric value array: %s", tmp_str); @@ -298,7 +299,7 @@ read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, EBUF_PFI("Cannot translate PFI value: %s", tmp_str); goto err; } - rc = bootenv_list_to_vector(ubi_name_list, &(res->names_size), + rc = bootenv_list_to_vector(ubi_name_list, (void *) &(res->names_size), &(tmp_names)); if (rc != 0) { EBUF_PFI("Cannot create string array: %s", tmp_str); diff --git a/ubi-utils/src/unubi.c b/ubi-utils/src/unubi.c index cade1e1..811a6db 100644 --- a/ubi-utils/src/unubi.c +++ b/ubi-utils/src/unubi.c @@ -102,7 +102,7 @@ static const char *usage = #define FN_INVAL "%s/eb%04u%s" /* invalid eraseblock */ #define FN_NSURE "%s/eb%04u_%03u_%03u_%03x%s" /* unsure eraseblock */ #define FN_VALID "%s/eb%04u_%03u_%03u_%03x%s" /* valid eraseblock */ -#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04u" /* split volume */ +#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04zu" /* split volume */ #define FN_VOLWH "%s/volume%03u" /* whole volume */ static uint32_t crc32_table[256]; diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c index 2e94ca9..6009fc0 100644 --- a/ubi-utils/src/unubi_analyze.c +++ b/ubi-utils/src/unubi_analyze.c @@ -167,9 +167,9 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path) (crc != ubi32_to_cpu(cur->outer.hdr_crc))) fprintf(fpdata, "# "); - fprintf(fpdata, "%u %llu %llu", count, - ubi64_to_cpu(cur->outer.ec), - erase_counts[count]); + fprintf(fpdata, "%zu %llu %llu", count, + (unsigned long long) ubi64_to_cpu(cur->outer.ec), + (unsigned long long) erase_counts[count]); if (ubi32_to_cpu(cur->outer.magic) != UBI_EC_HDR_MAGIC) fprintf(fpdata, " ## bad magic: %08x", @@ -198,7 +198,7 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path) if ((count % EC_X_INT) == 0) { if (count > 0) fprintf(fpplot, ", "); - fprintf(fpplot, "%d", count); + fprintf(fpplot, "%zd", count); } cur = cur->next; @@ -207,9 +207,9 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path) fprintf(fpplot, ")\n"); fprintf(fpplot, "set ylabel \"erase count\"\n"); - fprintf(fpplot, "set xrange [-1:%u]\n", eraseblocks + 1); + fprintf(fpplot, "set xrange [-1:%zu]\n", eraseblocks + 1); fprintf(fpplot, "# set yrange [-1:%llu]\n", - erase_counts[eraseblocks - 1] + 1); + (unsigned long long) erase_counts[eraseblocks - 1] + 1); fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n", FN_EH_DATA, FN_EH_DATA); fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n", @@ -299,7 +299,7 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path) if ((y1 == -1) || (y2 == -1)) return -1; - fprintf(fpdata, "%u %u %u %u %u %u %u\n", + fprintf(fpdata, "%zu %u %u %u %u %u %u\n", count, ubi32_to_cpu(cur->inner.vol_id), ubi32_to_cpu(cur->inner.lnum), @@ -325,10 +325,10 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path) fprintf(fpplot, ", "); if (step != ubi32_to_cpu(cur->inner.vol_id)) { step = ubi32_to_cpu(cur->inner.vol_id); - fprintf(fpplot, "\"%d\" %d 0", step, count); + fprintf(fpplot, "\"%zd\" %zd 0", step, count); } else - fprintf(fpplot, "\"%d\" %d 1", + fprintf(fpplot, "\"%d\" %zd 1", ubi32_to_cpu(cur->inner.lnum), count); cur = cur->next; count++; @@ -384,7 +384,7 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path) y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth); y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth); - fprintf(fpplot, "set xrange [-1:%u]\n", count + 1); + fprintf(fpplot, "set xrange [-1:%zu]\n", count + 1); fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1); fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1); fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" " -- cgit v1.2.3 From 8bc5349626f1a83f49dd400ca6f45e0bb8347a4e Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Wed, 28 Feb 2007 10:29:34 +0100 Subject: UBI Tools - problem with multiple ubi devices. Fix problem with multiple ubi devices Signed-off-by: Alexander Schmidt Signed-off-by: Josh Boyer --- ubi-utils/src/libubi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c index 7cb74bf..62216ad 100644 --- a/ubi-utils/src/libubi.c +++ b/ubi-utils/src/libubi.c @@ -138,7 +138,7 @@ static int get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) { int err; - int n = 1; + int dev_count = 0; char *path; struct stat stat; @@ -147,31 +147,31 @@ get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) return -1; /* Calculate number of UBI devices */ - do { + while (!err) { char dir[20]; - sprintf(&dir[0], "ubi%d", n); - path = mkpath(desc->sysfs_root, dir); + sprintf(&dir[0], "ubi%d", dev_count); + path = mkpath(desc->ubi_root, dir); if (!path) return ENOMEM; err = lstat(path, &stat); if (err == 0) - n += 1; + dev_count += 1; free(path); - } while (err == 0); + } if (errno != ENOENT) return -1; - if (n == 0) { + if (dev_count == 0) { ubi_err("no UBI devices found"); errno = EINVAL; return -1; } errno = 0; - ubi->dev_count = n; + ubi->dev_count = dev_count; return 0; } -- cgit v1.2.3 From 2271f47026e986ecd038db8fbf7a1d14c11a7b64 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 16 Mar 2007 18:07:43 +0200 Subject: UBI-Utils: Updated libubi for latest UBI Signed-off-by: Adrian Hunter --- ubi-utils/src/libubi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c index 62216ad..da4919b 100644 --- a/ubi-utils/src/libubi.c +++ b/ubi-utils/src/libubi.c @@ -311,7 +311,7 @@ ubi_open(ubi_lib_t *desc) if (err) goto error; - res->vdev_path = mkpath(res->udev_path, "%d/"); + res->vdev_path = mkpath(res->ubi_root, "ubi%d_%d/"); if (!res->vdev_path) goto error; @@ -595,6 +595,11 @@ ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, int fd; int err; struct ubi_mkvol_req req; + size_t n; + + n = strlen(name); + if (n > UBI_MAX_VOLUME_NAME) + return -1; if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) return -1; @@ -603,8 +608,9 @@ ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, req.bytes = bytes; req.vol_type = vol_type; req.alignment = alignment; - req.name_len = strlen(name); - req.name = name; + + strncpy(req.name, name, UBI_MAX_VOLUME_NAME + 1); + req.name_len = n; /* printf("DBG: %s(vol_id=%d, bytes=%lld, type=%d, alig=%d, nlen=%d, " "name=%s)\n", __func__, vol_id, bytes, vol_type, alignment, -- cgit v1.2.3 From db0fa8cfb0fae8c07c4c88f73bbc71176df36d7c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 21 Mar 2007 11:45:07 +0200 Subject: UBI-Utils: Rename old ubi library Signed-off-by: Adrian Hunter --- ubi-utils/inc/libubi.h | 310 ---------------- ubi-utils/inc/libubiold.h | 310 ++++++++++++++++ ubi-utils/src/libubi.c | 768 ---------------------------------------- ubi-utils/src/libubi_int.h | 119 ------- ubi-utils/src/libubi_sysfs.c | 232 ------------ ubi-utils/src/libubi_sysfs.h | 109 ------ ubi-utils/src/libubiold.c | 768 ++++++++++++++++++++++++++++++++++++++++ ubi-utils/src/libubiold_int.h | 119 +++++++ ubi-utils/src/libubiold_sysfs.c | 232 ++++++++++++ ubi-utils/src/libubiold_sysfs.h | 109 ++++++ 10 files changed, 1538 insertions(+), 1538 deletions(-) delete mode 100644 ubi-utils/inc/libubi.h create mode 100644 ubi-utils/inc/libubiold.h delete mode 100644 ubi-utils/src/libubi.c delete mode 100644 ubi-utils/src/libubi_int.h delete mode 100644 ubi-utils/src/libubi_sysfs.c delete mode 100644 ubi-utils/src/libubi_sysfs.h create mode 100644 ubi-utils/src/libubiold.c create mode 100644 ubi-utils/src/libubiold_int.h create mode 100644 ubi-utils/src/libubiold_sysfs.c create mode 100644 ubi-utils/src/libubiold_sysfs.h (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/inc/libubi.h deleted file mode 100644 index f13d812..0000000 --- a/ubi-utils/inc/libubi.h +++ /dev/null @@ -1,310 +0,0 @@ -#ifndef __UBI_H__ -#define __UBI_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * UBI (Unsorted Block Images) library. - * @file libubi.h - * @author Artem B. Bityutskiy - * @author Additions: Oliver Lohmann - * @version 1.0 - */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @section eh Error Handling - * The following error indication policy is used: in case of success, all - * library functions return 0, in case of failure they either return UBI error - * codes, or -1 if a system error occured; in the latter case the exact error - * code has to be in the errno variable. - * - * @def UBI_ENOTFOUND - * @brief UBI was not found in the system. - * @def UBI_EBUG - * @brief An error due to bug in kernel part of UBI in UBI library. - * @def UBI_EINVAL - * @brief Invalid argument. - * @def UBI_EMACS - * @brief Highest error value. - */ -#define UBI_ENOTFOUND 1 -#define UBI_EBUG 2 -#define UBI_EINVAL 3 -#define UBI_EMAX 4 - - -/** - * UBI library descriptor, vague for library users. - */ -typedef struct ubi_lib *ubi_lib_t; - -/** - * struct ubi_info - general information about UBI. - * - * @version UBI version - * @nlen_max maximum length of names of volumes - * @dev_count count UBI devices in the system - */ -struct ubi_info -{ - unsigned int version; - unsigned int nlen_max; - unsigned int dev_count; -}; - -/** - * struct ubi_dev_info - information about an UBI device - * - * @wear average number of erasures of flash erasable blocks - * @major major number of the corresponding character device - * @minor minor number of the corresponding character device - * @eb_size size of eraseblocks - * @total_ebs total count of eraseblocks - * @avail_ebs count of unused eraseblock available for new volumes - * @vol_count total count of volumes in this UBI device - */ -struct ubi_dev_info -{ - unsigned long long wear; - unsigned int major; - unsigned int minor; - unsigned int eb_size; - unsigned int total_ebs; - unsigned int avail_ebs; - unsigned int vol_count; -}; - -/** - * struct ubi_vol_info - information about an UBI volume - * - * @bytes volume size in bytes - * @eraseblocks volume size in eraseblocks - * @major major number of the corresponding character device - * @minor minor number of the corresponding character device - * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) - * @dev_path device path to volume - * @name volume name - */ -struct ubi_vol_info -{ - unsigned long long bytes; - unsigned int eraseblocks; - unsigned int major; - unsigned int minor; - int type; - char *dev_path; - char *name; -}; - -/** - * ubi_mkvol - create a dynamic UBI volume. - * - * @desc UBI library descriptor - * @devn Number of UBI device to create new volume on - * @vol_id volume ID to assign to the new volume - * @vol_type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) - * @bytes volume size in bytes - * @alignment volume alignment - * @name volume name - * - * This function creates new UBI volume. If @vol_id is %UBI_VOLN_AUTO, then - * volume number is assigned automatically. This function returns positive - * volume number of the new volume in case of success or %-1 in case of - * failure. - */ -int ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, - long long bytes, int alignment, const char *name); - -/** - * ubi_rmvol - remove a volume. - * - * @desc UBI library descriptor - * @devn Number of UBI device to remove volume from - * @vol_id volume ID to remove - * - * This function returns zero in case of success or %-1 in case of failure. - */ -int ubi_rmvol(ubi_lib_t desc, int devn, int vol_id); - -/** - * ubi_get_info - get UBI information. - * - * @desc UBI library descriptor - * @ubi UBI information is returned here - * - * This function retrieves information about UBI and puts it to @ubi. Returns - * zero in case of success and %-1 in case of failure. - */ -int ubi_get_info(ubi_lib_t desc, struct ubi_info *ubi); - -/** - * ubi_vol_open - open a UBI volume - * - * @desc UBI library descriptor - * @devn Number of UBI device on which to open the volume - * @vol_id Number of UBI device on which to open the volume - * @flags Flags to pass to open() - * - * This function opens a UBI volume on a given UBI device. It returns - * the file descriptor of the opened volume device. In case of an - * error %-1 is returned and errno is set appropriately. - */ -int ubi_vol_open(ubi_lib_t desc, int devn, int vol_id, int flags); - -/** - * ubi_vol_close - close a UBI volume - * - * @vol_fd file descriptor of UBI volume to close - * - * This function closes the given UBI device. - */ -int ubi_vol_close(int vol_fd); - -/** - * ubi_vol_update - initiate volume update on a UBI volume - * @vol_fd File descriptor of UBI volume to update - * @bytes No. of bytes which shall be written. - * - * Initiates a volume update on a given volume. The caller must then - * actually write the appropriate number of bytes to the volume by - * calling write(). Returns 0 on success, else error. - */ -int ubi_vol_update(int vol_fd, unsigned long long bytes); - -/** - * ubi_vol_fopen_read - open a volume for reading, returning a FILE * - * @desc UBI library descriptor - * @devn UBI device number - * @vol_id volume ID to read - * - * Opens a volume for reading. Reading itself can then be performed - * with fread(). The stream can be closed with fclose(). Returns a - * stream on success, else NULL. - */ -FILE * -ubi_vol_fopen_read(ubi_lib_t desc, int devn, uint32_t vol_id); - -/** - * ubi_vol_fopen_update - open a volume for writing, returning a FILE * - * @desc UBI library descriptor - * @devn UBI device number - * @vol_id volume ID to update - * @bytes No. of bytes which shall be written. - * - * Initiates a volume update on a given volume. The caller must then - * actually write the appropriate number of bytes to the volume by - * calling fwrite(). The file can be closed with fclose(). Returns a - * stream on success, else NULL. - */ -FILE * -ubi_vol_fopen_update(ubi_lib_t desc, int devn, uint32_t vol_id, - unsigned long long bytes); - -/** - * ubi_vol_get_used_bytes - determine used bytes in a UBI volume - * @vol_fd File descriptor of UBI volume - * @bytes Pointer to result - * - * Returns 0 on success, else error. - */ -int ubi_vol_get_used_bytes(int vol_fd, unsigned long long *bytes); - -/** - * ubi_open - open UBI library. - * - * @desc A pointer to an UBI library descriptor - * - * Returns zero in case of success. - */ -int ubi_open(ubi_lib_t *desc); - -/** - * ubi_close - close UBI library. - * - * @desc A pointer to an UBI library descriptor - */ -int ubi_close(ubi_lib_t *desc); - - -/** - * ubi_perror - print UBI error. - * - * @prefix a prefix string to prepend to the error message - * @code error code - * - * If @code is %-1, this function calls 'perror()' - */ -void ubi_perror(const char *prefix, int code); - -/** - * ubi_set_cdev_pattern - set 'sprintf()'-like pattern of paths to UBI - * character devices. - * - * @desc UBI library descriptor - * @pattern the pattern to set - * - * The default UBI character device path is "/dev/ubi%u". - */ -int ubi_set_cdev_pattern(ubi_lib_t desc, const char *pattern); - -/** - * ubi_get_dev_info get information about an UBI device. - * - * @desc UBI library descriptor - * @devn UBI device number - * @di the requested information is returned here - */ -int ubi_get_dev_info(ubi_lib_t desc, unsigned int devn, - struct ubi_dev_info *di); - -/** - * ubi_set_vol_cdev_pattern - set 'sprintf()'-like pattµern ofpaths to UBI - * volume character devices. - * - * @desc UBI library descriptor - * @pattern the pattern to set - * - * The default UBI character device path is "/dev/ubi%u_%u". - */ -int ubi_set_vol_cdev_pattern(ubi_lib_t desc, const char *pattern); - -/** - * ubi_get_vol_info - get information about an UBI volume - * - * @desc UBI library descriptor - * @devn UBI device number the volume belongs to - * @vol_id the requested volume number - * @vi volume information is returned here - * - * Users must free the volume name string @vi->name. - */ -int ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, - struct ubi_vol_info *vi); - -#ifdef __cplusplus -} -#endif - -#endif /* !__UBI_H__ */ diff --git a/ubi-utils/inc/libubiold.h b/ubi-utils/inc/libubiold.h new file mode 100644 index 0000000..f13d812 --- /dev/null +++ b/ubi-utils/inc/libubiold.h @@ -0,0 +1,310 @@ +#ifndef __UBI_H__ +#define __UBI_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * @file libubi.h + * @author Artem B. Bityutskiy + * @author Additions: Oliver Lohmann + * @version 1.0 + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @section eh Error Handling + * The following error indication policy is used: in case of success, all + * library functions return 0, in case of failure they either return UBI error + * codes, or -1 if a system error occured; in the latter case the exact error + * code has to be in the errno variable. + * + * @def UBI_ENOTFOUND + * @brief UBI was not found in the system. + * @def UBI_EBUG + * @brief An error due to bug in kernel part of UBI in UBI library. + * @def UBI_EINVAL + * @brief Invalid argument. + * @def UBI_EMACS + * @brief Highest error value. + */ +#define UBI_ENOTFOUND 1 +#define UBI_EBUG 2 +#define UBI_EINVAL 3 +#define UBI_EMAX 4 + + +/** + * UBI library descriptor, vague for library users. + */ +typedef struct ubi_lib *ubi_lib_t; + +/** + * struct ubi_info - general information about UBI. + * + * @version UBI version + * @nlen_max maximum length of names of volumes + * @dev_count count UBI devices in the system + */ +struct ubi_info +{ + unsigned int version; + unsigned int nlen_max; + unsigned int dev_count; +}; + +/** + * struct ubi_dev_info - information about an UBI device + * + * @wear average number of erasures of flash erasable blocks + * @major major number of the corresponding character device + * @minor minor number of the corresponding character device + * @eb_size size of eraseblocks + * @total_ebs total count of eraseblocks + * @avail_ebs count of unused eraseblock available for new volumes + * @vol_count total count of volumes in this UBI device + */ +struct ubi_dev_info +{ + unsigned long long wear; + unsigned int major; + unsigned int minor; + unsigned int eb_size; + unsigned int total_ebs; + unsigned int avail_ebs; + unsigned int vol_count; +}; + +/** + * struct ubi_vol_info - information about an UBI volume + * + * @bytes volume size in bytes + * @eraseblocks volume size in eraseblocks + * @major major number of the corresponding character device + * @minor minor number of the corresponding character device + * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) + * @dev_path device path to volume + * @name volume name + */ +struct ubi_vol_info +{ + unsigned long long bytes; + unsigned int eraseblocks; + unsigned int major; + unsigned int minor; + int type; + char *dev_path; + char *name; +}; + +/** + * ubi_mkvol - create a dynamic UBI volume. + * + * @desc UBI library descriptor + * @devn Number of UBI device to create new volume on + * @vol_id volume ID to assign to the new volume + * @vol_type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) + * @bytes volume size in bytes + * @alignment volume alignment + * @name volume name + * + * This function creates new UBI volume. If @vol_id is %UBI_VOLN_AUTO, then + * volume number is assigned automatically. This function returns positive + * volume number of the new volume in case of success or %-1 in case of + * failure. + */ +int ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, + long long bytes, int alignment, const char *name); + +/** + * ubi_rmvol - remove a volume. + * + * @desc UBI library descriptor + * @devn Number of UBI device to remove volume from + * @vol_id volume ID to remove + * + * This function returns zero in case of success or %-1 in case of failure. + */ +int ubi_rmvol(ubi_lib_t desc, int devn, int vol_id); + +/** + * ubi_get_info - get UBI information. + * + * @desc UBI library descriptor + * @ubi UBI information is returned here + * + * This function retrieves information about UBI and puts it to @ubi. Returns + * zero in case of success and %-1 in case of failure. + */ +int ubi_get_info(ubi_lib_t desc, struct ubi_info *ubi); + +/** + * ubi_vol_open - open a UBI volume + * + * @desc UBI library descriptor + * @devn Number of UBI device on which to open the volume + * @vol_id Number of UBI device on which to open the volume + * @flags Flags to pass to open() + * + * This function opens a UBI volume on a given UBI device. It returns + * the file descriptor of the opened volume device. In case of an + * error %-1 is returned and errno is set appropriately. + */ +int ubi_vol_open(ubi_lib_t desc, int devn, int vol_id, int flags); + +/** + * ubi_vol_close - close a UBI volume + * + * @vol_fd file descriptor of UBI volume to close + * + * This function closes the given UBI device. + */ +int ubi_vol_close(int vol_fd); + +/** + * ubi_vol_update - initiate volume update on a UBI volume + * @vol_fd File descriptor of UBI volume to update + * @bytes No. of bytes which shall be written. + * + * Initiates a volume update on a given volume. The caller must then + * actually write the appropriate number of bytes to the volume by + * calling write(). Returns 0 on success, else error. + */ +int ubi_vol_update(int vol_fd, unsigned long long bytes); + +/** + * ubi_vol_fopen_read - open a volume for reading, returning a FILE * + * @desc UBI library descriptor + * @devn UBI device number + * @vol_id volume ID to read + * + * Opens a volume for reading. Reading itself can then be performed + * with fread(). The stream can be closed with fclose(). Returns a + * stream on success, else NULL. + */ +FILE * +ubi_vol_fopen_read(ubi_lib_t desc, int devn, uint32_t vol_id); + +/** + * ubi_vol_fopen_update - open a volume for writing, returning a FILE * + * @desc UBI library descriptor + * @devn UBI device number + * @vol_id volume ID to update + * @bytes No. of bytes which shall be written. + * + * Initiates a volume update on a given volume. The caller must then + * actually write the appropriate number of bytes to the volume by + * calling fwrite(). The file can be closed with fclose(). Returns a + * stream on success, else NULL. + */ +FILE * +ubi_vol_fopen_update(ubi_lib_t desc, int devn, uint32_t vol_id, + unsigned long long bytes); + +/** + * ubi_vol_get_used_bytes - determine used bytes in a UBI volume + * @vol_fd File descriptor of UBI volume + * @bytes Pointer to result + * + * Returns 0 on success, else error. + */ +int ubi_vol_get_used_bytes(int vol_fd, unsigned long long *bytes); + +/** + * ubi_open - open UBI library. + * + * @desc A pointer to an UBI library descriptor + * + * Returns zero in case of success. + */ +int ubi_open(ubi_lib_t *desc); + +/** + * ubi_close - close UBI library. + * + * @desc A pointer to an UBI library descriptor + */ +int ubi_close(ubi_lib_t *desc); + + +/** + * ubi_perror - print UBI error. + * + * @prefix a prefix string to prepend to the error message + * @code error code + * + * If @code is %-1, this function calls 'perror()' + */ +void ubi_perror(const char *prefix, int code); + +/** + * ubi_set_cdev_pattern - set 'sprintf()'-like pattern of paths to UBI + * character devices. + * + * @desc UBI library descriptor + * @pattern the pattern to set + * + * The default UBI character device path is "/dev/ubi%u". + */ +int ubi_set_cdev_pattern(ubi_lib_t desc, const char *pattern); + +/** + * ubi_get_dev_info get information about an UBI device. + * + * @desc UBI library descriptor + * @devn UBI device number + * @di the requested information is returned here + */ +int ubi_get_dev_info(ubi_lib_t desc, unsigned int devn, + struct ubi_dev_info *di); + +/** + * ubi_set_vol_cdev_pattern - set 'sprintf()'-like pattµern ofpaths to UBI + * volume character devices. + * + * @desc UBI library descriptor + * @pattern the pattern to set + * + * The default UBI character device path is "/dev/ubi%u_%u". + */ +int ubi_set_vol_cdev_pattern(ubi_lib_t desc, const char *pattern); + +/** + * ubi_get_vol_info - get information about an UBI volume + * + * @desc UBI library descriptor + * @devn UBI device number the volume belongs to + * @vol_id the requested volume number + * @vi volume information is returned here + * + * Users must free the volume name string @vi->name. + */ +int ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, + struct ubi_vol_info *vi); + +#ifdef __cplusplus +} +#endif + +#endif /* !__UBI_H__ */ diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c deleted file mode 100644 index da4919b..0000000 --- a/ubi-utils/src/libubi.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * UBI (Unsorted Block Images) library. - * - * Author: Artem B. Bityutskiy - * Oliver Lohmann - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libubi.h" -#include "libubi_int.h" -#include "libubi_sysfs.h" - -/** - * struct ubi_lib - UBI library descriptor. - * - * @ubi general UBI information - * - * @sysfs_root sysfs root directory - * @ubi_root UBI root directory in sysfs - * - * @version full path to the "UBI version" sysfs file - * - * @cdev_path path pattern to UBI character devices - * @cdev_path_len maximum length of the @cdev_path string after substitution - * @udev_path path to sysfs directories corresponding to UBI devices - * @wear_path path to sysfs file containing UBI wear information - * @vol_count_path path to sysfs file containing the number of volumes in an - * UBI device - * @tot_ebs_path path to sysfs file containing the total number of - * eraseblock on an UBI device - * @avail_ebs_path path to sysfs file containing the number of unused - * eraseblocks on an UBI device, available for new volumes - * @eb_size_path path to sysfs file containing size of UBI eraseblocks - * @nums_path path to sysfs file containing major and minor number of an - * UBI device - * @vol_cdev_path path to UBI volume character devices - * @vdev_path path to sysfs directories corresponding to UBI volume - * devices - * @vol_nums_path path to sysfs file containing major and minor number of an - * UBI volume device - * @vol_bytes_path path to sysfs file containing size of an UBI volume device - * in bytes - * @vol_ebs_path path to sysfs file containing the number of eraseblocks in - * an UBI volume device - * @vol_type_path path to sysfs file containing type of an UBI volume - * @vol_name_path @FIXME: Describe me. - * - * This structure is created and initialized by 'ubi_init()' and is passed to - * all UBI library calls. - */ -struct ubi_lib -{ - struct ubi_info ubi; - - char *sysfs_root; - char *ubi_root; - - char *version; - char *cdev_path; - int cdev_path_len; - char *udev_path; - char *wear_path; - char *vol_count_path; - char *tot_ebs_path; - char *avail_ebs_path; - char *eb_size_path; - char *nums_path; - int vol_cdev_path_len; - char *vol_cdev_path; - char *vdev_path; - char *vol_nums_path; - char *vol_bytes_path; - char *vol_ebs_path; - char *vol_type_path; - char *vol_name_path; -}; - - -/** - * mkpath - compose full path from 2 given components. - * - * @path first component @name second component - * - * Returns the resulting path in case of success and %NULL in case of failure. - * Callers have to take care the resulting path is freed. - */ -static char* -mkpath(const char *path, const char *name) -{ - char *n; - int len1 = strlen(path); - int len2 = strlen(name); - - n = malloc(len1 + len2 + 2); - if (!n) - return NULL; - - memcpy(n, path, len1); - if (n[len1 - 1] != '/') - n[len1++] = '/'; - - memcpy(n + len1, name, len2 + 1); - return n; -} - - -static int -get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) -{ - int err; - int dev_count = 0; - char *path; - struct stat stat; - - err = sysfs_read_int(desc->version, (int*) &ubi->version); - if (err) - return -1; - - /* Calculate number of UBI devices */ - while (!err) { - char dir[20]; - - sprintf(&dir[0], "ubi%d", dev_count); - path = mkpath(desc->ubi_root, dir); - if (!path) - return ENOMEM; - - err = lstat(path, &stat); - if (err == 0) - dev_count += 1; - free(path); - } - - if (errno != ENOENT) - return -1; - - if (dev_count == 0) { - ubi_err("no UBI devices found"); - errno = EINVAL; - return -1; - } - - errno = 0; - ubi->dev_count = dev_count; - return 0; -} - -void -ubi_dump_handler(ubi_lib_t desc) -{ - ubi_lib_t d = desc; - printf( "UBI Library Descriptor:\n" - "ubi_root: %s\n" - "version: %s\n" - "cdev_path: %s\n" - "udev_path: %s\n" - "wear_path: %s\n" - "vol_count_path: %s\n" - "tot_ebs_path: %s\n" - "avail_ebs_path: %s\n" - "eb_size_path: %s\n" - "nums_path: %s\n" - "vol_cdev_path: %s\n" - "vdev_path: %s\n" - "vol_nums_path: %s\n" - "vol_bytes_path: %s\n" - "vol_ebs_path: %s\n" - "vol_type_path: %s\n" - "vol_name_path: %s\n" - "cdev_path_len: %d\n\n", - d->ubi_root, d->version, d->cdev_path, d->udev_path, - d->wear_path, d->vol_count_path, d->tot_ebs_path, - d->avail_ebs_path, d->eb_size_path, d->nums_path, - d->vol_cdev_path, d->vdev_path, d->vol_nums_path, - d->vol_bytes_path, d->vol_ebs_path, d->vol_type_path, - d->vol_name_path, d->cdev_path_len); -} - -int -ubi_set_cdev_pattern(ubi_lib_t desc, const char *pattern) -{ - char *patt; - - patt = strdup(pattern); - if (!patt) { - ubi_err("cannot allocate memory"); - return -1; - } - - if (desc->cdev_path) - free(desc->cdev_path); - - desc->cdev_path = patt; - desc->cdev_path_len = strlen(patt) + 1 + UBI_MAX_ID_SIZE; - - ubi_dbg("ubi dev pattern is now \"%s\"", patt); - - return 0; -} - -int -ubi_set_vol_cdev_pattern(ubi_lib_t desc, const char *pattern) -{ - char *patt; - - patt = strdup(pattern); - if (!patt) { - ubi_err("cannot allocate memory"); - return -1; - } - - free(desc->vol_cdev_path); - desc->vol_cdev_path = patt; - desc->vol_cdev_path_len = strlen(patt) + 1 + 2 * UBI_MAX_ID_SIZE; - - ubi_dbg("ubi volume dev pattern is now \"%s\"", patt); - - return 0; -} - -int -ubi_open(ubi_lib_t *desc) -{ - int err = -1; - ubi_lib_t res; - struct stat stat; - - res = calloc(1, sizeof(struct ubi_lib)); - if (!res) { - ubi_err("cannot allocate memory"); - return -1; - } - - res->cdev_path = NULL; - err = ubi_set_cdev_pattern(res, UBI_CDEV_PATH); - if (err) - goto error; - - /* TODO: this actually has to be discovered */ - res->sysfs_root = strdup(UBI_SYSFS_ROOT); - if (!res->sysfs_root) - goto error; - - res->ubi_root = mkpath(res->sysfs_root, UBI_ROOT); - if (!res->ubi_root) - goto error; - - res->version = mkpath(res->ubi_root, UBI_VER); - if (!res->version) - goto error; - - res->udev_path = mkpath(res->ubi_root, "ubi%d/"); - if (!res->udev_path) - goto error; - - res->wear_path = mkpath(res->udev_path, UBI_WEAR); - if (!res->wear_path) - goto error; - - res->vol_count_path = mkpath(res->udev_path, UBI_VOL_COUNT); - if (!res->vol_count_path) - goto error; - - res->tot_ebs_path = mkpath(res->udev_path, UBI_AVAIL_EBS); - if (!res->tot_ebs_path) - goto error; - - res->avail_ebs_path = mkpath(res->udev_path, UBI_TOT_EBS); - if (!res->avail_ebs_path) - goto error; - - res->eb_size_path = mkpath(res->udev_path, UBI_EB_SIZE); - if (!res->eb_size_path) - goto error; - - res->nums_path = mkpath(res->udev_path, UBI_NUMS); - if (!res->nums_path) - goto error; - - err = ubi_set_vol_cdev_pattern(res, UBI_VOL_CDEV_PATH); - if (err) - goto error; - - res->vdev_path = mkpath(res->ubi_root, "ubi%d_%d/"); - if (!res->vdev_path) - goto error; - - res->vol_nums_path = mkpath(res->vdev_path, UBI_NUMS); - if (!res->vol_nums_path) - goto error; - - res->vol_bytes_path = mkpath(res->vdev_path, UBI_VBYTES); - if (!res->vol_bytes_path) - goto error; - - res->vol_ebs_path = mkpath(res->vdev_path, UBI_VEBS); - if (!res->vol_ebs_path) - goto error; - - res->vol_type_path = mkpath(res->vdev_path, UBI_VTYPE); - if (!res->vol_type_path) - goto error; - - res->vol_name_path = mkpath(res->vdev_path, UBI_VNAME); - if (!res->vol_name_path) - goto error; - - /* Check if UBI exists in the system */ - err = lstat(res->ubi_root, &stat); - if (err) { - perror("lstat"); - fprintf(stderr, "%s\n", res->ubi_root); - err = UBI_ENOTFOUND; - goto error; - } - - err = get_ubi_info(res, &res->ubi); - if (err) - goto error; - - *desc = res; - - ubi_dbg("opened library successfully."); - - return 0; - -error: - ubi_close(&res); - - if (err == -1 && errno == ENOMEM) - ubi_err("Cannot allocate memory"); - - return err; -} - -int -ubi_close(ubi_lib_t *desc) -{ - ubi_lib_t tmp = *desc; - - free(tmp->vol_name_path); - free(tmp->vol_type_path); - free(tmp->vol_ebs_path); - free(tmp->vol_bytes_path); - free(tmp->vol_nums_path); - free(tmp->vdev_path); - free(tmp->vol_cdev_path); - free(tmp->nums_path); - free(tmp->eb_size_path); - free(tmp->avail_ebs_path); - free(tmp->tot_ebs_path); - free(tmp->vol_count_path); - free(tmp->wear_path); - free(tmp->udev_path); - free(tmp->cdev_path); - free(tmp->version); - free(tmp->ubi_root); - free(tmp->sysfs_root); - free(tmp); - - *desc = NULL; - - return 0; -} - -void -ubi_perror(const char *prefix, int code) -{ - if (code == 0) - return; - - fprintf(stderr, "%s: ", prefix); - - switch (code) { - case UBI_ENOTFOUND: - fprintf(stderr, "UBI was not found in system\n"); - break; - case UBI_EBUG: - fprintf(stderr, "an UBI or UBI library bug\n"); - break; - case UBI_EINVAL: - fprintf(stderr, "invalid parameter\n"); - break; - case -1: - perror(prefix); - break; - default: - ubi_err("unknown error code %d", code); - break; - } -} - -int -ubi_get_dev_info(ubi_lib_t desc, unsigned int devn, struct ubi_dev_info *di) -{ - int err; - - if (devn >= desc->ubi.dev_count) { - ubi_err("bad device number, max is %d\n", - desc->ubi.dev_count - 1); - return UBI_EINVAL; - } - - err = sysfs_read_dev_subst(desc->nums_path, &di->major, - &di->minor, 1, devn); - if (err) - return -1; - - err = sysfs_read_ull_subst(desc->wear_path, &di->wear, 1, devn); - if (err) - return -1; - - err = sysfs_read_uint_subst(desc->vol_count_path, - &di->vol_count, 1, devn); - if (err) - return -1; - - err = sysfs_read_uint_subst(desc->eb_size_path, &di->eb_size, 1, devn); - if (err) - return -1; - - err = sysfs_read_uint_subst(desc->tot_ebs_path, &di->total_ebs, 1, devn); - if (err) - return -1; - - err = sysfs_read_uint_subst(desc->avail_ebs_path, - &di->avail_ebs, 1, devn); - if (err) - return -1; - -#if 0 - ubi_dbg("major:minor %d:%d, wear %llu, EB size %d, " - "vol. count %d, tot. EBs %d, avail. EBs %d", - di->major, di->minor, di->wear, di->eb_size, - di->vol_count, di->total_ebs, di->avail_ebs); -#endif - - return err; -} - -int -ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, - struct ubi_vol_info *req) -{ - int err; - int len; - char buf1[10]; - char buf2[UBI_MAX_VOLUME_NAME]; - - err = sysfs_read_dev_subst(desc->vol_nums_path, &req->major, - &req->minor, 2, devn, vol_id); - if (err) - return -1; - - err = sysfs_read_ull_subst(desc->vol_bytes_path, - &req->bytes, 2, devn, vol_id); - if (err) - return -1; - - err = sysfs_read_uint_subst(desc->vol_ebs_path, - &req->eraseblocks, 2, devn, vol_id); - if (err) - return -1; - - len = sysfs_read_data_subst(desc->vol_type_path, &buf1[0], - 10, 2, devn, vol_id); - if (len == -1) - return -1; - - if (buf1[len - 1] != '\n') { - ubi_err("bad volume type"); - return UBI_EBUG; - } - - if (!strncmp(&buf1[0], "static", sizeof("static") - 1)) { - req->type = UBI_STATIC_VOLUME; - } else if (!strncmp(&buf1[0], "dynamic", sizeof("dynamic") - 1)) { - req->type = UBI_DYNAMIC_VOLUME; - } else { - ubi_err("bad type %s", &buf1[0]); - return -1; - } - - len = sysfs_read_data_subst(desc->vol_name_path, &buf2[0], - UBI_MAX_VOLUME_NAME, 2, devn, vol_id); - if (len == -1) - return -1; - - if (buf2[len - 1] != '\n') { - ubi_err("bad volume name"); - return UBI_EBUG; - } - - req->name = malloc(len); - if (!req->name) { - ubi_err("cannot allocate memory"); - return -1; - } - - memcpy(req->name, &buf2[0], len - 1); - req->name[len - 1] = '\0'; - - return 0; -} - -/** - * ubi_cdev_open - open a UBI device - * - * @desc UBI library descriptor - * @devn Number of UBI device to open - * @flags Flags to pass to open() - * - * This function opens a UBI device by number and returns a file - * descriptor. In case of an error %-1 is returned and errno is set - * appropriately. - */ -static int -ubi_cdev_open(ubi_lib_t desc, int devn, int flags) -{ - char *buf; - int fd; - - ubi_dbg("desc=%p, devn=%d, flags=%08x\n", desc, devn, flags); - - if (desc == NULL) { - ubi_err("desc is NULL\n"); - return -1; - } - if (desc->vol_cdev_path_len == 0) { - ubi_err("path_len == 0\n"); - return -1; - } - buf = malloc(desc->cdev_path_len); - - sprintf(buf, desc->cdev_path, devn); - - fd = open(buf, flags); - if (fd == -1) - ubi_dbg("cannot open %s", buf); - - free(buf); - return fd; -} - -/** - * ubi_cdev_close - close a UBI device - * - * @dev_fd file descriptor of UBI device to close - * - * This function closes the given UBI device. - */ -static int -ubi_cdev_close(int dev_fd) -{ - return close(dev_fd); -} - -/** - * @size is now in bytes. - */ -int -ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, - long long bytes, int alignment, const char *name) -{ - int fd; - int err; - struct ubi_mkvol_req req; - size_t n; - - n = strlen(name); - if (n > UBI_MAX_VOLUME_NAME) - return -1; - - if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) - return -1; - - req.vol_id = vol_id; - req.bytes = bytes; - req.vol_type = vol_type; - req.alignment = alignment; - - strncpy(req.name, name, UBI_MAX_VOLUME_NAME + 1); - req.name_len = n; - - /* printf("DBG: %s(vol_id=%d, bytes=%lld, type=%d, alig=%d, nlen=%d, " - "name=%s)\n", __func__, vol_id, bytes, vol_type, alignment, - strlen(name), name);*/ - - err = ioctl(fd, UBI_IOCMKVOL, &req); - if (err < 0) { - ubi_err("ioctl returned %d errno=%d\n", err, errno); - goto out_close; - } - - ubi_dbg("created volume %d, size %lld, name \"%s\" " - "at UBI dev %d\n", vol_id, bytes, name, devn); - - close(fd); - return err; - out_close: - ubi_cdev_close(fd); - return err; -} - -int -ubi_rmvol(ubi_lib_t desc, int devn, int vol_id) -{ - int fd; - int err; - - if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) - return -1; - - err = ioctl(fd, UBI_IOCRMVOL, &vol_id); - if (err < 0) - goto out_close; - - ubi_dbg("removed volume %d", vol_id); - - out_close: - ubi_cdev_close(fd); - return err; -} - -int -ubi_get_info(ubi_lib_t desc, struct ubi_info *ubi) -{ - memcpy(ubi, &desc->ubi, sizeof(struct ubi_info)); - return 0; -} - - -int -ubi_vol_open(ubi_lib_t desc, int devn, int vol_id, int flags) -{ - char *buf; - int fd; - - ubi_dbg("desc=%p, devn=%d, vol_id=%d, flags=%08x\n", - desc, devn, vol_id, flags); - - if (desc == NULL) { - ubi_err("desc is NULL\n"); - return -1; - } - if (desc->vol_cdev_path_len == 0) { - ubi_err("path_len == 0\n"); - return -1; - } - buf = malloc(desc->cdev_path_len); - - sprintf(buf, desc->vol_cdev_path, devn, vol_id); - - fd = open(buf, flags); - if (fd == -1) - ubi_dbg("cannot open %s", buf); - - free(buf); - return fd; -} - -int -ubi_vol_close(int vol_fd) -{ - return close(vol_fd); -} - - -int -ubi_vol_update(int vol_fd, unsigned long long bytes) -{ - int err; - - err = ioctl(vol_fd, UBI_IOCVOLUP, &bytes); - if (err) { - ubi_err("%s failure calling update ioctl\n" - " IOCTL(%08lx) err=%d errno=%d\n", - __func__, (long unsigned int)UBI_IOCVOLUP, err, errno); - } - return err; -} - -FILE * -ubi_vol_fopen_read(ubi_lib_t desc, int devn, uint32_t vol_id) -{ - FILE *fp; - int fd; - - fd = ubi_vol_open(desc, devn, vol_id, O_RDONLY); - if (fd == -1) - return NULL; - - fp = fdopen(fd, "r"); - if (fp == NULL) - ubi_vol_close(fd); - - return fp; -} - -FILE * -ubi_vol_fopen_update(ubi_lib_t desc, int devn, uint32_t vol_id, - unsigned long long bytes) -{ - FILE *fp; - int fd; - int err; - - fd = ubi_vol_open(desc, devn, vol_id, O_RDWR); - if (fd == -1) - return NULL; - - fp = fdopen(fd, "r+"); - if (fp == NULL) { - printf("DBG: %s(errno=%d)\n", __func__, errno); - ubi_vol_close(fd); - return NULL; - } - err = ubi_vol_update(fd, bytes); - if (err < 0) { - printf("DBG: %s() fd=%d err=%d\n", __func__, fd, err); - fclose(fp); - return NULL; - } - return fp; -} - -int -ubi_vol_get_used_bytes(int vol_fd, unsigned long long *bytes) -{ - off_t res; - - res = lseek(vol_fd, 0, SEEK_END); - if (res == (off_t)-1) - return -1; - *bytes = (unsigned long long) res; - res = lseek(vol_fd, 0, SEEK_SET); - return res == (off_t)-1 ? -1 : 0; -} diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h deleted file mode 100644 index 830a682..0000000 --- a/ubi-utils/src/libubi_int.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * UBI (Unsorted Block Images) library. - * - * Author: Artem B. Bityutskiy - */ - -#ifndef __UBI_INT_H__ -#define __UBI_INT_H__ -/* - * Enable/disable UBI library debugging messages. - */ -#undef UBILIB_DEBUG - -/* - * UBI library error message. - */ -#define ubi_err(fmt, ...) do { \ - fprintf(stderr, "UBI Library Error at %s: ", __func__); \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } while (0) - -#ifdef UBILIB_DEBUG -#define ubi_dbg(fmt, ...) do { \ - fprintf(stderr, "UBI Debug: %s: ", __func__); \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } while (0) - -#else -#define ubi_dbg(fmt, ...) do { } while (0) -#endif - -/** - * SYSFS Entries. - * - * @def UBI_ROOT - * @brief Name of the root UBI directory in sysfs. - * - * @def UBI_NLEN_MAX - * @brief Name of syfs file containing the maximum UBI volume name length. - * - * @def UBI_VER - * @brief Name of sysfs file containing UBI version. - * - * @def UBI_WEAR - * @brief Name of sysfs file containing wear level of an UBI device. - * - * @def UBI_VOL_COUNT - * @brief Name of sysfs file contaning the of volume on an UBI device - * - * @def UBI_TOT_EBS - * @brief Name of sysfs file contaning the total number of - * eraseblocks on an UBI device. - * - * @def UBI_AVAIL_EBS - * @brief Name of sysfs file contaning the number of unused eraseblocks on - * an UBI device. - * - * @def UBI_EB_SIZE - * @brief Name of sysfs file containing size of UBI eraseblocks. - * - * @def UBI_NUMS - * @brief Name of sysfs file containing major and minor numbers - * of an UBI device or an UBI volume device. - * - * @def UBI_VBYTES - * @brief Name of sysfs file containing size of an UBI volume device in - * bytes. - * - * @def UBI_VEBS - * @brief Name of sysfs file containing size of an UBI volume device in - * eraseblocks. - * - * @def UBI_VTYPE - * @brief Name of sysfs file containing type of an UBI volume device. - * - * @def UBI_VNAME - * @brief Name of sysfs file containing name of an UBI volume device. - **/ -#define UBI_ROOT "ubi" -#define UBI_NLEN_MAX "volume_name_max" -#define UBI_VER "version" -#define UBI_WEAR "wear" -#define UBI_VOL_COUNT "volumes_count" -#define UBI_TOT_EBS "total_eraseblocks" -#define UBI_AVAIL_EBS "avail_eraseblocks" -#define UBI_EB_SIZE "eraseblock_size" -#define UBI_NUMS "dev" -#define UBI_VBYTES "bytes" -#define UBI_VEBS "eraseblocks" -#define UBI_VTYPE "type" -#define UBI_VNAME "name" - -#define UBI_CDEV_PATH "/dev/ubi%d" -#define UBI_VOL_CDEV_PATH "/dev/ubi%d_%d" -#define UBI_SYSFS_ROOT "/sys/class" - -#define UBI_MAX_ID_SIZE 9 - -#endif /* !__UBI_INT_H__ */ diff --git a/ubi-utils/src/libubi_sysfs.c b/ubi-utils/src/libubi_sysfs.c deleted file mode 100644 index 95fd3de..0000000 --- a/ubi-utils/src/libubi_sysfs.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * UBI (Unsorted Block Images) library. - * - * Author: Artem B. Bityutskiy - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "libubi_int.h" - -int -sysfs_read_data(const char *file, void *buf, int len) -{ - int fd; - ssize_t rd; - - fd = open(file, O_RDONLY); - if (fd == -1) { - ubi_err("cannot open file %s", file); - return -1; - } - - rd = read(fd, buf, len); - if (rd == -1) - ubi_err("cannot read file %s", file); - - close(fd); - - return rd; -} - -int -sysfs_read_data_subst(const char *patt, void *buf, int len, int n, ...) -{ - va_list args; - char buf1[strlen(patt) + 20 * n]; - - va_start(args, n); - vsprintf(&buf1[0], patt, args); - va_end(args); - - return sysfs_read_data(&buf1[0], buf, len); -} - -int -sysfs_read_dev(const char *file, unsigned int *major, unsigned int *minor) -{ - int fd; - int ret; - ssize_t rd; - int err = -1; - char buf[40]; - - fd = open(file, O_RDONLY); - if (fd == -1) { - ubi_err("cannot open file %s", file); - return -1; - } - - rd = read(fd, &buf[0], 20); - if (rd == -1) { - ubi_err("cannot read file %s", file); - goto error; - } - if (rd < 4) { - ubi_err("bad contents of file %s:", file); - goto error; - } - - err = -1; - if (buf[rd -1] != '\n') { - ubi_err("bad contents of file %s", file); - goto error; - } - - ret = sscanf(&buf[0], "%d:%d\n", major, minor); - if (ret != 2) { - ubi_err("bad contents of file %s", file); - goto error; - } - - err = 0; - -error: - close(fd); - - return err; -} - -int -sysfs_read_dev_subst(const char *patt, unsigned int *major, - unsigned int *minor, int n, ...) -{ - va_list args; - char buf[strlen(patt) + 20 * n]; - - va_start(args, n); - vsprintf(&buf[0], patt, args); - va_end(args); - - return sysfs_read_dev(&buf[0], major, minor); -} - -static int -sysfs_read_ull(const char *file __unused, unsigned long long *num __unused) -{ - return 0; -} - -int -sysfs_read_ull_subst(const char *patt, unsigned long long *num, int n, ...) -{ - va_list args; - char buf[strlen(patt) + 20 * n]; - - va_start(args, n); - vsprintf(&buf[0], patt, args); - va_end(args); - - return sysfs_read_ull(&buf[0], num); -} - -static int -sysfs_read_uint(const char *file __unused, unsigned int *num __unused) -{ - return 0; -} - -int -sysfs_read_uint_subst(const char *patt, unsigned int *num, int n, ...) -{ - va_list args; - char buf[strlen(patt) + 20 * n]; - - va_start(args, n); - vsprintf(&buf[0], patt, args); - va_end(args); - - return sysfs_read_uint(&buf[0], num); -} - -int -sysfs_read_ll(const char *file, long long *num) -{ - int fd; - ssize_t rd; - int err = -1; - char buf[20]; - char *endptr; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 20); - if (rd == -1) - goto out; - - if (rd < 2) { - ubi_err("bad contents in file %s: \"%c%c...\"", - file, buf[0], buf[1]); - goto out_errno; - } - - *num = strtoll(&buf[0], &endptr, 10); - if (endptr == &buf[0] || *endptr != '\n') { - ubi_err("bad contents in file %s: \"%c%c...\"", - file, buf[0], buf[1]); - goto out_errno; - } - - if (*num < 0) { - ubi_err("bad number in file %s: %lld", file, *num); - goto out_errno; - } - - err = 0; - -out_errno: - errno = EINVAL; - -out: - close(fd); - return err; -} - -int -sysfs_read_int(const char *file, int *num) -{ - int err; - long long res = 0; - - err = sysfs_read_ll(file, &res); - if (err) - return err; - - if (res < 0 || res > INT_MAX) { - ubi_err("bad number in file %s: %lld", file, res); - errno = EINVAL; - return -1; - } - - *num = res; - return 0; -} diff --git a/ubi-utils/src/libubi_sysfs.h b/ubi-utils/src/libubi_sysfs.h deleted file mode 100644 index 2fb6072..0000000 --- a/ubi-utils/src/libubi_sysfs.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * UBI (Unsorted Block Images) library. - * - * Author: Artem B. Bityutskiy - */ - -/** - * sysfs_read_data - read data from a sysfs file. - * - * @file path to the file to read from - * @buf furrer where to store read data - * @len length of provided buffer @buf - * - * This function returns the number of read bytes or -1 in case of error. - */ -int sysfs_read_data(const char *file, void *buf, int len); - -/** - * sysfs_read_data_subst - form path to a sysfs file and read data from it. - * - * @patt path to the file to read from - * @buf furrer where to store read data - * @len length of provided buffer @buf - * @n number of parameters to substitute to @patt - * - * This function forms path to a sysfs file by means of substituting parameters - * to @patt and then reads @len bytes from this file and stores the read data - * to @buf. This function returns the number of read bytes or -1 in case of - * error. - */ -int sysfs_read_data_subst(const char *patt, void *buf, int len, int n, ...); - -/** - * sysfs_read_dev - read major and minor number from a sysfs file. - * - * @file path to the file to read from - * @major major number is returned here - * @minor minor number is returned here - */ -int sysfs_read_dev(const char *file, unsigned int *major, - unsigned int *minor); -/** - * sysfs_read_dev_subst - for path to a file and read major and minor number - * from it. - * - * @patt pattern of the path to the file to read from - * @major major number is returned here - * @minor minor number is returned here - * @n number of arguments to substitute - * - * This function substitures arguments to the @patt file path pattern and reads - * major and minor numbers from the resulting file. - */ -int sysfs_read_dev_subst(const char *patt, unsigned int *major, - unsigned int *minor, int n, ...); - -/** - * sysfs_read_ull_subst - form path to a sysfs file and read an unsigned long - * long value from there. - * - * @patt pattern of file path - * @num the read value is returned here - * @n number of parameters to substitute - * - * - * This function first forms the path to a sysfs file by means of substituting - * passed parameters to the @patt string, and then read an 'unsigned long long' - * value from this file. - */ -int sysfs_read_ull_subst(const char *patt, unsigned long long *num, - int n, ...); - -/** - * sysfs_read_uint_subst - the same as 'sysfs_read_uint_subst()' but reads an - * unsigned int value. - */ -int sysfs_read_uint_subst(const char *patt, unsigned int *num, - int n, ...); - -/** - * sysfs_read_ll - read a long long integer from an UBI sysfs file. - * - * @file file name from where to read - * @num the result is returned here - */ -int sysfs_read_ll(const char *file, long long *num); - -/** - * sysfs_read_int - the same as 'sysfs_read_ll()' but reads an 'int' value. - */ -int sysfs_read_int(const char *file, int *num); diff --git a/ubi-utils/src/libubiold.c b/ubi-utils/src/libubiold.c new file mode 100644 index 0000000..da4919b --- /dev/null +++ b/ubi-utils/src/libubiold.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * + * Author: Artem B. Bityutskiy + * Oliver Lohmann + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libubi.h" +#include "libubi_int.h" +#include "libubi_sysfs.h" + +/** + * struct ubi_lib - UBI library descriptor. + * + * @ubi general UBI information + * + * @sysfs_root sysfs root directory + * @ubi_root UBI root directory in sysfs + * + * @version full path to the "UBI version" sysfs file + * + * @cdev_path path pattern to UBI character devices + * @cdev_path_len maximum length of the @cdev_path string after substitution + * @udev_path path to sysfs directories corresponding to UBI devices + * @wear_path path to sysfs file containing UBI wear information + * @vol_count_path path to sysfs file containing the number of volumes in an + * UBI device + * @tot_ebs_path path to sysfs file containing the total number of + * eraseblock on an UBI device + * @avail_ebs_path path to sysfs file containing the number of unused + * eraseblocks on an UBI device, available for new volumes + * @eb_size_path path to sysfs file containing size of UBI eraseblocks + * @nums_path path to sysfs file containing major and minor number of an + * UBI device + * @vol_cdev_path path to UBI volume character devices + * @vdev_path path to sysfs directories corresponding to UBI volume + * devices + * @vol_nums_path path to sysfs file containing major and minor number of an + * UBI volume device + * @vol_bytes_path path to sysfs file containing size of an UBI volume device + * in bytes + * @vol_ebs_path path to sysfs file containing the number of eraseblocks in + * an UBI volume device + * @vol_type_path path to sysfs file containing type of an UBI volume + * @vol_name_path @FIXME: Describe me. + * + * This structure is created and initialized by 'ubi_init()' and is passed to + * all UBI library calls. + */ +struct ubi_lib +{ + struct ubi_info ubi; + + char *sysfs_root; + char *ubi_root; + + char *version; + char *cdev_path; + int cdev_path_len; + char *udev_path; + char *wear_path; + char *vol_count_path; + char *tot_ebs_path; + char *avail_ebs_path; + char *eb_size_path; + char *nums_path; + int vol_cdev_path_len; + char *vol_cdev_path; + char *vdev_path; + char *vol_nums_path; + char *vol_bytes_path; + char *vol_ebs_path; + char *vol_type_path; + char *vol_name_path; +}; + + +/** + * mkpath - compose full path from 2 given components. + * + * @path first component @name second component + * + * Returns the resulting path in case of success and %NULL in case of failure. + * Callers have to take care the resulting path is freed. + */ +static char* +mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) + return NULL; + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + + +static int +get_ubi_info(ubi_lib_t desc, struct ubi_info *ubi) +{ + int err; + int dev_count = 0; + char *path; + struct stat stat; + + err = sysfs_read_int(desc->version, (int*) &ubi->version); + if (err) + return -1; + + /* Calculate number of UBI devices */ + while (!err) { + char dir[20]; + + sprintf(&dir[0], "ubi%d", dev_count); + path = mkpath(desc->ubi_root, dir); + if (!path) + return ENOMEM; + + err = lstat(path, &stat); + if (err == 0) + dev_count += 1; + free(path); + } + + if (errno != ENOENT) + return -1; + + if (dev_count == 0) { + ubi_err("no UBI devices found"); + errno = EINVAL; + return -1; + } + + errno = 0; + ubi->dev_count = dev_count; + return 0; +} + +void +ubi_dump_handler(ubi_lib_t desc) +{ + ubi_lib_t d = desc; + printf( "UBI Library Descriptor:\n" + "ubi_root: %s\n" + "version: %s\n" + "cdev_path: %s\n" + "udev_path: %s\n" + "wear_path: %s\n" + "vol_count_path: %s\n" + "tot_ebs_path: %s\n" + "avail_ebs_path: %s\n" + "eb_size_path: %s\n" + "nums_path: %s\n" + "vol_cdev_path: %s\n" + "vdev_path: %s\n" + "vol_nums_path: %s\n" + "vol_bytes_path: %s\n" + "vol_ebs_path: %s\n" + "vol_type_path: %s\n" + "vol_name_path: %s\n" + "cdev_path_len: %d\n\n", + d->ubi_root, d->version, d->cdev_path, d->udev_path, + d->wear_path, d->vol_count_path, d->tot_ebs_path, + d->avail_ebs_path, d->eb_size_path, d->nums_path, + d->vol_cdev_path, d->vdev_path, d->vol_nums_path, + d->vol_bytes_path, d->vol_ebs_path, d->vol_type_path, + d->vol_name_path, d->cdev_path_len); +} + +int +ubi_set_cdev_pattern(ubi_lib_t desc, const char *pattern) +{ + char *patt; + + patt = strdup(pattern); + if (!patt) { + ubi_err("cannot allocate memory"); + return -1; + } + + if (desc->cdev_path) + free(desc->cdev_path); + + desc->cdev_path = patt; + desc->cdev_path_len = strlen(patt) + 1 + UBI_MAX_ID_SIZE; + + ubi_dbg("ubi dev pattern is now \"%s\"", patt); + + return 0; +} + +int +ubi_set_vol_cdev_pattern(ubi_lib_t desc, const char *pattern) +{ + char *patt; + + patt = strdup(pattern); + if (!patt) { + ubi_err("cannot allocate memory"); + return -1; + } + + free(desc->vol_cdev_path); + desc->vol_cdev_path = patt; + desc->vol_cdev_path_len = strlen(patt) + 1 + 2 * UBI_MAX_ID_SIZE; + + ubi_dbg("ubi volume dev pattern is now \"%s\"", patt); + + return 0; +} + +int +ubi_open(ubi_lib_t *desc) +{ + int err = -1; + ubi_lib_t res; + struct stat stat; + + res = calloc(1, sizeof(struct ubi_lib)); + if (!res) { + ubi_err("cannot allocate memory"); + return -1; + } + + res->cdev_path = NULL; + err = ubi_set_cdev_pattern(res, UBI_CDEV_PATH); + if (err) + goto error; + + /* TODO: this actually has to be discovered */ + res->sysfs_root = strdup(UBI_SYSFS_ROOT); + if (!res->sysfs_root) + goto error; + + res->ubi_root = mkpath(res->sysfs_root, UBI_ROOT); + if (!res->ubi_root) + goto error; + + res->version = mkpath(res->ubi_root, UBI_VER); + if (!res->version) + goto error; + + res->udev_path = mkpath(res->ubi_root, "ubi%d/"); + if (!res->udev_path) + goto error; + + res->wear_path = mkpath(res->udev_path, UBI_WEAR); + if (!res->wear_path) + goto error; + + res->vol_count_path = mkpath(res->udev_path, UBI_VOL_COUNT); + if (!res->vol_count_path) + goto error; + + res->tot_ebs_path = mkpath(res->udev_path, UBI_AVAIL_EBS); + if (!res->tot_ebs_path) + goto error; + + res->avail_ebs_path = mkpath(res->udev_path, UBI_TOT_EBS); + if (!res->avail_ebs_path) + goto error; + + res->eb_size_path = mkpath(res->udev_path, UBI_EB_SIZE); + if (!res->eb_size_path) + goto error; + + res->nums_path = mkpath(res->udev_path, UBI_NUMS); + if (!res->nums_path) + goto error; + + err = ubi_set_vol_cdev_pattern(res, UBI_VOL_CDEV_PATH); + if (err) + goto error; + + res->vdev_path = mkpath(res->ubi_root, "ubi%d_%d/"); + if (!res->vdev_path) + goto error; + + res->vol_nums_path = mkpath(res->vdev_path, UBI_NUMS); + if (!res->vol_nums_path) + goto error; + + res->vol_bytes_path = mkpath(res->vdev_path, UBI_VBYTES); + if (!res->vol_bytes_path) + goto error; + + res->vol_ebs_path = mkpath(res->vdev_path, UBI_VEBS); + if (!res->vol_ebs_path) + goto error; + + res->vol_type_path = mkpath(res->vdev_path, UBI_VTYPE); + if (!res->vol_type_path) + goto error; + + res->vol_name_path = mkpath(res->vdev_path, UBI_VNAME); + if (!res->vol_name_path) + goto error; + + /* Check if UBI exists in the system */ + err = lstat(res->ubi_root, &stat); + if (err) { + perror("lstat"); + fprintf(stderr, "%s\n", res->ubi_root); + err = UBI_ENOTFOUND; + goto error; + } + + err = get_ubi_info(res, &res->ubi); + if (err) + goto error; + + *desc = res; + + ubi_dbg("opened library successfully."); + + return 0; + +error: + ubi_close(&res); + + if (err == -1 && errno == ENOMEM) + ubi_err("Cannot allocate memory"); + + return err; +} + +int +ubi_close(ubi_lib_t *desc) +{ + ubi_lib_t tmp = *desc; + + free(tmp->vol_name_path); + free(tmp->vol_type_path); + free(tmp->vol_ebs_path); + free(tmp->vol_bytes_path); + free(tmp->vol_nums_path); + free(tmp->vdev_path); + free(tmp->vol_cdev_path); + free(tmp->nums_path); + free(tmp->eb_size_path); + free(tmp->avail_ebs_path); + free(tmp->tot_ebs_path); + free(tmp->vol_count_path); + free(tmp->wear_path); + free(tmp->udev_path); + free(tmp->cdev_path); + free(tmp->version); + free(tmp->ubi_root); + free(tmp->sysfs_root); + free(tmp); + + *desc = NULL; + + return 0; +} + +void +ubi_perror(const char *prefix, int code) +{ + if (code == 0) + return; + + fprintf(stderr, "%s: ", prefix); + + switch (code) { + case UBI_ENOTFOUND: + fprintf(stderr, "UBI was not found in system\n"); + break; + case UBI_EBUG: + fprintf(stderr, "an UBI or UBI library bug\n"); + break; + case UBI_EINVAL: + fprintf(stderr, "invalid parameter\n"); + break; + case -1: + perror(prefix); + break; + default: + ubi_err("unknown error code %d", code); + break; + } +} + +int +ubi_get_dev_info(ubi_lib_t desc, unsigned int devn, struct ubi_dev_info *di) +{ + int err; + + if (devn >= desc->ubi.dev_count) { + ubi_err("bad device number, max is %d\n", + desc->ubi.dev_count - 1); + return UBI_EINVAL; + } + + err = sysfs_read_dev_subst(desc->nums_path, &di->major, + &di->minor, 1, devn); + if (err) + return -1; + + err = sysfs_read_ull_subst(desc->wear_path, &di->wear, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->vol_count_path, + &di->vol_count, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->eb_size_path, &di->eb_size, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->tot_ebs_path, &di->total_ebs, 1, devn); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->avail_ebs_path, + &di->avail_ebs, 1, devn); + if (err) + return -1; + +#if 0 + ubi_dbg("major:minor %d:%d, wear %llu, EB size %d, " + "vol. count %d, tot. EBs %d, avail. EBs %d", + di->major, di->minor, di->wear, di->eb_size, + di->vol_count, di->total_ebs, di->avail_ebs); +#endif + + return err; +} + +int +ubi_get_vol_info(ubi_lib_t desc, unsigned int devn, unsigned int vol_id, + struct ubi_vol_info *req) +{ + int err; + int len; + char buf1[10]; + char buf2[UBI_MAX_VOLUME_NAME]; + + err = sysfs_read_dev_subst(desc->vol_nums_path, &req->major, + &req->minor, 2, devn, vol_id); + if (err) + return -1; + + err = sysfs_read_ull_subst(desc->vol_bytes_path, + &req->bytes, 2, devn, vol_id); + if (err) + return -1; + + err = sysfs_read_uint_subst(desc->vol_ebs_path, + &req->eraseblocks, 2, devn, vol_id); + if (err) + return -1; + + len = sysfs_read_data_subst(desc->vol_type_path, &buf1[0], + 10, 2, devn, vol_id); + if (len == -1) + return -1; + + if (buf1[len - 1] != '\n') { + ubi_err("bad volume type"); + return UBI_EBUG; + } + + if (!strncmp(&buf1[0], "static", sizeof("static") - 1)) { + req->type = UBI_STATIC_VOLUME; + } else if (!strncmp(&buf1[0], "dynamic", sizeof("dynamic") - 1)) { + req->type = UBI_DYNAMIC_VOLUME; + } else { + ubi_err("bad type %s", &buf1[0]); + return -1; + } + + len = sysfs_read_data_subst(desc->vol_name_path, &buf2[0], + UBI_MAX_VOLUME_NAME, 2, devn, vol_id); + if (len == -1) + return -1; + + if (buf2[len - 1] != '\n') { + ubi_err("bad volume name"); + return UBI_EBUG; + } + + req->name = malloc(len); + if (!req->name) { + ubi_err("cannot allocate memory"); + return -1; + } + + memcpy(req->name, &buf2[0], len - 1); + req->name[len - 1] = '\0'; + + return 0; +} + +/** + * ubi_cdev_open - open a UBI device + * + * @desc UBI library descriptor + * @devn Number of UBI device to open + * @flags Flags to pass to open() + * + * This function opens a UBI device by number and returns a file + * descriptor. In case of an error %-1 is returned and errno is set + * appropriately. + */ +static int +ubi_cdev_open(ubi_lib_t desc, int devn, int flags) +{ + char *buf; + int fd; + + ubi_dbg("desc=%p, devn=%d, flags=%08x\n", desc, devn, flags); + + if (desc == NULL) { + ubi_err("desc is NULL\n"); + return -1; + } + if (desc->vol_cdev_path_len == 0) { + ubi_err("path_len == 0\n"); + return -1; + } + buf = malloc(desc->cdev_path_len); + + sprintf(buf, desc->cdev_path, devn); + + fd = open(buf, flags); + if (fd == -1) + ubi_dbg("cannot open %s", buf); + + free(buf); + return fd; +} + +/** + * ubi_cdev_close - close a UBI device + * + * @dev_fd file descriptor of UBI device to close + * + * This function closes the given UBI device. + */ +static int +ubi_cdev_close(int dev_fd) +{ + return close(dev_fd); +} + +/** + * @size is now in bytes. + */ +int +ubi_mkvol(ubi_lib_t desc, int devn, int vol_id, int vol_type, + long long bytes, int alignment, const char *name) +{ + int fd; + int err; + struct ubi_mkvol_req req; + size_t n; + + n = strlen(name); + if (n > UBI_MAX_VOLUME_NAME) + return -1; + + if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) + return -1; + + req.vol_id = vol_id; + req.bytes = bytes; + req.vol_type = vol_type; + req.alignment = alignment; + + strncpy(req.name, name, UBI_MAX_VOLUME_NAME + 1); + req.name_len = n; + + /* printf("DBG: %s(vol_id=%d, bytes=%lld, type=%d, alig=%d, nlen=%d, " + "name=%s)\n", __func__, vol_id, bytes, vol_type, alignment, + strlen(name), name);*/ + + err = ioctl(fd, UBI_IOCMKVOL, &req); + if (err < 0) { + ubi_err("ioctl returned %d errno=%d\n", err, errno); + goto out_close; + } + + ubi_dbg("created volume %d, size %lld, name \"%s\" " + "at UBI dev %d\n", vol_id, bytes, name, devn); + + close(fd); + return err; + out_close: + ubi_cdev_close(fd); + return err; +} + +int +ubi_rmvol(ubi_lib_t desc, int devn, int vol_id) +{ + int fd; + int err; + + if ((fd = ubi_cdev_open(desc, devn, O_RDWR)) == -1) + return -1; + + err = ioctl(fd, UBI_IOCRMVOL, &vol_id); + if (err < 0) + goto out_close; + + ubi_dbg("removed volume %d", vol_id); + + out_close: + ubi_cdev_close(fd); + return err; +} + +int +ubi_get_info(ubi_lib_t desc, struct ubi_info *ubi) +{ + memcpy(ubi, &desc->ubi, sizeof(struct ubi_info)); + return 0; +} + + +int +ubi_vol_open(ubi_lib_t desc, int devn, int vol_id, int flags) +{ + char *buf; + int fd; + + ubi_dbg("desc=%p, devn=%d, vol_id=%d, flags=%08x\n", + desc, devn, vol_id, flags); + + if (desc == NULL) { + ubi_err("desc is NULL\n"); + return -1; + } + if (desc->vol_cdev_path_len == 0) { + ubi_err("path_len == 0\n"); + return -1; + } + buf = malloc(desc->cdev_path_len); + + sprintf(buf, desc->vol_cdev_path, devn, vol_id); + + fd = open(buf, flags); + if (fd == -1) + ubi_dbg("cannot open %s", buf); + + free(buf); + return fd; +} + +int +ubi_vol_close(int vol_fd) +{ + return close(vol_fd); +} + + +int +ubi_vol_update(int vol_fd, unsigned long long bytes) +{ + int err; + + err = ioctl(vol_fd, UBI_IOCVOLUP, &bytes); + if (err) { + ubi_err("%s failure calling update ioctl\n" + " IOCTL(%08lx) err=%d errno=%d\n", + __func__, (long unsigned int)UBI_IOCVOLUP, err, errno); + } + return err; +} + +FILE * +ubi_vol_fopen_read(ubi_lib_t desc, int devn, uint32_t vol_id) +{ + FILE *fp; + int fd; + + fd = ubi_vol_open(desc, devn, vol_id, O_RDONLY); + if (fd == -1) + return NULL; + + fp = fdopen(fd, "r"); + if (fp == NULL) + ubi_vol_close(fd); + + return fp; +} + +FILE * +ubi_vol_fopen_update(ubi_lib_t desc, int devn, uint32_t vol_id, + unsigned long long bytes) +{ + FILE *fp; + int fd; + int err; + + fd = ubi_vol_open(desc, devn, vol_id, O_RDWR); + if (fd == -1) + return NULL; + + fp = fdopen(fd, "r+"); + if (fp == NULL) { + printf("DBG: %s(errno=%d)\n", __func__, errno); + ubi_vol_close(fd); + return NULL; + } + err = ubi_vol_update(fd, bytes); + if (err < 0) { + printf("DBG: %s() fd=%d err=%d\n", __func__, fd, err); + fclose(fp); + return NULL; + } + return fp; +} + +int +ubi_vol_get_used_bytes(int vol_fd, unsigned long long *bytes) +{ + off_t res; + + res = lseek(vol_fd, 0, SEEK_END); + if (res == (off_t)-1) + return -1; + *bytes = (unsigned long long) res; + res = lseek(vol_fd, 0, SEEK_SET); + return res == (off_t)-1 ? -1 : 0; +} diff --git a/ubi-utils/src/libubiold_int.h b/ubi-utils/src/libubiold_int.h new file mode 100644 index 0000000..830a682 --- /dev/null +++ b/ubi-utils/src/libubiold_int.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * + * Author: Artem B. Bityutskiy + */ + +#ifndef __UBI_INT_H__ +#define __UBI_INT_H__ +/* + * Enable/disable UBI library debugging messages. + */ +#undef UBILIB_DEBUG + +/* + * UBI library error message. + */ +#define ubi_err(fmt, ...) do { \ + fprintf(stderr, "UBI Library Error at %s: ", __func__); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) + +#ifdef UBILIB_DEBUG +#define ubi_dbg(fmt, ...) do { \ + fprintf(stderr, "UBI Debug: %s: ", __func__); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) + +#else +#define ubi_dbg(fmt, ...) do { } while (0) +#endif + +/** + * SYSFS Entries. + * + * @def UBI_ROOT + * @brief Name of the root UBI directory in sysfs. + * + * @def UBI_NLEN_MAX + * @brief Name of syfs file containing the maximum UBI volume name length. + * + * @def UBI_VER + * @brief Name of sysfs file containing UBI version. + * + * @def UBI_WEAR + * @brief Name of sysfs file containing wear level of an UBI device. + * + * @def UBI_VOL_COUNT + * @brief Name of sysfs file contaning the of volume on an UBI device + * + * @def UBI_TOT_EBS + * @brief Name of sysfs file contaning the total number of + * eraseblocks on an UBI device. + * + * @def UBI_AVAIL_EBS + * @brief Name of sysfs file contaning the number of unused eraseblocks on + * an UBI device. + * + * @def UBI_EB_SIZE + * @brief Name of sysfs file containing size of UBI eraseblocks. + * + * @def UBI_NUMS + * @brief Name of sysfs file containing major and minor numbers + * of an UBI device or an UBI volume device. + * + * @def UBI_VBYTES + * @brief Name of sysfs file containing size of an UBI volume device in + * bytes. + * + * @def UBI_VEBS + * @brief Name of sysfs file containing size of an UBI volume device in + * eraseblocks. + * + * @def UBI_VTYPE + * @brief Name of sysfs file containing type of an UBI volume device. + * + * @def UBI_VNAME + * @brief Name of sysfs file containing name of an UBI volume device. + **/ +#define UBI_ROOT "ubi" +#define UBI_NLEN_MAX "volume_name_max" +#define UBI_VER "version" +#define UBI_WEAR "wear" +#define UBI_VOL_COUNT "volumes_count" +#define UBI_TOT_EBS "total_eraseblocks" +#define UBI_AVAIL_EBS "avail_eraseblocks" +#define UBI_EB_SIZE "eraseblock_size" +#define UBI_NUMS "dev" +#define UBI_VBYTES "bytes" +#define UBI_VEBS "eraseblocks" +#define UBI_VTYPE "type" +#define UBI_VNAME "name" + +#define UBI_CDEV_PATH "/dev/ubi%d" +#define UBI_VOL_CDEV_PATH "/dev/ubi%d_%d" +#define UBI_SYSFS_ROOT "/sys/class" + +#define UBI_MAX_ID_SIZE 9 + +#endif /* !__UBI_INT_H__ */ diff --git a/ubi-utils/src/libubiold_sysfs.c b/ubi-utils/src/libubiold_sysfs.c new file mode 100644 index 0000000..95fd3de --- /dev/null +++ b/ubi-utils/src/libubiold_sysfs.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * + * Author: Artem B. Bityutskiy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "libubi_int.h" + +int +sysfs_read_data(const char *file, void *buf, int len) +{ + int fd; + ssize_t rd; + + fd = open(file, O_RDONLY); + if (fd == -1) { + ubi_err("cannot open file %s", file); + return -1; + } + + rd = read(fd, buf, len); + if (rd == -1) + ubi_err("cannot read file %s", file); + + close(fd); + + return rd; +} + +int +sysfs_read_data_subst(const char *patt, void *buf, int len, int n, ...) +{ + va_list args; + char buf1[strlen(patt) + 20 * n]; + + va_start(args, n); + vsprintf(&buf1[0], patt, args); + va_end(args); + + return sysfs_read_data(&buf1[0], buf, len); +} + +int +sysfs_read_dev(const char *file, unsigned int *major, unsigned int *minor) +{ + int fd; + int ret; + ssize_t rd; + int err = -1; + char buf[40]; + + fd = open(file, O_RDONLY); + if (fd == -1) { + ubi_err("cannot open file %s", file); + return -1; + } + + rd = read(fd, &buf[0], 20); + if (rd == -1) { + ubi_err("cannot read file %s", file); + goto error; + } + if (rd < 4) { + ubi_err("bad contents of file %s:", file); + goto error; + } + + err = -1; + if (buf[rd -1] != '\n') { + ubi_err("bad contents of file %s", file); + goto error; + } + + ret = sscanf(&buf[0], "%d:%d\n", major, minor); + if (ret != 2) { + ubi_err("bad contents of file %s", file); + goto error; + } + + err = 0; + +error: + close(fd); + + return err; +} + +int +sysfs_read_dev_subst(const char *patt, unsigned int *major, + unsigned int *minor, int n, ...) +{ + va_list args; + char buf[strlen(patt) + 20 * n]; + + va_start(args, n); + vsprintf(&buf[0], patt, args); + va_end(args); + + return sysfs_read_dev(&buf[0], major, minor); +} + +static int +sysfs_read_ull(const char *file __unused, unsigned long long *num __unused) +{ + return 0; +} + +int +sysfs_read_ull_subst(const char *patt, unsigned long long *num, int n, ...) +{ + va_list args; + char buf[strlen(patt) + 20 * n]; + + va_start(args, n); + vsprintf(&buf[0], patt, args); + va_end(args); + + return sysfs_read_ull(&buf[0], num); +} + +static int +sysfs_read_uint(const char *file __unused, unsigned int *num __unused) +{ + return 0; +} + +int +sysfs_read_uint_subst(const char *patt, unsigned int *num, int n, ...) +{ + va_list args; + char buf[strlen(patt) + 20 * n]; + + va_start(args, n); + vsprintf(&buf[0], patt, args); + va_end(args); + + return sysfs_read_uint(&buf[0], num); +} + +int +sysfs_read_ll(const char *file, long long *num) +{ + int fd; + ssize_t rd; + int err = -1; + char buf[20]; + char *endptr; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 20); + if (rd == -1) + goto out; + + if (rd < 2) { + ubi_err("bad contents in file %s: \"%c%c...\"", + file, buf[0], buf[1]); + goto out_errno; + } + + *num = strtoll(&buf[0], &endptr, 10); + if (endptr == &buf[0] || *endptr != '\n') { + ubi_err("bad contents in file %s: \"%c%c...\"", + file, buf[0], buf[1]); + goto out_errno; + } + + if (*num < 0) { + ubi_err("bad number in file %s: %lld", file, *num); + goto out_errno; + } + + err = 0; + +out_errno: + errno = EINVAL; + +out: + close(fd); + return err; +} + +int +sysfs_read_int(const char *file, int *num) +{ + int err; + long long res = 0; + + err = sysfs_read_ll(file, &res); + if (err) + return err; + + if (res < 0 || res > INT_MAX) { + ubi_err("bad number in file %s: %lld", file, res); + errno = EINVAL; + return -1; + } + + *num = res; + return 0; +} diff --git a/ubi-utils/src/libubiold_sysfs.h b/ubi-utils/src/libubiold_sysfs.h new file mode 100644 index 0000000..2fb6072 --- /dev/null +++ b/ubi-utils/src/libubiold_sysfs.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * UBI (Unsorted Block Images) library. + * + * Author: Artem B. Bityutskiy + */ + +/** + * sysfs_read_data - read data from a sysfs file. + * + * @file path to the file to read from + * @buf furrer where to store read data + * @len length of provided buffer @buf + * + * This function returns the number of read bytes or -1 in case of error. + */ +int sysfs_read_data(const char *file, void *buf, int len); + +/** + * sysfs_read_data_subst - form path to a sysfs file and read data from it. + * + * @patt path to the file to read from + * @buf furrer where to store read data + * @len length of provided buffer @buf + * @n number of parameters to substitute to @patt + * + * This function forms path to a sysfs file by means of substituting parameters + * to @patt and then reads @len bytes from this file and stores the read data + * to @buf. This function returns the number of read bytes or -1 in case of + * error. + */ +int sysfs_read_data_subst(const char *patt, void *buf, int len, int n, ...); + +/** + * sysfs_read_dev - read major and minor number from a sysfs file. + * + * @file path to the file to read from + * @major major number is returned here + * @minor minor number is returned here + */ +int sysfs_read_dev(const char *file, unsigned int *major, + unsigned int *minor); +/** + * sysfs_read_dev_subst - for path to a file and read major and minor number + * from it. + * + * @patt pattern of the path to the file to read from + * @major major number is returned here + * @minor minor number is returned here + * @n number of arguments to substitute + * + * This function substitures arguments to the @patt file path pattern and reads + * major and minor numbers from the resulting file. + */ +int sysfs_read_dev_subst(const char *patt, unsigned int *major, + unsigned int *minor, int n, ...); + +/** + * sysfs_read_ull_subst - form path to a sysfs file and read an unsigned long + * long value from there. + * + * @patt pattern of file path + * @num the read value is returned here + * @n number of parameters to substitute + * + * + * This function first forms the path to a sysfs file by means of substituting + * passed parameters to the @patt string, and then read an 'unsigned long long' + * value from this file. + */ +int sysfs_read_ull_subst(const char *patt, unsigned long long *num, + int n, ...); + +/** + * sysfs_read_uint_subst - the same as 'sysfs_read_uint_subst()' but reads an + * unsigned int value. + */ +int sysfs_read_uint_subst(const char *patt, unsigned int *num, + int n, ...); + +/** + * sysfs_read_ll - read a long long integer from an UBI sysfs file. + * + * @file file name from where to read + * @num the result is returned here + */ +int sysfs_read_ll(const char *file, long long *num); + +/** + * sysfs_read_int - the same as 'sysfs_read_ll()' but reads an 'int' value. + */ +int sysfs_read_int(const char *file, int *num); -- cgit v1.2.3 From 9c37b558705b776e51f7d522f376de019a6ea203 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 21 Mar 2007 11:53:25 +0200 Subject: UBI-Utils: Convert to new ubi library Signed-off-by: Adrian Hunter --- ubi-utils/Makefile | 20 +- ubi-utils/inc/libubi.h | 268 ++++++++++++ ubi-utils/src/libpfiflash.c | 2 +- ubi-utils/src/libubi.c | 917 ++++++++++++++++++++++++++++++++++++++++ ubi-utils/src/libubi_int.h | 129 ++++++ ubi-utils/src/libubimirror.c | 10 +- ubi-utils/src/libubiold.c | 6 +- ubi-utils/src/libubiold_sysfs.c | 2 +- ubi-utils/src/pddcustomize.c | 2 +- ubi-utils/src/reader.c | 13 +- ubi-utils/src/ubimkvol.c | 33 +- ubi-utils/src/ubirmvol.c | 24 +- ubi-utils/src/ubiupdatevol.c | 46 +- 13 files changed, 1409 insertions(+), 63 deletions(-) create mode 100644 ubi-utils/inc/libubi.h create mode 100644 ubi-utils/src/libubi.c create mode 100644 ubi-utils/src/libubi_int.h (limited to 'ubi-utils/src/libubi.c') diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile index 0818a9b..797807d 100644 --- a/ubi-utils/Makefile +++ b/ubi-utils/Makefile @@ -16,11 +16,12 @@ CFLAGS := -I./inc -I./src -I$(KERNELHDR) -O2 -g -Wall -Werror \ -Wwrite-strings -W -std=gnu99 \ -DHOST_OS_NAME=\"$(HOST_OS_NAME)\" \ -DHOST_VERSION_NAME=\"$(HOST_VERSION_NAME)\" \ - -DBUILD_CPU=\"$(BUILD_CPU)\" -DBUILD_OS=\"$(BUILD_OS)\" + -DBUILD_CPU=\"$(BUILD_CPU)\" -DBUILD_OS=\"$(BUILD_OS)\" \ + -DPACKAGE_VERSION=\"1.0\" PERLPROGS = mkpfi ubicrc32.pl TARGETS = ubiupdatevol ubimkvol ubirmvol pfiflash pddcustomize ubimirror \ - bin2nand nand2bin ubigen mkbootenv unubi pfi2bin + bin2nand nand2bin ubigen mkbootenv unubi pfi2bin ubicrc32 vpath %.c ./src @@ -38,25 +39,25 @@ IGNORE=${wildcard .*.c.dep} clean: rm -rf *.o $(TARGETS) .*.c.dep -ubiupdatevol: ubiupdatevol.o error.o libubi.o libubi_sysfs.o +ubiupdatevol: ubiupdatevol.o error.o libubi.o $(CC) $(LDFLAGS) -o $@ $^ -ubimkvol: ubimkvol.o error.o libubi.o libubi_sysfs.o +ubimkvol: ubimkvol.o error.o libubi.o $(CC) $(LDFLAGS) -o $@ $^ -ubirmvol: ubirmvol.o error.o libubi.o libubi_sysfs.o +ubirmvol: ubirmvol.o error.o libubi.o $(CC) $(LDFLAGS) -o $@ $^ pddcustomize: pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \ - libubi.o libubi_sysfs.o crc32.o + libubiold.o libubiold_sysfs.o crc32.o $(CC) $(LDFLAGS) -o $@ $^ pfiflash: pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \ - bootenv.o hashmap.o pfi.o libubi.o libubi_sysfs.o crc32.o + bootenv.o hashmap.o pfi.o libubiold.o libubiold_sysfs.o crc32.o $(CC) $(LDFLAGS) -o $@ $^ ubimirror: ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \ - libubi.o libubi_sysfs.o crc32.o + libubiold.o libubiold_sysfs.o crc32.o $(CC) $(LDFLAGS) -o $@ $^ nand2bin: nand2bin.o nandecc.o nandcorr.o @@ -78,6 +79,9 @@ pfi2bin: pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \ hashmap.o reader.o pfi.o $(CC) $(LDFLAGS) -o $@ $^ +ubicrc32: ubicrc32.o crc32.o + $(CC) $(LDFLAGS) -o $@ $^ + install: ${TARGETS} mkdir -p ${DESTDIR}/${SBINDIR} install -m0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/inc/libubi.h new file mode 100644 index 0000000..d39c1b9 --- /dev/null +++ b/ubi-utils/inc/libubi.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem B. Bityutskiy + * + * UBI (Unsorted Block Images) library. + */ + +#ifndef __LIBUBI_H__ +#define __LIBUBI_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* UBI version libubi is made for */ +#define LIBUBI_UBI_VERSION 1 + +/* UBI library descriptor */ +typedef void * libubi_t; + +/** + * struct ubi_mkvol_request - volume creation request. + * */ +struct ubi_mkvol_request +{ + int vol_id; + int alignment; + long long bytes; + int vol_type; + const char *name; +}; + +/** + * struct ubi_info - general UBI information. + * + * @dev_count count of UBI devices in system + * @lowest_dev_num lowest UBI device number + * @highest_dev_num highest UBI device number + * @version UBI version + */ +struct ubi_info +{ + int dev_count; + int lowest_dev_num; + int highest_dev_num; + int version; +}; + +/** + * struct ubi_dev_info - UBI device information. + * + * @vol_count count of volumes on this UBI device + * @lowest_vol_num lowest volume number + * @highest_vol_num highest volume number + * @total_ebs total number of eraseblocks on this UBI device + * @avail_ebs how many eraseblocks are not used and available for new + * volumes + * @total_bytes @total_ebs * @eb_size + * @avail_bytes @avail_ebs * @eb_size + * @bad_count count of bad eraseblocks + * @eb_size size of UBI eraseblock + * @max_ec current highest erase counter value + * @bad_rsvd how many physical eraseblocks of the underlying flash + * device are reserved for bad eraseblocks handling + * @max_vol_count maximum count of volumes on this UBI device + * @min_io_size minimum input/output size of the UBI device + */ +struct ubi_dev_info +{ + int dev_num; + int vol_count; + int lowest_vol_num; + int highest_vol_num; + int total_ebs; + int avail_ebs; + long long total_bytes; + long long avail_bytes; + int bad_count; + int eb_size; + long long max_ec; + int bad_rsvd; + int max_vol_count; + int min_io_size; +}; + +/** + * struct ubi_vol_info - UBI volume information. + * + * @dev_num UBI device number the volume resides on + * @vol_id ID of this volume + * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) + * @alignment alignemnt of this volume + * @data_bytes how many data bytes are stored on this volume (equivalent to + * @rsvd_bytes for dynamic volumes) + * @rsvd_bytes how many bytes are reserved for this volume + * @rsvd_ebs how many eraseblocks are reserved for this volume + * @eb_size logical eraseblock size of this volume (may be less then + * device's logical eraseblock size due to alignment) + * @corrupted the volume is corrupted if this flag is not zero + * @name volume name (null-terminated) + */ +struct ubi_vol_info +{ + int dev_num; + int vol_id; + int type; + int alignment; + long long data_bytes; + long long rsvd_bytes; + int rsvd_ebs; + int eb_size; + int corrupted; + char name[UBI_VOL_NAME_MAX + 1]; +}; + +/** + * libubi_open - open UBI library. + * + * This function initializes and opens the UBI library and returns UBI library + * descriptor in case of success and %NULL in case of failure. + */ +libubi_t libubi_open(void); + +/** + * libubi_close - close UBI library + * + * @desc UBI library descriptor + */ +void libubi_close(libubi_t desc); + +/** + * ubi_get_info - get general UBI information. + * + * @info pointer to the &struct ubi_info object to fill + * @desc UBI library descriptor + * + * This function fills the passed @info object with general UBI information and + * returns %0 in case of success and %-1 in case of failure. + */ +int ubi_get_info(libubi_t desc, struct ubi_info *info); + +/** + * ubi_mkvol - create an UBI volume. + * + * @desc UBI library descriptor + * @node name of the UBI character device to create a volume at + * @req UBI volume creation request (defined at ) + * + * This function creates a UBI volume as described at @req and returns %0 in + * case of success and %-1 in case of failure. The assigned volume ID is + * returned in @req->vol_id. + */ +int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req); + +/** + * ubi_rmvol - remove a UBI volume. + * + * @desc UBI library descriptor + * @node name of the UBI character device to remove a volume from + * @vol_id ID of the volume to remove + * + * This function removes volume @vol_id from UBI device @node and returns %0 in + * case of success and %-1 in case of failure. + */ +int ubi_rmvol(libubi_t desc, const char *node, int vol_id); + +/** + * ubi_rsvol - re-size UBI volume. + * + * @desc UBI library descriptor + * @node name of the UBI character device owning the volume which should be + * re-sized + * @vol_id volume ID to re-size + * @bytes new volume size in bytes + * + * This function returns %0 in case of success and %-1 in case of error. + */ +int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes); + +/** + * ubi_get_dev_info - get UBI device information. + * + * @desc UBI library descriptor + * @node name of the UBI character device to fetch information about + * @info pointer to the &struct ubi_dev_info object to fill + * + * This function fills the passed @info object with UBI device information and + * returns %0 in case of success and %-1 in case of failure. + */ +int ubi_get_dev_info(libubi_t desc, const char *node, + struct ubi_dev_info *info); + +/** + * ubi_get_dev_info1 - get UBI device information. + * + * @desc UBI library descriptor + * @dev_num UBI device number to fetch information about + * @info pointer to the &struct ubi_dev_info object to fill + * + * This function is identical to 'ubi_get_dev_info()' except that it accepts UBI + * device number, not UBI character device. + */ +int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info); + +/** + * ubi_get_vol_info - get UBI volume information. + * + * @desc UBI library descriptor + * @node name of the UBI volume character device to fetch information about + * @info pointer to the &struct ubi_vol_info object to fill + * + * This function fills the passed @info object with UBI volume information and + * returns %0 in case of success and %-1 in case of failure. + */ +int ubi_get_vol_info(libubi_t desc, const char *node, + struct ubi_vol_info *info); + +/** + * ubi_get_vol_info1 - get UBI volume information. + * + * @desc UBI library descriptor + * @dev_num UBI device number + * @vol_id ID of the UBI volume to fetch information about + * @info pointer to the &struct ubi_vol_info object to fill + * + * This function is identical to 'ubi_get_vol_info()' except that it accepts UBI + * volume number, not UBI volume character device. + */ +int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, + struct ubi_vol_info *info); + +/** + * ubi_update_start - start UBI volume update. + * + * @desc UBI library descriptor + * @fd volume character devie file descriptor + * @bytes how many bytes will be written to the volume + * + * This function initiates UBI volume update and returns %0 in case of success + * and %-1 in case of error. + */ +int ubi_update_start(libubi_t desc, int fd, long long bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* !__LIBUBI_H__ */ diff --git a/ubi-utils/src/libpfiflash.c b/ubi-utils/src/libpfiflash.c index 4dfafea..4f1f5cd 100644 --- a/ubi-utils/src/libpfiflash.c +++ b/ubi-utils/src/libpfiflash.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include /* FIXME Is this ok here? */ diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c new file mode 100644 index 0000000..17ab4ee --- /dev/null +++ b/ubi-utils/src/libubi.c @@ -0,0 +1,917 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem B. Bityutskiy + * + * UBI (Unsorted Block Images) library. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libubi.h" +#include "libubi_int.h" + +libubi_t libubi_open(void) +{ + int fd, version; + struct libubi *lib; + + lib = calloc(1, sizeof(struct libubi)); + if (!lib) + return NULL; + + /* TODO: this must be discovered instead */ + lib->sysfs = strdup("/sys"); + if (!lib->sysfs) + goto error; + + lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); + if (!lib->sysfs_ubi) + goto error; + + /* Make sure UBI is present */ + fd = open(lib->sysfs_ubi, O_RDONLY); + if (fd == -1) + goto error; + close(fd); + + lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); + if (!lib->ubi_dev) + goto error; + + lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); + if (!lib->ubi_version) + goto error; + + lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); + if (!lib->dev_dev) + goto error; + + lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); + if (!lib->dev_avail_ebs) + goto error; + + lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); + if (!lib->dev_total_ebs) + goto error; + + lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); + if (!lib->dev_bad_count) + goto error; + + lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); + if (!lib->dev_eb_size) + goto error; + + lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); + if (!lib->dev_max_ec) + goto error; + + lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); + if (!lib->dev_bad_rsvd) + goto error; + + lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); + if (!lib->dev_max_vols) + goto error; + + lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); + if (!lib->dev_min_io_size) + goto error; + + lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); + if (!lib->ubi_vol) + goto error; + + lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); + if (!lib->vol_type) + goto error; + + lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); + if (!lib->vol_dev) + goto error; + + lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); + if (!lib->vol_alignment) + goto error; + + lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); + if (!lib->vol_data_bytes) + goto error; + + lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); + if (!lib->vol_rsvd_ebs) + goto error; + + lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); + if (!lib->vol_eb_size) + goto error; + + lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); + if (!lib->vol_corrupted) + goto error; + + lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); + if (!lib->vol_name) + goto error; + + if (read_int(lib->ubi_version, &version)) + goto error; + if (version != LIBUBI_UBI_VERSION) { + fprintf(stderr, "LIBUBI: this library was made for UBI version " + "%d, but UBI version %d is detected\n", + LIBUBI_UBI_VERSION, version); + goto error; + } + + return lib; + +error: + free(lib->vol_corrupted); + free(lib->vol_eb_size); + free(lib->vol_rsvd_ebs); + free(lib->vol_data_bytes); + free(lib->vol_alignment); + free(lib->vol_dev); + free(lib->vol_type); + free(lib->ubi_vol); + free(lib->dev_min_io_size); + free(lib->dev_max_vols); + free(lib->dev_bad_rsvd); + free(lib->dev_max_ec); + free(lib->dev_eb_size); + free(lib->dev_bad_count); + free(lib->dev_total_ebs); + free(lib->dev_avail_ebs); + free(lib->dev_dev); + free(lib->ubi_version); + free(lib->ubi_dev); + free(lib->sysfs_ubi); + free(lib->sysfs); + free(lib); + return NULL; +} + +void libubi_close(libubi_t desc) +{ + struct libubi *lib = (struct libubi *)desc; + + free(lib->vol_name); + free(lib->vol_corrupted); + free(lib->vol_eb_size); + free(lib->vol_rsvd_ebs); + free(lib->vol_data_bytes); + free(lib->vol_alignment); + free(lib->vol_dev); + free(lib->vol_type); + free(lib->ubi_vol); + free(lib->dev_min_io_size); + free(lib->dev_max_vols); + free(lib->dev_bad_rsvd); + free(lib->dev_max_ec); + free(lib->dev_eb_size); + free(lib->dev_bad_count); + free(lib->dev_total_ebs); + free(lib->dev_avail_ebs); + free(lib->dev_dev); + free(lib->ubi_version); + free(lib->ubi_dev); + free(lib->sysfs_ubi); + free(lib->sysfs); + free(lib); +} + +int ubi_get_info(libubi_t desc, struct ubi_info *info) +{ + DIR *sysfs_ubi; + struct dirent *dirent; + struct libubi *lib = (struct libubi *)desc; + + memset(info, '\0', sizeof(struct ubi_info)); + + /* + * We have to scan the UBI sysfs directory to identify how many UBI + * devices are present. + */ + sysfs_ubi = opendir(lib->sysfs_ubi); + if (!sysfs_ubi) + return -1; + + info->lowest_dev_num = INT_MAX; + while ((dirent = readdir(sysfs_ubi))) { + char *name = &dirent->d_name[0]; + int dev_num, ret; + + ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num); + if (ret == 1) { + info->dev_count += 1; + if (dev_num > info->highest_dev_num) + info->highest_dev_num = dev_num; + if (dev_num < info->lowest_dev_num) + info->lowest_dev_num = dev_num; + } + } + + if (info->lowest_dev_num == INT_MAX) + info->lowest_dev_num = 0; + + if (read_int(lib->ubi_version, &info->version)) + goto close; + + return closedir(sysfs_ubi); + +close: + closedir(sysfs_ubi); + return -1; +} + +int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) +{ + int fd, ret; + struct ubi_mkvol_req r; + size_t n; + + desc = desc; + r.vol_id = req->vol_id; + r.alignment = req->alignment; + r.bytes = req->bytes; + r.vol_type = req->vol_type; + + n = strlen(req->name); + if (n > UBI_MAX_VOLUME_NAME) + return -1; + + strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); + r.name_len = n; + + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + ret = ioctl(fd, UBI_IOCMKVOL, &r); + + if (!ret) + req->vol_id = r.vol_id; + + close(fd); + return ret; +} + +int ubi_rmvol(libubi_t desc, const char *node, int vol_id) +{ + int fd, ret; + + desc = desc; + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); + close(fd); + return ret; +} + +int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) +{ + int fd, ret; + struct ubi_rsvol_req req; + + desc = desc; + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + req.bytes = bytes; + req.vol_id = vol_id; + + ret = ioctl(fd, UBI_IOCRSVOL, &req); + close(fd); + return ret; +} + +int ubi_update_start(libubi_t desc, int fd, long long bytes) +{ + desc = desc; + if (ioctl(fd, UBI_IOCVOLUP, &bytes)) + return -1; + return 0; +} + +int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) +{ + int dev_num; + struct libubi *lib = (struct libubi *)desc; + + dev_num = find_dev_num(lib, node); + if (dev_num == -1) + return -1; + + return ubi_get_dev_info1(desc, dev_num, info); +} + +int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) +{ + DIR *sysfs_ubi; + struct dirent *dirent; + struct libubi *lib = (struct libubi *)desc; + + memset(info, '\0', sizeof(struct ubi_dev_info)); + info->dev_num = dev_num; + + sysfs_ubi = opendir(lib->sysfs_ubi); + if (!sysfs_ubi) + return -1; + + info->lowest_vol_num = INT_MAX; + while ((dirent = readdir(sysfs_ubi))) { + char *name = &dirent->d_name[0]; + int vol_id, ret, devno; + + ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id); + if (ret == 2 && devno == dev_num) { + info->vol_count += 1; + if (vol_id > info->highest_vol_num) + info->highest_vol_num = vol_id; + if (vol_id < info->lowest_vol_num) + info->lowest_vol_num = vol_id; + } + } + + closedir(sysfs_ubi); + + if (info->lowest_vol_num == INT_MAX) + info->lowest_vol_num = 0; + + if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs)) + return -1; + if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs)) + return -1; + if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) + return -1; + if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size)) + return -1; + if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) + return -1; + if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) + return -1; + if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) + return -1; + if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) + return -1; + + info->avail_bytes = info->avail_ebs * info->eb_size; + info->total_bytes = info->total_ebs * info->eb_size; + + return 0; +} + +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_info1(libubi_t desc, int dev_num, int vol_id, + struct ubi_vol_info *info) +{ + int ret; + struct libubi *lib = (struct libubi *)desc; + char buf[50]; + + memset(info, '\0', sizeof(struct ubi_vol_info)); + info->dev_num = dev_num; + info->vol_id = vol_id; + + ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50); + if (ret < 0) + return -1; + + if (strncmp(&buf[0], "static\n", ret) == 0) + info->type = UBI_STATIC_VOLUME; + else if (strncmp(&buf[0], "dynamic\n", ret) == 0) + info->type = UBI_DYNAMIC_VOLUME; + else { + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + return -1; + } + + ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, + &info->alignment); + if (ret) + return -1; + ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, + &info->data_bytes); + if (ret) + return -1; + ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs); + if (ret) + return -1; + ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size); + if (ret) + return -1; + ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, + &info->corrupted); + if (ret) + return -1; + info->rsvd_bytes = info->eb_size * info->rsvd_ebs; + + ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, + UBI_VOL_NAME_MAX + 2); + if (ret < 0) + return -1; + + info->name[ret - 1] = '\0'; + + return 0; +} + +/** + * read_int - read an 'int' value from a file. + * + * @file the file to read from + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int read_int(const char *file, int *value) +{ + int fd, rd; + char buf[50]; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_int - read an 'int' value from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_int(const char *patt, int dev_num, int *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_ll - read a 'long long' value from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_ll(const char *patt, int dev_num, long long *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%lld\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_data - read data from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @buf buffer to read data to + * @buf_len buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len) +{ + int fd, rd; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) { + close(fd); + return -1; + } + + close(fd); + return rd; +} + +/** + * vol_read_int - read an 'int' value from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_ll(const char *patt, int dev_num, int vol_id, + long long *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%lld\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * vol_read_data - read data from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @buf buffer to read to + * @buf_len buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, + int buf_len) +{ + int fd, rd; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) { + close(fd); + return -1; + } + + close(fd); + return rd; +} + +/** + * mkpath - compose full path from 2 given components. + * + * @path first component + * @name second component + * + * This function returns the resulting path in case of success and %NULL in + * case of failure. + */ +static char *mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) + return NULL; + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + +/** + * 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; +} + +/** + * find_dev_num_vol - find UBI device number by volume 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_vol(struct libubi *lib, const char *node) +{ + struct stat stat; + struct ubi_info info; + int i, major; + + if (lstat(node, &stat)) + return -1; + + if (!S_ISCHR(stat.st_mode)) { + errno = EINVAL; + return -1; + } + + major = major(stat.st_rdev); + + if (minor(stat.st_rdev) == 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 (major1 == major) + return i; + } + + errno = ENOENT; + return -1; +} + +/** + * find_vol_num - find UBI volume number by its character device node. + * + * @lib UBI library descriptor + * @dev_num UBI device number + * @node UBI volume character device node name + * + * This function returns positive UBI volume number in case of success and %-1 + * in case of failure. + */ +static int find_vol_num(struct libubi *lib, int dev_num, const char *node) +{ + struct stat stat; + struct ubi_dev_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_dev_info1((libubi_t *)lib, dev_num, &info)) + return -1; + + for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) { + int major1, minor1, ret; + char buf[50]; + + ret = vol_read_data(lib->vol_dev, dev_num, 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; +} diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h new file mode 100644 index 0000000..e68b791 --- /dev/null +++ b/ubi-utils/src/libubi_int.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem B. Bityutskiy + * + * UBI (Unsorted Block Images) library. + */ + +#ifndef __LIBUBI_INT_H__ +#define __LIBUBI_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * UBI heavily makes use of the sysfs file system to interact with users-pace. + * The below are pre-define UBI file and directory names. + */ + +#define SYSFS_UBI "class/ubi" +#define UBI_DEV_NAME_PATT "ubi%d" +#define UBI_VER "version" +#define DEV_DEV "dev" +#define UBI_VOL_NAME_PATT "ubi%d_%d" +#define DEV_AVAIL_EBS "avail_eraseblocks" +#define DEV_TOTAL_EBS "total_eraseblocks" +#define DEV_BAD_COUNT "bad_peb_count" +#define DEV_EB_SIZE "eraseblock_size" +#define DEV_MAX_EC "max_ec" +#define DEV_MAX_RSVD "reserved_for_bad" +#define DEV_MAX_VOLS "max_vol_count" +#define DEV_MIN_IO_SIZE "min_io_size" +#define VOL_TYPE "type" +#define VOL_DEV "dev" +#define VOL_ALIGNMENT "alignment" +#define VOL_DATA_BYTES "data_bytes" +#define VOL_RSVD_EBS "reserved_ebs" +#define VOL_EB_SIZE "usable_eb_size" +#define VOL_CORRUPTED "corrupted" +#define VOL_NAME "name" + +/** + * libubi - UBI library description data structure. + * + * @sysfs sysfs file system path + * @sysfs_ubi UBI directory in sysfs + * @ubi_dev UBI device sysfs directory pattern + * @ubi_version UBI version file sysfs path + * @dev_dev UBI device's major/minor numbers file pattern + * @dev_avail_ebs count of available eraseblocks sysfs path pattern + * @dev_total_ebs total eraseblocks count sysfs path pattern + * @dev_bad_count count of bad eraseblocks sysfs path pattern + * @dev_eb_size size of UBI device's eraseblocks sysfs path pattern + * @dev_max_ec maximum erase counter sysfs path pattern + * @dev_bad_rsvd count of physical eraseblock reserved for bad eraseblocks + * handling + * @dev_max_vols maximum volumes number count sysfs path pattern + * @dev_min_io_size minimum I/O unit size sysfs path pattern + * @ubi_vol UBI volume sysfs directory pattern + * @vol_type volume type sysfs path pattern + * @vol_dev volume's major/minor numbers file pattern + * @vol_alignment volume alignment sysfs path pattern + * @vol_data_bytes volume data size sysfs path pattern + * @vol_rsvd_ebs volume reserved size sysfs path pattern + * @vol_eb_size volume eraseblock size sysfs path pattern + * @vol_corrupted volume corruption flag sysfs path pattern + * @vol_name volume name sysfs path pattern + */ +struct libubi +{ + char *sysfs; + char *sysfs_ubi; + char *ubi_dev; + char *ubi_version; + char *dev_dev; + char *dev_avail_ebs; + char *dev_total_ebs; + char *dev_bad_count; + char *dev_eb_size; + char *dev_max_ec; + char *dev_bad_rsvd; + char *dev_max_vols; + char *dev_min_io_size; + char *ubi_vol; + char *vol_type; + char *vol_dev; + char *vol_alignment; + char *vol_data_bytes; + char *vol_rsvd_ebs; + char *vol_eb_size; + char *vol_corrupted; + char *vol_name; + char *vol_max_count; +}; + +static int read_int(const char *file, int *value); +static int dev_read_int(const char *patt, int dev_num, int *value); +static int dev_read_ll(const char *patt, int dev_num, long long *value); +static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len); +static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value); +static int vol_read_ll(const char *patt, int dev_num, int vol_id, + long long *value); +static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, + int buf_len); +static char *mkpath(const char *path, const char *name); +static int find_dev_num(struct libubi *lib, const char *node); +static int find_dev_num_vol(struct libubi *lib, const char *node); +static int find_vol_num(struct libubi *lib, int dev_num, const char *node); + +#ifdef __cplusplus +} +#endif + +#endif /* !__LIBUBI_INT_H__ */ diff --git a/ubi-utils/src/libubimirror.c b/ubi-utils/src/libubimirror.c index e5715fc..d8ea548 100644 --- a/ubi-utils/src/libubimirror.c +++ b/ubi-utils/src/libubimirror.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include "ubimirror.h" #define COMPARE_BUF_SIZE (128 * 1024) @@ -207,11 +207,11 @@ ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size, fd_out = -1; } err: - if (ulib != NULL) - ubi_close(&ulib); - if (fd_in != -1) - ubi_vol_close(fd_in); if (fd_out != -1) ubi_vol_close(fd_out); + if (fd_in != -1) + ubi_vol_close(fd_in); + if (ulib != NULL) + ubi_close(&ulib); return rc; } diff --git a/ubi-utils/src/libubiold.c b/ubi-utils/src/libubiold.c index da4919b..0ff8bae 100644 --- a/ubi-utils/src/libubiold.c +++ b/ubi-utils/src/libubiold.c @@ -36,9 +36,9 @@ #include #include -#include "libubi.h" -#include "libubi_int.h" -#include "libubi_sysfs.h" +#include "libubiold.h" +#include "libubiold_int.h" +#include "libubiold_sysfs.h" /** * struct ubi_lib - UBI library descriptor. diff --git a/ubi-utils/src/libubiold_sysfs.c b/ubi-utils/src/libubiold_sysfs.c index 95fd3de..c4860f6 100644 --- a/ubi-utils/src/libubiold_sysfs.c +++ b/ubi-utils/src/libubiold_sysfs.c @@ -33,7 +33,7 @@ #include #include "config.h" -#include "libubi_int.h" +#include "libubiold_int.h" int sysfs_read_data(const char *file, void *buf, int len) diff --git a/ubi-utils/src/pddcustomize.c b/ubi-utils/src/pddcustomize.c index 764f2e7..a86e942 100644 --- a/ubi-utils/src/pddcustomize.c +++ b/ubi-utils/src/pddcustomize.c @@ -41,7 +41,7 @@ #include "bootenv.h" #include "error.h" #include "example_ubi.h" -#include "libubi.h" +#include "libubiold.h" #include "ubimirror.h" #define PROGRAM_VERSION "1.4" diff --git a/ubi-utils/src/reader.c b/ubi-utils/src/reader.c index 7935a15..0ea8c6d 100644 --- a/ubi-utils/src/reader.c +++ b/ubi-utils/src/reader.c @@ -142,6 +142,7 @@ read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw, char tmp_str[PFI_KEYWORD_LEN]; bootenv_list_t raw_start_list = NULL; pfi_raw_t res; + size_t size; res = (pfi_raw_t) malloc(sizeof(struct pfi_raw)); if (!res) @@ -178,8 +179,9 @@ read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw, } rc = bootenv_list_to_num_vector(raw_start_list, - (void *) &(res->starts_size), - &(res->starts)); + &size, &(res->starts)); + res->starts_size = size; + if (rc != 0) { EBUF_PFI("Cannot create numeric value array: %s", tmp_str); goto err; @@ -209,6 +211,7 @@ read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, bootenv_list_t ubi_name_list = NULL; pfi_ubi_t res; uint32_t i; + size_t size; res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi)); if (!res) @@ -247,8 +250,9 @@ read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, goto err; } - rc = bootenv_list_to_num_vector(ubi_id_list, (void *) &(res->ids_size), + rc = bootenv_list_to_num_vector(ubi_id_list, &size, &(res->ids)); + res->ids_size = size; if (rc != 0) { EBUF_PFI("Cannot create numeric value array: %s", tmp_str); goto err; @@ -299,8 +303,9 @@ read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi, EBUF_PFI("Cannot translate PFI value: %s", tmp_str); goto err; } - rc = bootenv_list_to_vector(ubi_name_list, (void *) &(res->names_size), + rc = bootenv_list_to_vector(ubi_name_list, &size, &(tmp_names)); + res->names_size = size; if (rc != 0) { EBUF_PFI("Cannot create string array: %s", tmp_str); goto err; diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c index 879dcb6..1368671 100644 --- a/ubi-utils/src/ubimkvol.c +++ b/ubi-utils/src/ubimkvol.c @@ -28,6 +28,7 @@ * 1.2 Reworked the user-interface to use argp. * 1.3 Removed argp because we want to use uClibc. * 1.4 Minor cleanups + * 1.5 Use a different libubi */ #include @@ -40,7 +41,7 @@ #include #include -#define PROGRAM_VERSION "1.4" +#define PROGRAM_VERSION "1.5" /* * The variables below are set by command line arguments. @@ -53,6 +54,7 @@ struct args { int alignment; char *name; int nlen; + char node[256]; /* special stuff needed to get additional arguments */ char *arg1; @@ -69,7 +71,7 @@ static struct args myargs = { .nlen = 0, }; -static int param_sanity_check(struct args *args, ubi_lib_t lib); +static int param_sanity_check(struct args *args, libubi_t libubi); static char doc[] = "\nVersion: " PROGRAM_VERSION "\n\t" BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n" @@ -177,6 +179,7 @@ parse_opt(int argc, char **argv, struct args *args) "\"%s\"\n", optarg); goto out; } + sprintf(args->node, "/dev/ubi%d", args->devn); break; case 'n': /* --volid= */ args->vol_id = strtoul(optarg, &endp, 0); @@ -224,7 +227,7 @@ parse_opt(int argc, char **argv, struct args *args) return -1; } -static int param_sanity_check(struct args *args, ubi_lib_t lib) +static int param_sanity_check(struct args *args, libubi_t libubi) { int err, len; struct ubi_info ubi; @@ -239,7 +242,7 @@ static int param_sanity_check(struct args *args, ubi_lib_t lib) goto out; } - err = ubi_get_info(lib, &ubi); + err = ubi_get_info(libubi, &ubi); if (err) return -1; @@ -264,7 +267,8 @@ out: int main(int argc, char * const argv[]) { int err; - ubi_lib_t lib; + libubi_t libubi; + struct ubi_mkvol_request req; err = parse_opt(argc, (char **)argv, &myargs); if (err) { @@ -278,21 +282,26 @@ int main(int argc, char * const argv[]) return -1; } - err = ubi_open(&lib); - if (err) { + libubi = libubi_open(); + if (libubi == NULL) { perror("Cannot open libubi"); return -1; } - err = param_sanity_check(&myargs, lib); + err = param_sanity_check(&myargs, libubi); if (err) { perror("Input parameters check"); fprintf(stderr, "Use -h option for help\n"); goto out_libubi; } - err = ubi_mkvol(lib, myargs.devn, myargs.vol_id, myargs.vol_type, - myargs.bytes, myargs.alignment, myargs.name); + req.vol_id = myargs.vol_id; + req.alignment = myargs.alignment; + req.bytes = myargs.bytes; + req.vol_type = myargs.vol_type; + req.name = myargs.name; + + err = ubi_mkvol(libubi, myargs.node, &req); if (err < 0) { perror("Cannot create volume"); fprintf(stderr, " err=%d\n", err); @@ -304,10 +313,10 @@ int main(int argc, char * const argv[]) "dynamic" : "static", name); */ myargs.vol_id = err; - ubi_close(&lib); + libubi_close(libubi); return 0; out_libubi: - ubi_close(&lib); + libubi_close(libubi); return -1; } diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c index f458e8a..f32cbe0 100644 --- a/ubi-utils/src/ubirmvol.c +++ b/ubi-utils/src/ubirmvol.c @@ -25,6 +25,7 @@ * 1.1 Reworked the userinterface to use argp. * 1.2 Removed argp because we want to use uClibc. * 1.3 Minor cleanups + * 1.4 Use a different libubi */ #include @@ -37,7 +38,7 @@ #include #include -#define PROGRAM_VERSION "1.3" +#define PROGRAM_VERSION "1.4" /* * The below variables are set by command line options. @@ -45,6 +46,7 @@ struct args { int devn; int vol_id; + char node[256]; /* special stuff needed to get additional arguments */ char *arg1; @@ -59,7 +61,7 @@ static struct args myargs = { .options = NULL, }; -static int param_sanity_check(struct args *args, ubi_lib_t lib); +static int param_sanity_check(struct args *args, libubi_t libubi); static char doc[] = "\nVersion: " PROGRAM_VERSION "\n\t" BUILD_OS" "BUILD_CPU" at "__DATE__" "__TIME__"\n" @@ -118,6 +120,7 @@ parse_opt(int argc, char **argv, struct args *args) "\"%s\"\n", optarg); goto out; } + sprintf(args->node, "/dev/ubi%d", args->devn); break; case 'n': /* --volid= */ args->vol_id = strtoul(optarg, &endp, 0); @@ -156,7 +159,7 @@ parse_opt(int argc, char **argv, struct args *args) return -1; } -static int param_sanity_check(struct args *args, ubi_lib_t lib) +static int param_sanity_check(struct args *args, libubi_t libubi) { int err; struct ubi_info ubi; @@ -166,7 +169,7 @@ static int param_sanity_check(struct args *args, ubi_lib_t lib) goto out; } - err = ubi_get_info(lib, &ubi); + err = ubi_get_info(libubi, &ubi); if (err) return -1; @@ -185,7 +188,7 @@ out: int main(int argc, char * const argv[]) { int err, old_errno; - ubi_lib_t lib; + libubi_t libubi; err = parse_opt(argc, (char **)argv, &myargs); if (err) @@ -197,20 +200,20 @@ int main(int argc, char * const argv[]) return -1; } - err = ubi_open(&lib); - if (err) { + libubi = libubi_open(); + if (libubi == NULL) { perror("Cannot open libubi"); return -1; } - err = param_sanity_check(&myargs, lib); + err = param_sanity_check(&myargs, libubi); if (err) { perror("Input parameters check"); fprintf(stderr, "Use -h option for help\n"); goto out_libubi; } - err = ubi_rmvol(lib, myargs.devn, myargs.vol_id); + err = ubi_rmvol(libubi, myargs.node, myargs.vol_id); old_errno = errno; if (err < 0) { perror("Cannot remove volume"); @@ -218,9 +221,10 @@ int main(int argc, char * const argv[]) goto out_libubi; } + libubi_close(libubi); return 0; out_libubi: - ubi_close(&lib); + libubi_close(libubi); return -1; } diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c index c0b4178..5401eb1 100644 --- a/ubi-utils/src/ubiupdatevol.c +++ b/ubi-utils/src/ubiupdatevol.c @@ -25,6 +25,7 @@ * 1.0 Reworked the userinterface to use argp. * 1.1 Removed argp parsing because we want to use uClib. * 1.2 Minor cleanups + * 1.3 Use a different libubi */ #include @@ -36,14 +37,12 @@ #include #include #include -#include #include -#include #include #include -#define PROGRAM_VERSION "1.2" +#define PROGRAM_VERSION "1.3" #define MAXPATH 1024 #define BUFSIZE 128 * 1024 @@ -174,7 +173,7 @@ parse_opt(int argc, char **argv, struct args *args) * some reason nothing is written. The volume is unusable after this. */ static int -ubi_truncate_volume(struct args *args, int64_t bytes) +ubi_truncate_volume(struct args *args, int64_t bytes,libubi_t libubi) { int rc, ofd; char path[MAXPATH]; @@ -188,7 +187,7 @@ ubi_truncate_volume(struct args *args, int64_t bytes) fprintf(stderr, "Cannot open volume %s\n", path); exit(EXIT_FAILURE); } - rc = ioctl(ofd, UBI_IOCVOLUP, &bytes); + rc = ubi_update_start(libubi, ofd, bytes); old_errno = errno; if (rc < 0) { perror("UBI volume update ioctl"); @@ -220,7 +219,7 @@ static ssize_t ubi_write(int fd, const void *buf, size_t count) } static int -ubi_update_volume(struct args *args) +ubi_update_volume(struct args *args, libubi_t libubi) { int rc, ofd; FILE *ifp = NULL; @@ -263,7 +262,7 @@ ubi_update_volume(struct args *args) exit(EXIT_FAILURE); } - rc = ioctl(ofd, UBI_IOCVOLUP, &bytes); + rc = ubi_update_start(libubi, ofd, bytes); old_errno = errno; if (rc < 0) { perror("UBI volume update ioctl"); @@ -304,24 +303,35 @@ int main(int argc, char *argv[]) { int rc; + libubi_t libubi; parse_opt(argc, argv, &myargs); + libubi = libubi_open(); + if (libubi == NULL) { + perror("Cannot open libubi"); + return -1; + } + if (myargs.truncate) { - rc = ubi_truncate_volume(&myargs, 0LL); + rc = ubi_truncate_volume(&myargs, 0LL, libubi); if (rc < 0) - exit(EXIT_FAILURE); - exit(EXIT_SUCCESS); + goto out_libubi; } - if (myargs.broken_update) { - rc = ubi_truncate_volume(&myargs, 1LL); + else if (myargs.broken_update) { + rc = ubi_truncate_volume(&myargs, 1LL, libubi); if (rc < 0) - exit(EXIT_FAILURE); - exit(EXIT_SUCCESS); + goto out_libubi; + } else { + rc = ubi_update_volume(&myargs, libubi); + if (rc < 0) + goto out_libubi; } - rc = ubi_update_volume(&myargs); - if (rc < 0) - exit(EXIT_FAILURE); - exit(EXIT_SUCCESS); + libubi_close(libubi); + return 0; + +out_libubi: + libubi_close(libubi); + return -1; } -- cgit v1.2.3