Provide read/write access to U-Boot environment stored in eMMC flash from Linux.

Access to U-Boot environment can be very useful; dual kernel/rootfs images, 
production default values, change kernel bootargs, etc.

Tested with U-Boot 2009.08 and 2013.04 on TQMa28.

Warning! This is not ready for ptxdist mainline inclusion.

Signed-off-by: Martin Fisker <m...@kamstrup.dk>
Signed-off-by: Bruno Thomsen <b...@kamstrup.dk>
---
 ...oot-emmc-support-in-fw_printenv-fw_setenv.patch | 182 +++++++++++++++++++++
 patches/u-boot-2011.12/series                      |   3 +-
 2 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 
patches/u-boot-2011.12/0002-u-boot-emmc-support-in-fw_printenv-fw_setenv.patch

diff --git 
a/patches/u-boot-2011.12/0002-u-boot-emmc-support-in-fw_printenv-fw_setenv.patch
 
b/patches/u-boot-2011.12/0002-u-boot-emmc-support-in-fw_printenv-fw_setenv.patch
new file mode 100644
index 0000000..95916ca
--- /dev/null
+++ 
b/patches/u-boot-2011.12/0002-u-boot-emmc-support-in-fw_printenv-fw_setenv.patch
@@ -0,0 +1,182 @@
+From: Bruno Thomsen <b...@kamstrup.dk>
+Date: Fri, 1 Aug 2014 10:00:16 +0200
+Subject: [RFC] u-boot: emmc support in fw_printenv/fw_setenv
+
+Provide read/write access to U-Boot environment stored in eMMC flash from 
Linux.
+
+Signed-off-by: Martin Fisker <m...@kamstrup.dk>
+Signed-off-by: Bruno Thomsen <b...@kamstrup.dk>
+---
+ tools/env/fw_env.c      | 77 +++++++++++++++++++++++++++++++++----------------
+ tools/env/fw_env.config |  4 +++
+ 2 files changed, 56 insertions(+), 25 deletions(-)
+
+diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
+index 996682e..631a26f 100644
+--- a/tools/env/fw_env.c
++++ b/tools/env/fw_env.c
+@@ -45,6 +45,8 @@
+ 
+ #include "fw_env.h"
+ 
++#define CONFIG_ENV_IS_IN_MMC
++
+ #define WHITESPACE(c) ((c == '\t') || (c == ' '))
+ 
+ #define min(x, y) ({                          \
+@@ -773,10 +775,10 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+ 
+       blocklen = DEVESIZE (dev);
+ 
+-      top_of_range = ((DEVOFFSET(dev) / blocklen) +
+-                                      ENVSECTORS (dev)) * blocklen;
++      top_of_range = (DEVOFFSET(dev) & ~(blocklen - 1)) +
++                                      ENVSECTORS (dev) * blocklen;
+ 
+-      erase_offset = (offset / blocklen) * blocklen;
++      erase_offset = offset & ~(blocklen - 1);
+ 
+       /* Maximum area we may use */
+       erase_len = top_of_range - erase_offset;
+@@ -790,8 +792,7 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+        * to the start of the data, then count bytes of data, and to the
+        * end of the block
+        */
+-      write_total = ((block_seek + count + blocklen - 1) /
+-                                              blocklen) * blocklen;
++      write_total = (block_seek + count + blocklen - 1) & ~(blocklen - 1);
+ 
+       /*
+        * Support data anywhere within erase sectors: read out the complete
+@@ -807,9 +808,9 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+                       return -1;
+               }
+ 
+-              rc = flash_read_buf (dev, fd, data, write_total, erase_offset,
+-                                   mtd_type);
+-              if (write_total != rc)
++              rc = flash_read_buf (dev, fd, data, CONFIG_ENV_SIZE,
++                                      DEVOFFSET(dev_current), mtd_type);
++              if (CONFIG_ENV_SIZE != rc)
+                       return -1;
+ 
+               /* Overwrite the old environment */
+@@ -835,22 +836,27 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+       erase.length = erasesize;
+ 
+       /* This only runs once on NOR flash and SPI-dataflash */
++      int loopcount = 0;
+       while (processed < write_total) {
+-              rc = flash_bad_block (fd, mtd_type, &blockstart);
+-              if (rc < 0)             /* block test failed */
+-                      return rc;
+-
+-              if (blockstart + erasesize > top_of_range) {
+-                      fprintf (stderr, "End of range reached, aborting\n");
+-                      return -1;
+-              }
++              loopcount++;
++              if(mtd_type != MTD_ABSENT)
++              {
++                      rc = flash_bad_block (fd, mtd_type, &blockstart);
++                      if (rc < 0)             /* block test failed */
++                              return rc;
++
++                      if (blockstart + erasesize > top_of_range) {
++                              fprintf (stderr, "End of range reached, 
aborting\n");
++                              return -1;
++                      }
+ 
+-              if (rc) {               /* block is bad */
+-                      blockstart += blocklen;
+-                      continue;
++                      if (rc) {               /* block is bad */
++                              blockstart += blocklen;
++                              continue;
++                      }
+               }
+-
+               erase.start = blockstart;
++#ifndef CONFIG_ENV_IS_IN_MMC
+               ioctl (fd, MEMUNLOCK, &erase);
+ 
+               /* Dataflash does not need an explicit erase cycle */
+@@ -861,7 +867,7 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+                                        strerror (errno));
+                               return -1;
+                       }
+-
++#endif
+               if (lseek (fd, blockstart, SEEK_SET) == -1) {
+                       fprintf (stderr,
+                                "Seek error on %s: %s\n",
+@@ -870,17 +876,34 @@ static int flash_write_buf (int dev, int fd, void *buf, 
size_t count,
+               }
+ 
+ #ifdef DEBUG
+-              printf ("Write 0x%x bytes at 0x%llx\n", erasesize, blockstart);
++              printf ("Write 0x%x bytes at 0x%llx\n", write_total, 
blockstart);
++              printf("erasesize %d\n", erasesize);
++              printf("count %d\n", count);
++              printf("writeTotal %d\n", write_total);
++              printf("processed %d\n", processed);
++              printf("loopcount %d\n", loopcount);
++              printf("blocklen %d\n", blocklen);
++#endif
++#ifdef CONFIG_ENV_IS_IN_MMC
++              size_t bytesWritten = write (fd, data + processed, write_total);
++              if (bytesWritten != write_total) {
++#else
++              size_t bytesWritten = write (fd, data + processed, erasesize);
++              if (bytesWritten != erasesize) {
+ #endif
+-              if (write (fd, data + processed, erasesize) != erasesize) {
+                       fprintf (stderr, "Write error on %s: %s\n",
+                                DEVNAME (dev), strerror (errno));
+                       return -1;
+               }
+ 
++#ifndef CONFIG_ENV_IS_IN_MMC
+               ioctl (fd, MEMLOCK, &erase);
+-
++#endif
++#ifdef CONFIG_ENV_IS_IN_MMC
++              processed  += bytesWritten;
++#else
+               processed  += blocklen;
++#endif
+               block_seek = 0;
+               blockstart += blocklen;
+       }
+@@ -964,7 +987,7 @@ static int flash_read (int fd)
+ {
+       struct mtd_info_user mtdinfo;
+       int rc;
+-
++#ifndef CONFIG_ENV_IS_IN_MMC
+       rc = ioctl (fd, MEMGETINFO, &mtdinfo);
+       if (rc < 0) {
+               perror ("Cannot get MTD information");
+@@ -982,6 +1005,10 @@ static int flash_read (int fd)
+ 
+       rc = flash_read_buf (dev_current, fd, environment.image, 
CONFIG_ENV_SIZE,
+                            DEVOFFSET (dev_current), mtdinfo.type);
++#else
++      rc = flash_read_buf (dev_current, fd, environment.image, 
CONFIG_ENV_SIZE,
++                           DEVOFFSET (dev_current), 0);
++#endif
+ 
+       return (rc != CONFIG_ENV_SIZE) ? -1 : 0;
+ }
+diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
+index 8e21d5a..6b45687 100644
+--- a/tools/env/fw_env.config
++++ b/tools/env/fw_env.config
+@@ -17,3 +17,7 @@
+ 
+ # NAND example
+ #/dev/mtd0            0x4000          0x4000          0x20000                 
2
++
++# eMMC example
++# MMC device name       Device offset   Env. size
++#/dev/mmcblk0         0x400           0x1FC00         0x1FC00                 
1
diff --git a/patches/u-boot-2011.12/series b/patches/u-boot-2011.12/series
index eea4611..20733b1 100644
--- a/patches/u-boot-2011.12/series
+++ b/patches/u-boot-2011.12/series
@@ -1,4 +1,5 @@
 # generated by git-ptx-patches
 #tag:base --start-number 1
 0001-tools-Prefer-u-boot-includes-to-system-include-direc.patch
-# 944f1726d2ab9856a3d9b36c7af8e95b  - git-ptx-patches magic
+0002-u-boot-emmc-support-in-fw_printenv-fw_setenv.patch
+# 856c73a788cbb5e251c4dbadfbbf3785  - git-ptx-patches magic
-- 
1.9.1


-- 
ptxdist mailing list
ptxdist@pengutronix.de

Reply via email to