[PATCH v6 4/7] env: Allow U-Boot scripts to be placed in a .env file
Simon Glass
sjg at chromium.org
Thu Oct 14 20:22:54 CEST 2021
At present U-Boot environment variables, and thus scripts, are defined
by CONFIG_EXTRA_ENV_SETTINGS. It is painful to add large amounts of text
to this file and dealing with quoting and newlines is harder than it
should be. It would be better if we could just type the script into a
text file and have it included by U-Boot.
Add a feature that brings in a .env file associated with the board
config, if present. To use it, create a file in a board/<vendor>/env
directory called <board>.env (or common.env if you want the same
environment for all boards).
The environment variables should be of the form "var=value". Values can
extend to multiple lines. See the README under 'Environment Variables:'
for more information and an example.
In many cases environment variables need access to the U-Boot CONFIG
variables to select different options. Enable this so that the environment
scripts can be as useful as the ones currently in the board config files.
This uses the C preprocessor, means that comments can be included in the
environment using /* ... */
Also support += to allow variables to be appended to. This is needed when
using the preprocessor.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v6:
- Combine the two env2string.awk patches into one
Changes in v5:
- Explain how to include the common.env file
- Explain why variables starting with _ , and / are not supported
- Expand the definition of how to declare an environment variable
- Explain what happens to empty variables
- Update maintainer
- Move use of += to this patch
- Explain that environment variables may not end in +
Changes in v4:
- Move this from being part of configuring U-Boot to part of building it
- Don't put the environment in autoconf.mk as it is not needed
- Add documentation in rST format instead of README
- Drop mention of import/export
- Update awk script to ignore blank lines, as generated by clang
- Add documentation in rST format instead of README
Changes in v3:
- Adjust Makefile to generate the .inc and .h files in separate fules
- Add more detail in the README about the format of .env files
- Improve the comment about " in the awk script
- Correctly terminate environment files with \n
- Define __UBOOT_CONFIG__ when collecting environment files
Changes in v2:
- Move .env file from include/configs to board/
- Use awk script to process environment since it is much easier on the brain
- Add information and updated example script to README
- Add dependency rule so that the environment is rebuilt when it changes
- Add separate patch to enable C preprocessor for environment files
- Enable var+=value form to simplify composing variables in multiple steps
MAINTAINERS | 7 +++++
Makefile | 39 ++++++++++++++++++++++++++-
config.mk | 2 ++
doc/usage/environment.rst | 54 +++++++++++++++++++++++++++++++++++++
env/embedded.c | 1 +
include/env_default.h | 8 ++++++
scripts/env2string.awk | 56 +++++++++++++++++++++++++++++++++++++++
7 files changed, 166 insertions(+), 1 deletion(-)
create mode 100644 scripts/env2string.awk
diff --git a/MAINTAINERS b/MAINTAINERS
index 71f468c00a8..36846528368 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -738,6 +738,13 @@ F: test/env/
F: tools/env*
F: tools/mkenvimage.c
+ENVIRONMENT AS TEXT
+M: Simon Glass <sjg at chromium.org>
+R: Wolfgang Denk <wd at denx.de>
+S: Maintained
+F: doc/usage/environment.rst
+F: scripts/env2string.awk
+
FPGA
M: Michal Simek <michal.simek at xilinx.com>
S: Maintained
diff --git a/Makefile b/Makefile
index f911f703443..635221025da 100644
--- a/Makefile
+++ b/Makefile
@@ -513,6 +513,7 @@ version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h
defaultenv_h := include/generated/defaultenv_autogenerated.h
dt_h := include/generated/dt.h
+env_h := include/generated/environment.h
no-dot-config-targets := clean clobber mrproper distclean \
help %docs check% coccicheck \
@@ -1785,6 +1786,42 @@ quiet_cmd_sym ?= SYM $@
u-boot.sym: u-boot FORCE
$(call if_changed,sym)
+# We expect '<board>.env' but failing that will use 'common.env'
+ENV_DIR := $(if $(VENDOR),$(VENDOR)/env,$(BOARD)/env)
+ENV_FILE_BOARD := $(srctree)/board/${ENV_DIR}/$(BOARD).env
+ENV_FILE_COMMON := $(srctree)/board/${ENV_DIR}/common.env
+ENV_FILE := $(if $(wildcard $(ENV_FILE_BOARD)),$(ENV_FILE_BOARD),$(ENV_FILE_COMMON))
+
+# Run the environment text file through the preprocessor
+quiet_cmd_gen_envp = ENVP $@
+ cmd_gen_envp = \
+ if [ -f "$(ENV_FILE)" ]; then \
+ $(CPP) -P $(CFLAGS) -x assembler-with-cpp -D__ASSEMBLY__ \
+ -D__UBOOT_CONFIG__ \
+ -I . -I include \
+ -I $(srctree)/include -include include/config.h \
+ -I$(srctree)/arch/$(ARCH)/include \
+ $(ENV_FILE) -o $@; \
+ else \
+ echo -n >$@ ; \
+ fi
+
+# Regenerate the environment if it changes
+# We use 'wildcard' since the file is not required to exist (at present), in
+# which case we don't want this dependency, but instead should create an empty
+# file
+include/generated/environment.in: \
+ $(if $(wildcard $(ENV_FILE)),$(wildcard $(ENV_FILE)),FORCE)
+ $(call cmd,gen_envp)
+
+quiet_cmd_gen_envt = ENVT $@
+ cmd_gen_envt = \
+ echo -n "\#define CONFIG_EXTRA_ENV_TEXT " >$@; \
+ awk -f $(srctree)/scripts/env2string.awk $< >>$@
+
+$(env_h): include/generated/environment.in
+ $(call cmd,gen_envt)
+
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ;
@@ -1840,7 +1877,7 @@ endif
# prepare2 creates a makefile if using a separate output directory
prepare2: prepare3 outputmakefile cfg
-prepare1: prepare2 $(version_h) $(timestamp_h) $(dt_h) \
+prepare1: prepare2 $(version_h) $(timestamp_h) $(dt_h) $(env_h) \
include/config/auto.conf
ifeq ($(wildcard $(LDSCRIPT)),)
@echo >&2 " Could not find linker script."
diff --git a/config.mk b/config.mk
index 7bb1fd4ed1b..2595aed218b 100644
--- a/config.mk
+++ b/config.mk
@@ -50,8 +50,10 @@ endif
ifneq ($(BOARD),)
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
+ENVDIR=${vendor}/env
else
BOARDDIR = $(BOARD)
+ENVDIR=${board}/env
endif
endif
ifdef BOARD
diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst
index be785a8f717..76915484b85 100644
--- a/doc/usage/environment.rst
+++ b/doc/usage/environment.rst
@@ -16,6 +16,60 @@ environment is erased by accident, a default environment is provided.
Some configuration options can be set using Environment Variables.
+The default environment is created in `include/env_default.h`, and can be
+augmented by various `CONFIG` defines. See that file for details. In
+particular you can define `CONFIG_EXTRA_ENV_SETTINGS` in your board file
+to add environment variables (see `CONFIG_EXTRA_ENV_SETTINGS` for details).
+
+It is also possible to create an environment file with the name
+`board/<vendor>/env/<board>.env` for your board. If that file is not present
+then U-Boot will look for `board/<vendor>/env/common.env` so that you can
+have a common environment for all vendor boards.
+
+To include the common.env file in your board.env file, use `#include`.
+
+This is a plain text file where you can type your environment variables in
+the form `var=value`. Blank lines and multi-line variables are supported.
+The conversion script looks for a line that starts in column 1 with a string
+and has an equals sign immediately afterwards. Spaces before the = are not
+permitted. It is a good idea to indent your scripts so that only the 'var='
+appears at the start of a line.
+
+To add additional text to a variable you can use var+=value. This text is
+merged into the variable during the make process and made available as a
+single value to U-Boot. To support this, environment variables may not end
+in `+`.
+
+This file can include C-style comments. Blank lines and multi-line
+variables are supported, and you can use normal C preprocessor directives
+and CONFIG defines from your board config also.
+
+For example, for snapper9260 you would create a text file called
+`board/bluewater/env/snapper9260.env` containing the environment text.
+
+Example::
+
+ stdout=serial
+ #ifdef CONFIG_LCD
+ stdout+=,lcd
+ #endif
+ bootcmd=
+ /* U-Boot script for booting */
+
+ if [ -z ${tftpserverip} ]; then
+ echo "Use 'setenv tftpserverip a.b.c.d' to set IP address."
+ fi
+
+ usb start; setenv autoload n; bootp;
+ tftpboot ${tftpserverip}:
+ bootm
+ failed=
+ /* Print a message when boot fails */
+ echo CONFIG_SYS_BOARD boot failed - please check your image
+ echo Load address is CONFIG_SYS_LOAD_ADDR
+
+Some configuration options can be set using Environment Variables.
+
List of environment variables (most likely not complete):
baudrate
diff --git a/env/embedded.c b/env/embedded.c
index 208553e6af1..9f26e6cad9c 100644
--- a/env/embedded.c
+++ b/env/embedded.c
@@ -66,6 +66,7 @@
#endif
#define DEFAULT_ENV_INSTANCE_EMBEDDED
+#include <config.h>
#include <env_default.h>
#ifdef CONFIG_ENV_ADDR_REDUND
diff --git a/include/env_default.h b/include/env_default.h
index 66e203eb6e4..48190a7c1af 100644
--- a/include/env_default.h
+++ b/include/env_default.h
@@ -10,6 +10,10 @@
#include <env_callback.h>
#include <linux/stringify.h>
+#ifndef USE_HOSTCC
+#include <generated/environment.h>
+#endif
+
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
env_t embedded_environment __UBOOT_ENV_SECTION__(environment) = {
ENV_CRC, /* CRC Sum */
@@ -112,6 +116,10 @@ const uchar default_environment[] = {
#endif
#ifdef CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
+#endif
+#ifdef CONFIG_EXTRA_ENV_TEXT
+ /* This is created in the Makefile */
+ CONFIG_EXTRA_ENV_TEXT
#endif
"\0"
#else /* CONFIG_USE_DEFAULT_ENV_FILE */
diff --git a/scripts/env2string.awk b/scripts/env2string.awk
new file mode 100644
index 00000000000..6de3e3dd87e
--- /dev/null
+++ b/scripts/env2string.awk
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Awk script to parse a text file containing an environment and convert it
+# to a C string which can be compiled into U-Boot.
+
+# We output a double quote before starting, and again when we finish so that
+# all output is quoted.
+BEGIN {
+ # env holds the env variable we are currently processing
+ env = "";
+ ORS = ""
+ print "\""
+}
+
+# Skip empty lines, as these are generated by the clang preprocessor
+NF {
+ # Quote quotes
+ gsub("\"", "\\\"")
+
+ # Is this the start of a new environment variable?
+ if (match($0, "^([^ =][^ =]*)=(.*)", arr)) {
+ if (length(env) != 0) {
+ # Record the value of the variable now completed
+ vars[var] = env
+ }
+ var = arr[1]
+ env = arr[2]
+
+ # Deal with +=
+ if (match(var, "(.*)[+]$", var_arr)) {
+ var = var_arr[1]
+ env = vars[var] env
+ }
+ } else {
+ # Change newline to \n
+ env = env "\\n" $0;
+ }
+}
+
+END {
+ # Record the value of the variable now completed. If the variable is
+ # empty it is not set.
+ if (length(env) != 0) {
+ vars[var] = env
+ }
+
+ # Print out all the variables
+ for (var in vars) {
+ print var "=" vars[var] "\\0";
+ }
+ print "\"\n"
+}
--
2.33.0.1079.g6e70778dc9-goog
More information about the U-Boot
mailing list