From patchwork Fri May 23 04:12:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Golle X-Patchwork-Id: 351733 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 30A1D140086 for ; Fri, 23 May 2014 15:16:20 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 376A04B635; Fri, 23 May 2014 07:16:17 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6DdTLbHTo7sJ; Fri, 23 May 2014 07:16:17 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id EA9AA4B638; Fri, 23 May 2014 07:16:12 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 33CFE4B653 for ; Fri, 23 May 2014 06:29:08 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jnSSGkkNzshE for ; Fri, 23 May 2014 06:29:02 +0200 (CEST) X-Greylist: delayed 993 seconds by postgrey-1.27 at theia; Fri, 23 May 2014 06:28:59 CEST X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from fudo.makrotopia.org (fudo.makrotopia.org [5.135.190.93]) by theia.denx.de (Postfix) with ESMTPS id 11A384B635 for ; Fri, 23 May 2014 06:28:59 +0200 (CEST) Received: from local by fudo.makrotopia.org with esmtpsa (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.80.1) (envelope-from ) id 1WngqG-00045o-UH; Fri, 23 May 2014 06:12:25 +0200 Date: Fri, 23 May 2014 06:12:13 +0200 From: Daniel Golle To: u-boot@lists.denx.de Message-ID: <20140523040658.GA15724@earthship.local> MIME-Version: 1.0 User-Agent: Mutt/1.5.23 (2014-03-12) X-Mailman-Approved-At: Fri, 23 May 2014 07:16:11 +0200 Cc: luka@openwrt.org, artem.bityutskiy@linux.intel.com Subject: [U-Boot] [RFC] tools/env: add support for ubi volume chardev X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 --- 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 #endif +#ifdef UBI +# include +#endif #include "fw_env.h" #include @@ -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;