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