* [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug
@ 2016-05-06 12:58 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 ` [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
0 siblings, 2 replies; 5+ messages in thread
From: Marcin Niestroj @ 2016-05-06 12:58 UTC (permalink / raw)
To: u-boot
Format warnings (-Wformat) were shown in printf() calls after defining
DEBUG macro.
Update format string and explicitly cast variables to suppress all
warnings.
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
---
tools/env/fw_env.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 06cf63d..b4b542a 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -649,8 +649,8 @@ static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
if (badblock) {
#ifdef DEBUG
- fprintf (stderr, "Bad block at 0x%llx, "
- "skipping\n", *blockstart);
+ fprintf (stderr, "Bad block at 0x%llx, skipping\n",
+ (unsigned long long) *blockstart);
#endif
return badblock;
}
@@ -737,7 +737,8 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count,
}
#ifdef DEBUG
fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n",
- rc, blockstart + block_seek, DEVNAME(dev));
+ rc, (unsigned long long) blockstart + block_seek,
+ DEVNAME(dev));
#endif
processed += readlen;
readlen = min (blocklen, count - processed);
@@ -835,8 +836,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
if (block_seek + count != write_total) {
if (block_seek != 0)
fprintf(stderr, " and ");
- fprintf(stderr, "0x%lx - 0x%x",
- block_seek + count, write_total - 1);
+ fprintf(stderr, "0x%lx - 0x%lx",
+ (unsigned long) block_seek + count,
+ (unsigned long) write_total - 1);
}
fprintf(stderr, "\n");
#endif
@@ -899,8 +901,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
}
#ifdef DEBUG
- fprintf(stderr, "Write 0x%x bytes at 0x%llx\n", erasesize,
- blockstart);
+ fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n",
+ (unsigned long long) erasesize,
+ (unsigned long long) blockstart);
#endif
if (write (fd, data + processed, erasesize) != erasesize) {
fprintf (stderr, "Write error on %s: %s\n",
--
2.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH 2/2] tools: env: Add support for direct read/write UBI volumes
2016-05-06 12:58 [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
@ 2016-05-06 12:58 ` Marcin Niestroj
2016-05-20 13:37 ` Marcin Niestroj
2016-07-26 6:36 ` [U-Boot] [U-Boot, " Heiko Schocher
2016-05-20 13:37 ` [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
1 sibling, 2 replies; 5+ messages in thread
From: Marcin Niestroj @ 2016-05-06 12:58 UTC (permalink / raw)
To: u-boot
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(-)
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
--
2.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug
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
1 sibling, 0 replies; 5+ messages in thread
From: Marcin Niestroj @ 2016-05-20 13:37 UTC (permalink / raw)
To: u-boot
ping
On 06.05.2016 14:58, Marcin Niestroj wrote:
> Format warnings (-Wformat) were shown in printf() calls after defining
> DEBUG macro.
>
> Update format string and explicitly cast variables to suppress all
> warnings.
>
> Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
> ---
> tools/env/fw_env.c | 17 ++++++++++-------
> 1 file changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
> index 06cf63d..b4b542a 100644
> --- a/tools/env/fw_env.c
> +++ b/tools/env/fw_env.c
> @@ -649,8 +649,8 @@ static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
>
> if (badblock) {
> #ifdef DEBUG
> - fprintf (stderr, "Bad block at 0x%llx, "
> - "skipping\n", *blockstart);
> + fprintf (stderr, "Bad block at 0x%llx, skipping\n",
> + (unsigned long long) *blockstart);
> #endif
> return badblock;
> }
> @@ -737,7 +737,8 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count,
> }
> #ifdef DEBUG
> fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n",
> - rc, blockstart + block_seek, DEVNAME(dev));
> + rc, (unsigned long long) blockstart + block_seek,
> + DEVNAME(dev));
> #endif
> processed += readlen;
> readlen = min (blocklen, count - processed);
> @@ -835,8 +836,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
> if (block_seek + count != write_total) {
> if (block_seek != 0)
> fprintf(stderr, " and ");
> - fprintf(stderr, "0x%lx - 0x%x",
> - block_seek + count, write_total - 1);
> + fprintf(stderr, "0x%lx - 0x%lx",
> + (unsigned long) block_seek + count,
> + (unsigned long) write_total - 1);
> }
> fprintf(stderr, "\n");
> #endif
> @@ -899,8 +901,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
> }
>
> #ifdef DEBUG
> - fprintf(stderr, "Write 0x%x bytes at 0x%llx\n", erasesize,
> - blockstart);
> + fprintf(stderr, "Write 0x%llx bytes at 0x%llx\n",
> + (unsigned long long) erasesize,
> + (unsigned long long) blockstart);
> #endif
> if (write (fd, data + processed, erasesize) != erasesize) {
> fprintf (stderr, "Write error on %s: %s\n",
>
--
Marcin Niestroj
^ permalink raw reply [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH 2/2] tools: env: Add support for direct read/write UBI volumes
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 ` [U-Boot] [U-Boot, " Heiko Schocher
1 sibling, 0 replies; 5+ messages in thread
From: Marcin Niestroj @ 2016-05-20 13:37 UTC (permalink / raw)
To: u-boot
On 06.05.2016 14:58, Marcin Niestroj wrote:
> 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(-)
>
> 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
>
--
Marcin Niestroj
^ permalink raw reply [flat|nested] 5+ messages in thread
* [U-Boot] [U-Boot, 2/2] tools: env: Add support for direct read/write UBI volumes
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
1 sibling, 0 replies; 5+ messages in thread
From: Heiko Schocher @ 2016-07-26 6:36 UTC (permalink / raw)
To: u-boot
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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-07-26 6:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [U-Boot] [U-Boot, " Heiko Schocher
2016-05-20 13:37 ` [U-Boot] [PATCH 1/2] tools: env: Fix format warnings in debug Marcin Niestroj
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox