env: add a common env driver for block device
The driver implementation refers to env/mmc.c, the storage media binding to block layer can use it(Nand/Nor Flash...). Support configure: - CONFIG_ENV_OFFSET - CONFIG_ENV_SIZE - CONFIG_ENV_OFFSET_REDUND (optional) - CONFIG_ENV_SIZE_REDUND (optional) - CONFIG_SYS_MMC_ENV_PART (optional) Change-Id: Ibb16f0dd7af1331f454784968fbdc9002f4b769c Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
parent
1712dc5c34
commit
2ba7147f80
|
|
@ -52,9 +52,10 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
!defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \
|
!defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \
|
||||||
!defined(CONFIG_ENV_IS_IN_REMOTE) && \
|
!defined(CONFIG_ENV_IS_IN_REMOTE) && \
|
||||||
!defined(CONFIG_ENV_IS_IN_UBI) && \
|
!defined(CONFIG_ENV_IS_IN_UBI) && \
|
||||||
|
!defined(CONFIG_ENV_IS_IN_BLK_DEV) && \
|
||||||
!defined(CONFIG_ENV_IS_NOWHERE)
|
!defined(CONFIG_ENV_IS_NOWHERE)
|
||||||
# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
|
# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
|
||||||
NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
|
NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI|BLK_DEV} or CONFIG_ENV_IS_NOWHERE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -358,6 +358,40 @@ config ENV_IS_IN_UBI
|
||||||
You will probably want to define these to avoid a really noisy system
|
You will probably want to define these to avoid a really noisy system
|
||||||
when storing the env in UBI.
|
when storing the env in UBI.
|
||||||
|
|
||||||
|
config ENV_IS_IN_BLK_DEV
|
||||||
|
bool "Environment in a block device"
|
||||||
|
depends on !CHAIN_OF_TRUST && CONFIG_BLK
|
||||||
|
help
|
||||||
|
Define this if you have an Block device which you want to use for the
|
||||||
|
environment.
|
||||||
|
|
||||||
|
- CONFIG_ENV_OFFSET:
|
||||||
|
- CONFIG_ENV_SIZE:
|
||||||
|
|
||||||
|
These two #defines specify the offset and size of the environment
|
||||||
|
area within the specified Block device. These two values are in units
|
||||||
|
of bytes, but must be aligned to an Block sector boundary.
|
||||||
|
|
||||||
|
- CONFIG_ENV_OFFSET_REDUND (optional):
|
||||||
|
|
||||||
|
Specifies a second storage area, of CONFIG_ENV_SIZE size, used to
|
||||||
|
hold a redundant copy of the environment data. This provides a
|
||||||
|
valid backup copy in case the other copy is corrupted, e.g. due
|
||||||
|
to a power failure during a "saveenv" operation. This is handled
|
||||||
|
in the same way as CONFIG_ENV_OFFSET.
|
||||||
|
|
||||||
|
- CONFIG_ENV_SIZE_REDUND (optional):
|
||||||
|
|
||||||
|
This value need not be set, even when CONFIG_ENV_OFFSET_REDUND is
|
||||||
|
set. If this value is set, it must be set to the same value as
|
||||||
|
CONFIG_ENV_SIZE.
|
||||||
|
|
||||||
|
- CONFIG_SYS_MMC_ENV_PART (optional):
|
||||||
|
|
||||||
|
Specifies which MMC partition the environment is stored in. If not
|
||||||
|
set, defaults to partition 0, the user area. Common values might be
|
||||||
|
1 (first MMC boot partition), 2 (second MMC boot partition).
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config ENV_AES
|
config ENV_AES
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ obj-$(CONFIG_ENV_IS_IN_SATA) += sata.o
|
||||||
obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o
|
obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o
|
||||||
obj-$(CONFIG_ENV_IS_IN_REMOTE) += remote.o
|
obj-$(CONFIG_ENV_IS_IN_REMOTE) += remote.o
|
||||||
obj-$(CONFIG_ENV_IS_IN_UBI) += ubi.o
|
obj-$(CONFIG_ENV_IS_IN_UBI) += ubi.o
|
||||||
|
obj-$(CONFIG_ENV_IS_IN_BLK_DEV) += env_blk.o
|
||||||
obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o
|
obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ static enum env_location env_get_default_location(void)
|
||||||
return ENVL_SPI_FLASH;
|
return ENVL_SPI_FLASH;
|
||||||
else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
|
else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
|
||||||
return ENVL_UBI;
|
return ENVL_UBI;
|
||||||
|
else if IS_ENABLED(CONFIG_ENV_IS_IN_BLK_DEV)
|
||||||
|
return ENVL_BLK;
|
||||||
else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
|
else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
|
||||||
return ENVL_NOWHERE;
|
return ENVL_NOWHERE;
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,290 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <environment.h>
|
||||||
|
#include <memalign.h>
|
||||||
|
#include <boot_rkimg.h>
|
||||||
|
|
||||||
|
#define __STR(X) #X
|
||||||
|
#define STR(X) __STR(X)
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
int get_env_addr(struct blk_desc *blk_desc, int copy, u32 *env_addr)
|
||||||
|
{
|
||||||
|
s64 offset = CONFIG_ENV_OFFSET;
|
||||||
|
|
||||||
|
#if defined(CONFIG_ENV_OFFSET_REDUND)
|
||||||
|
if (copy)
|
||||||
|
offset = CONFIG_ENV_OFFSET_REDUND;
|
||||||
|
#endif
|
||||||
|
if (offset < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*env_addr = offset;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_env_dev(void)
|
||||||
|
{
|
||||||
|
return CONFIG_SYS_MMC_ENV_DEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYS_MMC_ENV_PART
|
||||||
|
static unsigned char env_org_hwpart;
|
||||||
|
|
||||||
|
int get_env_part(void)
|
||||||
|
{
|
||||||
|
return CONFIG_SYS_MMC_ENV_PART;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *init_blk_hwpart_for_env(struct blk_desc *blk_desc)
|
||||||
|
{
|
||||||
|
enum if_type if_type;
|
||||||
|
const char *devtype;
|
||||||
|
int devnum, devpart, ret;
|
||||||
|
|
||||||
|
devtype = env_get("devtype");
|
||||||
|
devnum = env_get_ulong("devnum", 10, 0);
|
||||||
|
devpart = get_env_part();
|
||||||
|
if_type = if_typename_to_iftype(devtype);
|
||||||
|
|
||||||
|
env_org_hwpart = blk_desc->hwpart;
|
||||||
|
ret = blk_select_hwpart_devnum(if_type, devnum, devpart);
|
||||||
|
if (ret)
|
||||||
|
return "!Partition switch failed";
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fini_blk_hwpart_for_env(void)
|
||||||
|
{
|
||||||
|
enum if_type if_type;
|
||||||
|
const char *devtype;
|
||||||
|
int devnum;
|
||||||
|
|
||||||
|
devtype = env_get("devtype");
|
||||||
|
devnum = env_get_ulong("devnum", 10, 0);
|
||||||
|
if_type = if_typename_to_iftype(devtype);
|
||||||
|
|
||||||
|
blk_select_hwpart_devnum(if_type, devnum, env_org_hwpart);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline const char *init_blk_hwpart_for_env(struct blk_desc *blk_desc)
|
||||||
|
{ return NULL; }
|
||||||
|
static inline void fini_blk_hwpart_for_env(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_SPL_BUILD)
|
||||||
|
static inline int write_env(struct blk_desc *blk_desc, unsigned long size,
|
||||||
|
unsigned long offset, const void *buffer)
|
||||||
|
{
|
||||||
|
uint blk_start, blk_cnt, n;
|
||||||
|
|
||||||
|
blk_start = ALIGN(offset, blk_desc->blksz) / blk_desc->blksz;
|
||||||
|
blk_cnt = ALIGN(size, blk_desc->blksz) / blk_desc->blksz;
|
||||||
|
|
||||||
|
n = blk_dwrite(blk_desc, blk_start, blk_cnt, (u_char *)buffer);
|
||||||
|
|
||||||
|
return (n == blk_cnt) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int env_blk_save(void)
|
||||||
|
{
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
|
||||||
|
struct blk_desc *blk_desc;
|
||||||
|
const char *errmsg = NULL;
|
||||||
|
int ret, copy = 0;
|
||||||
|
u32 offset;
|
||||||
|
|
||||||
|
blk_desc = rockchip_get_bootdev();
|
||||||
|
if (!blk_desc) {
|
||||||
|
puts("Can't find bootdev\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
errmsg = init_blk_hwpart_for_env(blk_desc);
|
||||||
|
if (errmsg) {
|
||||||
|
puts(errmsg);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = env_export(env_new);
|
||||||
|
if (ret)
|
||||||
|
goto fini;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||||
|
if (gd->env_valid == ENV_VALID)
|
||||||
|
copy = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (get_env_addr(blk_desc, copy, &offset)) {
|
||||||
|
ret = 1;
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Writing to %s%s(%s)... ", copy ? "redundant " : "",
|
||||||
|
env_get("devtype"), env_get("devnum"));
|
||||||
|
|
||||||
|
if (write_env(blk_desc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) {
|
||||||
|
puts("failed\n");
|
||||||
|
ret = 1;
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("done\n");
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||||
|
gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fini:
|
||||||
|
fini_blk_hwpart_for_env();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CMD_SAVEENV && !CONFIG_SPL_BUILD */
|
||||||
|
|
||||||
|
static inline int read_env(struct blk_desc *blk_desc, unsigned long size,
|
||||||
|
unsigned long offset, const void *buffer)
|
||||||
|
{
|
||||||
|
uint blk_start, blk_cnt, n;
|
||||||
|
|
||||||
|
blk_start = ALIGN(offset, blk_desc->blksz) / blk_desc->blksz;
|
||||||
|
blk_cnt = ALIGN(size, blk_desc->blksz) / blk_desc->blksz;
|
||||||
|
|
||||||
|
n = blk_dread(blk_desc, blk_start, blk_cnt, (uchar *)buffer);
|
||||||
|
|
||||||
|
return (n == blk_cnt) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||||
|
static int env_blk_load(void)
|
||||||
|
{
|
||||||
|
#if !defined(ENV_IS_EMBEDDED)
|
||||||
|
struct blk_desc *blk_desc;
|
||||||
|
const char *errmsg = NULL;
|
||||||
|
int read1_fail = 0, read2_fail = 0;
|
||||||
|
u32 offset1, offset2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env1, 1);
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env2, 1);
|
||||||
|
|
||||||
|
blk_desc = rockchip_get_bootdev();
|
||||||
|
if (!blk_desc) {
|
||||||
|
puts("Can't find bootdev\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
errmsg = init_blk_hwpart_for_env(blk_desc);
|
||||||
|
if (errmsg) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_env_addr(blk_desc, 0, &offset1) ||
|
||||||
|
get_env_addr(blk_desc, 1, &offset2)) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
|
read1_fail = read_env(blk_desc, CONFIG_ENV_SIZE, offset1, tmp_env1);
|
||||||
|
read2_fail = read_env(blk_desc, CONFIG_ENV_SIZE, offset2, tmp_env2);
|
||||||
|
|
||||||
|
if (read1_fail && read2_fail)
|
||||||
|
puts("*** Error - No Valid Environment Area found\n");
|
||||||
|
else if (read1_fail || read2_fail)
|
||||||
|
puts("*** Warning - some problems detected "
|
||||||
|
"reading environment; recovered successfully\n");
|
||||||
|
|
||||||
|
if (read1_fail && read2_fail) {
|
||||||
|
errmsg = "!bad CRC";
|
||||||
|
ret = -EIO;
|
||||||
|
goto fini;
|
||||||
|
} else if (!read1_fail && read2_fail) {
|
||||||
|
gd->env_valid = ENV_VALID;
|
||||||
|
env_import((char *)tmp_env1, 1);
|
||||||
|
} else if (read1_fail && !read2_fail) {
|
||||||
|
gd->env_valid = ENV_REDUND;
|
||||||
|
env_import((char *)tmp_env2, 1);
|
||||||
|
} else {
|
||||||
|
env_import_redund((char *)tmp_env1, (char *)tmp_env2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
fini:
|
||||||
|
fini_blk_hwpart_for_env();
|
||||||
|
err:
|
||||||
|
if (ret)
|
||||||
|
set_default_env(errmsg);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else /* ! CONFIG_ENV_OFFSET_REDUND */
|
||||||
|
static int env_blk_load(void)
|
||||||
|
{
|
||||||
|
#if !defined(ENV_IS_EMBEDDED)
|
||||||
|
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
|
||||||
|
struct blk_desc *blk_desc;
|
||||||
|
const char *errmsg = NULL;
|
||||||
|
u32 offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
blk_desc = rockchip_get_bootdev();
|
||||||
|
if (!blk_desc) {
|
||||||
|
puts("Can't find bootdev\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
errmsg = init_blk_hwpart_for_env(blk_desc);
|
||||||
|
if (errmsg) {
|
||||||
|
ret = -EIO;
|
||||||
|
puts(errmsg);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_env_addr(blk_desc, 0, &offset)) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_env(blk_desc, CONFIG_ENV_SIZE, offset, buf)) {
|
||||||
|
errmsg = "!read failed";
|
||||||
|
ret = -EIO;
|
||||||
|
goto fini;
|
||||||
|
}
|
||||||
|
|
||||||
|
env_import(buf, 1);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
fini:
|
||||||
|
fini_blk_hwpart_for_env();
|
||||||
|
err:
|
||||||
|
if (ret)
|
||||||
|
set_default_env(errmsg);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ENV_OFFSET_REDUND */
|
||||||
|
|
||||||
|
U_BOOT_ENV_LOCATION(env_blk) = {
|
||||||
|
.location = ENVL_BLK,
|
||||||
|
ENV_NAME("ENV_BLK")
|
||||||
|
.load = env_blk_load,
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
|
.save = env_save_ptr(env_blk_save),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
@ -210,6 +210,7 @@ enum env_location {
|
||||||
ENVL_SPI_FLASH,
|
ENVL_SPI_FLASH,
|
||||||
ENVL_UBI,
|
ENVL_UBI,
|
||||||
ENVL_NOWHERE,
|
ENVL_NOWHERE,
|
||||||
|
ENVL_BLK,
|
||||||
|
|
||||||
ENVL_COUNT,
|
ENVL_COUNT,
|
||||||
ENVL_UNKNOWN,
|
ENVL_UNKNOWN,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue