From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [U-Boot, 2/2] tools: env: Add support for direct read/write UBI volumes
Date: Tue, 26 Jul 2016 08:36:35 +0200 [thread overview]
Message-ID: <579704F3.3020602@denx.de> (raw)
In-Reply-To: <1462539510-18306-2-git-send-email-m.niestroj@grinn-global.com>
Hello Marcin,
Sorry for the long delay
Am 06.05.2016 um 14:58 schrieb Marcin Niestroj:
> Up to now we were able to read/write environment data from/to UBI
> volumes only indirectly by gluebi driver. This driver creates NAND MTD
> on top of UBI volumes, which is quite a workaroung for this use case.
>
> Add support for direct read/write UBI volumes in order to not use
> obsolete gluebi driver.
>
> Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
> ---
> tools/env/fw_env.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++-
> tools/env/fw_env.config | 8 ++
> 2 files changed, 256 insertions(+), 1 deletion(-)
I tried to apply your patch, but this fails, and I was unsure,
if I could fix it correct... can you please send a new rebased
version?
Thanks!
bye,
Heiko
>
> diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
> index b4b542a..0e977e3 100644
> --- a/tools/env/fw_env.c
> +++ b/tools/env/fw_env.c
> @@ -24,6 +24,7 @@
> #include <sys/ioctl.h>
> #include <sys/stat.h>
> #include <unistd.h>
> +#include <dirent.h>
>
> #ifdef MTD_OLD
> # include <stdint.h>
> @@ -33,6 +34,8 @@
> # include <mtd/mtd-user.h>
> #endif
>
> +#include <mtd/ubi-user.h>
> +
> #include "fw_env.h"
>
> struct common_args common_args;
> @@ -54,6 +57,7 @@ struct envdev_s {
> ulong erase_size; /* device erase size */
> ulong env_sectors; /* number of environment sectors */
> uint8_t mtd_type; /* type of the MTD device */
> + int is_ubi; /* set if we use UBI volume */
> };
>
> static struct envdev_s envdevices[2] =
> @@ -72,6 +76,7 @@ static int dev_current;
> #define DEVESIZE(i) envdevices[(i)].erase_size
> #define ENVSECTORS(i) envdevices[(i)].env_sectors
> #define DEVTYPE(i) envdevices[(i)].mtd_type
> +#define IS_UBI(i) envdevices[(i)].is_ubi
>
> #define CUR_ENVSIZE ENVSIZE(dev_current)
>
> @@ -117,6 +122,229 @@ static unsigned char obsolete_flag = 0;
> #define DEFAULT_ENV_INSTANCE_STATIC
> #include <env_default.h>
>
> +#define UBI_DEV_START "/dev/ubi"
> +#define UBI_SYSFS "/sys/class/ubi"
> +#define UBI_VOL_NAME_PATT "ubi%d_%d"
> +
> +static int is_ubi_devname(const char *devname)
> +{
> + return !strncmp(devname, UBI_DEV_START, sizeof(UBI_DEV_START) - 1);
> +}
> +
> +static int ubi_check_volume_sysfs_name(const char *volume_sysfs_name,
> + const char *volname)
> +{
> + char path[256];
> + FILE *file;
> + char *name;
> + int ret;
> +
> + strcpy(path, UBI_SYSFS "/");
> + strcat(path, volume_sysfs_name);
> + strcat(path, "/name");
> +
> + file = fopen(path, "r");
> + if (!file)
> + return -1;
> +
> + ret = fscanf(file, "%ms", &name);
> + fclose(file);
> + if (ret <= 0 || !name) {
> + fprintf(stderr,
> + "Failed to read from file %s, ret = %d, name = %s\n",
> + path, ret, name);
> + return -1;
> + }
> +
> + if (!strcmp(name, volname)) {
> + free(name);
> + return 0;
> + }
> + free(name);
> +
> + return -1;
> +}
> +
> +static int ubi_get_volnum_by_name(int devnum, const char *volname)
> +{
> + DIR *sysfs_ubi;
> + struct dirent *dirent;
> + int ret;
> + int tmp_devnum;
> + int volnum;
> +
> + sysfs_ubi = opendir(UBI_SYSFS);
> + if (!sysfs_ubi)
> + return -1;
> +
> +#ifdef DEBUG
> + fprintf(stderr, "Looking for volume name \"%s\"\n", volname);
> +#endif
> +
> + while (1) {
> + dirent = readdir(sysfs_ubi);
> + if (!dirent)
> + return -1;
> +
> + ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT,
> + &tmp_devnum, &volnum);
> + if (ret == 2 && devnum == tmp_devnum) {
> + if (ubi_check_volume_sysfs_name(dirent->d_name,
> + volname) == 0)
> + return volnum;
> + }
> + }
> +
> + return -1;
> +}
> +
> +static int ubi_get_devnum_by_devname(const char *devname)
> +{
> + int devnum;
> + int ret;
> +
> + ret = sscanf(devname + sizeof(UBI_DEV_START) - 1, "%d", &devnum);
> + if (ret != 1)
> + return -1;
> +
> + return devnum;
> +}
> +
> +static const char *ubi_get_volume_devname(const char *devname,
> + const char *volname)
> +{
> + char *volume_devname;
> + int volnum;
> + int devnum;
> + int ret;
> +
> + devnum = ubi_get_devnum_by_devname(devname);
> + if (devnum < 0)
> + return NULL;
> +
> + volnum = ubi_get_volnum_by_name(devnum, volname);
> + if (volnum < 0)
> + return NULL;
> +
> + ret = asprintf(&volume_devname, "%s_%d", devname, volnum);
> + if (ret < 0)
> + return NULL;
> +
> +#ifdef DEBUG
> + fprintf(stderr, "Found ubi volume \"%s:%s\" -> %s\n",
> + devname, volname, volume_devname);
> +#endif
> +
> + return volume_devname;
> +}
> +
> +static void ubi_check_dev(unsigned int dev_id)
> +{
> + char *devname = (char *) DEVNAME(dev_id);
> + char *pname;
> + const char *volname = NULL;
> + const char *volume_devname;
> +
> + if (!is_ubi_devname(DEVNAME(dev_id)))
> + return;
> +
> + IS_UBI(dev_id) = 1;
> +
> + for (pname = devname; *pname != '\0'; pname++) {
> + if (*pname == ':') {
> + *pname = '\0';
> + volname = pname + 1;
> + break;
> + }
> + }
> +
> + if (volname) {
> + /* Let's find real volume device name */
> + volume_devname = ubi_get_volume_devname(devname,
> + volname);
> + if (!volume_devname) {
> + fprintf(stderr, "Didn't found ubi volume \"%s\"\n",
> + volname);
> + return;
> + }
> +
> + free(devname);
> + DEVNAME(dev_id) = volume_devname;
> + }
> +}
> +
> +static int ubi_update_start(int fd, int64_t bytes)
> +{
> + if (ioctl(fd, UBI_IOCVOLUP, &bytes))
> + return -1;
> + return 0;
> +}
> +
> +static int ubi_read(int fd, void *buf, size_t count)
> +{
> + ssize_t ret;
> +
> + while (count > 0) {
> + ret = read(fd, buf, count);
> + if (ret > 0) {
> + count -= ret;
> + buf += ret;
> +
> + continue;
> + }
> +
> + if (ret == 0) {
> + /*
> + * Happens in case of too short volume data size. If we
> + * return error status we will fail it will be treated
> + * as UBI device error.
> + *
> + * Leave catching this error to CRC check.
> + */
> + fprintf(stderr, "Warning: end of data on ubi volume\n");
> + return 0;
> + } else if (errno == EBADF) {
> + /*
> + * Happens in case of corrupted volume. The same as
> + * above, we cannot return error now, as we will still
> + * be able to successfully write environment later.
> + */
> + fprintf(stderr, "Warning: corrupted volume?\n");
> + return 0;
> + } else if (errno == EINTR) {
> + continue;
> + }
> +
> + fprintf(stderr, "Cannot read %u bytes from ubi volume, %s\n",
> + (unsigned int) count, strerror(errno));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int ubi_write(int fd, const void *buf, size_t count)
> +{
> + ssize_t ret;
> +
> + while (count > 0) {
> + ret = write(fd, buf, count);
> + if (ret <= 0) {
> + if (ret < 0 && errno == EINTR)
> + continue;
> +
> + fprintf(stderr, "Cannot write %u bytes to ubi volume\n",
> + (unsigned int) count);
> + return -1;
> + }
> +
> + count -= ret;
> + buf += ret;
> + }
> +
> + return 0;
> +}
> +
> static int flash_io (int mode);
> static char *envmatch (char * s1, char * s2);
> static int parse_config (void);
> @@ -997,6 +1225,12 @@ static int flash_write (int fd_current, int fd_target, int dev_target)
> DEVOFFSET (dev_target), DEVNAME (dev_target));
> #endif
>
> + if (IS_UBI(dev_target)) {
> + if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
> + return 0;
> + return ubi_write(fd_target, environment.image, CUR_ENVSIZE);
> + }
> +
> rc = flash_write_buf(dev_target, fd_target, environment.image,
> CUR_ENVSIZE, DEVOFFSET(dev_target),
> DEVTYPE(dev_target));
> @@ -1024,6 +1258,12 @@ static int flash_read (int fd)
> struct stat st;
> int rc;
>
> + if (IS_UBI(dev_current)) {
> + DEVTYPE(dev_current) = MTD_ABSENT;
> +
> + return ubi_read(fd, environment.image, CUR_ENVSIZE);
> + }
> +
> rc = fstat(fd, &st);
> if (rc < 0) {
> fprintf(stderr, "Cannot stat the file %s\n",
> @@ -1236,7 +1476,8 @@ int fw_env_open(void)
> DEVTYPE(!dev_current) == MTD_UBIVOLUME) {
> environment.flag_scheme = FLAG_INCREMENTAL;
> } else if (DEVTYPE(dev_current) == MTD_ABSENT &&
> - DEVTYPE(!dev_current) == MTD_ABSENT) {
> + DEVTYPE(!dev_current) == MTD_ABSENT &&
> + IS_UBI(dev_current) == IS_UBI(!dev_current)) {
> environment.flag_scheme = FLAG_INCREMENTAL;
> } else {
> fprintf (stderr, "Incompatible flash types!\n");
> @@ -1369,6 +1610,12 @@ static int parse_config ()
> HaveRedundEnv = 1;
> #endif
> #endif
> +
> + /* Fills in IS_UBI(), converts DEVNAME() with ubi volume name */
> + ubi_check_dev(0);
> + if (HaveRedundEnv)
> + ubi_check_dev(1);
> +
> if (stat (DEVNAME (0), &st)) {
> fprintf (stderr,
> "Cannot access MTD device %s: %s\n",
> diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
> index 6f216f9..db5498a 100644
> --- a/tools/env/fw_env.config
> +++ b/tools/env/fw_env.config
> @@ -23,3 +23,11 @@
>
> # VFAT example
> #/boot/uboot.env 0x0000 0x4000
> +
> +# UBI volume
> +#/dev/ubi0_0 0x0 0x20000
> +#/dev/ubi0_1 0x0 0x20000
> +
> +# UBI volume by name
> +#/dev/ubi0:env 0x0 0x20000
> +#/dev/ubi0:env-redund 0x0 0x20000
>
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
next prev parent reply other threads:[~2016-07-26 6:36 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-06 12:58 [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
2016-05-06 12:58 ` [U-Boot] [PATCH 2/2] tools: env: Add support for direct read/write UBI volumes Marcin Niestroj
2016-05-20 13:37 ` Marcin Niestroj
2016-07-26 6:36 ` Heiko Schocher [this message]
2016-05-20 13:37 ` [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=579704F3.3020602@denx.de \
--to=hs@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.