Allow SCSI to be able to store environment variables. Signed-off-by: Varadarajan Narayanan <quic_var...@quicinc.com> --- v3: s/SCSI_ENV_PART/SCSI_ENV_PART_UUID --- env/Kconfig | 15 +++++- env/Makefile | 1 + env/env.c | 3 ++ env/scsi.c | 115 +++++++++++++++++++++++++++++++++++++++++ include/env_internal.h | 1 + 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 env/scsi.c
diff --git a/env/Kconfig b/env/Kconfig index 9f5ec44601e..9081f7099b7 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -74,7 +74,7 @@ config ENV_IS_DEFAULT !ENV_IS_IN_MMC && !ENV_IS_IN_NAND && \ !ENV_IS_IN_NVRAM && !ENV_IS_IN_ONENAND && \ !ENV_IS_IN_REMOTE && !ENV_IS_IN_SPI_FLASH && \ - !ENV_IS_IN_UBI && !ENV_IS_IN_MTD + !ENV_IS_IN_UBI && !ENV_IS_IN_MTD && !ENV_IS_IN_SCSI select ENV_IS_NOWHERE config ENV_IS_NOWHERE @@ -297,6 +297,13 @@ config ENV_IS_IN_NAND Currently, CONFIG_ENV_OFFSET_REDUND is not supported when using CONFIG_ENV_OFFSET_OOB. +config ENV_IS_IN_SCSI + bool "Environment in an SCSI device" + depends on SCSI + help + Define this if you have an SCSI device which you want to use for the + environment. + config ENV_RANGE hex "Length of the region in which the environment can be written" depends on ENV_IS_IN_NAND @@ -731,6 +738,12 @@ config ENV_MMC_USE_DT The 2 defines CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET_REDUND are not used as fallback. +config SCSI_ENV_PART_UUID + string "SCSI partition UUID for saving environment" + depends on ENV_IS_IN_SCSI + help + UUID of the SCSI partition that you want to store the environment in. + config USE_DEFAULT_ENV_FILE bool "Create default environment from file" help diff --git a/env/Makefile b/env/Makefile index 3b9c71d5681..d11b87702c1 100644 --- a/env/Makefile +++ b/env/Makefile @@ -28,5 +28,6 @@ obj-$(CONFIG_$(PHASE_)ENV_IS_IN_NAND) += nand.o obj-$(CONFIG_$(PHASE_)ENV_IS_IN_SPI_FLASH) += sf.o obj-$(CONFIG_$(PHASE_)ENV_IS_IN_MTD) += mtd.o obj-$(CONFIG_$(PHASE_)ENV_IS_IN_FLASH) += flash.o +obj-$(CONFIG_$(PHASE_)ENV_IS_IN_SCSI) += scsi.o CFLAGS_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff --git a/env/env.c b/env/env.c index dbaeedc3c3b..7a9c96b4078 100644 --- a/env/env.c +++ b/env/env.c @@ -46,6 +46,9 @@ static enum env_location env_locations[] = { #ifdef CONFIG_ENV_IS_IN_MMC ENVL_MMC, #endif +#ifdef CONFIG_ENV_IS_IN_SCSI + ENVL_SCSI, +#endif #ifdef CONFIG_ENV_IS_IN_NAND ENVL_NAND, #endif diff --git a/env/scsi.c b/env/scsi.c new file mode 100644 index 00000000000..207717e17b1 --- /dev/null +++ b/env/scsi.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2008-2011 Freescale Semiconductor, Inc. + */ + +/* #define DEBUG */ + +#include <asm/global_data.h> + +#include <command.h> +#include <env.h> +#include <env_internal.h> +#include <fdtdec.h> +#include <linux/stddef.h> +#include <malloc.h> +#include <memalign.h> +#include <part.h> +#include <search.h> +#include <scsi.h> +#include <errno.h> +#include <dm/ofnode.h> + +DECLARE_GLOBAL_DATA_PTR; +static env_t envbuf; + +struct env_scsi_info { + struct blk_desc *blk; + struct disk_partition part; + int count; +}; + +static struct env_scsi_info env_part; + +static inline struct env_scsi_info *env_scsi_get_part(void) +{ + struct env_scsi_info *ep = &env_part; + + if (scsi_get_blk_by_uuid(CONFIG_SCSI_ENV_PART_UUID, &ep->blk, &ep->part)) + return NULL; + + ep->count = CONFIG_ENV_SIZE / ep->part.blksz; + + return ep; +} + +static int env_scsi_save(void) +{ + struct env_scsi_info *ep = env_scsi_get_part(); + int ret; + + if (!ep) + return -ENOENT; + + ret = env_export(&envbuf); + if (ret) + return ret; + + if (blk_dwrite(ep->blk, ep->part.start, ep->count, &envbuf) != ep->count) + return -EIO; + + return 0; +} + +static int env_scsi_erase(void) +{ + struct env_scsi_info *ep = env_scsi_get_part(); + + if (!ep) + return -ENOENT; + + return (int)blk_derase(ep->blk, ep->part.start, ep->count); +} + +#if defined(ENV_IS_EMBEDDED) +static int env_scsi_load(void) +{ + return 0; +} +#else +static int env_scsi_load(void) +{ + struct env_scsi_info *ep = env_scsi_get_part(); + int ret; + + if (!ep) { + env_set_default(CONFIG_SCSI_ENV_PART_UUID " partition not found", 0); + return -ENOENT; + } + + if (blk_dread(ep->blk, ep->part.start, ep->count, &envbuf) != ep->count) { + env_set_default(CONFIG_SCSI_ENV_PART_UUID " partition read failed", 0); + return -EIO; + } + + ret = env_import((char *)&envbuf, 1, H_EXTERNAL); + if (ret) { + debug("ENV import failed\n"); + env_set_default("Cannot load environment", 0); + } else { + gd->env_addr = (ulong)envbuf.data; + } + + return ret; +} +#endif + +U_BOOT_ENV_LOCATION(scsi) = { + .location = ENVL_SCSI, + ENV_NAME("SCSI") + .load = env_scsi_load, +#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_XPL_BUILD) + .save = env_save_ptr(env_scsi_save), + .erase = ENV_ERASE_PTR(env_scsi_erase), +#endif +}; diff --git a/include/env_internal.h b/include/env_internal.h index ee939ba4293..75b46d0bcb0 100644 --- a/include/env_internal.h +++ b/include/env_internal.h @@ -115,6 +115,7 @@ enum env_location { ENVL_SPI_FLASH, ENVL_MTD, ENVL_UBI, + ENVL_SCSI, ENVL_NOWHERE, ENVL_COUNT, -- 2.34.1