145 lines
4.0 KiB
Diff
145 lines
4.0 KiB
Diff
From: Hector Palacios <hector.palacios@digi.com>
|
|
Date: Mon, 22 Jan 2018 10:18:18 +0100
|
|
Subject: [PATCH 4/4] tools: env: add support to set dynamic location of
|
|
environment copies
|
|
|
|
A mechanism was added in U-Boot to set the location of environment copies
|
|
dynamically in an shared area. If the config file sets both copies to the
|
|
same offset, a function will be called to set the offset of each copy to
|
|
the first two good NAND sectors within the specified area.
|
|
|
|
The config file should contain the sector size and the number of sectors
|
|
of the area, like in this example:
|
|
|
|
# Device name Offset Size Erase-size No.Blocks
|
|
/dev/mtd1 0x0 0x20000 0x20000 8
|
|
/dev/mtd1 0x0 0x20000 0x20000 8
|
|
|
|
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
|
|
|
https://jira.digi.com/browse/DUB-741
|
|
Signed-off-by: Gonzalo Ruiz <Gonzalo.Ruiz@digi.com>
|
|
---
|
|
tools/env/fw_env.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 87 insertions(+)
|
|
|
|
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
|
|
index b87cd83..041dc1b 100644
|
|
--- a/tools/env/fw_env.c
|
|
+++ b/tools/env/fw_env.c
|
|
@@ -129,6 +129,8 @@ static struct environment environment = {
|
|
|
|
static int have_redund_env;
|
|
static int caam_encryption_flag;
|
|
+static int have_dynamic_env;
|
|
+static off_t top_of_range; /* end of the last block we may use */
|
|
|
|
static unsigned char active_flag = 1;
|
|
/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
|
|
@@ -1031,6 +1033,22 @@ static int flash_read_buf(int dev, int fd, void *buf, size_t count,
|
|
*/
|
|
blocklen = DEVESIZE(dev);
|
|
|
|
+ if (!have_dynamic_env) {
|
|
+ /*
|
|
+ * To calculate the top of the range, we have to use the
|
|
+ * global DEVOFFSET (dev), which can be different from
|
|
+ * offset
|
|
+ */
|
|
+ top_of_range = ((DEVOFFSET(dev) / blocklen) +
|
|
+ ENVSECTORS(dev)) * blocklen;
|
|
+ }
|
|
+
|
|
+ if (offset >= top_of_range) {
|
|
+ /* End of range is reached */
|
|
+ fprintf(stderr, "Too few good blocks within range\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
/* Limit to one block for the first read */
|
|
if (readlen > blocklen - block_seek)
|
|
readlen = blocklen - block_seek;
|
|
@@ -1411,6 +1429,63 @@ static int sysfs_mmcboot_set_protection(const char *device, int value)
|
|
return 0;
|
|
}
|
|
|
|
+static int set_dynamic_location(void)
|
|
+{
|
|
+ int fd, i, nsectors;
|
|
+ loff_t offset, blocksize;
|
|
+ int dev = 0;
|
|
+ int copies = 1;
|
|
+ int rc = 0;
|
|
+
|
|
+ if (have_redund_env)
|
|
+ copies++;
|
|
+
|
|
+ fd = open(DEVNAME(dev), O_RDONLY);
|
|
+ if (fd < 0) {
|
|
+ fprintf(stderr, "Can't open %s: %s\n", DEVNAME(dev),
|
|
+ strerror(errno));
|
|
+ rc = -1;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ /* Set initial block to start looking for environment */
|
|
+ offset = DEVOFFSET(dev);
|
|
+ /* Use variables for common values */
|
|
+ blocksize = DEVESIZE(dev);
|
|
+ /* Look for the number of sectors specified for the primary copy */
|
|
+ nsectors = ENVSECTORS(dev);
|
|
+
|
|
+ for (i = 0; i < nsectors && copies; i++) {
|
|
+ rc = flash_bad_block(fd, DEVTYPE(dev), offset);
|
|
+ if (rc < 0) {
|
|
+ rc = -1;
|
|
+ goto error;
|
|
+ } else if (!rc) {
|
|
+ /*
|
|
+ * Set first good block as primary (no matter if it is
|
|
+ * the other copy. After all, the 'current' copy is
|
|
+ * determined by the active flag.
|
|
+ */
|
|
+ DEVOFFSET(dev) = offset;
|
|
+ copies--;
|
|
+ dev++;
|
|
+ }
|
|
+ offset += blocksize;
|
|
+ }
|
|
+
|
|
+ while (copies) {
|
|
+ /* No good sectors available. Set offset out of bounds */
|
|
+ DEVOFFSET(dev) = offset;
|
|
+ copies--;
|
|
+ dev++;
|
|
+ }
|
|
+ rc = 0;
|
|
+
|
|
+error:
|
|
+ close(fd);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static int flash_io_write(int fd_current)
|
|
{
|
|
int fd_target = -1, rc, dev_target;
|
|
@@ -1586,6 +1661,18 @@ int fw_env_open(struct env_opts *opts)
|
|
environment.data = single->data;
|
|
}
|
|
|
|
+ /*
|
|
+ * Trigger dynamic location of environment if redundant copy has the
|
|
+ * same offset than primary copy.
|
|
+ */
|
|
+ if (have_redund_env && (DEVOFFSET(0) == DEVOFFSET(1))) {
|
|
+ have_dynamic_env = 1;
|
|
+ top_of_range = DEVOFFSET(0) + (ENVSECTORS(0) * DEVESIZE(0));
|
|
+
|
|
+ if (set_dynamic_location() < 0)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
dev_current = 0;
|
|
if (flash_io(O_RDONLY)) {
|
|
ret = -EIO;
|