diff options
author | Ben Gardiner <bengardiner@nanometrics.ca> | 2010-07-05 13:27:07 -0400 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2010-07-12 13:56:46 -0500 |
commit | c9f7351b5bb70d292f6b0baaf0e21366e0b0b163 (patch) | |
tree | 19b4353d9a4c5428b486e19f803c1855107cd76f /common/env_nand.c | |
parent | 67ceefa79b86d9d72b7487005a6a8a61cd6a1d66 (diff) | |
download | u-boot-c9f7351b5bb70d292f6b0baaf0e21366e0b0b163.tar.gz u-boot-c9f7351b5bb70d292f6b0baaf0e21366e0b0b163.tar.xz u-boot-c9f7351b5bb70d292f6b0baaf0e21366e0b0b163.zip |
NAND: environment offset in OOB (CONFIG_ENV_OFFSET_OOB)
This is a re-submission of the patch by Harald Welte
<laforge@openmoko.org> with minor modifications for rebase and changes
as suggested by Scott Wood <scottwood@freescale.com> [1] [2].
This patch enables the environment partition to have a run-time dynamic
location (offset) in the NAND flash. The reason for this is simply that
all NAND flashes have factory-default bad blocks, and a fixed compile
time offset would mean that sometimes the environment partition would
live inside factory bad blocks. Since the number of factory default
blocks can be quite high (easily 1.3MBytes in current standard
components), it is not economic to keep that many spare blocks inside
the environment partition.
With this patch and CONFIG_ENV_OFFSET_OOB enabled, the location of the
environment partition is stored in the out-of-band (OOB) data of the
first block in flash. Since the first block is where most systems boot
from, the vendors guarantee that the first block is not a factory
default block.
This patch introduces the 'nand env.oob' command, which can be called
from the u-boot command line. 'nand env.oob get' reads the address of
the environment partition from the OOB data, 'nand env.oob set
{offset,partition-name}' allows the setting of the marker by specifying
a numeric offset or a partition name.
[1] http://article.gmane.org/gmane.comp.boot-loaders.u-boot/43916
[2] http://article.gmane.org/gmane.comp.boot-loaders.u-boot/79195
Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
Acked-by: Harald Welte <laforge@gnumonks.org>
Diffstat (limited to 'common/env_nand.c')
-rw-r--r-- | common/env_nand.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/common/env_nand.c b/common/env_nand.c index 50bc111a3b..47d9848acb 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -38,6 +38,7 @@ #include <linux/stddef.h> #include <malloc.h> #include <nand.h> +#include <asm/errno.h> #if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_NAND) #define CMD_SAVEENV @@ -284,6 +285,40 @@ int readenv (size_t offset, u_char * buf) return 0; } +#ifdef CONFIG_ENV_OFFSET_OOB +int get_nand_env_oob(nand_info_t *nand, unsigned long *result) +{ + struct mtd_oob_ops ops; + uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; + int ret; + + ops.datbuf = NULL; + ops.mode = MTD_OOB_AUTO; + ops.ooboffs = 0; + ops.ooblen = ENV_OFFSET_SIZE; + ops.oobbuf = (void *) oob_buf; + + ret = nand->read_oob(nand, ENV_OFFSET_SIZE, &ops); + + if (!ret) { + if (oob_buf[0] == ENV_OOB_MARKER) { + *result = oob_buf[1] * nand->erasesize; + } else if (oob_buf[0] == ENV_OOB_MARKER_OLD) { + *result = oob_buf[1]; + } else { + printf("No dynamic environment marker in OOB block 0" + "\n"); + ret = -ENOENT; + goto fail; + } + } else { + printf("error reading OOB block 0\n"); + } +fail: + return ret; +} +#endif + #ifdef CONFIG_ENV_OFFSET_REDUND void env_relocate_spec (void) { @@ -353,6 +388,17 @@ void env_relocate_spec (void) #if !defined(ENV_IS_EMBEDDED) int ret; +#if defined(CONFIG_ENV_OFFSET_OOB) + ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset); + /* If unable to read environment offset from NAND OOB then fall through + * to the normal environment reading code below + */ + if (!ret) + printf("Found Environment offset in OOB..\n"); + else + return use_default(); +#endif + ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); if (ret) return use_default(); |