[U-Boot] [RFC 2/3] tools/env: Support writing to files

Steve Sakoman
2010-12-04T04:28:52Z

From: Lo?c Minier <loic.minier@linaro.org>

Track st_mode and use it to skip ioctls on file-backed fds. This allows
writing to regular files transparently.

Signed-off-by: Lo?c Minier <loic.minier@linaro.org>
Tested-by: Steve Sakoman <steve.sakoman@linaro.org>
---
tools/env/fw_env.c | 92 ++++++++++++++++++++++++++++++++++-----------------
1 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 75f6a98..d2f9748 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -60,6 +60,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 */
+ mode_t st_mode; /* protection / file type */
};

static struct envdev_s envdevices[2] =
@@ -78,6 +79,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 STMODE(i) envdevices[(i)].st_mode

#define CONFIG_ENV_SIZE ENVSIZE(dev_current)

@@ -633,8 +635,12 @@ int fw_parse_script(char *fname)
* > 0 - block is bad
* < 0 - failed to test
*/
-static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
+static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart,
+ int is_mtd)
{
+ if (!is_mtd)
+ return 0;
+
if (mtd_type == MTD_NANDFLASH) {
int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart);

@@ -661,7 +667,7 @@ static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
* the DEVOFFSET (dev) block. On NOR the loop is only run once.
*/
static int flash_read_buf (int dev, int fd, void *buf, size_t count,
- off_t offset, uint8_t mtd_type)
+ off_t offset, uint8_t mtd_type, int is_mtd)
{
size_t blocklen; /* erase / write length - one block on NAND,
0 on NOR */
@@ -683,7 +689,7 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count,
/* Offset inside a block */
block_seek = offset - blockstart;

- if (mtd_type == MTD_NANDFLASH) {
+ if (!is_mtd || mtd_type == MTD_NANDFLASH) {
/*
* NAND: calculate which blocks we are reading. We have
* to read one block at a time to skip bad blocks.
@@ -707,7 +713,7 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count,

/* This only runs once on NOR flash */
while (processed < count) {
- rc = flash_bad_block (fd, mtd_type, &blockstart);
+ rc = flash_bad_block (fd, mtd_type, &blockstart, is_mtd);
if (rc < 0) /* block test failed */
return -1;

@@ -754,7 +760,7 @@ static int flash_read_buf (int dev, int fd, void *buf, size_t count,
* the whole data at once.
*/
static int flash_write_buf (int dev, int fd, void *buf, size_t count,
- off_t offset, uint8_t mtd_type)
+ off_t offset, uint8_t mtd_type, int is_mtd)
{
void *data;
struct erase_info_user erase;
@@ -812,7 +818,7 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
}

rc = flash_read_buf (dev, fd, data, write_total, erase_offset,
- mtd_type);
+ mtd_type, is_mtd);
if (write_total != rc)
return -1;

@@ -826,7 +832,7 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
data = buf;
}

- if (mtd_type == MTD_NANDFLASH) {
+ if (!is_mtd || mtd_type == MTD_NANDFLASH) {
/*
* NAND: calculate which blocks we are writing. We have
* to write one block@a time to skip bad blocks.
@@ -840,7 +846,7 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,

/* This only runs once on NOR flash */
while (processed < write_total) {
- rc = flash_bad_block (fd, mtd_type, &blockstart);
+ rc = flash_bad_block (fd, mtd_type, &blockstart, is_mtd);
if (rc < 0) /* block test failed */
return rc;

@@ -854,14 +860,16 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
continue;
}

- erase.start = blockstart;
- ioctl (fd, MEMUNLOCK, &erase);
+ if (is_mtd) {
+ erase.start = blockstart;
+ ioctl (fd, MEMUNLOCK, &erase);

- if (ioctl (fd, MEMERASE, &erase) != 0) {
- fprintf (stderr, "MTD erase error on %s: %s\n",
- DEVNAME (dev),
- strerror (errno));
- return -1;
+ if (ioctl (fd, MEMERASE, &erase) != 0) {
+ fprintf (stderr, "MTD erase error on %s: %s\n",
+ DEVNAME (dev),
+ strerror (errno));
+ return -1;
+ }
}

if (lseek (fd, blockstart, SEEK_SET) == -1) {
@@ -880,7 +888,9 @@ static int flash_write_buf (int dev, int fd, void *buf, size_t count,
return -1;
}

- ioctl (fd, MEMLOCK, &erase);
+ if (is_mtd) {
+ ioctl (fd, MEMLOCK, &erase);
+ }

processed += blocklen;
block_seek = 0;
@@ -919,7 +929,8 @@ static int flash_flag_obsolete (int dev, int fd, off_t offset)
return rc;
}

-static int flash_write (int fd_current, int fd_target, int dev_target)
+static int flash_write (int fd_current, int fd_target, int dev_target,
+ int is_mtd)
{
int rc;

@@ -944,7 +955,7 @@ static int flash_write (int fd_current, int fd_target, int dev_target)
#endif
rc = flash_write_buf (dev_target, fd_target, environment.image,
CONFIG_ENV_SIZE, DEVOFFSET (dev_target),
- DEVTYPE(dev_target));
+ DEVTYPE(dev_target), is_mtd);
if (rc < 0)
return rc;

@@ -962,26 +973,32 @@ static int flash_write (int fd_current, int fd_target, int dev_target)
return 0;
}

-static int flash_read (int fd)
+static int flash_read (int fd, int is_mtd)
{
struct mtd_info_user mtdinfo;
int rc;

- rc = ioctl (fd, MEMGETINFO, &mtdinfo);
- if (rc < 0) {
- perror ("Cannot get MTD information");
- return -1;
- }
+ if (is_mtd) {
+ rc = ioctl (fd, MEMGETINFO, &mtdinfo);
+ if (rc < 0) {
+ perror ("Cannot get MTD information");
+ return -1;
+ }

- if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) {
- fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type);
- return -1;
+ if (mtdinfo.type != MTD_NORFLASH &&
+ mtdinfo.type != MTD_NANDFLASH) {
+ fprintf (stderr,
+ "Unsupported flash type %u\n",
+ mtdinfo.type);
+ return -1;
}

- DEVTYPE(dev_current) = mtdinfo.type;
+ DEVTYPE(dev_current) = mtdinfo.type;
+ }

rc = flash_read_buf (dev_current, fd, environment.image, CONFIG_ENV_SIZE,
- DEVOFFSET (dev_current), mtdinfo.type);
+ DEVOFFSET (dev_current), DEVTYPE(dev_current),
+ is_mtd);

return (rc != CONFIG_ENV_SIZE) ? -1 : 0;
}
@@ -989,6 +1006,7 @@ static int flash_read (int fd)
static int flash_io (int mode)
{
int fd_current, fd_target, rc, dev_target;
+ int is_mtd;

/* dev_current: fd_current, erase_current */
fd_current = open (DEVNAME (dev_current), mode);
@@ -999,6 +1017,16 @@ static int flash_io (int mode)
return -1;
}

+ /* Check whether fd is a MTD device, otherwise assume regular file */
+ if (S_ISREG (STMODE (dev_current)))
+ is_mtd = 0;
+ else if (S_ISCHR (STMODE (dev_current)))
+ is_mtd = 1;
+ else
+ fprintf (stderr,
+ "%s has unknown file type: %u\n",
+ DEVNAME (dev_current), STMODE (dev_current));
+
if (mode == O_RDWR) {
if (HaveRedundEnv) {
/* switch to next partition for writing */
@@ -1018,7 +1046,7 @@ static int flash_io (int mode)
fd_target = fd_current;
}

- rc = flash_write (fd_current, fd_target, dev_target);
+ rc = flash_write (fd_current, fd_target, dev_target, is_mtd);

if (HaveRedundEnv) {
if (close (fd_target)) {
@@ -1030,7 +1058,7 @@ static int flash_io (int mode)
}
}
} else {
- rc = flash_read (fd_current);
+ rc = flash_read (fd_current, is_mtd);
}

exit:
@@ -1258,6 +1286,7 @@ static int parse_config ()
DEVNAME (0), strerror (errno));
return -1;
}
+ STMODE(0) = st.st_mode;

if (HaveRedundEnv && stat (DEVNAME (1), &st)) {
fprintf (stderr,
@@ -1265,6 +1294,7 @@ static int parse_config ()
DEVNAME (1), strerror (errno));
return -1;
}
+ STMODE(1) = st.st_mode;
return 0;
}

--
1.7.0.4