@@ -1479,6 +1479,17 @@ config BOOTSTAGE_FDT
Code in the Linux kernel can find this in /proc/devicetree.
+config BOOTSTAGE_SAVE
+ bool "Allow saving and restoring the bootstage record count"
+ depends on BOOTSTAGE
+ default y if UNIT_TEST
+ help
+ Provide 'bootstage save' and 'bootstage restore' subcommands
+ which store and retrieve the record count via the bootstage_count
+ environment variable. These are used by Python tests to prevent
+ records from accumulating across tests and filling the bootstage
+ table.
+
config BOOTSTAGE_STASH
bool "Stash the boot timing information in memory before booting OS"
depends on BOOTSTAGE
@@ -5,6 +5,7 @@
#include <bootstage.h>
#include <command.h>
+#include <env.h>
#include <vsprintf.h>
#include <linux/string.h>
@@ -62,8 +63,31 @@ static int do_bootstage_stash(struct cmd_tbl *cmdtp, int flag, int argc,
}
#endif
+static int __maybe_unused do_bootstage_save(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ env_set_hex("bootstage_count", bootstage_get_rec_count());
+
+ return 0;
+}
+
+static int __maybe_unused do_bootstage_restore(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ ulong count = env_get_hex("bootstage_count", 0);
+
+ if (count)
+ bootstage_set_rec_count(count);
+
+ return 0;
+}
+
static struct cmd_tbl cmd_bootstage_sub[] = {
U_BOOT_CMD_MKENT(report, 2, 1, do_bootstage_report, "", ""),
+#if IS_ENABLED(CONFIG_BOOTSTAGE_SAVE)
+ U_BOOT_CMD_MKENT(save, 1, 0, do_bootstage_save, "", ""),
+ U_BOOT_CMD_MKENT(restore, 1, 0, do_bootstage_restore, "", ""),
+#endif
#if IS_ENABLED(CONFIG_BOOTSTAGE_STASH)
U_BOOT_CMD_MKENT(stash, 4, 0, do_bootstage_stash, "", ""),
U_BOOT_CMD_MKENT(unstash, 4, 0, do_bootstage_stash, "", ""),
@@ -95,6 +119,10 @@ U_BOOT_CMD(bootstage, 4, 1, do_boostage,
"Boot stage command",
" - check boot progress and timing\n"
"report - Print a report\n"
+#if IS_ENABLED(CONFIG_BOOTSTAGE_SAVE)
+ "save - Save record count to $bootstage_count\n"
+ "restore - Restore record count from $bootstage_count\n"
+#endif
#if IS_ENABLED(CONFIG_BOOTSTAGE_STASH)
"stash [<start> [<size>]] - Stash data into memory\n"
"unstash [<start> [<size>]] - Unstash data from memory\n"
new file mode 100644
@@ -0,0 +1,86 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. index::
+ single: bootstage (command)
+
+bootstage command
+=================
+
+Synopsis
+--------
+
+::
+
+ bootstage report
+ bootstage save
+ bootstage restore
+ bootstage stash [<start> [<size>]]
+ bootstage unstash [<start> [<size>]]
+
+Description
+-----------
+
+The *bootstage* command provides access to U-Boot's boot-timing records.
+
+bootstage report
+ Print a report of all bootstage records, showing the timestamp and elapsed
+ time for each stage.
+
+bootstage save
+ Save the current record count to the *bootstage_count* environment
+ variable. This can be used to snapshot the bootstage state before an
+ operation that adds records.
+
+bootstage restore
+ Restore the record count from *bootstage_count*, discarding any records
+ added since the last save. This is used by the Python test framework to
+ prevent records from accumulating across tests.
+
+bootstage stash
+ Stash bootstage data into memory at the given address and size.
+ Only available when ``CONFIG_BOOTSTAGE_STASH`` is enabled.
+
+bootstage unstash
+ Read back previously stashed bootstage data from memory.
+ Only available when ``CONFIG_BOOTSTAGE_STASH`` is enabled.
+
+Configuration
+-------------
+
+The *bootstage* command is available when ``CONFIG_BOOTSTAGE`` is enabled.
+
+CONFIG_BOOTSTAGE_REPORT
+ Enable output of a boot-time report before booting the OS.
+
+CONFIG_BOOTSTAGE_RECORD_COUNT
+ Number of bootstage records to store (default 50).
+
+CONFIG_BOOTSTAGE_SAVE
+ Enable the *save* and *restore* subcommands. Default y when
+ ``CONFIG_UNIT_TEST`` is set.
+
+CONFIG_BOOTSTAGE_STASH
+ Enable the *stash* and *unstash* subcommands for passing bootstage
+ data to the OS via memory.
+
+Example
+-------
+
+::
+
+ => bootstage report
+ Timer summary in microseconds (8 records):
+ Mark Elapsed Stage
+ 0 0 reset
+ 0 0 board_init_f
+ 29,743 29,743 board_init_r
+ 52,918 23,175 eth_common_init
+ 53,007 89 eth_initialize
+
+ Accumulated time:
+ 1,235 dm_f
+ 670 of_live
+ 5,621 dm_r
+
+ => bootstage save
+ => bootstage restore
@@ -49,6 +49,7 @@ Shell commands
cmd/bootm
cmd/bootmenu
cmd/bootmeth
+ cmd/bootstage
cmd/bootstd
cmd/bootz
cmd/button
@@ -519,6 +519,15 @@ static inline int bootstage_init(bool first)
return 0;
}
+static inline uint bootstage_get_rec_count(void)
+{
+ return 0;
+}
+
+static inline void bootstage_set_rec_count(uint count)
+{
+}
+
#endif /* ENABLE_BOOTSTAGE */
/* helpers for SPL */
@@ -30,3 +30,27 @@ static int cmd_bootstage_report(struct unit_test_state *uts)
return 0;
}
CMD_TEST(cmd_bootstage_report, UTF_CONSOLE);
+
+static int cmd_bootstage_save_restore(struct unit_test_state *uts)
+{
+ uint count;
+
+ count = bootstage_get_rec_count();
+ ut_assert(count > 0);
+
+ /* Save the current count */
+ ut_assertok(run_command("bootstage save", 0));
+ ut_assert_console_end();
+
+ /* Add a new record and check the count grows by one */
+ bootstage_mark_name(BOOTSTAGE_ID_USER + 60, "test_save_restore");
+ ut_asserteq(count + 1, bootstage_get_rec_count());
+
+ /* Restore should bring the count back */
+ ut_assertok(run_command("bootstage restore", 0));
+ ut_assert_console_end();
+ ut_asserteq(count, bootstage_get_rec_count());
+
+ return 0;
+}
+CMD_TEST(cmd_bootstage_save_restore, UTF_CONSOLE);