tools: env: Fix format warnings in debug
PATCH 1/2 tools: env: Fix format warnings in debug
Format warnings (-Wformat) were shown in printf() calls after defining DEBUG macro.
Update format string and explicitly cast variables to suppress all warnings.
--- tools/env/fw_env.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
tools/env/fw_env.c +10 -7
@@ -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",
Signature · 1 line
2.8.0
PATCH 1/2 tools: env: Fix format warnings in debug
ping
Quoted 61 lines · Marcin Niestroj
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 <[email protected]>--- tools/env/fw_env.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)tools/env/fw_env.c +10
-7@@ -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",
Signature · 1 line
Marcin Niestroj
PATCH 2/2 tools: env: Add support for direct read/write UBI volumes
In reply to Marcin NiestrojUp 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.
--- tools/env/fw_env.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++- tools/env/fw_env.config | 8 ++ 2 files changed, 256 insertions(+), 1 deletion(-)
tools/env/fw_env.c +248 -1
@@ -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",
tools/env/fw_env.config +8 -0
@@ -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
Signature · 1 line
2.8.0
PATCH 2/2 tools: env: Add support for direct read/write UBI volumes
Quoted 346 lines · 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 <[email protected]>--- tools/env/fw_env.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++- tools/env/fw_env.config | 8 ++ 2 files changed, 256 insertions(+), 1 deletion(-)tools/env/fw_env.c +248
-1@@ -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",tools/env/fw_env.config +8
-0@@ -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
Signature · 1 line
Marcin Niestroj
PATCH 2/2 tools: env: Add support for direct read/write UBI volumes
In reply to Marcin NiestrojHello Marcin,
Sorry for the long delay
Am 06.05.2016 um 14:58 schrieb Marcin Niestroj:
Quoted 4 lines
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.
Quoted 8 lines
Add support for direct read/write UBI volumes in order to not use obsolete gluebi driver.
Signed-off-by Marcin Niestroj <[email protected]>--- 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
Quoted 334 lines
tools/env/fw_env.c +248
-1@@ -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",tools/env/fw_env.config +8
-0@@ -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
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany