* [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 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.