bootstd: Add a simple command to list images

Add a new 'bootstd images' command, which lists the images which have
been loaded.

Update some existing tests to use it. Provide some documentation about
images in general and this command in particular.

Use a more realistic kernel command-line to make the test easier to
follow.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 9397328..14de5b5 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -15,6 +15,7 @@
 #include <efi.h>
 #include <efi_loader.h>
 #include <expo.h>
+#include <mapmem.h>
 #ifdef CONFIG_SANDBOX
 #include <asm/test.h>
 #endif
@@ -77,6 +78,14 @@
 	ut_assert_nextline("(1 bootflow, 1 valid)");
 	ut_assert_console_end();
 
+	ut_assertok(run_command("bootstd images", 0));
+	ut_assert_nextlinen("Seq");
+	ut_assert_nextlinen("---");
+	ut_assert_nextlinen("  0  mmc1.bootdev.part_1  extlinux_cfg");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 image)");
+	ut_assert_console_end();
+
 	return 0;
 }
 BOOTSTD_TEST(bootflow_cmd, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
@@ -1193,6 +1202,19 @@
 	ut_assert_nextlinen("---");
 	ut_assert_skip_to_line("(3 bootflows, 3 valid)");
 
+	ut_assertok(run_command("bootstd images", 0));
+	ut_assert_nextlinen("Seq");
+	ut_assert_nextlinen("---");
+	ut_assert_nextlinen("  0  mmc1.bootdev.part_1  extlinux_cfg");
+	ut_assert_nextlinen("  1  mmc5.bootdev.part_2  x86_setup");
+	ut_assert_nextlinen("  1  mmc5.bootdev.part_2  cmdline");
+	ut_assert_nextlinen("  1  mmc5.bootdev.part_2  kernel                 -      4000  kernel");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_4  x86_setup");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_4  cmdline");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_4  kernel                 -      4000  kernel");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(7 images)");
+
 	ut_assert_console_end();
 
 	return 0;
@@ -1284,3 +1306,87 @@
 	return 0;
 }
 BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE);
+
+/* Check 'bootflow scan' provides a list of images */
+static int bootstd_images(struct unit_test_state *uts)
+{
+	static const char *order[] = {"mmc2", "mmc1", "mmc4", "mmc5", NULL};
+	const struct legacy_img_hdr *hdr;
+	const struct bootflow_img *img;
+	const struct bootflow *bflow;
+	struct bootstd_priv *std;
+	const char **old_order;
+	struct udevice *dev;
+	ofnode root, node;
+	ulong data, len;
+	char *ptr;
+
+	/* get access to the current bootflow */
+	ut_assertok(bootstd_get_priv(&std));
+
+	ut_assertok(prep_mmc_bootdev(uts, "mmc4", true, &old_order));
+
+	/* bind mmc5 too, for cros */
+	root = oftree_root(oftree_default());
+	node = ofnode_find_subnode(root, "mmc5");
+	ut_assert(ofnode_valid(node));
+	ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
+
+	std->bootdev_order = order;
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_console_end();
+	std->bootdev_order = old_order;
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_skip_to_line("(4 bootflows, 4 valid)");
+
+	ut_assertok(run_command("bootstd images", 0));
+	ut_assert_nextlinen("Seq");
+	ut_assert_nextlinen("---");
+	ut_assert_nextlinen("  0  mmc1.bootdev.part_1  extlinux_cfg");
+	ut_assert_nextlinen("  1  mmc4.bootdev.part_1  script");
+	ut_assert_nextlinen("  1  mmc4.bootdev.part_1  logo");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_2  x86_setup");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_2  cmdline");
+	ut_assert_nextlinen("  2  mmc5.bootdev.part_2  kernel                 -");
+	ut_assert_nextlinen("  3  mmc5.bootdev.part_4  x86_setup");
+	ut_assert_nextlinen("  3  mmc5.bootdev.part_4  cmdline");
+	ut_assert_nextlinen("  3  mmc5.bootdev.part_4  kernel                 -");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(9 images)");
+
+	/* check the first image */
+	bflow = alist_get(&std->bootflows, 0, struct bootflow);
+	img = alist_get(&bflow->images, 0, struct bootflow_img);
+	ut_asserteq_strn("# extlinux.conf", map_sysmem(img->addr, 0));
+
+	/* check the second image */
+	bflow = alist_get(&std->bootflows, 1, struct bootflow);
+	img = alist_get(&bflow->images, 0, struct bootflow_img);
+
+	/* this is the length of the script in bytes */
+	hdr = map_sysmem(img->addr, 0);
+	image_multi_getimg(hdr, 0, &data, &len);
+	ptr = (void *)data;
+	ut_asserteq_strn("# DO NOT EDIT THIS FILE", ptr);
+
+	/* check the ChromiumOS images */
+	bflow = alist_get(&std->bootflows, 2, struct bootflow);
+	img = alist_get(&bflow->images, 1, struct bootflow_img);
+	ptr = map_sysmem(img->addr, 0);
+	ut_asserteq_strn("BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=", ptr);
+
+	/*
+	 * the x86 setup is not a real binary, so just check that it is empty,
+	 * so that if this changes in the future someone will notice and update
+	 * this test
+	 */
+	img = alist_get(&bflow->images, 0, struct bootflow_img);
+	ptr = map_sysmem(img->addr, 0);
+	ut_asserteq(0, *(ulong *)ptr);
+
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootstd_images, UTF_CONSOLE);
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index 6d44191..1ca9ecc 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -402,9 +402,10 @@
         start, size, num, name = line.split(maxsplit=3)
         parts[int(num)] = Partition(int(start), int(size), name)
 
+    # Set up the kernel command-line
     dummy = os.path.join(cons.config.result_dir, 'dummy.txt')
     with open(dummy, 'wb') as outf:
-        outf.write(b'dummy\n')
+        outf.write(b'BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=/dev/nvme0n1p1 ro quiet splash vt.handoff=7')
 
     # For now we just use dummy kernels. This limits testing to just detecting
     # a signed kernel. We could add support for the x86 data structures so that