From: Simon Glass Date: Thu, 3 Aug 2017 18:21:49 +0000 (-0600) Subject: Move environment files from common/ to env/ X-Git-Tag: v2017.09-rc3~104 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0649cd0d4908d9b983a0361b8665938ef25701be;p=u-boot Move environment files from common/ to env/ About a quarter of the files in common/ relate to the environment. It seems better to put these into their own subdirectory and remove the prefix. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- diff --git a/Kconfig b/Kconfig index 14740b49f1..c48f00ea36 100644 --- a/Kconfig +++ b/Kconfig @@ -380,6 +380,8 @@ source "disk/Kconfig" source "dts/Kconfig" +source "env/Kconfig" + source "net/Kconfig" source "drivers/Kconfig" diff --git a/Makefile b/Makefile index 8d245bde5d..2fc4616bb6 100644 --- a/Makefile +++ b/Makefile @@ -690,6 +690,7 @@ libs-y += drivers/usb/phy/ libs-y += drivers/usb/ulpi/ libs-y += cmd/ libs-y += common/ +libs-y += env/ libs-$(CONFIG_API) += api/ libs-$(CONFIG_HAS_POST) += post/ libs-y += test/ diff --git a/arch/sh/cpu/u-boot.lds b/arch/sh/cpu/u-boot.lds index bbf9ff485f..7fc91bc4aa 100644 --- a/arch/sh/cpu/u-boot.lds +++ b/arch/sh/cpu/u-boot.lds @@ -33,9 +33,9 @@ SECTIONS KEEP(CONFIG_BOARDDIR/lowlevel_init.o (.text .spiboot1.text)) KEEP(*(.spiboot2.text)) . = ALIGN(8192); - common/env_embedded.o (.ppcenv) + env/embedded.o (.ppcenv) . = ALIGN(8192); - common/env_embedded.o (.ppcenvr) + env/embedded.o (.ppcenvr) . = ALIGN(8192); *(.text) . = ALIGN(4); diff --git a/board/freescale/mx31ads/u-boot.lds b/board/freescale/mx31ads/u-boot.lds index 8a4a8a2f07..71a63f188e 100644 --- a/board/freescale/mx31ads/u-boot.lds +++ b/board/freescale/mx31ads/u-boot.lds @@ -30,7 +30,7 @@ SECTIONS drivers/mtd/built-in.o (.text*) . = DEFINED(env_offset) ? env_offset : .; - common/env_embedded.o(.text*) + env/embedded.o(.text*) *(.text*) } diff --git a/common/Kconfig b/common/Kconfig index 3ef1ab0de3..4d8cae9610 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -174,448 +174,6 @@ config SPI_BOOT endmenu -menu "Environment" - -config ENV_IS_IN_DATAFLASH - bool "Environment in dataflash" - depends on !CHAIN_OF_TRUST - help - Define this if you have a DataFlash memory device which you - want to use for the environment. - - - CONFIG_ENV_OFFSET: - - CONFIG_ENV_ADDR: - - CONFIG_ENV_SIZE: - - These three #defines specify the offset and size of the - environment area within the total memory of your DataFlash placed - at the specified address. - -config ENV_IS_IN_EEPROM - bool "Environment in EEPROM" - depends on !CHAIN_OF_TRUST - 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. - - - CONFIG_SYS_I2C_EEPROM_ADDR: - If defined, specified the chip address of the EEPROM device. - The default address is zero. - - - CONFIG_SYS_I2C_EEPROM_BUS: - If defined, specified the i2c bus of the EEPROM device. - - - CONFIG_SYS_EEPROM_PAGE_WRITE_BITS: - If defined, the number of bits used to address bytes in a - single page in the EEPROM device. A 64 byte page, for example - would require six bits. - - - CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS: - If defined, the number of milliseconds to delay between - page writes. The default is zero milliseconds. - - - CONFIG_SYS_I2C_EEPROM_ADDR_LEN: - The length in bytes of the EEPROM memory array address. Note - that this is NOT the chip address length! - - - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW: - EEPROM chips that implement "address overflow" are ones - like Catalyst 24WC04/08/16 which has 9/10/11 bits of - address and the extra bits end up in the "chip address" bit - slots. This makes a 24WC08 (1Kbyte) chip look like four 256 - byte chips. - - 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_SYS_EEPROM_SIZE: - The size in bytes of the EEPROM device. - - - 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 - select FAT_WRITE - help - Define this if you want to use the FAT file system for the environment. - - - - CONFIG_FAT_WRITE: - This must be enabled. Otherwise it cannot save the environment file. - -config ENV_IS_IN_FLASH - bool "Environment in flash memory" - depends on !CHAIN_OF_TRUST - 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 /u-boot.lds* - accordingly! - -config ENV_IS_IN_MMC - bool "Environment in an MMC device" - depends on !CHAIN_OF_TRUST - default y if ARCH_SUNXI - 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 - 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 - 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 - 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 remove memory space" - depends on !CHAIN_OF_TRUST - 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 - 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_ENV_SPI_BUS (optional): - - CONFIG_ENV_SPI_CS (optional): - - Define the SPI bus and chip select. If not defined they will be 0. - - - CONFIG_ENV_SPI_MAX_HZ (optional): - - Define the SPI max work clock. If not defined then use 1MHz. - - - CONFIG_ENV_SPI_MODE (optional): - - Define the SPI work mode. If not defined then use SPI_MODE_3. - -config ENV_IS_IN_UBI - bool "Environment in a UBI volume" - depends on !CHAIN_OF_TRUST - 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_UBI_SILENCE_MSG - - CONFIG_UBIFS_SILENCE_MSG - - You will probably want to define these to avoid a really noisy system - when storing the env in UBI. - -config ENV_IS_NOWHERE - bool "Environment is not stored" - help - Define this if you don't want to or can't have an environment stored - on a storage medium - -config ENV_FAT_INTERFACE - string "Name of the block device for the environment" - depends on ENV_IS_IN_FAT - 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 environemt in FAT" - depends on ENV_IS_IN_FAT - default "0:1" if TI_COMMON_CMD_OPTIONS - default "0:auto" if ARCH_ZYNQMP - 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 environemnt" - 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. - -if ARCH_SUNXI - -config ENV_OFFSET - hex "Environment Offset" - depends on !ENV_IS_IN_UBI - depends on !ENV_IS_NOWHERE - default 0x88000 if ARCH_SUNXI - help - Offset from the start of the device (or partition) - -config ENV_SIZE - hex "Environment Size" - depends on !ENV_IS_NOWHERE - default 0x20000 if ARCH_SUNXI - help - Size of the environment storage area - -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. - -endif - -endmenu - config BOOTDELAY int "delay in seconds before automatically booting" default 2 diff --git a/common/Makefile b/common/Makefile index 3ee7a6b18b..1b56cf9a70 100644 --- a/common/Makefile +++ b/common/Makefile @@ -19,7 +19,7 @@ ifdef CONFIG_BOOT_RETRY_TIME obj-y += bootretry.o endif -# boards +# # boards obj-y += board_f.o obj-y += board_r.o obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o @@ -29,29 +29,6 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o -# environment -obj-y += env_attr.o -obj-y += env_callback.o -obj-y += env_flags.o -obj-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o -obj-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o -extra-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o -obj-$(CONFIG_ENV_IS_IN_EEPROM) += env_embedded.o -extra-$(CONFIG_ENV_IS_IN_FLASH) += env_embedded.o -obj-$(CONFIG_ENV_IS_IN_NVRAM) += env_embedded.o -obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o -obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o -obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o -obj-$(CONFIG_ENV_IS_IN_EXT4) += env_ext4.o -obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o -obj-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o -obj-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o -obj-$(CONFIG_ENV_IS_IN_SATA) += env_sata.o -obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o -obj-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o -obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o -obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o - obj-$(CONFIG_CMD_BEDBUG) += bedbug.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o @@ -92,7 +69,6 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu.o obj-$(CONFIG_SPL_DFU_SUPPORT) += cli_hush.o obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o -obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o @@ -101,28 +77,7 @@ ifdef CONFIG_SPL_USB_HOST_SUPPORT obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif -# environment -ifdef CONFIG_TPL_BUILD -obj-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o -obj-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o -obj-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o -else -obj-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o -obj-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o -obj-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o -endif -ifneq ($(CONFIG_TPL_ENV_SUPPORT)$(CONFIG_SPL_ENV_SUPPORT),) -obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o -obj-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o -obj-$(CONFIG_ENV_IS_IN_FAT) += env_fat.o -obj-$(CONFIG_ENV_IS_IN_EXT4) += env_ext4.o -obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o -obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o -obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o -endif endif -#environment -obj-y += env_common.o #others obj-$(CONFIG_DDR_SPD) += ddr_spd.o obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o @@ -175,5 +130,3 @@ obj-$(CONFIG_CMD_DFU) += dfu.o obj-y += command.o obj-y += s_record.o obj-y += xyzModem.o - -CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff --git a/common/env_attr.c b/common/env_attr.c deleted file mode 100644 index f965b4bbb6..0000000000 --- a/common/env_attr.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * (C) Copyright 2012 - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */ -#include -#include -#include -#else -#include -#include -#endif - -#include -#include -#include -#include - -/* - * Iterate through the whole list calling the callback for each found element. - * "attr_list" takes the form: - * attributes = [^,:\s]* - * entry = name[:attributes] - * list = entry[,list] - */ -int env_attr_walk(const char *attr_list, - int (*callback)(const char *name, const char *attributes, void *priv), - void *priv) -{ - const char *entry, *entry_end; - char *name, *attributes; - - if (!attr_list) - /* list not found */ - return 1; - - entry = attr_list; - do { - char *entry_cpy = NULL; - - entry_end = strchr(entry, ENV_ATTR_LIST_DELIM); - /* check if this is the last entry in the list */ - if (entry_end == NULL) { - int entry_len = strlen(entry); - - if (entry_len) { - /* - * allocate memory to copy the entry into since - * we will need to inject '\0' chars and squash - * white-space before calling the callback - */ - entry_cpy = malloc(entry_len + 1); - if (entry_cpy) - /* copy the rest of the list */ - strcpy(entry_cpy, entry); - else - return -ENOMEM; - } - } else { - int entry_len = entry_end - entry; - - if (entry_len) { - /* - * allocate memory to copy the entry into since - * we will need to inject '\0' chars and squash - * white-space before calling the callback - */ - entry_cpy = malloc(entry_len + 1); - if (entry_cpy) { - /* copy just this entry and null term */ - strncpy(entry_cpy, entry, entry_len); - entry_cpy[entry_len] = '\0'; - } else - return -ENOMEM; - } - } - - /* check if there is anything to process (e.g. not ",,,") */ - if (entry_cpy != NULL) { - attributes = strchr(entry_cpy, ENV_ATTR_SEP); - /* check if there is a ':' */ - if (attributes != NULL) { - /* replace the ':' with '\0' to term name */ - *attributes++ = '\0'; - /* remove white-space from attributes */ - attributes = strim(attributes); - } - /* remove white-space from name */ - name = strim(entry_cpy); - - /* only call the callback if there is a name */ - if (strlen(name) != 0) { - int retval = 0; - - retval = callback(name, attributes, priv); - if (retval) { - free(entry_cpy); - return retval; - } - } - } - - free(entry_cpy); - entry = entry_end + 1; - } while (entry_end != NULL); - - return 0; -} - -#if defined(CONFIG_REGEX) -struct regex_callback_priv { - const char *searched_for; - char *regex; - char *attributes; -}; - -static int regex_callback(const char *name, const char *attributes, void *priv) -{ - int retval = 0; - struct regex_callback_priv *cbp = (struct regex_callback_priv *)priv; - struct slre slre; - char regex[strlen(name) + 3]; - - /* Require the whole string to be described by the regex */ - sprintf(regex, "^%s$", name); - if (slre_compile(&slre, regex)) { - struct cap caps[slre.num_caps + 2]; - - if (slre_match(&slre, cbp->searched_for, - strlen(cbp->searched_for), caps)) { - free(cbp->regex); - if (!attributes) { - retval = -EINVAL; - goto done; - } - cbp->regex = malloc(strlen(regex) + 1); - if (cbp->regex) { - strcpy(cbp->regex, regex); - } else { - retval = -ENOMEM; - goto done; - } - - free(cbp->attributes); - cbp->attributes = malloc(strlen(attributes) + 1); - if (cbp->attributes) { - strcpy(cbp->attributes, attributes); - } else { - retval = -ENOMEM; - free(cbp->regex); - cbp->regex = NULL; - goto done; - } - } - } else { - printf("Error compiling regex: %s\n", slre.err_str); - retval = -EINVAL; - } -done: - return retval; -} - -/* - * Retrieve the attributes string associated with a single name in the list - * There is no protection on attributes being too small for the value - */ -int env_attr_lookup(const char *attr_list, const char *name, char *attributes) -{ - if (!attributes) - /* bad parameter */ - return -EINVAL; - if (!attr_list) - /* list not found */ - return -EINVAL; - - struct regex_callback_priv priv; - int retval; - - priv.searched_for = name; - priv.regex = NULL; - priv.attributes = NULL; - retval = env_attr_walk(attr_list, regex_callback, &priv); - if (retval) - return retval; /* error */ - - if (priv.regex) { - strcpy(attributes, priv.attributes); - free(priv.attributes); - free(priv.regex); - /* success */ - return 0; - } - return -ENOENT; /* not found in list */ -} -#else - -/* - * Search for the last exactly matching name in an attribute list - */ -static int reverse_name_search(const char *searched, const char *search_for, - const char **result) -{ - int result_size = 0; - const char *cur_searched = searched; - - if (result) - *result = NULL; - - if (*search_for == '\0') { - if (result) - *result = searched; - return strlen(searched); - } - - for (;;) { - const char *match = strstr(cur_searched, search_for); - const char *prevch; - const char *nextch; - - /* Stop looking if no new match is found */ - if (match == NULL) - break; - - prevch = match - 1; - nextch = match + strlen(search_for); - - /* Skip spaces */ - while (*prevch == ' ' && prevch >= searched) - prevch--; - while (*nextch == ' ') - nextch++; - - /* Start looking past the current match so last is found */ - cur_searched = match + 1; - /* Check for an exact match */ - if (match != searched && - *prevch != ENV_ATTR_LIST_DELIM && - prevch != searched - 1) - continue; - if (*nextch != ENV_ATTR_SEP && - *nextch != ENV_ATTR_LIST_DELIM && - *nextch != '\0') - continue; - - if (result) - *result = match; - result_size = strlen(search_for); - } - - return result_size; -} - -/* - * Retrieve the attributes string associated with a single name in the list - * There is no protection on attributes being too small for the value - */ -int env_attr_lookup(const char *attr_list, const char *name, char *attributes) -{ - const char *entry = NULL; - int entry_len; - - if (!attributes) - /* bad parameter */ - return -EINVAL; - if (!attr_list) - /* list not found */ - return -EINVAL; - - entry_len = reverse_name_search(attr_list, name, &entry); - if (entry != NULL) { - int len; - - /* skip the name */ - entry += entry_len; - /* skip spaces */ - while (*entry == ' ') - entry++; - if (*entry != ENV_ATTR_SEP) - len = 0; - else { - const char *delim; - static const char delims[] = { - ENV_ATTR_LIST_DELIM, ' ', '\0'}; - - /* skip the attr sep */ - entry += 1; - /* skip spaces */ - while (*entry == ' ') - entry++; - - delim = strpbrk(entry, delims); - if (delim == NULL) - len = strlen(entry); - else - len = delim - entry; - memcpy(attributes, entry, len); - } - attributes[len] = '\0'; - - /* success */ - return 0; - } - - /* not found in list */ - return -ENOENT; -} -#endif diff --git a/common/env_callback.c b/common/env_callback.c deleted file mode 100644 index 1957cc1996..0000000000 --- a/common/env_callback.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * (C) Copyright 2012 - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#if defined(CONFIG_NEEDS_MANUAL_RELOC) -DECLARE_GLOBAL_DATA_PTR; -#endif - -/* - * Look up a callback function pointer by name - */ -static struct env_clbk_tbl *find_env_callback(const char *name) -{ - struct env_clbk_tbl *clbkp; - int i; - int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk); - - if (name == NULL) - return NULL; - - /* look up the callback in the linker-list */ - for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk); - i < num_callbacks; - i++, clbkp++) { - if (strcmp(name, clbkp->name) == 0) - return clbkp; - } - - return NULL; -} - -static int first_call = 1; -static const char *callback_list; - -/* - * Look for a possible callback for a newly added variable - * This is called specifically when the variable did not exist in the hash - * previously, so the blanket update did not find this variable. - */ -void env_callback_init(ENTRY *var_entry) -{ - const char *var_name = var_entry->key; - char callback_name[256] = ""; - struct env_clbk_tbl *clbkp; - int ret = 1; - - if (first_call) { - callback_list = getenv(ENV_CALLBACK_VAR); - first_call = 0; - } - - /* look in the ".callbacks" var for a reference to this variable */ - if (callback_list != NULL) - ret = env_attr_lookup(callback_list, var_name, callback_name); - - /* only if not found there, look in the static list */ - if (ret) - ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name, - callback_name); - - /* if an association was found, set the callback pointer */ - if (!ret && strlen(callback_name)) { - clbkp = find_env_callback(callback_name); - if (clbkp != NULL) -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - var_entry->callback = clbkp->callback + gd->reloc_off; -#else - var_entry->callback = clbkp->callback; -#endif - } -} - -/* - * Called on each existing env var prior to the blanket update since removing - * a callback association should remove its callback. - */ -static int clear_callback(ENTRY *entry) -{ - entry->callback = NULL; - - return 0; -} - -/* - * Call for each element in the list that associates variables to callbacks - */ -static int set_callback(const char *name, const char *value, void *priv) -{ - ENTRY e, *ep; - struct env_clbk_tbl *clbkp; - - e.key = name; - e.data = NULL; - e.callback = NULL; - hsearch_r(e, FIND, &ep, &env_htab, 0); - - /* does the env variable actually exist? */ - if (ep != NULL) { - /* the assocaition delares no callback, so remove the pointer */ - if (value == NULL || strlen(value) == 0) - ep->callback = NULL; - else { - /* assign the requested callback */ - clbkp = find_env_callback(value); - if (clbkp != NULL) -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - ep->callback = clbkp->callback + gd->reloc_off; -#else - ep->callback = clbkp->callback; -#endif - } - } - - return 0; -} - -static int on_callbacks(const char *name, const char *value, enum env_op op, - int flags) -{ - /* remove all callbacks */ - hwalk_r(&env_htab, clear_callback); - - /* configure any static callback bindings */ - env_attr_walk(ENV_CALLBACK_LIST_STATIC, set_callback, NULL); - /* configure any dynamic callback bindings */ - env_attr_walk(value, set_callback, NULL); - - return 0; -} -U_BOOT_ENV_CALLBACK(callbacks, on_callbacks); diff --git a/common/env_common.c b/common/env_common.c deleted file mode 100644 index d9c0c4e3f3..0000000000 --- a/common/env_common.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/************************************************************************ - * Default settings to be used when no valid environment is found - */ -#include - -struct hsearch_data env_htab = { - .change_ok = env_flags_validate, -}; - -__weak uchar env_get_char_spec(int index) -{ - return *((uchar *)(gd->env_addr + index)); -} - -static uchar env_get_char_init(int index) -{ - /* if crc was bad, use the default environment */ - if (gd->env_valid) - return env_get_char_spec(index); - else - return default_environment[index]; -} - -uchar env_get_char_memory(int index) -{ - return *env_get_addr(index); -} - -uchar env_get_char(int index) -{ - /* if relocated to RAM */ - if (gd->flags & GD_FLG_RELOC) - return env_get_char_memory(index); - else - return env_get_char_init(index); -} - -const uchar *env_get_addr(int index) -{ - if (gd->env_valid) - return (uchar *)(gd->env_addr + index); - else - return &default_environment[index]; -} - -/* - * Read an environment variable as a boolean - * Return -1 if variable does not exist (default to true) - */ -int getenv_yesno(const char *var) -{ - char *s = getenv(var); - - if (s == NULL) - return -1; - return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ? - 1 : 0; -} - -/* - * Look up the variable from the default environment - */ -char *getenv_default(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 = 0; - ret_val = getenv(name); - gd->env_valid = really_valid; - gd->flags = real_gd_flags; - return ret_val; -} - -void set_default_env(const char *s) -{ - int flags = 0; - - if (sizeof(default_environment) > ENV_SIZE) { - puts("*** Error - default environment is too large\n\n"); - return; - } - - if (s) { - if (*s == '!') { - printf("*** Warning - %s, " - "using default environment\n\n", - s + 1); - } else { - flags = H_INTERACTIVE; - puts(s); - } - } else { - puts("Using default environment\n\n"); - } - - if (himport_r(&env_htab, (char *)default_environment, - sizeof(default_environment), '\0', flags, 0, - 0, NULL) == 0) - 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 set_default_vars(int nvars, char * const vars[]) -{ - /* - * Special use-case: import from default environment - * (and use \0 as a separator) - */ - return himport_r(&env_htab, (const char *)default_environment, - sizeof(default_environment), '\0', - H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars); -} - -#ifdef CONFIG_ENV_AES -#include -/** - * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment - * - * This function shall return 16-byte array containing AES-128 key used - * to encrypt and decrypt the environment. This function must be overridden - * by the implementer as otherwise the environment encryption will not - * work. - */ -__weak uint8_t *env_aes_cbc_get_key(void) -{ - return NULL; -} - -static int env_aes_cbc_crypt(env_t *env, const int enc) -{ - unsigned char *data = env->data; - uint8_t *key; - uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; - uint32_t aes_blocks; - - key = env_aes_cbc_get_key(); - if (!key) - return -EINVAL; - - /* First we expand the key. */ - aes_expand_key(key, key_exp); - - /* Calculate the number of AES blocks to encrypt. */ - aes_blocks = ENV_SIZE / AES_KEY_LENGTH; - - if (enc) - aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); - else - aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); - - return 0; -} -#else -static inline int env_aes_cbc_crypt(env_t *env, const int enc) -{ - return 0; -} -#endif - -/* - * Check if CRC is valid and (if yes) import the environment. - * Note that "buf" may or may not be aligned. - */ -int env_import(const char *buf, int check) -{ - env_t *ep = (env_t *)buf; - int ret; - - if (check) { - uint32_t crc; - - memcpy(&crc, &ep->crc, sizeof(crc)); - - if (crc32(0, ep->data, ENV_SIZE) != crc) { - set_default_env("!bad CRC"); - return 0; - } - } - - /* Decrypt the env if desired. */ - ret = env_aes_cbc_crypt(ep, 0); - if (ret) { - error("Failed to decrypt env!\n"); - set_default_env("!import failed"); - return ret; - } - - if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, - 0, NULL)) { - gd->flags |= GD_FLG_ENV_READY; - return 1; - } - - error("Cannot import environment: errno = %d\n", errno); - - set_default_env("!import failed"); - - return 0; -} - -#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT -static unsigned char env_flags; - -int env_import_redund(const char *buf1, const char *buf2) -{ - int crc1_ok, crc2_ok; - env_t *ep, *tmp_env1, *tmp_env2; - - tmp_env1 = (env_t *)buf1; - tmp_env2 = (env_t *)buf2; - - 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) { - set_default_env("!bad CRC"); - return 0; - } 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; - } - - if (gd->env_valid == 1) - ep = tmp_env1; - else - ep = tmp_env2; - - env_flags = ep->flags; - return env_import((char *)ep, 0); -} -#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ - -/* Export the environment and generate CRC for it. */ -int env_export(env_t *env_out) -{ - char *res; - ssize_t len; - int ret; - - res = (char *)env_out->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - - /* Encrypt the env if desired. */ - ret = env_aes_cbc_crypt(env_out, 1); - if (ret) - return ret; - - env_out->crc = crc32(0, env_out->data, ENV_SIZE); - -#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT - env_out->flags = ++env_flags; /* increase the serial */ -#endif - - return 0; -} - -void env_relocate(void) -{ -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - env_reloc(); - env_htab.change_ok += gd->reloc_off; -#endif - if (gd->env_valid == 0) { -#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD) - /* Environment not changable */ - set_default_env(NULL); -#else - bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM); - set_default_env("!bad CRC"); -#endif - } else { - env_relocate_spec(); - } -} - -#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) -int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) -{ - ENTRY *match; - int found, idx; - - idx = 0; - found = 0; - cmdv[0] = NULL; - - while ((idx = hmatch_r(var, idx, &match, &env_htab))) { - int vallen = strlen(match->key) + 1; - - if (found >= maxv - 2 || bufsz < vallen) - break; - - cmdv[found++] = buf; - memcpy(buf, match->key, vallen); - buf += vallen; - bufsz -= vallen; - } - - qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); - - if (idx) - cmdv[found++] = "..."; - - cmdv[found] = NULL; - return found; -} -#endif diff --git a/common/env_dataflash.c b/common/env_dataflash.c deleted file mode 100644 index 034e323169..0000000000 --- a/common/env_dataflash.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * LowLevel function for DataFlash environment support - * Author : Gilles Gastaldi (Atmel) - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -env_t *env_ptr; - -char *env_name_spec = "dataflash"; - -uchar env_get_char_spec(int index) -{ - uchar c; - - read_dataflash(CONFIG_ENV_ADDR + index + offsetof(env_t, data), - 1, (char *)&c); - return c; -} - -void env_relocate_spec(void) -{ - ulong crc, new = 0; - unsigned off; - char buf[CONFIG_ENV_SIZE]; - - /* Read old CRC */ - read_dataflash(CONFIG_ENV_ADDR + offsetof(env_t, crc), - sizeof(ulong), (char *)&crc); - - /* Read whole environment */ - read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, buf); - - /* Calculate the CRC */ - off = offsetof(env_t, data); - new = crc32(new, (unsigned char *)(buf + off), ENV_SIZE); - - if (crc == new) - env_import(buf, 1); - else - set_default_env("!bad CRC"); -} - -#ifdef CONFIG_ENV_OFFSET_REDUND -#error No support for redundant environment on dataflash yet! -#endif - -int saveenv(void) -{ - env_t env_new; - int ret; - - ret = env_export(&env_new); - if (ret) - return ret; - - return write_dataflash(CONFIG_ENV_ADDR, - (unsigned long)&env_new, - CONFIG_ENV_SIZE); -} - -/* - * Initialize environment use - * - * We are still running from ROM, so data use is limited. - * Use a (moderately small) buffer on the stack - */ -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} diff --git a/common/env_eeprom.c b/common/env_eeprom.c deleted file mode 100644 index 5f63a6cd4a..0000000000 --- a/common/env_eeprom.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#if defined(CONFIG_I2C_ENV_EEPROM_BUS) -#include -#endif -#include -#include -#include /* for BUG_ON */ - -DECLARE_GLOBAL_DATA_PTR; - -env_t *env_ptr; - -char *env_name_spec = "EEPROM"; - -static int eeprom_bus_read(unsigned dev_addr, unsigned offset, - uchar *buffer, unsigned cnt) -{ - int rcode; -#if defined(CONFIG_I2C_ENV_EEPROM_BUS) - int old_bus = i2c_get_bus_num(); - - if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS) - i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS); -#endif - - rcode = eeprom_read(dev_addr, offset, buffer, cnt); - -#if defined(CONFIG_I2C_ENV_EEPROM_BUS) - i2c_set_bus_num(old_bus); -#endif - - return rcode; -} - -static int eeprom_bus_write(unsigned dev_addr, unsigned offset, - uchar *buffer, unsigned cnt) -{ - int rcode; -#if defined(CONFIG_I2C_ENV_EEPROM_BUS) - int old_bus = i2c_get_bus_num(); - - if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS) - i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS); -#endif - - rcode = eeprom_write(dev_addr, offset, buffer, cnt); - -#if defined(CONFIG_I2C_ENV_EEPROM_BUS) - i2c_set_bus_num(old_bus); -#endif - - return rcode; -} - -uchar env_get_char_spec(int index) -{ - uchar c; - unsigned int off = CONFIG_ENV_OFFSET; - -#ifdef CONFIG_ENV_OFFSET_REDUND - if (gd->env_valid == 2) - off = CONFIG_ENV_OFFSET_REDUND; -#endif - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - off + index + offsetof(env_t, data), &c, 1); - - return c; -} - -void env_relocate_spec(void) -{ - char buf_env[CONFIG_ENV_SIZE]; - unsigned int off = CONFIG_ENV_OFFSET; - -#ifdef CONFIG_ENV_OFFSET_REDUND - ulong len, crc[2], crc_tmp; - unsigned int off_env[2]; - uchar rdbuf[64], flags[2]; - int i, crc_ok[2] = {0, 0}; - - eeprom_init(-1); /* prepare for EEPROM read/write */ - - off_env[0] = CONFIG_ENV_OFFSET; - off_env[1] = CONFIG_ENV_OFFSET_REDUND; - - for (i = 0; i < 2; i++) { - /* read CRC */ - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - off_env[i] + offsetof(env_t, crc), - (uchar *)&crc[i], sizeof(ulong)); - /* read FLAGS */ - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - off_env[i] + offsetof(env_t, flags), - (uchar *)&flags[i], sizeof(uchar)); - - crc_tmp = 0; - len = ENV_SIZE; - off = off_env[i] + offsetof(env_t, data); - while (len > 0) { - int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; - - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, off, - rdbuf, n); - - crc_tmp = crc32(crc_tmp, rdbuf, n); - len -= n; - off += n; - } - - if (crc_tmp == crc[i]) - crc_ok[i] = 1; - } - - if (!crc_ok[0] && !crc_ok[1]) { - gd->env_addr = 0; - gd->env_valid = 0; - } else if (crc_ok[0] && !crc_ok[1]) { - gd->env_valid = 1; - } else if (!crc_ok[0] && crc_ok[1]) { - gd->env_valid = 2; - } else { - /* both ok - check serial */ - if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG) - gd->env_valid = 1; - else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG) - gd->env_valid = 2; - else if (flags[0] == 0xFF && flags[1] == 0) - gd->env_valid = 2; - else if (flags[1] == 0xFF && flags[0] == 0) - gd->env_valid = 1; - else /* flags are equal - almost impossible */ - gd->env_valid = 1; - } - -#else /* CONFIG_ENV_OFFSET_REDUND */ - ulong crc, len, new; - uchar rdbuf[64]; - - eeprom_init(-1); /* prepare for EEPROM read/write */ - - /* read old CRC */ - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - CONFIG_ENV_OFFSET + offsetof(env_t, crc), - (uchar *)&crc, sizeof(ulong)); - - new = 0; - len = ENV_SIZE; - off = offsetof(env_t, data); - while (len > 0) { - int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; - - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - CONFIG_ENV_OFFSET + off, rdbuf, n); - new = crc32(new, rdbuf, n); - len -= n; - off += n; - } - - if (crc == new) { - gd->env_valid = 1; - } else { - gd->env_valid = 0; - } -#endif /* CONFIG_ENV_OFFSET_REDUND */ - - off = CONFIG_ENV_OFFSET; -#ifdef CONFIG_ENV_OFFSET_REDUND - if (gd->env_valid == 2) - off = CONFIG_ENV_OFFSET_REDUND; -#endif - - eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, - off, (uchar *)buf_env, CONFIG_ENV_SIZE); - - env_import(buf_env, 1); -} - -int saveenv(void) -{ - env_t env_new; - int rc; - unsigned int off = CONFIG_ENV_OFFSET; -#ifdef CONFIG_ENV_OFFSET_REDUND - unsigned int off_red = CONFIG_ENV_OFFSET_REDUND; - char flag_obsolete = OBSOLETE_FLAG; -#endif - - BUG_ON(env_ptr != NULL); - - rc = env_export(&env_new); - if (rc) - return rc; - -#ifdef CONFIG_ENV_OFFSET_REDUND - if (gd->env_valid == 1) { - off = CONFIG_ENV_OFFSET_REDUND; - off_red = CONFIG_ENV_OFFSET; - } - - env_new.flags = ACTIVE_FLAG; -#endif - - rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR, - off, (uchar *)&env_new, CONFIG_ENV_SIZE); - -#ifdef CONFIG_ENV_OFFSET_REDUND - if (rc == 0) { - eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR, - off_red + offsetof(env_t, flags), - (uchar *)&flag_obsolete, 1); - - if (gd->env_valid == 1) - gd->env_valid = 2; - else - gd->env_valid = 1; - } -#endif - return rc; -} - -/* - * Initialize Environment use - * - * We are still running from ROM, so data use is limited. - * Use a (moderately small) buffer on the stack - */ -int env_init(void) -{ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - return 0; -} diff --git a/common/env_embedded.c b/common/env_embedded.c deleted file mode 100644 index 43694db70f..0000000000 --- a/common/env_embedded.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * (C) Copyright 2001 - * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#ifndef __ASSEMBLY__ -#define __ASSEMBLY__ /* Dirty trick to get only #defines */ -#endif -#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ -#include -#undef __ASSEMBLY__ -#include -#include - -/* Handle HOSTS that have prepended crap on symbol names, not TARGETS. */ -#if defined(__APPLE__) -/* Leading underscore on symbols */ -# define SYM_CHAR "_" -#else /* No leading character on symbols */ -# define SYM_CHAR -#endif - -/* - * Generate embedded environment table - * inside U-Boot image, if needed. - */ -#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_BUILD_ENVCRC) -/* - * Put the environment in the .text section when we are building - * U-Boot proper. The host based program "tools/envcrc" does not need - * a seperate section. - */ -#if defined(USE_HOSTCC) /* Native for 'tools/envcrc' */ -# define __UBOOT_ENV_SECTION__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ - -#else /* Environment is embedded in U-Boot's .text section */ -/* XXX - This only works with GNU C */ -# define __UBOOT_ENV_SECTION__ __attribute__ ((section(".text"))) -#endif - -/* - * Macros to generate global absolutes. - */ -#if defined(__bfin__) -# define GEN_SET_VALUE(name, value) \ - asm(".set " GEN_SYMNAME(name) ", " GEN_VALUE(value)) -#else -# define GEN_SET_VALUE(name, value) \ - asm(GEN_SYMNAME(name) " = " GEN_VALUE(value)) -#endif -#define GEN_SYMNAME(str) SYM_CHAR #str -#define GEN_VALUE(str) #str -#define GEN_ABS(name, value) \ - asm(".globl " GEN_SYMNAME(name)); \ - GEN_SET_VALUE(name, value) - -/* - * Check to see if we are building with a - * computed CRC. Otherwise define it as ~0. - */ -#if !defined(ENV_CRC) -# define ENV_CRC (~0) -#endif - -#define DEFAULT_ENV_INSTANCE_EMBEDDED -#include - -#ifdef CONFIG_ENV_ADDR_REDUND -env_t redundand_environment __UBOOT_ENV_SECTION__ = { - 0, /* CRC Sum: invalid */ - 0, /* Flags: invalid */ - { - "\0" - } -}; -#endif /* CONFIG_ENV_ADDR_REDUND */ - -/* - * These will end up in the .text section - * if the environment strings are embedded - * in the image. When this is used for - * tools/envcrc, they are placed in the - * .data/.sdata section. - * - */ -unsigned long env_size __UBOOT_ENV_SECTION__ = sizeof(env_t); - -/* - * Add in absolutes. - */ -GEN_ABS(env_offset, CONFIG_ENV_OFFSET); - -#endif /* ENV_IS_EMBEDDED */ diff --git a/common/env_ext4.c b/common/env_ext4.c deleted file mode 100644 index adefa7dc99..0000000000 --- a/common/env_ext4.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * (c) Copyright 2016 by VRT Technology - * - * Author: - * Stuart Longland - * - * Based on FAT environment driver - * (c) Copyright 2011 by Tigris Elektronik GmbH - * - * Author: - * Maximilian Schwerin - * - * and EXT4 filesystem implementation - * (C) Copyright 2011 - 2012 Samsung Electronics - * EXT4 filesystem implementation in Uboot by - * Uma Shankar - * Manjunatha C Achar - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -char *env_name_spec = "EXT4"; - -env_t *env_ptr; - -DECLARE_GLOBAL_DATA_PTR; - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} - -#ifdef CONFIG_CMD_SAVEENV -int saveenv(void) -{ - env_t env_new; - struct blk_desc *dev_desc = NULL; - disk_partition_t info; - int dev, part; - int err; - - err = env_export(&env_new); - if (err) - return err; - - part = blk_get_device_part_str(EXT4_ENV_INTERFACE, - EXT4_ENV_DEVICE_AND_PART, - &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->devnum; - ext4fs_set_blk_dev(dev_desc, &info); - - if (!ext4fs_mount(info.size)) { - printf("\n** Unable to use %s %s for saveenv **\n", - EXT4_ENV_INTERFACE, EXT4_ENV_DEVICE_AND_PART); - return 1; - } - - err = ext4fs_write(EXT4_ENV_FILE, (void *)&env_new, sizeof(env_t)); - ext4fs_close(); - - if (err == -1) { - printf("\n** Unable to write \"%s\" from %s%d:%d **\n", - EXT4_ENV_FILE, EXT4_ENV_INTERFACE, dev, part); - return 1; - } - - puts("done\n"); - return 0; -} -#endif /* CONFIG_CMD_SAVEENV */ - -void env_relocate_spec(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - struct blk_desc *dev_desc = NULL; - disk_partition_t info; - int dev, part; - int err; - loff_t off; - - part = blk_get_device_part_str(EXT4_ENV_INTERFACE, - EXT4_ENV_DEVICE_AND_PART, - &dev_desc, &info, 1); - if (part < 0) - goto err_env_relocate; - - dev = dev_desc->devnum; - ext4fs_set_blk_dev(dev_desc, &info); - - if (!ext4fs_mount(info.size)) { - printf("\n** Unable to use %s %s for loading the env **\n", - EXT4_ENV_INTERFACE, EXT4_ENV_DEVICE_AND_PART); - goto err_env_relocate; - } - - err = ext4_read_file(EXT4_ENV_FILE, buf, 0, CONFIG_ENV_SIZE, &off); - ext4fs_close(); - - if (err == -1) { - printf("\n** Unable to read \"%s\" from %s%d:%d **\n", - EXT4_ENV_FILE, EXT4_ENV_INTERFACE, dev, part); - goto err_env_relocate; - } - - env_import(buf, 1); - return; - -err_env_relocate: - set_default_env(NULL); -} diff --git a/common/env_fat.c b/common/env_fat.c deleted file mode 100644 index b51c920cd4..0000000000 --- a/common/env_fat.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * (c) Copyright 2011 by Tigris Elektronik GmbH - * - * Author: - * Maximilian Schwerin - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -char *env_name_spec = "FAT"; - -env_t *env_ptr; - -DECLARE_GLOBAL_DATA_PTR; - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} - -#ifdef CONFIG_CMD_SAVEENV -int saveenv(void) -{ - env_t env_new; - struct blk_desc *dev_desc = NULL; - disk_partition_t info; - int dev, part; - int err; - loff_t size; - - err = env_export(&env_new); - if (err) - return err; - - part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE, - CONFIG_ENV_FAT_DEVICE_AND_PART, - &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->devnum; - if (fat_set_blk_dev(dev_desc, &info) != 0) { - printf("\n** Unable to use %s %d:%d for saveenv **\n", - CONFIG_ENV_FAT_INTERFACE, dev, part); - return 1; - } - - err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t), - &size); - if (err == -1) { - printf("\n** Unable to write \"%s\" from %s%d:%d **\n", - CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part); - return 1; - } - - puts("done\n"); - return 0; -} -#endif /* CONFIG_CMD_SAVEENV */ - -void env_relocate_spec(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - struct blk_desc *dev_desc = NULL; - disk_partition_t info; - int dev, part; - int err; - - part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE, - CONFIG_ENV_FAT_DEVICE_AND_PART, - &dev_desc, &info, 1); - if (part < 0) - goto err_env_relocate; - - dev = dev_desc->devnum; - if (fat_set_blk_dev(dev_desc, &info) != 0) { - printf("\n** Unable to use %s %d:%d for loading the env **\n", - CONFIG_ENV_FAT_INTERFACE, dev, part); - goto err_env_relocate; - } - - err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE); - if (err == -1) { - printf("\n** Unable to read \"%s\" from %s%d:%d **\n", - CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part); - goto err_env_relocate; - } - - env_import(buf, 1); - return; - -err_env_relocate: - set_default_env(NULL); -} diff --git a/common/env_flags.c b/common/env_flags.c deleted file mode 100644 index 3c50620cb3..0000000000 --- a/common/env_flags.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * (C) Copyright 2012 - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */ -#include -#include -#include "fw_env_private.h" -#include "fw_env.h" -#include -#include -#define getenv fw_getenv -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#else -#include -#include -#endif - -#ifdef CONFIG_CMD_NET -#define ENV_FLAGS_NET_VARTYPE_REPS "im" -#else -#define ENV_FLAGS_NET_VARTYPE_REPS "" -#endif - -static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS; -static const char env_flags_varaccess_rep[] = "aroc"; -static const int env_flags_varaccess_mask[] = { - 0, - ENV_FLAGS_VARACCESS_PREVENT_DELETE | - ENV_FLAGS_VARACCESS_PREVENT_CREATE | - ENV_FLAGS_VARACCESS_PREVENT_OVERWR, - ENV_FLAGS_VARACCESS_PREVENT_DELETE | - ENV_FLAGS_VARACCESS_PREVENT_OVERWR, - ENV_FLAGS_VARACCESS_PREVENT_DELETE | - ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR}; - -#ifdef CONFIG_CMD_ENV_FLAGS -static const char * const env_flags_vartype_names[] = { - "string", - "decimal", - "hexadecimal", - "boolean", -#ifdef CONFIG_CMD_NET - "IP address", - "MAC address", -#endif -}; -static const char * const env_flags_varaccess_names[] = { - "any", - "read-only", - "write-once", - "change-default", -}; - -/* - * Print the whole list of available type flags. - */ -void env_flags_print_vartypes(void) -{ - enum env_flags_vartype curtype = (enum env_flags_vartype)0; - - while (curtype != env_flags_vartype_end) { - printf("\t%c -\t%s\n", env_flags_vartype_rep[curtype], - env_flags_vartype_names[curtype]); - curtype++; - } -} - -/* - * Print the whole list of available access flags. - */ -void env_flags_print_varaccess(void) -{ - enum env_flags_varaccess curaccess = (enum env_flags_varaccess)0; - - while (curaccess != env_flags_varaccess_end) { - printf("\t%c -\t%s\n", env_flags_varaccess_rep[curaccess], - env_flags_varaccess_names[curaccess]); - curaccess++; - } -} - -/* - * Return the name of the type. - */ -const char *env_flags_get_vartype_name(enum env_flags_vartype type) -{ - return env_flags_vartype_names[type]; -} - -/* - * Return the name of the access. - */ -const char *env_flags_get_varaccess_name(enum env_flags_varaccess access) -{ - return env_flags_varaccess_names[access]; -} -#endif /* CONFIG_CMD_ENV_FLAGS */ - -/* - * Parse the flags string from a .flags attribute list into the vartype enum. - */ -enum env_flags_vartype env_flags_parse_vartype(const char *flags) -{ - char *type; - - if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC) - return env_flags_vartype_string; - - type = strchr(env_flags_vartype_rep, - flags[ENV_FLAGS_VARTYPE_LOC]); - - if (type != NULL) - return (enum env_flags_vartype) - (type - &env_flags_vartype_rep[0]); - - printf("## Warning: Unknown environment variable type '%c'\n", - flags[ENV_FLAGS_VARTYPE_LOC]); - return env_flags_vartype_string; -} - -/* - * Parse the flags string from a .flags attribute list into the varaccess enum. - */ -enum env_flags_varaccess env_flags_parse_varaccess(const char *flags) -{ - char *access; - - if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) - return env_flags_varaccess_any; - - access = strchr(env_flags_varaccess_rep, - flags[ENV_FLAGS_VARACCESS_LOC]); - - if (access != NULL) - return (enum env_flags_varaccess) - (access - &env_flags_varaccess_rep[0]); - - printf("## Warning: Unknown environment variable access method '%c'\n", - flags[ENV_FLAGS_VARACCESS_LOC]); - return env_flags_varaccess_any; -} - -/* - * Parse the binary flags from a hash table entry into the varaccess enum. - */ -enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(env_flags_varaccess_mask); i++) - if (env_flags_varaccess_mask[i] == - (binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) - return (enum env_flags_varaccess)i; - - printf("Warning: Non-standard access flags. (0x%x)\n", - binflags & ENV_FLAGS_VARACCESS_BIN_MASK); - - return env_flags_varaccess_any; -} - -static inline int is_hex_prefix(const char *value) -{ - return value[0] == '0' && (value[1] == 'x' || value[1] == 'X'); -} - -static void skip_num(int hex, const char *value, const char **end, - int max_digits) -{ - int i; - - if (hex && is_hex_prefix(value)) - value += 2; - - for (i = max_digits; i != 0; i--) { - if (hex && !isxdigit(*value)) - break; - if (!hex && !isdigit(*value)) - break; - value++; - } - if (end != NULL) - *end = value; -} - -#ifdef CONFIG_CMD_NET -int eth_validate_ethaddr_str(const char *addr) -{ - const char *end; - const char *cur; - int i; - - cur = addr; - for (i = 0; i < 6; i++) { - skip_num(1, cur, &end, 2); - if (cur == end) - return -1; - if (cur + 2 == end && is_hex_prefix(cur)) - return -1; - if (i != 5 && *end != ':') - return -1; - if (i == 5 && *end != '\0') - return -1; - cur = end + 1; - } - - return 0; -} -#endif - -/* - * Based on the declared type enum, validate that the value string complies - * with that format - */ -static int _env_flags_validate_type(const char *value, - enum env_flags_vartype type) -{ - const char *end; -#ifdef CONFIG_CMD_NET - const char *cur; - int i; -#endif - - switch (type) { - case env_flags_vartype_string: - break; - case env_flags_vartype_decimal: - skip_num(0, value, &end, -1); - if (*end != '\0') - return -1; - break; - case env_flags_vartype_hex: - skip_num(1, value, &end, -1); - if (*end != '\0') - return -1; - if (value + 2 == end && is_hex_prefix(value)) - return -1; - break; - case env_flags_vartype_bool: - if (value[0] != '1' && value[0] != 'y' && value[0] != 't' && - value[0] != 'Y' && value[0] != 'T' && - value[0] != '0' && value[0] != 'n' && value[0] != 'f' && - value[0] != 'N' && value[0] != 'F') - return -1; - if (value[1] != '\0') - return -1; - break; -#ifdef CONFIG_CMD_NET - case env_flags_vartype_ipaddr: - cur = value; - for (i = 0; i < 4; i++) { - skip_num(0, cur, &end, 3); - if (cur == end) - return -1; - if (i != 3 && *end != '.') - return -1; - if (i == 3 && *end != '\0') - return -1; - cur = end + 1; - } - break; - case env_flags_vartype_macaddr: - if (eth_validate_ethaddr_str(value)) - return -1; - break; -#endif - case env_flags_vartype_end: - return -1; - } - - /* OK */ - return 0; -} - -/* - * Look for flags in a provided list and failing that the static list - */ -static inline int env_flags_lookup(const char *flags_list, const char *name, - char *flags) -{ - int ret = 1; - - if (!flags) - /* bad parameter */ - return -1; - - /* try the env first */ - if (flags_list) - ret = env_attr_lookup(flags_list, name, flags); - - if (ret != 0) - /* if not found in the env, look in the static list */ - ret = env_attr_lookup(ENV_FLAGS_LIST_STATIC, name, flags); - - return ret; -} - -#ifdef USE_HOSTCC /* Functions only used from tools/env */ -/* - * Look up any flags directly from the .flags variable and the static list - * and convert them to the vartype enum. - */ -enum env_flags_vartype env_flags_get_type(const char *name) -{ - const char *flags_list = getenv(ENV_FLAGS_VAR); - char flags[ENV_FLAGS_ATTR_MAX_LEN + 1]; - - if (env_flags_lookup(flags_list, name, flags)) - return env_flags_vartype_string; - - if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC) - return env_flags_vartype_string; - - return env_flags_parse_vartype(flags); -} - -/* - * Look up the access of a variable directly from the .flags var. - */ -enum env_flags_varaccess env_flags_get_varaccess(const char *name) -{ - const char *flags_list = getenv(ENV_FLAGS_VAR); - char flags[ENV_FLAGS_ATTR_MAX_LEN + 1]; - - if (env_flags_lookup(flags_list, name, flags)) - return env_flags_varaccess_any; - - if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) - return env_flags_varaccess_any; - - return env_flags_parse_varaccess(flags); -} - -/* - * Validate that the proposed new value for "name" is valid according to the - * defined flags for that variable, if any. - */ -int env_flags_validate_type(const char *name, const char *value) -{ - enum env_flags_vartype type; - - if (value == NULL) - return 0; - type = env_flags_get_type(name); - if (_env_flags_validate_type(value, type) < 0) { - printf("## Error: flags type check failure for " - "\"%s\" <= \"%s\" (type: %c)\n", - name, value, env_flags_vartype_rep[type]); - return -1; - } - return 0; -} - -/* - * Validate that the proposed access to variable "name" is valid according to - * the defined flags for that variable, if any. - */ -int env_flags_validate_varaccess(const char *name, int check_mask) -{ - enum env_flags_varaccess access; - int access_mask; - - access = env_flags_get_varaccess(name); - access_mask = env_flags_varaccess_mask[access]; - - return (check_mask & access_mask) != 0; -} - -/* - * Validate the parameters to "env set" directly - */ -int env_flags_validate_env_set_params(char *name, char * const val[], int count) -{ - if ((count >= 1) && val[0] != NULL) { - enum env_flags_vartype type = env_flags_get_type(name); - - /* - * we don't currently check types that need more than - * one argument - */ - if (type != env_flags_vartype_string && count > 1) { - printf("## Error: too many parameters for setting \"%s\"\n", - name); - return -1; - } - return env_flags_validate_type(name, val[0]); - } - /* ok */ - return 0; -} - -#else /* !USE_HOSTCC - Functions only used from lib/hashtable.c */ - -/* - * Parse the flag charachters from the .flags attribute list into the binary - * form to be stored in the environment entry->flags field. - */ -static int env_parse_flags_to_bin(const char *flags) -{ - int binflags; - - binflags = env_flags_parse_vartype(flags) & ENV_FLAGS_VARTYPE_BIN_MASK; - binflags |= env_flags_varaccess_mask[env_flags_parse_varaccess(flags)]; - - return binflags; -} - -static int first_call = 1; -static const char *flags_list; - -/* - * Look for possible flags for a newly added variable - * This is called specifically when the variable did not exist in the hash - * previously, so the blanket update did not find this variable. - */ -void env_flags_init(ENTRY *var_entry) -{ - const char *var_name = var_entry->key; - char flags[ENV_FLAGS_ATTR_MAX_LEN + 1] = ""; - int ret = 1; - - if (first_call) { - flags_list = getenv(ENV_FLAGS_VAR); - first_call = 0; - } - /* look in the ".flags" and static for a reference to this variable */ - ret = env_flags_lookup(flags_list, var_name, flags); - - /* if any flags were found, set the binary form to the entry */ - if (!ret && strlen(flags)) - var_entry->flags = env_parse_flags_to_bin(flags); -} - -/* - * Called on each existing env var prior to the blanket update since removing - * a flag in the flag list should remove its flags. - */ -static int clear_flags(ENTRY *entry) -{ - entry->flags = 0; - - return 0; -} - -/* - * Call for each element in the list that defines flags for a variable - */ -static int set_flags(const char *name, const char *value, void *priv) -{ - ENTRY e, *ep; - - e.key = name; - e.data = NULL; - e.callback = NULL; - hsearch_r(e, FIND, &ep, &env_htab, 0); - - /* does the env variable actually exist? */ - if (ep != NULL) { - /* the flag list is empty, so clear the flags */ - if (value == NULL || strlen(value) == 0) - ep->flags = 0; - else - /* assign the requested flags */ - ep->flags = env_parse_flags_to_bin(value); - } - - return 0; -} - -static int on_flags(const char *name, const char *value, enum env_op op, - int flags) -{ - /* remove all flags */ - hwalk_r(&env_htab, clear_flags); - - /* configure any static flags */ - env_attr_walk(ENV_FLAGS_LIST_STATIC, set_flags, NULL); - /* configure any dynamic flags */ - env_attr_walk(value, set_flags, NULL); - - return 0; -} -U_BOOT_ENV_CALLBACK(flags, on_flags); - -/* - * Perform consistency checking before creating, overwriting, or deleting an - * environment variable. Called as a callback function by hsearch_r() and - * hdelete_r(). Returns 0 in case of success, 1 in case of failure. - * When (flag & H_FORCE) is set, do not print out any error message and force - * overwriting of write-once variables. - */ - -int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op, - int flag) -{ - const char *name; - const char *oldval = NULL; - - if (op != env_op_create) - oldval = item->data; - - name = item->key; - - /* Default value for NULL to protect string-manipulating functions */ - newval = newval ? : ""; - - /* validate the value to match the variable type */ - if (op != env_op_delete) { - enum env_flags_vartype type = (enum env_flags_vartype) - (ENV_FLAGS_VARTYPE_BIN_MASK & item->flags); - - if (_env_flags_validate_type(newval, type) < 0) { - printf("## Error: flags type check failure for " - "\"%s\" <= \"%s\" (type: %c)\n", - name, newval, env_flags_vartype_rep[type]); - return -1; - } - } - - /* check for access permission */ -#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE - if (flag & H_FORCE) - return 0; -#endif - switch (op) { - case env_op_delete: - if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) { - printf("## Error: Can't delete \"%s\"\n", name); - return 1; - } - break; - case env_op_overwrite: - if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_OVERWR) { - printf("## Error: Can't overwrite \"%s\"\n", name); - return 1; - } else if (item->flags & - ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR) { - const char *defval = getenv_default(name); - - if (defval == NULL) - defval = ""; - printf("oldval: %s defval: %s\n", oldval, defval); - if (strcmp(oldval, defval) != 0) { - printf("## Error: Can't overwrite \"%s\"\n", - name); - return 1; - } - } - break; - case env_op_create: - if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_CREATE) { - printf("## Error: Can't create \"%s\"\n", name); - return 1; - } - break; - } - - return 0; -} - -#endif diff --git a/common/env_flash.c b/common/env_flash.c deleted file mode 100644 index 004e8849a7..0000000000 --- a/common/env_flash.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_FLASH) -#define CMD_SAVEENV -#elif defined(CONFIG_ENV_ADDR_REDUND) -#error CONFIG_ENV_ADDR_REDUND must have CONFIG_CMD_SAVEENV & CONFIG_CMD_FLASH -#endif - -#if defined(CONFIG_ENV_SIZE_REDUND) && \ - (CONFIG_ENV_SIZE_REDUND < CONFIG_ENV_SIZE) -#error CONFIG_ENV_SIZE_REDUND should not be less then CONFIG_ENV_SIZE -#endif - -char *env_name_spec = "Flash"; - -#ifdef ENV_IS_EMBEDDED -env_t *env_ptr = &environment; - -static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; - -#else /* ! ENV_IS_EMBEDDED */ - -env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; -static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; -#endif /* ENV_IS_EMBEDDED */ - -#if defined(CMD_SAVEENV) || defined(CONFIG_ENV_ADDR_REDUND) -/* CONFIG_ENV_ADDR is supposed to be on sector boundary */ -static ulong end_addr = CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1; -#endif - -#ifdef CONFIG_ENV_ADDR_REDUND -static env_t *flash_addr_new = (env_t *)CONFIG_ENV_ADDR_REDUND; - -/* CONFIG_ENV_ADDR_REDUND is supposed to be on sector boundary */ -static ulong end_addr_new = CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1; -#endif /* CONFIG_ENV_ADDR_REDUND */ - - -#ifdef CONFIG_ENV_ADDR_REDUND -int env_init(void) -{ - int crc1_ok = 0, crc2_ok = 0; - - uchar flag1 = flash_addr->flags; - uchar flag2 = flash_addr_new->flags; - - ulong addr_default = (ulong)&default_environment[0]; - ulong addr1 = (ulong)&(flash_addr->data); - ulong addr2 = (ulong)&(flash_addr_new->data); - - crc1_ok = crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc; - crc2_ok = - crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc; - - if (crc1_ok && !crc2_ok) { - gd->env_addr = addr1; - gd->env_valid = 1; - } else if (!crc1_ok && crc2_ok) { - gd->env_addr = addr2; - gd->env_valid = 1; - } else if (!crc1_ok && !crc2_ok) { - gd->env_addr = addr_default; - gd->env_valid = 0; - } else if (flag1 == ACTIVE_FLAG && flag2 == OBSOLETE_FLAG) { - gd->env_addr = addr1; - gd->env_valid = 1; - } else if (flag1 == OBSOLETE_FLAG && flag2 == ACTIVE_FLAG) { - gd->env_addr = addr2; - gd->env_valid = 1; - } else if (flag1 == flag2) { - gd->env_addr = addr1; - gd->env_valid = 2; - } else if (flag1 == 0xFF) { - gd->env_addr = addr1; - gd->env_valid = 2; - } else if (flag2 == 0xFF) { - gd->env_addr = addr2; - gd->env_valid = 2; - } - - return 0; -} - -#ifdef CMD_SAVEENV -int saveenv(void) -{ - env_t env_new; - char *saved_data = NULL; - char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG; - int rc = 1; -#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE - ulong up_data = 0; -#endif - - debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr); - - if (flash_sect_protect(0, (ulong)flash_addr, end_addr)) - goto done; - - debug("Protect off %08lX ... %08lX\n", - (ulong)flash_addr_new, end_addr_new); - - if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) - goto done; - - rc = env_export(&env_new); - if (rc) - return rc; - env_new.flags = new_flag; - -#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE - up_data = end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE); - debug("Data to save 0x%lX\n", up_data); - if (up_data) { - saved_data = malloc(up_data); - if (saved_data == NULL) { - printf("Unable to save the rest of sector (%ld)\n", - up_data); - goto done; - } - memcpy(saved_data, - (void *)((long)flash_addr_new + CONFIG_ENV_SIZE), - up_data); - debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n", - (long)flash_addr_new + CONFIG_ENV_SIZE, - up_data, saved_data); - } -#endif - puts("Erasing Flash..."); - debug(" %08lX ... %08lX ...", (ulong)flash_addr_new, end_addr_new); - - if (flash_sect_erase((ulong)flash_addr_new, end_addr_new)) - goto done; - - puts("Writing to Flash... "); - debug(" %08lX ... %08lX ...", - (ulong)&(flash_addr_new->data), - sizeof(env_ptr->data) + (ulong)&(flash_addr_new->data)); - rc = flash_write((char *)&env_new, (ulong)flash_addr_new, - sizeof(env_new)); - if (rc) - goto perror; - - rc = flash_write(&flag, (ulong)&(flash_addr->flags), - sizeof(flash_addr->flags)); - if (rc) - goto perror; - -#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE - if (up_data) { /* restore the rest of sector */ - debug("Restoring the rest of data to 0x%lX len 0x%lX\n", - (long)flash_addr_new + CONFIG_ENV_SIZE, up_data); - if (flash_write(saved_data, - (long)flash_addr_new + CONFIG_ENV_SIZE, - up_data)) - goto perror; - } -#endif - puts("done\n"); - - { - env_t *etmp = flash_addr; - ulong ltmp = end_addr; - - flash_addr = flash_addr_new; - flash_addr_new = etmp; - - end_addr = end_addr_new; - end_addr_new = ltmp; - } - - rc = 0; - goto done; -perror: - flash_perror(rc); -done: - if (saved_data) - free(saved_data); - /* try to re-protect */ - flash_sect_protect(1, (ulong)flash_addr, end_addr); - flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new); - - return rc; -} -#endif /* CMD_SAVEENV */ - -#else /* ! CONFIG_ENV_ADDR_REDUND */ - -int env_init(void) -{ - if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { - gd->env_addr = (ulong)&(env_ptr->data); - gd->env_valid = 1; - return 0; - } - - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 0; - return 0; -} - -#ifdef CMD_SAVEENV -int saveenv(void) -{ - env_t env_new; - int rc = 1; - char *saved_data = NULL; -#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE - ulong up_data = 0; - - up_data = end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE); - debug("Data to save 0x%lx\n", up_data); - if (up_data) { - saved_data = malloc(up_data); - if (saved_data == NULL) { - printf("Unable to save the rest of sector (%ld)\n", - up_data); - goto done; - } - memcpy(saved_data, - (void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data); - debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n", - (ulong)flash_addr + CONFIG_ENV_SIZE, - up_data, - (ulong)saved_data); - } -#endif /* CONFIG_ENV_SECT_SIZE */ - - debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr); - - if (flash_sect_protect(0, (long)flash_addr, end_addr)) - goto done; - - rc = env_export(&env_new); - if (rc) - goto done; - - puts("Erasing Flash..."); - if (flash_sect_erase((long)flash_addr, end_addr)) - goto done; - - puts("Writing to Flash... "); - rc = flash_write((char *)&env_new, (long)flash_addr, CONFIG_ENV_SIZE); - if (rc != 0) - goto perror; - -#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE - if (up_data) { /* restore the rest of sector */ - debug("Restoring the rest of data to 0x%lx len 0x%lx\n", - (ulong)flash_addr + CONFIG_ENV_SIZE, up_data); - if (flash_write(saved_data, - (long)flash_addr + CONFIG_ENV_SIZE, - up_data)) - goto perror; - } -#endif - puts("done\n"); - rc = 0; - goto done; -perror: - flash_perror(rc); -done: - if (saved_data) - free(saved_data); - /* try to re-protect */ - flash_sect_protect(1, (long)flash_addr, end_addr); - return rc; -} -#endif /* CMD_SAVEENV */ - -#endif /* CONFIG_ENV_ADDR_REDUND */ - -void env_relocate_spec(void) -{ -#ifdef CONFIG_ENV_ADDR_REDUND - if (gd->env_addr != (ulong)&(flash_addr->data)) { - env_t *etmp = flash_addr; - ulong ltmp = end_addr; - - flash_addr = flash_addr_new; - flash_addr_new = etmp; - - end_addr = end_addr_new; - end_addr_new = ltmp; - } - - if (flash_addr_new->flags != OBSOLETE_FLAG && - crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc) { - char flag = OBSOLETE_FLAG; - - gd->env_valid = 2; - flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new); - flash_write(&flag, - (ulong)&(flash_addr_new->flags), - sizeof(flash_addr_new->flags)); - flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new); - } - - if (flash_addr->flags != ACTIVE_FLAG && - (flash_addr->flags & ACTIVE_FLAG) == ACTIVE_FLAG) { - char flag = ACTIVE_FLAG; - - gd->env_valid = 2; - flash_sect_protect(0, (ulong)flash_addr, end_addr); - flash_write(&flag, - (ulong)&(flash_addr->flags), - sizeof(flash_addr->flags)); - flash_sect_protect(1, (ulong)flash_addr, end_addr); - } - - if (gd->env_valid == 2) - puts("*** Warning - some problems detected " - "reading environment; recovered successfully\n\n"); -#endif /* CONFIG_ENV_ADDR_REDUND */ - - env_import((char *)flash_addr, 1); -} diff --git a/common/env_mmc.c b/common/env_mmc.c deleted file mode 100644 index bb760a00ed..0000000000 --- a/common/env_mmc.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * (C) Copyright 2008-2011 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* #define DEBUG */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - -char *env_name_spec = "MMC"; - -#ifdef ENV_IS_EMBEDDED -env_t *env_ptr = &environment; -#else /* ! ENV_IS_EMBEDDED */ -env_t *env_ptr; -#endif /* ENV_IS_EMBEDDED */ - -DECLARE_GLOBAL_DATA_PTR; - -#if !defined(CONFIG_ENV_OFFSET) -#define CONFIG_ENV_OFFSET 0 -#endif - -#if CONFIG_IS_ENABLED(OF_CONTROL) -static inline s64 mmc_offset(int copy) -{ - const char *propname = "u-boot,mmc-env-offset"; - s64 defvalue = CONFIG_ENV_OFFSET; - -#if defined(CONFIG_ENV_OFFSET_REDUND) - if (copy) { - propname = "u-boot,mmc-env-offset-redundant"; - defvalue = CONFIG_ENV_OFFSET_REDUND; - } -#endif - - return fdtdec_get_config_int(gd->fdt_blob, propname, defvalue); -} -#else -static inline s64 mmc_offset(int copy) -{ - s64 offset = CONFIG_ENV_OFFSET; - -#if defined(CONFIG_ENV_OFFSET_REDUND) - if (copy) - offset = CONFIG_ENV_OFFSET_REDUND; -#endif - return offset; -} -#endif - -__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) -{ - s64 offset = mmc_offset(copy); - - if (offset < 0) - offset += mmc->capacity; - - *env_addr = offset; - - return 0; -} - -__weak int mmc_get_env_dev(void) -{ - return CONFIG_SYS_MMC_ENV_DEV; -} - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} - -#ifdef CONFIG_SYS_MMC_ENV_PART -__weak uint mmc_get_env_part(struct mmc *mmc) -{ - return CONFIG_SYS_MMC_ENV_PART; -} - -static unsigned char env_mmc_orig_hwpart; - -static int mmc_set_env_part(struct mmc *mmc) -{ - uint part = mmc_get_env_part(mmc); - int dev = mmc_get_env_dev(); - int ret = 0; - - env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart; - ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); - if (ret) - puts("MMC partition switch failed\n"); - - return ret; -} -#else -static inline int mmc_set_env_part(struct mmc *mmc) {return 0; }; -#endif - -static const char *init_mmc_for_env(struct mmc *mmc) -{ - if (!mmc) - return "!No MMC card found"; - -#ifdef CONFIG_BLK - struct udevice *dev; - - if (blk_get_from_parent(mmc->dev, &dev)) - return "!No block device"; -#else - if (mmc_init(mmc)) - return "!MMC init failed"; -#endif - if (mmc_set_env_part(mmc)) - return "!MMC partition switch failed"; - - return NULL; -} - -static void fini_mmc_for_env(struct mmc *mmc) -{ -#ifdef CONFIG_SYS_MMC_ENV_PART - int dev = mmc_get_env_dev(); - - blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart); -#endif -} - -#ifdef CONFIG_CMD_SAVEENV -static inline int write_env(struct mmc *mmc, unsigned long size, - unsigned long offset, const void *buffer) -{ - uint blk_start, blk_cnt, n; - struct blk_desc *desc = mmc_get_blk_desc(mmc); - - blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; - blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; - - n = blk_dwrite(desc, blk_start, blk_cnt, (u_char *)buffer); - - return (n == blk_cnt) ? 0 : -1; -} - -int saveenv(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - int dev = mmc_get_env_dev(); - struct mmc *mmc = find_mmc_device(dev); - u32 offset; - int ret, copy = 0; - const char *errmsg; - - errmsg = init_mmc_for_env(mmc); - if (errmsg) { - printf("%s\n", errmsg); - return 1; - } - - ret = env_export(env_new); - if (ret) - goto fini; - -#ifdef CONFIG_ENV_OFFSET_REDUND - if (gd->env_valid == 1) - copy = 1; -#endif - - if (mmc_get_env_addr(mmc, copy, &offset)) { - ret = 1; - goto fini; - } - - printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", dev); - if (write_env(mmc, 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 == 2 ? 1 : 2; -#endif - -fini: - fini_mmc_for_env(mmc); - return ret; -} -#endif /* CONFIG_CMD_SAVEENV */ - -static inline int read_env(struct mmc *mmc, unsigned long size, - unsigned long offset, const void *buffer) -{ - uint blk_start, blk_cnt, n; - struct blk_desc *desc = mmc_get_blk_desc(mmc); - - blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; - blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; - - n = blk_dread(desc, blk_start, blk_cnt, (uchar *)buffer); - - return (n == blk_cnt) ? 0 : -1; -} - -#ifdef CONFIG_ENV_OFFSET_REDUND -void env_relocate_spec(void) -{ -#if !defined(ENV_IS_EMBEDDED) - struct mmc *mmc; - u32 offset1, offset2; - int read1_fail = 0, read2_fail = 0; - int ret; - int dev = mmc_get_env_dev(); - const char *errmsg = NULL; - - ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env1, 1); - ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env2, 1); - - mmc = find_mmc_device(dev); - - errmsg = init_mmc_for_env(mmc); - if (errmsg) { - ret = 1; - goto err; - } - - if (mmc_get_env_addr(mmc, 0, &offset1) || - mmc_get_env_addr(mmc, 1, &offset2)) { - ret = 1; - goto fini; - } - - read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); - read2_fail = read_env(mmc, 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 = 1; - goto fini; - } else if (!read1_fail && read2_fail) { - gd->env_valid = 1; - env_import((char *)tmp_env1, 1); - } else if (read1_fail && !read2_fail) { - gd->env_valid = 2; - env_import((char *)tmp_env2, 1); - } else { - env_import_redund((char *)tmp_env1, (char *)tmp_env2); - } - - ret = 0; - -fini: - fini_mmc_for_env(mmc); -err: - if (ret) - set_default_env(errmsg); -#endif -} -#else /* ! CONFIG_ENV_OFFSET_REDUND */ -void env_relocate_spec(void) -{ -#if !defined(ENV_IS_EMBEDDED) - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - struct mmc *mmc; - u32 offset; - int ret; - int dev = mmc_get_env_dev(); - const char *errmsg; - - mmc = find_mmc_device(dev); - - errmsg = init_mmc_for_env(mmc); - if (errmsg) { - ret = 1; - goto err; - } - - if (mmc_get_env_addr(mmc, 0, &offset)) { - ret = 1; - goto fini; - } - - if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) { - errmsg = "!read failed"; - ret = 1; - goto fini; - } - - env_import(buf, 1); - ret = 0; - -fini: - fini_mmc_for_env(mmc); -err: - if (ret) - set_default_env(errmsg); -#endif -} -#endif /* CONFIG_ENV_OFFSET_REDUND */ diff --git a/common/env_nand.c b/common/env_nand.c deleted file mode 100644 index 760f6859e3..0000000000 --- a/common/env_nand.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2008 - * Stuart Wood, Lab X Technologies - * - * (C) Copyright 2004 - * Jian Zhang, Texas Instruments, jzhang@ti.com. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_NAND) -#define CMD_SAVEENV -#elif defined(CONFIG_ENV_OFFSET_REDUND) -#error CONFIG_ENV_OFFSET_REDUND must have CONFIG_CMD_SAVEENV & CONFIG_CMD_NAND -#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 - -#ifndef CONFIG_ENV_RANGE -#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE -#endif - -char *env_name_spec = "NAND"; - -#if defined(ENV_IS_EMBEDDED) -env_t *env_ptr = &environment; -#elif defined(CONFIG_NAND_ENV_DST) -env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST; -#else /* ! ENV_IS_EMBEDDED */ -env_t *env_ptr; -#endif /* ENV_IS_EMBEDDED */ - -DECLARE_GLOBAL_DATA_PTR; - -/* - * 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 does the real validation. - * - * When using a NAND boot image (like sequoia_nand), the environment - * can be embedded or attached to the U-Boot image in NAND flash. - * This way the SPL loads not only the U-Boot image from NAND but - * also the environment. - */ -int env_init(void) -{ -#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_NAND_ENV_DST) - int crc1_ok = 0, crc2_ok = 0; - env_t *tmp_env1; - -#ifdef CONFIG_ENV_OFFSET_REDUND - env_t *tmp_env2; - - tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE); - crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc; -#endif - tmp_env1 = env_ptr; - crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; - - if (!crc1_ok && !crc2_ok) { - gd->env_addr = 0; - gd->env_valid = 0; - - return 0; - } else if (crc1_ok && !crc2_ok) { - gd->env_valid = 1; - } -#ifdef CONFIG_ENV_OFFSET_REDUND - 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; - } - - if (gd->env_valid == 2) - env_ptr = tmp_env2; - else -#endif - if (gd->env_valid == 1) - env_ptr = tmp_env1; - - gd->env_addr = (ulong)env_ptr->data; - -#else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; -#endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */ - - return 0; -} - -#ifdef CMD_SAVEENV -/* - * The legacy NAND code saved the environment in the first NAND device i.e., - * nand_dev_desc + 0. This is also the behaviour using the new NAND code. - */ -static int writeenv(size_t offset, u_char *buf) -{ - size_t end = offset + CONFIG_ENV_RANGE; - size_t amount_saved = 0; - size_t blocksize, len; - struct mtd_info *mtd; - u_char *char_ptr; - - mtd = get_nand_dev_by_index(0); - if (!mtd) - return 1; - - blocksize = mtd->erasesize; - len = min(blocksize, (size_t)CONFIG_ENV_SIZE); - - while (amount_saved < CONFIG_ENV_SIZE && offset < end) { - if (nand_block_isbad(mtd, offset)) { - offset += blocksize; - } else { - char_ptr = &buf[amount_saved]; - if (nand_write(mtd, offset, &len, char_ptr)) - return 1; - - offset += blocksize; - amount_saved += len; - } - } - if (amount_saved != CONFIG_ENV_SIZE) - return 1; - - return 0; -} - -struct env_location { - const char *name; - const nand_erase_options_t erase_opts; -}; - -static int erase_and_write_env(const struct env_location *location, - u_char *env_new) -{ - struct mtd_info *mtd; - int ret = 0; - - mtd = get_nand_dev_by_index(0); - if (!mtd) - return 1; - - printf("Erasing %s...\n", location->name); - if (nand_erase_opts(mtd, &location->erase_opts)) - return 1; - - printf("Writing to %s... ", location->name); - ret = writeenv(location->erase_opts.offset, env_new); - puts(ret ? "FAILED!\n" : "OK\n"); - - return ret; -} - -int saveenv(void) -{ - int ret = 0; - ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - int env_idx = 0; - static const struct env_location location[] = { - { - .name = "NAND", - .erase_opts = { - .length = CONFIG_ENV_RANGE, - .offset = CONFIG_ENV_OFFSET, - }, - }, -#ifdef CONFIG_ENV_OFFSET_REDUND - { - .name = "redundant NAND", - .erase_opts = { - .length = CONFIG_ENV_RANGE, - .offset = CONFIG_ENV_OFFSET_REDUND, - }, - }, -#endif - }; - - - if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) - return 1; - - ret = env_export(env_new); - if (ret) - return ret; - -#ifdef CONFIG_ENV_OFFSET_REDUND - env_idx = (gd->env_valid == 1); -#endif - - ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); -#ifdef CONFIG_ENV_OFFSET_REDUND - if (!ret) { - /* preset other copy for next write */ - gd->env_valid = gd->env_valid == 2 ? 1 : 2; - return ret; - } - - env_idx = (env_idx + 1) & 1; - ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); - if (!ret) - printf("Warning: primary env write failed," - " redundancy is lost!\n"); -#endif - - return ret; -} -#endif /* CMD_SAVEENV */ - -#if defined(CONFIG_SPL_BUILD) -static int readenv(size_t offset, u_char *buf) -{ - return nand_spl_load_image(offset, CONFIG_ENV_SIZE, buf); -} -#else -static int readenv(size_t offset, u_char *buf) -{ - size_t end = offset + CONFIG_ENV_RANGE; - size_t amount_loaded = 0; - size_t blocksize, len; - struct mtd_info *mtd; - u_char *char_ptr; - - mtd = get_nand_dev_by_index(0); - if (!mtd) - return 1; - - blocksize = mtd->erasesize; - len = min(blocksize, (size_t)CONFIG_ENV_SIZE); - - while (amount_loaded < CONFIG_ENV_SIZE && offset < end) { - if (nand_block_isbad(mtd, offset)) { - offset += blocksize; - } else { - char_ptr = &buf[amount_loaded]; - if (nand_read_skip_bad(mtd, offset, - &len, NULL, - mtd->size, char_ptr)) - return 1; - - offset += blocksize; - amount_loaded += len; - } - } - - if (amount_loaded != CONFIG_ENV_SIZE) - return 1; - - return 0; -} -#endif /* #if defined(CONFIG_SPL_BUILD) */ - -#ifdef CONFIG_ENV_OFFSET_OOB -int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result) -{ - struct mtd_oob_ops ops; - uint32_t oob_buf[ENV_OFFSET_SIZE / sizeof(uint32_t)]; - int ret; - - ops.datbuf = NULL; - ops.mode = MTD_OOB_AUTO; - ops.ooboffs = 0; - ops.ooblen = ENV_OFFSET_SIZE; - ops.oobbuf = (void *)oob_buf; - - ret = mtd->read_oob(mtd, ENV_OFFSET_SIZE, &ops); - if (ret) { - printf("error reading OOB block 0\n"); - return ret; - } - - if (oob_buf[0] == ENV_OOB_MARKER) { - *result = oob_buf[1] * mtd->erasesize; - } else if (oob_buf[0] == ENV_OOB_MARKER_OLD) { - *result = oob_buf[1]; - } else { - printf("No dynamic environment marker in OOB block 0\n"); - return -ENOENT; - } - - return 0; -} -#endif - -#ifdef CONFIG_ENV_OFFSET_REDUND -void env_relocate_spec(void) -{ -#if !defined(ENV_IS_EMBEDDED) - int read1_fail = 0, read2_fail = 0; - env_t *tmp_env1, *tmp_env2; - - tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); - tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); - if (tmp_env1 == NULL || tmp_env2 == NULL) { - puts("Can't allocate buffers for environment\n"); - set_default_env("!malloc() failed"); - goto done; - } - - read1_fail = readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1); - read2_fail = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) 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) { - set_default_env("!bad env area"); - goto done; - } else if (!read1_fail && read2_fail) { - gd->env_valid = 1; - env_import((char *)tmp_env1, 1); - } else if (read1_fail && !read2_fail) { - gd->env_valid = 2; - env_import((char *)tmp_env2, 1); - } else { - env_import_redund((char *)tmp_env1, (char *)tmp_env2); - } - -done: - free(tmp_env1); - free(tmp_env2); - -#endif /* ! ENV_IS_EMBEDDED */ -} -#else /* ! CONFIG_ENV_OFFSET_REDUND */ -/* - * The legacy NAND code saved the environment in the first NAND - * device i.e., nand_dev_desc + 0. This is also the behaviour using - * the new NAND code. - */ -void env_relocate_spec(void) -{ -#if !defined(ENV_IS_EMBEDDED) - int ret; - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - -#if defined(CONFIG_ENV_OFFSET_OOB) - struct mtd_info *mtd = get_nand_dev_by_index(0); - /* - * If unable to read environment offset from NAND OOB then fall through - * to the normal environment reading code below - */ - if (mtd && !get_nand_env_oob(mtd, &nand_env_oob_offset)) { - printf("Found Environment offset in OOB..\n"); - } else { - set_default_env("!no env offset in OOB"); - return; - } -#endif - - ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf); - if (ret) { - set_default_env("!readenv() failed"); - return; - } - - env_import(buf, 1); -#endif /* ! ENV_IS_EMBEDDED */ -} -#endif /* CONFIG_ENV_OFFSET_REDUND */ diff --git a/common/env_nowhere.c b/common/env_nowhere.c deleted file mode 100644 index bdc1ed5e67..0000000000 --- a/common/env_nowhere.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -env_t *env_ptr; - -void env_relocate_spec(void) -{ -} - -/* - * Initialize Environment use - * - * We are still running from ROM, so data use is limited - */ -int env_init(void) -{ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 0; - - return 0; -} diff --git a/common/env_nvram.c b/common/env_nvram.c deleted file mode 100644 index 524f07d5f8..0000000000 --- a/common/env_nvram.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH - * - * It might not be possible in all cases to use 'memcpy()' to copy - * the environment to NVRAM, as the NVRAM might not be mapped into - * the memory space. (I.e. this is the case for the BAB750). In those - * cases it might be possible to access the NVRAM using a different - * method. For example, the RTC on the BAB750 is accessible in IO - * space using its address and data registers. To enable usage of - * NVRAM in those cases I invented the functions 'nvram_read()' and - * 'nvram_write()', which will be activated upon the configuration - * #define CONFIG_SYS_NVRAM_ACCESS_ROUTINE. Note, that those functions are - * strongly dependent on the used HW, and must be redefined for each - * board that wants to use them. - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE -extern void *nvram_read(void *dest, const long src, size_t count); -extern void nvram_write(long dest, const void *src, size_t count); -env_t *env_ptr; -#else -env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; -#endif - -char *env_name_spec = "NVRAM"; - -#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE -uchar env_get_char_spec(int index) -{ - uchar c; - - nvram_read(&c, CONFIG_ENV_ADDR + index, 1); - - return c; -} -#endif - -void env_relocate_spec(void) -{ - char buf[CONFIG_ENV_SIZE]; - -#if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) - nvram_read(buf, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); -#else - memcpy(buf, (void *)CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); -#endif - env_import(buf, 1); -} - -int saveenv(void) -{ - env_t env_new; - int rcode = 0; - - rcode = env_export(&env_new); - if (rcode) - return rcode; - -#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE - nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE); -#else - if (memcpy((char *)CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE) == NULL) - rcode = 1; -#endif - return rcode; -} - -/* - * Initialize Environment use - * - * We are still running from ROM, so data use is limited - */ -int env_init(void) -{ -#if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) - ulong crc; - uchar data[ENV_SIZE]; - - nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong)); - nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE); - - if (crc32(0, data, ENV_SIZE) == crc) { - gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long); -#else - if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { - gd->env_addr = (ulong)&env_ptr->data; -#endif - gd->env_valid = 1; - } else { - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 0; - } - - return 0; -} diff --git a/common/env_onenand.c b/common/env_onenand.c deleted file mode 100644 index cc3d670de8..0000000000 --- a/common/env_onenand.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * (C) Copyright 2010 DENX Software Engineering - * Wolfgang Denk - * - * (C) Copyright 2005-2009 Samsung Electronics - * Kyungmin Park - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -char *env_name_spec = "OneNAND"; - -#define ONENAND_MAX_ENV_SIZE CONFIG_ENV_SIZE -#define ONENAND_ENV_SIZE(mtd) (ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE) - -DECLARE_GLOBAL_DATA_PTR; - -void env_relocate_spec(void) -{ - struct mtd_info *mtd = &onenand_mtd; -#ifdef CONFIG_ENV_ADDR_FLEX - struct onenand_chip *this = &onenand_chip; -#endif - int rc; - size_t retlen; -#ifdef ENV_IS_EMBEDDED - char *buf = (char *)&environment; -#else - loff_t env_addr = CONFIG_ENV_ADDR; - char onenand_env[ONENAND_MAX_ENV_SIZE]; - char *buf = (char *)&onenand_env[0]; -#endif /* ENV_IS_EMBEDDED */ - -#ifndef ENV_IS_EMBEDDED -# ifdef CONFIG_ENV_ADDR_FLEX - if (FLEXONENAND(this)) - env_addr = CONFIG_ENV_ADDR_FLEX; -# endif - /* Check OneNAND exist */ - if (mtd->writesize) - /* Ignore read fail */ - mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, - &retlen, (u_char *)buf); - else - mtd->writesize = MAX_ONENAND_PAGESIZE; -#endif /* !ENV_IS_EMBEDDED */ - - rc = env_import(buf, 1); - if (rc) - gd->env_valid = 1; -} - -int saveenv(void) -{ - env_t env_new; - int ret; - struct mtd_info *mtd = &onenand_mtd; -#ifdef CONFIG_ENV_ADDR_FLEX - struct onenand_chip *this = &onenand_chip; -#endif - loff_t env_addr = CONFIG_ENV_ADDR; - size_t retlen; - struct erase_info instr = { - .callback = NULL, - }; - - ret = env_export(&env_new); - if (ret) - return ret; - - instr.len = CONFIG_ENV_SIZE; -#ifdef CONFIG_ENV_ADDR_FLEX - if (FLEXONENAND(this)) { - env_addr = CONFIG_ENV_ADDR_FLEX; - instr.len = CONFIG_ENV_SIZE_FLEX; - instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ? - 1 : 0; - } -#endif - instr.addr = env_addr; - instr.mtd = mtd; - if (mtd_erase(mtd, &instr)) { - printf("OneNAND: erase failed at 0x%08llx\n", env_addr); - return 1; - } - - if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, - (u_char *)&env_new)) { - printf("OneNAND: write failed at 0x%llx\n", instr.addr); - return 2; - } - - return 0; -} - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} diff --git a/common/env_remote.c b/common/env_remote.c deleted file mode 100644 index eb977ee1fe..0000000000 --- a/common/env_remote.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * (C) Copyright 2011-2012 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* #define DEBUG */ - -#include -#include -#include -#include - -char *env_name_spec = "Remote"; - -#ifdef ENV_IS_EMBEDDED -env_t *env_ptr = &environment; -#else /* ! ENV_IS_EMBEDDED */ -env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; -#endif /* ENV_IS_EMBEDDED */ - -DECLARE_GLOBAL_DATA_PTR; - -#if !defined(CONFIG_ENV_OFFSET) -#define CONFIG_ENV_OFFSET 0 -#endif - -int env_init(void) -{ - if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { - gd->env_addr = (ulong)&(env_ptr->data); - gd->env_valid = 1; - return 0; - } - - gd->env_addr = (ulong)default_environment; - gd->env_valid = 0; - return 0; -} - -#ifdef CONFIG_CMD_SAVEENV -int saveenv(void) -{ -#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE - printf("Can not support the 'saveenv' when boot from SRIO or PCIE!\n"); - return 1; -#else - return 0; -#endif -} -#endif /* CONFIG_CMD_SAVEENV */ - -void env_relocate_spec(void) -{ -#ifndef ENV_IS_EMBEDDED - env_import((char *)env_ptr, 1); -#endif -} diff --git a/common/env_sata.c b/common/env_sata.c deleted file mode 100644 index b0cee35a60..0000000000 --- a/common/env_sata.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * (C) Copyright 2010-2016 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* #define DEBUG */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_ENV_SIZE_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND) -#error ENV REDUND not supported -#endif - -#if !defined(CONFIG_ENV_OFFSET) || !defined(CONFIG_ENV_SIZE) -#error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined -#endif - -char *env_name_spec = "SATA"; - -DECLARE_GLOBAL_DATA_PTR; - -__weak int sata_get_env_dev(void) -{ - return CONFIG_SYS_SATA_ENV_DEV; -} - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} - -#ifdef CONFIG_CMD_SAVEENV -static inline int write_env(struct blk_desc *sata, unsigned long size, - unsigned long offset, void *buffer) -{ - uint blk_start, blk_cnt, n; - - blk_start = ALIGN(offset, sata->blksz) / sata->blksz; - blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; - - n = blk_dwrite(sata, blk_start, blk_cnt, buffer); - - return (n == blk_cnt) ? 0 : -1; -} - -int saveenv(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - struct blk_desc *sata = NULL; - int env_sata, ret; - - if (sata_initialize()) - return 1; - - env_sata = sata_get_env_dev(); - - sata = sata_get_dev(env_sata); - if (sata == NULL) { - printf("Unknown SATA(%d) device for environment!\n", - env_sata); - return 1; - } - - ret = env_export(env_new); - if (ret) - return 1; - - printf("Writing to SATA(%d)...", env_sata); - if (write_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, &env_new)) { - puts("failed\n"); - return 1; - } - - puts("done\n"); - return 0; -} -#endif /* CONFIG_CMD_SAVEENV */ - -static inline int read_env(struct blk_desc *sata, unsigned long size, - unsigned long offset, void *buffer) -{ - uint blk_start, blk_cnt, n; - - blk_start = ALIGN(offset, sata->blksz) / sata->blksz; - blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; - - n = blk_dread(sata, blk_start, blk_cnt, buffer); - - return (n == blk_cnt) ? 0 : -1; -} - -void env_relocate_spec(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - struct blk_desc *sata = NULL; - int env_sata; - - if (sata_initialize()) - return; - - env_sata = sata_get_env_dev(); - - sata = sata_get_dev(env_sata); - if (sata == NULL) { - printf("Unknown SATA(%d) device for environment!\n", - env_sata); - return; - } - - if (read_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) - return set_default_env(NULL); - - env_import(buf, 1); -} diff --git a/common/env_sf.c b/common/env_sf.c deleted file mode 100644 index 45f441a042..0000000000 --- a/common/env_sf.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * (C) Copyright 2000-2010 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * (C) Copyright 2008 Atmel Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_ENV_SPI_BUS -# define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS -#endif -#ifndef CONFIG_ENV_SPI_CS -# define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS -#endif -#ifndef CONFIG_ENV_SPI_MAX_HZ -# define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED -#endif -#ifndef CONFIG_ENV_SPI_MODE -# define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE -#endif - -#ifdef CONFIG_ENV_OFFSET_REDUND -static ulong env_offset = CONFIG_ENV_OFFSET; -static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND; - -#define ACTIVE_FLAG 1 -#define OBSOLETE_FLAG 0 -#endif /* CONFIG_ENV_OFFSET_REDUND */ - -DECLARE_GLOBAL_DATA_PTR; - -char *env_name_spec = "SPI Flash"; - -static struct spi_flash *env_flash; - -static int setup_flash_device(void) -{ -#ifdef CONFIG_DM_SPI_FLASH - struct udevice *new; - int ret; - - /* speed and mode will be read from DT */ - ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, - 0, 0, &new); - if (ret) { - set_default_env("!spi_flash_probe_bus_cs() failed"); - return 1; - } - - env_flash = dev_get_uclass_priv(new); -#else - - if (!env_flash) { - env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, - CONFIG_ENV_SPI_CS, - CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); - if (!env_flash) { - set_default_env("!spi_flash_probe() failed"); - return 1; - } - } -#endif - return 0; -} - -#if defined(CONFIG_ENV_OFFSET_REDUND) -int saveenv(void) -{ - env_t env_new; - char *saved_buffer = NULL, flag = OBSOLETE_FLAG; - u32 saved_size, saved_offset, sector; - int ret; - - ret = setup_flash_device(); - if (ret) - return ret; - - ret = env_export(&env_new); - if (ret) - return ret; - env_new.flags = ACTIVE_FLAG; - - if (gd->env_valid == 1) { - env_new_offset = CONFIG_ENV_OFFSET_REDUND; - env_offset = CONFIG_ENV_OFFSET; - } else { - env_new_offset = CONFIG_ENV_OFFSET; - env_offset = CONFIG_ENV_OFFSET_REDUND; - } - - /* Is the sector larger than the env (i.e. embedded) */ - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; - saved_offset = env_new_offset + CONFIG_ENV_SIZE; - saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size); - if (!saved_buffer) { - ret = 1; - goto done; - } - ret = spi_flash_read(env_flash, saved_offset, - saved_size, saved_buffer); - if (ret) - goto done; - } - - sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); - - puts("Erasing SPI flash..."); - ret = spi_flash_erase(env_flash, env_new_offset, - sector * CONFIG_ENV_SECT_SIZE); - if (ret) - goto done; - - puts("Writing to SPI flash..."); - - ret = spi_flash_write(env_flash, env_new_offset, - CONFIG_ENV_SIZE, &env_new); - if (ret) - goto done; - - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - ret = spi_flash_write(env_flash, saved_offset, - saved_size, saved_buffer); - if (ret) - goto done; - } - - ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags), - sizeof(env_new.flags), &flag); - if (ret) - goto done; - - puts("done\n"); - - gd->env_valid = gd->env_valid == 2 ? 1 : 2; - - printf("Valid environment: %d\n", (int)gd->env_valid); - - done: - if (saved_buffer) - free(saved_buffer); - - return ret; -} - -void env_relocate_spec(void) -{ - int ret; - int crc1_ok = 0, crc2_ok = 0; - env_t *tmp_env1 = NULL; - env_t *tmp_env2 = NULL; - env_t *ep = NULL; - - tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN, - CONFIG_ENV_SIZE); - tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN, - CONFIG_ENV_SIZE); - if (!tmp_env1 || !tmp_env2) { - set_default_env("!malloc() failed"); - goto out; - } - - ret = setup_flash_device(); - if (ret) - goto out; - - ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, - CONFIG_ENV_SIZE, tmp_env1); - if (ret) { - set_default_env("!spi_flash_read() failed"); - goto err_read; - } - - if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc) - crc1_ok = 1; - - ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND, - CONFIG_ENV_SIZE, tmp_env2); - if (!ret) { - if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc) - crc2_ok = 1; - } - - if (!crc1_ok && !crc2_ok) { - set_default_env("!bad CRC"); - goto err_read; - } else if (crc1_ok && !crc2_ok) { - gd->env_valid = 1; - } else if (!crc1_ok && crc2_ok) { - gd->env_valid = 2; - } else if (tmp_env1->flags == ACTIVE_FLAG && - tmp_env2->flags == OBSOLETE_FLAG) { - gd->env_valid = 1; - } else if (tmp_env1->flags == OBSOLETE_FLAG && - tmp_env2->flags == ACTIVE_FLAG) { - gd->env_valid = 2; - } else if (tmp_env1->flags == tmp_env2->flags) { - gd->env_valid = 1; - } else if (tmp_env1->flags == 0xFF) { - gd->env_valid = 1; - } else if (tmp_env2->flags == 0xFF) { - gd->env_valid = 2; - } else { - /* - * this differs from code in env_flash.c, but I think a sane - * default path is desirable. - */ - gd->env_valid = 1; - } - - if (gd->env_valid == 1) - ep = tmp_env1; - else - ep = tmp_env2; - - ret = env_import((char *)ep, 0); - if (!ret) { - error("Cannot import environment: errno = %d\n", errno); - set_default_env("!env_import failed"); - } - -err_read: - spi_flash_free(env_flash); - env_flash = NULL; -out: - free(tmp_env1); - free(tmp_env2); -} -#else -int saveenv(void) -{ - u32 saved_size, saved_offset, sector; - char *saved_buffer = NULL; - int ret = 1; - env_t env_new; - - ret = setup_flash_device(); - if (ret) - return ret; - - /* Is the sector larger than the env (i.e. embedded) */ - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; - saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; - saved_buffer = malloc(saved_size); - if (!saved_buffer) - goto done; - - ret = spi_flash_read(env_flash, saved_offset, - saved_size, saved_buffer); - if (ret) - goto done; - } - - ret = env_export(&env_new); - if (ret) - goto done; - - sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); - - puts("Erasing SPI flash..."); - ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, - sector * CONFIG_ENV_SECT_SIZE); - if (ret) - goto done; - - puts("Writing to SPI flash..."); - ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, - CONFIG_ENV_SIZE, &env_new); - if (ret) - goto done; - - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - ret = spi_flash_write(env_flash, saved_offset, - saved_size, saved_buffer); - if (ret) - goto done; - } - - ret = 0; - puts("done\n"); - - done: - if (saved_buffer) - free(saved_buffer); - - return ret; -} - -void env_relocate_spec(void) -{ - int ret; - char *buf = NULL; - - buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE); - if (!buf) { - set_default_env("!malloc() failed"); - return; - } - - ret = setup_flash_device(); - if (ret) - goto out; - - ret = spi_flash_read(env_flash, - CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf); - if (ret) { - set_default_env("!spi_flash_read() failed"); - goto err_read; - } - - ret = env_import(buf, 1); - if (ret) - gd->env_valid = 1; - -err_read: - spi_flash_free(env_flash); - env_flash = NULL; -out: - free(buf); -} -#endif - -int env_init(void) -{ - /* SPI flash isn't usable before relocation */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} diff --git a/common/env_ubi.c b/common/env_ubi.c deleted file mode 100644 index 95b527ddca..0000000000 --- a/common/env_ubi.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * (c) Copyright 2012 by National Instruments, - * Joe Hershberger - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#undef crc32 - -char *env_name_spec = "UBI"; - -env_t *env_ptr; - -DECLARE_GLOBAL_DATA_PTR; - -int env_init(void) -{ - /* use default */ - gd->env_addr = (ulong)&default_environment[0]; - gd->env_valid = 1; - - return 0; -} - -#ifdef CONFIG_CMD_SAVEENV -#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT -int saveenv(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - int ret; - - ret = env_export(env_new); - if (ret) - return ret; - - if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { - printf("\n** Cannot find mtd partition \"%s\"\n", - CONFIG_ENV_UBI_PART); - return 1; - } - - if (gd->env_valid == 1) { - puts("Writing to redundant UBI... "); - if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, - (void *)env_new, CONFIG_ENV_SIZE)) { - printf("\n** Unable to write env to %s:%s **\n", - CONFIG_ENV_UBI_PART, - CONFIG_ENV_UBI_VOLUME_REDUND); - return 1; - } - } else { - puts("Writing to UBI... "); - if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, - (void *)env_new, CONFIG_ENV_SIZE)) { - printf("\n** Unable to write env to %s:%s **\n", - CONFIG_ENV_UBI_PART, - CONFIG_ENV_UBI_VOLUME); - return 1; - } - } - - puts("done\n"); - - gd->env_valid = gd->env_valid == 2 ? 1 : 2; - - return 0; -} -#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ -int saveenv(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - int ret; - - ret = env_export(env_new); - if (ret) - return ret; - - if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { - printf("\n** Cannot find mtd partition \"%s\"\n", - CONFIG_ENV_UBI_PART); - return 1; - } - - if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, - CONFIG_ENV_SIZE)) { - printf("\n** Unable to write env to %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); - return 1; - } - - puts("done\n"); - return 0; -} -#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ -#endif /* CONFIG_CMD_SAVEENV */ - -#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT -void env_relocate_spec(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE); - ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE); - env_t *tmp_env1, *tmp_env2; - - /* - * In case we have restarted u-boot there is a chance that buffer - * contains old environment (from the previous boot). - * If UBI volume is zero size, ubi_volume_read() doesn't modify the - * buffer. - * We need to clear buffer manually here, so the invalid CRC will - * cause setting default environment as expected. - */ - memset(env1_buf, 0x0, CONFIG_ENV_SIZE); - memset(env2_buf, 0x0, CONFIG_ENV_SIZE); - - tmp_env1 = (env_t *)env1_buf; - tmp_env2 = (env_t *)env2_buf; - - if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { - printf("\n** Cannot find mtd partition \"%s\"\n", - CONFIG_ENV_UBI_PART); - set_default_env(NULL); - return; - } - - if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1, - CONFIG_ENV_SIZE)) { - printf("\n** Unable to read env from %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); - } - - if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)tmp_env2, - CONFIG_ENV_SIZE)) { - printf("\n** Unable to read redundant env from %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); - } - - env_import_redund((char *)tmp_env1, (char *)tmp_env2); -} -#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ -void env_relocate_spec(void) -{ - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); - - /* - * In case we have restarted u-boot there is a chance that buffer - * contains old environment (from the previous boot). - * If UBI volume is zero size, ubi_volume_read() doesn't modify the - * buffer. - * We need to clear buffer manually here, so the invalid CRC will - * cause setting default environment as expected. - */ - memset(buf, 0x0, CONFIG_ENV_SIZE); - - if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { - printf("\n** Cannot find mtd partition \"%s\"\n", - CONFIG_ENV_UBI_PART); - set_default_env(NULL); - return; - } - - if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, CONFIG_ENV_SIZE)) { - printf("\n** Unable to read env from %s:%s **\n", - CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); - set_default_env(NULL); - return; - } - - env_import(buf, 1); -} -#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ diff --git a/env/Kconfig b/env/Kconfig new file mode 100644 index 0000000000..9f97f9c90c --- /dev/null +++ b/env/Kconfig @@ -0,0 +1,441 @@ +menu "Environment" + +config ENV_IS_IN_DATAFLASH + bool "Environment in dataflash" + depends on !CHAIN_OF_TRUST + help + Define this if you have a DataFlash memory device which you + want to use for the environment. + + - CONFIG_ENV_OFFSET: + - CONFIG_ENV_ADDR: + - CONFIG_ENV_SIZE: + + These three #defines specify the offset and size of the + environment area within the total memory of your DataFlash placed + at the specified address. + +config ENV_IS_IN_EEPROM + bool "Environment in EEPROM" + depends on !CHAIN_OF_TRUST + 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. + + - CONFIG_SYS_I2C_EEPROM_ADDR: + If defined, specified the chip address of the EEPROM device. + The default address is zero. + + - CONFIG_SYS_I2C_EEPROM_BUS: + If defined, specified the i2c bus of the EEPROM device. + + - CONFIG_SYS_EEPROM_PAGE_WRITE_BITS: + If defined, the number of bits used to address bytes in a + single page in the EEPROM device. A 64 byte page, for example + would require six bits. + + - CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS: + If defined, the number of milliseconds to delay between + page writes. The default is zero milliseconds. + + - CONFIG_SYS_I2C_EEPROM_ADDR_LEN: + The length in bytes of the EEPROM memory array address. Note + that this is NOT the chip address length! + + - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW: + EEPROM chips that implement "address overflow" are ones + like Catalyst 24WC04/08/16 which has 9/10/11 bits of + address and the extra bits end up in the "chip address" bit + slots. This makes a 24WC08 (1Kbyte) chip look like four 256 + byte chips. + + 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_SYS_EEPROM_SIZE: + The size in bytes of the EEPROM device. + + - 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 + select FAT_WRITE + help + Define this if you want to use the FAT file system for the environment. + + + - CONFIG_FAT_WRITE: + This must be enabled. Otherwise it cannot save the environment file. + +config ENV_IS_IN_FLASH + bool "Environment in flash memory" + depends on !CHAIN_OF_TRUST + 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 /u-boot.lds* + accordingly! + +config ENV_IS_IN_MMC + bool "Environment in an MMC device" + depends on !CHAIN_OF_TRUST + default y if ARCH_SUNXI + 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 + 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 + 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 + 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 remove memory space" + depends on !CHAIN_OF_TRUST + 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 + 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_ENV_SPI_BUS (optional): + - CONFIG_ENV_SPI_CS (optional): + + Define the SPI bus and chip select. If not defined they will be 0. + + - CONFIG_ENV_SPI_MAX_HZ (optional): + + Define the SPI max work clock. If not defined then use 1MHz. + + - CONFIG_ENV_SPI_MODE (optional): + + Define the SPI work mode. If not defined then use SPI_MODE_3. + +config ENV_IS_IN_UBI + bool "Environment in a UBI volume" + depends on !CHAIN_OF_TRUST + 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_UBI_SILENCE_MSG + - CONFIG_UBIFS_SILENCE_MSG + + You will probably want to define these to avoid a really noisy system + when storing the env in UBI. + +config ENV_IS_NOWHERE + bool "Environment is not stored" + help + Define this if you don't want to or can't have an environment stored + on a storage medium + +config ENV_FAT_INTERFACE + string "Name of the block device for the environment" + depends on ENV_IS_IN_FAT + 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 environemt in FAT" + depends on ENV_IS_IN_FAT + default "0:1" if TI_COMMON_CMD_OPTIONS + default "0:auto" if ARCH_ZYNQMP + 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 environemnt" + 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. + +if ARCH_SUNXI + +config ENV_OFFSET + hex "Environment Offset" + depends on !ENV_IS_IN_UBI + depends on !ENV_IS_NOWHERE + default 0x88000 if ARCH_SUNXI + help + Offset from the start of the device (or partition) + +config ENV_SIZE + hex "Environment Size" + depends on !ENV_IS_NOWHERE + default 0x20000 if ARCH_SUNXI + help + Size of the environment storage area + +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. + +endif + +endmenu diff --git a/env/Makefile b/env/Makefile new file mode 100644 index 0000000000..4c1bdcfdf4 --- /dev/null +++ b/env/Makefile @@ -0,0 +1,57 @@ +# +# (C) Copyright 2004-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += common.o + +ifndef CONFIG_SPL_BUILD +obj-y += attr.o +obj-y += callback.o +obj-y += flags.o +obj-$(CONFIG_ENV_IS_IN_DATAFLASH) += dataflash.o +obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o +extra-$(CONFIG_ENV_IS_EMBEDDED) += embedded.o +obj-$(CONFIG_ENV_IS_IN_EEPROM) += embedded.o +extra-$(CONFIG_ENV_IS_IN_FLASH) += embedded.o +obj-$(CONFIG_ENV_IS_IN_NVRAM) += embedded.o +obj-$(CONFIG_ENV_IS_IN_FLASH) += flash.o +obj-$(CONFIG_ENV_IS_IN_MMC) += mmc.o +obj-$(CONFIG_ENV_IS_IN_FAT) += fat.o +obj-$(CONFIG_ENV_IS_IN_EXT4) += ext4.o +obj-$(CONFIG_ENV_IS_IN_NAND) += nand.o +obj-$(CONFIG_ENV_IS_IN_NVRAM) += nvram.o +obj-$(CONFIG_ENV_IS_IN_ONENAND) += onenand.o +obj-$(CONFIG_ENV_IS_IN_SATA) += sata.o +obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o +obj-$(CONFIG_ENV_IS_IN_REMOTE) += remote.o +obj-$(CONFIG_ENV_IS_IN_UBI) += ubi.o +obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o +endif + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_ENV_IS_IN_FLASH) += flash.o +# environment +ifdef CONFIG_TPL_BUILD +obj-$(CONFIG_TPL_ENV_SUPPORT) += attr.o +obj-$(CONFIG_TPL_ENV_SUPPORT) += flags.o +obj-$(CONFIG_TPL_ENV_SUPPORT) += callback.o +else +obj-$(CONFIG_SPL_ENV_SUPPORT) += attr.o +obj-$(CONFIG_SPL_ENV_SUPPORT) += flags.o +obj-$(CONFIG_SPL_ENV_SUPPORT) += callback.o +endif +ifneq ($(CONFIG_TPL_ENV_SUPPORT)$(CONFIG_SPL_ENV_SUPPORT),) +obj-$(CONFIG_ENV_IS_NOWHERE) += nowhere.o +obj-$(CONFIG_ENV_IS_IN_MMC) += mmc.o +obj-$(CONFIG_ENV_IS_IN_FAT) += fat.o +obj-$(CONFIG_ENV_IS_IN_EXT4) += ext4.o +obj-$(CONFIG_ENV_IS_IN_NAND) += nand.o +obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += sf.o +obj-$(CONFIG_ENV_IS_IN_FLASH) += flash.o +endif +endif + +CFLAGS_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff --git a/env/attr.c b/env/attr.c new file mode 100644 index 0000000000..f965b4bbb6 --- /dev/null +++ b/env/attr.c @@ -0,0 +1,310 @@ +/* + * (C) Copyright 2012 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */ +#include +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include + +/* + * Iterate through the whole list calling the callback for each found element. + * "attr_list" takes the form: + * attributes = [^,:\s]* + * entry = name[:attributes] + * list = entry[,list] + */ +int env_attr_walk(const char *attr_list, + int (*callback)(const char *name, const char *attributes, void *priv), + void *priv) +{ + const char *entry, *entry_end; + char *name, *attributes; + + if (!attr_list) + /* list not found */ + return 1; + + entry = attr_list; + do { + char *entry_cpy = NULL; + + entry_end = strchr(entry, ENV_ATTR_LIST_DELIM); + /* check if this is the last entry in the list */ + if (entry_end == NULL) { + int entry_len = strlen(entry); + + if (entry_len) { + /* + * allocate memory to copy the entry into since + * we will need to inject '\0' chars and squash + * white-space before calling the callback + */ + entry_cpy = malloc(entry_len + 1); + if (entry_cpy) + /* copy the rest of the list */ + strcpy(entry_cpy, entry); + else + return -ENOMEM; + } + } else { + int entry_len = entry_end - entry; + + if (entry_len) { + /* + * allocate memory to copy the entry into since + * we will need to inject '\0' chars and squash + * white-space before calling the callback + */ + entry_cpy = malloc(entry_len + 1); + if (entry_cpy) { + /* copy just this entry and null term */ + strncpy(entry_cpy, entry, entry_len); + entry_cpy[entry_len] = '\0'; + } else + return -ENOMEM; + } + } + + /* check if there is anything to process (e.g. not ",,,") */ + if (entry_cpy != NULL) { + attributes = strchr(entry_cpy, ENV_ATTR_SEP); + /* check if there is a ':' */ + if (attributes != NULL) { + /* replace the ':' with '\0' to term name */ + *attributes++ = '\0'; + /* remove white-space from attributes */ + attributes = strim(attributes); + } + /* remove white-space from name */ + name = strim(entry_cpy); + + /* only call the callback if there is a name */ + if (strlen(name) != 0) { + int retval = 0; + + retval = callback(name, attributes, priv); + if (retval) { + free(entry_cpy); + return retval; + } + } + } + + free(entry_cpy); + entry = entry_end + 1; + } while (entry_end != NULL); + + return 0; +} + +#if defined(CONFIG_REGEX) +struct regex_callback_priv { + const char *searched_for; + char *regex; + char *attributes; +}; + +static int regex_callback(const char *name, const char *attributes, void *priv) +{ + int retval = 0; + struct regex_callback_priv *cbp = (struct regex_callback_priv *)priv; + struct slre slre; + char regex[strlen(name) + 3]; + + /* Require the whole string to be described by the regex */ + sprintf(regex, "^%s$", name); + if (slre_compile(&slre, regex)) { + struct cap caps[slre.num_caps + 2]; + + if (slre_match(&slre, cbp->searched_for, + strlen(cbp->searched_for), caps)) { + free(cbp->regex); + if (!attributes) { + retval = -EINVAL; + goto done; + } + cbp->regex = malloc(strlen(regex) + 1); + if (cbp->regex) { + strcpy(cbp->regex, regex); + } else { + retval = -ENOMEM; + goto done; + } + + free(cbp->attributes); + cbp->attributes = malloc(strlen(attributes) + 1); + if (cbp->attributes) { + strcpy(cbp->attributes, attributes); + } else { + retval = -ENOMEM; + free(cbp->regex); + cbp->regex = NULL; + goto done; + } + } + } else { + printf("Error compiling regex: %s\n", slre.err_str); + retval = -EINVAL; + } +done: + return retval; +} + +/* + * Retrieve the attributes string associated with a single name in the list + * There is no protection on attributes being too small for the value + */ +int env_attr_lookup(const char *attr_list, const char *name, char *attributes) +{ + if (!attributes) + /* bad parameter */ + return -EINVAL; + if (!attr_list) + /* list not found */ + return -EINVAL; + + struct regex_callback_priv priv; + int retval; + + priv.searched_for = name; + priv.regex = NULL; + priv.attributes = NULL; + retval = env_attr_walk(attr_list, regex_callback, &priv); + if (retval) + return retval; /* error */ + + if (priv.regex) { + strcpy(attributes, priv.attributes); + free(priv.attributes); + free(priv.regex); + /* success */ + return 0; + } + return -ENOENT; /* not found in list */ +} +#else + +/* + * Search for the last exactly matching name in an attribute list + */ +static int reverse_name_search(const char *searched, const char *search_for, + const char **result) +{ + int result_size = 0; + const char *cur_searched = searched; + + if (result) + *result = NULL; + + if (*search_for == '\0') { + if (result) + *result = searched; + return strlen(searched); + } + + for (;;) { + const char *match = strstr(cur_searched, search_for); + const char *prevch; + const char *nextch; + + /* Stop looking if no new match is found */ + if (match == NULL) + break; + + prevch = match - 1; + nextch = match + strlen(search_for); + + /* Skip spaces */ + while (*prevch == ' ' && prevch >= searched) + prevch--; + while (*nextch == ' ') + nextch++; + + /* Start looking past the current match so last is found */ + cur_searched = match + 1; + /* Check for an exact match */ + if (match != searched && + *prevch != ENV_ATTR_LIST_DELIM && + prevch != searched - 1) + continue; + if (*nextch != ENV_ATTR_SEP && + *nextch != ENV_ATTR_LIST_DELIM && + *nextch != '\0') + continue; + + if (result) + *result = match; + result_size = strlen(search_for); + } + + return result_size; +} + +/* + * Retrieve the attributes string associated with a single name in the list + * There is no protection on attributes being too small for the value + */ +int env_attr_lookup(const char *attr_list, const char *name, char *attributes) +{ + const char *entry = NULL; + int entry_len; + + if (!attributes) + /* bad parameter */ + return -EINVAL; + if (!attr_list) + /* list not found */ + return -EINVAL; + + entry_len = reverse_name_search(attr_list, name, &entry); + if (entry != NULL) { + int len; + + /* skip the name */ + entry += entry_len; + /* skip spaces */ + while (*entry == ' ') + entry++; + if (*entry != ENV_ATTR_SEP) + len = 0; + else { + const char *delim; + static const char delims[] = { + ENV_ATTR_LIST_DELIM, ' ', '\0'}; + + /* skip the attr sep */ + entry += 1; + /* skip spaces */ + while (*entry == ' ') + entry++; + + delim = strpbrk(entry, delims); + if (delim == NULL) + len = strlen(entry); + else + len = delim - entry; + memcpy(attributes, entry, len); + } + attributes[len] = '\0'; + + /* success */ + return 0; + } + + /* not found in list */ + return -ENOENT; +} +#endif diff --git a/env/callback.c b/env/callback.c new file mode 100644 index 0000000000..1957cc1996 --- /dev/null +++ b/env/callback.c @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2012 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#if defined(CONFIG_NEEDS_MANUAL_RELOC) +DECLARE_GLOBAL_DATA_PTR; +#endif + +/* + * Look up a callback function pointer by name + */ +static struct env_clbk_tbl *find_env_callback(const char *name) +{ + struct env_clbk_tbl *clbkp; + int i; + int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk); + + if (name == NULL) + return NULL; + + /* look up the callback in the linker-list */ + for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk); + i < num_callbacks; + i++, clbkp++) { + if (strcmp(name, clbkp->name) == 0) + return clbkp; + } + + return NULL; +} + +static int first_call = 1; +static const char *callback_list; + +/* + * Look for a possible callback for a newly added variable + * This is called specifically when the variable did not exist in the hash + * previously, so the blanket update did not find this variable. + */ +void env_callback_init(ENTRY *var_entry) +{ + const char *var_name = var_entry->key; + char callback_name[256] = ""; + struct env_clbk_tbl *clbkp; + int ret = 1; + + if (first_call) { + callback_list = getenv(ENV_CALLBACK_VAR); + first_call = 0; + } + + /* look in the ".callbacks" var for a reference to this variable */ + if (callback_list != NULL) + ret = env_attr_lookup(callback_list, var_name, callback_name); + + /* only if not found there, look in the static list */ + if (ret) + ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name, + callback_name); + + /* if an association was found, set the callback pointer */ + if (!ret && strlen(callback_name)) { + clbkp = find_env_callback(callback_name); + if (clbkp != NULL) +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + var_entry->callback = clbkp->callback + gd->reloc_off; +#else + var_entry->callback = clbkp->callback; +#endif + } +} + +/* + * Called on each existing env var prior to the blanket update since removing + * a callback association should remove its callback. + */ +static int clear_callback(ENTRY *entry) +{ + entry->callback = NULL; + + return 0; +} + +/* + * Call for each element in the list that associates variables to callbacks + */ +static int set_callback(const char *name, const char *value, void *priv) +{ + ENTRY e, *ep; + struct env_clbk_tbl *clbkp; + + e.key = name; + e.data = NULL; + e.callback = NULL; + hsearch_r(e, FIND, &ep, &env_htab, 0); + + /* does the env variable actually exist? */ + if (ep != NULL) { + /* the assocaition delares no callback, so remove the pointer */ + if (value == NULL || strlen(value) == 0) + ep->callback = NULL; + else { + /* assign the requested callback */ + clbkp = find_env_callback(value); + if (clbkp != NULL) +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + ep->callback = clbkp->callback + gd->reloc_off; +#else + ep->callback = clbkp->callback; +#endif + } + } + + return 0; +} + +static int on_callbacks(const char *name, const char *value, enum env_op op, + int flags) +{ + /* remove all callbacks */ + hwalk_r(&env_htab, clear_callback); + + /* configure any static callback bindings */ + env_attr_walk(ENV_CALLBACK_LIST_STATIC, set_callback, NULL); + /* configure any dynamic callback bindings */ + env_attr_walk(value, set_callback, NULL); + + return 0; +} +U_BOOT_ENV_CALLBACK(callbacks, on_callbacks); diff --git a/env/common.c b/env/common.c new file mode 100644 index 0000000000..d9c0c4e3f3 --- /dev/null +++ b/env/common.c @@ -0,0 +1,353 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/************************************************************************ + * Default settings to be used when no valid environment is found + */ +#include + +struct hsearch_data env_htab = { + .change_ok = env_flags_validate, +}; + +__weak uchar env_get_char_spec(int index) +{ + return *((uchar *)(gd->env_addr + index)); +} + +static uchar env_get_char_init(int index) +{ + /* if crc was bad, use the default environment */ + if (gd->env_valid) + return env_get_char_spec(index); + else + return default_environment[index]; +} + +uchar env_get_char_memory(int index) +{ + return *env_get_addr(index); +} + +uchar env_get_char(int index) +{ + /* if relocated to RAM */ + if (gd->flags & GD_FLG_RELOC) + return env_get_char_memory(index); + else + return env_get_char_init(index); +} + +const uchar *env_get_addr(int index) +{ + if (gd->env_valid) + return (uchar *)(gd->env_addr + index); + else + return &default_environment[index]; +} + +/* + * Read an environment variable as a boolean + * Return -1 if variable does not exist (default to true) + */ +int getenv_yesno(const char *var) +{ + char *s = getenv(var); + + if (s == NULL) + return -1; + return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ? + 1 : 0; +} + +/* + * Look up the variable from the default environment + */ +char *getenv_default(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 = 0; + ret_val = getenv(name); + gd->env_valid = really_valid; + gd->flags = real_gd_flags; + return ret_val; +} + +void set_default_env(const char *s) +{ + int flags = 0; + + if (sizeof(default_environment) > ENV_SIZE) { + puts("*** Error - default environment is too large\n\n"); + return; + } + + if (s) { + if (*s == '!') { + printf("*** Warning - %s, " + "using default environment\n\n", + s + 1); + } else { + flags = H_INTERACTIVE; + puts(s); + } + } else { + puts("Using default environment\n\n"); + } + + if (himport_r(&env_htab, (char *)default_environment, + sizeof(default_environment), '\0', flags, 0, + 0, NULL) == 0) + 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 set_default_vars(int nvars, char * const vars[]) +{ + /* + * Special use-case: import from default environment + * (and use \0 as a separator) + */ + return himport_r(&env_htab, (const char *)default_environment, + sizeof(default_environment), '\0', + H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars); +} + +#ifdef CONFIG_ENV_AES +#include +/** + * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment + * + * This function shall return 16-byte array containing AES-128 key used + * to encrypt and decrypt the environment. This function must be overridden + * by the implementer as otherwise the environment encryption will not + * work. + */ +__weak uint8_t *env_aes_cbc_get_key(void) +{ + return NULL; +} + +static int env_aes_cbc_crypt(env_t *env, const int enc) +{ + unsigned char *data = env->data; + uint8_t *key; + uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; + uint32_t aes_blocks; + + key = env_aes_cbc_get_key(); + if (!key) + return -EINVAL; + + /* First we expand the key. */ + aes_expand_key(key, key_exp); + + /* Calculate the number of AES blocks to encrypt. */ + aes_blocks = ENV_SIZE / AES_KEY_LENGTH; + + if (enc) + aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); + else + aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); + + return 0; +} +#else +static inline int env_aes_cbc_crypt(env_t *env, const int enc) +{ + return 0; +} +#endif + +/* + * Check if CRC is valid and (if yes) import the environment. + * Note that "buf" may or may not be aligned. + */ +int env_import(const char *buf, int check) +{ + env_t *ep = (env_t *)buf; + int ret; + + if (check) { + uint32_t crc; + + memcpy(&crc, &ep->crc, sizeof(crc)); + + if (crc32(0, ep->data, ENV_SIZE) != crc) { + set_default_env("!bad CRC"); + return 0; + } + } + + /* Decrypt the env if desired. */ + ret = env_aes_cbc_crypt(ep, 0); + if (ret) { + error("Failed to decrypt env!\n"); + set_default_env("!import failed"); + return ret; + } + + if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, + 0, NULL)) { + gd->flags |= GD_FLG_ENV_READY; + return 1; + } + + error("Cannot import environment: errno = %d\n", errno); + + set_default_env("!import failed"); + + return 0; +} + +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +static unsigned char env_flags; + +int env_import_redund(const char *buf1, const char *buf2) +{ + int crc1_ok, crc2_ok; + env_t *ep, *tmp_env1, *tmp_env2; + + tmp_env1 = (env_t *)buf1; + tmp_env2 = (env_t *)buf2; + + 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) { + set_default_env("!bad CRC"); + return 0; + } 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; + } + + if (gd->env_valid == 1) + ep = tmp_env1; + else + ep = tmp_env2; + + env_flags = ep->flags; + return env_import((char *)ep, 0); +} +#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ + +/* Export the environment and generate CRC for it. */ +int env_export(env_t *env_out) +{ + char *res; + ssize_t len; + int ret; + + res = (char *)env_out->data; + len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); + if (len < 0) { + error("Cannot export environment: errno = %d\n", errno); + return 1; + } + + /* Encrypt the env if desired. */ + ret = env_aes_cbc_crypt(env_out, 1); + if (ret) + return ret; + + env_out->crc = crc32(0, env_out->data, ENV_SIZE); + +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + env_out->flags = ++env_flags; /* increase the serial */ +#endif + + return 0; +} + +void env_relocate(void) +{ +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + env_reloc(); + env_htab.change_ok += gd->reloc_off; +#endif + if (gd->env_valid == 0) { +#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD) + /* Environment not changable */ + set_default_env(NULL); +#else + bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM); + set_default_env("!bad CRC"); +#endif + } else { + env_relocate_spec(); + } +} + +#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) +int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) +{ + ENTRY *match; + int found, idx; + + idx = 0; + found = 0; + cmdv[0] = NULL; + + while ((idx = hmatch_r(var, idx, &match, &env_htab))) { + int vallen = strlen(match->key) + 1; + + if (found >= maxv - 2 || bufsz < vallen) + break; + + cmdv[found++] = buf; + memcpy(buf, match->key, vallen); + buf += vallen; + bufsz -= vallen; + } + + qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); + + if (idx) + cmdv[found++] = "..."; + + cmdv[found] = NULL; + return found; +} +#endif diff --git a/env/dataflash.c b/env/dataflash.c new file mode 100644 index 0000000000..034e323169 --- /dev/null +++ b/env/dataflash.c @@ -0,0 +1,84 @@ +/* + * LowLevel function for DataFlash environment support + * Author : Gilles Gastaldi (Atmel) + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +env_t *env_ptr; + +char *env_name_spec = "dataflash"; + +uchar env_get_char_spec(int index) +{ + uchar c; + + read_dataflash(CONFIG_ENV_ADDR + index + offsetof(env_t, data), + 1, (char *)&c); + return c; +} + +void env_relocate_spec(void) +{ + ulong crc, new = 0; + unsigned off; + char buf[CONFIG_ENV_SIZE]; + + /* Read old CRC */ + read_dataflash(CONFIG_ENV_ADDR + offsetof(env_t, crc), + sizeof(ulong), (char *)&crc); + + /* Read whole environment */ + read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, buf); + + /* Calculate the CRC */ + off = offsetof(env_t, data); + new = crc32(new, (unsigned char *)(buf + off), ENV_SIZE); + + if (crc == new) + env_import(buf, 1); + else + set_default_env("!bad CRC"); +} + +#ifdef CONFIG_ENV_OFFSET_REDUND +#error No support for redundant environment on dataflash yet! +#endif + +int saveenv(void) +{ + env_t env_new; + int ret; + + ret = env_export(&env_new); + if (ret) + return ret; + + return write_dataflash(CONFIG_ENV_ADDR, + (unsigned long)&env_new, + CONFIG_ENV_SIZE); +} + +/* + * Initialize environment use + * + * We are still running from ROM, so data use is limited. + * Use a (moderately small) buffer on the stack + */ +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} diff --git a/env/eeprom.c b/env/eeprom.c new file mode 100644 index 0000000000..5f63a6cd4a --- /dev/null +++ b/env/eeprom.c @@ -0,0 +1,245 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#if defined(CONFIG_I2C_ENV_EEPROM_BUS) +#include +#endif +#include +#include +#include /* for BUG_ON */ + +DECLARE_GLOBAL_DATA_PTR; + +env_t *env_ptr; + +char *env_name_spec = "EEPROM"; + +static int eeprom_bus_read(unsigned dev_addr, unsigned offset, + uchar *buffer, unsigned cnt) +{ + int rcode; +#if defined(CONFIG_I2C_ENV_EEPROM_BUS) + int old_bus = i2c_get_bus_num(); + + if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS) + i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS); +#endif + + rcode = eeprom_read(dev_addr, offset, buffer, cnt); + +#if defined(CONFIG_I2C_ENV_EEPROM_BUS) + i2c_set_bus_num(old_bus); +#endif + + return rcode; +} + +static int eeprom_bus_write(unsigned dev_addr, unsigned offset, + uchar *buffer, unsigned cnt) +{ + int rcode; +#if defined(CONFIG_I2C_ENV_EEPROM_BUS) + int old_bus = i2c_get_bus_num(); + + if (old_bus != CONFIG_I2C_ENV_EEPROM_BUS) + i2c_set_bus_num(CONFIG_I2C_ENV_EEPROM_BUS); +#endif + + rcode = eeprom_write(dev_addr, offset, buffer, cnt); + +#if defined(CONFIG_I2C_ENV_EEPROM_BUS) + i2c_set_bus_num(old_bus); +#endif + + return rcode; +} + +uchar env_get_char_spec(int index) +{ + uchar c; + unsigned int off = CONFIG_ENV_OFFSET; + +#ifdef CONFIG_ENV_OFFSET_REDUND + if (gd->env_valid == 2) + off = CONFIG_ENV_OFFSET_REDUND; +#endif + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + off + index + offsetof(env_t, data), &c, 1); + + return c; +} + +void env_relocate_spec(void) +{ + char buf_env[CONFIG_ENV_SIZE]; + unsigned int off = CONFIG_ENV_OFFSET; + +#ifdef CONFIG_ENV_OFFSET_REDUND + ulong len, crc[2], crc_tmp; + unsigned int off_env[2]; + uchar rdbuf[64], flags[2]; + int i, crc_ok[2] = {0, 0}; + + eeprom_init(-1); /* prepare for EEPROM read/write */ + + off_env[0] = CONFIG_ENV_OFFSET; + off_env[1] = CONFIG_ENV_OFFSET_REDUND; + + for (i = 0; i < 2; i++) { + /* read CRC */ + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + off_env[i] + offsetof(env_t, crc), + (uchar *)&crc[i], sizeof(ulong)); + /* read FLAGS */ + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + off_env[i] + offsetof(env_t, flags), + (uchar *)&flags[i], sizeof(uchar)); + + crc_tmp = 0; + len = ENV_SIZE; + off = off_env[i] + offsetof(env_t, data); + while (len > 0) { + int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; + + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, off, + rdbuf, n); + + crc_tmp = crc32(crc_tmp, rdbuf, n); + len -= n; + off += n; + } + + if (crc_tmp == crc[i]) + crc_ok[i] = 1; + } + + if (!crc_ok[0] && !crc_ok[1]) { + gd->env_addr = 0; + gd->env_valid = 0; + } else if (crc_ok[0] && !crc_ok[1]) { + gd->env_valid = 1; + } else if (!crc_ok[0] && crc_ok[1]) { + gd->env_valid = 2; + } else { + /* both ok - check serial */ + if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG) + gd->env_valid = 1; + else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG) + gd->env_valid = 2; + else if (flags[0] == 0xFF && flags[1] == 0) + gd->env_valid = 2; + else if (flags[1] == 0xFF && flags[0] == 0) + gd->env_valid = 1; + else /* flags are equal - almost impossible */ + gd->env_valid = 1; + } + +#else /* CONFIG_ENV_OFFSET_REDUND */ + ulong crc, len, new; + uchar rdbuf[64]; + + eeprom_init(-1); /* prepare for EEPROM read/write */ + + /* read old CRC */ + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + CONFIG_ENV_OFFSET + offsetof(env_t, crc), + (uchar *)&crc, sizeof(ulong)); + + new = 0; + len = ENV_SIZE; + off = offsetof(env_t, data); + while (len > 0) { + int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; + + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + CONFIG_ENV_OFFSET + off, rdbuf, n); + new = crc32(new, rdbuf, n); + len -= n; + off += n; + } + + if (crc == new) { + gd->env_valid = 1; + } else { + gd->env_valid = 0; + } +#endif /* CONFIG_ENV_OFFSET_REDUND */ + + off = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND + if (gd->env_valid == 2) + off = CONFIG_ENV_OFFSET_REDUND; +#endif + + eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR, + off, (uchar *)buf_env, CONFIG_ENV_SIZE); + + env_import(buf_env, 1); +} + +int saveenv(void) +{ + env_t env_new; + int rc; + unsigned int off = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND + unsigned int off_red = CONFIG_ENV_OFFSET_REDUND; + char flag_obsolete = OBSOLETE_FLAG; +#endif + + BUG_ON(env_ptr != NULL); + + rc = env_export(&env_new); + if (rc) + return rc; + +#ifdef CONFIG_ENV_OFFSET_REDUND + if (gd->env_valid == 1) { + off = CONFIG_ENV_OFFSET_REDUND; + off_red = CONFIG_ENV_OFFSET; + } + + env_new.flags = ACTIVE_FLAG; +#endif + + rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR, + off, (uchar *)&env_new, CONFIG_ENV_SIZE); + +#ifdef CONFIG_ENV_OFFSET_REDUND + if (rc == 0) { + eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR, + off_red + offsetof(env_t, flags), + (uchar *)&flag_obsolete, 1); + + if (gd->env_valid == 1) + gd->env_valid = 2; + else + gd->env_valid = 1; + } +#endif + return rc; +} + +/* + * Initialize Environment use + * + * We are still running from ROM, so data use is limited. + * Use a (moderately small) buffer on the stack + */ +int env_init(void) +{ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + return 0; +} diff --git a/env/embedded.c b/env/embedded.c new file mode 100644 index 0000000000..43694db70f --- /dev/null +++ b/env/embedded.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ /* Dirty trick to get only #defines */ +#endif +#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ +#include +#undef __ASSEMBLY__ +#include +#include + +/* Handle HOSTS that have prepended crap on symbol names, not TARGETS. */ +#if defined(__APPLE__) +/* Leading underscore on symbols */ +# define SYM_CHAR "_" +#else /* No leading character on symbols */ +# define SYM_CHAR +#endif + +/* + * Generate embedded environment table + * inside U-Boot image, if needed. + */ +#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_BUILD_ENVCRC) +/* + * Put the environment in the .text section when we are building + * U-Boot proper. The host based program "tools/envcrc" does not need + * a seperate section. + */ +#if defined(USE_HOSTCC) /* Native for 'tools/envcrc' */ +# define __UBOOT_ENV_SECTION__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ + +#else /* Environment is embedded in U-Boot's .text section */ +/* XXX - This only works with GNU C */ +# define __UBOOT_ENV_SECTION__ __attribute__ ((section(".text"))) +#endif + +/* + * Macros to generate global absolutes. + */ +#if defined(__bfin__) +# define GEN_SET_VALUE(name, value) \ + asm(".set " GEN_SYMNAME(name) ", " GEN_VALUE(value)) +#else +# define GEN_SET_VALUE(name, value) \ + asm(GEN_SYMNAME(name) " = " GEN_VALUE(value)) +#endif +#define GEN_SYMNAME(str) SYM_CHAR #str +#define GEN_VALUE(str) #str +#define GEN_ABS(name, value) \ + asm(".globl " GEN_SYMNAME(name)); \ + GEN_SET_VALUE(name, value) + +/* + * Check to see if we are building with a + * computed CRC. Otherwise define it as ~0. + */ +#if !defined(ENV_CRC) +# define ENV_CRC (~0) +#endif + +#define DEFAULT_ENV_INSTANCE_EMBEDDED +#include + +#ifdef CONFIG_ENV_ADDR_REDUND +env_t redundand_environment __UBOOT_ENV_SECTION__ = { + 0, /* CRC Sum: invalid */ + 0, /* Flags: invalid */ + { + "\0" + } +}; +#endif /* CONFIG_ENV_ADDR_REDUND */ + +/* + * These will end up in the .text section + * if the environment strings are embedded + * in the image. When this is used for + * tools/envcrc, they are placed in the + * .data/.sdata section. + * + */ +unsigned long env_size __UBOOT_ENV_SECTION__ = sizeof(env_t); + +/* + * Add in absolutes. + */ +GEN_ABS(env_offset, CONFIG_ENV_OFFSET); + +#endif /* ENV_IS_EMBEDDED */ diff --git a/env/ext4.c b/env/ext4.c new file mode 100644 index 0000000000..adefa7dc99 --- /dev/null +++ b/env/ext4.c @@ -0,0 +1,129 @@ +/* + * (c) Copyright 2016 by VRT Technology + * + * Author: + * Stuart Longland + * + * Based on FAT environment driver + * (c) Copyright 2011 by Tigris Elektronik GmbH + * + * Author: + * Maximilian Schwerin + * + * and EXT4 filesystem implementation + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar + * Manjunatha C Achar + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *env_name_spec = "EXT4"; + +env_t *env_ptr; + +DECLARE_GLOBAL_DATA_PTR; + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +int saveenv(void) +{ + env_t env_new; + struct blk_desc *dev_desc = NULL; + disk_partition_t info; + int dev, part; + int err; + + err = env_export(&env_new); + if (err) + return err; + + part = blk_get_device_part_str(EXT4_ENV_INTERFACE, + EXT4_ENV_DEVICE_AND_PART, + &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->devnum; + ext4fs_set_blk_dev(dev_desc, &info); + + if (!ext4fs_mount(info.size)) { + printf("\n** Unable to use %s %s for saveenv **\n", + EXT4_ENV_INTERFACE, EXT4_ENV_DEVICE_AND_PART); + return 1; + } + + err = ext4fs_write(EXT4_ENV_FILE, (void *)&env_new, sizeof(env_t)); + ext4fs_close(); + + if (err == -1) { + printf("\n** Unable to write \"%s\" from %s%d:%d **\n", + EXT4_ENV_FILE, EXT4_ENV_INTERFACE, dev, part); + return 1; + } + + puts("done\n"); + return 0; +} +#endif /* CONFIG_CMD_SAVEENV */ + +void env_relocate_spec(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + struct blk_desc *dev_desc = NULL; + disk_partition_t info; + int dev, part; + int err; + loff_t off; + + part = blk_get_device_part_str(EXT4_ENV_INTERFACE, + EXT4_ENV_DEVICE_AND_PART, + &dev_desc, &info, 1); + if (part < 0) + goto err_env_relocate; + + dev = dev_desc->devnum; + ext4fs_set_blk_dev(dev_desc, &info); + + if (!ext4fs_mount(info.size)) { + printf("\n** Unable to use %s %s for loading the env **\n", + EXT4_ENV_INTERFACE, EXT4_ENV_DEVICE_AND_PART); + goto err_env_relocate; + } + + err = ext4_read_file(EXT4_ENV_FILE, buf, 0, CONFIG_ENV_SIZE, &off); + ext4fs_close(); + + if (err == -1) { + printf("\n** Unable to read \"%s\" from %s%d:%d **\n", + EXT4_ENV_FILE, EXT4_ENV_INTERFACE, dev, part); + goto err_env_relocate; + } + + env_import(buf, 1); + return; + +err_env_relocate: + set_default_env(NULL); +} diff --git a/env/fat.c b/env/fat.c new file mode 100644 index 0000000000..b51c920cd4 --- /dev/null +++ b/env/fat.c @@ -0,0 +1,110 @@ +/* + * (c) Copyright 2011 by Tigris Elektronik GmbH + * + * Author: + * Maximilian Schwerin + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *env_name_spec = "FAT"; + +env_t *env_ptr; + +DECLARE_GLOBAL_DATA_PTR; + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +int saveenv(void) +{ + env_t env_new; + struct blk_desc *dev_desc = NULL; + disk_partition_t info; + int dev, part; + int err; + loff_t size; + + err = env_export(&env_new); + if (err) + return err; + + part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE, + CONFIG_ENV_FAT_DEVICE_AND_PART, + &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->devnum; + if (fat_set_blk_dev(dev_desc, &info) != 0) { + printf("\n** Unable to use %s %d:%d for saveenv **\n", + CONFIG_ENV_FAT_INTERFACE, dev, part); + return 1; + } + + err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t), + &size); + if (err == -1) { + printf("\n** Unable to write \"%s\" from %s%d:%d **\n", + CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part); + return 1; + } + + puts("done\n"); + return 0; +} +#endif /* CONFIG_CMD_SAVEENV */ + +void env_relocate_spec(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + struct blk_desc *dev_desc = NULL; + disk_partition_t info; + int dev, part; + int err; + + part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE, + CONFIG_ENV_FAT_DEVICE_AND_PART, + &dev_desc, &info, 1); + if (part < 0) + goto err_env_relocate; + + dev = dev_desc->devnum; + if (fat_set_blk_dev(dev_desc, &info) != 0) { + printf("\n** Unable to use %s %d:%d for loading the env **\n", + CONFIG_ENV_FAT_INTERFACE, dev, part); + goto err_env_relocate; + } + + err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE); + if (err == -1) { + printf("\n** Unable to read \"%s\" from %s%d:%d **\n", + CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part); + goto err_env_relocate; + } + + env_import(buf, 1); + return; + +err_env_relocate: + set_default_env(NULL); +} diff --git a/env/flags.c b/env/flags.c new file mode 100644 index 0000000000..3c50620cb3 --- /dev/null +++ b/env/flags.c @@ -0,0 +1,567 @@ +/* + * (C) Copyright 2012 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */ +#include +#include +#include "fw_env_private.h" +#include "fw_env.h" +#include +#include +#define getenv fw_getenv +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#else +#include +#include +#endif + +#ifdef CONFIG_CMD_NET +#define ENV_FLAGS_NET_VARTYPE_REPS "im" +#else +#define ENV_FLAGS_NET_VARTYPE_REPS "" +#endif + +static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS; +static const char env_flags_varaccess_rep[] = "aroc"; +static const int env_flags_varaccess_mask[] = { + 0, + ENV_FLAGS_VARACCESS_PREVENT_DELETE | + ENV_FLAGS_VARACCESS_PREVENT_CREATE | + ENV_FLAGS_VARACCESS_PREVENT_OVERWR, + ENV_FLAGS_VARACCESS_PREVENT_DELETE | + ENV_FLAGS_VARACCESS_PREVENT_OVERWR, + ENV_FLAGS_VARACCESS_PREVENT_DELETE | + ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR}; + +#ifdef CONFIG_CMD_ENV_FLAGS +static const char * const env_flags_vartype_names[] = { + "string", + "decimal", + "hexadecimal", + "boolean", +#ifdef CONFIG_CMD_NET + "IP address", + "MAC address", +#endif +}; +static const char * const env_flags_varaccess_names[] = { + "any", + "read-only", + "write-once", + "change-default", +}; + +/* + * Print the whole list of available type flags. + */ +void env_flags_print_vartypes(void) +{ + enum env_flags_vartype curtype = (enum env_flags_vartype)0; + + while (curtype != env_flags_vartype_end) { + printf("\t%c -\t%s\n", env_flags_vartype_rep[curtype], + env_flags_vartype_names[curtype]); + curtype++; + } +} + +/* + * Print the whole list of available access flags. + */ +void env_flags_print_varaccess(void) +{ + enum env_flags_varaccess curaccess = (enum env_flags_varaccess)0; + + while (curaccess != env_flags_varaccess_end) { + printf("\t%c -\t%s\n", env_flags_varaccess_rep[curaccess], + env_flags_varaccess_names[curaccess]); + curaccess++; + } +} + +/* + * Return the name of the type. + */ +const char *env_flags_get_vartype_name(enum env_flags_vartype type) +{ + return env_flags_vartype_names[type]; +} + +/* + * Return the name of the access. + */ +const char *env_flags_get_varaccess_name(enum env_flags_varaccess access) +{ + return env_flags_varaccess_names[access]; +} +#endif /* CONFIG_CMD_ENV_FLAGS */ + +/* + * Parse the flags string from a .flags attribute list into the vartype enum. + */ +enum env_flags_vartype env_flags_parse_vartype(const char *flags) +{ + char *type; + + if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC) + return env_flags_vartype_string; + + type = strchr(env_flags_vartype_rep, + flags[ENV_FLAGS_VARTYPE_LOC]); + + if (type != NULL) + return (enum env_flags_vartype) + (type - &env_flags_vartype_rep[0]); + + printf("## Warning: Unknown environment variable type '%c'\n", + flags[ENV_FLAGS_VARTYPE_LOC]); + return env_flags_vartype_string; +} + +/* + * Parse the flags string from a .flags attribute list into the varaccess enum. + */ +enum env_flags_varaccess env_flags_parse_varaccess(const char *flags) +{ + char *access; + + if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) + return env_flags_varaccess_any; + + access = strchr(env_flags_varaccess_rep, + flags[ENV_FLAGS_VARACCESS_LOC]); + + if (access != NULL) + return (enum env_flags_varaccess) + (access - &env_flags_varaccess_rep[0]); + + printf("## Warning: Unknown environment variable access method '%c'\n", + flags[ENV_FLAGS_VARACCESS_LOC]); + return env_flags_varaccess_any; +} + +/* + * Parse the binary flags from a hash table entry into the varaccess enum. + */ +enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(env_flags_varaccess_mask); i++) + if (env_flags_varaccess_mask[i] == + (binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) + return (enum env_flags_varaccess)i; + + printf("Warning: Non-standard access flags. (0x%x)\n", + binflags & ENV_FLAGS_VARACCESS_BIN_MASK); + + return env_flags_varaccess_any; +} + +static inline int is_hex_prefix(const char *value) +{ + return value[0] == '0' && (value[1] == 'x' || value[1] == 'X'); +} + +static void skip_num(int hex, const char *value, const char **end, + int max_digits) +{ + int i; + + if (hex && is_hex_prefix(value)) + value += 2; + + for (i = max_digits; i != 0; i--) { + if (hex && !isxdigit(*value)) + break; + if (!hex && !isdigit(*value)) + break; + value++; + } + if (end != NULL) + *end = value; +} + +#ifdef CONFIG_CMD_NET +int eth_validate_ethaddr_str(const char *addr) +{ + const char *end; + const char *cur; + int i; + + cur = addr; + for (i = 0; i < 6; i++) { + skip_num(1, cur, &end, 2); + if (cur == end) + return -1; + if (cur + 2 == end && is_hex_prefix(cur)) + return -1; + if (i != 5 && *end != ':') + return -1; + if (i == 5 && *end != '\0') + return -1; + cur = end + 1; + } + + return 0; +} +#endif + +/* + * Based on the declared type enum, validate that the value string complies + * with that format + */ +static int _env_flags_validate_type(const char *value, + enum env_flags_vartype type) +{ + const char *end; +#ifdef CONFIG_CMD_NET + const char *cur; + int i; +#endif + + switch (type) { + case env_flags_vartype_string: + break; + case env_flags_vartype_decimal: + skip_num(0, value, &end, -1); + if (*end != '\0') + return -1; + break; + case env_flags_vartype_hex: + skip_num(1, value, &end, -1); + if (*end != '\0') + return -1; + if (value + 2 == end && is_hex_prefix(value)) + return -1; + break; + case env_flags_vartype_bool: + if (value[0] != '1' && value[0] != 'y' && value[0] != 't' && + value[0] != 'Y' && value[0] != 'T' && + value[0] != '0' && value[0] != 'n' && value[0] != 'f' && + value[0] != 'N' && value[0] != 'F') + return -1; + if (value[1] != '\0') + return -1; + break; +#ifdef CONFIG_CMD_NET + case env_flags_vartype_ipaddr: + cur = value; + for (i = 0; i < 4; i++) { + skip_num(0, cur, &end, 3); + if (cur == end) + return -1; + if (i != 3 && *end != '.') + return -1; + if (i == 3 && *end != '\0') + return -1; + cur = end + 1; + } + break; + case env_flags_vartype_macaddr: + if (eth_validate_ethaddr_str(value)) + return -1; + break; +#endif + case env_flags_vartype_end: + return -1; + } + + /* OK */ + return 0; +} + +/* + * Look for flags in a provided list and failing that the static list + */ +static inline int env_flags_lookup(const char *flags_list, const char *name, + char *flags) +{ + int ret = 1; + + if (!flags) + /* bad parameter */ + return -1; + + /* try the env first */ + if (flags_list) + ret = env_attr_lookup(flags_list, name, flags); + + if (ret != 0) + /* if not found in the env, look in the static list */ + ret = env_attr_lookup(ENV_FLAGS_LIST_STATIC, name, flags); + + return ret; +} + +#ifdef USE_HOSTCC /* Functions only used from tools/env */ +/* + * Look up any flags directly from the .flags variable and the static list + * and convert them to the vartype enum. + */ +enum env_flags_vartype env_flags_get_type(const char *name) +{ + const char *flags_list = getenv(ENV_FLAGS_VAR); + char flags[ENV_FLAGS_ATTR_MAX_LEN + 1]; + + if (env_flags_lookup(flags_list, name, flags)) + return env_flags_vartype_string; + + if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC) + return env_flags_vartype_string; + + return env_flags_parse_vartype(flags); +} + +/* + * Look up the access of a variable directly from the .flags var. + */ +enum env_flags_varaccess env_flags_get_varaccess(const char *name) +{ + const char *flags_list = getenv(ENV_FLAGS_VAR); + char flags[ENV_FLAGS_ATTR_MAX_LEN + 1]; + + if (env_flags_lookup(flags_list, name, flags)) + return env_flags_varaccess_any; + + if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) + return env_flags_varaccess_any; + + return env_flags_parse_varaccess(flags); +} + +/* + * Validate that the proposed new value for "name" is valid according to the + * defined flags for that variable, if any. + */ +int env_flags_validate_type(const char *name, const char *value) +{ + enum env_flags_vartype type; + + if (value == NULL) + return 0; + type = env_flags_get_type(name); + if (_env_flags_validate_type(value, type) < 0) { + printf("## Error: flags type check failure for " + "\"%s\" <= \"%s\" (type: %c)\n", + name, value, env_flags_vartype_rep[type]); + return -1; + } + return 0; +} + +/* + * Validate that the proposed access to variable "name" is valid according to + * the defined flags for that variable, if any. + */ +int env_flags_validate_varaccess(const char *name, int check_mask) +{ + enum env_flags_varaccess access; + int access_mask; + + access = env_flags_get_varaccess(name); + access_mask = env_flags_varaccess_mask[access]; + + return (check_mask & access_mask) != 0; +} + +/* + * Validate the parameters to "env set" directly + */ +int env_flags_validate_env_set_params(char *name, char * const val[], int count) +{ + if ((count >= 1) && val[0] != NULL) { + enum env_flags_vartype type = env_flags_get_type(name); + + /* + * we don't currently check types that need more than + * one argument + */ + if (type != env_flags_vartype_string && count > 1) { + printf("## Error: too many parameters for setting \"%s\"\n", + name); + return -1; + } + return env_flags_validate_type(name, val[0]); + } + /* ok */ + return 0; +} + +#else /* !USE_HOSTCC - Functions only used from lib/hashtable.c */ + +/* + * Parse the flag charachters from the .flags attribute list into the binary + * form to be stored in the environment entry->flags field. + */ +static int env_parse_flags_to_bin(const char *flags) +{ + int binflags; + + binflags = env_flags_parse_vartype(flags) & ENV_FLAGS_VARTYPE_BIN_MASK; + binflags |= env_flags_varaccess_mask[env_flags_parse_varaccess(flags)]; + + return binflags; +} + +static int first_call = 1; +static const char *flags_list; + +/* + * Look for possible flags for a newly added variable + * This is called specifically when the variable did not exist in the hash + * previously, so the blanket update did not find this variable. + */ +void env_flags_init(ENTRY *var_entry) +{ + const char *var_name = var_entry->key; + char flags[ENV_FLAGS_ATTR_MAX_LEN + 1] = ""; + int ret = 1; + + if (first_call) { + flags_list = getenv(ENV_FLAGS_VAR); + first_call = 0; + } + /* look in the ".flags" and static for a reference to this variable */ + ret = env_flags_lookup(flags_list, var_name, flags); + + /* if any flags were found, set the binary form to the entry */ + if (!ret && strlen(flags)) + var_entry->flags = env_parse_flags_to_bin(flags); +} + +/* + * Called on each existing env var prior to the blanket update since removing + * a flag in the flag list should remove its flags. + */ +static int clear_flags(ENTRY *entry) +{ + entry->flags = 0; + + return 0; +} + +/* + * Call for each element in the list that defines flags for a variable + */ +static int set_flags(const char *name, const char *value, void *priv) +{ + ENTRY e, *ep; + + e.key = name; + e.data = NULL; + e.callback = NULL; + hsearch_r(e, FIND, &ep, &env_htab, 0); + + /* does the env variable actually exist? */ + if (ep != NULL) { + /* the flag list is empty, so clear the flags */ + if (value == NULL || strlen(value) == 0) + ep->flags = 0; + else + /* assign the requested flags */ + ep->flags = env_parse_flags_to_bin(value); + } + + return 0; +} + +static int on_flags(const char *name, const char *value, enum env_op op, + int flags) +{ + /* remove all flags */ + hwalk_r(&env_htab, clear_flags); + + /* configure any static flags */ + env_attr_walk(ENV_FLAGS_LIST_STATIC, set_flags, NULL); + /* configure any dynamic flags */ + env_attr_walk(value, set_flags, NULL); + + return 0; +} +U_BOOT_ENV_CALLBACK(flags, on_flags); + +/* + * Perform consistency checking before creating, overwriting, or deleting an + * environment variable. Called as a callback function by hsearch_r() and + * hdelete_r(). Returns 0 in case of success, 1 in case of failure. + * When (flag & H_FORCE) is set, do not print out any error message and force + * overwriting of write-once variables. + */ + +int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op, + int flag) +{ + const char *name; + const char *oldval = NULL; + + if (op != env_op_create) + oldval = item->data; + + name = item->key; + + /* Default value for NULL to protect string-manipulating functions */ + newval = newval ? : ""; + + /* validate the value to match the variable type */ + if (op != env_op_delete) { + enum env_flags_vartype type = (enum env_flags_vartype) + (ENV_FLAGS_VARTYPE_BIN_MASK & item->flags); + + if (_env_flags_validate_type(newval, type) < 0) { + printf("## Error: flags type check failure for " + "\"%s\" <= \"%s\" (type: %c)\n", + name, newval, env_flags_vartype_rep[type]); + return -1; + } + } + + /* check for access permission */ +#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE + if (flag & H_FORCE) + return 0; +#endif + switch (op) { + case env_op_delete: + if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) { + printf("## Error: Can't delete \"%s\"\n", name); + return 1; + } + break; + case env_op_overwrite: + if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_OVERWR) { + printf("## Error: Can't overwrite \"%s\"\n", name); + return 1; + } else if (item->flags & + ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR) { + const char *defval = getenv_default(name); + + if (defval == NULL) + defval = ""; + printf("oldval: %s defval: %s\n", oldval, defval); + if (strcmp(oldval, defval) != 0) { + printf("## Error: Can't overwrite \"%s\"\n", + name); + return 1; + } + } + break; + case env_op_create: + if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_CREATE) { + printf("## Error: Can't create \"%s\"\n", name); + return 1; + } + break; + } + + return 0; +} + +#endif diff --git a/env/flash.c b/env/flash.c new file mode 100644 index 0000000000..004e8849a7 --- /dev/null +++ b/env/flash.c @@ -0,0 +1,338 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* #define DEBUG */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_FLASH) +#define CMD_SAVEENV +#elif defined(CONFIG_ENV_ADDR_REDUND) +#error CONFIG_ENV_ADDR_REDUND must have CONFIG_CMD_SAVEENV & CONFIG_CMD_FLASH +#endif + +#if defined(CONFIG_ENV_SIZE_REDUND) && \ + (CONFIG_ENV_SIZE_REDUND < CONFIG_ENV_SIZE) +#error CONFIG_ENV_SIZE_REDUND should not be less then CONFIG_ENV_SIZE +#endif + +char *env_name_spec = "Flash"; + +#ifdef ENV_IS_EMBEDDED +env_t *env_ptr = &environment; + +static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; + +#else /* ! ENV_IS_EMBEDDED */ + +env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; +static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; +#endif /* ENV_IS_EMBEDDED */ + +#if defined(CMD_SAVEENV) || defined(CONFIG_ENV_ADDR_REDUND) +/* CONFIG_ENV_ADDR is supposed to be on sector boundary */ +static ulong end_addr = CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1; +#endif + +#ifdef CONFIG_ENV_ADDR_REDUND +static env_t *flash_addr_new = (env_t *)CONFIG_ENV_ADDR_REDUND; + +/* CONFIG_ENV_ADDR_REDUND is supposed to be on sector boundary */ +static ulong end_addr_new = CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1; +#endif /* CONFIG_ENV_ADDR_REDUND */ + + +#ifdef CONFIG_ENV_ADDR_REDUND +int env_init(void) +{ + int crc1_ok = 0, crc2_ok = 0; + + uchar flag1 = flash_addr->flags; + uchar flag2 = flash_addr_new->flags; + + ulong addr_default = (ulong)&default_environment[0]; + ulong addr1 = (ulong)&(flash_addr->data); + ulong addr2 = (ulong)&(flash_addr_new->data); + + crc1_ok = crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc; + crc2_ok = + crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc; + + if (crc1_ok && !crc2_ok) { + gd->env_addr = addr1; + gd->env_valid = 1; + } else if (!crc1_ok && crc2_ok) { + gd->env_addr = addr2; + gd->env_valid = 1; + } else if (!crc1_ok && !crc2_ok) { + gd->env_addr = addr_default; + gd->env_valid = 0; + } else if (flag1 == ACTIVE_FLAG && flag2 == OBSOLETE_FLAG) { + gd->env_addr = addr1; + gd->env_valid = 1; + } else if (flag1 == OBSOLETE_FLAG && flag2 == ACTIVE_FLAG) { + gd->env_addr = addr2; + gd->env_valid = 1; + } else if (flag1 == flag2) { + gd->env_addr = addr1; + gd->env_valid = 2; + } else if (flag1 == 0xFF) { + gd->env_addr = addr1; + gd->env_valid = 2; + } else if (flag2 == 0xFF) { + gd->env_addr = addr2; + gd->env_valid = 2; + } + + return 0; +} + +#ifdef CMD_SAVEENV +int saveenv(void) +{ + env_t env_new; + char *saved_data = NULL; + char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG; + int rc = 1; +#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE + ulong up_data = 0; +#endif + + debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr); + + if (flash_sect_protect(0, (ulong)flash_addr, end_addr)) + goto done; + + debug("Protect off %08lX ... %08lX\n", + (ulong)flash_addr_new, end_addr_new); + + if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) + goto done; + + rc = env_export(&env_new); + if (rc) + return rc; + env_new.flags = new_flag; + +#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE + up_data = end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE); + debug("Data to save 0x%lX\n", up_data); + if (up_data) { + saved_data = malloc(up_data); + if (saved_data == NULL) { + printf("Unable to save the rest of sector (%ld)\n", + up_data); + goto done; + } + memcpy(saved_data, + (void *)((long)flash_addr_new + CONFIG_ENV_SIZE), + up_data); + debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n", + (long)flash_addr_new + CONFIG_ENV_SIZE, + up_data, saved_data); + } +#endif + puts("Erasing Flash..."); + debug(" %08lX ... %08lX ...", (ulong)flash_addr_new, end_addr_new); + + if (flash_sect_erase((ulong)flash_addr_new, end_addr_new)) + goto done; + + puts("Writing to Flash... "); + debug(" %08lX ... %08lX ...", + (ulong)&(flash_addr_new->data), + sizeof(env_ptr->data) + (ulong)&(flash_addr_new->data)); + rc = flash_write((char *)&env_new, (ulong)flash_addr_new, + sizeof(env_new)); + if (rc) + goto perror; + + rc = flash_write(&flag, (ulong)&(flash_addr->flags), + sizeof(flash_addr->flags)); + if (rc) + goto perror; + +#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE + if (up_data) { /* restore the rest of sector */ + debug("Restoring the rest of data to 0x%lX len 0x%lX\n", + (long)flash_addr_new + CONFIG_ENV_SIZE, up_data); + if (flash_write(saved_data, + (long)flash_addr_new + CONFIG_ENV_SIZE, + up_data)) + goto perror; + } +#endif + puts("done\n"); + + { + env_t *etmp = flash_addr; + ulong ltmp = end_addr; + + flash_addr = flash_addr_new; + flash_addr_new = etmp; + + end_addr = end_addr_new; + end_addr_new = ltmp; + } + + rc = 0; + goto done; +perror: + flash_perror(rc); +done: + if (saved_data) + free(saved_data); + /* try to re-protect */ + flash_sect_protect(1, (ulong)flash_addr, end_addr); + flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new); + + return rc; +} +#endif /* CMD_SAVEENV */ + +#else /* ! CONFIG_ENV_ADDR_REDUND */ + +int env_init(void) +{ + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); + gd->env_valid = 1; + return 0; + } + + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 0; + return 0; +} + +#ifdef CMD_SAVEENV +int saveenv(void) +{ + env_t env_new; + int rc = 1; + char *saved_data = NULL; +#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE + ulong up_data = 0; + + up_data = end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE); + debug("Data to save 0x%lx\n", up_data); + if (up_data) { + saved_data = malloc(up_data); + if (saved_data == NULL) { + printf("Unable to save the rest of sector (%ld)\n", + up_data); + goto done; + } + memcpy(saved_data, + (void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data); + debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n", + (ulong)flash_addr + CONFIG_ENV_SIZE, + up_data, + (ulong)saved_data); + } +#endif /* CONFIG_ENV_SECT_SIZE */ + + debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr); + + if (flash_sect_protect(0, (long)flash_addr, end_addr)) + goto done; + + rc = env_export(&env_new); + if (rc) + goto done; + + puts("Erasing Flash..."); + if (flash_sect_erase((long)flash_addr, end_addr)) + goto done; + + puts("Writing to Flash... "); + rc = flash_write((char *)&env_new, (long)flash_addr, CONFIG_ENV_SIZE); + if (rc != 0) + goto perror; + +#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE + if (up_data) { /* restore the rest of sector */ + debug("Restoring the rest of data to 0x%lx len 0x%lx\n", + (ulong)flash_addr + CONFIG_ENV_SIZE, up_data); + if (flash_write(saved_data, + (long)flash_addr + CONFIG_ENV_SIZE, + up_data)) + goto perror; + } +#endif + puts("done\n"); + rc = 0; + goto done; +perror: + flash_perror(rc); +done: + if (saved_data) + free(saved_data); + /* try to re-protect */ + flash_sect_protect(1, (long)flash_addr, end_addr); + return rc; +} +#endif /* CMD_SAVEENV */ + +#endif /* CONFIG_ENV_ADDR_REDUND */ + +void env_relocate_spec(void) +{ +#ifdef CONFIG_ENV_ADDR_REDUND + if (gd->env_addr != (ulong)&(flash_addr->data)) { + env_t *etmp = flash_addr; + ulong ltmp = end_addr; + + flash_addr = flash_addr_new; + flash_addr_new = etmp; + + end_addr = end_addr_new; + end_addr_new = ltmp; + } + + if (flash_addr_new->flags != OBSOLETE_FLAG && + crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc) { + char flag = OBSOLETE_FLAG; + + gd->env_valid = 2; + flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new); + flash_write(&flag, + (ulong)&(flash_addr_new->flags), + sizeof(flash_addr_new->flags)); + flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new); + } + + if (flash_addr->flags != ACTIVE_FLAG && + (flash_addr->flags & ACTIVE_FLAG) == ACTIVE_FLAG) { + char flag = ACTIVE_FLAG; + + gd->env_valid = 2; + flash_sect_protect(0, (ulong)flash_addr, end_addr); + flash_write(&flag, + (ulong)&(flash_addr->flags), + sizeof(flash_addr->flags)); + flash_sect_protect(1, (ulong)flash_addr, end_addr); + } + + if (gd->env_valid == 2) + puts("*** Warning - some problems detected " + "reading environment; recovered successfully\n\n"); +#endif /* CONFIG_ENV_ADDR_REDUND */ + + env_import((char *)flash_addr, 1); +} diff --git a/env/mmc.c b/env/mmc.c new file mode 100644 index 0000000000..bb760a00ed --- /dev/null +++ b/env/mmc.c @@ -0,0 +1,326 @@ +/* + * (C) Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* #define DEBUG */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +char *env_name_spec = "MMC"; + +#ifdef ENV_IS_EMBEDDED +env_t *env_ptr = &environment; +#else /* ! ENV_IS_EMBEDDED */ +env_t *env_ptr; +#endif /* ENV_IS_EMBEDDED */ + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_ENV_OFFSET) +#define CONFIG_ENV_OFFSET 0 +#endif + +#if CONFIG_IS_ENABLED(OF_CONTROL) +static inline s64 mmc_offset(int copy) +{ + const char *propname = "u-boot,mmc-env-offset"; + s64 defvalue = CONFIG_ENV_OFFSET; + +#if defined(CONFIG_ENV_OFFSET_REDUND) + if (copy) { + propname = "u-boot,mmc-env-offset-redundant"; + defvalue = CONFIG_ENV_OFFSET_REDUND; + } +#endif + + return fdtdec_get_config_int(gd->fdt_blob, propname, defvalue); +} +#else +static inline s64 mmc_offset(int copy) +{ + s64 offset = CONFIG_ENV_OFFSET; + +#if defined(CONFIG_ENV_OFFSET_REDUND) + if (copy) + offset = CONFIG_ENV_OFFSET_REDUND; +#endif + return offset; +} +#endif + +__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) +{ + s64 offset = mmc_offset(copy); + + if (offset < 0) + offset += mmc->capacity; + + *env_addr = offset; + + return 0; +} + +__weak int mmc_get_env_dev(void) +{ + return CONFIG_SYS_MMC_ENV_DEV; +} + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#ifdef CONFIG_SYS_MMC_ENV_PART +__weak uint mmc_get_env_part(struct mmc *mmc) +{ + return CONFIG_SYS_MMC_ENV_PART; +} + +static unsigned char env_mmc_orig_hwpart; + +static int mmc_set_env_part(struct mmc *mmc) +{ + uint part = mmc_get_env_part(mmc); + int dev = mmc_get_env_dev(); + int ret = 0; + + env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart; + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); + if (ret) + puts("MMC partition switch failed\n"); + + return ret; +} +#else +static inline int mmc_set_env_part(struct mmc *mmc) {return 0; }; +#endif + +static const char *init_mmc_for_env(struct mmc *mmc) +{ + if (!mmc) + return "!No MMC card found"; + +#ifdef CONFIG_BLK + struct udevice *dev; + + if (blk_get_from_parent(mmc->dev, &dev)) + return "!No block device"; +#else + if (mmc_init(mmc)) + return "!MMC init failed"; +#endif + if (mmc_set_env_part(mmc)) + return "!MMC partition switch failed"; + + return NULL; +} + +static void fini_mmc_for_env(struct mmc *mmc) +{ +#ifdef CONFIG_SYS_MMC_ENV_PART + int dev = mmc_get_env_dev(); + + blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart); +#endif +} + +#ifdef CONFIG_CMD_SAVEENV +static inline int write_env(struct mmc *mmc, unsigned long size, + unsigned long offset, const void *buffer) +{ + uint blk_start, blk_cnt, n; + struct blk_desc *desc = mmc_get_blk_desc(mmc); + + blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; + blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; + + n = blk_dwrite(desc, blk_start, blk_cnt, (u_char *)buffer); + + return (n == blk_cnt) ? 0 : -1; +} + +int saveenv(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); + int dev = mmc_get_env_dev(); + struct mmc *mmc = find_mmc_device(dev); + u32 offset; + int ret, copy = 0; + const char *errmsg; + + errmsg = init_mmc_for_env(mmc); + if (errmsg) { + printf("%s\n", errmsg); + return 1; + } + + ret = env_export(env_new); + if (ret) + goto fini; + +#ifdef CONFIG_ENV_OFFSET_REDUND + if (gd->env_valid == 1) + copy = 1; +#endif + + if (mmc_get_env_addr(mmc, copy, &offset)) { + ret = 1; + goto fini; + } + + printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", dev); + if (write_env(mmc, 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 == 2 ? 1 : 2; +#endif + +fini: + fini_mmc_for_env(mmc); + return ret; +} +#endif /* CONFIG_CMD_SAVEENV */ + +static inline int read_env(struct mmc *mmc, unsigned long size, + unsigned long offset, const void *buffer) +{ + uint blk_start, blk_cnt, n; + struct blk_desc *desc = mmc_get_blk_desc(mmc); + + blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; + blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; + + n = blk_dread(desc, blk_start, blk_cnt, (uchar *)buffer); + + return (n == blk_cnt) ? 0 : -1; +} + +#ifdef CONFIG_ENV_OFFSET_REDUND +void env_relocate_spec(void) +{ +#if !defined(ENV_IS_EMBEDDED) + struct mmc *mmc; + u32 offset1, offset2; + int read1_fail = 0, read2_fail = 0; + int ret; + int dev = mmc_get_env_dev(); + const char *errmsg = NULL; + + ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env1, 1); + ALLOC_CACHE_ALIGN_BUFFER(env_t, tmp_env2, 1); + + mmc = find_mmc_device(dev); + + errmsg = init_mmc_for_env(mmc); + if (errmsg) { + ret = 1; + goto err; + } + + if (mmc_get_env_addr(mmc, 0, &offset1) || + mmc_get_env_addr(mmc, 1, &offset2)) { + ret = 1; + goto fini; + } + + read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); + read2_fail = read_env(mmc, 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 = 1; + goto fini; + } else if (!read1_fail && read2_fail) { + gd->env_valid = 1; + env_import((char *)tmp_env1, 1); + } else if (read1_fail && !read2_fail) { + gd->env_valid = 2; + env_import((char *)tmp_env2, 1); + } else { + env_import_redund((char *)tmp_env1, (char *)tmp_env2); + } + + ret = 0; + +fini: + fini_mmc_for_env(mmc); +err: + if (ret) + set_default_env(errmsg); +#endif +} +#else /* ! CONFIG_ENV_OFFSET_REDUND */ +void env_relocate_spec(void) +{ +#if !defined(ENV_IS_EMBEDDED) + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + struct mmc *mmc; + u32 offset; + int ret; + int dev = mmc_get_env_dev(); + const char *errmsg; + + mmc = find_mmc_device(dev); + + errmsg = init_mmc_for_env(mmc); + if (errmsg) { + ret = 1; + goto err; + } + + if (mmc_get_env_addr(mmc, 0, &offset)) { + ret = 1; + goto fini; + } + + if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) { + errmsg = "!read failed"; + ret = 1; + goto fini; + } + + env_import(buf, 1); + ret = 0; + +fini: + fini_mmc_for_env(mmc); +err: + if (ret) + set_default_env(errmsg); +#endif +} +#endif /* CONFIG_ENV_OFFSET_REDUND */ diff --git a/env/nand.c b/env/nand.c new file mode 100644 index 0000000000..760f6859e3 --- /dev/null +++ b/env/nand.c @@ -0,0 +1,395 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2008 + * Stuart Wood, Lab X Technologies + * + * (C) Copyright 2004 + * Jian Zhang, Texas Instruments, jzhang@ti.com. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_NAND) +#define CMD_SAVEENV +#elif defined(CONFIG_ENV_OFFSET_REDUND) +#error CONFIG_ENV_OFFSET_REDUND must have CONFIG_CMD_SAVEENV & CONFIG_CMD_NAND +#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 + +#ifndef CONFIG_ENV_RANGE +#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE +#endif + +char *env_name_spec = "NAND"; + +#if defined(ENV_IS_EMBEDDED) +env_t *env_ptr = &environment; +#elif defined(CONFIG_NAND_ENV_DST) +env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST; +#else /* ! ENV_IS_EMBEDDED */ +env_t *env_ptr; +#endif /* ENV_IS_EMBEDDED */ + +DECLARE_GLOBAL_DATA_PTR; + +/* + * 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 does the real validation. + * + * When using a NAND boot image (like sequoia_nand), the environment + * can be embedded or attached to the U-Boot image in NAND flash. + * This way the SPL loads not only the U-Boot image from NAND but + * also the environment. + */ +int env_init(void) +{ +#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_NAND_ENV_DST) + int crc1_ok = 0, crc2_ok = 0; + env_t *tmp_env1; + +#ifdef CONFIG_ENV_OFFSET_REDUND + env_t *tmp_env2; + + tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE); + crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc; +#endif + tmp_env1 = env_ptr; + crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; + + if (!crc1_ok && !crc2_ok) { + gd->env_addr = 0; + gd->env_valid = 0; + + return 0; + } else if (crc1_ok && !crc2_ok) { + gd->env_valid = 1; + } +#ifdef CONFIG_ENV_OFFSET_REDUND + 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; + } + + if (gd->env_valid == 2) + env_ptr = tmp_env2; + else +#endif + if (gd->env_valid == 1) + env_ptr = tmp_env1; + + gd->env_addr = (ulong)env_ptr->data; + +#else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; +#endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */ + + return 0; +} + +#ifdef CMD_SAVEENV +/* + * The legacy NAND code saved the environment in the first NAND device i.e., + * nand_dev_desc + 0. This is also the behaviour using the new NAND code. + */ +static int writeenv(size_t offset, u_char *buf) +{ + size_t end = offset + CONFIG_ENV_RANGE; + size_t amount_saved = 0; + size_t blocksize, len; + struct mtd_info *mtd; + u_char *char_ptr; + + mtd = get_nand_dev_by_index(0); + if (!mtd) + return 1; + + blocksize = mtd->erasesize; + len = min(blocksize, (size_t)CONFIG_ENV_SIZE); + + while (amount_saved < CONFIG_ENV_SIZE && offset < end) { + if (nand_block_isbad(mtd, offset)) { + offset += blocksize; + } else { + char_ptr = &buf[amount_saved]; + if (nand_write(mtd, offset, &len, char_ptr)) + return 1; + + offset += blocksize; + amount_saved += len; + } + } + if (amount_saved != CONFIG_ENV_SIZE) + return 1; + + return 0; +} + +struct env_location { + const char *name; + const nand_erase_options_t erase_opts; +}; + +static int erase_and_write_env(const struct env_location *location, + u_char *env_new) +{ + struct mtd_info *mtd; + int ret = 0; + + mtd = get_nand_dev_by_index(0); + if (!mtd) + return 1; + + printf("Erasing %s...\n", location->name); + if (nand_erase_opts(mtd, &location->erase_opts)) + return 1; + + printf("Writing to %s... ", location->name); + ret = writeenv(location->erase_opts.offset, env_new); + puts(ret ? "FAILED!\n" : "OK\n"); + + return ret; +} + +int saveenv(void) +{ + int ret = 0; + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); + int env_idx = 0; + static const struct env_location location[] = { + { + .name = "NAND", + .erase_opts = { + .length = CONFIG_ENV_RANGE, + .offset = CONFIG_ENV_OFFSET, + }, + }, +#ifdef CONFIG_ENV_OFFSET_REDUND + { + .name = "redundant NAND", + .erase_opts = { + .length = CONFIG_ENV_RANGE, + .offset = CONFIG_ENV_OFFSET_REDUND, + }, + }, +#endif + }; + + + if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) + return 1; + + ret = env_export(env_new); + if (ret) + return ret; + +#ifdef CONFIG_ENV_OFFSET_REDUND + env_idx = (gd->env_valid == 1); +#endif + + ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); +#ifdef CONFIG_ENV_OFFSET_REDUND + if (!ret) { + /* preset other copy for next write */ + gd->env_valid = gd->env_valid == 2 ? 1 : 2; + return ret; + } + + env_idx = (env_idx + 1) & 1; + ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); + if (!ret) + printf("Warning: primary env write failed," + " redundancy is lost!\n"); +#endif + + return ret; +} +#endif /* CMD_SAVEENV */ + +#if defined(CONFIG_SPL_BUILD) +static int readenv(size_t offset, u_char *buf) +{ + return nand_spl_load_image(offset, CONFIG_ENV_SIZE, buf); +} +#else +static int readenv(size_t offset, u_char *buf) +{ + size_t end = offset + CONFIG_ENV_RANGE; + size_t amount_loaded = 0; + size_t blocksize, len; + struct mtd_info *mtd; + u_char *char_ptr; + + mtd = get_nand_dev_by_index(0); + if (!mtd) + return 1; + + blocksize = mtd->erasesize; + len = min(blocksize, (size_t)CONFIG_ENV_SIZE); + + while (amount_loaded < CONFIG_ENV_SIZE && offset < end) { + if (nand_block_isbad(mtd, offset)) { + offset += blocksize; + } else { + char_ptr = &buf[amount_loaded]; + if (nand_read_skip_bad(mtd, offset, + &len, NULL, + mtd->size, char_ptr)) + return 1; + + offset += blocksize; + amount_loaded += len; + } + } + + if (amount_loaded != CONFIG_ENV_SIZE) + return 1; + + return 0; +} +#endif /* #if defined(CONFIG_SPL_BUILD) */ + +#ifdef CONFIG_ENV_OFFSET_OOB +int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result) +{ + struct mtd_oob_ops ops; + uint32_t oob_buf[ENV_OFFSET_SIZE / sizeof(uint32_t)]; + int ret; + + ops.datbuf = NULL; + ops.mode = MTD_OOB_AUTO; + ops.ooboffs = 0; + ops.ooblen = ENV_OFFSET_SIZE; + ops.oobbuf = (void *)oob_buf; + + ret = mtd->read_oob(mtd, ENV_OFFSET_SIZE, &ops); + if (ret) { + printf("error reading OOB block 0\n"); + return ret; + } + + if (oob_buf[0] == ENV_OOB_MARKER) { + *result = oob_buf[1] * mtd->erasesize; + } else if (oob_buf[0] == ENV_OOB_MARKER_OLD) { + *result = oob_buf[1]; + } else { + printf("No dynamic environment marker in OOB block 0\n"); + return -ENOENT; + } + + return 0; +} +#endif + +#ifdef CONFIG_ENV_OFFSET_REDUND +void env_relocate_spec(void) +{ +#if !defined(ENV_IS_EMBEDDED) + int read1_fail = 0, read2_fail = 0; + env_t *tmp_env1, *tmp_env2; + + tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); + tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); + if (tmp_env1 == NULL || tmp_env2 == NULL) { + puts("Can't allocate buffers for environment\n"); + set_default_env("!malloc() failed"); + goto done; + } + + read1_fail = readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1); + read2_fail = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) 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) { + set_default_env("!bad env area"); + goto done; + } else if (!read1_fail && read2_fail) { + gd->env_valid = 1; + env_import((char *)tmp_env1, 1); + } else if (read1_fail && !read2_fail) { + gd->env_valid = 2; + env_import((char *)tmp_env2, 1); + } else { + env_import_redund((char *)tmp_env1, (char *)tmp_env2); + } + +done: + free(tmp_env1); + free(tmp_env2); + +#endif /* ! ENV_IS_EMBEDDED */ +} +#else /* ! CONFIG_ENV_OFFSET_REDUND */ +/* + * The legacy NAND code saved the environment in the first NAND + * device i.e., nand_dev_desc + 0. This is also the behaviour using + * the new NAND code. + */ +void env_relocate_spec(void) +{ +#if !defined(ENV_IS_EMBEDDED) + int ret; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + +#if defined(CONFIG_ENV_OFFSET_OOB) + struct mtd_info *mtd = get_nand_dev_by_index(0); + /* + * If unable to read environment offset from NAND OOB then fall through + * to the normal environment reading code below + */ + if (mtd && !get_nand_env_oob(mtd, &nand_env_oob_offset)) { + printf("Found Environment offset in OOB..\n"); + } else { + set_default_env("!no env offset in OOB"); + return; + } +#endif + + ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf); + if (ret) { + set_default_env("!readenv() failed"); + return; + } + + env_import(buf, 1); +#endif /* ! ENV_IS_EMBEDDED */ +} +#endif /* CONFIG_ENV_OFFSET_REDUND */ diff --git a/env/nowhere.c b/env/nowhere.c new file mode 100644 index 0000000000..bdc1ed5e67 --- /dev/null +++ b/env/nowhere.c @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +env_t *env_ptr; + +void env_relocate_spec(void) +{ +} + +/* + * Initialize Environment use + * + * We are still running from ROM, so data use is limited + */ +int env_init(void) +{ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 0; + + return 0; +} diff --git a/env/nvram.c b/env/nvram.c new file mode 100644 index 0000000000..524f07d5f8 --- /dev/null +++ b/env/nvram.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH + * + * It might not be possible in all cases to use 'memcpy()' to copy + * the environment to NVRAM, as the NVRAM might not be mapped into + * the memory space. (I.e. this is the case for the BAB750). In those + * cases it might be possible to access the NVRAM using a different + * method. For example, the RTC on the BAB750 is accessible in IO + * space using its address and data registers. To enable usage of + * NVRAM in those cases I invented the functions 'nvram_read()' and + * 'nvram_write()', which will be activated upon the configuration + * #define CONFIG_SYS_NVRAM_ACCESS_ROUTINE. Note, that those functions are + * strongly dependent on the used HW, and must be redefined for each + * board that wants to use them. + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE +extern void *nvram_read(void *dest, const long src, size_t count); +extern void nvram_write(long dest, const void *src, size_t count); +env_t *env_ptr; +#else +env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; +#endif + +char *env_name_spec = "NVRAM"; + +#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE +uchar env_get_char_spec(int index) +{ + uchar c; + + nvram_read(&c, CONFIG_ENV_ADDR + index, 1); + + return c; +} +#endif + +void env_relocate_spec(void) +{ + char buf[CONFIG_ENV_SIZE]; + +#if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) + nvram_read(buf, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); +#else + memcpy(buf, (void *)CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); +#endif + env_import(buf, 1); +} + +int saveenv(void) +{ + env_t env_new; + int rcode = 0; + + rcode = env_export(&env_new); + if (rcode) + return rcode; + +#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE + nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE); +#else + if (memcpy((char *)CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE) == NULL) + rcode = 1; +#endif + return rcode; +} + +/* + * Initialize Environment use + * + * We are still running from ROM, so data use is limited + */ +int env_init(void) +{ +#if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) + ulong crc; + uchar data[ENV_SIZE]; + + nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong)); + nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE); + + if (crc32(0, data, ENV_SIZE) == crc) { + gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long); +#else + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&env_ptr->data; +#endif + gd->env_valid = 1; + } else { + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 0; + } + + return 0; +} diff --git a/env/onenand.c b/env/onenand.c new file mode 100644 index 0000000000..cc3d670de8 --- /dev/null +++ b/env/onenand.c @@ -0,0 +1,116 @@ +/* + * (C) Copyright 2010 DENX Software Engineering + * Wolfgang Denk + * + * (C) Copyright 2005-2009 Samsung Electronics + * Kyungmin Park + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +char *env_name_spec = "OneNAND"; + +#define ONENAND_MAX_ENV_SIZE CONFIG_ENV_SIZE +#define ONENAND_ENV_SIZE(mtd) (ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE) + +DECLARE_GLOBAL_DATA_PTR; + +void env_relocate_spec(void) +{ + struct mtd_info *mtd = &onenand_mtd; +#ifdef CONFIG_ENV_ADDR_FLEX + struct onenand_chip *this = &onenand_chip; +#endif + int rc; + size_t retlen; +#ifdef ENV_IS_EMBEDDED + char *buf = (char *)&environment; +#else + loff_t env_addr = CONFIG_ENV_ADDR; + char onenand_env[ONENAND_MAX_ENV_SIZE]; + char *buf = (char *)&onenand_env[0]; +#endif /* ENV_IS_EMBEDDED */ + +#ifndef ENV_IS_EMBEDDED +# ifdef CONFIG_ENV_ADDR_FLEX + if (FLEXONENAND(this)) + env_addr = CONFIG_ENV_ADDR_FLEX; +# endif + /* Check OneNAND exist */ + if (mtd->writesize) + /* Ignore read fail */ + mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, + &retlen, (u_char *)buf); + else + mtd->writesize = MAX_ONENAND_PAGESIZE; +#endif /* !ENV_IS_EMBEDDED */ + + rc = env_import(buf, 1); + if (rc) + gd->env_valid = 1; +} + +int saveenv(void) +{ + env_t env_new; + int ret; + struct mtd_info *mtd = &onenand_mtd; +#ifdef CONFIG_ENV_ADDR_FLEX + struct onenand_chip *this = &onenand_chip; +#endif + loff_t env_addr = CONFIG_ENV_ADDR; + size_t retlen; + struct erase_info instr = { + .callback = NULL, + }; + + ret = env_export(&env_new); + if (ret) + return ret; + + instr.len = CONFIG_ENV_SIZE; +#ifdef CONFIG_ENV_ADDR_FLEX + if (FLEXONENAND(this)) { + env_addr = CONFIG_ENV_ADDR_FLEX; + instr.len = CONFIG_ENV_SIZE_FLEX; + instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ? + 1 : 0; + } +#endif + instr.addr = env_addr; + instr.mtd = mtd; + if (mtd_erase(mtd, &instr)) { + printf("OneNAND: erase failed at 0x%08llx\n", env_addr); + return 1; + } + + if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, + (u_char *)&env_new)) { + printf("OneNAND: write failed at 0x%llx\n", instr.addr); + return 2; + } + + return 0; +} + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} diff --git a/env/remote.c b/env/remote.c new file mode 100644 index 0000000000..eb977ee1fe --- /dev/null +++ b/env/remote.c @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2011-2012 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* #define DEBUG */ + +#include +#include +#include +#include + +char *env_name_spec = "Remote"; + +#ifdef ENV_IS_EMBEDDED +env_t *env_ptr = &environment; +#else /* ! ENV_IS_EMBEDDED */ +env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; +#endif /* ENV_IS_EMBEDDED */ + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_ENV_OFFSET) +#define CONFIG_ENV_OFFSET 0 +#endif + +int env_init(void) +{ + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); + gd->env_valid = 1; + return 0; + } + + gd->env_addr = (ulong)default_environment; + gd->env_valid = 0; + return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +int saveenv(void) +{ +#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE + printf("Can not support the 'saveenv' when boot from SRIO or PCIE!\n"); + return 1; +#else + return 0; +#endif +} +#endif /* CONFIG_CMD_SAVEENV */ + +void env_relocate_spec(void) +{ +#ifndef ENV_IS_EMBEDDED + env_import((char *)env_ptr, 1); +#endif +} diff --git a/env/sata.c b/env/sata.c new file mode 100644 index 0000000000..b0cee35a60 --- /dev/null +++ b/env/sata.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2010-2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* #define DEBUG */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_ENV_SIZE_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND) +#error ENV REDUND not supported +#endif + +#if !defined(CONFIG_ENV_OFFSET) || !defined(CONFIG_ENV_SIZE) +#error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined +#endif + +char *env_name_spec = "SATA"; + +DECLARE_GLOBAL_DATA_PTR; + +__weak int sata_get_env_dev(void) +{ + return CONFIG_SYS_SATA_ENV_DEV; +} + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +static inline int write_env(struct blk_desc *sata, unsigned long size, + unsigned long offset, void *buffer) +{ + uint blk_start, blk_cnt, n; + + blk_start = ALIGN(offset, sata->blksz) / sata->blksz; + blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; + + n = blk_dwrite(sata, blk_start, blk_cnt, buffer); + + return (n == blk_cnt) ? 0 : -1; +} + +int saveenv(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); + struct blk_desc *sata = NULL; + int env_sata, ret; + + if (sata_initialize()) + return 1; + + env_sata = sata_get_env_dev(); + + sata = sata_get_dev(env_sata); + if (sata == NULL) { + printf("Unknown SATA(%d) device for environment!\n", + env_sata); + return 1; + } + + ret = env_export(env_new); + if (ret) + return 1; + + printf("Writing to SATA(%d)...", env_sata); + if (write_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, &env_new)) { + puts("failed\n"); + return 1; + } + + puts("done\n"); + return 0; +} +#endif /* CONFIG_CMD_SAVEENV */ + +static inline int read_env(struct blk_desc *sata, unsigned long size, + unsigned long offset, void *buffer) +{ + uint blk_start, blk_cnt, n; + + blk_start = ALIGN(offset, sata->blksz) / sata->blksz; + blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; + + n = blk_dread(sata, blk_start, blk_cnt, buffer); + + return (n == blk_cnt) ? 0 : -1; +} + +void env_relocate_spec(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + struct blk_desc *sata = NULL; + int env_sata; + + if (sata_initialize()) + return; + + env_sata = sata_get_env_dev(); + + sata = sata_get_dev(env_sata); + if (sata == NULL) { + printf("Unknown SATA(%d) device for environment!\n", + env_sata); + return; + } + + if (read_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) + return set_default_env(NULL); + + env_import(buf, 1); +} diff --git a/env/sf.c b/env/sf.c new file mode 100644 index 0000000000..45f441a042 --- /dev/null +++ b/env/sf.c @@ -0,0 +1,344 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * (C) Copyright 2008 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_ENV_SPI_BUS +# define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS +#endif +#ifndef CONFIG_ENV_SPI_CS +# define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS +#endif +#ifndef CONFIG_ENV_SPI_MAX_HZ +# define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED +#endif +#ifndef CONFIG_ENV_SPI_MODE +# define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE +#endif + +#ifdef CONFIG_ENV_OFFSET_REDUND +static ulong env_offset = CONFIG_ENV_OFFSET; +static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND; + +#define ACTIVE_FLAG 1 +#define OBSOLETE_FLAG 0 +#endif /* CONFIG_ENV_OFFSET_REDUND */ + +DECLARE_GLOBAL_DATA_PTR; + +char *env_name_spec = "SPI Flash"; + +static struct spi_flash *env_flash; + +static int setup_flash_device(void) +{ +#ifdef CONFIG_DM_SPI_FLASH + struct udevice *new; + int ret; + + /* speed and mode will be read from DT */ + ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, + 0, 0, &new); + if (ret) { + set_default_env("!spi_flash_probe_bus_cs() failed"); + return 1; + } + + env_flash = dev_get_uclass_priv(new); +#else + + if (!env_flash) { + env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, + CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); + if (!env_flash) { + set_default_env("!spi_flash_probe() failed"); + return 1; + } + } +#endif + return 0; +} + +#if defined(CONFIG_ENV_OFFSET_REDUND) +int saveenv(void) +{ + env_t env_new; + char *saved_buffer = NULL, flag = OBSOLETE_FLAG; + u32 saved_size, saved_offset, sector; + int ret; + + ret = setup_flash_device(); + if (ret) + return ret; + + ret = env_export(&env_new); + if (ret) + return ret; + env_new.flags = ACTIVE_FLAG; + + if (gd->env_valid == 1) { + env_new_offset = CONFIG_ENV_OFFSET_REDUND; + env_offset = CONFIG_ENV_OFFSET; + } else { + env_new_offset = CONFIG_ENV_OFFSET; + env_offset = CONFIG_ENV_OFFSET_REDUND; + } + + /* Is the sector larger than the env (i.e. embedded) */ + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + saved_offset = env_new_offset + CONFIG_ENV_SIZE; + saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size); + if (!saved_buffer) { + ret = 1; + goto done; + } + ret = spi_flash_read(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + + puts("Erasing SPI flash..."); + ret = spi_flash_erase(env_flash, env_new_offset, + sector * CONFIG_ENV_SECT_SIZE); + if (ret) + goto done; + + puts("Writing to SPI flash..."); + + ret = spi_flash_write(env_flash, env_new_offset, + CONFIG_ENV_SIZE, &env_new); + if (ret) + goto done; + + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + ret = spi_flash_write(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags), + sizeof(env_new.flags), &flag); + if (ret) + goto done; + + puts("done\n"); + + gd->env_valid = gd->env_valid == 2 ? 1 : 2; + + printf("Valid environment: %d\n", (int)gd->env_valid); + + done: + if (saved_buffer) + free(saved_buffer); + + return ret; +} + +void env_relocate_spec(void) +{ + int ret; + int crc1_ok = 0, crc2_ok = 0; + env_t *tmp_env1 = NULL; + env_t *tmp_env2 = NULL; + env_t *ep = NULL; + + tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN, + CONFIG_ENV_SIZE); + tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN, + CONFIG_ENV_SIZE); + if (!tmp_env1 || !tmp_env2) { + set_default_env("!malloc() failed"); + goto out; + } + + ret = setup_flash_device(); + if (ret) + goto out; + + ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, + CONFIG_ENV_SIZE, tmp_env1); + if (ret) { + set_default_env("!spi_flash_read() failed"); + goto err_read; + } + + if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc) + crc1_ok = 1; + + ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND, + CONFIG_ENV_SIZE, tmp_env2); + if (!ret) { + if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc) + crc2_ok = 1; + } + + if (!crc1_ok && !crc2_ok) { + set_default_env("!bad CRC"); + goto err_read; + } else if (crc1_ok && !crc2_ok) { + gd->env_valid = 1; + } else if (!crc1_ok && crc2_ok) { + gd->env_valid = 2; + } else if (tmp_env1->flags == ACTIVE_FLAG && + tmp_env2->flags == OBSOLETE_FLAG) { + gd->env_valid = 1; + } else if (tmp_env1->flags == OBSOLETE_FLAG && + tmp_env2->flags == ACTIVE_FLAG) { + gd->env_valid = 2; + } else if (tmp_env1->flags == tmp_env2->flags) { + gd->env_valid = 1; + } else if (tmp_env1->flags == 0xFF) { + gd->env_valid = 1; + } else if (tmp_env2->flags == 0xFF) { + gd->env_valid = 2; + } else { + /* + * this differs from code in env_flash.c, but I think a sane + * default path is desirable. + */ + gd->env_valid = 1; + } + + if (gd->env_valid == 1) + ep = tmp_env1; + else + ep = tmp_env2; + + ret = env_import((char *)ep, 0); + if (!ret) { + error("Cannot import environment: errno = %d\n", errno); + set_default_env("!env_import failed"); + } + +err_read: + spi_flash_free(env_flash); + env_flash = NULL; +out: + free(tmp_env1); + free(tmp_env2); +} +#else +int saveenv(void) +{ + u32 saved_size, saved_offset, sector; + char *saved_buffer = NULL; + int ret = 1; + env_t env_new; + + ret = setup_flash_device(); + if (ret) + return ret; + + /* Is the sector larger than the env (i.e. embedded) */ + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; + saved_buffer = malloc(saved_size); + if (!saved_buffer) + goto done; + + ret = spi_flash_read(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + ret = env_export(&env_new); + if (ret) + goto done; + + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + + puts("Erasing SPI flash..."); + ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, + sector * CONFIG_ENV_SECT_SIZE); + if (ret) + goto done; + + puts("Writing to SPI flash..."); + ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, + CONFIG_ENV_SIZE, &env_new); + if (ret) + goto done; + + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + ret = spi_flash_write(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + ret = 0; + puts("done\n"); + + done: + if (saved_buffer) + free(saved_buffer); + + return ret; +} + +void env_relocate_spec(void) +{ + int ret; + char *buf = NULL; + + buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE); + if (!buf) { + set_default_env("!malloc() failed"); + return; + } + + ret = setup_flash_device(); + if (ret) + goto out; + + ret = spi_flash_read(env_flash, + CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf); + if (ret) { + set_default_env("!spi_flash_read() failed"); + goto err_read; + } + + ret = env_import(buf, 1); + if (ret) + gd->env_valid = 1; + +err_read: + spi_flash_free(env_flash); + env_flash = NULL; +out: + free(buf); +} +#endif + +int env_init(void) +{ + /* SPI flash isn't usable before relocation */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} diff --git a/env/ubi.c b/env/ubi.c new file mode 100644 index 0000000000..95b527ddca --- /dev/null +++ b/env/ubi.c @@ -0,0 +1,179 @@ +/* + * (c) Copyright 2012 by National Instruments, + * Joe Hershberger + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#undef crc32 + +char *env_name_spec = "UBI"; + +env_t *env_ptr; + +DECLARE_GLOBAL_DATA_PTR; + +int env_init(void) +{ + /* use default */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +int saveenv(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); + int ret; + + ret = env_export(env_new); + if (ret) + return ret; + + if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { + printf("\n** Cannot find mtd partition \"%s\"\n", + CONFIG_ENV_UBI_PART); + return 1; + } + + if (gd->env_valid == 1) { + puts("Writing to redundant UBI... "); + if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, + (void *)env_new, CONFIG_ENV_SIZE)) { + printf("\n** Unable to write env to %s:%s **\n", + CONFIG_ENV_UBI_PART, + CONFIG_ENV_UBI_VOLUME_REDUND); + return 1; + } + } else { + puts("Writing to UBI... "); + if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, + (void *)env_new, CONFIG_ENV_SIZE)) { + printf("\n** Unable to write env to %s:%s **\n", + CONFIG_ENV_UBI_PART, + CONFIG_ENV_UBI_VOLUME); + return 1; + } + } + + puts("done\n"); + + gd->env_valid = gd->env_valid == 2 ? 1 : 2; + + return 0; +} +#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +int saveenv(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); + int ret; + + ret = env_export(env_new); + if (ret) + return ret; + + if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { + printf("\n** Cannot find mtd partition \"%s\"\n", + CONFIG_ENV_UBI_PART); + return 1; + } + + if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, + CONFIG_ENV_SIZE)) { + printf("\n** Unable to write env to %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); + return 1; + } + + puts("done\n"); + return 0; +} +#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +#endif /* CONFIG_CMD_SAVEENV */ + +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +void env_relocate_spec(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE); + ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE); + env_t *tmp_env1, *tmp_env2; + + /* + * In case we have restarted u-boot there is a chance that buffer + * contains old environment (from the previous boot). + * If UBI volume is zero size, ubi_volume_read() doesn't modify the + * buffer. + * We need to clear buffer manually here, so the invalid CRC will + * cause setting default environment as expected. + */ + memset(env1_buf, 0x0, CONFIG_ENV_SIZE); + memset(env2_buf, 0x0, CONFIG_ENV_SIZE); + + tmp_env1 = (env_t *)env1_buf; + tmp_env2 = (env_t *)env2_buf; + + if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { + printf("\n** Cannot find mtd partition \"%s\"\n", + CONFIG_ENV_UBI_PART); + set_default_env(NULL); + return; + } + + if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1, + CONFIG_ENV_SIZE)) { + printf("\n** Unable to read env from %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); + } + + if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)tmp_env2, + CONFIG_ENV_SIZE)) { + printf("\n** Unable to read redundant env from %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); + } + + env_import_redund((char *)tmp_env1, (char *)tmp_env2); +} +#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +void env_relocate_spec(void) +{ + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + + /* + * In case we have restarted u-boot there is a chance that buffer + * contains old environment (from the previous boot). + * If UBI volume is zero size, ubi_volume_read() doesn't modify the + * buffer. + * We need to clear buffer manually here, so the invalid CRC will + * cause setting default environment as expected. + */ + memset(buf, 0x0, CONFIG_ENV_SIZE); + + if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { + printf("\n** Cannot find mtd partition \"%s\"\n", + CONFIG_ENV_UBI_PART); + set_default_env(NULL); + return; + } + + if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, CONFIG_ENV_SIZE)) { + printf("\n** Unable to read env from %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); + set_default_env(NULL); + return; + } + + env_import(buf, 1); +} +#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ diff --git a/include/configs/M5208EVBE.h b/include/configs/M5208EVBE.h index 0fbf457cdc..c56cbd9f54 100644 --- a/include/configs/M5208EVBE.h +++ b/include/configs/M5208EVBE.h @@ -161,8 +161,8 @@ #define CONFIG_ENV_SECT_SIZE 0x2000 #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text*); /* Cache Configuration */ #define CONFIG_SYS_CACHELINE_SIZE 16 diff --git a/include/configs/M5235EVB.h b/include/configs/M5235EVB.h index dac2a32383..57bc57817d 100644 --- a/include/configs/M5235EVB.h +++ b/include/configs/M5235EVB.h @@ -176,7 +176,7 @@ #define LDS_BOARD_TEXT \ . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text); + env/embedded.o(.text); #ifdef NORFLASH_PS32BIT # define CONFIG_ENV_OFFSET (0x8000) diff --git a/include/configs/M5249EVB.h b/include/configs/M5249EVB.h index f6027e231f..df0733e6c2 100644 --- a/include/configs/M5249EVB.h +++ b/include/configs/M5249EVB.h @@ -85,8 +85,8 @@ #define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_GBL_DATA_OFFSET #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text); #define CONFIG_ENV_OFFSET 0x4000 /* Address of Environment Sector*/ #define CONFIG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ diff --git a/include/configs/M5253DEMO.h b/include/configs/M5253DEMO.h index 2bdfe80ef5..da8333ac6f 100644 --- a/include/configs/M5253DEMO.h +++ b/include/configs/M5253DEMO.h @@ -29,8 +29,8 @@ #endif #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text*); /* * Command line configuration. diff --git a/include/configs/M5253EVBE.h b/include/configs/M5253EVBE.h index 0722ea19e3..5a2f0e204f 100644 --- a/include/configs/M5253EVBE.h +++ b/include/configs/M5253EVBE.h @@ -31,7 +31,7 @@ #define LDS_BOARD_TEXT \ . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text) + env/embedded.o(.text) /* * BOOTP options diff --git a/include/configs/M5272C3.h b/include/configs/M5272C3.h index e6bd7f3609..f5693d8178 100644 --- a/include/configs/M5272C3.h +++ b/include/configs/M5272C3.h @@ -39,8 +39,8 @@ #endif #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text); /* * BOOTP options diff --git a/include/configs/M5275EVB.h b/include/configs/M5275EVB.h index 6bcd6b6f2e..339a03c7b1 100644 --- a/include/configs/M5275EVB.h +++ b/include/configs/M5275EVB.h @@ -40,8 +40,8 @@ #endif #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text); /* * BOOTP options diff --git a/include/configs/M5282EVB.h b/include/configs/M5282EVB.h index cc703aac19..3f2d9a9bac 100644 --- a/include/configs/M5282EVB.h +++ b/include/configs/M5282EVB.h @@ -32,7 +32,7 @@ #define LDS_BOARD_TEXT \ . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + env/embedded.o(.text*); /* * BOOTP options diff --git a/include/configs/M53017EVB.h b/include/configs/M53017EVB.h index f7812468af..45e4be2f01 100644 --- a/include/configs/M53017EVB.h +++ b/include/configs/M53017EVB.h @@ -183,7 +183,7 @@ #define LDS_BOARD_TEXT \ . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*) + env/embedded.o(.text*) /*----------------------------------------------------------------------- * Cache Configuration diff --git a/include/configs/M5329EVB.h b/include/configs/M5329EVB.h index f7b284fda8..1b5cae2dfe 100644 --- a/include/configs/M5329EVB.h +++ b/include/configs/M5329EVB.h @@ -185,8 +185,8 @@ #define CONFIG_ENV_SECT_SIZE 0x2000 #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text*); /*----------------------------------------------------------------------- * Cache Configuration diff --git a/include/configs/M5373EVB.h b/include/configs/M5373EVB.h index b85e0f088f..a0e582e2b8 100644 --- a/include/configs/M5373EVB.h +++ b/include/configs/M5373EVB.h @@ -185,8 +185,8 @@ #define CONFIG_ENV_SECT_SIZE 0x2000 #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text*); /*----------------------------------------------------------------------- * Cache Configuration diff --git a/include/configs/amcore.h b/include/configs/amcore.h index 0a40746112..5f8b6c5518 100644 --- a/include/configs/amcore.h +++ b/include/configs/amcore.h @@ -93,8 +93,8 @@ #define CONFIG_ENV_SECT_SIZE 0x1000 #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text*); /* memory map space for linux boot data */ #define CONFIG_SYS_BOOTMAPSZ (8 << 20) diff --git a/include/configs/astro_mcf5373l.h b/include/configs/astro_mcf5373l.h index af03b303c4..563732a5c4 100644 --- a/include/configs/astro_mcf5373l.h +++ b/include/configs/astro_mcf5373l.h @@ -296,7 +296,7 @@ #define LDS_BOARD_TEXT \ . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text*) + env/embedded.o(.text*) #if ENABLE_JFFS /* JFFS Partition offset set */ diff --git a/include/configs/cobra5272.h b/include/configs/cobra5272.h index c44c6cae58..9adf7a35f0 100644 --- a/include/configs/cobra5272.h +++ b/include/configs/cobra5272.h @@ -102,8 +102,8 @@ #endif #define LDS_BOARD_TEXT \ - . = DEFINED(env_offset) ? env_offset : .; \ - common/env_embedded.o (.text); + . = DEFINED(env_offset) ? env_offset : .; \ + env/embedded.o(.text); /* * BOOTP options diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 167b2d9d29..3ba00077d3 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -69,10 +69,10 @@ libs-y += common/init/ # Special handling for a few options which support SPL/TPL ifeq ($(CONFIG_TPL_BUILD),y) -libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/ +libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/ libs-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/ else -libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ +libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/ libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/ endif diff --git a/tools/Makefile b/tools/Makefile index 0743677dc8..a1790ebd59 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -37,7 +37,7 @@ hostprogs-$(CONFIG_VIDEO_LOGO) += bmp_logo HOSTCFLAGS_bmp_logo.o := -pedantic hostprogs-$(CONFIG_BUILD_ENVCRC) += envcrc -envcrc-objs := envcrc.o lib/crc32.o common/env_embedded.o lib/sha1.o +envcrc-objs := envcrc.o lib/crc32.o env/embedded.o lib/sha1.o hostprogs-$(CONFIG_CMD_NET) += gen_eth_addr HOSTCFLAGS_gen_eth_addr.o := -pedantic @@ -225,7 +225,7 @@ HOSTCFLAGS_sha256.o := -pedantic quiet_cmd_wrap = WRAP $@ cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@ -$(obj)/lib/%.c $(obj)/common/%.c: +$(obj)/lib/%.c $(obj)/common/%.c $(obj)/env/%.c: $(call cmd,wrap) clean-dirs := lib common