summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-09-02 21:51:21 -0400
committerTom Rini <trini@konsulko.com>2022-09-02 21:53:36 -0400
commit98b3a998b31a83d8167f888b11ddd5cce8194f35 (patch)
tree91e5c815982e9f1823f86f61bc49e28d948d1b4c
parent2d7069126d11f8708ee38c68b1c6cafae5e50dae (diff)
parent21ddac140e3040b2693c1a5558a84c19a879c04f (diff)
Merge branch '2022-09-02-assorted-improvements' into next
- DM RTC improvements that should help in CI, allow disabling LTO from the make line, add extension (cape, etc) support to distro bootcmd, add a pause command and re-enable ARM v4T support.
-rw-r--r--.azure-pipelines.yml4
-rw-r--r--.gitlab-ci.yml7
-rw-r--r--Makefile17
-rw-r--r--arch/arm/config.mk4
-rw-r--r--arch/arm/include/asm/assembler.h10
-rw-r--r--arch/arm/include/asm/global_data.h2
-rw-r--r--arch/arm/lib/lib1funcs.S8
-rw-r--r--arch/arm/lib/memcpy.S6
-rw-r--r--arch/arm/lib/relocate.S10
-rw-r--r--arch/arm/lib/setjmp.S4
-rw-r--r--arch/sandbox/cpu/spl.c2
-rw-r--r--cmd/Kconfig6
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/pause.c32
-rw-r--r--configs/sandbox64_defconfig1
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/build/gcc.rst17
-rw-r--r--doc/develop/tests_sandbox.rst24
-rw-r--r--doc/usage/cmd/pause.rst53
-rw-r--r--doc/usage/index.rst1
-rw-r--r--include/config_distro_bootcmd.h32
-rw-r--r--include/test/test.h2
-rw-r--r--include/test/ut.h3
-rw-r--r--scripts/Makefile.spl2
-rw-r--r--test/cmd/Makefile3
-rw-r--r--test/cmd/test_pause.c45
-rw-r--r--test/cmd_ut.c12
-rw-r--r--test/dm/rtc.c53
-rw-r--r--test/dm/test-dm.c13
-rw-r--r--test/test-main.c14
30 files changed, 336 insertions, 53 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 0fa92479b4c..d78a170d0c5 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -243,6 +243,9 @@ stages:
sandbox_clang:
TEST_PY_BD: "sandbox"
OVERRIDE: "-O clang-13"
+ sandbox_nolto:
+ TEST_PY_BD: "sandbox"
+ BUILD_ENV: "NO_LTO=1"
sandbox_spl:
TEST_PY_BD: "sandbox_spl"
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
@@ -354,6 +357,7 @@ stages:
export TEST_PY_ID="${TEST_PY_ID}"
export TEST_PY_TEST_SPEC="${TEST_PY_TEST_SPEC}"
export OVERRIDE="${OVERRIDE}"
+ export BUILD_ENV="${BUILD_ENV}"
EOF
cat << "EOF" >> test.sh
# the below corresponds to .gitlab-ci.yml "before_script"
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5592862f74b..8e94bf8d4e8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,6 +33,7 @@ stages:
script:
# If we've been asked to use clang only do one configuration.
- export UBOOT_TRAVIS_BUILD_DIR=/tmp/${TEST_PY_BD}
+ - echo BUILD_ENV ${BUILD_ENV}
- tools/buildman/buildman -o ${UBOOT_TRAVIS_BUILD_DIR} -w -E -W -e
--board ${TEST_PY_BD} ${OVERRIDE}
- cp ~/grub_x86.efi $UBOOT_TRAVIS_BUILD_DIR/
@@ -254,6 +255,12 @@ sandbox with clang test.py:
OVERRIDE: "-O clang-13"
<<: *buildman_and_testpy_dfn
+sandbox without LTO test.py:
+ variables:
+ TEST_PY_BD: "sandbox"
+ BUILD_ENV: "NO_LTO=1"
+ <<: *buildman_and_testpy_dfn
+
sandbox_spl test.py:
variables:
TEST_PY_BD: "sandbox_spl"
diff --git a/Makefile b/Makefile
index 541e942ed51..27375f033f4 100644
--- a/Makefile
+++ b/Makefile
@@ -643,6 +643,13 @@ export CFLAGS_EFI # Compiler flags to add when building EFI app
export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app
export EFI_TARGET # binutils target if EFI is natively supported
+export LTO_ENABLE
+
+# This is y if LTO is enabled for this build. See NO_LTO=1 to disable LTO
+ifeq ($(NO_LTO),)
+LTO_ENABLE=$(if $(CONFIG_LTO),y)
+endif
+
# If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use
# that (or fail if absent). Otherwise, search for a linker script in a
# standard location.
@@ -708,16 +715,16 @@ endif
LTO_CFLAGS :=
LTO_FINAL_LDFLAGS :=
export LTO_CFLAGS LTO_FINAL_LDFLAGS
-ifdef CONFIG_LTO
+ifeq ($(LTO_ENABLE),y)
ifeq ($(cc-name),clang)
- LTO_CFLAGS += -flto
+ LTO_CFLAGS += -DLTO_ENABLE -flto
LTO_FINAL_LDFLAGS += -flto
AR = $(shell $(CC) -print-prog-name=llvm-ar)
NM = $(shell $(CC) -print-prog-name=llvm-nm)
else
NPROC := $(shell nproc 2>/dev/null || echo 1)
- LTO_CFLAGS += -flto=$(NPROC)
+ LTO_CFLAGS += -DLTO_ENABLE -flto=$(NPROC)
LTO_FINAL_LDFLAGS += -fuse-linker-plugin -flto=$(NPROC)
# use plugin aware tools
@@ -1765,7 +1772,7 @@ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
# Generate linker list symbols references to force compiler to not optimize
# them away when compiling with LTO
-ifdef CONFIG_LTO
+ifeq ($(LTO_ENABLE),y)
u-boot-keep-syms-lto := keep-syms-lto.o
u-boot-keep-syms-lto_c := $(patsubst %.o,%.c,$(u-boot-keep-syms-lto))
@@ -1787,7 +1794,7 @@ endif
# Rule to link u-boot
# May be overridden by arch/$(ARCH)/config.mk
-ifdef CONFIG_LTO
+ifeq ($(LTO_ENABLE),y)
quiet_cmd_u-boot__ ?= LTO $@
cmd_u-boot__ ?= \
$(CC) -nostdlib -nostartfiles \
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index b3548ce2439..2065438d053 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -15,11 +15,11 @@ CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections -fdata-sections \
-fstack-protector-strong
CFLAGS_EFI := -fpic -fshort-wchar
-ifneq ($(CONFIG_LTO)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
+ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
LDFLAGS_FINAL += --gc-sections
endif
-ifndef CONFIG_LTO
+ifneq ($(LTO_ENABLE),y)
PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
endif
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b1469185860..8d42ef4823e 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -58,16 +58,22 @@
#endif
/*
- * We only support cores that support at least Thumb-1 and thus we use
- * 'bx lr'
+ * Use 'bx lr' everywhere except ARMv4 (without 'T') where only 'mov pc, lr'
+ * works
*/
.irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
.macro ret\c, reg
+
+ /* ARMv4- don't know bx lr but the assembler fails to see that */
+#ifdef __ARM_ARCH_4__
+ mov\c pc, \reg
+#else
.ifeqs "\reg", "lr"
bx\c \reg
.else
mov\c pc, \reg
.endif
+#endif
.endm
.endr
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 6ee2a767615..cd6112dfcda 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -101,7 +101,7 @@ struct arch_global_data {
#include <asm-generic/global_data.h>
-#if defined(__clang__) || defined(CONFIG_LTO)
+#if defined(__clang__) || defined(LTO_ENABLE)
#define DECLARE_GLOBAL_DATA_PTR
#define gd get_gd()
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 700eee5fbbe..7ff4446dd64 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -377,7 +377,7 @@ ENTRY(__gnu_thumb1_case_sqi)
lsls r1, r1, #1
add lr, lr, r1
pop {r1}
- bx lr
+ ret lr
ENDPROC(__gnu_thumb1_case_sqi)
.popsection
@@ -391,7 +391,7 @@ ENTRY(__gnu_thumb1_case_uqi)
lsls r1, r1, #1
add lr, lr, r1
pop {r1}
- bx lr
+ ret lr
ENDPROC(__gnu_thumb1_case_uqi)
.popsection
@@ -406,7 +406,7 @@ ENTRY(__gnu_thumb1_case_shi)
lsls r1, r1, #1
add lr, lr, r1
pop {r0, r1}
- bx lr
+ ret lr
ENDPROC(__gnu_thumb1_case_shi)
.popsection
@@ -421,7 +421,7 @@ ENTRY(__gnu_thumb1_case_uhi)
lsls r1, r1, #1
add lr, lr, r1
pop {r0, r1}
- bx lr
+ ret lr
ENDPROC(__gnu_thumb1_case_uhi)
.popsection
#endif
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
index eee7a219ce3..a1c996f94ef 100644
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -59,7 +59,7 @@
#endif
ENTRY(memcpy)
cmp r0, r1
- bxeq lr
+ reteq lr
enter r4, lr
@@ -148,7 +148,7 @@ ENTRY(memcpy)
str1b r0, ip, cs, abort=21f
exit r4, lr
- bx lr
+ ret lr
9: rsb ip, ip, #4
cmp ip, #2
@@ -258,7 +258,7 @@ ENTRY(memcpy)
.macro copy_abort_end
ldmfd sp!, {r4, lr}
- bx lr
+ ret lr
.endm
ENDPROC(memcpy)
diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S
index 5102bfabde4..dd6f2e3bd5e 100644
--- a/arch/arm/lib/relocate.S
+++ b/arch/arm/lib/relocate.S
@@ -61,7 +61,7 @@ ENTRY(relocate_vectors)
stmia r1!, {r2-r8,r10}
#endif
#endif
- bx lr
+ ret lr
ENDPROC(relocate_vectors)
@@ -127,13 +127,7 @@ relocate_done:
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
#endif
- /* ARMv4- don't know bx lr but the assembler fails to see that */
-
-#ifdef __ARM_ARCH_4__
- mov pc, lr
-#else
- bx lr
-#endif
+ ret lr
ENDPROC(relocate_code)
diff --git a/arch/arm/lib/setjmp.S b/arch/arm/lib/setjmp.S
index 176a1d5315b..2f041aeef01 100644
--- a/arch/arm/lib/setjmp.S
+++ b/arch/arm/lib/setjmp.S
@@ -17,7 +17,7 @@ ENTRY(setjmp)
mov ip, sp
stm a1, {v1-v8, ip, lr}
mov a1, #0
- bx lr
+ ret lr
ENDPROC(setjmp)
.popsection
@@ -31,6 +31,6 @@ ENTRY(longjmp)
bne 1f
mov a1, #1
1:
- bx lr
+ ret lr
ENDPROC(longjmp)
.popsection
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index fe5d44d36ed..1d49a9bd102 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -89,7 +89,7 @@ void spl_board_init(void)
int ret;
ret = ut_run_list("spl", NULL, tests, count,
- state->select_unittests);
+ state->select_unittests, 1);
/* continue execution into U-Boot */
}
}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 211ebe9c878..67c7d2512f3 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1971,6 +1971,12 @@ config CMD_GETTIME
milliseconds. See also the 'bootstage' command which provides more
flexibility for boot timing.
+config CMD_PAUSE
+ bool "pause command"
+ help
+ Delay execution waiting for any user input.
+ Useful to allow the user to read a failure log.
+
config CMD_RNG
bool "rng command"
depends on DM_RNG
diff --git a/cmd/Makefile b/cmd/Makefile
index 6e87522b62e..7abe1d36302 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_CMD_MFSL) += mfsl.o
obj-$(CONFIG_CMD_MII) += mii.o
obj-$(CONFIG_CMD_MISC) += misc.o
obj-$(CONFIG_CMD_MDIO) += mdio.o
+obj-$(CONFIG_CMD_PAUSE) += pause.o
obj-$(CONFIG_CMD_SLEEP) += sleep.o
obj-$(CONFIG_CMD_MMC) += mmc.o
obj-$(CONFIG_CMD_OPTEE_RPMB) += optee_rpmb.o
diff --git a/cmd/pause.c b/cmd/pause.c
new file mode 100644
index 00000000000..c97833c0d70
--- /dev/null
+++ b/cmd/pause.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021
+ * Samuel Dionne-Riel <samuel@dionne-riel.com>
+ */
+
+#include <command.h>
+#include <stdio.h>
+
+static int do_pause(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *message = "Press any key to continue...";
+
+ if (argc == 2)
+ message = argv[1];
+
+ /* No newline, so it sticks to the bottom of the screen */
+ printf("%s", message);
+
+ /* Wait on "any" key... */
+ (void) getchar();
+
+ /* Since there was no newline, we need it now */
+ printf("\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(pause, 2, 1, do_pause,
+ "delay until user input",
+ "[prompt] - Wait until users presses any key. [prompt] can be used to customize the message.\n"
+);
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 4599db73ed0..9a1b6e4bbfc 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -67,6 +67,7 @@ CONFIG_CMD_BMP=y
CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_RTC=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_PAUSE=y
CONFIG_CMD_TIMER=y
CONFIG_CMD_SOUND=y
CONFIG_CMD_QFW=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 4a0c51c7f52..e6a17185719 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -96,6 +96,7 @@ CONFIG_CMD_BOOTCOUNT=y
CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_RTC=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_PAUSE=y
CONFIG_CMD_TIMER=y
CONFIG_CMD_SOUND=y
CONFIG_CMD_QFW=y
diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst
index ee544ad87ee..a71f860a487 100644
--- a/doc/build/gcc.rst
+++ b/doc/build/gcc.rst
@@ -152,6 +152,23 @@ of dtc is new enough. It also makes sure that pylibfdt is present, if needed
Note that the :doc:`tools` are always built with the included version of libfdt
so it is not possible to build U-Boot tools with a system libfdt, at present.
+Link-time optimisation (LTO)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+U-Boot supports link-time optimisation which can reduce the size of the final
+U-Boot binaries, particularly with SPL.
+
+At present this can be enabled by ARM boards by adding `CONFIG_LTO=y` into the
+defconfig file. Other architectures are not supported. LTO is enabled by default
+for sandbox.
+
+This does incur a link-time penalty of several seconds. For faster incremental
+builds during development, you can disable it by setting `NO_LTO` to `1`.
+
+.. code-block:: bash
+
+ NO_LTO=1 make
+
Other build targets
~~~~~~~~~~~~~~~~~~~
diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst
index 40cf8ecdd7f..8e42a32afb9 100644
--- a/doc/develop/tests_sandbox.rst
+++ b/doc/develop/tests_sandbox.rst
@@ -119,6 +119,30 @@ You can easily use gdb on these tests, without needing --gdbserver::
You can then single-step and look at variables as needed.
+Running tests multiple times
+----------------------------
+
+Some tests can have race conditions which are hard to detect on a single
+one. It is possible to run each individual test multiple times, before moving
+to the next test, with the '-r' flag.
+
+This is most useful when running a single test, since running all tests
+multiple times can take a while.
+
+For example::
+
+ => ut dm -r1000 dm_test_rtc_set_get
+ ...
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ Test: dm_test_rtc_set_get: rtc.c
+ test/dm/rtc.c:257, dm_test_rtc_reset(): old_base_time == base_time: Expected 0x62e7453c (1659323708), got 0x62e7453d (1659323709)
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ Test: dm_test_rtc_set_get: rtc.c
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ ...
+ Test dm_test_rtc_reset failed 3 times
+
+
Running sandbox_spl tests directly
----------------------------------
diff --git a/doc/usage/cmd/pause.rst b/doc/usage/cmd/pause.rst
new file mode 100644
index 00000000000..c79e399c020
--- /dev/null
+++ b/doc/usage/cmd/pause.rst
@@ -0,0 +1,53 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later:
+
+pause command
+=============
+
+Synopsis
+--------
+
+::
+
+ pause [prompt]
+
+
+Description
+-----------
+
+The pause command delays execution waiting for any user input.
+
+It can accept a single parameter to change the prompt message.
+
+Examples
+--------
+
+Using with the default prompt:
+
+::
+
+ => pause
+ Press any key to continue...
+
+
+Using with a custom prompt:
+
+::
+
+ => pause 'Prompt for pause...'
+ Prompt for pause...
+
+Note that complex prompts require proper quoting:
+
+::
+
+ => pause Prompt for pause...
+ pause - delay until user input
+
+ Usage:
+ pause [prompt] - Wait until users presses any key. [prompt] can be used to customize the message.
+
+Return value
+------------
+
+The return value $? is always set to 0 (true), unless invoked in an invalid
+manner.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 28f9683a3e6..5170fa8b4a5 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -52,6 +52,7 @@ Shell commands
cmd/mbr
cmd/md
cmd/mmc
+ cmd/pause
cmd/pinmux
cmd/printenv
cmd/pstore
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index c6e9c497413..2157f3533e5 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -160,11 +160,13 @@
"scan_dev_for_efi=" \
"setenv efi_fdtfile ${fdtfile}; " \
BOOTENV_EFI_SET_FDTFILE_FALLBACK \
+ BOOTENV_RUN_EXTENSION_INIT \
"for prefix in ${efi_dtb_prefixes}; do " \
"if test -e ${devtype} " \
"${devnum}:${distro_bootpart} " \
"${prefix}${efi_fdtfile}; then " \
"run load_efi_dtb; " \
+ BOOTENV_RUN_EXTENSION_APPLY \
"fi;" \
"done;" \
"run boot_efi_bootmgr;" \
@@ -416,6 +418,34 @@
BOOT_TARGET_DEVICES_references_PXE_without_CONFIG_CMD_DHCP_or_PXE
#endif
+#if defined(CONFIG_CMD_EXTENSION)
+#define BOOTENV_RUN_EXTENSION_INIT "run extension_init; "
+#define BOOTENV_RUN_EXTENSION_APPLY "run extension_apply; "
+#define BOOTENV_SET_EXTENSION_NEED_INIT \
+ "extension_need_init=; " \
+ "setenv extension_overlay_addr ${fdtoverlay_addr_r}; "
+#define BOOTENV_SHARED_EXTENSION \
+ "extension_init=" \
+ "echo Extension init...; " \
+ "if ${extension_need_init}; then " \
+ "extension_need_init=false; " \
+ "extension scan; " \
+ "fi\0" \
+ \
+ "extension_overlay_cmd=" \
+ "load ${devtype} ${devnum}:${distro_bootpart} " \
+ "${extension_overlay_addr} ${prefix}${extension_overlay_name}\0" \
+ "extension_apply=" \
+ "if fdt addr -q ${fdt_addr_r}; then " \
+ "extension apply all; " \
+ "fi\0"
+#else
+#define BOOTENV_RUN_EXTENSION_INIT
+#define BOOTENV_RUN_EXTENSION_APPLY
+#define BOOTENV_SET_EXTENSION_NEED_INIT
+#define BOOTENV_SHARED_EXTENSION
+#endif
+
#define BOOTENV_DEV_NAME(devtypeu, devtypel, instance, ...) \
BOOTENV_DEV_NAME_##devtypeu(devtypeu, devtypel, instance, ## __VA_ARGS__)
#define BOOTENV_BOOT_TARGETS \
@@ -435,6 +465,7 @@
BOOTENV_SHARED_UBIFS \
BOOTENV_SHARED_EFI \
BOOTENV_SHARED_VIRTIO \
+ BOOTENV_SHARED_EXTENSION \
"boot_prefixes=/ /boot/\0" \
"boot_scripts=boot.scr.uimg boot.scr\0" \
"boot_script_dhcp=boot.scr.uimg\0" \
@@ -499,6 +530,7 @@
BOOTENV_SET_NVME_NEED_INIT \
BOOTENV_SET_IDE_NEED_INIT \
BOOTENV_SET_VIRTIO_NEED_INIT \
+ BOOTENV_SET_EXTENSION_NEED_INIT \
"for target in ${boot_targets}; do " \
"run bootcmd_${target}; " \
"done\0"
diff --git a/include/test/test.h b/include/test/test.h
index c888d68b1ed..2b68331b546 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -20,6 +20,7 @@
* @testdev: Test device
* @force_fail_alloc: Force all memory allocs to fail
* @skip_post_probe: Skip uclass post-probe processing
+ * @runs_per_test: Number of times to run each test (typically 1)
* @expect_str: Temporary string used to hold expected string value
* @actual_str: Temporary string used to hold actual string value
*/
@@ -32,6 +33,7 @@ struct unit_test_state {
struct udevice *testdev;
int force_fail_alloc;
int skip_post_probe;
+ int runs_per_test;
char expect_str[512];
char actual_str[512];
};
diff --git a/include/test/ut.h b/include/test/ut.h
index 18740f5807c..f7d1d18f7c1 100644
--- a/include/test/ut.h
+++ b/include/test/ut.h
@@ -403,9 +403,10 @@ void test_set_state(struct unit_test_state *uts);
* @count: Number of tests to run
* @select_name: Name of a single test to run (from the list provided). If NULL
* then all tests are run
+ * @runs_per_test: Number of times to run each test (typically 1)
* Return: 0 if all tests passed, -1 if any failed
*/
int ut_run_list(const char *name, const char *prefix, struct unit_test *tests,
- int count, const char *select_name);
+ int count, const char *select_name, int runs_per_test);
#endif
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 3bafeb4fe98..0b3a51da13b 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -489,7 +489,7 @@ endif
# Rule to link u-boot-spl
# May be overridden by arch/$(ARCH)/config.mk
-ifdef CONFIG_LTO
+ifeq ($(LTO_ENABLE),y)
quiet_cmd_u-boot-spl ?= LTO $@
cmd_u-boot-spl ?= \
( \
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index c331757425e..1bb02d93a23 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -5,6 +5,9 @@
ifdef CONFIG_HUSH_PARSER
obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
endif
+ifdef CONFIG_CONSOLE_RECORD
+obj-$(CONFIG_CMD_PAUSE) += test_pause.o
+endif
obj-y += mem.o
obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
obj-$(CONFIG_CMD_FDT) += fdt.o
diff --git a/test/cmd/test_pause.c b/test/cmd/test_pause.c
new file mode 100644
index 00000000000..2b85cce3271
--- /dev/null
+++ b/test/cmd/test_pause.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for pause command
+ *
+ * Copyright 2022, Samuel Dionne-Riel <samuel@dionne-riel.com>
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <test/lib.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int lib_test_hush_pause(struct unit_test_state *uts)
+{
+ /* Test default message */
+ console_record_reset_enable();
+ /* Cook a newline when the command is expected to pause */
+ console_in_puts("\n");
+ ut_assertok(run_command("pause", 0));
+ console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ ut_asserteq_str("Press any key to continue...", uts->actual_str);
+ ut_assertok(ut_check_console_end(uts));
+
+ /* Test provided message */
+ console_record_reset_enable();
+ /* Cook a newline when the command is expected to pause */
+ console_in_puts("\n");
+ ut_assertok(run_command("pause 'Prompt for pause...'", 0));
+ console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ ut_asserteq_str("Prompt for pause...", uts->actual_str);
+ ut_assertok(ut_check_console_end(uts));
+
+ /* Test providing more than one params */
+ console_record_reset_enable();
+ /* No newline cooked here since the command is expected to fail */
+ ut_asserteq(1, run_command("pause a b", 0));
+ console_record_readline(uts->actual_str, sizeof(uts->actual_str));
+ ut_asserteq_str("pause - delay until user input", uts->actual_str);
+ ut_asserteq(1, ut_check_console_end(uts));
+
+ return 0;
+}
+LIB_TEST(lib_test_hush_pause, 0);
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 3789c6b784c..11c219b48ac 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -18,10 +18,17 @@ int cmd_ut_category(const char *name, const char *prefix,
struct unit_test *tests, int n_ents,
int argc, char *const argv[])
{
+ int runs_per_text = 1;
int ret;
+ if (argc > 1 && !strncmp("-r", argv[1], 2)) {
+ runs_per_text = dectoul(argv[1] + 2, NULL);
+ argv++;
+ argc++;
+ }
+
ret = ut_run_list(name, prefix, tests, n_ents,
- argc > 1 ? argv[1] : NULL);
+ argc > 1 ? argv[1] : NULL, runs_per_text);
return ret ? CMD_RET_FAILURE : 0;
}
@@ -168,7 +175,8 @@ static char ut_help_text[] =
#ifdef CONFIG_CMD_LOADM
"ut loadm [test-name]- test of parameters and load memory blob\n"
#endif
- ;
+ "All commands accept an optional [-r<runs>] flag before [test-name], to\n"
+ "run each test multiple times (<runs> is in decimal)";
#endif /* CONFIG_SYS_LONGHELP */
U_BOOT_CMD(
diff --git a/test/dm/rtc.c b/test/dm/rtc.c
index c7f9f8f0ce7..bf97dbbd2f9 100644
--- a/test/dm/rtc.c
+++ b/test/dm/rtc.c
@@ -60,16 +60,27 @@ static int dm_test_rtc_set_get(struct unit_test_state *uts)
{
struct rtc_time now, time, cmp;
struct udevice *dev, *emul;
- long offset, old_offset, old_base_time;
+ long offset, check_offset, old_offset, old_base_time;
+ int i;
ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
- ut_assertok(dm_rtc_get(dev, &now));
ut_assertok(i2c_emul_find(dev, &emul));
- ut_assert(emul != NULL);
+ ut_assertnonnull(emul);
+
+ /* Get the offset, putting the RTC into manual mode */
+ i = 0;
+ do {
+ check_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
+ ut_assertok(dm_rtc_get(dev, &now));
+
+ /* Tell the RTC to go into manual mode */
+ old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
+
+ /* If the times changed in that period, read it again */
+ } while (++i < 2 && check_offset != old_offset);
+ ut_asserteq(check_offset, old_offset);
- /* Tell the RTC to go into manual mode */
- old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
memset(&time, '\0', sizeof(time));
@@ -127,7 +138,8 @@ static int dm_test_rtc_set_get(struct unit_test_state *uts)
ut_asserteq(now.tm_sec + 1, cmp.tm_sec);
}
- old_offset = sandbox_i2c_rtc_set_offset(emul, true, 0);
+ /* return RTC to normal mode */
+ sandbox_i2c_rtc_set_offset(emul, true, 0);
return 0;
}
@@ -161,7 +173,7 @@ static int dm_test_rtc_read_write(struct unit_test_state *uts)
ut_asserteq(memcmp(buf, "at", 3), 0);
ut_assertok(i2c_emul_find(dev, &emul));
- ut_assert(emul != NULL);
+ ut_assertnonnull(emul);
old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
ut_assertok(dm_rtc_get(dev, &time));
@@ -240,20 +252,31 @@ static int dm_test_rtc_reset(struct unit_test_state *uts)
struct rtc_time now;
struct udevice *dev, *emul;
long old_base_time, base_time;
+ int i;
ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
ut_assertok(dm_rtc_get(dev, &now));
ut_assertok(i2c_emul_find(dev, &emul));
- ut_assert(emul != NULL);
+ ut_assertnonnull(emul);
+
+ i = 0;
+ do {
+ old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
- old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
+ ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1));
- ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1));
+ ut_assertok(dm_rtc_reset(dev));
+ base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
- /* Resetting the RTC should put he base time back to normal */
- ut_assertok(dm_rtc_reset(dev));
- base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
+ /*
+ * Resetting the RTC should put the base time back to normal.
+ * Allow for a one-timeadjustment in case the time flips over
+ * while this test process is pre-empted (either by a second
+ * or a daylight-saving change), since reset_time() in
+ * i2c_rtc_emul.c reads the time from the OS.
+ */
+ } while (++i < 2 && base_time != old_base_time);
ut_asserteq(old_base_time, base_time);
return 0;
@@ -274,9 +297,9 @@ static int dm_test_rtc_dual(struct unit_test_state *uts)
ut_assertok(dm_rtc_get(dev2, &now2));
ut_assertok(i2c_emul_find(dev1, &emul1));
- ut_assert(emul1 != NULL);
+ ut_assertnonnull(emul1);
ut_assertok(i2c_emul_find(dev2, &emul2));
- ut_assert(emul2 != NULL);
+ ut_assertnonnull(emul2);
offset = sandbox_i2c_rtc_set_offset(emul1, false, -1);
sandbox_i2c_rtc_set_offset(emul2, false, offset + 1);
diff --git a/test/dm/test-dm.c b/test/dm/test-dm.c
index f5cda81bbfc..eb3581333b9 100644
--- a/test/dm/test-dm.c
+++ b/test/dm/test-dm.c
@@ -29,13 +29,14 @@ DECLARE_GLOBAL_DATA_PTR;
* "fdt_pre_reloc"), or NULL to run all
* Return: 0 if all tests passed, 1 if not
*/
-static int dm_test_run(const char *test_name)
+static int dm_test_run(const char *test_name, int runs_per_text)
{
struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test);
const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test);
int ret;
- ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name);
+ ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name,
+ runs_per_text);
return ret ? CMD_RET_FAILURE : 0;
}
@@ -43,9 +44,15 @@ static int dm_test_run(const char *test_name)
int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
const char *test_name = NULL;
+ int runs_per_text = 1;
+ if (argc > 1 && !strncmp("-r", argv[1], 2)) {
+ runs_per_text = dectoul(argv[1] + 2, NULL);
+ argv++;
+ argc++;
+ }
if (argc > 1)
test_name = argv[1];
- return dm_test_run(test_name);
+ return dm_test_run(test_name, runs_per_text);
}
diff --git a/test/test-main.c b/test/test-main.c
index 31837e57a8f..4f1c54b0f9b 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -390,11 +390,17 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix,
for (test = tests; test < tests + count; test++) {
const char *test_name = test->name;
- int ret;
+ int ret, i, old_fail_count;
if (!test_matches(prefix, test_name, select_name))
continue;
- ret = ut_run_test_live_flat(uts, test, select_name);
+ old_fail_count = uts->fail_count;
+ for (i = 0; i < uts->runs_per_test; i++)
+ ret = ut_run_test_live_flat(uts, test, select_name);
+ if (uts->fail_count != old_fail_count) {
+ printf("Test %s failed %d times\n", select_name,
+ uts->fail_count - old_fail_count);
+ }
found++;
if (ret == -EAGAIN)
continue;
@@ -408,7 +414,8 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix,
}
int ut_run_list(const char *category, const char *prefix,
- struct unit_test *tests, int count, const char *select_name)
+ struct unit_test *tests, int count, const char *select_name,
+ int runs_per_test)
{
struct unit_test_state uts = { .fail_count = 0 };
bool has_dm_tests = false;
@@ -432,6 +439,7 @@ int ut_run_list(const char *category, const char *prefix,
printf("Running %d %s tests\n", count, category);
uts.of_root = gd_of_root();
+ uts.runs_per_test = runs_per_test;
ret = ut_run_tests(&uts, prefix, tests, count, select_name);
if (ret == -ENOENT)