uboot/common/env_onenand.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2010 DENX Software Engineering
   3 * Wolfgang Denk <wd@denx.de>
   4 *
   5 * (C) Copyright 2005-2009 Samsung Electronics
   6 * Kyungmin Park <kyungmin.park@samsung.com>
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <command.h>
  29#include <environment.h>
  30#include <linux/stddef.h>
  31#include <malloc.h>
  32#include <search.h>
  33#include <errno.h>
  34#include <onenand_uboot.h>
  35
  36#include <linux/mtd/compat.h>
  37#include <linux/mtd/mtd.h>
  38#include <linux/mtd/onenand.h>
  39
  40char *env_name_spec = "OneNAND";
  41
  42#define ONENAND_MAX_ENV_SIZE    4096
  43#define ONENAND_ENV_SIZE(mtd)   (ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE)
  44
  45DECLARE_GLOBAL_DATA_PTR;
  46
  47void env_relocate_spec(void)
  48{
  49        struct mtd_info *mtd = &onenand_mtd;
  50#ifdef CONFIG_ENV_ADDR_FLEX
  51        struct onenand_chip *this = &onenand_chip;
  52#endif
  53        int rc;
  54        size_t retlen;
  55#ifdef ENV_IS_EMBEDDED
  56        char *buf = (char *)&environment;
  57#else
  58        loff_t env_addr = CONFIG_ENV_ADDR;
  59        char onenand_env[ONENAND_MAX_ENV_SIZE];
  60        char *buf = (char *)&onenand_env[0];
  61#endif /* ENV_IS_EMBEDDED */
  62
  63#ifndef ENV_IS_EMBEDDED
  64# ifdef CONFIG_ENV_ADDR_FLEX
  65        if (FLEXONENAND(this))
  66                env_addr = CONFIG_ENV_ADDR_FLEX;
  67# endif
  68        /* Check OneNAND exist */
  69        if (mtd->writesize)
  70                /* Ignore read fail */
  71                mtd->read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
  72                                &retlen, (u_char *)buf);
  73        else
  74                mtd->writesize = MAX_ONENAND_PAGESIZE;
  75#endif /* !ENV_IS_EMBEDDED */
  76
  77        rc = env_import(buf, 1);
  78        if (rc)
  79                gd->env_valid = 1;
  80}
  81
  82int saveenv(void)
  83{
  84        env_t   env_new;
  85        ssize_t len;
  86        char    *res;
  87        struct mtd_info *mtd = &onenand_mtd;
  88#ifdef CONFIG_ENV_ADDR_FLEX
  89        struct onenand_chip *this = &onenand_chip;
  90#endif
  91        loff_t  env_addr = CONFIG_ENV_ADDR;
  92        size_t  retlen;
  93        struct erase_info instr = {
  94                .callback       = NULL,
  95        };
  96
  97        res = (char *)&env_new.data;
  98        len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
  99        if (len < 0) {
 100                error("Cannot export environment: errno = %d\n", errno);
 101                return 1;
 102        }
 103        env_new.crc = crc32(0, env_new.data, ENV_SIZE);
 104
 105        instr.len = CONFIG_ENV_SIZE;
 106#ifdef CONFIG_ENV_ADDR_FLEX
 107        if (FLEXONENAND(this)) {
 108                env_addr = CONFIG_ENV_ADDR_FLEX;
 109                instr.len = CONFIG_ENV_SIZE_FLEX;
 110                instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
 111                                1 : 0;
 112        }
 113#endif
 114        instr.addr = env_addr;
 115        instr.mtd = mtd;
 116        if (mtd->erase(mtd, &instr)) {
 117                printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
 118                return 1;
 119        }
 120
 121        if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
 122                        (u_char *)&env_new)) {
 123                printf("OneNAND: write failed at 0x%llx\n", instr.addr);
 124                return 2;
 125        }
 126
 127        return 0;
 128}
 129
 130int env_init(void)
 131{
 132        /* use default */
 133        gd->env_addr = (ulong)&default_environment[0];
 134        gd->env_valid = 1;
 135
 136        return 0;
 137}
 138