From 134afc5596a7d270923c65e09129d63c39caecfe Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Wed, 3 Nov 2010 11:14:06 +0100 Subject: Rework env_emmc Use TOC functionality instead of hardcoded environment addresses to make it easier to move the U-boot environment configuration to other locations in the flash memory. ST-Ericsson ID: 270847 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-10009 Change-Id: If70d56587d47afdc60a2e50e85d0de13cdf556cc Signed-off-by: Ulf Hansson Signed-off-by: Sebastian Rasmussen Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/7761 Reviewed-by: Simon SJOLANDER Reviewed-by: Michael BRANDT Reviewed-by: Patrik RYD Reviewed-by: Mikael GULLBERG Tested-by: Patrik RYD --- common/env_emmc.c | 310 ++++++++++++++++-------------------------------------- 1 file changed, 90 insertions(+), 220 deletions(-) (limited to 'common') diff --git a/common/env_emmc.c b/common/env_emmc.c index 0d0c1c3e1..76adcb831 100755 --- a/common/env_emmc.c +++ b/common/env_emmc.c @@ -1,267 +1,137 @@ /* - * Copyright (C) ST-Ericsson SA 2009 + * Copyright (C) ST-Ericsson SA 2010 * - * See file CREDITS for list of people who contributed to this - * project. + * Author: Ulf Hansson for + * ST-Ericsson * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * License terms: GNU General Public License (GPL), version 2. */ -/* #define DEBUG */ #include - -#if defined(CONFIG_ENV_IS_IN_EMMC) /* Environment is in EMMC Flash */ - -#include #include -#include -#include +#include #include -#if defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_EMMC) -#define CMD_SAVEENV -#elif defined(CONFIG_ENV_OFFSET_REDUND) -#error Cannot use CONFIG_ENV_OFFSET_REDUND without CONFIG_CMD_ENV & CONFIG_CMD_EMMC -#endif - -#if defined(CONFIG_ENV_SIZE_REDUND) && (CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE) -#error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE -#endif - -#ifdef CONFIG_INFERNO -#error CONFIG_INFERNO not supported yet -#endif - -/* references to names in env_common.c */ -extern uchar default_environment[]; -extern int default_environment_size; - -char * env_name_spec = "EMMC"; - +DECLARE_GLOBAL_DATA_PTR; -#ifdef ENV_IS_EMBEDDED -extern uchar environment[]; -env_t *env_ptr = (env_t *)(&environment[0]); -#else /* ! ENV_IS_EMBEDDED */ +/* global var allocated in env_common when doing env_relocate */ env_t *env_ptr = 0; -#endif /* ENV_IS_EMBEDDED */ +/* global var used from cmd_nvedit when saveenv */ +char *env_name_spec = "EMMC"; -DECLARE_GLOBAL_DATA_PTR; - -uchar env_get_char_spec (int index) +/* global funtion used from env_common */ +uchar env_get_char_spec(int index) { return ( *((uchar *)(gd->env_addr + index)) ); } -static int emmc_read_write(u32 byte_offset, void *read_buffer, - u32 size, u32 write) +/* global function called before mmc_initialize */ +int env_init(void) { - int i; - u32 xferred_bytes; - struct mmc *boot_dev = NULL; - u32 blkcnt; - - for (i = 0;; i++) { - boot_dev = find_mmc_device(i); - if (!boot_dev) - return -1; - if (!strcmp(boot_dev->name, env_name_spec)) - break; - } - - if (write) { - blkcnt = size/boot_dev->write_bl_len; - if (size && !blkcnt) - blkcnt++; - xferred_bytes = - boot_dev->block_dev.block_write(i, - byte_offset/boot_dev->write_bl_len, - blkcnt, - (u_char *)read_buffer); - xferred_bytes *= boot_dev->write_bl_len; - } else { - blkcnt = size/boot_dev->read_bl_len; - if (size && !blkcnt) - blkcnt++; - xferred_bytes = - boot_dev->block_dev.block_read(i, - byte_offset/boot_dev->read_bl_len, - blkcnt, - (u_char *)read_buffer); - xferred_bytes *= boot_dev->read_bl_len; - } - debug("emmc read write:requested:0x%x,done:0x%x", size, xferred_bytes); - return xferred_bytes; + set_default_env(); + return 0; } - -/* this is called before nand_init() - * so we can't read Nand to validate env data. - * Mark it OK for now. env_relocate() in env_common.c - * will call our relocate function which will does - * the real validation. - * - * When using a eMMC boot image (like sequoia_nand), the environment - * can be embedded or attached to the U-Boot image in eMMC flash. This way - * the SPL loads not only the U-Boot image from eMMC but also the - * environment. - */ -int env_init(void) +/* global function called from cmd_nvedit */ +#ifdef CONFIG_CMD_SAVEENV +int saveenv(void) { -#if defined(ENV_IS_EMBEDDED) - ulong total; - int crc1_ok = 0, crc2_ok = 0; - env_t *tmp_env1, *tmp_env2; - - total = CONFIG_ENV_SIZE; - - tmp_env1 = env_ptr; - tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE); + int ret; + struct mmc *mmc_dev; + u32 offset; + u32 size; + u32 loadaddr; + u32 blkcnt; - crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); - crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); + printf("Writing to EMMC... "); - if (!crc1_ok && !crc2_ok) - gd->env_valid = 0; - else if(crc1_ok && !crc2_ok) - gd->env_valid = 1; - else if(!crc1_ok && crc2_ok) - gd->env_valid = 2; - else { - #ifdef CONFIG_REDUNDAND_ENVIRONMENT - /* both ok - check serial */ - if(tmp_env1->flags == 255 && tmp_env2->flags == 0) - gd->env_valid = 2; - else if(tmp_env2->flags == 255 && tmp_env1->flags == 0) - gd->env_valid = 1; - else if(tmp_env1->flags > tmp_env2->flags) - gd->env_valid = 1; - else if(tmp_env2->flags > tmp_env1->flags) - gd->env_valid = 2; - else /* flags are equal - almost impossible */ - #endif - gd->env_valid = 1; + mmc_dev = find_mmc_device(CONFIG_EMMC_DEV_NUM); + if (!mmc_dev) { + printf("emmc device not found, so env not saved!\n"); + return 1; } - if (gd->env_valid == 1) - env_ptr = tmp_env1; - else if (gd->env_valid == 2) - env_ptr = tmp_env2; -#else /* ENV_IS_EMBEDDED */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; -#endif /* ENV_IS_EMBEDDED */ - - return (0); -} + ret = get_entry_info_toc(&mmc_dev->block_dev, + CONFIG_ENV_TOC_NAME, + &offset, + &size, + &loadaddr); + if (ret) { + printf("env address not found, so env not saved!\n"); + return 1; + } -#ifdef CMD_SAVEENV -int saveenv(void) -{ - int ret = 0; + if (size != CONFIG_ENV_SIZE) { + printf("env size mismatch, so env not saved!\n"); + return 1; + } - puts ("Writing to EMMC... "); env_crc_update(); - ret = emmc_read_write(CONFIG_ENV_OFFSET_START, (void *) env_ptr, - CONFIG_ENV_SIZE, 1); - if (ret != CONFIG_ENV_SIZE) - puts("error in saving environment\n"); - else - puts("done\n"); + blkcnt = (size + mmc_dev->write_bl_len - 1) / mmc_dev->write_bl_len; + ret = mmc_dev->block_dev.block_write(mmc_dev->block_dev.dev, + offset / mmc_dev->write_bl_len, + blkcnt, + (void *)env_ptr); + if (ret != blkcnt) { + printf("env write failed, so env not saved!\n"); + return 1; + } - return ret; + printf("done\n"); + return 0; } -#endif /* CMD_SAVEENV */ -#ifdef CONFIG_ENV_OFFSET_REDUND +#endif + +/* global function called from env_common when doing env_relocate */ void env_relocate_spec (void) { -#if !defined(ENV_IS_EMBEDDED) - ulong total; - int crc1_ok = 0, crc2_ok = 0; - env_t *tmp_env1, *tmp_env2; - - total = CONFIG_ENV_SIZE; - - tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE); - tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE); - - emmc_read_write(CONFIG_ENV_OFFSET_START, (void *) tmp_env1, total, 0); - emmc_read_write(CONFIG_ENV_OFFSET_START, (void *) tmp_env2, total, 0); - - crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); - crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); - - if(!crc1_ok && !crc2_ok) - return set_default_env(); - else if(crc1_ok && !crc2_ok) - gd->env_valid = 1; - else if(!crc1_ok && crc2_ok) - gd->env_valid = 2; - else { - /* both ok - check serial */ - if(tmp_env1->flags == 255 && tmp_env2->flags == 0) - gd->env_valid = 2; - else if(tmp_env2->flags == 255 && tmp_env1->flags == 0) - gd->env_valid = 1; - else if(tmp_env1->flags > tmp_env2->flags) - gd->env_valid = 1; - else if(tmp_env2->flags > tmp_env1->flags) - gd->env_valid = 2; - else /* flags are equal - almost impossible */ - gd->env_valid = 1; + int ret; + struct mmc *mmc_dev; + u32 offset; + u32 size; + u32 loadaddr; + u32 blkcnt; + mmc_dev = find_mmc_device(CONFIG_EMMC_DEV_NUM); + if (!mmc_dev) { + printf("env emmc device not found, so setting default env!\n"); + goto err; } - free(env_ptr); - if(gd->env_valid == 1) { - env_ptr = tmp_env1; - free(tmp_env2); - } else { - env_ptr = tmp_env2; - free(tmp_env1); + ret = get_entry_info_toc(&mmc_dev->block_dev, + CONFIG_ENV_TOC_NAME, + &offset, + &size, + &loadaddr); + if (ret) { + printf("env not found, so setting default env!\n"); + goto err; } -#endif /* ! ENV_IS_EMBEDDED */ -} -#else /* ! CONFIG_ENV_OFFSET_REDUND */ -void env_relocate_spec (void) -{ -#if !defined(ENV_IS_EMBEDDED) - int ret; - - ret = emmc_read_write(CONFIG_ENV_OFFSET_START, - (void *)env_ptr, CONFIG_ENV_SIZE, 0); + if (size != CONFIG_ENV_SIZE) { + printf("env size mismatch, so setting default env!\n"); + goto err; + } - if (ret != CONFIG_ENV_SIZE) { - printf("env read failed so setting default env\n"); - goto misc; + blkcnt = (size + mmc_dev->read_bl_len - 1) / mmc_dev->read_bl_len; + ret = mmc_dev->block_dev.block_read(mmc_dev->block_dev.dev, + offset / mmc_dev->read_bl_len, + blkcnt, + (void *)env_ptr); + if (ret != blkcnt) { + printf("env read failed, so setting default env!\n"); + goto err; } if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) { - printf("env crc failed so setting default env\n"); - goto misc; + printf("env crc failed, so setting default env!\n"); + goto err; } return; -misc: - return set_default_env(); -#endif /* ! ENV_IS_EMBEDDED */ +err: + set_default_env(); } -#endif /* CONFIG_ENV_OFFSET_REDUND */ -#endif /* CONFIG_ENV_IS_IN_EMMC */ -- cgit v1.2.3