[U-Boot] [RFC] tools/env: add support for ubi volume chardev

Daniel Golle daniel at makrotopia.org
Fri May 23 06:12:13 CEST 2014


Hi!

fw_printenv/fw_setenv in tools/env currently doesn't support
readring/writing directly from UBI volumes, which is supported in
U-Boot itself since commit 2b74433f365fa677a60431a80e524b5d8d04e995.

At that time gluebi mtd devices were widely used though never meant to
be more than a legacy-hack. Kconfig clearly states
"Do not enable this unless you use legacy software."
Using gluebi with fw_printenv/fw_setenv is also quite dangerous, as
numbering (and thus device names) of gluebi-emulated mtd devices is
not consistent.

As of today, ubiblock provides a much more conveniant way to access
squashfs filesystems in UBI volumes and was included in linux.git
in commit 9d54c8a33eec78289b1b3f6e10874719c27ce0a7.
Most likely this is going to further reduce the use-cases where gluebi
is needed. ubiblock devices, however, are read-only and cannot be used
for fw_setenv.

In the attempt to build a legacy-free system without gluebi, I added
support for reading/writing the U-Boot environment directly from/to
a UBI volume character device using libubi from mtd-utils
http://git.infradead.org/mtd-utils.git/tree/HEAD:/ubi-utils
The library is currently used only internally by ubi-utils and thus
not installed or available for linking right now.
Can mtd-utils/ubi-utils be changed to install libubi.a and the
required headers so U-Boot's env-tool could link it?

If not, the remaining options are to either clone libubi (or the
needed parts of it) into the U-Boot sources or directly call that bunch
of ioctls in the tool without using libubi at all.
Which of these options would be preferable?

I'm also not clear about how to properly integrate that into U-Boot's
build system and currently use an additional make variable which
allows to select whether or not to build support for UBI volumes.
I tried to implement this in a way that makes it easy to verify that
the existing codepaths are not hurt in case UBI support is disabled.

Thank you for your advise!

Daniel
--


Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 tools/env/Makefile |  5 ++++
 tools/env/fw_env.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/tools/env/Makefile b/tools/env/Makefile
index f5368bc..d006a93 100644
--- a/tools/env/Makefile
+++ b/tools/env/Makefile
@@ -20,6 +20,11 @@ ifeq ($(MTD_VERSION),old)
 HOST_EXTRACFLAGS += -DMTD_OLD
 endif
 
+ifeq ($(UBI),y)
+HOST_EXTRACFLAGS += -DUBI
+HOST_LOADLIBES = "-lubi"
+endif
+
 always := fw_printenv
 hostprogs-y := fw_printenv_unstripped
 
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 30d5b03..5c0acd5 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -29,6 +29,9 @@
 # include <mtd/mtd-user.h>
 #endif
 
+#ifdef UBI
+# include <libubi.h>
+#endif
 #include "fw_env.h"
 
 #include <aes.h>
@@ -809,6 +812,11 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
 	off_t top_of_range;	/* end of the last block we may use */
 	loff_t blockstart;	/* running start of the current block -
 				   MEMGETBADBLOCK needs 64 bits */
+#ifdef UBI
+	libubi_t *libubi = NULL;/* pointer to libubi struct */
+#else
+	void *libubi = NULL;
+#endif
 	int rc;
 
 	/*
@@ -914,7 +922,30 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
 			continue;
 		}
 
-		if (mtd_type != MTD_ABSENT) {
+#ifdef UBI
+		if (mtd_type == MTD_UBIVOLUME) {
+			struct ubi_vol_info volinfo;
+			libubi = libubi_open();
+			if (libubi)
+				rc = !ubi_get_vol_info(libubi,
+					DEVNAME(dev_current), &volinfo);
+			if (libubi && !rc) {
+				erasesize = volinfo.leb_size;
+				int leb = blockstart / erasesize;
+				if (volinfo.type != UBI_STATIC_VOLUME)
+					rc = ubi_leb_change_start(libubi, fd,
+						leb, erasesize);
+				else
+					rc = ubi_update_start(libubi, fd,
+						erasesize);
+			}
+			if (libubi && rc) {
+				libubi_close(libubi);
+				libubi = NULL;
+			}
+		}
+#endif
+		if (!libubi && mtd_type != MTD_ABSENT) {
 			erase.start = blockstart;
 			ioctl(fd, MEMUNLOCK, &erase);
 			/* These do not need an explicit erase cycle */
@@ -931,7 +962,8 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
 			fprintf (stderr,
 				 "Seek error on %s: %s\n",
 				 DEVNAME (dev), strerror (errno));
-			return -1;
+			processed = -1;
+			goto out;
 		}
 
 #ifdef DEBUG
@@ -941,10 +973,11 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
 		if (write (fd, data + processed, erasesize) != erasesize) {
 			fprintf (stderr, "Write error on %s: %s\n",
 				 DEVNAME (dev), strerror (errno));
-			return -1;
+			processed = -1;
+			goto out;
 		}
 
-		if (mtd_type != MTD_ABSENT)
+		if (!libubi && mtd_type != MTD_ABSENT)
 			ioctl(fd, MEMLOCK, &erase);
 
 		processed  += erasesize;
@@ -955,6 +988,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
 	if (write_total > count)
 		free (data);
 
+out:
+	if (libubi)
+		libubi_close(libubi);
 	return processed;
 }
 
@@ -1066,12 +1102,8 @@ static int flash_read (int fd)
 
 	if (S_ISCHR(st.st_mode)) {
 		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
-		if (rc < 0) {
-			fprintf(stderr, "Cannot get MTD information for %s\n",
-				DEVNAME(dev_current));
-			return -1;
-		}
-		if (mtdinfo.type != MTD_NORFLASH &&
+		if (!rc &&
+		    mtdinfo.type != MTD_NORFLASH &&
 		    mtdinfo.type != MTD_NANDFLASH &&
 		    mtdinfo.type != MTD_DATAFLASH &&
 		    mtdinfo.type != MTD_UBIVOLUME) {
@@ -1079,6 +1111,28 @@ static int flash_read (int fd)
 				 mtdinfo.type, DEVNAME(dev_current));
 			return -1;
 		}
+#ifdef UBI
+		if (rc) {
+			libubi_t *libubi;
+			struct ubi_vol_info volinfo;
+			libubi = libubi_open();
+			if (!libubi)
+				return -ENOMEM;
+
+			rc = ubi_get_vol_info(libubi, DEVNAME(dev_current),
+						&volinfo);
+			if (rc) {
+				libubi_close(libubi);
+				return -ENODEV;
+			}
+			memset(&mtdinfo, 0, sizeof(mtdinfo));
+			mtdinfo.type = MTD_UBIVOLUME;
+			mtdinfo.size = volinfo.data_bytes;
+			mtdinfo.erasesize = volinfo.leb_size;
+			mtdinfo.writesize = volinfo.leb_size;
+			libubi_close(libubi);
+		}
+#endif
 	} else {
 		memset(&mtdinfo, 0, sizeof(mtdinfo));
 		mtdinfo.type = MTD_ABSENT;
-- 
1.9.3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140523/18f4de37/attachment.pgp>


More information about the U-Boot mailing list