From patchwork Wed Nov 21 12:59:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 200773 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 17D1F2C0098 for ; Thu, 22 Nov 2012 01:05:07 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 816324A372; Wed, 21 Nov 2012 15:04:51 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ilspijVWDcMj; Wed, 21 Nov 2012 15:04:51 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5FB624A373; Wed, 21 Nov 2012 15:04:24 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6A6B14A02D for ; Wed, 21 Nov 2012 13:59:36 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wa272M8oxMwu for ; Wed, 21 Nov 2012 13:59:34 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from zimbra.vipri.net (zimbra.vipri.net [89.207.250.15]) by theia.denx.de (Postfix) with ESMTP id 21DD34A02C for ; Wed, 21 Nov 2012 13:59:34 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by zimbra.vipri.net (Postfix) with ESMTP id 4EF0A21C005 for ; Wed, 21 Nov 2012 13:57:36 +0100 (CET) X-Virus-Scanned: amavisd-new at zimbra.vipri.net Received: from zimbra.vipri.net ([127.0.0.1]) by localhost (zimbra.vipri.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Rz+QxcX0wP5w for ; Wed, 21 Nov 2012 13:57:36 +0100 (CET) Received: from phil.computerman.de (host-089-207-255-234.vipri.net [89.207.255.234]) by zimbra.vipri.net (Postfix) with ESMTPSA id CD1CD21C004 for ; Wed, 21 Nov 2012 13:57:35 +0100 (CET) From: Phil Sutter To: u-boot@lists.denx.de Date: Wed, 21 Nov 2012 13:59:19 +0100 Message-Id: <1353502761-12640-2-git-send-email-phil.sutter@viprinet.com> X-Mailer: git-send-email 1.7.12.3 In-Reply-To: <1353502761-12640-1-git-send-email-phil.sutter@viprinet.com> References: <1353502761-12640-1-git-send-email-phil.sutter@viprinet.com> X-Mailman-Approved-At: Wed, 21 Nov 2012 15:04:17 +0100 Subject: [U-Boot] [PATCH 2/4] env_nand.c: support falling back to redundant env when writing X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Without this patch, when the currently chosen environment to be written has bad blocks, saveenv fails completely. Instead, when there is redundant environment fall back to the other copy. Environment reading needs no adjustment, as the fallback logic for incomplete writes applies to this case as well. Signed-off-by: Phil Sutter --- common/env_nand.c | 100 ++++++++++++++++++++++------------------------------ 1 files changed, 42 insertions(+), 58 deletions(-) diff --git a/common/env_nand.c b/common/env_nand.c index 79e8033..895532b 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -168,72 +168,53 @@ int writeenv(size_t offset, u_char *buf) return 0; } -#ifdef CONFIG_ENV_OFFSET_REDUND -static unsigned char env_flags; +typedef struct env_location { + const char *name; + nand_erase_options_t *erase_opts; + loff_t offset; +} env_location_t; -int saveenv(void) +static int erase_and_write_env(env_location_t *location, u_char *env_new) { - env_t env_new; - ssize_t len; - char *res; - int ret = 0; - nand_erase_options_t nand_erase_options; - - memset(&nand_erase_options, 0, sizeof(nand_erase_options)); - nand_erase_options.length = CONFIG_ENV_RANGE; + int ret = 0; - if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) + printf("Erasing %s...\n", location->name); + location->erase_opts->offset = location->offset; + if (nand_erase_opts(&nand_info[0], location->erase_opts)) return 1; - res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); - env_new.flags = ++env_flags; /* increase the serial */ - - if (gd->env_valid == 1) { - puts("Erasing redundant NAND...\n"); - nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND; - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) - return 1; - - puts("Writing to redundant NAND... "); - ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *)&env_new); - } else { - puts("Erasing NAND...\n"); - nand_erase_options.offset = CONFIG_ENV_OFFSET; - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) - return 1; - - puts("Writing to NAND... "); - ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new); - } - if (ret) { + printf("Writing to %s... ", location->name); + if ((ret = writeenv(location->offset, env_new))) puts("FAILED!\n"); - return 1; - } - - puts("done\n"); - - gd->env_valid = gd->env_valid == 2 ? 1 : 2; return ret; } -#else /* ! CONFIG_ENV_OFFSET_REDUND */ + +static unsigned char env_flags; + int saveenv(void) { int ret = 0; ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); ssize_t len; char *res; + int env_idx; nand_erase_options_t nand_erase_options; + env_location_t location[] = {{ + .name = "NAND", + .erase_opts = &nand_erase_options, + .offset = CONFIG_ENV_OFFSET, +#ifdef CONFIG_ENV_OFFSET_REDUND + }, { + .name = "redundant NAND", + .erase_opts = &nand_erase_options, + .offset = CONFIG_ENV_OFFSET_REDUND, +#endif + }}; + memset(&nand_erase_options, 0, sizeof(nand_erase_options)); nand_erase_options.length = CONFIG_ENV_RANGE; - nand_erase_options.offset = CONFIG_ENV_OFFSET; if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) return 1; @@ -244,22 +225,25 @@ int saveenv(void) error("Cannot export environment: errno = %d\n", errno); return 1; } - env_new->crc = crc32(0, env_new->data, ENV_SIZE); - - puts("Erasing Nand...\n"); - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) - return 1; + env_new->crc = crc32(0, env_new->data, ENV_SIZE); +#ifdef CONFIG_ENV_OFFSET_REDUND + env_new->flags = ++env_flags; /* increase the serial */ + env_idx = (gd->env_valid == 1); +#endif - puts("Writing to Nand... "); - if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) { - puts("FAILED!\n"); - return 1; - } + ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); +#ifdef CONFIG_ENV_OFFSET_REDUND + if (ret) { + env_idx = (env_idx + 1) & 1; + ret = erase_and_write_env(&location[env_idx], + (u_char *)env_new); + } else + gd->env_valid = gd->env_valid == 2 ? 1 : 2; +#endif puts("done\n"); return ret; } -#endif /* CONFIG_ENV_OFFSET_REDUND */ #endif /* CMD_SAVEENV */ int readenv(size_t offset, u_char *buf)