[U-Boot] [PATCH v5 02/19] env: define env context for U-Boot environment

AKASHI Takahiro takahiro.akashi at linaro.org
Fri Sep 6 00:41:26 UTC 2019


On Thu, Sep 05, 2019 at 09:43:59PM +0200, Heinrich Schuchardt wrote:
> On 9/5/19 10:21 AM, AKASHI Takahiro wrote:
> >In this patch, env context fo U-Boot environment is defined to utilize
> >new env interfaces, maintaining the compatibility with the existing
> >semantics and Kconfig configuration.
> >
> >In this commit, FAT file system and flash device are only supported
> >devices for backing storages, but extending to other devices will be
> >quite straightforward.
> >
> >Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> >---
> >  env/Kconfig.uboot   | 671 ++++++++++++++++++++++++++++++++++++++++++++
> >  env/Makefile        |   2 +-
> >  env/env_ctx_uboot.c | 292 +++++++++++++++++++
> >  include/env.h       |   3 +
> >  4 files changed, 967 insertions(+), 1 deletion(-)
> >  create mode 100644 env/Kconfig.uboot
> >  create mode 100644 env/env_ctx_uboot.c
> >
> >diff --git a/env/Kconfig.uboot b/env/Kconfig.uboot
> >new file mode 100644
> >index 000000000000..e4334f7f2878
> >--- /dev/null
> >+++ b/env/Kconfig.uboot
> >@@ -0,0 +1,671 @@
> 
> Only one of the options below should be selected. So, please, use a
> 'choice' statement. drives/video/Kconfig has an example.

I didn't change much from the original env/Kconfig.
So there may be some reason for not using 'choice' here that I don't
know yet.

> >+config ENV_IS_NOWHERE
> >+	bool "U-Boot Environment is not stored"
> >+	default y if !ENV_IS_IN_EEPROM && !ENV_IS_IN_EXT4 && \
> >+		     !ENV_IS_IN_FAT && !ENV_IS_IN_FLASH && \
> >+		     !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
> >+	help
> >+	  Define this if you don't want to or can't have an environment stored
> >+	  on a storage medium. In this case the environment will still exist
> >+	  while U-Boot is running, but once U-Boot exits it will not be
> >+	  stored. U-Boot will therefore always start up with a default
> >+	  environment.
> >+
> >+config ENV_IS_IN_EEPROM
> >+	bool "Environment in EEPROM"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_EEPROM
> >+	help
> >+	  Use this if you have an EEPROM or similar serial access
> >+	  device and a driver for it.
> >+
> >+	  - CONFIG_ENV_OFFSET:
> >+	  - CONFIG_ENV_SIZE:
> >+
> >+	  These two #defines specify the offset and size of the
> >+	  environment area within the total memory of your EEPROM.
> >+
> >+	  Note that we consider the length of the address field to
> >+	  still be one byte because the extra address bits are hidden
> >+	  in the chip address.
> >+
> >+	  - CONFIG_ENV_EEPROM_IS_ON_I2C
> >+	  define this, if you have I2C and SPI activated, and your
> >+	  EEPROM, which holds the environment, is on the I2C bus.
> >+
> >+	  - CONFIG_I2C_ENV_EEPROM_BUS
> >+	  if you have an Environment on an EEPROM reached over
> >+	  I2C muxes, you can define here, how to reach this
> >+	  EEPROM. For example:
> >+
> >+	  #define CONFIG_I2C_ENV_EEPROM_BUS	  1
> >+
> >+	  EEPROM which holds the environment, is reached over
> >+	  a pca9547 i2c mux with address 0x70, channel 3.
> >+
> >+config ENV_IS_IN_FAT
> >+	bool "Environment is in a FAT filesystem"
> >+	depends on !CHAIN_OF_TRUST
> >+	default y if ARCH_BCM283X
> >+	default y if ARCH_SUNXI && MMC
> >+	default y if MMC_OMAP_HS && TI_COMMON_CMD_OPTIONS
> >+	select ENV_DRV_FAT
> >+	help
> >+	  Define this if you want to use the FAT file system for the environment.
> >+
> >+config ENV_IS_IN_EXT4
> >+	bool "Environment is in a EXT4 filesystem"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_EXT4
> >+	help
> >+	  Define this if you want to use the EXT4 file system for the environment.
> >+
> >+config ENV_IS_IN_FLASH
> >+	bool "Environment in flash memory"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_FLASH
> >+	default y if ARCH_CINTEGRATOR
> >+	default y if ARCH_INTEGRATOR_CP
> >+	default y if M548x || M547x || M5282 || MCF547x_8x
> >+	default y if MCF532x || MCF52x2
> >+	default y if MPC86xx || MPC83xx
> >+	default y if ARCH_MPC8572 || ARCH_MPC8548 || ARCH_MPC8641
> >+	default y if SH && !CPU_SH4
> >+	help
> >+	  Define this if you have a flash device which you want to use for the
> >+	  environment.
> >+
> >+	  a) The environment occupies one whole flash sector, which is
> >+	   "embedded" in the text segment with the U-Boot code. This
> >+	   happens usually with "bottom boot sector" or "top boot
> >+	   sector" type flash chips, which have several smaller
> >+	   sectors at the start or the end. For instance, such a
> >+	   layout can have sector sizes of 8, 2x4, 16, Nx32 kB. In
> >+	   such a case you would place the environment in one of the
> >+	   4 kB sectors - with U-Boot code before and after it. With
> >+	   "top boot sector" type flash chips, you would put the
> >+	   environment in one of the last sectors, leaving a gap
> >+	   between U-Boot and the environment.
> >+
> >+	  CONFIG_ENV_OFFSET:
> >+
> >+	   Offset of environment data (variable area) to the
> >+	   beginning of flash memory; for instance, with bottom boot
> >+	   type flash chips the second sector can be used: the offset
> >+	   for this sector is given here.
> >+
> >+	   CONFIG_ENV_OFFSET is used relative to CONFIG_SYS_FLASH_BASE.
> >+
> >+	  CONFIG_ENV_ADDR:
> >+
> >+	   This is just another way to specify the start address of
> >+	   the flash sector containing the environment (instead of
> >+	   CONFIG_ENV_OFFSET).
> >+
> >+	  CONFIG_ENV_SECT_SIZE:
> >+
> >+	   Size of the sector containing the environment.
> >+
> >+
> >+	  b) Sometimes flash chips have few, equal sized, BIG sectors.
> >+	   In such a case you don't want to spend a whole sector for
> >+	   the environment.
> >+
> >+	  CONFIG_ENV_SIZE:
> >+
> >+	   If you use this in combination with CONFIG_ENV_IS_IN_FLASH
> >+	   and CONFIG_ENV_SECT_SIZE, you can specify to use only a part
> >+	   of this flash sector for the environment. This saves
> >+	   memory for the RAM copy of the environment.
> >+
> >+	   It may also save flash memory if you decide to use this
> >+	   when your environment is "embedded" within U-Boot code,
> >+	   since then the remainder of the flash sector could be used
> >+	   for U-Boot code. It should be pointed out that this is
> >+	   STRONGLY DISCOURAGED from a robustness point of view:
> >+	   updating the environment in flash makes it always
> >+	   necessary to erase the WHOLE sector. If something goes
> >+	   wrong before the contents has been restored from a copy in
> >+	   RAM, your target system will be dead.
> >+
> >+	  CONFIG_ENV_ADDR_REDUND
> >+	  CONFIG_ENV_SIZE_REDUND
> >+
> >+	   These settings describe a second storage area used to hold
> >+	   a redundant copy of the environment data, so that there is
> >+	   a valid backup copy in case there is a power failure during
> >+	   a "saveenv" operation.
> >+
> >+	  BE CAREFUL! Any changes to the flash layout, and some changes to the
> >+	  source code will make it necessary to adapt <board>/u-boot.lds*
> >+	  accordingly!
> >+
> >+config ENV_IS_IN_MMC
> >+	bool "Environment in an MMC device"
> >+	depends on !CHAIN_OF_TRUST
> >+	depends on MMC
> >+	select ENV_DRV_MMC
> >+	default y if ARCH_EXYNOS4
> >+	default y if MX6SX || MX7D
> >+	default y if TEGRA30 || TEGRA124
> >+	default y if TEGRA_ARMV8_COMMON
> >+	help
> >+	  Define this if you have an MMC device which you want to use for the
> >+	  environment.
> >+
> >+	  CONFIG_SYS_MMC_ENV_DEV:
> >+
> >+	  Specifies which MMC device the environment is stored in.
> >+
> >+	  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).
> >+
> >+	  CONFIG_ENV_OFFSET:
> >+	  CONFIG_ENV_SIZE:
> >+
> >+	  These two #defines specify the offset and size of the environment
> >+	  area within the specified MMC device.
> >+
> >+	  If offset is positive (the usual case), it is treated as relative to
> >+	  the start of the MMC partition. If offset is negative, it is treated
> >+	  as relative to the end of the MMC partition. This can be useful if
> >+	  your board may be fitted with different MMC devices, which have
> >+	  different sizes for the MMC partitions, and you always want the
> >+	  environment placed at the very end of the partition, to leave the
> >+	  maximum possible space before it, to store other data.
> >+
> >+	  These two values are in units of bytes, but must be aligned to an
> >+	  MMC 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 value may also be positive or negative; this is handled in the
> >+	  same way as CONFIG_ENV_OFFSET.
> >+
> >+	  This value is also in units of bytes, but must also be aligned to
> >+	  an MMC sector boundary.
> >+
> >+	  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 ENV_IS_IN_NAND
> >+	bool "Environment in a NAND device"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_NAND
> >+	help
> >+	  Define this if you have a NAND 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 first NAND device.  CONFIG_ENV_OFFSET must be
> >+	  aligned to an erase block boundary.
> >+
> >+	  - CONFIG_ENV_OFFSET_REDUND (optional):
> >+
> >+	  This setting describes a second storage area of CONFIG_ENV_SIZE
> >+	  size used to hold a redundant copy of the environment data, so
> >+	  that there is a valid backup copy in case there is a power failure
> >+	  during a "saveenv" operation.	 CONFIG_ENV_OFFSET_REDUND must be
> >+	  aligned to an erase block boundary.
> >+
> >+	  - CONFIG_ENV_RANGE (optional):
> >+
> >+	  Specifies the length of the region in which the environment
> >+	  can be written.  This should be a multiple of the NAND device's
> >+	  block size.  Specifying a range with more erase blocks than
> >+	  are needed to hold CONFIG_ENV_SIZE allows bad blocks within
> >+	  the range to be avoided.
> >+
> >+	  - CONFIG_ENV_OFFSET_OOB (optional):
> >+
> >+	  Enables support for dynamically retrieving the offset of the
> >+	  environment from block zero's out-of-band data.  The
> >+	  "nand env.oob" command can be used to record this offset.
> >+	  Currently, CONFIG_ENV_OFFSET_REDUND is not supported when
> >+	  using CONFIG_ENV_OFFSET_OOB.
> >+
> >+config ENV_IS_IN_NVRAM
> >+	bool "Environment in a non-volatile RAM"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_NVRAM
> >+	help
> >+	  Define this if you have some non-volatile memory device
> >+	  (NVRAM, battery buffered SRAM) which you want to use for the
> >+	  environment.
> >+
> >+	  - CONFIG_ENV_ADDR:
> >+	  - CONFIG_ENV_SIZE:
> >+
> >+	  These two #defines are used to determine the memory area you
> >+	  want to use for environment. It is assumed that this memory
> >+	  can just be read and written to, without any special
> >+	  provision.
> >+
> >+config ENV_IS_IN_ONENAND
> >+	bool "Environment is in OneNAND"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_ONENAND
> >+	help
> >+	  Define this if you want to put your local device's environment in
> >+	  OneNAND.
> >+
> >+	  - CONFIG_ENV_ADDR:
> >+	  - CONFIG_ENV_SIZE:
> >+
> >+	  These two #defines are used to determine the device range you
> >+	  want to use for environment. It is assumed that this memory
> >+	  can just be read and written to, without any special
> >+	  provision.
> >+
> >+config ENV_IS_IN_REMOTE
> >+	bool "Environment is in remote memory space"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_REMOTE
> >+	help
> >+	  Define this if you have a remote memory space which you
> >+	  want to use for the local device's environment.
> >+
> >+	  - CONFIG_ENV_ADDR:
> >+	  - CONFIG_ENV_SIZE:
> >+
> >+	  These two #defines specify the address and size of the
> >+	  environment area within the remote memory space. The
> >+	  local device can get the environment from remote memory
> >+	  space by SRIO or PCIE links.
> >+
> >+config ENV_IS_IN_SPI_FLASH
> >+	bool "Environment is in SPI flash"
> >+	depends on !CHAIN_OF_TRUST && SPI
> >+	select ENV_DRV_SPI_FLASH
> >+	default y if ARMADA_XP
> >+	default y if INTEL_BAYTRAIL
> >+	default y if INTEL_BRASWELL
> >+	default y if INTEL_BROADWELL
> >+	default y if NORTHBRIDGE_INTEL_IVYBRIDGE
> >+	default y if INTEL_QUARK
> >+	default y if INTEL_QUEENSBAY
> >+	help
> >+	  Define this if you have a SPI Flash memory 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 SPI Flash. CONFIG_ENV_OFFSET must be
> >+	  aligned to an erase sector boundary.
> >+
> >+	  - CONFIG_ENV_SECT_SIZE:
> >+
> >+	  Define the SPI flash's sector size.
> >+
> >+	  - CONFIG_ENV_OFFSET_REDUND (optional):
> >+
> >+	  This setting describes a second storage area of CONFIG_ENV_SIZE
> >+	  size used to hold a redundant copy of the environment data, so
> >+	  that there is a valid backup copy in case there is a power failure
> >+	  during a "saveenv" operation. CONFIG_ENV_OFFSET_REDUND must be
> >+	  aligned to an erase sector boundary.
> >+
> >+config USE_ENV_SPI_BUS
> >+	bool "SPI flash bus for environment"
> >+	depends on ENV_IS_IN_SPI_FLASH
> >+	help
> >+	  Force the SPI bus for environment.
> >+	  If not defined, use CONFIG_SF_DEFAULT_BUS.
> >+
> >+config ENV_SPI_BUS
> >+	int "Value of SPI flash bus for environment"
> >+	depends on USE_ENV_SPI_BUS
> >+	help
> >+	  Value the SPI bus and chip select for environment.
> >+
> >+config USE_ENV_SPI_CS
> >+	bool "SPI flash chip select for environment"
> >+	depends on ENV_IS_IN_SPI_FLASH
> >+	help
> >+	  Force the SPI chip select for environment.
> >+	  If not defined, use CONFIG_SF_DEFAULT_CS.
> >+
> >+config ENV_SPI_CS
> >+	int "Value of SPI flash chip select for environment"
> >+	depends on USE_ENV_SPI_CS
> >+	help
> >+	  Value of the SPI chip select for environment.
> >+
> >+config USE_ENV_SPI_MAX_HZ
> >+	bool "SPI flash max frequency for environment"
> >+	depends on ENV_IS_IN_SPI_FLASH
> >+	help
> >+	  Force the SPI max work clock for environment.
> >+	  If not defined, use CONFIG_SF_DEFAULT_SPEED.
> >+
> >+config ENV_SPI_MAX_HZ
> >+	int "Value of SPI flash max frequency for environment"
> >+	depends on USE_ENV_SPI_MAX_HZ
> >+	help
> >+	  Value of the SPI max work clock for environment.
> >+
> >+config USE_ENV_SPI_MODE
> >+	bool "SPI flash mode for environment"
> >+	depends on ENV_IS_IN_SPI_FLASH
> >+	help
> >+	  Force the SPI work mode for environment.
> >+
> >+config ENV_SPI_MODE
> >+	hex "Value of SPI flash work mode for environment"
> >+	depends on USE_ENV_SPI_MODE
> >+	help
> >+	  Value of the SPI work mode for environment.
> >+	  See include/spi.h for value.
> >+
> >+config ENV_IS_IN_UBI
> >+	bool "Environment in a UBI volume"
> >+	depends on !CHAIN_OF_TRUST
> >+	select ENV_DRV_UBI
> >+	help
> >+	  Define this if you have an UBI volume that you want to use for the
> >+	  environment.  This has the benefit of wear-leveling the environment
> >+	  accesses, which is important on NAND.
> >+
> >+	  - CONFIG_ENV_UBI_PART:
> >+
> >+	  Define this to a string that is the mtd partition containing the UBI.
> >+
> >+	  - CONFIG_ENV_UBI_VOLUME:
> >+
> >+	  Define this to the name of the volume that you want to store the
> >+	  environment in.
> >+
> >+	  - CONFIG_ENV_UBI_VOLUME_REDUND:
> >+
> >+	  Define this to the name of another volume to store a second copy of
> >+	  the environment in.  This will enable redundant environments in UBI.
> >+	  It is assumed that both volumes are in the same MTD partition.
> >+
> >+config ENV_FAT_INTERFACE
> >+	string "Name of the block device for the environment"
> >+	depends on ENV_IS_IN_FAT
> >+	default "mmc" if ARCH_SUNXI
> >+	default "mmc" if TI_COMMON_CMD_OPTIONS || ARCH_ZYNQMP || ARCH_AT91
> >+	help
> >+	  Define this to a string that is the name of the block device.
> >+
> >+config ENV_FAT_DEVICE_AND_PART
> >+	string "Device and partition for where to store the environment in FAT"
> >+	depends on ENV_IS_IN_FAT
> >+	default "0:1" if TI_COMMON_CMD_OPTIONS
> >+	default "0:auto" if ARCH_ZYNQMP
> >+	default "0:auto" if ARCH_SUNXI && MMC_SUNXI_SLOT_EXTRA = -1
> >+	default "1:auto" if ARCH_SUNXI && MMC_SUNXI_SLOT_EXTRA != -1
> >+	default "0" if ARCH_AT91
> >+	help
> >+	  Define this to a string to specify the partition of the device. It can
> >+	  be as following:
> >+
> >+	    "D:P", "D:0", "D", "D:" or "D:auto" (D, P are integers. And P >= 1)
> >+	       - "D:P": device D partition P. Error occurs if device D has no
> >+	                partition table.
> >+	       - "D:0": device D.
> >+	       - "D" or "D:": device D partition 1 if device D has partition
> >+	                      table, or the whole device D if has no partition
> >+	                      table.
> >+	       - "D:auto": first partition in device D with bootable flag set.
> >+	                   If none, first valid partition in device D. If no
> >+	                   partition table then means device D.
> >+
> >+config ENV_FAT_FILE
> >+	string "Name of the FAT file to use for the environment"
> >+	depends on ENV_IS_IN_FAT
> >+	default "uboot.env"
> >+	help
> >+	  It's a string of the FAT file name. This file use to store the
> >+	  environment.
> >+
> >+config ENV_EXT4_INTERFACE
> >+	string "Name of the block device for the environment"
> >+	depends on ENV_IS_IN_EXT4
> >+	help
> >+	  Define this to a string that is the name of the block device.
> >+
> >+config ENV_EXT4_DEVICE_AND_PART
> >+	string "Device and partition for where to store the environment in EXT4"
> >+	depends on ENV_IS_IN_EXT4
> >+	help
> >+	  Define this to a string to specify the partition of the device. It can
> >+	  be as following:
> >+
> >+	    "D:P", "D:0", "D", "D:" or "D:auto" (D, P are integers. And P >= 1)
> >+	       - "D:P": device D partition P. Error occurs if device D has no
> >+	                partition table.
> >+	       - "D:0": device D.
> >+	       - "D" or "D:": device D partition 1 if device D has partition
> >+	                      table, or the whole device D if has no partition
> >+	                      table.
> >+	       - "D:auto": first partition in device D with bootable flag set.
> >+	                   If none, first valid partition in device D. If no
> >+	                   partition table then means device D.
> >+
> >+config ENV_EXT4_FILE
> >+	string "Name of the EXT4 file to use for the environment"
> >+	depends on ENV_IS_IN_EXT4
> >+	default "uboot.env"
> >+	help
> >+	  It's a string of the EXT4 file name. This file use to store the
> >+	  environment (explicit path to the file)
> >+
> >+if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC || ARCH_STM32MP || ARCH_OMAP2PLUS || ARCH_AT91
> >+
> >+config ENV_OFFSET
> >+	hex "Environment Offset"
> >+	depends on (!ENV_IS_IN_UBI && !ENV_IS_NOWHERE) || ARCH_STM32MP
> >+	default 0x3f8000 if ARCH_ROCKCHIP
> >+	default 0x88000 if ARCH_SUNXI
> >+	default 0xE0000 if ARCH_ZYNQ
> >+	default 0x1E00000 if ARCH_ZYNQMP
> >+	default 0 if ARC
> >+	default 0x140000 if ARCH_AT91
> >+	default 0x260000 if ARCH_OMAP2PLUS
> >+	help
> >+	  Offset from the start of the device (or partition)
> >+
> >+config ENV_SIZE
> >+	hex "Environment Size"
> >+	default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP
> >+	default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
> >+	default 0x8000 if ARCH_ROCKCHIP || ARCH_ZYNQMP || ARCH_VERSAL
> >+	default 0x4000 if ARC
> >+	default 0x1f000
> >+	help
> >+	  Size of the environment storage area
> >+
> >+config ENV_SECT_SIZE
> >+	hex "Environment Sector-Size"
> >+	depends on (!ENV_IS_NOWHERE && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_OMAP2PLUS || ARCH_AT91) )|| ARCH_STM32MP
> >+	default 0x40000 if ARCH_ZYNQMP
> >+	default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
> >+	help
> >+	  Size of the sector containing the environment.
> >+
> >+config ENV_UBI_PART
> >+	string "UBI partition name"
> >+	depends on ENV_IS_IN_UBI
> >+	help
> >+	  MTD partition containing the UBI device
> >+
> >+config ENV_UBI_VOLUME
> >+	string "UBI volume name"
> >+	depends on ENV_IS_IN_UBI
> >+	help
> >+	  Name of the volume that you want to store the environment in.
> >+
> >+config ENV_UBI_VOLUME_REDUND
> >+	string "UBI redundant volume name"
> >+	depends on ENV_IS_IN_UBI
> >+	help
> >+	  Name of the redundant volume that you want to store the environment in.
> >+
> >+config ENV_UBI_VID_OFFSET
> >+	int "ubi environment VID offset"
> >+	depends on ENV_IS_IN_UBI
> >+	default 0
> >+	help
> >+	  UBI VID offset for environment. If 0, no custom VID offset is used.
> >+
> >+endif
> >+
> >+config USE_DEFAULT_ENV_FILE
> >+	bool "Create default environment from file"
> >+	help
> >+	  Normally, the default environment is automatically generated
> >+	  based on the settings of various CONFIG_* options, as well
> >+	  as the CONFIG_EXTRA_ENV_SETTINGS. By selecting this option,
> >+	  you can instead define the entire default environment in an
> >+	  external file.
> >+
> >+config DEFAULT_ENV_FILE
> >+	string "Path to default environment file"
> >+	depends on USE_DEFAULT_ENV_FILE
> >+	help
> >+	  The path containing the default environment. The format is
> >+	  the same as accepted by the mkenvimage tool: lines
> >+	  containing key=value pairs, blank lines and lines beginning
> >+	  with # are ignored.
> >+
> >+config ENV_VARS_UBOOT_RUNTIME_CONFIG
> >+	bool "Add run-time information to the environment"
> >+	help
> >+	  Enable this in order to add variables describing certain
> >+	  run-time determined information about the hardware to the
> >+	  environment.  These will be named board_name, board_rev.
> >+
> >+if SPL_ENV_SUPPORT
> >+config SPL_ENV_IS_NOWHERE
> >+	bool "SPL Environment is not stored"
> >+	default y if ENV_IS_NOWHERE
> >+	help
> >+	  Similar to ENV_IS_NOWHERE, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_MMC
> >+	bool "SPL Environment in an MMC device"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_MMC
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_MMC, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_FAT
> >+	bool "SPL Environment is in a FAT filesystem"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_FAT
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_FAT, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_EXT4
> >+	bool "SPL Environment is in a EXT4 filesystem"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_EXT4
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_EXT4, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_NAND
> >+	bool "SPL Environment in a NAND device"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_NAND
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_NAND, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_SPI_FLASH
> >+	bool "SPL Environment is in SPI flash"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_SPI_FLASH
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_SPI_FLASH, used for SPL environment.
> >+
> >+config SPL_ENV_IS_IN_FLASH
> >+	bool "SPL Environment in flash memory"
> >+	depends on !SPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_FLASH
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_FLASH, used for SPL environment.
> >+
> >+endif
> >+
> >+if TPL_ENV_SUPPORT
> >+
> >+config TPL_ENV_IS_NOWHERE
> >+	bool "TPL Environment is not stored"
> >+	default y if ENV_IS_NOWHERE
> >+	help
> >+	  Similar to ENV_IS_NOWHERE, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_MMC
> >+	bool "TPL Environment in an MMC device"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_MMC
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_MMC, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_FAT
> >+	bool "TPL Environment is in a FAT filesystem"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_FAT
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_FAT, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_EXT4
> >+	bool "TPL Environment is in a EXT4 filesystem"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_EXT4
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_EXT4, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_NAND
> >+	bool "TPL Environment in a NAND device"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_NAND
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_NAND, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_SPI_FLASH
> >+	bool "TPL Environment is in SPI flash"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_SPI_FLASH
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_SPI_FLASH, used for TPL environment.
> >+
> >+config TPL_ENV_IS_IN_FLASH
> >+	bool "TPL Environment in flash memory"
> >+	depends on !TPL_ENV_IS_NOWHERE
> >+	select ENV_DRV_FLASH
> >+	default y
> >+	help
> >+	  Similar to ENV_IS_IN_FLASH, used for TPL environment.
> >+
> >+endif
> >diff --git a/env/Makefile b/env/Makefile
> >index ee37cc822024..0168eb47f00d 100644
> >--- a/env/Makefile
> >+++ b/env/Makefile
> >@@ -3,7 +3,7 @@
> >  # (C) Copyright 2004-2006
> >  # Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> >
> >-obj-y += common.o env.o
> >+obj-y += common.o env.o env_ctx_uboot.o
> >
> >  ifndef CONFIG_SPL_BUILD
> >  obj-y += attr.o
> >diff --git a/env/env_ctx_uboot.c b/env/env_ctx_uboot.c
> >new file mode 100644
> >index 000000000000..5ca645599347
> >--- /dev/null
> >+++ b/env/env_ctx_uboot.c
> >@@ -0,0 +1,292 @@
> >+// SPDX-License-Identifier: GPL-2.0+
> >+/*
> >+ * Copyright (C) 2019 Linaro Limited
> >+ *		Author: AKASHI Takahiro
> >+ */
> >+
> >+#include <common.h>
> >+#include <env_default.h>
> >+#include <env_flags.h>
> >+#include <env_internal.h>
> >+#include <search.h>
> >+
> >+DECLARE_GLOBAL_DATA_PTR;
> >+
> >+#if !defined(ENV_IS_IN_DEVICE) && !defined(CONFIG_ENV_IS_NOWHERE)
> >+# 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
> >+#endif
> >+
> >+struct hsearch_data env_htab = {
> >+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
> >+	/* defined in flags.c, only compile with ENV_SUPPORT */
> >+	.change_ok = env_flags_validate,
> >+#endif
> >+};
> >+
> >+/*
> >+ * NOTE: extracted from env/env.c
> >+ */
> >+static bool env_has_inited_uboot(struct env_context *ctx,
> >+				 enum env_location location)
> >+{
> >+	return gd->env_has_init & BIT(location);
> >+}
> >+
> >+static void env_set_inited_uboot(struct env_context *ctx,
> >+				 enum env_location location)
> >+{
> >+	gd->env_has_init |= BIT(location);
> >+}
> >+
> >+static int env_get_load_prio_uboot(struct env_context *ctx)
> >+{
> >+	return gd->env_load_prio;
> >+}
> >+
> >+static enum env_location env_get_location_uboot(struct env_context *ctx,
> >+						enum env_operation op, int prio)
> >+{
> >+	gd->env_load_prio = prio;
> >+
> >+	return env_locations[prio];
> >+}
> >+
> >+int env_get_char_default_uboot(struct env_context *ctx, int index)
> >+{
> >+	return default_environment[index];
> >+}
> >+
> >+int env_get_char_spec_uboot(struct env_context *ctx, int index)
> >+{
> >+	return *(uchar *)(gd->env_addr + index);
> >+}
> >+
> >+static int env_init_uboot(struct env_context *ctx)
> >+{
> >+	struct env_driver *drv;
> >+	int ret = -ENOENT;
> >+	int prio;
> >+
> >+	for (prio = 0; (drv = env_driver_lookup(ctx, ENVOP_INIT, prio));
> >+	     prio++) {
> >+		if (!drv->init || !(ret = drv->init(ctx)))
> >+			gd->env_has_init |= BIT(drv->location);
> >+
> >+		debug("%s: Environment %s init done (ret=%d)\n", __func__,
> >+		      drv->name, ret);
> >+	}
> >+
> >+	if (!prio)
> >+		return -ENODEV;
> >+
> >+	if (ret == -ENOENT) {
> >+		gd->env_addr = (ulong)&default_environment[0];
> >+		gd->env_valid = ENV_VALID;
> >+
> >+		return 0;
> >+	}
> >+
> >+	return ret;
> >+}
> >+
> >+static int env_drv_init_uboot(struct env_context *ctx, enum env_location loc)
> >+{
> >+	__maybe_unused int ret;
> >+
> >+	switch (loc) {
> >+#ifdef CONFIG_ENV_IS_IN_FLASH
> >+	case ENVL_FLASH: {
> >+		env_hdr_t *env_ptr;
> >+		env_hdr_t *flash_addr;
> >+		ulong end_addr;
> >+		env_hdr_t *flash_addr_new;
> >+		ulong end_addr_new;
> >+
> >+#ifdef ENV_IS_EMBEDDED
> >+		env_ptr = &embedded_environment;
> >+#else /* ! ENV_IS_EMBEDDED */
> >+		env_ptr = (env_hdr_t *)CONFIG_ENV_ADDR;
> >+#endif /* ENV_IS_EMBEDDED */
> >+		flash_addr = (env_hdr_t *)CONFIG_ENV_ADDR;
> >+
> >+/* CONFIG_ENV_ADDR is supposed to be on sector boundary */
> >+		end_addr = CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1;
> >+
> >+#ifdef CONFIG_ENV_ADDR_REDUND
> >+		flash_addr_new = (env_hdr_t *)CONFIG_ENV_ADDR_REDUND;
> >+/* CONFIG_ENV_ADDR_REDUND is supposed to be on sector boundary */
> >+		end_addr_new = CONFIG_ENV_ADDR_REDUND
> >+					+ CONFIG_ENV_SECT_SIZE - 1;
> >+#else
> >+		flash_addr_new = NULL;
> >+		end_addr_new = 0;
> >+#endif /* CONFIG_ENV_ADDR_REDUND */
> >+
> >+		ret = env_flash_init_params(ctx, env_ptr, flash_addr, end_addr,
> >+					    flash_addr_new, end_addr_new,
> >+					    (ulong)&default_environment[0]);
> >+		if (ret)
> >+			return -ENOENT;
> >+
> >+		return 0;
> >+		}
> >+#endif
> >+#ifdef CONFIG_ENV_IS_IN_FAT
> >+	case ENVL_FAT: {
> >+		ret = env_fat_init_params(ctx,
> >+					  CONFIG_ENV_FAT_INTERFACE,
> >+					  CONFIG_ENV_FAT_DEVICE_AND_PART,
> >+					  CONFIG_ENV_FAT_FILE);
> >+
> >+		return -ENOENT;
> >+		}
> >+#endif
> >+#ifdef CONFIG_ENV_DRV_NONE
> >+	case ENVL_NOWHERE:
> >+#ifdef CONFIG_ENV_IS_NOWHERE
> >+		gd->env_addr = (ulong)&default_environment[0];
> >+		gd->env_valid = ENV_INVALID;
> >+
> >+		return 0;
> >+#else
> >+		return -ENOENT;
> >+#endif
> >+#endif
> >+	default:
> >+		return -ENOENT;
> >+	}
> >+}
> >+
> >+/*
> >+ * NOTE: extracted from env/common.c
> >+ */
> >+void env_set_ready_uboot(struct env_context *ctx)
> >+{
> >+	gd->flags |= GD_FLG_ENV_READY;
> >+}
> >+
> >+bool env_is_ready_uboot(struct env_context *ctx)
> >+{
> >+	return (gd->flags & GD_FLG_ENV_READY);
> >+}
> >+
> >+void env_set_valid_uboot(struct env_context *ctx, enum env_valid valid)
> >+{
> >+	gd->env_valid = valid;
> >+}
> >+
> >+enum env_valid env_get_valid_uboot(struct env_context *ctx)
> >+{
> >+	return gd->env_valid;
> >+}
> >+
> >+void env_set_addr_uboot(struct env_context *ctx, ulong env_addr)
> >+{
> >+	gd->env_addr = env_addr;
> >+}
> >+
> >+ulong env_get_addr_uboot(struct env_context *ctx)
> >+{
> >+	return gd->env_addr;
> >+}
> >+
> >+/*
> >+ * Look up the variable from the default environment
> >+ */
> >+char *env_get_default_uboot(struct env_context *ctx, const char *name)
> >+{
> >+	char *ret_val;
> >+	unsigned long really_valid = gd->env_valid;
> >+	unsigned long real_gd_flags = gd->flags;
> >+
> >+	/* Pretend that the image is bad. */
> >+	gd->flags &= ~GD_FLG_ENV_READY;
> >+	gd->env_valid = ENV_INVALID;
> >+	ret_val = env_get(ctx, name);
> >+	gd->env_valid = really_valid;
> >+	gd->flags = real_gd_flags;
> >+	return ret_val;
> >+}
> >+
> >+void env_set_default_env_uboot(struct env_context *ctx, const char *s,
> >+			       int flags)
> >+{
> >+	if (sizeof(default_environment) > ctx->env_size) {
> >+		puts("*** Error - default environment is too large\n\n");
> >+		return;
> >+	}
> >+
> >+	if (s) {
> >+		if ((flags & H_INTERACTIVE) == 0)
> >+			printf("*** Warning - %s, using default environment\n\n", s);
> >+		else
> >+			puts(s);
> >+	} else {
> >+		debug("Using default environment\n");
> >+	}
> >+
> >+	env_htab.ctx = ctx;
> >+	if (himport_r(&env_htab, (char *)default_environment,
> >+		      sizeof(default_environment), '\0', flags, 0,
> >+		      0, NULL) == 0)
> >+		pr_err("## Error: Environment import failed: errno = %d\n",
> >+		       errno);
> >+
> >+	gd->flags |= GD_FLG_ENV_READY;
> >+	gd->flags |= GD_FLG_ENV_DEFAULT;
> >+}
> >+
> >+/* [re]set individual variables to their value in the default environment */
> >+int env_set_default_vars_uboot(struct env_context *ctx, int nvars,
> >+			       char * const vars[], int flags)
> >+{
> >+	/*
> >+	 * Special use-case: import from default environment
> >+	 * (and use \0 as a separator)
> >+	 */
> >+	flags |= H_NOCLEAR;
> >+	env_htab.ctx = ctx;
> >+	return himport_r(&env_htab, (const char *)default_environment,
> >+				sizeof(default_environment), '\0',
> >+				flags, 0, nvars, vars);
> >+}
> >+
> >+void env_post_relocate_uboot(struct env_context *ctx)
> >+{
> >+	if (gd->env_valid == ENV_INVALID) {
> >+#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
> >+		/* Environment not changeable */
> >+		env_set_default(ctx, NULL, 0);
> >+#else
> >+		bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
> >+		env_set_default(ctx, "bad CRC", 0);
> >+#endif
> >+	} else {
> >+		env_load(ctx);
> >+	}
> >+}
> >+
> >+U_BOOT_ENV_CONTEXT(uboot) = {
> >+	.name = "uboot",
> >+	.htab = &env_htab,
> >+	.env_size = ENV_SIZE,
> >+	.has_inited = env_has_inited_uboot,
> >+	.set_inited = env_set_inited_uboot,
> >+	.get_load_prio = env_get_load_prio_uboot,
> >+	.get_location = env_get_location_uboot,
> >+	.get_char_default = env_get_char_default_uboot,
> >+	.get_char_spec = env_get_char_spec_uboot,
> >+	.init = env_init_uboot,
> >+	.drv_init = env_drv_init_uboot,
> >+	.get_default = env_get_default_uboot,
> >+	.set_default = env_set_default_env_uboot,
> >+	.set_default_vars = env_set_default_vars_uboot,
> >+	.set_ready = env_set_ready_uboot,
> >+	.is_ready = env_is_ready_uboot,
> >+	.set_valid = env_set_valid_uboot,
> >+	.get_valid = env_get_valid_uboot,
> >+	.set_addr = env_set_addr_uboot,
> >+	.get_addr = env_get_addr_uboot,
> >+	.post_relocate = env_post_relocate_uboot,
> >+};
> >diff --git a/include/env.h b/include/env.h
> >index 203605e5e778..26abae2a5c42 100644
> >--- a/include/env.h
> >+++ b/include/env.h
> >@@ -9,6 +9,7 @@
> >  #ifndef __ENV_H
> >  #define __ENV_H
> >
> >+#include <linker_lists.h>
> >  #include <stdbool.h>
> >  #include <linux/types.h>
> >
> >@@ -63,6 +64,8 @@ enum env_redund_flags {
> >  	ENV_REDUND_ACTIVE = 1,
> >  };
> >
> >+#define ctx_uboot ll_entry_get(struct env_context, uboot, env_contexts)
> 
> Please, do not call ll_entry_get(,uboot,) multiple times. Just call it
> once during initialization and store the reference in a global variable.
> In this case you do not need the macro.

ll_entry_get() won't hurt anything, but for efficiency I agree.

Thanks,
-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> >+
> >  /* Accessor functions */
> >  void env_set_ready(struct env_context *ctx);
> >  bool env_is_ready(struct env_context *ctx);
> >
> 


More information about the U-Boot mailing list