diff options
author | Wolfgang Denk <wd@denx.de> | 2010-07-15 22:48:46 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2010-07-15 22:48:46 +0200 |
commit | 93502a5e0adcfc0ce6cf8e3daa7eb9a4f4e53658 (patch) | |
tree | 85bf8677d8e8095ef18453199a99c5e4131d217d /common | |
parent | dce6538f5d21a0def8a4df5328d536abed3e136a (diff) | |
parent | d6f324d03d7829a1da1dee8b60f91b173a3976f0 (diff) | |
download | u-boot-imx-93502a5e0adcfc0ce6cf8e3daa7eb9a4f4e53658.zip u-boot-imx-93502a5e0adcfc0ce6cf8e3daa7eb9a4f4e53658.tar.gz u-boot-imx-93502a5e0adcfc0ce6cf8e3daa7eb9a4f4e53658.tar.bz2 |
Merge branch 'master' of ../master
Diffstat (limited to 'common')
-rw-r--r-- | common/cmd_nand.c | 109 | ||||
-rw-r--r-- | common/env_nand.c | 44 |
2 files changed, 152 insertions, 1 deletions
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index ea80555..84b6272 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -4,6 +4,10 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> * + * Ported 'dynenv' to 'nand env.oob' command + * (C) 2010 Nanometrics, Inc. + * 'dynenv' -- Dynamic environment offset in NAND OOB + * (C) Copyright 2006-2007 OpenMoko, Inc. * Added 16-bit nand support * (C) 2004 Texas Instruments */ @@ -193,6 +197,90 @@ static void do_nand_status(nand_info_t *nand) } #endif +#ifdef CONFIG_ENV_OFFSET_OOB +unsigned long nand_env_oob_offset; + +int do_nand_env_oob(cmd_tbl_t *cmdtp, nand_info_t *nand, + int argc, char * const argv[]) +{ + int ret; + uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; + + char *cmd = argv[1]; + + if (!strcmp(cmd, "get")) { + ret = get_nand_env_oob(nand, &nand_env_oob_offset); + if (ret) + return 1; + + printf("0x%08lx\n", nand_env_oob_offset); + } else if (!strcmp(cmd, "set")) { + ulong addr; + size_t dummy_size; + struct mtd_oob_ops ops; + + if (argc < 3) + goto usage; + + if (arg_off_size(argc - 2, argv + 2, nand, &addr, + &dummy_size) < 0) { + printf("Offset or partition name expected\n"); + return 1; + } + + if (nand->oobavail < ENV_OFFSET_SIZE) { + printf("Insufficient available OOB bytes:\n" + "%d OOB bytes available but %d required for " + "env.oob support\n", + nand->oobavail, ENV_OFFSET_SIZE); + return 1; + } + + if ((addr & (nand->erasesize - 1)) != 0) { + printf("Environment offset must be block-aligned\n"); + return 1; + } + + ops.datbuf = NULL; + ops.mode = MTD_OOB_AUTO; + ops.ooboffs = 0; + ops.ooblen = ENV_OFFSET_SIZE; + ops.oobbuf = (void *) oob_buf; + + oob_buf[0] = ENV_OOB_MARKER; + oob_buf[1] = addr / nand->erasesize; + + ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops); + if (ret) { + printf("Error writing OOB block 0\n"); + return ret; + } + + ret = get_nand_env_oob(nand, &nand_env_oob_offset); + if (ret) { + printf("Error reading env offset in OOB\n"); + return ret; + } + + if (addr != nand_env_oob_offset) { + printf("Verification of env offset in OOB failed: " + "0x%08lx expected but got 0x%08lx\n", + addr, nand_env_oob_offset); + return 1; + } + } else { + goto usage; + } + + return ret; + +usage: + cmd_usage(cmdtp); + return 1; +} + +#endif + static void nand_print_info(int idx) { nand_info_t *nand = &nand_info[idx]; @@ -272,9 +360,21 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && strcmp(cmd, "biterr") != 0 && - strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) + strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 +#ifdef CONFIG_ENV_OFFSET_OOB + && strcmp(cmd, "env.oob") != 0 +#endif + ) goto usage; +#ifdef CONFIG_ENV_OFFSET_OOB + /* this command operates only on the first nand device */ + if (strcmp(cmd, "env.oob") == 0) { + return do_nand_env_oob(cmdtp, &nand_info[0], + argc - 1, argv + 1); + } +#endif + /* the following commands operate on the current device */ if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[nand_curr_device].name) { @@ -502,6 +602,13 @@ U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand, " bring nand to lock state or display locked pages\n" "nand unlock [offset] [size] - unlock section" #endif +#ifdef CONFIG_ENV_OFFSET_OOB + "\n" + "nand env.oob - environment offset in OOB of block 0 of" + " first device.\n" + "nand env.oob set off|partition - set enviromnent offset\n" + "nand env.oob get - get environment offset" +#endif ); static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, diff --git a/common/env_nand.c b/common/env_nand.c index 50bc111..a5e1038 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,38 @@ 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) { + printf("error reading OOB block 0\n"); + return 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"); + return -ENOENT; + } + + return 0; +} +#endif + #ifdef CONFIG_ENV_OFFSET_REDUND void env_relocate_spec (void) { @@ -353,6 +386,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(); |