diff --git a/README b/README
index c76fc9131276..605773d4ecd3 100644
--- a/README
+++ b/README
@@ -67,6 +67,26 @@ Notes:
 	
 	in the configuration (e.g. conf/local.conf).
 
+U-Boot Environment:
+------------------
+	In order to configure U-Boot to be able to store its environment into the
+	device from which it was booted, for any device supported in this BSP,
+	simply add the following to MACHINE_FEATURES:
+
+		rk-u-boot-env
+
+	If enabled, to additionally have the U-Boot environment generated and
+	stored in the image, also enable the following variable (default: off):
+
+		RK_IMAGE_INCLUDES_UBOOT_ENV
+
+	The script:
+
+		scripts/dump-uboot-env-from-yocto-image.sh
+
+	can be used on a rockchip wic image to see the contents of the U-Boot
+	environment partition at build time.
+
 Maintenance:
 -----------
 	Please send pull requests, patches, comments, or questions to the
diff --git a/conf/machine/include/rockchip-wic.inc b/conf/machine/include/rockchip-wic.inc
index 147a36685d7d..92749b514499 100644
--- a/conf/machine/include/rockchip-wic.inc
+++ b/conf/machine/include/rockchip-wic.inc
@@ -2,6 +2,11 @@
 
 require conf/machine/include/rockchip-extlinux.inc
 
+# 'rk-u-boot-env' indicates the user wants to be able to save their U-Boot
+# environment back to the drive from which the device was booted
+MACHINEOVERRIDES .= "${@bb.utils.contains('MACHINE_FEATURES', 'rk-u-boot-env', ':rk-u-boot-env', '', d)}"
+IMAGE_INSTALL:append:rk-u-boot-env = " u-boot-fw-utils u-boot-env"
+
 SPL_BINARY ?= "idbloader.img"
 
 IMAGE_FSTYPES += "wic wic.bmap"
@@ -11,7 +16,13 @@ WKS_FILE_DEPENDS ?= " \
 	virtual/bootloader \
 	"
 
+RK_IMAGE_INCLUDES_UBOOT_ENV ?= "no"
+RK_UBOOT_ENV = " "
+RK_UBOOT_ENV:rk-u-boot-env = "${@ '--source rawcopy --sourceparams=file=u-boot.env' if \
+	bb.utils.to_boolean(d.getVar('RK_IMAGE_INCLUDES_UBOOT_ENV'), False) else ' '}"
+
 WICVARS:append = " \
+	RK_UBOOT_ENV \
 	SPL_BINARY \
 	UBOOT_SUFFIX \
 	"
diff --git a/recipes-bsp/u-boot/files/rk-u-boot-env/rockchip-enable-environment-mmc.cfg b/recipes-bsp/u-boot/files/rk-u-boot-env/rockchip-enable-environment-mmc.cfg
new file mode 100644
index 000000000000..778772d27767
--- /dev/null
+++ b/recipes-bsp/u-boot/files/rk-u-boot-env/rockchip-enable-environment-mmc.cfg
@@ -0,0 +1,6 @@
+CONFIG_ENV_SIZE=0x8000
+CONFIG_ENV_OFFSET=0x3f8000
+# CONFIG_ENV_IS_NOWHERE is not set
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_DM_SEQ_ALIAS=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
diff --git a/recipes-bsp/u-boot/u-boot_%.bbappend b/recipes-bsp/u-boot/u-boot_%.bbappend
index a83179a9f007..32cb11939f77 100644
--- a/recipes-bsp/u-boot/u-boot_%.bbappend
+++ b/recipes-bsp/u-boot/u-boot_%.bbappend
@@ -1,7 +1,13 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
+
+SRC_URI:append:rk-u-boot-env = " file://rockchip-enable-environment-mmc.cfg"
+SRCREV:rk-u-boot-env = "cdfcc37428e06f4730ab9a17cc084eeb7676ea1a"
+
 # various machines require the pyelftools library for parsing dtb files
 DEPENDS:append = " python3-pyelftools-native"
 DEPENDS:append:rk3308 = " u-boot-tools-native"
 DEPENDS:append:rock-pi-4 = " gnutls-native"
+DEPENDS:append:rk-u-boot-env = " u-boot-mkenvimage-native"
 
 EXTRA_OEMAKE:append:px30 = " BL31=${DEPLOY_DIR_IMAGE}/bl31-px30.elf"
 EXTRA_OEMAKE:append:rk3308 = " \
@@ -34,3 +40,37 @@ do_compile:append:rock2-square () {
 		cp ${B}/spl/${SPL_BINARY} ${B}
 	fi
 }
+
+rk_generate_env() {
+	if [ ! -f "${B}/.config" ]; then
+		echo "U-Boot .config not found, can't determine environment size"
+		return 1
+	fi
+	cat ${B}/.config | grep "^CONFIG_ENV_SIZE=" > /dev/null
+	if [ $? -ne 0 ]; then
+		echo "can not find CONFIG_ENV_SIZE value in U-Boot .config"
+		return 1
+	fi
+
+	UBOOT_ENV_SIZE="$(cat ${B}/.config | grep "^CONFIG_ENV_SIZE=" | cut -d'=' -f2)"
+
+	# linux user-space U-Boot env config file
+	echo "/dev/disk/by-partlabel/uboot_env 0x0000 ${UBOOT_ENV_SIZE}" > ${WORKDIR}/fw_env.config
+
+	# convert text-based environment to binary suitable for image
+	if [ "${@bb.utils.to_boolean(d.getVar('RK_IMAGE_INCLUDES_UBOOT_ENV'), False)}" = "True" ]; then
+		if [ ! -f ${B}/u-boot-initial-env ]; then
+			echo "initial, text-formatted U-Boot environment file \"${B}/u-boot-initial-env\" not found"
+			return 1
+		fi
+		mkenvimage -s ${UBOOT_ENV_SIZE} ${B}/u-boot-initial-env -o ${WORKDIR}/u-boot.env
+	fi
+}
+do_compile[postfuncs] += "${@bb.utils.contains('MACHINE_FEATURES', 'rk-u-boot-env', 'rk_generate_env', '', d)}"
+
+do_deploy:append:rk-u-boot-env() {
+	if [ -f ${WORKDIR}/u-boot.env -a "${@bb.utils.to_boolean(d.getVar('RK_IMAGE_INCLUDES_UBOOT_ENV'),False)}" = "True" ]; then
+		install -d ${DEPLOYDIR}
+		install -m 0644 ${WORKDIR}/u-boot.env ${DEPLOYDIR}
+	fi
+}
diff --git a/scripts/dump-uboot-env-from-yocto-image.sh b/scripts/dump-uboot-env-from-yocto-image.sh
new file mode 100755
index 000000000000..05b7048f1734
--- /dev/null
+++ b/scripts/dump-uboot-env-from-yocto-image.sh
@@ -0,0 +1,29 @@
+#/bin/bash
+# SPDX-License-Identifier: OSL-3.0
+#
+# a program that can take a wic file and dump out the contents
+# of the U-Boot environment in canonical hex+ascii format
+# (assuming the "rockchip" layout specified in this layer's wic file)
+
+# check for programs
+check_pgm() {
+	$1 --help > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "required program \"$1\" not found"
+		exit 1
+	fi
+}
+check_pgm dd
+check_pgm hexdump
+
+if [ $# -ne 1 ]; then
+	echo "required param missing: yocto wic image"
+	exit 1
+fi
+if [ ! -f "$1" ]; then
+	echo "specified file \"$1\" not found"
+	exit 1
+fi
+
+SKIP=$(( 8128 * 512 ))
+dd if="$1" ibs=1 skip=$SKIP count=32k 2> /dev/null | hexdump -C
diff --git a/wic/rockchip.wks b/wic/rockchip.wks
index 9ba3352b51bb..bc65f73b0cf3 100644
--- a/wic/rockchip.wks
+++ b/wic/rockchip.wks
@@ -22,7 +22,7 @@ part loader1   --offset 64s    --fixed-size 3552K --fstype=none --part-name load
 part v_storage --offset 7168s  --fixed-size 256K  --fstype=none --part-name v_storage
 part reserved  --offset 7680s  --fixed-size 192K  --fstype=none --part-name reserved
 part reserved1 --offset 8064s  --fixed-size 32K   --fstype=none --part-name reserved1
-part uboot_env --offset 8128s  --fixed-size 32K   --fstype=none --part-name uboot_env
+part uboot_env --offset 8128s  --fixed-size 32K   --fstype=none --part-name uboot_env ${RK_UBOOT_ENV}
 part reserved2 --offset 8192s  --fixed-size 4096K --fstype=none --part-name reserved2
 part loader2   --offset 16384s --fixed-size 4096K --fstype=none --part-name loader2   --source rawcopy --sourceparams="file=u-boot.${UBOOT_SUFFIX}"
 part atf       --offset 24576s --fixed-size 4096K --fstype=none --part-name atf
