return ptr;
}
+
+int bootflow_get_seq(const struct bootflow *bflow)
+{
+ struct bootstd_priv *std;
+ int ret;
+
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return ret;
+
+ return alist_calc_index(&std->bootflows, bflow);
+}
This command is not necessary for bootstd to work.
+config CMD_BOOTSTD
+ bool "bootstd"
+ depends on BOOTSTD
+ default y if BOOTSTD_FULL
+ help
+ Provide general information and control for bootstd.
+
+ This command is not necessary for bootstd to work.
+
config BOOTM_EFI
bool "Support booting UEFI FIT images"
depends on EFI_BINARY_EXEC && CMD_BOOTM && FIT
obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o
obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o
obj-$(CONFIG_CMD_BOOTMETH) += bootmeth.o
+obj-$(CONFIG_CMD_BOOTSTD) += bootstd.o
obj-$(CONFIG_CMD_SOURCE) += source.o
obj-$(CONFIG_CMD_BCB) += bcb.o
obj-$(CONFIG_CMD_BDI) += bdinfo.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootstd' command
+ *
+ * Copyright 2024 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <command.h>
+#include <dm.h>
+#include <malloc.h>
+#include <dm/uclass-internal.h>
+
+static int do_bootstd_images(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const struct bootflow *bflow;
+ struct bootstd_priv *std;
+ int ret, i;
+
+ ret = bootstd_get_priv(&std);
+ if (ret) {
+ printf("Cannot get bootstd (err=%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Seq Bootflow Type At Size Filename\n");
+ printf("--- ------------------- -------------- -------- -------- ----------------\n");
+
+ /*
+ * Use the ordering if we have one, so long as we are not trying to list
+ * all bootmethds
+ */
+ i = 0;
+ alist_for_each(bflow, &std->bootflows) {
+ const struct bootflow_img *img;
+
+ alist_for_each(img, &bflow->images) {
+ printf("%3d %-20.20s %-15.15s ",
+ bootflow_get_seq(bflow), bflow->name,
+ bootflow_img_type_name(img->type));
+ if (img->addr)
+ printf("%8lx", img->addr);
+ else
+ printf("%8s", "-");
+ printf(" %8lx %s\n", img->size, img->fname);
+ i++;
+ }
+ }
+
+ printf("--- ------------------- -------------- -------- -------- ----------------\n");
+ printf("(%d image%s)\n", i, i != 1 ? "s" : "");
+
+ return 0;
+}
+
+U_BOOT_LONGHELP(bootstd,
+ "images - list loaded images");
+
+U_BOOT_CMD_WITH_SUBCMDS(bootstd, "Standard-boot operation", bootstd_help_text,
+ U_BOOT_SUBCMD_MKENT(images, 1, 1, do_bootstd_images));
Command interface
-----------------
-Three commands are available:
+Four commands are available:
`bootdev`
Allows listing of available bootdevs, selecting a particular one and
Allow listing of available bootmethds, setting the order in which they are
tried and bootmeth specific configuration. See :doc:`/usage/cmd/bootmeth`
+`bootstd`
+ Allow access to standard boot itself, so far only for listing images across
+ all bootflows. See :doc:`/usage/cmd/bootstd`
+
+Images
+------
+
+Standard boot keeps track of images which can or have been loaded. These are
+kept in a list attached to each bootflow. They can be listed using the
+``bootstd images`` command (see :doc:`/usage/cmd/bootstd`).
+
+For now most bootmeths load their images when scanning. Over time, some may
+adjust to load them only when needed, but in this case the images will still
+be visible.
+
+Once a bootflow has been selected, images for those that are not selected can
+potentially be dropped from the memory map. For now, this is not implemented.
+
+
.. _BootflowStates:
Bootflow states
--- /dev/null
+.. SPDX-License-Identifier: GPL-2.0+:
+
+.. index::
+ single: bootstd (command)
+
+bootstd command
+===============
+
+Synopsis
+--------
+
+::
+
+ bootstd images
+
+Description
+-----------
+
+The `bootstd` command is used to manage standard boot. At present the only
+functionality available is to look at the images which have been loaded, or
+could be loaded should a particular bootflow be selected.
+
+See :doc:`/develop/bootstd/index` for more information.
+
+bootflow images
+~~~~~~~~~~~~~~~
+
+Lists the available images and their location in memory.
+
+Example
+-------
+
+This shows listing images attached to various bootflows, then checking the
+content of a few of them::
+
+ => bootflow scan
+ => bootflow list
+ Showing all bootflows
+ Seq Method State Uclass Part Name Filename
+ --- ----------- ------ -------- ---- ------------------------ ----------------
+ 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf
+ 1 script ready mmc 1 mmc4.bootdev.part_1 /boot/boot.scr
+ 2 cros ready mmc 2 mmc5.bootdev.part_2
+ 3 cros ready mmc 4 mmc5.bootdev.part_4
+ --- ----------- ------ -------- ---- ------------------------ ----------------
+ (4 bootflows, 4 valid)
+ =>
+ => bootstd images
+ Seq Bootflow Type At Size Filename
+ --- ------------------- -------------- -------- -------- ----------------
+ 0 mmc1.bootdev.part_1 extlinux_cfg 8ed5a70 253 /extlinux/extlinux.conf
+ 1 mmc4.bootdev.part_1 script 8ed9550 c73 /boot/boot.scr
+ 1 mmc4.bootdev.part_1 logo 8eda2a0 5d42 boot.bmp
+ 2 mmc5.bootdev.part_2 x86_setup 8ee84d0 3000 setup
+ 2 mmc5.bootdev.part_2 cmdline 8ee84d0 1000 cmdline
+ 2 mmc5.bootdev.part_2 kernel - 4000 kernel
+ 3 mmc5.bootdev.part_4 x86_setup 8eeb4e0 3000 setup
+ 3 mmc5.bootdev.part_4 cmdline 8eeb4e0 1000 cmdline
+ 3 mmc5.bootdev.part_4 kernel - 4000 kernel
+ --- ------------------- -------------- -------- -------- ----------------
+ (9 images)
+ => md 8eda2a0 10
+ 08eda2a0: 5d424d42 00000000 008a0000 007c0000 BMB]..........|.
+ 08eda2b0: 00ac0000 002e0000 00010000 00000018 ................
+ 08eda2c0: 5cb80000 0b130000 0b130000 00000000 ...\............
+ 08eda2d0: 00000000 00000000 ff0000ff 00ff0000 ................
+ => md 8ee84d0 10
+ 08ee84d0: 544f4f42 414d495f 2f3d4547 696c6d76 BOOT_IMAGE=/vmli
+ 08ee84e0: 2d7a756e 35312e35 312d302e 672d3132 nuz-5.15.0-121-g
+ 08ee84f0: 72656e65 72206369 3d746f6f 7665642f eneric root=/dev
+ 08ee8500: 6d766e2f 316e3065 72203170 7571206f /nvme0n1p1 ro qu
+
+Return value
+------------
+
+The return value $? is always 0 (true).
+
+
+.. BootflowStates_:
cmd/bootm
cmd/bootmenu
cmd/bootmeth
+ cmd/bootstd
cmd/bootz
cmd/button
cmd/cat
struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
enum bootflow_img_t type, ulong addr,
ulong size);
+/**
+ * bootflow_get_seq() - Get the sequence number of a bootflow
+ *
+ * Bootflows are numbered by their position in the bootstd list.
+ *
+ * Return: Sequence number of bootflow (0 = first)
+ */
+int bootflow_get_seq(const struct bootflow *bflow);
#endif
#include <efi.h>
#include <efi_loader.h>
#include <expo.h>
+#include <mapmem.h>
#ifdef CONFIG_SANDBOX
#include <asm/test.h>
#endif
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);
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;
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);
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