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 <dan...@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
pgptONynTTpLE.pgp
Description: PGP signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot