All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/41] Initial implementation of standard boot
@ 2021-10-23 23:25 ` Simon Glass
  2021-10-23 23:25   ` [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number Simon Glass
                     ` (57 more replies)
  0 siblings, 58 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren


The bootflow feature provide a built-in way for U-Boot to automatically
boot an Operating System without custom scripting and other customisation.
This is called 'standard boot' since it provides a standard way for
U-Boot to boot a distro, without scripting.

It introduces the following concepts:

   - bootdev - a device which can hold a distro
   - bootmeth - a method to scan a bootdev to find bootflows (owned by
                U-Boot)
   - bootflow - a description of how to boot (owned by the distro)

This series provides an implementation of these, enabled to scan for
bootflows from MMC, USB and Ethernet. It supports the existing distro
boot as well as the EFI loader flow (bootefi/bootmgr). It works
similiarly to the existing script-based approach, but is native to
U-Boot.

With this we can boot on a Raspberry Pi 3 with just one command:

   bootflow scan -lb

which means to scan, listing (-l) each bootflow and trying to boot each
one (-b). The final patch shows this.

With a standard way to identify boot devices, booting become easier. It
also should be possible to support U-Boot scripts, for backwards
compatibility only.

This series relies on the PXE clean-up series, posted here:

   https://patchwork.ozlabs.org/project/uboot/list/?series=267078

For documentation, see the 'doc' patch.

For version 2, a new naming scheme is used as above:

   - bootdev is used instead of bootdevice, because 'device' is overused,
       is everywhere in U-Boot, can be confused with udevice
   - bootmeth - because 'method' is too vanilla, appears 1300 times in
       U-Boot

Also in version 2, drivers are introduced for the boot methods, to make
it more extensible. Booting a custom OS is simply a matter of creating a
bootmeth for it and implementing the read_file() and boot() methods.

The design is described in these two documents:

https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing

https://drive.google.com/file/d/1kTrflO9vvGlKp-ZH_jlgb9TY3WYG6FF9/view?usp=sharing

The series is available at u-boot-dm/bme-working

Sample log on rpi_3_32b:

U-Boot 2021.10-rc2-00043-gccd453aa918-dirty (Aug 28 2021 - 13:58:46 -0600)

DRAM:  992 MiB
RPI 3 Model B (0xa22082)
MMC:   mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:    serial
Out:   vidconsole
Err:   vidconsole
Net:   No ethernet found.
starting USB...
Bus usb@7e980000: USB DWC2
scanning bus usb@7e980000 for devices... usb_kbd usb_kbd: Timeout poll on interrupt endpoint
Failed to get keyboard state from device 0c40:8000
4 USB Device(s) found
       scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot:  0
Scanning for bootflows in all bootmethods
Seq  Type         State   Uclass    Part  Name                      Filename
---  -----------  ------  --------  ----  ------------------------  ----------------
Scanning bootmethod 'mmc@7e202000.bootmethod':
  0  efi-loader   loaded  mmc          1  mmc@7e202000.bootmethod.p efi/boot/bootarm.efi
** Booting bootflow 'mmc@7e202000.bootmethod.part_1'
Scanning disk mmc@7e202000.blk...
** Unrecognized filesystem type **
Card did not respond to voltage select! : -110
Scanning disk sdhci@7e300000.blk...
Disk sdhci@7e300000.blk not ready
Found 4 disks
No EFI system partition
Booting /efi\boot
Waiting for Ethernet connection... done.

      Fedora (5.11.12-300.fc34.armv7hl) 34 (Workstation Edition)
      UEFI Firmware Settings

      Use the ▲ and ▼ keys to change the selection.
      Press 'e' to edit the selected item, or 'c' for a command prompt. Press Escape to return to the previous menu.
   The selected entry will be started automatically in 0s.

Changes in v2:
- Free the memory buffer, to avoid running out of memory
- Unmap the file
- Reorder struct sandbox_mmc_priv

Simon Glass (41):
  lib: Add a way to find the postiion of a trailing number
  Makefile: Allow LTO to be disabled for a build
  test/py: Allow passing input to a program
  sandbox: Support unmapping a file
  sandbox: mmc: Support a backing file
  mmc: Allow for children other than the block device
  mbr: Correct verification check
  disk: part_dos: Fix a NULL pointer error
  common: Allow a smaller console-recording pre-reloc
  dm: core: Add tests for stringlist functions
  dm: core: Fix handling of uclass pre_unbind method
  dm: core: Fix up string-function documentation
  dm: core: Add a way to obtain a string list
  dm: core: Allow finding children / uclasses by partial name
  dm: core: Add a way to count the devices in a uclass
  sandbox: Enable HEXDUMP for sandbox_flattree
  test/py: Relax the naming rules for unit tests
  test/py: Raise a ValueError if a command fails
  bootstd: Add the concept of a bootflow
  bootstd: Add the bootstd uclass and core implementation
  bootstd: Add the bootdev uclass
  bootstd: Add the bootmeth uclass and helpers
  bootstd: Add support for bootflows
  bootstd: Add a bootdev command
  bootstd: Add a bootflow ommand
  bootstd: Add a bootmeth command
  bootstd: Add an implementation of distro boot
  bootstd: mmc: Add a bootdev driver
  bootstd: ethernet: Add a bootdev driver
  bootstd: Add an implementation of distro PXE boot
  bootstd: Add an implementation of EFI boot
  bootstd: Add a system bootdev for strange boot methods
  bootstd: Add an implementation of EFI bootmgr
  bootstd: Add a sandbox bootmeth driver
  bootstd: usb: Add a bootdev driver
  test: fastboot: Avoid using mmc1
  test: dm: Restart USB before assuming it is stopped
  bootstd: Add tests for bootstd including all uclasses
  bootstd: Add setup for the bootflow tests
  bootstd: doc: Add documentation
  RFC: Switch rpi over to use bootstd

 MAINTAINERS                                  |  21 +
 Makefile                                     |  18 +-
 arch/arm/config.mk                           |   4 +-
 arch/arm/include/asm/global_data.h           |   2 +-
 arch/sandbox/cpu/os.c                        |  10 +
 arch/sandbox/dts/test.dts                    |  19 +
 boot/Kconfig                                 |  77 ++-
 boot/Makefile                                |  14 +
 boot/bootdev-uclass.c                        | 439 ++++++++++++++
 boot/bootflow.c                              | 576 ++++++++++++++++++
 boot/bootmeth-uclass.c                       |  59 ++
 boot/bootmeth_distro.c                       | 217 +++++++
 boot/bootmeth_efi.c                          | 263 ++++++++
 boot/bootmeth_efi_mgr.c                      |  84 +++
 boot/bootmeth_pxe.c                          | 183 ++++++
 boot/bootmeth_sandbox.c                      |  67 +++
 boot/bootstd-uclass.c                        | 176 ++++++
 boot/system_bootdev.c                        |  64 ++
 cmd/Kconfig                                  |  15 +
 cmd/Makefile                                 |   1 +
 cmd/bootdev.c                                | 120 ++++
 cmd/bootflow.c                               | 386 ++++++++++++
 cmd/bootmeth.c                               | 158 +++++
 cmd/mbr.c                                    |   8 +-
 common/Kconfig                               |  10 +
 common/console.c                             |   4 +-
 common/usb_storage.c                         |  12 +
 configs/amcore_defconfig                     |   1 +
 configs/rcar3_salvator-x_defconfig           |   1 +
 configs/sandbox_defconfig                    |   3 +-
 configs/sandbox_flattree_defconfig           |   4 +-
 configs/tbs2910_defconfig                    |   1 +
 disk/part_dos.c                              |  10 +-
 doc/build/gcc.rst                            |  17 +
 doc/develop/bootstd.rst                      | 600 +++++++++++++++++++
 doc/develop/distro.rst                       |   3 +
 doc/develop/index.rst                        |   1 +
 doc/device-tree-bindings/bootdev.txt         |  26 +
 doc/device-tree-bindings/bootmeth.txt        |  31 +
 doc/device-tree-bindings/bootstd.txt         |  36 ++
 doc/device-tree-bindings/mmc/sandbox,mmc.txt |  18 +
 doc/usage/bootdev.rst                        | 135 +++++
 doc/usage/bootflow.rst                       | 427 +++++++++++++
 doc/usage/bootmeth.rst                       | 106 ++++
 doc/usage/index.rst                          |   3 +
 drivers/core/device-remove.c                 |   9 +-
 drivers/core/device.c                        |  13 +-
 drivers/core/of_access.c                     |   3 +-
 drivers/core/ofnode.c                        |  26 +
 drivers/core/read.c                          |   6 +
 drivers/core/uclass.c                        |  29 +-
 drivers/mmc/Makefile                         |   5 +
 drivers/mmc/mmc-uclass.c                     |  27 +-
 drivers/mmc/mmc_bootdev.c                    |  62 ++
 drivers/mmc/sandbox_mmc.c                    |  60 +-
 drivers/usb/host/Makefile                    |   4 +
 drivers/usb/host/usb_bootdev.c               |  61 ++
 include/bootdev.h                            | 258 ++++++++
 include/bootflow.h                           | 304 ++++++++++
 include/bootmeth.h                           | 156 +++++
 include/bootstd.h                            |  80 +++
 include/configs/rpi.h                        |  41 +-
 include/distro.h                             |  24 +
 include/dm/device.h                          |  12 +
 include/dm/ofnode.h                          |  24 +-
 include/dm/read.h                            |  28 +
 include/dm/uclass-id.h                       |   3 +
 include/dm/uclass-internal.h                 |  14 +-
 include/dm/uclass.h                          |  17 +
 include/mmc.h                                |  12 +-
 include/os.h                                 |   9 +
 include/test/suites.h                        |   2 +
 include/vsprintf.h                           |  18 +
 lib/strto.c                                  |  14 +-
 net/Kconfig                                  |   9 +
 net/Makefile                                 |   1 +
 net/eth-uclass.c                             |   8 +
 net/eth_bootdev.c                            | 101 ++++
 test/Makefile                                |   1 +
 test/boot/Makefile                           |   5 +
 test/boot/bootdev.c                          | 200 +++++++
 test/boot/bootflow.c                         | 398 ++++++++++++
 test/boot/bootmeth.c                         |  90 +++
 test/boot/bootstd_common.c                   |  35 ++
 test/boot/bootstd_common.h                   |  27 +
 test/cmd_ut.c                                |   7 +
 test/dm/blk.c                                |   6 +
 test/dm/fastboot.c                           |   4 +-
 test/dm/ofnode.c                             |  96 +++
 test/py/conftest.py                          |   2 +-
 test/py/multiplexed_log.py                   |  10 +-
 test/py/tests/bootstd/mmc1.img.xz            | Bin 0 -> 4448 bytes
 test/py/tests/test_ut.py                     | 103 ++++
 test/py/u_boot_utils.py                      |   5 +-
 94 files changed, 6765 insertions(+), 94 deletions(-)
 create mode 100644 boot/bootdev-uclass.c
 create mode 100644 boot/bootflow.c
 create mode 100644 boot/bootmeth-uclass.c
 create mode 100644 boot/bootmeth_distro.c
 create mode 100644 boot/bootmeth_efi.c
 create mode 100644 boot/bootmeth_efi_mgr.c
 create mode 100644 boot/bootmeth_pxe.c
 create mode 100644 boot/bootmeth_sandbox.c
 create mode 100644 boot/bootstd-uclass.c
 create mode 100644 boot/system_bootdev.c
 create mode 100644 cmd/bootdev.c
 create mode 100644 cmd/bootflow.c
 create mode 100644 cmd/bootmeth.c
 create mode 100644 doc/develop/bootstd.rst
 create mode 100644 doc/device-tree-bindings/bootdev.txt
 create mode 100644 doc/device-tree-bindings/bootmeth.txt
 create mode 100644 doc/device-tree-bindings/bootstd.txt
 create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt
 create mode 100644 doc/usage/bootdev.rst
 create mode 100644 doc/usage/bootflow.rst
 create mode 100644 doc/usage/bootmeth.rst
 create mode 100644 drivers/mmc/mmc_bootdev.c
 create mode 100644 drivers/usb/host/usb_bootdev.c
 create mode 100644 include/bootdev.h
 create mode 100644 include/bootflow.h
 create mode 100644 include/bootmeth.h
 create mode 100644 include/bootstd.h
 create mode 100644 include/distro.h
 create mode 100644 net/eth_bootdev.c
 create mode 100644 test/boot/Makefile
 create mode 100644 test/boot/bootdev.c
 create mode 100644 test/boot/bootflow.c
 create mode 100644 test/boot/bootmeth.c
 create mode 100644 test/boot/bootstd_common.c
 create mode 100644 test/boot/bootstd_common.h
 create mode 100644 test/py/tests/bootstd/mmc1.img.xz

-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
@ 2021-10-23 23:25   ` Simon Glass
  2021-10-27 12:13     ` Heinrich Schuchardt
  2021-10-23 23:25   ` [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build Simon Glass
                     ` (56 subsequent siblings)
  57 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

At present it is not possible to find out which part of the string is the
number part and which is before it. Add a new variant which provides this
feature, so we can separate the two in the caller.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 include/vsprintf.h | 18 ++++++++++++++++++
 lib/strto.c        | 14 ++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index b4746301462..8230e7a5126 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -118,6 +118,24 @@ long trailing_strtol(const char *str);
  */
 long trailing_strtoln(const char *str, const char *end);
 
+/**
+ * trailing_strtoln() - extract a trailing integer from a fixed-length string
+ *
+ * Given a fixed-length string this finds a trailing number on the string
+ * and returns it. For example, "abc123" would return 123. Only the
+ * characters between @str and @end - 1 are examined. If @end is NULL, it is
+ * set to str + strlen(str).
+ *
+ * @str:	String to exxamine
+ * @end:	Pointer to end of string to examine, or NULL to use the
+ *		whole string
+ * @lenp:	If non-NULL, this is set to the number of characters before the
+ *	number starts, e.g. for "mmc0" this would be 3; if no trailing number is
+ *	found, it is set to the length of the whole string
+ * @return training number if found, else -1
+ */
+long trailing_strtoln_len(const char *str, const char *end, int *lenp);
+
 /**
  * panic() - Print a message and reset/hang
  *
diff --git a/lib/strto.c b/lib/strto.c
index 7bba1e3e549..13ae22a87a1 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -183,7 +183,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 	return simple_strtoull(cp, endp, base);
 }
 
-long trailing_strtoln(const char *str, const char *end)
+long trailing_strtoln_len(const char *str, const char *end, int *lenp)
 {
 	const char *p;
 
@@ -191,14 +191,24 @@ long trailing_strtoln(const char *str, const char *end)
 		end = str + strlen(str);
 	if (isdigit(end[-1])) {
 		for (p = end - 1; p > str; p--) {
-			if (!isdigit(*p))
+			if (!isdigit(*p)) {
+				if (lenp)
+					*lenp = p - str + 1;
 				return dectoul(p + 1, NULL);
+			}
 		}
 	}
+	if (lenp)
+		*lenp = end - str;
 
 	return -1;
 }
 
+long trailing_strtoln(const char *str, const char *end)
+{
+	return trailing_strtoln_len(str, end, NULL);
+}
+
 long trailing_strtol(const char *str)
 {
 	return trailing_strtoln(str, NULL);
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
  2021-10-23 23:25   ` [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number Simon Glass
@ 2021-10-23 23:25   ` Simon Glass
  2021-10-27  8:50     ` Ilias Apalodimas
  2021-10-23 23:25   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass
                     ` (55 subsequent siblings)
  57 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Masahiro Yamada

LTO (Link-Time Optimisation) is an very useful feature which can
significantly reduce the size of U-Boot binaries. So far it has been
made available for selected ARM boards and sandbox.

However, incremental builds are much slower when LTO is used. For example,
an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
seconds with LTO enabled.

Add a LTO_BUILD=n parameter to the build, so it can be disabled during
development if needed, for faster builds.

Add some documentation about LTO while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 Makefile                           | 18 +++++++++++++-----
 arch/arm/config.mk                 |  4 ++--
 arch/arm/include/asm/global_data.h |  2 +-
 doc/build/gcc.rst                  | 17 +++++++++++++++++
 4 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/Makefile b/Makefile
index b79b2319ff6..7057723e046 100644
--- a/Makefile
+++ b/Makefile
@@ -434,6 +434,9 @@ KBUILD_CFLAGS	+= -fshort-wchar -fno-strict-aliasing
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 KBUILD_LDFLAGS  :=
 
+# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
+LTO_BUILD	?= y
+
 ifeq ($(cc-name),clang)
 ifneq ($(CROSS_COMPILE),)
 CLANG_TARGET	:= --target=$(notdir $(CROSS_COMPILE:%-=%))
@@ -641,6 +644,11 @@ 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
+LTO_ENABLE=$(if $(CONFIG_LTO),$(LTO_BUILD),)
+
 # 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.
@@ -688,16 +696,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
@@ -1717,7 +1725,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))
 
@@ -1739,7 +1747,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 b107b1af27a..065dbec4064 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/global_data.h b/arch/arm/include/asm/global_data.h
index 085e12b5d4d..b255b195aa0 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -98,7 +98,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/doc/build/gcc.rst b/doc/build/gcc.rst
index cdd79700326..136c318727d 100644
--- a/doc/build/gcc.rst
+++ b/doc/build/gcc.rst
@@ -141,6 +141,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 `LTO_BUILD` to `n`.
+
+.. code-block:: bash
+
+    LTO_BUILD=n make
+
 Other build targets
 ~~~~~~~~~~~~~~~~~~~
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 03/41] test/py: Allow passing input to a program
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
  2021-10-23 23:25   ` [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number Simon Glass
  2021-10-23 23:25   ` [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build Simon Glass
@ 2021-10-23 23:25   ` Simon Glass
  2021-10-23 23:25   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
                     ` (54 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Stephen Warren,
	Stephen Warren

When running a program on the host, allow input to be passed in as stdin.
This is needed for running sfdisk, for example.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/multiplexed_log.py | 8 +++++---
 test/py/u_boot_utils.py    | 5 +++--
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py
index 545a7743022..9325fae46d2 100644
--- a/test/py/multiplexed_log.py
+++ b/test/py/multiplexed_log.py
@@ -109,7 +109,7 @@ class RunAndLog(object):
         """Clean up any resources managed by this object."""
         pass
 
-    def run(self, cmd, cwd=None, ignore_errors=False):
+    def run(self, cmd, cwd=None, ignore_errors=False, stdin=None):
         """Run a command as a sub-process, and log the results.
 
         The output is available at self.output which can be useful if there is
@@ -123,6 +123,7 @@ class RunAndLog(object):
                 function will simply return if the command cannot be executed
                 or exits with an error code, otherwise an exception will be
                 raised if such problems occur.
+            stdin: Input string to pass to the command as stdin (or None)
 
         Returns:
             The output as a string.
@@ -135,8 +136,9 @@ class RunAndLog(object):
 
         try:
             p = subprocess.Popen(cmd, cwd=cwd,
-                stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-            (stdout, stderr) = p.communicate()
+                stdin=subprocess.PIPE if stdin else None,
+                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+            (stdout, stderr) = p.communicate(input=stdin)
             if stdout is not None:
                 stdout = stdout.decode('utf-8')
             if stderr is not None:
diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py
index e816c7fbb6a..f44442e0c77 100644
--- a/test/py/u_boot_utils.py
+++ b/test/py/u_boot_utils.py
@@ -154,7 +154,7 @@ def wait_until_file_open_fails(fn, ignore_errors):
         return
     raise Exception('File can still be opened')
 
-def run_and_log(u_boot_console, cmd, ignore_errors=False):
+def run_and_log(u_boot_console, cmd, ignore_errors=False, stdin=None):
     """Run a command and log its output.
 
     Args:
@@ -166,6 +166,7 @@ def run_and_log(u_boot_console, cmd, ignore_errors=False):
             will simply return if the command cannot be executed or exits with
             an error code, otherwise an exception will be raised if such
             problems occur.
+        stdin: Input string to pass to the command as stdin (or None)
 
     Returns:
         The output as a string.
@@ -173,7 +174,7 @@ def run_and_log(u_boot_console, cmd, ignore_errors=False):
     if isinstance(cmd, str):
         cmd = cmd.split()
     runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
-    output = runner.run(cmd, ignore_errors=ignore_errors)
+    output = runner.run(cmd, ignore_errors=ignore_errors, stdin=stdin)
     runner.close()
     return output
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 04/41] sandbox: Support unmapping a file
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (2 preceding siblings ...)
  2021-10-23 23:25   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass
@ 2021-10-23 23:25   ` Simon Glass
  2021-10-23 23:25   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
                     ` (53 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add the opposite of mapping, so that we can unmap and avoid running out of
address space.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/sandbox/cpu/os.c | 10 ++++++++++
 include/os.h          |  9 +++++++++
 2 files changed, 19 insertions(+)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index b72dafca2ba..873f85ac3be 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -211,6 +211,16 @@ int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep)
 	return 0;
 }
 
+int os_unmap(void *buf, int size)
+{
+	if (munmap(buf, size)) {
+		printf("Can't unmap %p %x\n", buf, size);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 /* Restore tty state when we exit */
 static struct termios orig_term;
 static bool term_setup;
diff --git a/include/os.h b/include/os.h
index 770d76e02f7..4cbcbd93a71 100644
--- a/include/os.h
+++ b/include/os.h
@@ -419,6 +419,15 @@ int os_read_file(const char *name, void **bufp, int *sizep);
  */
 int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep);
 
+/**
+ * os_unmap() - Unmap a file previously mapped
+ *
+ * @buf: Mapped address
+ * @size: Size in bytes
+ * Return:	0 if OK, -ve on error
+ */
+int os_unmap(void *buf, int size);
+
 /*
  * os_find_text_base() - Find the text section in this running process
  *
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 05/41] sandbox: mmc: Support a backing file
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (3 preceding siblings ...)
  2021-10-23 23:25   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
@ 2021-10-23 23:25   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
                     ` (52 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:25 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Jaehoon Chung, Peng Fan

Provide a way for sandbox MMC to present data from a backing file. This
allows a filesystem to be created on the host and easily served via an
emulated mmc device.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v2:
- Free the memory buffer, to avoid running out of memory
- Unmap the file
- Reorder struct sandbox_mmc_priv

 doc/device-tree-bindings/mmc/sandbox,mmc.txt | 18 ++++++
 drivers/mmc/sandbox_mmc.c                    | 60 +++++++++++++++++---
 2 files changed, 69 insertions(+), 9 deletions(-)
 create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt

diff --git a/doc/device-tree-bindings/mmc/sandbox,mmc.txt b/doc/device-tree-bindings/mmc/sandbox,mmc.txt
new file mode 100644
index 00000000000..1170bcd6a00
--- /dev/null
+++ b/doc/device-tree-bindings/mmc/sandbox,mmc.txt
@@ -0,0 +1,18 @@
+Sandbox MMC
+===========
+
+Required properties:
+- compatible : "sandbox,mmc"
+
+Optional properties:
+- filename : Name of backing file, if any. This is mapped into the MMC device
+    so can be used to provide a filesystem or other test data
+
+
+Example
+-------
+
+mmc2 {
+	compatible = "sandbox,mmc";
+	non-removable;
+};
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 895fbffecfc..451fe4a4e5a 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -9,23 +9,26 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <log.h>
+#include <malloc.h>
 #include <mmc.h>
+#include <os.h>
 #include <asm/test.h>
 
 struct sandbox_mmc_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
+	const char *fname;
 };
 
-#define MMC_CSIZE 0
-#define MMC_CMULT 8 /* 8 because the card is high-capacity */
-#define MMC_BL_LEN_SHIFT 10
-#define MMC_BL_LEN BIT(MMC_BL_LEN_SHIFT)
-#define MMC_CAPACITY (((MMC_CSIZE + 1) << (MMC_CMULT + 2)) \
-		      * MMC_BL_LEN) /* 1 MiB */
+#define MMC_CMULT		8 /* 8 because the card is high-capacity */
+#define MMC_BL_LEN_SHIFT	10
+#define MMC_BL_LEN		BIT(MMC_BL_LEN_SHIFT)
+#define SIZE_MULTIPLE		((1 << (MMC_CMULT + 2)) * MMC_BL_LEN)
 
 struct sandbox_mmc_priv {
-	u8 buf[MMC_CAPACITY];
+	char *buf;
+	int csize;	/* CSIZE value to report */
+	int size;
 };
 
 /**
@@ -60,8 +63,8 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 	case MMC_CMD_SEND_CSD:
 		cmd->response[0] = 0;
 		cmd->response[1] = (MMC_BL_LEN_SHIFT << 16) |
-				   ((MMC_CSIZE >> 16) & 0x3f);
-		cmd->response[2] = (MMC_CSIZE & 0xffff) << 16;
+				   ((priv->csize >> 16) & 0x3f);
+		cmd->response[2] = (priv->csize & 0xffff) << 16;
 		cmd->response[3] = 0;
 		break;
 	case SD_CMD_SWITCH_FUNC: {
@@ -143,6 +146,8 @@ static int sandbox_mmc_of_to_plat(struct udevice *dev)
 	struct blk_desc *blk;
 	int ret;
 
+	plat->fname = dev_read_string(dev, "filename");
+
 	ret = mmc_of_parse(dev, cfg);
 	if (ret)
 		return ret;
@@ -156,10 +161,46 @@ static int sandbox_mmc_of_to_plat(struct udevice *dev)
 static int sandbox_mmc_probe(struct udevice *dev)
 {
 	struct sandbox_mmc_plat *plat = dev_get_plat(dev);
+	struct sandbox_mmc_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (plat->fname) {
+		ret = os_map_file(plat->fname, OS_O_RDWR | OS_O_CREAT,
+				  (void **)&priv->buf, &priv->size);
+		if (ret) {
+			log_err("%s: Unable to map file '%s'\n", dev->name,
+				plat->fname);
+			return ret;
+		}
+		priv->csize = priv->size / SIZE_MULTIPLE - 1;
+	} else {
+		priv->csize = 0;
+		priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */
+
+		priv->buf = malloc(priv->size);
+		if (!priv->buf) {
+			log_err("%s: Not enough memory (%x bytes)\n",
+				dev->name, priv->size);
+			return -ENOMEM;
+		}
+	}
 
 	return mmc_init(&plat->mmc);
 }
 
+static int sandbox_mmc_remove(struct udevice *dev)
+{
+	struct sandbox_mmc_plat *plat = dev_get_plat(dev);
+	struct sandbox_mmc_priv *priv = dev_get_priv(dev);
+
+	if (plat->fname)
+		os_unmap(priv->buf, priv->size);
+	else
+		free(priv->buf);
+
+	return 0;
+}
+
 static int sandbox_mmc_bind(struct udevice *dev)
 {
 	struct sandbox_mmc_plat *plat = dev_get_plat(dev);
@@ -196,6 +237,7 @@ U_BOOT_DRIVER(mmc_sandbox) = {
 	.unbind		= sandbox_mmc_unbind,
 	.of_to_plat	= sandbox_mmc_of_to_plat,
 	.probe		= sandbox_mmc_probe,
+	.remove		= sandbox_mmc_remove,
 	.priv_auto = sizeof(struct sandbox_mmc_priv),
 	.plat_auto = sizeof(struct sandbox_mmc_plat),
 };
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 06/41] mmc: Allow for children other than the block device
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (4 preceding siblings ...)
  2021-10-23 23:25   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 07/41] mbr: Correct verification check Simon Glass
                     ` (51 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Jaehoon Chung, Peng Fan

At present the MMC uclass assumes that the only child it can have is a
block device. Update this so we can add a bootmethod too.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/mmc/mmc-uclass.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 3ee92d03ca2..b80e838066c 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -320,7 +320,7 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
 	struct blk_desc *desc;
 	struct udevice *dev;
 
-	device_find_first_child(mmc->dev, &dev);
+	device_find_first_child_by_uclass(mmc->dev, UCLASS_BLK, &dev);
 	if (!dev)
 		return NULL;
 	desc = dev_get_uclass_plat(dev);
@@ -425,7 +425,7 @@ int mmc_unbind(struct udevice *dev)
 {
 	struct udevice *bdev;
 
-	device_find_first_child(dev, &bdev);
+	device_find_first_child_by_uclass(dev, UCLASS_BLK, &bdev);
 	if (bdev) {
 		device_remove(bdev, DM_REMOVE_NORMAL);
 		device_unbind(bdev);
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 07/41] mbr: Correct verification check
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (5 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-27  7:41     ` Ilias Apalodimas
  2021-11-24 22:22     ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
                     ` (50 subsequent siblings)
  57 siblings, 2 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

At present this command considers the partitions to be identical if the
start and size are smaller than expected. It should check that they are
the same. Fix this and tidy up the code style a little.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 cmd/mbr.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/cmd/mbr.c b/cmd/mbr.c
index e7e22980969..c269833eb82 100644
--- a/cmd/mbr.c
+++ b/cmd/mbr.c
@@ -244,12 +244,12 @@ static int do_verify_mbr(struct blk_desc *dev, const char *str)
 	for (i = 0; i < count; i++) {
 		struct disk_partition p;
 
-		if (part_get_info(dev, i+1, &p))
+		if (part_get_info(dev, i + 1, &p))
 			goto fail;
 
-		if ((partitions[i].size && p.size < partitions[i].size) ||
-		    (partitions[i].start && p.start < partitions[i].start) ||
-		    (p.sys_ind != partitions[i].sys_ind))
+		if ((partitions[i].size && p.size != partitions[i].size) ||
+		    (partitions[i].start && p.start != partitions[i].start) ||
+		    p.sys_ind != partitions[i].sys_ind)
 			goto fail;
 	}
 	ret = 0;
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (6 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 07/41] mbr: Correct verification check Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
                     ` (49 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

When ext is NULL we cannot dereference it. Update the code flow to avoid
this, so that layout_mbr_partitions() can be used with partition tables
that do not include an extended partition.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 disk/part_dos.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/disk/part_dos.c b/disk/part_dos.c
index 9e29aa6583a..94fae7166d7 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -459,10 +459,12 @@ int layout_mbr_partitions(struct disk_partition *p, int count,
 			ext = &p[i];
 	}
 
-	if (i >= 4 && !ext) {
-		printf("%s: extended partition is needed for more than 4 partitions\n",
-		        __func__);
-		return -1;
+	if (count < 4)
+		return 0;
+
+	if (!ext) {
+		log_err("extended partition is needed for more than 4 partitions\n");
+		return -EINVAL;
 	}
 
 	/* calculate extended volumes start and size if needed */
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (7 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
                     ` (48 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Before relocation there is generally not as much available memory and not
that much console output. At present the console-output buffer is the same
side before and after relocation. Add a separate Kconfig option to remove
this limitation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 common/Kconfig   | 10 ++++++++++
 common/console.c |  4 +++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/common/Kconfig b/common/Kconfig
index fdcf4536d0f..fede7e40215 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -32,6 +32,16 @@ config CONSOLE_RECORD_OUT_SIZE
 	  more data will be recorded until some is removed. The buffer is
 	  allocated immediately after the malloc() region is ready.
 
+config CONSOLE_RECORD_OUT_SIZE_F
+	hex "Output buffer size before relocation"
+	depends on CONSOLE_RECORD
+	default 0x400 if CONSOLE_RECORD
+	help
+	  Set the size of the console output buffer before relocation. When
+	  this fills up, no more data will be recorded until some is removed.
+	  The buffer is allocated immediately after the early malloc() region is
+	  ready.
+
 config CONSOLE_RECORD_IN_SIZE
 	hex "Input buffer size"
 	depends on CONSOLE_RECORD
diff --git a/common/console.c b/common/console.c
index 0013d183aeb..0c9099ca52a 100644
--- a/common/console.c
+++ b/common/console.c
@@ -735,7 +735,9 @@ int console_record_init(void)
 	int ret;
 
 	ret = membuff_new((struct membuff *)&gd->console_out,
-			  CONFIG_CONSOLE_RECORD_OUT_SIZE);
+			  gd->flags & GD_FLG_RELOC ?
+				  CONFIG_CONSOLE_RECORD_OUT_SIZE :
+				  CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
 	if (ret)
 		return ret;
 	ret = membuff_new((struct membuff *)&gd->console_in,
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 10/41] dm: core: Add tests for stringlist functions
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (8 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
                     ` (47 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

These functions currently lack tests so add some. The error handling
differs betwee livetree and flattree at present, so only check the error
codes with livetree.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/sandbox/dts/test.dts |  1 +
 test/dm/ofnode.c          | 76 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e27d106466b..07a5118babe 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -207,6 +207,7 @@
 		test4-gpios = <&gpio_a 14>, <&gpio_b 4 1 3 2 1>;
 		test5-gpios = <&gpio_a 19>;
 
+		bool-value;
 		int-value = <1234>;
 		uint-value = <(-1234)>;
 		int64-value = /bits/ 64 <0x1111222233334444>;
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 49efabe871c..537028ca8fc 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -333,3 +333,79 @@ static int dm_test_ofnode_conf(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_ofnode_conf, 0);
+
+static int dm_test_ofnode_string(struct unit_test_state *uts)
+{
+	const char *out;
+	ofnode node;
+
+	node = ofnode_path("/a-test");
+	ut_assert(ofnode_valid(node));
+
+	/* single string */
+	ut_asserteq(1, ofnode_read_string_count(node, "str-value"));
+	ut_assertok(ofnode_read_string_index(node, "str-value", 0, &out));
+	ut_asserteq_str("test string", out);
+	ut_asserteq(0, ofnode_stringlist_search(node, "str-value",
+						"test string"));
+
+	/* list of strings */
+	ut_asserteq(5, ofnode_read_string_count(node, "mux-control-names"));
+	ut_assertok(ofnode_read_string_index(node, "mux-control-names", 0,
+					     &out));
+	ut_asserteq_str("mux0", out);
+	ut_asserteq(0, ofnode_stringlist_search(node, "mux-control-names",
+						"mux0"));
+
+	ut_assertok(ofnode_read_string_index(node, "mux-control-names", 4,
+					     &out));
+	ut_asserteq_str("mux4", out);
+	ut_asserteq(4, ofnode_stringlist_search(node, "mux-control-names",
+						"mux4"));
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_string, 0);
+
+static int dm_test_ofnode_string_err(struct unit_test_state *uts)
+{
+	const char *out;
+	ofnode node;
+
+	/*
+	 * Test error codes only on livetree, as they are different with
+	 * flattree
+	 */
+	node = ofnode_path("/a-test");
+	ut_assert(ofnode_valid(node));
+
+	/* non-existent property */
+	ut_asserteq(-EINVAL, ofnode_read_string_count(node, "missing"));
+	ut_asserteq(-EINVAL, ofnode_read_string_index(node, "missing", 0,
+						      &out));
+
+	/* empty property */
+	ut_asserteq(-ENODATA, ofnode_read_string_count(node, "bool-value"));
+	ut_asserteq(-ENODATA, ofnode_read_string_index(node, "bool-value", 0,
+						       &out));
+
+	/* badly formatted string list */
+	ut_asserteq(-EILSEQ, ofnode_read_string_count(node, "int64-value"));
+	ut_asserteq(-EILSEQ, ofnode_read_string_index(node, "int64-value", 0,
+						       &out));
+
+	/* out of range / not found */
+	ut_asserteq(-ENODATA, ofnode_read_string_index(node, "str-value", 1,
+						       &out));
+	ut_asserteq(-ENODATA, ofnode_stringlist_search(node, "str-value",
+						       "other"));
+
+	/* negative value for index is not allowed, so don't test for that */
+
+	ut_asserteq(-ENODATA, ofnode_read_string_index(node,
+						       "mux-control-names", 5,
+						       &out));
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_string_err, UT_TESTF_LIVE_TREE);
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (9 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
                     ` (46 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

This method is currently called after the platform data has been freed.
But the pre_unbind() method may wish to access this, e.g. to free some
data structures stored there.

Split the unbinding of devices into two pieces, as is done with removal.
This corrects the problem.

Also tidy a code-style issue in device_remove() while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/device-remove.c |  9 +++++----
 drivers/core/uclass.c        |  8 +++++++-
 include/dm/uclass-internal.h | 14 +++++++++++++-
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 11d3959d20f..69c50da44a9 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -95,6 +95,9 @@ int device_unbind(struct udevice *dev)
 	if (ret)
 		return log_msg_ret("child unbind", ret);
 
+	ret = uclass_pre_unbind_device(dev);
+	if (ret)
+		return log_msg_ret("uc", ret);
 	if (dev_get_flags(dev) & DM_FLAG_ALLOC_PDATA) {
 		free(dev_get_plat(dev));
 		dev_set_plat(dev, NULL);
@@ -142,10 +145,8 @@ void device_free(struct udevice *dev)
 	}
 	if (dev->parent) {
 		size = dev->parent->driver->per_child_auto;
-		if (!size) {
-			size = dev->parent->uclass->uc_drv->
-					per_child_auto;
-		}
+		if (!size)
+			size = dev->parent->uclass->uc_drv->per_child_auto;
 		if (size) {
 			free(dev_get_parent_priv(dev));
 			dev_set_parent_priv(dev, NULL);
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index c5a50952fd0..2fede896bfb 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -682,7 +682,7 @@ err:
 }
 
 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
-int uclass_unbind_device(struct udevice *dev)
+int uclass_pre_unbind_device(struct udevice *dev)
 {
 	struct uclass *uc;
 	int ret;
@@ -694,7 +694,13 @@ int uclass_unbind_device(struct udevice *dev)
 			return ret;
 	}
 
+	return 0;
+}
+
+int uclass_unbind_device(struct udevice *dev)
+{
 	list_del(&dev->uclass_node);
+
 	return 0;
 }
 #endif
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 57c664c6daa..49808c5c856 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -243,6 +243,17 @@ int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
  */
 int uclass_bind_device(struct udevice *dev);
 
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+/**
+ * uclass_pre_unbind_device() - Prepare to deassociate device with a uclass
+ *
+ * Call any handled needed before uclass_unbind_device() is called
+ *
+ * @dev:	Pointer to the device
+ * #return 0 on success, -ve on error
+ */
+int uclass_pre_unbind_device(struct udevice *dev);
+
 /**
  * uclass_unbind_device() - Deassociate device with a uclass
  *
@@ -251,9 +262,10 @@ int uclass_bind_device(struct udevice *dev);
  * @dev:	Pointer to the device
  * #return 0 on success, -ve on error
  */
-#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
 int uclass_unbind_device(struct udevice *dev);
+
 #else
+static inline int uclass_pre_unbind_device(struct udevice *dev) { return 0; }
 static inline int uclass_unbind_device(struct udevice *dev) { return 0; }
 #endif
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 12/41] dm: core: Fix up string-function documentation
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (10 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 13/41] dm: core: Add a way to obtain a string list Simon Glass
                     ` (45 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

The details for of_property_read_string_helper() and
ofnode_read_string_index() are a little inaccurate. Fix up the comments to
avoid confusion.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/of_access.c | 3 ++-
 include/dm/ofnode.h      | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 9960e6b310b..3707143ae66 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -581,7 +581,8 @@ int of_property_match_string(const struct device_node *np, const char *propname,
  * @propname:	name of the property to be searched.
  * @out_strs:	output array of string pointers.
  * @sz:		number of array elements to read.
- * @skip:	Number of strings to skip over at beginning of list.
+ * @skip:	Number of strings to skip over at beginning of list (cannot be
+ *	negative)
  *
  * Don't call this function directly. It is a utility helper for the
  * of_property_read_string*() family of functions.
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 6a714d0c7b5..4faa9bfa563 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -590,11 +590,11 @@ int ofnode_stringlist_search(ofnode node, const char *propname,
  *
  * @node: node to check
  * @propname: name of the property containing the string list
- * @index: index of the string to return
+ * @index: index of the string to return (cannot be negative)
  * @lenp: return location for the string length or an error code on failure
  *
  * @return:
- *   length of string, if found or -ve error value if not found
+ *   0 if found or -ve error value if not found
  */
 int ofnode_read_string_index(ofnode node, const char *propname, int index,
 			     const char **outp);
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 13/41] dm: core: Add a way to obtain a string list
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (11 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-26 19:20     ` Ilias Apalodimas
  2021-10-23 23:26   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
                     ` (44 subsequent siblings)
  57 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

At present we support reading a string list a string at a time. Apart
from being inefficient, this makes it impossible to separate reading of
the devicetree into the of_to_plat() method where it belongs, since any
code which needs access to the string must read it from the devicetree.

Add a function which returns the string property as an array of pointers
to the strings, which is easily used by clients.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/ofnode.c | 26 ++++++++++++++++++++++++++
 drivers/core/read.c   |  6 ++++++
 include/dm/ofnode.h   | 20 ++++++++++++++++++++
 include/dm/read.h     | 28 ++++++++++++++++++++++++++++
 test/dm/ofnode.c      | 20 ++++++++++++++++++++
 5 files changed, 100 insertions(+)

diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 08705ef8d99..709bea272a6 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -456,6 +456,32 @@ int ofnode_read_string_count(ofnode node, const char *property)
 	}
 }
 
+int ofnode_read_string_list(ofnode node, const char *property,
+			    const char ***listp)
+{
+	const char **prop;
+	int count;
+	int i;
+
+	*listp = NULL;
+	count = ofnode_read_string_count(node, property);
+	if (count < 0)
+		return count;
+	if (!count)
+		return 0;
+
+	prop = calloc(count + 1, sizeof(char *));
+	if (!prop)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++)
+		ofnode_read_string_index(node, property, i, &prop[i]);
+	prop[count] = NULL;
+	*listp = prop;
+
+	return count;
+}
+
 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
 					    struct ofnode_phandle_args *out)
 {
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 4307ca45799..31f9e78a062 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -205,6 +205,12 @@ int dev_read_string_count(const struct udevice *dev, const char *propname)
 	return ofnode_read_string_count(dev_ofnode(dev), propname);
 }
 
+int dev_read_string_list(const struct udevice *dev, const char *propname,
+			 const char ***listp)
+{
+	return ofnode_read_string_list(dev_ofnode(dev), propname, listp);
+}
+
 int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name,
 			       const char *cells_name, int cell_count,
 			       int index, struct ofnode_phandle_args *out_args)
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 4faa9bfa563..f2b5b9c2d33 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -609,6 +609,26 @@ int ofnode_read_string_index(ofnode node, const char *propname, int index,
  */
 int ofnode_read_string_count(ofnode node, const char *property);
 
+/**
+ * ofnode_read_string_list() - read a list of strings
+ *
+ * This produces a list of string pointers with each one pointing to a string
+ * in the string list. If the property does not exist, it returns {NULL}.
+ *
+ * The data is allocated and the caller is reponsible for freeing the return
+ * value (the list of string pointers). The strings themselves may not be
+ * changed as they point directly into the devicetree property.
+ *
+ * @node: node to check
+ * @listp: returns an allocated, NULL-terminated list of strings if the return
+ *	value is > 0, else is set to NULL
+ * @return number of strings in list, 0 if none, -ENOMEM if out of memory,
+ *	-EINVAL if no such property, -EENODATA if property is empty
+ * @return: NULL-terminated list of strings (NULL if no property or empty)
+ */
+int ofnode_read_string_list(ofnode node, const char *property,
+			    const char ***listp);
+
 /**
  * ofnode_parse_phandle_with_args() - Find a node pointed by phandle in a list
  *
diff --git a/include/dm/read.h b/include/dm/read.h
index 890bf3d8472..75c6ad6ee49 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -371,6 +371,27 @@ int dev_read_string_index(const struct udevice *dev, const char *propname,
  *   number of strings in the list, or -ve error value if not found
  */
 int dev_read_string_count(const struct udevice *dev, const char *propname);
+
+/**
+ * dev_read_string_list() - read a list of strings
+ *
+ * This produces a list of string pointers with each one pointing to a string
+ * in the string list. If the property does not exist, it returns {NULL}.
+ *
+ * The data is allocated and the caller is reponsible for freeing the return
+ * value (the list of string pointers). The strings themselves may not be
+ * changed as they point directly into the devicetree property.
+ *
+ * @dev: device to examine
+ * @propname: name of the property containing the string list
+ * @listp: returns an allocated, NULL-terminated list of strings if the return
+ *	value is > 0, else is set to NULL
+ * @return number of strings in list, 0 if none, -ENOMEM if out of memory,
+ *	-ENOENT if no such property
+ */
+int dev_read_string_list(const struct udevice *dev, const char *propname,
+			 const char ***listp);
+
 /**
  * dev_read_phandle_with_args() - Find a node pointed by phandle in a list
  *
@@ -906,6 +927,13 @@ static inline int dev_read_string_count(const struct udevice *dev,
 	return ofnode_read_string_count(dev_ofnode(dev), propname);
 }
 
+static inline int dev_read_string_list(const struct udevice *dev,
+				       const char *propname,
+				       const char ***listp)
+{
+	return ofnode_read_string_list(dev_ofnode(dev), propname, listp);
+}
+
 static inline int dev_read_phandle_with_args(const struct udevice *dev,
 		const char *list_name, const char *cells_name, int cell_count,
 		int index, struct ofnode_phandle_args *out_args)
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 537028ca8fc..470cbce4c2e 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -336,6 +336,7 @@ DM_TEST(dm_test_ofnode_conf, 0);
 
 static int dm_test_ofnode_string(struct unit_test_state *uts)
 {
+	const char **val;
 	const char *out;
 	ofnode node;
 
@@ -348,6 +349,10 @@ static int dm_test_ofnode_string(struct unit_test_state *uts)
 	ut_asserteq_str("test string", out);
 	ut_asserteq(0, ofnode_stringlist_search(node, "str-value",
 						"test string"));
+	ut_asserteq(1, ofnode_read_string_list(node, "str-value", &val));
+	ut_asserteq_str("test string", val[0]);
+	ut_assertnull(val[1]);
+	free(val);
 
 	/* list of strings */
 	ut_asserteq(5, ofnode_read_string_count(node, "mux-control-names"));
@@ -356,6 +361,15 @@ static int dm_test_ofnode_string(struct unit_test_state *uts)
 	ut_asserteq_str("mux0", out);
 	ut_asserteq(0, ofnode_stringlist_search(node, "mux-control-names",
 						"mux0"));
+	ut_asserteq(5, ofnode_read_string_list(node, "mux-control-names",
+					       &val));
+	ut_asserteq_str("mux0", val[0]);
+	ut_asserteq_str("mux1", val[1]);
+	ut_asserteq_str("mux2", val[2]);
+	ut_asserteq_str("mux3", val[3]);
+	ut_asserteq_str("mux4", val[4]);
+	ut_assertnull(val[5]);
+	free(val);
 
 	ut_assertok(ofnode_read_string_index(node, "mux-control-names", 4,
 					     &out));
@@ -369,6 +383,7 @@ DM_TEST(dm_test_ofnode_string, 0);
 
 static int dm_test_ofnode_string_err(struct unit_test_state *uts)
 {
+	const char **val;
 	const char *out;
 	ofnode node;
 
@@ -383,16 +398,21 @@ static int dm_test_ofnode_string_err(struct unit_test_state *uts)
 	ut_asserteq(-EINVAL, ofnode_read_string_count(node, "missing"));
 	ut_asserteq(-EINVAL, ofnode_read_string_index(node, "missing", 0,
 						      &out));
+	ut_asserteq(-EINVAL, ofnode_read_string_list(node, "missing", &val));
 
 	/* empty property */
 	ut_asserteq(-ENODATA, ofnode_read_string_count(node, "bool-value"));
 	ut_asserteq(-ENODATA, ofnode_read_string_index(node, "bool-value", 0,
 						       &out));
+	ut_asserteq(-ENODATA, ofnode_read_string_list(node, "bool-value",
+						     &val));
 
 	/* badly formatted string list */
 	ut_asserteq(-EILSEQ, ofnode_read_string_count(node, "int64-value"));
 	ut_asserteq(-EILSEQ, ofnode_read_string_index(node, "int64-value", 0,
 						       &out));
+	ut_asserteq(-EILSEQ, ofnode_read_string_list(node, "int64-value",
+						     &val));
 
 	/* out of range / not found */
 	ut_asserteq(-ENODATA, ofnode_read_string_index(node, "str-value", 1,
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (12 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 13/41] dm: core: Add a way to obtain a string list Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
                     ` (43 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

In some cases it is useful to search just by a partial name, such as
when looking for a sibling device that has a common name substring. Add
helper functions to handle these requirements.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/device.c | 13 ++++++++++---
 drivers/core/uclass.c |  9 +++++++--
 include/dm/device.h   | 12 ++++++++++++
 include/dm/uclass.h   |  9 +++++++++
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index d7a778a2413..77e30dcd0db 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -894,15 +894,16 @@ int device_find_first_child_by_uclass(const struct udevice *parent,
 	return -ENODEV;
 }
 
-int device_find_child_by_name(const struct udevice *parent, const char *name,
-			      struct udevice **devp)
+int device_find_child_by_namelen(const struct udevice *parent, const char *name,
+				 int len, struct udevice **devp)
 {
 	struct udevice *dev;
 
 	*devp = NULL;
 
 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
-		if (!strcmp(dev->name, name)) {
+		if (!strncmp(dev->name, name, len) &&
+		    strlen(dev->name) == len) {
 			*devp = dev;
 			return 0;
 		}
@@ -911,6 +912,12 @@ int device_find_child_by_name(const struct udevice *parent, const char *name,
 	return -ENODEV;
 }
 
+int device_find_child_by_name(const struct udevice *parent, const char *name,
+			      struct udevice **devp)
+{
+	return device_find_child_by_namelen(parent, name, strlen(name), devp);
+}
+
 int device_first_child_err(struct udevice *parent, struct udevice **devp)
 {
 	struct udevice *dev;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 2fede896bfb..3de5f27fe4a 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -180,20 +180,25 @@ void uclass_set_priv(struct uclass *uc, void *priv)
 	uc->priv_ = priv;
 }
 
-enum uclass_id uclass_get_by_name(const char *name)
+enum uclass_id uclass_get_by_name_len(const char *name, int len)
 {
 	int i;
 
 	for (i = 0; i < UCLASS_COUNT; i++) {
 		struct uclass_driver *uc_drv = lists_uclass_lookup(i);
 
-		if (uc_drv && !strcmp(uc_drv->name, name))
+		if (uc_drv && !strncmp(uc_drv->name, name, len))
 			return i;
 	}
 
 	return UCLASS_INVALID;
 }
 
+enum uclass_id uclass_get_by_name(const char *name)
+{
+	return uclass_get_by_name_len(name, strlen(name));
+}
+
 int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp)
 {
 	struct udevice *iter;
diff --git a/include/dm/device.h b/include/dm/device.h
index 3028d002ab0..daf28a0a457 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -758,6 +758,18 @@ int device_find_first_child_by_uclass(const struct udevice *parent,
 				      enum uclass_id uclass_id,
 				      struct udevice **devp);
 
+/**
+ * device_find_child_by_name() - Find a child by device name
+ *
+ * @parent:	Parent device to search
+ * @name:	Name to look for
+ * @len:	Length of the name
+ * @devp:	Returns device found, if any
+ * @return 0 if found, else -ENODEV
+ */
+int device_find_child_by_namelen(const struct udevice *parent, const char *name,
+				 int len, struct udevice **devp);
+
 /**
  * device_find_child_by_name() - Find a child by device name
  *
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 15e5f9ef5bc..aea2f34fce1 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -172,6 +172,15 @@ int uclass_get(enum uclass_id key, struct uclass **ucp);
  */
 const char *uclass_get_name(enum uclass_id id);
 
+/**
+ * uclass_get_by_name() - Look up a uclass by its driver name
+ *
+ * @name: Name to look up
+ * @len: Length of name
+ * @returns the associated uclass ID, or UCLASS_INVALID if not found
+ */
+enum uclass_id uclass_get_by_name_len(const char *name, int len);
+
 /**
  * uclass_get_by_name() - Look up a uclass by its driver name
  *
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (13 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
                     ` (42 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

Add a function that returns the number of devices in a uclass. This can be
helpful in sizing an array that needs to hold a list of them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/uclass.c | 12 ++++++++++++
 include/dm/uclass.h   |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 3de5f27fe4a..2aa21430775 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -794,6 +794,18 @@ int uclass_probe_all(enum uclass_id id)
 	return 0;
 }
 
+int uclass_id_count(enum uclass_id id)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int count = 0;
+
+	uclass_id_foreach_dev(id, dev, uc)
+		count++;
+
+	return count;
+}
+
 UCLASS_DRIVER(nop) = {
 	.id		= UCLASS_NOP,
 	.name		= "nop",
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index aea2f34fce1..f1fd2ba2463 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -425,6 +425,14 @@ int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data,
  */
 int uclass_probe_all(enum uclass_id id);
 
+/**
+ * uclass_id_count() - Count the number of devices in a uclass
+ *
+ * @id: uclass ID to look up
+ * @return number of devices in that uclass (0 if none)
+ */
+int uclass_id_count(enum uclass_id id);
+
 /**
  * uclass_id_foreach_dev() - Helper function to iteration through devices
  *
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (14 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
                     ` (41 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

At present the hexdump tests are disabled in sandbox_flattree. This is
good, because they do not pass. Enable the required Kconfig so that they
will, when enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 configs/sandbox_flattree_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 11015744e7a..be129133d3d 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -202,6 +202,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y
 CONFIG_TPM=y
 CONFIG_LZ4=y
 CONFIG_ERRNO_STR=y
+CONFIG_HEXDUMP=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 17/41] test/py: Relax the naming rules for unit tests
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (15 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
                     ` (40 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Stephen Warren,
	Stephen Warren

At present the collection function used by pytest is quite strict on the
naming of the functions it detects. In particular it requires the name of
the test to be repeated in the function name.

This is not enforced anywhere else, but instead the tests are silently
omitted from the pytest run. This affects a few dozen tests.

The rule does not seem to have any particular purpose. Relax it, so that
all tests that use the UNIT_TEST() macro will run, regardless of the name
of the test function.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/conftest.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/py/conftest.py b/test/py/conftest.py
index 11a3f307ea8..16e445cd8ee 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -226,7 +226,7 @@ def pytest_configure(config):
         import u_boot_console_exec_attach
         console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig)
 
-re_ut_test_list = re.compile(r'[^a-zA-Z0-9_]_u_boot_list_2_ut_(.*)_test_2_\1_test_(.*)\s*$')
+re_ut_test_list = re.compile(r'[^a-zA-Z0-9_]_u_boot_list_2_ut_(.*)_test_2_(.*)\s*$')
 def generate_ut_subtest(metafunc, fixture_name, sym_path):
     """Provide parametrization for a ut_subtest fixture.
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 18/41] test/py: Raise a ValueError if a command fails
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (16 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 19/41] bootstd: Add the concept of a bootflow Simon Glass
                     ` (39 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Stephen Warren,
	Stephen Warren

At present an Exception is raised if a command fails. This is a very broad
class and makes it difficult for callers to catch the error without also
catching other things, like programming bugs.

Change it to ValueError to make this easier.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/multiplexed_log.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py
index 9325fae46d2..6688207fb31 100644
--- a/test/py/multiplexed_log.py
+++ b/test/py/multiplexed_log.py
@@ -165,7 +165,7 @@ class RunAndLog(object):
         if output and not output.endswith('\n'):
             output += '\n'
         if exit_status and not exception and not ignore_errors:
-            exception = Exception('Exit code: ' + str(exit_status))
+            exception = ValueError('Exit code: ' + str(exit_status))
         if exception:
             output += str(exception) + '\n'
         self.logfile.write(self, output)
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 19/41] bootstd: Add the concept of a bootflow
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (17 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 20/41] bootstd: Add the bootstd uclass and core implementation Simon Glass
                     ` (38 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

A bootflow encapsulates the process used to boot an operating system.
It typically has a control file (such as extlinux.conf) and information
about which 'bootdev' it came from.

Add the header file for this first, since it is needed by all other
files.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS        |   5 +
 include/bootflow.h | 254 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 259 insertions(+)
 create mode 100644 include/bootflow.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5069f188065..8f4211baf1f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -633,6 +633,11 @@ M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	tools/binman/
 
+BOOTDEVICE
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	include/bootflow.h
+
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
 R:	Qu Wenruo <wqu@suse.com>
diff --git a/include/bootflow.h b/include/bootflow.h
new file mode 100644
index 00000000000..56ff101a78a
--- /dev/null
+++ b/include/bootflow.h
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootflow_h
+#define __bootflow_h
+
+#include <linux/list.h>
+
+/**
+ * enum bootflow_state_t - states that a particular bootflow can be in
+ *
+ * Only bootflows in state BOOTFLOWST_READY can be used to boot.
+ */
+enum bootflow_state_t {
+	BOOTFLOWST_BASE,	/**< Nothing known yet */
+	BOOTFLOWST_MEDIA,	/**< Media exists */
+	BOOTFLOWST_PART,	/**< Partition exists */
+	BOOTFLOWST_FS,		/**< Filesystem exists */
+	BOOTFLOWST_FILE,	/**< Bootflow file exists */
+	BOOTFLOWST_READY,	/**< Bootflow file loaded */
+
+	BOOTFLOWST_COUNT
+};
+
+/**
+ * struct bootflow - information about a bootflow
+ *
+ * This is connected into two separate linked lists:
+ *
+ *   bm_sibling - links all bootflows in the same bootdev
+ *   glob_sibling - links all bootflows in all bootdevs
+ *
+ * @bm_node: Points to siblings in the same bootdev
+ * @glob_node: Points to siblings in the global list (all bootdev)
+ * @dev: Bootdevice device which produced this bootflow
+ * @blk: Block device which contains this bootflow, NULL if this is a network
+ *	device
+ * @part: Partition number (0 for whole device)
+ * @method: Bootmethod device used to perform the boot and read files
+ * @name: Name of bootflow (allocated)
+ * @state: Current state (enum bootflow_state_t)
+ * @subdir: Subdirectory to fetch files from (with trailing /), or NULL if none
+ * @fname: Filename of bootflow file (allocated)
+ * @buf: Bootflow file contents (allocated)
+ * @size: Size of bootflow file in bytes
+ * @err: Error number received (0 if OK)
+ */
+struct bootflow {
+	struct list_head bm_node;
+	struct list_head glob_node;
+	struct udevice *dev;
+	struct udevice *blk;
+	int part;
+	struct udevice *method;
+	char *name;
+	enum bootflow_state_t state;
+	char *subdir;
+	char *fname;
+	char *buf;
+	int size;
+	int err;
+};
+
+/**
+ * enum bootflow_flags_t - flags for the bootflow iterator
+ *
+ * @BOOTFLOWF_FIXED: Only used fixed/internal media
+ * @BOOTFLOWF_SHOW: Show each bootdev before scanning it
+ * @BOOTFLOWF_ALL: Return bootflows with errors as well
+ * @BOOTFLOWF_SINGLE_DEV: Just scan one bootmeth
+ */
+enum bootflow_flags_t {
+	BOOTFLOWF_FIXED		= 1 << 0,
+	BOOTFLOWF_SHOW		= 1 << 1,
+	BOOTFLOWF_ALL		= 1 << 2,
+	BOOTFLOWF_SINGLE_DEV	= 1 << 3,
+};
+
+/**
+ * struct bootflow_iter - state for iterating through bootflows
+ *
+ * This starts at with the first bootdev/partition/bootmeth and can be used to
+ * iterate through all of them.
+ *
+ * Iteration starts with the bootdev. The first partition (0, i.e. whole device)
+ * is scanned first. For partition 0, it iterates through all the available
+ * bootmeths to see which one(s) can provide a bootflow. Then it moves to
+ * parition 1 (if there is one) and the process continues. Once all partitions
+ * are examined, it moves to the next bootdev.
+ *
+ * Initially @max_part is 0, meaning that only the whole device (@part=0) can be
+ * used. During scanning, if a partition table is found, then @max_part is
+ * updated to a larger value, no less than the number of available partitions.
+ * This ensures that iteration works through all partitions on the bootdev.
+ *
+ * @flags: Flags to use (see enum bootflow_flags_t)
+ * @dev: Current bootdev
+ * @part: Current partition number (0 for whole device)
+ * @method: Current bootmeth
+ * @max_part: Maximum hardware partition number in @dev, 0 if there is no
+ *	partition table
+ * @err: Error obtained from checking the last iteration. This is used to skip
+ *	forward (e.g. to skip the current partition because it is not valid)
+ *	-ESHUTDOWN: try next bootdev
+ * @num_devs: Number of bootdevs in @dev_order
+ * @cur_dev: Current bootdev number, an index into @dev_order[]
+ * @dev_order: List of bootdevs to scan, in order of priority. The scan starts
+ *	with the first one on the list
+ * @num_methods: Number of bootmeth devices in @method_order
+ * @cur_method: Current method number, an index into @method_order
+ * @method_order: List of bootmeth devices to use, in order
+ */
+struct bootflow_iter {
+	int flags;
+	struct udevice *dev;
+	int part;
+	struct udevice *method;
+	int max_part;
+	int err;
+	int num_devs;
+	int cur_dev;
+	struct udevice **dev_order;
+	int num_methods;
+	int cur_method;
+	struct udevice **method_order;
+};
+
+/**
+ * bootflow_iter_init() - Reset a bootflow iterator
+ *
+ * This sets everything to the starting point, ready for use.
+ *
+ * @iter: Place to store private info (inited by this call)
+ * @flags: Flags to use (see enum bootflow_flags_t)
+ */
+void bootflow_iter_init(struct bootflow_iter *iter, int flags);
+
+/**
+ * bootflow_iter_uninit() - Free memory used by an interator
+ *
+ * @iter:	Iterator to free
+ */
+void bootflow_iter_uninit(struct bootflow_iter *iter);
+
+/**
+ * bootflow_scan_bootdev() - find the first bootflow in a bootdev
+ *
+ * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too
+ *
+ * @dev:	Boot device to scan, NULL to work through all of them until it
+ *	finds one that * can supply a bootflow
+ * @iter:	Place to store private info (inited by this call)
+ * @flags:	Flags for bootdev (enum bootflow_flags_t)
+ * @bflow:	Place to put the bootflow if found
+ * @return 0 if found,  -ENODEV if no device, other -ve on other error
+ *	(iteration can continue)
+ */
+int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
+			  int flags, struct bootflow *bflow);
+
+/**
+ * bootflow_scan_first() - find the first bootflow
+ *
+ * This works through the available bootdev devices until it finds one that
+ * can supply a bootflow. It then returns that
+ *
+ * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too
+ *
+ * @iter:	Place to store private info (inited by this call), with
+ * @flags:	Flags for bootdev (enum bootflow_flags_t)
+ * @bflow:	Place to put the bootflow if found
+ * @return 0 if found, -ENODEV if no device, other -ve on other error (iteration
+ *	can continue)
+ */
+int bootflow_scan_first(struct bootflow_iter *iter, int flags,
+			struct bootflow *bflow);
+
+/**
+ * bootflow_scan_next() - find the next bootflow
+ *
+ * This works through the available bootdev devices until it finds one that
+ * can supply a bootflow. It then returns that bootflow
+ *
+ * @iter:	Private info (as set up by bootflow_scan_first())
+ * @bflow:	Place to put the bootflow if found
+ * @return 0 if found, -ENODEV if no device, -ESHUTDOWN if no more bootflows,
+ *	other -ve on other error (iteration can continue)
+ */
+int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow);
+
+/**
+ * bootflow_first_glob() - Get the first bootflow from the global list
+ *
+ * Returns the first bootflow in the global list, no matter what bootflow it is
+ * attached to
+ *
+ * @bflowp: Returns a pointer to the bootflow
+ * @return 0 if found, -ENOENT if there are no bootflows
+ */
+int bootflow_first_glob(struct bootflow **bflowp);
+
+/**
+ * bootflow_next_glob() - Get the next bootflow from the global list
+ *
+ * Returns the next bootflow in the global list, no matter what bootflow it is
+ * attached to
+ *
+ * @bflowp: On entry, the last bootflow returned , e.g. from
+ *	bootflow_first_glob()
+ * @return 0 if found, -ENOENT if there are no more bootflows
+ */
+int bootflow_next_glob(struct bootflow **bflowp);
+
+/**
+ * bootflow_free() - Free memory used by a bootflow
+ *
+ * This frees fields within @bflow, but not the @bflow pointer itself
+ */
+void bootflow_free(struct bootflow *bflow);
+
+/**
+ * bootflow_boot() - boot a bootflow
+ *
+ * @bflow: Bootflow to boot
+ * @return -EPROTO if bootflow has not been loaded, -ENOSYS if the bootflow
+ *	type is not supported, -EFAULT if the boot returned without an error
+ *	when we are expecting it to boot, -ENOTSUPP if trying method resulted in
+ *	finding out that is not actually supported for this boot and should not
+ *	be tried again unless something changes
+ */
+int bootflow_boot(struct bootflow *bflow);
+
+/**
+ * bootflow_run_boot() - Try to boot a bootflow
+ *
+ * @iter: Current iteration (or NULL if none). Used to disable a bootmeth if the
+ *	boot returns -ENOTSUPP
+ * @bflow: Bootflow to boot
+ * @return result of trying to boot
+ */
+int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow);
+
+/**
+ * bootflow_state_get_name() - Get the name of a bootflow state
+ *
+ * @state: State to check
+ * @return name, or "?" if invalid
+ */
+const char *bootflow_state_get_name(enum bootflow_state_t state);
+
+#endif
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 20/41] bootstd: Add the bootstd uclass and core implementation
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (18 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 19/41] bootstd: Add the concept of a bootflow Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 21/41] bootstd: Add the bootdev uclass Simon Glass
                     ` (37 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

The 'bootstd' device provides the central information about U-Boot
standard boot.

Add a uclass for bootstd and the various helpers needed to make it
work. Also add a binding file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS                          |   2 +
 boot/Kconfig                         |  21 ++++
 boot/Makefile                        |   3 +
 boot/bootstd-uclass.c                | 145 +++++++++++++++++++++++++++
 doc/device-tree-bindings/bootstd.txt |  28 ++++++
 include/bootstd.h                    |  80 +++++++++++++++
 include/dm/uclass-id.h               |   1 +
 7 files changed, 280 insertions(+)
 create mode 100644 boot/bootstd-uclass.c
 create mode 100644 doc/device-tree-bindings/bootstd.txt
 create mode 100644 include/bootstd.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f4211baf1f..c928130f94b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -636,6 +636,8 @@ F:	tools/binman/
 BOOTDEVICE
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
+F:	boot/bootstd.c
+F:	include/bootstd.h
 F:	include/bootflow.h
 
 BTRFS
diff --git a/boot/Kconfig b/boot/Kconfig
index 9b84a8d005f..58c495bb347 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -274,6 +274,27 @@ endif # SPL
 
 endif # FIT
 
+config BOOTSTD
+	bool "Standard boot support"
+	default y
+	depends on OF_CONTROL
+	help
+	  U-Boot supports a standard way of locating something to boot,
+	  typically an Operating System such as Linux, provided by a distro such
+	  as Arch Linux or Debian. Enable this to support iterating through
+	  available bootdevs and using bootmeths to find bootflows suitable for
+	  booting.
+
+	  Standard boot is not a standard way of booting, just a framework
+	  within U-Boot for supporting all the different ways that exist.
+
+	  Terminology:
+
+	    - bootdev - a device which can hold a distro (e.g. MMC)
+	    - bootmeth - a method to scan a bootdev to find bootflows (owned by
+	        U-Boot)
+	    - bootflow - a description of how to boot (owned by the distro)
+
 config LEGACY_IMAGE_FORMAT
 	bool "Enable support for the legacy image format"
 	default y if !FIT_SIGNATURE
diff --git a/boot/Makefile b/boot/Makefile
index 2938c3f1458..48031d1c2b0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -22,6 +22,9 @@ endif
 obj-y += image.o image-board.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
+
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
+
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
new file mode 100644
index 00000000000..04823e5ba03
--- /dev/null
+++ b/boot/bootstd-uclass.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Uclass implemenation for standard boot
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/read.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int bootstd_of_to_plat(struct udevice *dev)
+{
+	struct bootstd_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	/* Don't check errors since livetree and flattree are different */
+	ret = dev_read_string_list(dev, "filename-prefixes", &priv->prefixes);
+	dev_read_string_list(dev, "bootdev-order", &priv->bootdev_order);
+
+	return 0;
+}
+
+static void bootstd_clear_glob_(struct bootstd_priv *priv)
+{
+	while (!list_empty(&priv->glob_head)) {
+		struct bootflow *bflow;
+
+		bflow = list_first_entry(&priv->glob_head, struct bootflow,
+					 glob_node);
+		/* add later bootflow_remove(bflow); */
+	}
+}
+
+void bootstd_clear_glob(void)
+{
+	struct bootstd_priv *std;
+
+	if (bootstd_get_priv(&std))
+		return;
+
+	bootstd_clear_glob_(std);
+}
+
+static int bootstd_remove(struct udevice *dev)
+{
+	struct bootstd_priv *priv = dev_get_priv(dev);
+
+	free(priv->prefixes);
+	free(priv->bootdev_order);
+	bootstd_clear_glob_(priv);
+
+	return 0;
+}
+
+const char *const *const bootstd_get_bootdev_order(struct udevice *dev)
+{
+	struct bootstd_priv *std = dev_get_priv(dev);
+
+	return std->bootdev_order;
+}
+
+const char *const *const bootstd_get_prefixes(struct udevice *dev)
+{
+	struct bootstd_priv *std = dev_get_priv(dev);
+
+	return std->prefixes;
+}
+
+int bootstd_get_priv(struct bootstd_priv **stdp)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_BOOTSTD, &dev);
+	if (ret)
+		return ret;
+	*stdp = dev_get_priv(dev);
+
+	return 0;
+}
+
+static int bootstd_probe(struct udevice *dev)
+{
+	struct bootstd_priv *std = dev_get_priv(dev);
+
+	INIT_LIST_HEAD(&std->glob_head);
+
+	return 0;
+}
+
+/* For now, bind the boormethod device if none are found in the devicetree */
+int dm_scan_other(bool pre_reloc_only)
+{
+	struct udevice *bootstd;
+	int ret;
+
+	/* These are not needed before relocation */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return 0;
+
+	/* Create a bootstd device if needed */
+	uclass_find_first_device(UCLASS_BOOTSTD, &bootstd);
+	if (!bootstd) {
+		ret = device_bind_driver(gd->dm_root, "bootstd_drv", "bootstd",
+					 &bootstd);
+		if (ret)
+			return log_msg_ret("bootstd", ret);
+	}
+
+	return 0;
+}
+
+static const struct udevice_id bootstd_ids[] = {
+	{ .compatible = "u-boot,boot-std" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootstd_drv) = {
+	.id		= UCLASS_BOOTSTD,
+	.name		= "bootstd_drv",
+	.of_to_plat	= bootstd_of_to_plat,
+	.probe		= bootstd_probe,
+	.remove		= bootstd_remove,
+	.of_match	= bootstd_ids,
+	.priv_auto	= sizeof(struct bootstd_priv),
+};
+
+UCLASS_DRIVER(bootstd) = {
+	.id		= UCLASS_BOOTSTD,
+	.name		= "bootstd",
+#if CONFIG_IS_ENABLED(OF_REAL)
+	.post_bind	= dm_scan_fdt_dev,
+#endif
+};
diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt
new file mode 100644
index 00000000000..f048b9dd327
--- /dev/null
+++ b/doc/device-tree-bindings/bootstd.txt
@@ -0,0 +1,28 @@
+U-Boot standard boot device (bootstd)
+=====================================
+
+This is the controlling device for U-Boot standard boot, providing a way to
+boot operating systems in a way that can be controlled by distros.
+
+Required properties:
+
+compatible: "u-boot,boot-std"
+
+Optional properties:
+
+filename-prefixes:
+   List of strings, each a directory to search for bootflow files
+
+bootdev-order:
+   List of bootdevs to check for bootflows, each a bootdev label (the media
+   uclass followed by the numeric sequence number of the media device)
+
+
+Example:
+
+	bootstd {
+		compatible = "u-boot,boot-std";
+
+		filename-prefixes = "/", "/boot/";
+		bootdev-order = "mmc2", "mmc1";
+	};
diff --git a/include/bootstd.h b/include/bootstd.h
new file mode 100644
index 00000000000..95b6e5e1a3c
--- /dev/null
+++ b/include/bootstd.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Standard U-Boot boot framework
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootstd_h
+#define __bootstd_h
+
+struct udevice;
+
+/**
+ * struct bootstd_priv - priv data for the bootstd driver
+ *
+ * This is attached to the (only) bootstd device, so there is only one instance
+ * of this struct. It provides overall information about bootdevs and bootflows.
+ *
+ * @prefixes: NULL-terminated list of prefixes to use for bootflow filenames,
+ *	e.g. "/", "/boot/"; NULL if none
+ * @bootdev_order: Order to use for bootdevs (or NULL if none), with each item
+ *	being a bootdev label, e.g. "mmc2", "mmc1";
+ * @cur_bootdev: Currently selected bootdev (for commands)
+ * @cur_bootflow: Currently selected bootflow (for commands)
+ * @glob_head: Head for the global list of all bootflows across all bootdevs
+ * @bootmeth_count: Number of bootmeth devices in @bootmeth_order
+ * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
+ */
+struct bootstd_priv {
+	const char **prefixes;
+	const char **bootdev_order;
+	struct udevice *cur_bootdev;
+	struct bootflow *cur_bootflow;
+	struct list_head glob_head;
+	int bootmeth_count;
+	struct udevice **bootmeth_order;
+};
+
+/**
+ * bootstd_get_bootdev_order() - Get the boot-order list
+ *
+ * This reads the boot order, e.g. {"mmc0", "mmc2", NULL}
+ *
+ * The list is alloced by the bootstd driver so should not be freed. That is the
+ * reason for all the const stuff in the function signature
+ *
+ * @return list of string points, terminated by NULL; or NULL if no boot order
+ */
+const char *const *const bootstd_get_bootdev_order(struct udevice *dev);
+
+/**
+ * bootstd_get_prefixes() - Get the filename-prefixes list
+ *
+ * This reads the prefixes, e.g. {"/", "/bpot", NULL}
+ *
+ * The list is alloced by the bootstd driver so should not be freed. That is the
+ * reason for all the const stuff in the function signature
+ *
+ * @return list of string points, terminated by NULL; or NULL if no boot order
+ */
+const char *const *const bootstd_get_prefixes(struct udevice *dev);
+
+/**
+ * bootstd_get_priv() - Get the (single) state for the bootstd system
+ *
+ * The state holds a global list of all bootflows that have been found.
+ *
+ * @return 0 if OK, -ve if the uclass does not exist
+ */
+int bootstd_get_priv(struct bootstd_priv **stdp);
+
+/**
+ * bootstd_clear_glob() - Clear the global list of bootflows
+ *
+ * This removes all bootflows globally and across all bootdevs.
+ */
+void bootstd_clear_glob(void);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 3768432b680..17383fc38c1 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -38,6 +38,7 @@ enum uclass_id {
 	UCLASS_AXI,		/* AXI bus */
 	UCLASS_BLK,		/* Block device */
 	UCLASS_BOOTCOUNT,       /* Bootcount backing store */
+	UCLASS_BOOTSTD,		/* Standard boot driver */
 	UCLASS_BUTTON,		/* Button */
 	UCLASS_CACHE,		/* Cache controller */
 	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 21/41] bootstd: Add the bootdev uclass
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (19 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 20/41] bootstd: Add the bootstd uclass and core implementation Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 22/41] bootstd: Add the bootmeth uclass and helpers Simon Glass
                     ` (36 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

A 'bootdev' is a device which can be used to boot an operating system.
It is a child of the media device (e.g. MMC) which handles reading files
from that device, such as a bootflow file.

Add a uclass for bootdev and the various helpers needed to make it
work. Also add a binding file, empty for now.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS                          |   4 +-
 boot/Makefile                        |   1 +
 boot/bootdev-uclass.c                | 431 +++++++++++++++++++++++++++
 doc/device-tree-bindings/bootdev.txt |   8 +
 include/bootdev.h                    | 258 ++++++++++++++++
 include/dm/uclass-id.h               |   1 +
 6 files changed, 702 insertions(+), 1 deletion(-)
 create mode 100644 boot/bootdev-uclass.c
 create mode 100644 doc/device-tree-bindings/bootdev.txt
 create mode 100644 include/bootdev.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c928130f94b..d800a3b7acb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -636,9 +636,11 @@ F:	tools/binman/
 BOOTDEVICE
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
+F:	boot/bootdev*.c
 F:	boot/bootstd.c
-F:	include/bootstd.h
+F:	include/bootdev*.h
 F:	include/bootflow.h
+F:	include/bootstd.h
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/boot/Makefile b/boot/Makefile
index 48031d1c2b0..35abfd37654 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -23,6 +23,7 @@ obj-y += image.o image-board.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
new file mode 100644
index 00000000000..c8455ec5159
--- /dev/null
+++ b/boot/bootdev-uclass.c
@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <fs.h>
+#include <log.h>
+#include <malloc.h>
+#include <part.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+
+enum {
+	/*
+	 * Set some sort of limit on the number of partitions a bootdev can
+	 * have. Note that for disks this limits the partitions numbers that
+	 * are scanned to 1..MAX_BOOTFLOWS_PER_BOOTDEV
+	 */
+	MAX_PART_PER_BOOTDEV		= 30,
+};
+
+int bootdev_add_bootflow(struct bootflow *bflow)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev);
+	struct bootstd_priv *std;
+	struct bootflow *new;
+	int ret;
+
+	assert(bflow->dev);
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	new = malloc(sizeof(*bflow));
+	if (!new)
+		return log_msg_ret("bflow", -ENOMEM);
+	memcpy(new, bflow, sizeof(*bflow));
+
+	list_add_tail(&new->glob_node, &std->glob_head);
+	list_add_tail(&new->bm_node, &ucp->bootflow_head);
+
+	return 0;
+}
+
+int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	if (list_empty(&ucp->bootflow_head))
+		return -ENOENT;
+
+	*bflowp = list_first_entry(&ucp->bootflow_head, struct bootflow,
+				   bm_node);
+
+	return 0;
+}
+
+int bootdev_next_bootflow(struct bootflow **bflowp)
+{
+	struct bootflow *bflow = *bflowp;
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev);
+
+	*bflowp = NULL;
+
+	if (list_is_last(&bflow->bm_node, &ucp->bootflow_head))
+		return -ENOENT;
+
+	*bflowp = list_entry(bflow->bm_node.next, struct bootflow, bm_node);
+
+	return 0;
+}
+
+int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
+		 struct udevice **devp)
+{
+	struct udevice *dev;
+	char dev_name[30];
+	char *str;
+	int ret;
+
+	snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
+	str = strdup(dev_name);
+	if (!str)
+		return -ENOMEM;
+	ret = device_bind_driver(parent, drv_name, str, &dev);
+	if (ret)
+		return ret;
+	device_set_name_alloced(dev);
+	*devp = dev;
+
+	return 0;
+}
+
+int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
+			struct bootflow_iter *iter, struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(blk);
+	struct disk_partition info;
+	char partstr[20];
+	char name[60];
+	int ret;
+
+	/* Sanity check */
+	if (iter->part >= MAX_PART_PER_BOOTDEV)
+		return log_msg_ret("max", -ESHUTDOWN);
+
+	bflow->blk = blk;
+	if (iter->part)
+		snprintf(partstr, sizeof(partstr), "part_%x", iter->part);
+	else
+		strcpy(partstr, "whole");
+	snprintf(name, sizeof(name), "%s.%s", dev->name, partstr);
+	bflow->name = strdup(name);
+	if (!bflow->name)
+		return log_msg_ret("name", -ENOMEM);
+
+	bflow->state = BOOTFLOWST_BASE;
+	bflow->part = iter->part;
+
+	/*
+	 * partition numbers start at 0 so this cannot succeed, but it can tell
+	 * us whether there is valid media there
+	 */
+	ret = part_get_info(desc, iter->part, &info);
+	if (!iter->part && ret == -ENOENT)
+		ret = 0;
+
+	/*
+	 * This error indicates the media is not present. Otherwise we just
+	 * blindly scan the next partition. We could be more intelligent here
+	 * and check which partition numbers actually exist.
+	 */
+	if (ret == -EOPNOTSUPP)
+		ret = -ESHUTDOWN;
+	else
+		bflow->state = BOOTFLOWST_MEDIA;
+	if (ret)
+		return log_msg_ret("part", ret);
+
+	/*
+	 * Currently we don't get the number of partitions, so just
+	 * assume a large number
+	 */
+	iter->max_part = MAX_PART_PER_BOOTDEV;
+
+	if (iter->part) {
+		ret = fs_set_blk_dev_with_part(desc, bflow->part);
+		bflow->state = BOOTFLOWST_PART;
+
+		/* Use an #ifdef due to info.sys_ind */
+#ifdef CONFIG_DOS_PARTITION
+		log_debug("%s: Found partition %x type %x fstype %d\n",
+			  blk->name, bflow->part, info.sys_ind,
+			  ret ? -1 : fs_get_type());
+#endif
+		if (ret)
+			return log_msg_ret("fs", ret);
+		bflow->state = BOOTFLOWST_FS;
+	}
+
+	return 0;
+}
+
+void bootdev_list(bool probe)
+{
+	struct udevice *dev;
+	int ret;
+	int i;
+
+	printf("Seq  Probed  Status  Uclass    Name\n");
+	printf("---  ------  ------  --------  ------------------\n");
+	if (probe)
+		ret = uclass_first_device_err(UCLASS_BOOTDEV, &dev);
+	else
+		ret = uclass_find_first_device(UCLASS_BOOTDEV, &dev);
+	for (i = 0; dev; i++) {
+		printf("%3x   [ %c ]  %6s  %-9.9s %s\n", dev_seq(dev),
+		       device_active(dev) ? '+' : ' ',
+		       ret ? simple_itoa(ret) : "OK",
+		       dev_get_uclass_name(dev_get_parent(dev)), dev->name);
+		if (probe)
+			ret = uclass_next_device_err(&dev);
+		else
+			ret = uclass_find_next_device(&dev);
+	}
+	printf("---  ------  ------  --------  ------------------\n");
+	printf("(%d bootdev%s)\n", i, i != 1 ? "s" : "");
+}
+
+int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name)
+{
+	struct udevice *bdev;
+	int ret;
+
+	ret = device_find_first_child_by_uclass(parent, UCLASS_BOOTDEV,
+						&bdev);
+	if (ret) {
+		if (ret != -ENODEV) {
+			log_debug("Cannot access bootdev device\n");
+			return ret;
+		}
+
+		ret = bootdev_bind(parent, drv_name, "bootdev", &bdev);
+		if (ret) {
+			log_debug("Cannot create bootdev device\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name)
+{
+	struct udevice *parent, *dev;
+	char dev_name[50];
+	int ret;
+
+	snprintf(dev_name, sizeof(dev_name), "%s.%s", blk->name, "bootdev");
+
+	parent = dev_get_parent(blk);
+	ret = device_find_child_by_name(parent, dev_name, &dev);
+	if (ret) {
+		char *str;
+
+		if (ret != -ENODEV) {
+			log_debug("Cannot access bootdev device\n");
+			return ret;
+		}
+		str = strdup(dev_name);
+		if (!str)
+			return -ENOMEM;
+
+		ret = device_bind_driver(parent, drv_name, str, &dev);
+		if (ret) {
+			log_debug("Cannot create bootdev device\n");
+			return ret;
+		}
+		device_set_name_alloced(dev);
+	}
+
+	return 0;
+}
+
+int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp)
+{
+	struct udevice *parent = dev_get_parent(dev);
+	struct udevice *blk;
+	int ret, len;
+	char *p;
+
+	if (device_get_uclass_id(dev) != UCLASS_BOOTDEV)
+		return -EINVAL;
+
+	/* This should always work if bootdev_setup_sibling_blk() was used */
+	p = strstr(dev->name, ".bootdev");
+	if (!p)
+		return log_msg_ret("str", -EINVAL);
+
+	len = p - dev->name;
+	ret = device_find_child_by_namelen(parent, dev->name, len, &blk);
+	if (ret)
+		return log_msg_ret("find", ret);
+	*blkp = blk;
+
+	return 0;
+}
+
+int bootdev_unbind_dev(struct udevice *parent)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = device_find_first_child_by_uclass(parent, UCLASS_BOOTDEV, &dev);
+	if (!ret) {
+		ret = device_remove(dev, DM_REMOVE_NORMAL);
+		if (ret)
+			return log_msg_ret("rem", ret);
+		ret = device_unbind(dev);
+		if (ret)
+			return log_msg_ret("unb", ret);
+	}
+
+	return 0;
+}
+
+/**
+ * bootdev_find_by_label() - Convert a label string to a bootdev device
+ *
+ * Looks up a label name to find the associated bootdev. For example, if the
+ * label name is "mmc2", this will find a bootdev for an mmc device whose
+ * sequence number is 2.
+ *
+ * @label: Label string to convert, e.g. "mmc2"
+ * @devp: Returns bootdev device corresponding to that boot label
+ * @return 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a
+ *	uclass, -ENOENT if no bootdev for that media has the sequence number
+ *	(e.g. 2)
+ */
+int bootdev_find_by_label(const char *label, struct udevice **devp)
+{
+	struct udevice *media;
+	struct uclass *uc;
+	enum uclass_id id;
+	int seq, len;
+
+	seq = trailing_strtoln_len(label, NULL, &len);
+	id = uclass_get_by_name_len(label, len);
+	if (id == UCLASS_INVALID) {
+		log_warning("Unknown uclass '%s' in label\n", label);
+		return -EINVAL;
+	}
+
+	/* Iterate through devices in the media uclass (e.g. UCLASS_MMC) */
+	uclass_id_foreach_dev(id, media, uc) {
+		struct udevice *bdev;
+		int ret;
+
+		/* if there is no seq, match anything */
+		if (seq != -1 && dev_seq(media) != seq)
+			continue;
+
+		ret = device_find_first_child_by_uclass(media, UCLASS_BOOTDEV,
+							&bdev);
+		if (!ret) {
+			*devp = bdev;
+			return 0;
+		}
+	}
+	log_warning("Unknown seq %d for label '%s'\n", seq, label);
+
+	return -ENOENT;
+}
+
+int bootdev_find_by_any(const char *name, struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret, seq;
+	char *endp;
+
+	seq = simple_strtol(name, &endp, 16);
+
+	/* Select by name, label or number */
+	if (*endp) {
+		ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev);
+		if (ret == -ENODEV) {
+			ret = bootdev_find_by_label(name, &dev);
+			if (ret) {
+				printf("Cannot find bootdev '%s' (err=%d)\n",
+				       name, ret);
+				return ret;
+			}
+			ret = device_probe(dev);
+		}
+		if (ret) {
+			printf("Cannot probe bootdev '%s' (err=%d)\n", name,
+			       ret);
+			return ret;
+		}
+	} else {
+		ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev);
+	}
+	if (ret) {
+		printf("Cannot find '%s' (err=%d)\n", name, ret);
+		return ret;
+	}
+
+	*devp = dev;
+
+	return 0;
+}
+
+int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			 struct bootflow *bflow)
+{
+	const struct bootdev_ops *ops = bootdev_get_ops(dev);
+
+	if (!ops->get_bootflow)
+		return -ENOSYS;
+	memset(bflow, '\0', sizeof(*bflow));
+	bflow->dev = dev;
+	bflow->method = iter->method;
+	bflow->state = BOOTFLOWST_BASE;
+
+	return ops->get_bootflow(dev, iter, bflow);
+}
+
+void bootdev_clear_bootflows(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	while (!list_empty(&ucp->bootflow_head)) {
+		struct bootflow *bflow;
+
+		bflow = list_first_entry(&ucp->bootflow_head, struct bootflow,
+					 bm_node);
+		/* later bootflow_remove(bflow); */
+	}
+}
+
+static int bootdev_post_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	INIT_LIST_HEAD(&ucp->bootflow_head);
+
+	return 0;
+}
+
+static int bootdev_pre_unbind(struct udevice *dev)
+{
+	bootdev_clear_bootflows(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(bootdev) = {
+	.id		= UCLASS_BOOTDEV,
+	.name		= "bootdev",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.per_device_plat_auto	= sizeof(struct bootdev_uc_plat),
+	.post_bind	= bootdev_post_bind,
+	.pre_unbind	= bootdev_pre_unbind,
+};
diff --git a/doc/device-tree-bindings/bootdev.txt b/doc/device-tree-bindings/bootdev.txt
new file mode 100644
index 00000000000..95b7fec8212
--- /dev/null
+++ b/doc/device-tree-bindings/bootdev.txt
@@ -0,0 +1,8 @@
+U-Boot boot device (bootdev)
+============================
+
+A bootdev provides a way to obtain a bootflow file from a device. It is a
+child of the media device (UCLASS_MMC, UCLASS_SPI_FLASH, etc.)
+
+The bootdev driver is provided by the media devices. The bindings for each
+are described in this file (to come).
diff --git a/include/bootdev.h b/include/bootdev.h
new file mode 100644
index 00000000000..3068cf309b9
--- /dev/null
+++ b/include/bootdev.h
@@ -0,0 +1,258 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootdev_h
+#define __bootdev_h
+
+#include <linux/list.h>
+
+struct bootflow;
+struct bootflow_iter;
+struct udevice;
+
+/**
+ * enum bootdev_prio_t - priority of each bootdev
+ *
+ * These values are associated with each bootdev and set up by the driver.
+ *
+ * Smallest value is the highest priority. By default, bootdevs are scanned from
+ * highest to lowest priority
+ */
+enum bootdev_prio_t {
+	BOOTDEVP_0_INTERNAL_FAST	= 10,
+	BOOTDEVP_1_INTERNAL_SLOW	= 20,
+	BOOTDEVP_2_SCAN_FAST		= 30,
+	BOOTDEVP_3_SCAN_SLOW		= 40,
+	BOOTDEVP_4_NET_BASE		= 50,
+	BOOTDEVP_5_NET_FALLBACK		= 60,
+	BOOTDEVP_6_SYSTEM		= 70,
+
+	BOOTDEVP_COUNT,
+};
+
+/**
+ * struct bootdev_uc_plat - uclass information about a bootdev
+ *
+ * This is attached to each device in the bootdev uclass and accessible via
+ * dev_get_uclass_plat(dev)
+ *
+ * @bootflows: List of available bootflows for this bootdev
+ * @piro: Priority of this bootdev
+ */
+struct bootdev_uc_plat {
+	struct list_head bootflow_head;
+	enum bootdev_prio_t prio;
+};
+
+/** struct bootdev_ops - Operations for the bootdev uclass */
+struct bootdev_ops {
+	/**
+	 * get_bootflow() - get a bootflow
+	 *
+	 * @dev:	Bootflow device to check
+	 * @iter:	Provides current dev, part, method to get. Should update
+	 *	max_part if there is a partition table. Should update state,
+	 *	subdir, fname, buf, size according to progress
+	 * @bflow:	Updated bootflow if found
+	 * @return 0 if OK, -ESHUTDOWN if there are no more bootflows on this
+	 *	device, -ENOSYS if this device doesn't support bootflows,
+	 *	other -ve value on other error
+	 */
+	int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter,
+			    struct bootflow *bflow);
+};
+
+#define bootdev_get_ops(dev)  ((struct bootdev_ops *)(dev)->driver->ops)
+
+/**
+ * bootdev_get_bootflow() - get a bootflow
+ *
+ * @dev:	Bootflow device to check
+ * @iter:	Provides current  part, method to get
+ * @bflow:	Returns bootflow if found
+ * @return 0 if OK, -ESHUTDOWN if there are no more bootflows on this device,
+ *	-ENOSYS if this device doesn't support bootflows, other -ve value on
+ *	other error
+ */
+int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			 struct bootflow *bflow);
+
+/**
+ * bootdev_bind() - Bind a new named bootdev device
+ *
+ * @parent:	Parent of the new device
+ * @drv_name:	Driver name to use for the bootdev device
+ * @name:	Name for the device (parent name is prepended)
+ * @devp:	the new device (which has not been probed)
+ */
+int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
+		 struct udevice **devp);
+
+/**
+ * bootdev_find_in_blk() - Find a bootdev in a block device
+ *
+ * @dev: Bootflow device associated with this block device
+ * @blk: Block device to search
+ * @iter:	Provides current dev, part, method to get. Should update
+ *	max_part if there is a partition table
+ * @bflow: On entry, provides information about the partition and device to
+ *	check. On exit, returns bootflow if found
+ * @return 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
+ */
+int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
+			struct bootflow_iter *iter, struct bootflow *bflow);
+
+/**
+ * bootdev_list() - List all available bootdevs
+ *
+ * @probe: true to probe devices, false to leave them as is
+ */
+void bootdev_list(bool probe);
+
+/**
+ * bootdev_clear_bootflows() - Clear bootflows from a bootdev
+ *
+ * Each bootdev maintains a list of discovered bootflows. This provides a
+ * way to clear it. These bootflows are removed from the global list too.
+ *
+ * @dev: bootdev device to update
+ */
+void bootdev_clear_bootflows(struct udevice *dev);
+
+/**
+ * bootdev_add_bootflow() - Add a bootflow to the bootdev's list
+ *
+ * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
+ * bootflow to that device.
+ *
+ * @dev: Bootdevice device to add to
+ * @bflow: Bootflow to add. Note that fields within bflow must be allocated
+ *	since this function takes over ownership of these. This functions makes
+ *	a copy of @bflow itself (without allocating its fields again), so the
+ *	caller must dispose of the memory used by the @bflow pointer itself
+ * @return 0 if OK, -ENOMEM if out of memory
+ */
+int bootdev_add_bootflow(struct bootflow *bflow);
+
+/**
+ * bootdev_first_bootflow() - Get the first bootflow from a bootdev
+ *
+ * Returns the first bootflow attached to a bootdev
+ *
+ * @dev: bootdev device
+ * @bflowp: Returns a pointer to the bootflow
+ * @return 0 if found, -ENOENT if there are no bootflows
+ */
+int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
+
+/**
+ * bootdev_next_bootflow() - Get the next bootflow from a bootdev
+ *
+ * Returns the next bootflow attached to a bootdev
+ *
+ * @bflowp: On entry, the last bootflow returned , e.g. from
+ *	bootdev_first_bootflow()
+ * @return 0 if found, -ENOENT if there are no more bootflows
+ */
+int bootdev_next_bootflow(struct bootflow **bflowp);
+
+/**
+ * bootdev_find_by_label() - Look up a bootdev by label
+ *
+ * Each bootdev has a label which contains the media-uclass name and a number,
+ * e.g. 'mmc2'. This looks up the label and returns the associated bootdev
+ *
+ * The lookup is performed based on the media device's sequence number. So for
+ * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2.
+ *
+ * @label: Label to look up (e.g. "mmc1" or "mmc0")
+ * @devp: Returns the bootdev device found, or NULL if none (note it does not
+ *	return the media device, but its bootdev child)
+ * @return 0 if OK, -EINVAL if the uclass is not supported by this board,
+ *	-ENOENT if there is no device with that number
+ */
+int bootdev_find_by_label(const char *label, struct udevice **devp);
+
+/**
+ * bootdev_find_by_any() - Find a bootdev by name, label or sequence
+ *
+ * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
+ * @devp: returns the device found, on success
+ * @return 0 if OK, -ve on error
+ */
+int bootdev_find_by_any(const char *name, struct udevice **devp);
+
+#if CONFIG_IS_ENABLED(BOOTSTD)
+/**
+ * bootdev_setup_for_dev() - Bind a new bootdev device
+ *
+ * Creates a bootdev device as a child of @parent. This should be called from
+ * the driver's bind() method or its uclass' post_bind() method.
+ *
+ * If a child bootdev already exists, this function does nothing
+ *
+ * @parent: Parent device (e.g. MMC or Ethernet)
+ * @drv_name: Name of bootdev driver to bind
+ * @return 0 if OK, -ve on error
+ */
+int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
+
+/**
+ * bootdev_setup_for_blk() - Bind a new bootdev device for a blk device
+ *
+ * Creates a bootdev device as a sibling of @blk. This should be called from
+ * the driver's bind() method or its uclass' post_bind() method, at the same
+ * time as the bould device is bound
+ *
+ * If a device of the same name already exists, this function does nothing
+ *
+ * @parent: Parent device (e.g. MMC or Ethernet)
+ * @drv_name: Name of bootdev driver to bind
+ * @return 0 if OK, -ve on error
+ */
+int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name);
+
+/**
+ * bootdev_get_sibling_blk() - Locate the block device for a bootdev
+ *
+ * @dev: bootdev to check
+ * @blkp: returns associated block device
+ * @return 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
+ *	error
+ */
+int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
+
+/**
+ * bootdev_unbind_dev() - Unbind a bootdev device
+ *
+ * Remove and unbind a bootdev device which is a child of @parent. This should
+ * be called from the driver's unbind() method or its uclass' post_bind()
+ * method.
+ *
+ * @parent: Parent device (e.g. MMC or Ethernet)
+ * @return 0 if OK, -ve on error
+ */
+int bootdev_unbind_dev(struct udevice *parent);
+#else
+static inline int bootdev_setup_for_dev(struct udevice *parent,
+					const char *drv_name)
+{
+	return 0;
+}
+
+static inline int bootdev_setup_sibling_blk(struct udevice *blk,
+					    const char *drv_name)
+{
+	return 0;
+}
+
+static inline int bootdev_unbind_dev(struct udevice *parent)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 17383fc38c1..03912cb0db8 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -38,6 +38,7 @@ enum uclass_id {
 	UCLASS_AXI,		/* AXI bus */
 	UCLASS_BLK,		/* Block device */
 	UCLASS_BOOTCOUNT,       /* Bootcount backing store */
+	UCLASS_BOOTDEV,		/* Boot device for locating an OS to boot */
 	UCLASS_BOOTSTD,		/* Standard boot driver */
 	UCLASS_BUTTON,		/* Button */
 	UCLASS_CACHE,		/* Cache controller */
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 22/41] bootstd: Add the bootmeth uclass and helpers
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (20 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 21/41] bootstd: Add the bootdev uclass Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 23/41] bootstd: Add support for bootflows Simon Glass
                     ` (35 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

A bootmeth is a method of locating an operating system. For now, just
add the uclass itself. Drivers for particular bootmeths are added later.

If no bootmeths devices are included in the devicetree, create them
automatically. This avoids the need for boilerplate in the devicetree
files.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS            |   2 +
 boot/Makefile          |   1 +
 boot/bootmeth-uclass.c |  59 ++++++++++++++++
 boot/bootstd-uclass.c  |  29 +++++++-
 include/bootmeth.h     | 156 +++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h |   1 +
 6 files changed, 246 insertions(+), 2 deletions(-)
 create mode 100644 boot/bootmeth-uclass.c
 create mode 100644 include/bootmeth.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d800a3b7acb..be11e3c2f2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -636,10 +636,12 @@ F:	tools/binman/
 BOOTDEVICE
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
+F:	boot/bootmeth*.c
 F:	boot/bootdev*.c
 F:	boot/bootstd.c
 F:	include/bootdev*.h
 F:	include/bootflow.h
+F:	include/bootmeth.h
 F:	include/bootstd.h
 
 BTRFS
diff --git a/boot/Makefile b/boot/Makefile
index 35abfd37654..54ded9541e0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
new file mode 100644
index 00000000000..5df5fb55c31
--- /dev/null
+++ b/boot/bootmeth-uclass.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmeth.h>
+#include <dm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+	if (!ops->check)
+		return 0;
+
+	return ops->check(dev, iter);
+}
+
+int bootmeth_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+	if (!ops->read_bootflow)
+		return -ENOSYS;
+
+	return ops->read_bootflow(dev, bflow);
+}
+
+int bootmeth_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+	if (!ops->boot)
+		return -ENOSYS;
+
+	return ops->boot(dev, bflow);
+}
+
+int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
+		       const char *file_path, ulong addr, ulong *sizep)
+{
+	const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+	if (!ops->read_file)
+		return -ENOSYS;
+
+	return ops->read_file(dev, bflow, file_path, addr, sizep);
+}
+
+UCLASS_DRIVER(bootmeth) = {
+	.id		= UCLASS_BOOTMETH,
+	.name		= "bootmeth",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.per_device_plat_auto	= sizeof(struct bootmeth_uc_plat),
+};
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index 04823e5ba03..f812fbd0ae8 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -102,8 +102,10 @@ static int bootstd_probe(struct udevice *dev)
 /* For now, bind the boormethod device if none are found in the devicetree */
 int dm_scan_other(bool pre_reloc_only)
 {
-	struct udevice *bootstd;
-	int ret;
+	struct driver *drv = ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct udevice *dev, *bootstd;
+	int i, ret;
 
 	/* These are not needed before relocation */
 	if (!(gd->flags & GD_FLG_RELOC))
@@ -118,6 +120,29 @@ int dm_scan_other(bool pre_reloc_only)
 			return log_msg_ret("bootstd", ret);
 	}
 
+	/* If there are no bootmeth devices, create them */
+	uclass_find_first_device(UCLASS_BOOTMETH, &dev);
+	if (dev)
+		return 0;
+
+	for (i = 0; i < n_ents; i++, drv++) {
+		/*
+		 * Disable EFI Manager for now as no one uses it so it is
+		 * confusing
+		 */
+		if (drv->id == UCLASS_BOOTMETH &&
+		    strcmp("efi_mgr_bootmeth", drv->name)) {
+			const char *name = drv->name;
+
+			if (!strncmp("bootmeth_", name, 9))
+				name += 9;
+			ret = device_bind(bootstd, drv, name, 0, ofnode_null(),
+					  &dev);			if (ret)
+
+				return log_msg_ret("meth", ret);
+		}
+	}
+
 	return 0;
 }
 
diff --git a/include/bootmeth.h b/include/bootmeth.h
new file mode 100644
index 00000000000..645fdc93add
--- /dev/null
+++ b/include/bootmeth.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootmeth_h
+#define __bootmeth_h
+
+struct bootflow;
+struct bootflow_iter;
+struct udevice;
+
+/**
+ * struct bootmeth_uc_plat - information the uclass keeps about each bootmeth
+ *
+ * @desc: A long description of the bootmeth
+ */
+struct bootmeth_uc_plat {
+	const char *desc;
+};
+
+/** struct bootmeth_ops - Operations for boot methods */
+struct bootmeth_ops {
+	/**
+	 * check_supported() - check if a bootmeth supports this bootflow
+	 *
+	 * This is optional. If not provided, the bootdev is assumed to be
+	 * supported
+	 *
+	 * The bootmeth can check the bootdev (e.g. to make sure it is a
+	 * network device) or the partition information. The following fields
+	 * in @iter are available:
+	 *
+	 *   name, dev, state, part
+	 *   max_part may be set if part != 0 (i.e. there is a valid partition
+	 *      table). Otherwise max_part is 0
+	 *   method is available but is the same as @dev
+	 *   the partition has not yet been read, nor has the filesystem been
+	 *   checked
+	 *
+	 * It may update only the flags in @iter
+	 *
+	 * @dev:	Bootmethod device to check against
+	 * @iter:	On entry, provides bootdev, hwpart, part
+	 * @return 0 if OK, -ENOTSUPP if this bootdev is not supported
+	 */
+	int (*check)(struct udevice *dev, struct bootflow_iter *iter);
+
+	/**
+	 * read_bootflow() - read a bootflow for a device
+	 *
+	 * @dev:	Bootmethod device to use
+	 * @bflow:	On entry, provides dev, hwpart, part and method.
+	 *	Returns updated bootflow if found
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*read_bootflow)(struct udevice *dev, struct bootflow *bflow);
+
+	/**
+	 * read_file() - read a file needed for a bootflow
+	 *
+	 * Read a file from the same place as the bootflow came from
+	 *
+	 * @dev:	Bootmethod device to use
+	 * @bflow:	Bootflow providing info on where to read from
+	 * @file_path:	Path to file (may be absolute or relative)
+	 * @addr:	Address to load file
+	 * @sizep:	On entry provides the maximum permitted size; on exit
+	 *		returns the size of the file
+	 * @return 0 if OK, -ENOSPC if the file is too large for @sizep, other
+	 *	-ve value if something else goes wrong
+	 */
+	int (*read_file)(struct udevice *dev, struct bootflow *bflow,
+			 const char *file_path, ulong addr, ulong *sizep);
+
+	/**
+	 * boot() - boot a bootflow
+	 *
+	 * @dev:	Bootmethod device to boot
+	 * @bflow:	Bootflow to boot
+	 * @return does not return on success, since it should boot the
+	 *	Operating Systemn. Returns -EFAULT if that fails, -ENOTSUPP if
+	 *	trying method resulted in finding out that is not actually
+	 *	supported for this boot and should not be tried again unless
+	 *	something changes, other -ve on other error
+	 */
+	int (*boot)(struct udevice *dev, struct bootflow *bflow);
+};
+
+#define bootmeth_get_ops(dev)  ((struct bootmeth_ops *)(dev)->driver->ops)
+
+/**
+ * bootmeth_check() - check if a bootmeth supports this bootflow
+ *
+ * This is optional. If not provided, the bootdev is assumed to be
+ * supported
+ *
+ * The bootmeth can check the bootdev (e.g. to make sure it is a
+ * network device) or the partition information. The following fields
+ * in @iter are available:
+ *
+ *   name, dev, state, part
+ *   max_part may be set if part != 0 (i.e. there is a valid partition
+ *      table). Otherwise max_part is 0
+ *   method is available but is the same as @dev
+ *   the partition has not yet been read, nor has the filesystem been
+ *   checked
+ *
+ * It may update only the flags in @iter
+ *
+ * @dev:	Bootmethod device to check against
+ * @iter:	On entry, provides bootdev, hwpart, part
+ * @return 0 if OK, -ENOTSUPP if this bootdev is not supported
+ */
+int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter);
+
+/**
+ * bootmeth_read_bootflow() - set up a bootflow for a device
+ *
+ * @dev:	Bootmethod device to check
+ * @bflow:	On entry, provides dev, hwpart, part and method.
+ *	Returns updated bootflow if found
+ * @return 0 if OK, -ve on error
+ */
+int bootmeth_read_bootflow(struct udevice *dev, struct bootflow *bflow);
+
+/**
+ * bootmeth_read_file() - read a file needed for a bootflow
+ *
+ * Read a file from the same place as the bootflow came from
+ *
+ * @dev:	Bootmethod device to use
+ * @bflow:	Bootflow providing info on where to read from
+ * @file_path:	Path to file (may be absolute or relative)
+ * @addr:	Address to load file
+ * @sizep:	On entry provides the maximum permitted size; on exit
+ *		returns the size of the file
+ * @return 0 if OK, -ENOSPC if the file is too large for @sizep, other
+ *	-ve value if something else goes wrong
+ */
+int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
+		       const char *file_path, ulong addr, ulong *sizep);
+
+/**
+ * bootmeth_boot() - boot a bootflow
+ *
+ * @dev:	Bootmethod device to boot
+ * @bflow:	Bootflow to boot
+ * @return does not return on success, since it should boot the
+ *	Operating Systemn. Returns -EFAULT if that fails, other -ve on
+ *	other error
+ */
+int bootmeth_boot(struct udevice *dev, struct bootflow *bflow);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 03912cb0db8..1f977672a37 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -39,6 +39,7 @@ enum uclass_id {
 	UCLASS_BLK,		/* Block device */
 	UCLASS_BOOTCOUNT,       /* Bootcount backing store */
 	UCLASS_BOOTDEV,		/* Boot device for locating an OS to boot */
+	UCLASS_BOOTMETH,	/* Bootmethod for booting an OS */
 	UCLASS_BOOTSTD,		/* Standard boot driver */
 	UCLASS_BUTTON,		/* Button */
 	UCLASS_CACHE,		/* Cache controller */
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 23/41] bootstd: Add support for bootflows
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (21 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 22/41] bootstd: Add the bootmeth uclass and helpers Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-27  7:37     ` Ilias Apalodimas
  2021-10-23 23:26   ` [PATCH v2 24/41] bootstd: Add a bootdev command Simon Glass
                     ` (34 subsequent siblings)
  57 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add support for bootflows, including maintaining a list of them and
iterating to find them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS           |   3 +-
 boot/Makefile         |   1 +
 boot/bootdev-uclass.c |  12 +-
 boot/bootflow.c       | 576 ++++++++++++++++++++++++++++++++++++++++++
 boot/bootstd-uclass.c |   2 +-
 include/bootflow.h    |  50 ++++
 6 files changed, 640 insertions(+), 4 deletions(-)
 create mode 100644 boot/bootflow.c

diff --git a/MAINTAINERS b/MAINTAINERS
index be11e3c2f2a..cbb7a160a26 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -636,8 +636,9 @@ F:	tools/binman/
 BOOTDEVICE
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
-F:	boot/bootmeth*.c
 F:	boot/bootdev*.c
+F:	boot/bootflow.c
+F:	boot/bootmeth*.c
 F:	boot/bootstd.c
 F:	include/bootdev*.h
 F:	include/bootflow.h
diff --git a/boot/Makefile b/boot/Makefile
index 54ded9541e0..f58c192ae07 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index c8455ec5159..deefe32605c 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <bootdev.h>
 #include <bootflow.h>
+#include <bootmeth.h>
 #include <bootstd.h>
 #include <fs.h>
 #include <log.h>
@@ -121,9 +122,12 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
 	if (!bflow->name)
 		return log_msg_ret("name", -ENOMEM);
 
-	bflow->state = BOOTFLOWST_BASE;
 	bflow->part = iter->part;
 
+	ret = bootmeth_check(bflow->method, iter);
+	if (ret)
+		return log_msg_ret("check", ret);
+
 	/*
 	 * partition numbers start at 0 so this cannot succeed, but it can tell
 	 * us whether there is valid media there
@@ -165,6 +169,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
 		bflow->state = BOOTFLOWST_FS;
 	}
 
+	ret = bootmeth_read_bootflow(bflow->method, bflow);
+	if (ret)
+		return log_msg_ret("method", ret);
+
 	return 0;
 }
 
@@ -401,7 +409,7 @@ void bootdev_clear_bootflows(struct udevice *dev)
 
 		bflow = list_first_entry(&ucp->bootflow_head, struct bootflow,
 					 bm_node);
-		/* later bootflow_remove(bflow); */
+		bootflow_remove(bflow);
 	}
 }
 
diff --git a/boot/bootflow.c b/boot/bootflow.c
new file mode 100644
index 00000000000..b87b656f5bd
--- /dev/null
+++ b/boot/bootflow.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <env.h>
+#include <malloc.h>
+#include <sort.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* error codes used to signal running out of things */
+enum {
+	BF_NO_MORE_PARTS	= -ESHUTDOWN,
+	BF_NO_MORE_DEVICES	= -ENODEV,
+};
+
+static const char *const bootflow_state[BOOTFLOWST_COUNT] = {
+	"base",
+	"media",
+	"part",
+	"fs",
+	"file",
+	"ready",
+};
+
+const char *bootflow_state_get_name(enum bootflow_state_t state)
+{
+	if (state < 0 || state >= BOOTFLOWST_COUNT)
+		return "?";
+
+	return bootflow_state[state];
+}
+
+int bootflow_first_glob(struct bootflow **bflowp)
+{
+	struct bootstd_priv *std;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	if (list_empty(&std->glob_head))
+		return -ENOENT;
+
+	*bflowp = list_first_entry(&std->glob_head, struct bootflow,
+				   glob_node);
+
+	return 0;
+}
+
+int bootflow_next_glob(struct bootflow **bflowp)
+{
+	struct bootstd_priv *std;
+	struct bootflow *bflow = *bflowp;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	*bflowp = NULL;
+
+	if (list_is_last(&bflow->glob_node, &std->glob_head))
+		return -ENOENT;
+
+	*bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node);
+
+	return 0;
+}
+
+void bootflow_iter_init(struct bootflow_iter *iter, int flags)
+{
+	memset(iter, '\0', sizeof(*iter));
+	iter->flags = flags;
+}
+
+void bootflow_iter_uninit(struct bootflow_iter *iter)
+{
+	free(iter->dev_order);
+	free(iter->method_order);
+}
+
+int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
+				const struct udevice *bmeth)
+{
+	/* We only support disabling the current bootmeth */
+	if (bmeth != iter->method || iter->cur_method >= iter->num_methods ||
+	    iter->method_order[iter->cur_method] != bmeth)
+		return -EINVAL;
+
+	memmove(&iter->method_order[iter->cur_method],
+		&iter->method_order[iter->cur_method + 1],
+		(iter->num_methods - iter->cur_method - 1) * sizeof(void *));
+
+	iter->num_methods--;
+
+	return 0;
+}
+
+static void bootflow_iter_set_dev(struct bootflow_iter *iter,
+				  struct udevice *dev)
+{
+	iter->dev = dev;
+	if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
+	    BOOTFLOWF_SHOW) {
+		if (dev)
+			printf("Scanning bootdev '%s':\n", dev->name);
+		else
+			printf("No more bootdevs\n");
+	}
+}
+
+/**
+ * h_cmp_bootdev() - Compare two bootdevs to find out which should go first
+ *
+ * @v1: struct udevice * of first bootdev device
+ * @v2: struct udevice * of second bootdev device
+ * @return sort order (<0 if dev1 < dev2, ==0 if equal, >0 if dev1 > dev2)
+ */
+static int h_cmp_bootdev(const void *v1, const void *v2)
+{
+	const struct udevice *dev1 = *(struct udevice **)v1;
+	const struct udevice *dev2 = *(struct udevice **)v2;
+	const struct bootdev_uc_plat *ucp1 = dev_get_uclass_plat(dev1);
+	const struct bootdev_uc_plat *ucp2 = dev_get_uclass_plat(dev2);
+	int diff;
+
+	/* Use priority first */
+	diff = ucp1->prio - ucp2->prio;
+	if (diff)
+		return diff;
+
+	/* Fall back to seq for devices of the same priority */
+	diff = dev_seq(dev1) - dev_seq(dev2);
+
+	return diff;
+}
+
+/**
+ * setup_order() - Set up the ordering of bootdevs to scan
+ *
+ * This sets up the ordering information in @iter, based on the priority of each
+ * bootdev and the bootdev-order property in the bootstd node
+ *
+ * If a single device is requested, no ordering is needed
+ *
+ * @iter: Iterator to update with the order
+ * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
+ *	device to scan. Returns the first device to use, which is the passed-in
+ *	@devp if it was non-NULL
+ * @return 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
+ *	on other error
+ */
+static int setup_bootdev_order(struct bootflow_iter *iter,
+			       struct udevice **devp)
+{
+	struct udevice *bootstd, *dev = *devp, **order;
+	const char *const *labels;
+	int upto, i;
+	int count;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
+	if (ret) {
+		log_err("Missing bootstd device\n");
+		return log_msg_ret("std", ret);
+	}
+
+	/* Handle scanning a single device */
+	if (dev) {
+		iter->flags |= BOOTFLOWF_SINGLE_DEV;
+		return 0;
+	}
+
+	count = uclass_id_count(UCLASS_BOOTDEV);
+	if (!count)
+		return log_msg_ret("count", -ENOENT);
+
+	order = calloc(count, sizeof(struct udevice *));
+	if (!order)
+		return log_msg_ret("order", -ENOMEM);
+
+	/*
+	 * Get a list of bootdevs, in seq order (i.e. using aliases). There may
+	 * be gaps so try to count up high enough to find them all.
+	 */
+	for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) {
+		ret = uclass_find_device_by_seq(UCLASS_BOOTDEV, i, &dev);
+		if (!ret)
+			order[upto++] = dev;
+	}
+	log_debug("Found %d bootdevs\n", count);
+	if (upto != count)
+		log_warning("Expected %d bootdevs, found %d using aliases\n",
+			    count, upto);
+	count = upto;
+
+	labels = bootstd_get_bootdev_order(bootstd);
+	if (labels) {
+		upto = 0;
+		for (i = 0; labels[i]; i++) {
+			ret = bootdev_find_by_label(labels[i], &dev);
+			if (!ret) {
+				if (upto == count) {
+					log_warning("Expected at most %d bootdevs, but overflowed with boot_target '%s'\n",
+						    count, labels[i]);
+					break;
+				}
+				order[upto++] = dev;
+			}
+		}
+		count = upto;
+		if (!count) {
+			free(order);
+			return log_msg_ret("targ", -ENOMEM);
+		}
+	} else {
+		/* sort them into priorty order */
+		qsort(order, count, sizeof(struct udevice *), h_cmp_bootdev);
+	}
+
+	iter->dev_order = order;
+	iter->num_devs = count;
+	iter->cur_dev = 0;
+
+	dev = *order;
+	ret = device_probe(dev);
+	if (ret)
+		return log_msg_ret("probe", ret);
+	*devp = dev;
+
+	return 0;
+}
+
+/**
+ * setup_bootmeth_order() - Set up the ordering of bootmeths to scan
+ *
+ * This sets up the ordering information in @iter, based on the selected
+ * ordering of the bootmethds in bootstd_priv->bootmeth_order. If there is no
+ * ordering there, then all bootmethods are added
+ *
+ * @iter: Iterator to update with the order
+ * @return 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
+ *	on other error
+ */
+static int setup_bootmeth_order(struct bootflow_iter *iter)
+{
+	struct bootstd_priv *std;
+	struct udevice **order;
+	int count;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	/* Create an array large enough */
+	count = std->bootmeth_count ? std->bootmeth_count :
+		uclass_id_count(UCLASS_BOOTMETH);
+	if (!count)
+		return log_msg_ret("count", -ENOENT);
+
+	order = calloc(count, sizeof(struct udevice *));
+	if (!order)
+		return log_msg_ret("order", -ENOMEM);
+
+	/* If we have an ordering, copy it */
+	if (std->bootmeth_count) {
+		memcpy(order, std->bootmeth_order,
+		       count * sizeof(struct bootmeth *));
+	} else {
+		struct udevice *dev;
+		int i, upto;
+
+		/*
+		 * Get a list of bootmethods, in seq order (i.e. using aliases).
+		 * There may be gaps so try to count up high enough to find them
+		 * all.
+		 */
+		for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) {
+			ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, i,
+						       &dev);
+			if (!ret)
+				order[upto++] = dev;
+		}
+		count = upto;
+	}
+
+	iter->method_order = order;
+	iter->num_methods = count;
+	iter->cur_method = 0;
+
+	return 0;
+}
+
+/**
+ * iter_incr() - Move to the next item (method, part, bootdev)
+ *
+ * @return 0 if OK, BF_NO_MORE_DEVICES if there are no more bootdevs
+ */
+static int iter_incr(struct bootflow_iter *iter)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (iter->err == BF_NO_MORE_DEVICES)
+		return BF_NO_MORE_DEVICES;
+
+	if (iter->err != BF_NO_MORE_PARTS) {
+		/* Get the next boothmethod */
+		if (++iter->cur_method < iter->num_methods) {
+			iter->method = iter->method_order[iter->cur_method];
+			return 0;
+		}
+	}
+
+	/* No more bootmeths; start at the first one, and... */
+	iter->cur_method = 0;
+	iter->method = iter->method_order[iter->cur_method];
+
+	if (iter->err != BF_NO_MORE_PARTS) {
+		/* ...select next partition  */
+		if (++iter->part <= iter->max_part)
+			return 0;
+	}
+
+	/* No more partitions; start at the first one and...*/
+	iter->part = 0;
+
+	/*
+	 * Note: as far as we know, there is no partition table on the next
+	 * bootdev, so set max_part to 0 until we discover otherwise. See
+	 * bootdev_find_in_blk() for where this is set.
+	 */
+	iter->max_part = 0;
+
+	/* ...select next bootdev */
+	if (iter->flags & BOOTFLOWF_SINGLE_DEV) {
+		ret = -ENOENT;
+	} else if (++iter->cur_dev == iter->num_devs) {
+		ret = -ENOENT;
+		bootflow_iter_set_dev(iter, NULL);
+	} else {
+		dev = iter->dev_order[iter->cur_dev];
+		ret = device_probe(dev);
+		if (!log_msg_ret("probe", ret))
+			bootflow_iter_set_dev(iter, dev);
+	}
+
+	/* if there are no more bootdevs, give up */
+	if (ret)
+		return log_msg_ret("next", BF_NO_MORE_DEVICES);
+
+	return 0;
+}
+
+/**
+ * bootflow_check() - Check if a bootflow can be obtained
+ *
+ * @iter: Provides part, bootmeth to use
+ * @bflow: Bootflow to update on success
+ * @return 0 if OK, -ENOSYS if there is no bootflow support on this device,
+ *	BF_NO_MORE_PARTS if there are no more partitions on bootdev
+ */
+static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
+{
+	struct udevice *dev;
+	int ret;
+
+	dev = iter->dev;
+	ret = bootdev_get_bootflow(dev, iter, bflow);
+
+	/* If we got a valid bootflow, return it */
+	if (!ret) {
+		log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n",
+			  dev->name, iter->part, iter->method->name);
+		return 0;
+	}
+
+	/* Unless there is nothing more to try, move to the next device */
+	else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
+		log_debug("Bootdevice '%s' part %d method '%s': Error %d\n",
+			  dev->name, iter->part, iter->method->name, ret);
+		/*
+		 * For 'all' we return all bootflows, even
+		 * those with errors
+		 */
+		if (iter->flags & BOOTFLOWF_ALL)
+			return log_msg_ret("all", ret);
+	}
+	if (ret)
+		return log_msg_ret("check", ret);
+
+	return 0;
+}
+
+int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
+			  int flags, struct bootflow *bflow)
+{
+	int ret;
+
+	bootflow_iter_init(iter, flags);
+
+	ret = setup_bootdev_order(iter, &dev);
+	if (ret)
+		return log_msg_ret("obdev", -ENODEV);
+	bootflow_iter_set_dev(iter, dev);
+
+	ret = setup_bootmeth_order(iter);
+	if (ret)
+		return log_msg_ret("obmeth", -ENODEV);
+
+	/* Find the first bootmeth (there must be at least one!) */
+	iter->method = iter->method_order[iter->cur_method];
+
+	ret = bootflow_check(iter, bflow);
+	if (ret) {
+		if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
+			if (iter->flags & BOOTFLOWF_ALL)
+				return log_msg_ret("all", ret);
+		}
+		iter->err = ret;
+		ret = bootflow_scan_next(iter, bflow);
+		if (ret)
+			return log_msg_ret("get", ret);
+	}
+
+	return 0;
+}
+
+int bootflow_scan_first(struct bootflow_iter *iter, int flags,
+			struct bootflow *bflow)
+{
+	return bootflow_scan_bootdev(NULL, iter, flags, bflow);
+}
+
+int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow)
+{
+	int ret;
+
+	do {
+		ret = iter_incr(iter);
+		if (ret == BF_NO_MORE_DEVICES)
+			return log_msg_ret("done", ret);
+
+		if (!ret) {
+			ret = bootflow_check(iter, bflow);
+			if (!ret)
+				return 0;
+			iter->err = ret;
+			if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
+				if (iter->flags & BOOTFLOWF_ALL)
+					return log_msg_ret("all", ret);
+			}
+		} else {
+			iter->err = ret;
+		}
+
+	} while (1);
+}
+
+void bootflow_free(struct bootflow *bflow)
+{
+	free(bflow->name);
+	free(bflow->subdir);
+	free(bflow->fname);
+	free(bflow->buf);
+}
+
+void bootflow_remove(struct bootflow *bflow)
+{
+	list_del(&bflow->bm_node);
+	list_del(&bflow->glob_node);
+
+	bootflow_free(bflow);
+	free(bflow);
+}
+
+int bootflow_boot(struct bootflow *bflow)
+{
+	int ret;
+
+	if (bflow->state != BOOTFLOWST_READY)
+		return log_msg_ret("load", -EPROTO);
+
+	ret = bootmeth_boot(bflow->method, bflow);
+	if (ret)
+		return log_msg_ret("boot", ret);
+
+	/*
+	 * internal error, should not get here since we should have booted
+	 * something or returned an error
+	 */
+
+	return log_msg_ret("end", -EFAULT);
+}
+
+int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow)
+{
+	int ret;
+
+	printf("** Booting bootflow '%s'\n", bflow->name);
+	ret = bootflow_boot(bflow);
+	switch (ret) {
+	case -EPROTO:
+		printf("Bootflow not loaded (state '%s')\n",
+		       bootflow_state_get_name(bflow->state));
+		break;
+	case -ENOSYS:
+		printf("Boot method '%s' not supported\n", bflow->method->name);
+		break;
+	case -ENOTSUPP:
+		/* Disable this bootflow for this iteration */
+		if (iter) {
+			int ret2;
+
+			ret2 = bootflow_iter_drop_bootmeth(iter, bflow->method);
+			if (!ret2) {
+				printf("Boot method '%s' failed and will not be retried\n",
+				       bflow->method->name);
+			}
+		}
+
+		break;
+	default:
+		printf("Boot failed (err=%d)\n", ret);
+		break;
+	}
+
+	return ret;
+}
+
+int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter)
+{
+	const struct udevice *media = dev_get_parent(iter->dev);
+	enum uclass_id id = device_get_uclass_id(media);
+
+	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
+	if (id != UCLASS_ETH && id != UCLASS_BOOTSTD)
+		return 0;
+
+	return -ENOTSUPP;
+}
+
+int bootflow_iter_uses_network(const struct bootflow_iter *iter)
+{
+	const struct udevice *media = dev_get_parent(iter->dev);
+	enum uclass_id id = device_get_uclass_id(media);
+
+	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
+	if (id == UCLASS_ETH)
+		return 0;
+
+	return -ENOTSUPP;
+}
+
+int bootflow_iter_uses_system(const struct bootflow_iter *iter)
+{
+	const struct udevice *media = dev_get_parent(iter->dev);
+	enum uclass_id id = device_get_uclass_id(media);
+
+	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
+	if (id == UCLASS_BOOTSTD)
+		return 0;
+
+	return -ENOTSUPP;
+}
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index f812fbd0ae8..7dddd72bc4a 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -38,7 +38,7 @@ static void bootstd_clear_glob_(struct bootstd_priv *priv)
 
 		bflow = list_first_entry(&priv->glob_head, struct bootflow,
 					 glob_node);
-		/* add later bootflow_remove(bflow); */
+		bootflow_remove(bflow);
 	}
 }
 
diff --git a/include/bootflow.h b/include/bootflow.h
index 56ff101a78a..420400c8363 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -145,6 +145,18 @@ void bootflow_iter_init(struct bootflow_iter *iter, int flags);
  */
 void bootflow_iter_uninit(struct bootflow_iter *iter);
 
+/**
+ * bootflow_iter_drop_bootmeth() - Remove a bootmeth from an iterator
+ *
+ * Update the iterator so that the bootmeth will not be used again while this
+ * iterator is in use
+ *
+ * @iter: Iterator to update
+ * @bmeth: Boot method to remove
+ */
+int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
+				const struct udevice *bmeth);
+
 /**
  * bootflow_scan_bootdev() - find the first bootflow in a bootdev
  *
@@ -251,4 +263,42 @@ int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow);
  */
 const char *bootflow_state_get_name(enum bootflow_state_t state);
 
+/**
+ * bootflow_remove() - Remove a bootflow and free its memory
+ *
+ * This updates the linked lists containing the bootflow then frees it.
+ *
+ * @bflow: Bootflow to remove
+ */
+void bootflow_remove(struct bootflow *bflow);
+
+/**
+ * bootflow_iter_uses_blk_dev() - Check that a bootflow uses a block device
+ *
+ * This checks the bootdev in the bootflow to make sure it uses a block device
+ *
+ * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
+ */
+int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter);
+
+/**
+ * bootflow_iter_uses_network() - Check that a bootflow uses a network device
+ *
+ * This checks the bootdev in the bootflow to make sure it uses a network
+ * device
+ *
+ * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC)
+ */
+int bootflow_iter_uses_network(const struct bootflow_iter *iter);
+
+/**
+ * bootflow_iter_uses_system() - Check that a bootflow uses the bootstd device
+ *
+ * This checks the bootdev in the bootflow to make sure it uses the bootstd
+ * device
+ *
+ * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC)
+ */
+int bootflow_iter_uses_system(const struct bootflow_iter *iter);
+
 #endif
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 24/41] bootstd: Add a bootdev command
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (22 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 23/41] bootstd: Add support for bootflows Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 25/41] bootstd: Add a bootflow ommand Simon Glass
                     ` (33 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a 'bootdev' command to handle listing and selection of bootdevs.

Disable standard boot for a few boards which otherwise run out of space.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS                        |   1 +
 cmd/Kconfig                        |   8 ++
 cmd/Makefile                       |   1 +
 cmd/bootdev.c                      | 120 +++++++++++++++++++++++++++++
 configs/amcore_defconfig           |   1 +
 configs/rcar3_salvator-x_defconfig |   1 +
 configs/tbs2910_defconfig          |   1 +
 7 files changed, 133 insertions(+)
 create mode 100644 cmd/bootdev.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cbb7a160a26..a95329286da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -640,6 +640,7 @@ F:	boot/bootdev*.c
 F:	boot/bootflow.c
 F:	boot/bootmeth*.c
 F:	boot/bootstd.c
+F:	cmd/bootdev.c
 F:	include/bootdev*.h
 F:	include/bootflow.h
 F:	include/bootmeth.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 5b30b13e438..bb6b881660c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -194,6 +194,14 @@ config CMD_BOOTM
 	help
 	  Boot an application image from the memory.
 
+config CMD_BOOTSTD
+	bool "bootdev"
+	depends on BOOTSTD
+	default y
+	help
+	  Support working with standard boot, including listing available
+	  bootdevs and showing information about a particular one.
+
 config BOOTM_EFI
 	bool "Support booting UEFI FIT images"
 	depends on CMD_BOOTEFI && CMD_BOOTM && FIT
diff --git a/cmd/Makefile b/cmd/Makefile
index 891819ae0f6..a8fce22d6c6 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o
 obj-$(CONFIG_CMD_ADC) += adc.o
 obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
 obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o
+obj-$(CONFIG_CMD_BOOTSTD) += bootdev.o
 obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BCB) += bcb.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
diff --git a/cmd/bootdev.c b/cmd/bootdev.c
new file mode 100644
index 00000000000..ecd797c0503
--- /dev/null
+++ b/cmd/bootdev.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootdev' command
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+static int bootdev_check_state(struct bootstd_priv **stdp)
+{
+	struct bootstd_priv *std;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+	if (!std->cur_bootdev) {
+		printf("Please use 'bootdev select' first\n");
+		return -ENOENT;
+	}
+	*stdp = std;
+
+	return 0;
+}
+
+static int do_bootdev_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			   char *const argv[])
+{
+	bool probe;
+
+	probe = argc >= 2 && !strcmp(argv[1], "-p");
+	bootdev_list(probe);
+
+	return 0;
+}
+
+static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc,
+			     char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+	if (argc < 2) {
+		std->cur_bootdev = NULL;
+		return 0;
+	}
+	if (bootdev_find_by_any(argv[1], &dev))
+		return CMD_RET_FAILURE;
+
+	std->cur_bootdev = dev;
+
+	return 0;
+}
+
+static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			   char *const argv[])
+{
+	struct bootstd_priv *priv;
+	struct bootflow *bflow;
+	int ret, i, num_valid;
+	struct udevice *dev;
+	bool probe;
+
+	probe = argc >= 2 && !strcmp(argv[1], "-p");
+
+	ret = bootdev_check_state(&priv);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	dev = priv->cur_bootdev;
+
+	/* Count the number of bootflows, including how many are valid*/
+	num_valid = 0;
+	for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
+	     !ret;
+	     ret = bootdev_next_bootflow(&bflow), i++)
+		num_valid += bflow->state == BOOTFLOWST_READY;
+
+	/*
+	 * Prove the device, if requested, otherwise assume that there is no
+	 * error
+	 */
+	ret = 0;
+	if (probe)
+		ret = device_probe(dev);
+
+	printf("Name:      %s\n", dev->name);
+	printf("Sequence:  %d\n", dev_seq(dev));
+	printf("Status:    %s\n", ret ? simple_itoa(ret) : device_active(dev) ?
+		"Probed" : "OK");
+	printf("Uclass:    %s\n", dev_get_uclass_name(dev_get_parent(dev)));
+	printf("Bootflows: %d (%d valid)\n", i, num_valid);
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootdev_help_text[] =
+	"list [-p]      - list all available bootdevs (-p to probe)\n"
+	"bootdev select <bd>    - select a bootdev by name | label | seq\n"
+	"bootdev info [-p]      - show information about a bootdev (-p to probe)";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list),
+	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select),
+	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info));
diff --git a/configs/amcore_defconfig b/configs/amcore_defconfig
index 4befa7a62bd..822da8a81c6 100644
--- a/configs/amcore_defconfig
+++ b/configs/amcore_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYS_MALLOC_LEN=0x100000
 CONFIG_DEFAULT_DEVICE_TREE="amcore"
 CONFIG_TARGET_AMCORE=y
 CONFIG_SYS_LOAD_ADDR=0x20000
+# CONFIG_BOOTSTD is not set
 CONFIG_BOOTDELAY=1
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/rcar3_salvator-x_defconfig b/configs/rcar3_salvator-x_defconfig
index 3b48ab2751b..c742f0304e3 100644
--- a/configs/rcar3_salvator-x_defconfig
+++ b/configs/rcar3_salvator-x_defconfig
@@ -11,6 +11,7 @@ CONFIG_RCAR_GEN3=y
 CONFIG_TARGET_SALVATOR_X=y
 CONFIG_SYS_LOAD_ADDR=0x58000000
 CONFIG_FIT=y
+# CONFIG_BOOTSTD is not set
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_USE_BOOTARGS=y
 CONFIG_DEFAULT_FDT_FILE="r8a77950-salvator-x.dtb"
diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig
index d393975a190..2f8eef41c55 100644
--- a/configs/tbs2910_defconfig
+++ b/configs/tbs2910_defconfig
@@ -14,6 +14,7 @@ CONFIG_DEFAULT_DEVICE_TREE="imx6q-tbs2910"
 CONFIG_PRE_CON_BUF_ADDR=0x7c000000
 CONFIG_CMD_HDMIDETECT=y
 CONFIG_AHCI=y
+# CONFIG_BOOTSTD is not set
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTCOMMAND=y
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 25/41] bootstd: Add a bootflow ommand
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (23 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 24/41] bootstd: Add a bootdev command Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 26/41] bootstd: Add a bootmeth command Simon Glass
                     ` (32 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a 'bootflow' command to handle listing and selection of bootflow.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 cmd/Kconfig    |  10 +-
 cmd/Makefile   |   2 +-
 cmd/bootflow.c | 386 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 395 insertions(+), 3 deletions(-)
 create mode 100644 cmd/bootflow.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index bb6b881660c..1b6900d7f52 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -195,12 +195,18 @@ config CMD_BOOTM
 	  Boot an application image from the memory.
 
 config CMD_BOOTSTD
-	bool "bootdev"
+	bool "bootdev, bootflow"
 	depends on BOOTSTD
 	default y
 	help
 	  Support working with standard boot, including listing available
-	  bootdevs and showing information about a particular one.
+	  bootdevs and showing information about a particular one. It also
+	  allows scanning for bootflows available with the bootdev.
+
+	  This enables the following commands:
+
+	     bootdev
+	     bootflow
 
 config BOOTM_EFI
 	bool "Support booting UEFI FIT images"
diff --git a/cmd/Makefile b/cmd/Makefile
index a8fce22d6c6..1b4ff861871 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -19,7 +19,7 @@ obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o
 obj-$(CONFIG_CMD_ADC) += adc.o
 obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
 obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o
-obj-$(CONFIG_CMD_BOOTSTD) += bootdev.o
+obj-$(CONFIG_CMD_BOOTSTD) += bootdev.o bootflow.o
 obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BCB) += bcb.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
new file mode 100644
index 00000000000..84b9970bd65
--- /dev/null
+++ b/cmd/bootflow.c
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootflow' command
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <mapmem.h>
+
+/**
+ * report_bootflow_err() - Report where a bootflow failed
+ *
+ * When a bootflow does not make it to the 'loaded' state, something went wrong.
+ * Print a helpful message if there is an error
+ *
+ * @bflow: Bootflow to process
+ * @err: Error code (0 if none)
+ */
+static void report_bootflow_err(struct bootflow *bflow, int err)
+{
+	if (!err)
+		return;
+
+	/* Indent out to 'Method' */
+	printf("     ** ");
+
+	switch (bflow->state) {
+	case BOOTFLOWST_BASE:
+		printf("No media/partition found");
+		break;
+	case BOOTFLOWST_MEDIA:
+		printf("No partition found");
+		break;
+	case BOOTFLOWST_PART:
+		printf("No filesystem found");
+		break;
+	case BOOTFLOWST_FS:
+		printf("File not found");
+		break;
+	case BOOTFLOWST_FILE:
+		printf("File cannot be loaded");
+		break;
+	case BOOTFLOWST_READY:
+		printf("Ready");
+		break;
+	case BOOTFLOWST_COUNT:
+		break;
+	}
+
+	printf(", err=%d\n", err);
+}
+
+/**
+ * show_bootflow() - Show the status of a bootflow
+ *
+ * @seq: Bootflow index
+ * @bflow: Bootflow to show
+ * @errors: True to show the error received, if any
+ */
+static void show_bootflow(int index, struct bootflow *bflow, bool errors)
+{
+	printf("%3x  %-11s  %-6s  %-9.9s %4x  %-25.25s %s\n", index,
+	       bflow->method->name, bootflow_state_get_name(bflow->state),
+	       dev_get_uclass_name(dev_get_parent(bflow->dev)), bflow->part,
+	       bflow->name, bflow->fname);
+	if (errors)
+		report_bootflow_err(bflow, bflow->err);
+}
+
+static void show_header(void)
+{
+	printf("Seq  Method       State   Uclass    Part  Name                      Filename\n");
+	printf("---  -----------  ------  --------  ----  ------------------------  ----------------\n");
+}
+
+static void show_footer(int count, int num_valid)
+{
+	printf("---  -----------  ------  --------  ----  ------------------------  ----------------\n");
+	printf("(%d bootflow%s, %d valid)\n", count, count != 1 ? "s" : "",
+	       num_valid);
+}
+
+static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	struct bootflow *bflow;
+	int num_valid = 0;
+	bool errors = false;
+	int ret, i;
+
+	if (argc > 1 && *argv[1] == '-')
+		errors = strchr(argv[1], 'e');
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+	dev = std->cur_bootdev;
+
+	/* If we have a device, just list bootflows attached to that device */
+	if (dev) {
+		printf("Showing bootflows for bootdev '%s'\n", dev->name);
+		show_header();
+		for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
+		     !ret;
+		     ret = bootdev_next_bootflow(&bflow), i++) {
+			num_valid += bflow->state == BOOTFLOWST_READY;
+			show_bootflow(i, bflow, errors);
+		}
+	} else {
+		printf("Showing all bootflows\n");
+		show_header();
+		for (ret = bootflow_first_glob(&bflow), i = 0;
+		     !ret;
+		     ret = bootflow_next_glob(&bflow), i++) {
+			num_valid += bflow->state == BOOTFLOWST_READY;
+			show_bootflow(i, bflow, errors);
+		}
+	}
+	show_footer(i, num_valid);
+
+	return 0;
+}
+
+static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct bootflow_iter iter;
+	struct udevice *dev;
+	struct bootflow bflow;
+	bool all = false, boot = false, errors = false, list = false;
+	int num_valid = 0;
+	int ret, i;
+	int flags;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+	dev = std->cur_bootdev;
+
+	if (argc > 1 && *argv[1] == '-') {
+		all = strchr(argv[1], 'a');
+		boot = strchr(argv[1], 'b');
+		errors = strchr(argv[1], 'e');
+		list = strchr(argv[1], 'l');
+		argc--;
+		argv++;
+	}
+	if (argc > 1) {
+		const char *label = argv[1];
+
+		if (bootdev_find_by_any(label, &dev))
+			return CMD_RET_FAILURE;
+	}
+
+	std->cur_bootflow = NULL;
+
+	flags = 0;
+	if (list)
+		flags |= BOOTFLOWF_SHOW;
+	if (all)
+		flags |= BOOTFLOWF_ALL;
+
+	/*
+	 * If we have a device, just scan for bootflows attached to that device
+	 */
+	if (dev) {
+		if (list) {
+			printf("Scanning for bootflows in bootdev '%s'\n",
+			       dev->name);
+			show_header();
+		}
+		bootdev_clear_bootflows(dev);
+		for (i = 0,
+		     ret = bootflow_scan_bootdev(dev, &iter, flags, &bflow);
+		     i < 1000 && ret != -ENODEV;
+		     i++, ret = bootflow_scan_next(&iter, &bflow)) {
+			bflow.err = ret;
+			if (!ret)
+				num_valid++;
+			ret = bootdev_add_bootflow(&bflow);
+			if (ret) {
+				printf("Out of memory\n");
+				return CMD_RET_FAILURE;
+			}
+			if (list)
+				show_bootflow(i, &bflow, errors);
+			if (boot && !bflow.err)
+				bootflow_run_boot(&iter, &bflow);
+		}
+	} else {
+		if (list) {
+			printf("Scanning for bootflows in all bootdevs\n");
+			show_header();
+		}
+		bootstd_clear_glob();
+
+		for (i = 0,
+		     ret = bootflow_scan_first(&iter, flags, &bflow);
+		     i < 1000 && ret != -ENODEV;
+		     i++, ret = bootflow_scan_next(&iter, &bflow)) {
+			bflow.err = ret;
+			if (!ret)
+				num_valid++;
+			ret = bootdev_add_bootflow(&bflow);
+			if (ret) {
+				printf("Out of memory\n");
+				return CMD_RET_FAILURE;
+			}
+			if (list)
+				show_bootflow(i, &bflow, errors);
+			if (boot && !bflow.err) {
+				bootflow_run_boot(&iter, &bflow);
+			}
+		}
+	}
+	bootflow_iter_uninit(&iter);
+	if (list)
+		show_footer(i, num_valid);
+
+	return 0;
+}
+
+static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct bootflow *bflow, *found;
+	struct udevice *dev;
+	const char *name;
+	char *endp;
+	int seq, i;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+;
+	if (argc < 2) {
+		std->cur_bootflow = NULL;
+		return 0;
+	}
+	dev = std->cur_bootdev;
+
+	name = argv[1];
+	seq = simple_strtol(name, &endp, 16);
+	found = NULL;
+
+	/*
+	 * If we have a bootdev device, only allow selection of bootflows
+	 * attached to that device
+	 */
+	if (dev) {
+		for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
+		     !ret;
+		     ret = bootdev_next_bootflow(&bflow), i++) {
+			if (*endp ? !strcmp(bflow->name, name) : (i == seq)) {
+				found = bflow;
+				break;
+			}
+		}
+	} else {
+		for (ret = bootflow_first_glob(&bflow), i = 0;
+		     !ret;
+		     ret = bootflow_next_glob(&bflow), i++) {
+			if (*endp ? !strcmp(bflow->name, name) : (i == seq)) {
+				found = bflow;
+				break;
+			}
+		}
+	}
+
+	if (!found) {
+		printf("Cannot find bootflow '%s' ", name);
+		if (dev)
+			printf("in bootdev '%s' ", dev->name);
+		printf("(err=%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+	std->cur_bootflow = found;
+
+	return 0;
+}
+
+static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct bootflow *bflow;
+	bool dump = false;
+	int ret;
+
+	if (argc > 1 && *argv[1] == '-')
+		dump = strchr(argv[1], 'd');
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (!std->cur_bootflow) {
+		printf("No bootflow selected\n");
+		return CMD_RET_FAILURE;
+	}
+	bflow = std->cur_bootflow;
+
+	printf("Name:      %s\n", bflow->name);
+	printf("Device:    %s\n", bflow->dev->name);
+	printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)");
+	printf("Method:    %s\n", bflow->method->name);
+	printf("State:     %s\n", bootflow_state_get_name(bflow->state));
+	printf("Partition: %d\n", bflow->part);
+	printf("Subdir:    %s\n", bflow->subdir ? bflow->subdir : "(none)");
+	printf("Filename:  %s\n", bflow->fname);
+	printf("Buffer:    %lx\n", (ulong)map_to_sysmem(bflow->buf));
+	printf("Size:      %x (%d bytes)\n", bflow->size, bflow->size);
+	printf("Error:     %d\n", bflow->err);
+	if (dump && bflow->buf) {
+		/* Set some sort of maximum on the size */
+		int size = min(bflow->size, 10 << 10);
+		int i;
+
+		printf("Contents:\n\n");
+		for (i = 0; i < size; i++) {
+			putc(bflow->buf[i]);
+			if (!(i % 128) && ctrlc()) {
+				printf("...interrupted\n");
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct bootflow *bflow;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/*
+	 * Require a current bootflow. Users can use 'bootflow scan -b' to
+	 * automatically scan and boot, if needed.
+	 */
+	if (!std->cur_bootflow) {
+		printf("No bootflow selected\n");
+		return CMD_RET_FAILURE;
+	}
+	bflow = std->cur_bootflow;
+	ret = bootflow_run_boot(NULL, bflow);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootflow_help_text[] =
+	"scan [-abel] [bdev]   - scan for valid bootflows (-l list, -a all, -e errors, -b boot)\n"
+	"bootflow list [-e]             - list scanned bootflows (-e errors)\n"
+	"bootflow select [<num>|<name>] - select a bootflow\n"
+	"bootflow info [-d]             - show info on current bootflow (-d dump bootflow)\n"
+	"bootflow boot                  - boot current bootflow (or first available if none selected)";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
+	U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_bootflow_scan),
+	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list),
+	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select),
+	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
+	U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot));
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 26/41] bootstd: Add a bootmeth command
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (24 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 25/41] bootstd: Add a bootflow ommand Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 27/41] bootstd: Add an implementation of distro boot Simon Glass
                     ` (31 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a 'bootmeth' command to handle listing and ordering of boot methods.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 cmd/Kconfig    |   3 +-
 cmd/Makefile   |   2 +-
 cmd/bootmeth.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+), 2 deletions(-)
 create mode 100644 cmd/bootmeth.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1b6900d7f52..9febb4ce1a5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -195,7 +195,7 @@ config CMD_BOOTM
 	  Boot an application image from the memory.
 
 config CMD_BOOTSTD
-	bool "bootdev, bootflow"
+	bool "bootdev, bootflow, bootmeth"
 	depends on BOOTSTD
 	default y
 	help
@@ -207,6 +207,7 @@ config CMD_BOOTSTD
 
 	     bootdev
 	     bootflow
+	     bootmeth
 
 config BOOTM_EFI
 	bool "Support booting UEFI FIT images"
diff --git a/cmd/Makefile b/cmd/Makefile
index 1b4ff861871..56defcde667 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -19,7 +19,7 @@ obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o
 obj-$(CONFIG_CMD_ADC) += adc.o
 obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
 obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o
-obj-$(CONFIG_CMD_BOOTSTD) += bootdev.o bootflow.o
+obj-$(CONFIG_CMD_BOOTSTD) += bootdev.o bootflow.o bootmeth.o
 obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BCB) += bcb.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
diff --git a/cmd/bootmeth.c b/cmd/bootmeth.c
new file mode 100644
index 00000000000..77ca7375837
--- /dev/null
+++ b/cmd/bootmeth.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootmeth' command
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <command.h>
+#include <dm.h>
+#include <malloc.h>
+#include <dm/uclass-internal.h>
+
+static int do_bootmeth_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct udevice *dev;
+	bool use_order;
+	bool all = false;
+	int ret;
+	int i;
+
+	if (argc > 1 && *argv[1] == '-') {
+		all = strchr(argv[1], 'a');
+		argc--;
+		argv++;
+	}
+
+	ret = bootstd_get_priv(&std);
+	if (ret) {
+		printf("Cannot get bootstd (err=%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Order  Seq  Name                Description\n");
+	printf("-----  ---  ------------------  ------------------\n");
+
+	/*
+	 * Use the ordering if we have one, so long as we are not trying to list
+	 * all bootmethds
+	 */
+	use_order = std->bootmeth_count && !all;
+	if (use_order)
+		dev = std->bootmeth_order[0];
+	else
+		ret = uclass_find_first_device(UCLASS_BOOTMETH, &dev);
+
+	for (i = 0; dev;) {
+		struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(dev);
+		int order = i;
+
+		/*
+		 * With the -a flag we may list bootdevs that are not in the
+		 * ordering. Find their place in the order
+		 */
+		if (all && std->bootmeth_count) {
+			int j;
+
+			/* Find the position of this bootmeth in the order */
+			order = -1;
+			for (j = 0; j < std->bootmeth_count; j++) {
+				if (std->bootmeth_order[j] == dev)
+					order = j;
+			}
+		}
+
+		if (order == -1)
+			printf("%5s", "-");
+		else
+			printf("%5x", order);
+		printf("  %3x  %-19.19s %s\n", dev_seq(dev), dev->name,
+		       ucp->desc);
+		i++;
+		if (use_order)
+			dev = std->bootmeth_order[i];
+		else
+			uclass_find_next_device(&dev);
+	}
+	printf("-----  ---  ------------------  ------------------\n");
+	printf("(%d bootmeth%s)\n", i, i != 1 ? "s" : "");
+
+	return 0;
+}
+
+static int bootmeth_order(int argc, char *const argv[])
+{
+	struct bootstd_priv *std;
+	struct udevice **order;
+	int count, ret, i;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	if (!argc) {
+		free(std->bootmeth_order);
+		std->bootmeth_order = NULL;
+		std->bootmeth_count = 0;
+		return 0;
+	}
+
+	/* Create an array large enough */
+	count = uclass_id_count(UCLASS_BOOTMETH);
+	if (!count)
+		return log_msg_ret("count", -ENOENT);
+
+	order = calloc(max(argc, count) + 1, sizeof(struct udevice *));
+	if (!order)
+		return log_msg_ret("order", -ENOMEM);
+
+	for (i = 0; i < argc; i++) {
+		struct udevice *dev;
+
+		ret = uclass_find_device_by_name(UCLASS_BOOTMETH, argv[i],
+						 &dev);
+		if (ret) {
+			printf("Unknown bootmeth '%s'\n", argv[i]);
+			free(order);
+			return ret;
+		}
+		order[i] = dev;
+	}
+	order[i] = NULL;
+	free(std->bootmeth_order);
+	std->bootmeth_order = order;
+	std->bootmeth_count = i;
+
+	return 0;
+}
+
+static int do_bootmeth_order(struct cmd_tbl *cmdtp, int flag, int argc,
+			     char *const argv[])
+{
+	int ret;
+
+	ret = bootmeth_order(argc - 1, argv + 1);
+	if (ret) {
+		printf("Failed (err=%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootmeth_help_text[] =
+	"list [-a]     - list available bootmeths (-a all)\n"
+	"bootmeth order [<bd> ...]  - select bootmeth order / subset to use";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(bootmeth, "Boot methods", bootmeth_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmeth_list),
+	U_BOOT_SUBCMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_bootmeth_order));
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 27/41] bootstd: Add an implementation of distro boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (25 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 26/41] bootstd: Add a bootmeth command Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 28/41] bootstd: mmc: Add a bootdev driver Simon Glass
                     ` (30 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootmeth driver which handles distro boot from a disk, so we can
boot a bootflow using this commonly used mechanism.

In effect, this provides the same functionality as the 'sysboot' command
and shares the same code. But the interface into it is via a bootmeth.

For now this requires the 'pxe' command be enabled. Future work may tidy
this up so that it can be used without CONFIG_CMDLINE being enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS            |   3 +-
 boot/Kconfig           |  15 +++
 boot/Makefile          |   2 +
 boot/bootmeth_distro.c | 217 +++++++++++++++++++++++++++++++++++++++++
 include/distro.h       |  24 +++++
 5 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 boot/bootmeth_distro.c
 create mode 100644 include/distro.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a95329286da..fc05570f11d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -641,7 +641,8 @@ F:	boot/bootflow.c
 F:	boot/bootmeth*.c
 F:	boot/bootstd.c
 F:	cmd/bootdev.c
-F:	include/bootdev*.h
+F:	cmd/bootflow.c
+F:	include/bootdev.h
 F:	include/bootflow.h
 F:	include/bootmeth.h
 F:	include/bootstd.h
diff --git a/boot/Kconfig b/boot/Kconfig
index 58c495bb347..c5c8be70da9 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -295,6 +295,21 @@ config BOOTSTD
 	        U-Boot)
 	    - bootflow - a description of how to boot (owned by the distro)
 
+if BOOTSTD
+
+config BOOTMETH_DISTRO
+	bool "Bootdev support for distro boot"
+	depends on CMD_PXE
+	default y
+	help
+	  Enables support for distro boot using bootdevs. This makes the
+	  bootdevs look for a 'extlinux/extlinux.conf' on each filesystem
+	  they scan.
+
+	  This provides a way to try out standard boot on an existing boot flow.
+
+endif
+
 config LEGACY_IMAGE_FORMAT
 	bool "Enable support for the legacy image format"
 	default y if !FIT_SIGNATURE
diff --git a/boot/Makefile b/boot/Makefile
index f58c192ae07..d8f5c340b85 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
+
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
diff --git a/boot/bootmeth_distro.c b/boot/bootmeth_distro.c
new file mode 100644
index 00000000000..551159abff3
--- /dev/null
+++ b/boot/bootmeth_distro.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for distro boot (syslinux boot from a block device)
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <bootstd.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <pxe_utils.h>
+
+static int disto_getfile(struct pxe_context *ctx, const char *file_path,
+			 char *file_addr, ulong *sizep)
+{
+	struct distro_info *info = ctx->userdata;
+	ulong addr;
+	int ret;
+
+	addr = simple_strtoul(file_addr, NULL, 16);
+
+	/* Allow up to 1GB */
+	*sizep = 1 << 30;
+	ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr,
+				 sizep);
+	if (ret)
+		return log_msg_ret("read", ret);
+
+	return 0;
+}
+
+static int distro_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	int ret;
+
+	/* This only works on block devices */
+	ret = bootflow_iter_uses_blk_dev(iter);
+	if (ret)
+		return log_msg_ret("blk", ret);
+
+	return 0;
+}
+
+static int distro_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	const char *const *prefixes;
+	struct udevice *bootstd;
+	loff_t size, bytes_read;
+	char fname[200];
+	ulong addr;
+	int ret, i;
+	char *buf;
+
+	ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
+	if (ret)
+		return log_msg_ret("std", ret);
+
+	/* We require a partition table */
+	if (!bflow->part)
+		return -ENOENT;
+
+	bflow->fname = strdup(DISTRO_FNAME);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+
+	prefixes = bootstd_get_prefixes(bootstd);
+	if (prefixes) {
+		log_debug("Trying prefixes:\n");
+		for (i = 0; prefixes[i]; i++) {
+			snprintf(fname, sizeof(fname), "%s%s", prefixes[i],
+				 DISTRO_FNAME);
+			ret = fs_size(fname, &size);
+			log_debug("   %s - err=%d\n", fname, ret);
+			if (!ret)
+				break;
+
+			/*
+			 * Sadly FS closes the file after fs_size() so we must
+			 * redo this
+			 */
+			ret = fs_set_blk_dev_with_part(desc, bflow->part);
+			if (ret)
+				return log_msg_ret("set", ret);
+		}
+		log_debug("   done\n");
+	} else {
+		strcpy(fname, DISTRO_FNAME);
+		ret = fs_size(bflow->fname, &size);
+		log_debug("No prefixes: %s - err=%d", fname, ret);
+	}
+	if (ret)
+		return log_msg_ret("size", ret);
+
+	bflow->fname = strdup(fname);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+
+	bflow->state = BOOTFLOWST_FILE;
+	bflow->size = size;
+	log_debug("   - distro file size %x\n", (uint)size);
+	if (size > 0x10000)
+		return log_msg_ret("chk", -E2BIG);
+
+	/* Sadly FS closes the file after fs_size() so we must redo this */
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return log_msg_ret("set", ret);
+
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	addr = map_to_sysmem(buf);
+
+	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
+	if (ret) {
+		free(buf);
+		return log_msg_ret("read", ret);
+	}
+	if (size != bytes_read)
+		return log_msg_ret("bread", -EINVAL);
+	buf[size] = '\0';
+	bflow->state = BOOTFLOWST_READY;
+	bflow->buf = buf;
+
+	return 0;
+}
+
+static int distro_read_file(struct udevice *dev, struct bootflow *bflow,
+			    const char *file_path, ulong addr, ulong *sizep)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	loff_t len_read;
+	loff_t size;
+	int ret;
+
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return log_msg_ret("set1", ret);
+	ret = fs_size(file_path, &size);
+	if (ret)
+		return log_msg_ret("size", ret);
+	if (size > *sizep)
+		return log_msg_ret("spc", -ENOSPC);
+
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return log_msg_ret("set2", ret);
+	ret = fs_read(file_path, addr, 0, 0, &len_read);
+	if (ret)
+		return ret;
+	*sizep = len_read;
+
+	return 0;
+}
+
+static int distro_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	struct cmd_tbl cmdtp = {};	/* dummy */
+	struct pxe_context ctx;
+	struct distro_info info;
+	ulong addr;
+	int ret;
+
+	addr = map_to_sysmem(bflow->buf);
+	info.dev = dev;
+	info.bflow = bflow;
+	ret = pxe_setup_ctx(&ctx, &cmdtp, disto_getfile, &info, true,
+			    bflow->subdir);
+	if (ret)
+		return log_msg_ret("ctx", -EINVAL);
+
+	ret = pxe_process(&ctx, addr, false);
+	if (ret)
+		return log_msg_ret("bread", -EINVAL);
+
+	return 0;
+}
+
+static int distro_bootmeth_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "Syslinux boot from a block device";
+
+	return 0;
+}
+
+static struct bootmeth_ops distro_bootmeth_ops = {
+	.check		= distro_check,
+	.read_bootflow	= distro_read_bootflow,
+	.read_file	= distro_read_file,
+	.boot		= distro_boot,
+};
+
+static const struct udevice_id distro_bootmeth_ids[] = {
+	{ .compatible = "u-boot,distro-syslinux" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_distro) = {
+	.name		= "bootmeth_distro",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= distro_bootmeth_ids,
+	.ops		= &distro_bootmeth_ops,
+	.bind		= distro_bootmeth_bind,
+};
diff --git a/include/distro.h b/include/distro.h
new file mode 100644
index 00000000000..2ee145871b2
--- /dev/null
+++ b/include/distro.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __distro_h
+#define __distro_h
+
+#define DISTRO_FNAME	"extlinux/extlinux.conf"
+
+/**
+ * struct distro_info - useful information for distro_getfile()
+ *
+ * @dev: bootmethod device being used to boot
+ * @bflow: bootflow being booted
+ */
+struct distro_info {
+	struct udevice *dev;
+	struct bootflow *bflow;
+	struct cmd_tbl *cmdtp;
+};
+
+#endif
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 28/41] bootstd: mmc: Add a bootdev driver
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (26 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 27/41] bootstd: Add an implementation of distro boot Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 29/41] bootstd: ethernet: " Simon Glass
                     ` (29 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Jaehoon Chung, Peng Fan

Add a bootdev driver for MMC. It mostly just calls the bootdev helper
function.

Add a function to obtain the block device for an MMC controller.

Fix up the comment for mmc_get_blk_desc() while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS               |  1 +
 drivers/mmc/Makefile      |  5 ++++
 drivers/mmc/mmc-uclass.c  | 23 +++++++++++++++
 drivers/mmc/mmc_bootdev.c | 62 +++++++++++++++++++++++++++++++++++++++
 include/mmc.h             | 12 +++++++-
 5 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/mmc_bootdev.c

diff --git a/MAINTAINERS b/MAINTAINERS
index fc05570f11d..8a19d08623f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -642,6 +642,7 @@ F:	boot/bootmeth*.c
 F:	boot/bootstd.c
 F:	cmd/bootdev.c
 F:	cmd/bootflow.c
+F:	drivers/mmc/mmc_bootdev.c
 F:	include/bootdev.h
 F:	include/bootflow.h
 F:	include/bootmeth.h
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 7e819d2b3a2..06d67718ddb 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -5,6 +5,11 @@
 
 obj-y += mmc.o
 obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o
+
+ifdef CONFIG_$(SPL_TPL_)DM_MMC
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += mmc_bootdev.o
+endif
+
 obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
 obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o
 obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index b80e838066c..35b8cdbe35f 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY UCLASS_MMC
 
 #include <common.h>
+#include <bootdev.h>
 #include <log.h>
 #include <mmc.h>
 #include <dm.h>
@@ -315,6 +316,20 @@ int mmc_get_next_devnum(void)
 	return blk_find_max_devnum(IF_TYPE_MMC);
 }
 
+int mmc_get_blk(struct udevice *dev, struct udevice **blkp)
+{
+	struct udevice *blk;
+	int ret;
+
+	device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk);
+	ret = device_probe(blk);
+	if (ret)
+		return ret;
+	*blkp = blk;
+
+	return 0;
+}
+
 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
 {
 	struct blk_desc *desc;
@@ -406,6 +421,10 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
 	mmc->cfg = cfg;
 	mmc->priv = dev;
 
+	ret = bootdev_setup_for_dev(dev, "mmc_bootdev");
+	if (ret)
+		return log_msg_ret("bootdev", ret);
+
 	/* the following chunk was from mmc_register() */
 
 	/* Setup dsr related values */
@@ -424,12 +443,16 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
 int mmc_unbind(struct udevice *dev)
 {
 	struct udevice *bdev;
+	int ret;
 
 	device_find_first_child_by_uclass(dev, UCLASS_BLK, &bdev);
 	if (bdev) {
 		device_remove(bdev, DM_REMOVE_NORMAL);
 		device_unbind(bdev);
 	}
+	ret = bootdev_unbind_dev(dev);
+	if (ret)
+		return log_msg_ret("bootdev", ret);
 
 	return 0;
 }
diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c
new file mode 100644
index 00000000000..b4f41fb3a67
--- /dev/null
+++ b/drivers/mmc/mmc_bootdev.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for MMC
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <mmc.h>
+
+static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			    struct bootflow *bflow)
+{
+	struct udevice *mmc_dev = dev_get_parent(dev);
+	struct udevice *blk;
+	int ret;
+
+	ret = mmc_get_blk(mmc_dev, &blk);
+	/*
+	 * If there is no media, indicate that no more partitions should be
+	 * checked
+	 */
+	if (ret == -EOPNOTSUPP)
+		ret = -ESHUTDOWN;
+	if (ret)
+		return log_msg_ret("blk", ret);
+	assert(blk);
+	ret = bootdev_find_in_blk(dev, blk, iter, bflow);
+	if (ret)
+		return log_msg_ret("find", ret);
+
+	return 0;
+}
+
+static int mmc_bootdev_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
+
+	return 0;
+}
+
+struct bootdev_ops mmc_bootdev_ops = {
+	.get_bootflow	= mmc_get_bootflow,
+};
+
+static const struct udevice_id mmc_bootdev_ids[] = {
+	{ .compatible = "u-boot,bootdev-mmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(mmc_bootdev) = {
+	.name		= "mmc_bootdev",
+	.id		= UCLASS_BOOTDEV,
+	.ops		= &mmc_bootdev_ops,
+	.bind		= mmc_bootdev_bind,
+	.of_match	= mmc_bootdev_ids,
+};
diff --git a/include/mmc.h b/include/mmc.h
index b92e2553402..668a8634a04 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -961,10 +961,20 @@ int mmc_get_env_dev(void);
  * mmc_get_blk_desc() - Get the block descriptor for an MMC device
  *
  * @mmc:	MMC device
- * @return block device if found, else NULL
+ * @return block descriptor if found, else NULL
  */
 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc);
 
+/**
+ * mmc_get_blk() - Get the block device for an MMC device
+ *
+ * @dev:	MMC device
+ * @blkp:	Returns pointer to probed block device on sucesss
+ *
+ * @return 0 on success, -ve on error
+ */
+int mmc_get_blk(struct udevice *dev, struct udevice **blkp);
+
 /**
  * mmc_send_ext_csd() - read the extended CSD register
  *
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 29/41] bootstd: ethernet: Add a bootdev driver
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (27 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 28/41] bootstd: mmc: Add a bootdev driver Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 30/41] bootstd: Add an implementation of distro PXE boot Simon Glass
                     ` (28 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootdev driver for Ethernet. It can use the PXE boot mechanism to
locate a file, added later.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS       |   1 +
 net/Kconfig       |   9 +++++
 net/Makefile      |   1 +
 net/eth-uclass.c  |   8 ++++
 net/eth_bootdev.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 120 insertions(+)
 create mode 100644 net/eth_bootdev.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8a19d08623f..ae0b1613fe2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -647,6 +647,7 @@ F:	include/bootdev.h
 F:	include/bootflow.h
 F:	include/bootmeth.h
 F:	include/bootstd.h
+F:	net/eth_bootdevice.c
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/net/Kconfig b/net/Kconfig
index 7a2d1450188..e110930553a 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -14,6 +14,15 @@ config PROT_UDP
 	  Enable a generic udp framework that allows defining a custom
 	  handler for udp protocol.
 
+config BOOTDEV_ETH
+	bool "Enable bootdev for ethernet"
+	depends on BOOTSTD
+	default y
+	help
+	  Provide a bootdev for ethernet so that is it possible to boot
+	  an operationg system over the network, using the PXE (Preboot
+	  Execution Environment) protocol.
+
 config BOOTP_SEND_HOSTNAME
 	bool "Send hostname to DNS server"
 	help
diff --git a/net/Makefile b/net/Makefile
index fb3eba840ff..6c812502d3e 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_CMD_DNS)  += dns.o
 obj-$(CONFIG_DM_DSA)   += dsa-uclass.o
 ifdef CONFIG_DM_ETH
 obj-$(CONFIG_NET)      += eth-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += eth_bootdev.o
 else
 obj-$(CONFIG_NET)      += eth_legacy.o
 endif
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 0da0e85be03..cccbc87ab29 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY UCLASS_ETH
 
 #include <common.h>
+#include <bootdev.h>
 #include <bootstage.h>
 #include <dm.h>
 #include <env.h>
@@ -473,6 +474,8 @@ int eth_initialize(void)
 
 static int eth_post_bind(struct udevice *dev)
 {
+	int ret;
+
 	if (strchr(dev->name, ' ')) {
 		printf("\nError: eth device name \"%s\" has a space!\n",
 		       dev->name);
@@ -482,6 +485,11 @@ static int eth_post_bind(struct udevice *dev)
 #ifdef CONFIG_DM_ETH_PHY
 	eth_phy_binds_nodes(dev);
 #endif
+	if (CONFIG_IS_ENABLED(BOOTDEV_ETH)) {
+		ret = bootdev_setup_for_dev(dev, "eth_bootdev");
+		if (ret)
+			return log_msg_ret("bootdev", ret);
+	}
 
 	return 0;
 }
diff --git a/net/eth_bootdev.c b/net/eth_bootdev.c
new file mode 100644
index 00000000000..b735966d2bc
--- /dev/null
+++ b/net/eth_bootdev.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for ethernet (uses PXE)
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <command.h>
+#include <bootmeth.h>
+#include <distro.h>
+#include <dm.h>
+#include <log.h>
+#include <net.h>
+
+static int eth_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			    struct bootflow *bflow)
+{
+	char name[60];
+	int ret;
+
+	/* Must be an Ethernet device */
+	ret = bootflow_iter_uses_network(iter);
+	if (ret)
+		return log_msg_ret("net", ret);
+
+	ret = bootmeth_check(bflow->method, iter);
+	if (ret)
+		return log_msg_ret("check", ret);
+
+	/*
+	 * Like distro boot, this assumes there is only one Ethernet device.
+	 * In this case, that means that @eth is ignored
+	 */
+
+	snprintf(name, sizeof(name), "%s.%d", dev->name, iter->part);
+	bflow->name = strdup(name);
+	if (!bflow->name)
+		return log_msg_ret("name", -ENOMEM);
+
+	/*
+	 * There is not a direct interface to the network stack so run
+	 * everything through the command-line interpreter for now.
+	 *
+	 * Don't bother checking the result of dhcp. It can fail with:
+	 *
+	 * DHCP client bound to address 192.168.4.50 (4 ms)
+	 * *** Warning: no boot file name; using 'C0A80432.img'
+	 * Using smsc95xx_eth device
+	 * TFTP from server 192.168.4.1; our IP address is 192.168.4.50
+	 * Filename 'C0A80432.img'.
+	 * Load address: 0x200000
+	 * Loading: *
+	 * TFTP error: 'File not found' (1)
+	 *
+	 * This is not a real failure, since we don't actually care if the
+	 * boot file exists.
+	 */
+	log_debug("running dhcp\n");
+	run_command("dhcp", 0);
+	bflow->state = BOOTFLOWST_MEDIA;
+
+	/* See distro_pxe_read_bootflow() for the standard impl of this */
+	log_debug("dhcp complete - reading bootflow with method %s\n",
+		  bflow->method->name);
+	ret = bootmeth_read_bootflow(bflow->method, bflow);
+	log_debug("reading bootflow returned %d\n", ret);
+	if (ret)
+		return log_msg_ret("method", ret);
+
+	return 0;
+}
+
+static int eth_bootdev_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	ucp->prio = BOOTDEVP_4_NET_BASE;
+
+	return 0;
+}
+
+struct bootdev_ops eth_bootdev_ops = {
+	.get_bootflow	= eth_get_bootflow,
+};
+
+static const struct udevice_id eth_bootdev_ids[] = {
+	{ .compatible = "u-boot,bootdev-eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_bootdev) = {
+	.name		= "eth_bootdev",
+	.id		= UCLASS_BOOTDEV,
+	.ops		= &eth_bootdev_ops,
+	.bind		= eth_bootdev_bind,
+	.of_match	= eth_bootdev_ids,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 30/41] bootstd: Add an implementation of distro PXE boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (28 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 29/41] bootstd: ethernet: " Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 31/41] bootstd: Add an implementation of EFI boot Simon Glass
                     ` (27 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootmeth driver which handles distro boot from a network device, so
we can boot a bootflow using this commonly used mechanism.

In effect, this provides the same functionality as the 'pxe' command
and shares the same code. But the interface into it is via a bootmeth.

For now this requires the 'pxe' command be enabled. Future work may tidy
this up so that it can be used without CONFIG_CMDLINE being enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Kconfig        |  10 +++
 boot/Makefile       |   1 +
 boot/bootmeth_pxe.c | 183 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 194 insertions(+)
 create mode 100644 boot/bootmeth_pxe.c

diff --git a/boot/Kconfig b/boot/Kconfig
index c5c8be70da9..7e948f95e92 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -308,6 +308,16 @@ config BOOTMETH_DISTRO
 
 	  This provides a way to try out standard boot on an existing boot flow.
 
+config BOOTMETH_DISTRO_PXE
+	bool "Bootdev support for distro boot over network"
+	depends on CMD_PXE && CMD_NET && DM_ETH
+	default y
+	help
+	  Enables support for distro boot using bootdevs. This makes the
+	  bootdevs look for a 'extlinux/extlinux.conf' on the tftp server.
+
+	  This provides a way to try out standard boot on an existing boot flow.
+
 endif
 
 config LEGACY_IMAGE_FORMAT
diff --git a/boot/Makefile b/boot/Makefile
index d8f5c340b85..170fcac8ec4 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
 
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
new file mode 100644
index 00000000000..6c92ce39265
--- /dev/null
+++ b/boot/bootmeth_pxe.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for distro boot using PXE (network boot)
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <fs.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <net.h>
+#include <pxe_utils.h>
+
+static int disto_pxe_getfile(struct pxe_context *ctx, const char *file_path,
+			     char *file_addr, ulong *sizep)
+{
+	struct distro_info *info = ctx->userdata;
+	ulong addr;
+	int ret;
+
+	addr = simple_strtoul(file_addr, NULL, 16);
+	ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr,
+				 sizep);
+	if (ret)
+		return log_msg_ret("read", ret);
+
+	return 0;
+}
+
+static int distro_pxe_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	int ret;
+
+	/* This only works on network devices */
+	ret = bootflow_iter_uses_network(iter);
+	if (ret)
+		return log_msg_ret("net", ret);
+
+	return 0;
+}
+
+static int distro_pxe_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	const char *addr_str;
+	char fname[200];
+	char *bootdir;
+	ulong addr;
+	ulong size;
+	char *buf;
+	int ret;
+
+	addr_str = env_get("pxefile_addr_r");
+	if (!addr_str)
+		return log_msg_ret("pxeb", -EPERM);
+	addr = simple_strtoul(addr_str, NULL, 16);
+
+	log_debug("calling pxe_get()\n");
+	ret = pxe_get(addr, &bootdir, &size);
+	log_debug("pxe_get() returned %d\n", ret);
+	if (ret)
+		return log_msg_ret("pxeb", ret);
+	bflow->size = size;
+
+	/* Use the directory of the dhcp bootdir as our subdir, if provided */
+	if (bootdir) {
+		const char *last_slash;
+		int path_len;
+
+		last_slash = strrchr(bootdir, '/');
+		if (last_slash) {
+			path_len = (last_slash - bootdir) + 1;
+			bflow->subdir = malloc(path_len + 1);
+			memcpy(bflow->subdir, bootdir, path_len);
+			bflow->subdir[path_len] = '\0';
+		}
+	}
+	snprintf(fname, sizeof(fname), "%s%s",
+		 bflow->subdir ? bflow->subdir : "", DISTRO_FNAME);
+
+	bflow->fname = strdup(fname);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+
+	bflow->state = BOOTFLOWST_READY;
+
+	/* Allocate the buffer, including the \0 byte added by get_pxe_file() */
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	memcpy(buf, map_sysmem(addr, 0), size + 1);
+	bflow->buf = buf;
+
+	return 0;
+}
+
+static int distro_pxe_read_file(struct udevice *dev, struct bootflow *bflow,
+				const char *file_path, ulong addr, ulong *sizep)
+{
+	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+	struct pxe_context *ctx = dev_get_priv(dev);
+	char file_addr[17];
+	ulong size;
+	int ret;
+
+	sprintf(file_addr, "%lx", addr);
+	tftp_argv[1] = file_addr;
+	tftp_argv[2] = (void *)file_path;
+
+	if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
+		return -ENOENT;
+	ret = pxe_get_file_size(&size);
+	if (ret)
+		return log_msg_ret("tftp", ret);
+	if (size > *sizep)
+		return log_msg_ret("spc", -ENOSPC);
+	*sizep = size;
+
+	return 0;
+}
+
+static int distro_pxe_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	struct pxe_context *ctx = dev_get_priv(dev);
+	struct cmd_tbl cmdtp = {};	/* dummy */
+	struct distro_info info;
+	ulong addr;
+	int ret;
+
+	addr = map_to_sysmem(bflow->buf);
+	info.dev = dev;
+	info.bflow = bflow;
+	info.cmdtp = &cmdtp;
+	ret = pxe_setup_ctx(ctx, &cmdtp, disto_pxe_getfile, &info, false,
+			    bflow->subdir);
+	if (ret)
+		return log_msg_ret("ctx", -EINVAL);
+
+	ret = pxe_process(ctx, addr, false);
+	if (ret)
+		return log_msg_ret("bread", -EINVAL);
+
+	return 0;
+}
+
+static int distro_bootmeth_pxe_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "PXE boot from a network device";
+
+	return 0;
+}
+
+static struct bootmeth_ops distro_bootmeth_pxe_ops = {
+	.check		= distro_pxe_check,
+	.read_bootflow	= distro_pxe_read_bootflow,
+	.read_file	= distro_pxe_read_file,
+	.boot		= distro_pxe_boot,
+};
+
+static const struct udevice_id distro_bootmeth_pxe_ids[] = {
+	{ .compatible = "u-boot,distro-pxe" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_pxe) = {
+	.name		= "bootmeth_pxe",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= distro_bootmeth_pxe_ids,
+	.ops		= &distro_bootmeth_pxe_ops,
+	.bind		= distro_bootmeth_pxe_bind,
+	.priv_auto	= sizeof(struct pxe_context),
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (29 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 30/41] bootstd: Add an implementation of distro PXE boot Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-27  8:35     ` Ilias Apalodimas
  2021-10-27 11:57     ` Heinrich Schuchardt
  2021-10-23 23:26   ` [PATCH v2 32/41] bootstd: Add a system bootdev for strange boot methods Simon Glass
                     ` (26 subsequent siblings)
  57 siblings, 2 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootmeth driver which handles EFI boot, using EFI_LOADER.

In effect, this provides the same functionality as the 'bootefi' command
and shares the same code. But the interface into it is via a bootmeth,
so it does not require any special scripts, etc.

For now this requires the 'bootefi' command be enabled. Future work may
tidy this up so that it can be used without CONFIG_CMDLINE being enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Kconfig        |  21 ++++
 boot/Makefile       |   1 +
 boot/bootmeth_efi.c | 263 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 285 insertions(+)
 create mode 100644 boot/bootmeth_efi.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 7e948f95e92..ebbd7427d7f 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -318,6 +318,27 @@ config BOOTMETH_DISTRO_PXE
 
 	  This provides a way to try out standard boot on an existing boot flow.
 
+config BOOTMETH_EFILOADER
+	bool "Bootdev support for EFI boot"
+	depends on CMD_BOOTEFI
+	default y
+	help
+	  Enables support for EFI boot using bootdevs. This makes the
+	  bootdevs look for a 'boot<arch>.efi' on each filesystem
+	  they scan. The resulting file is booted after enabling U-Boot's
+	  EFI loader support.
+
+	  The <arch> depends on the architecture of the board:
+
+	     aa64      - aarch64 (ARM 64-bit)
+	     arm       - ARM 32-bit
+	     ia32      - x86 32-bit
+	     x64       - x86 64-bit
+	     riscv32   - RISC-V 32-bit
+	     riscv64   - RISC-V 64-bit
+
+	  This provides a way to try out standard boot on an existing boot flow.
+
 endif
 
 config LEGACY_IMAGE_FORMAT
diff --git a/boot/Makefile b/boot/Makefile
index 170fcac8ec4..c2345435201 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
 
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
new file mode 100644
index 00000000000..eeb8f377c50
--- /dev/null
+++ b/boot/bootmeth_efi.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for distro boot via EFI
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <command.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <pxe_utils.h>
+
+#define EFI_DIRNAME	"efi/boot/"
+
+/**
+ * get_efi_leafname() - Get the leaf name for the EFI file we expect
+ *
+ * @str: Place to put leaf name for this architecture, e.g. "bootaa64.efi".
+ *	Must have at least 16 bytes of space
+ * @max_len: Length of @str, must be >=16
+ */
+static int get_efi_leafname(char *str, int max_len)
+{
+	const char *base;
+
+	if (max_len < 16)
+		return log_msg_ret("spc", -ENOSPC);
+	if (IS_ENABLED(CONFIG_ARM64))
+		base = "bootaa64";
+	else if (IS_ENABLED(CONFIG_ARM))
+		base = "bootarm";
+	else if (IS_ENABLED(CONFIG_X86_RUN_32BIT))
+		base = "bootia32";
+	else if (IS_ENABLED(CONFIG_X86_RUN_64BIT))
+		base = "bootx64";
+	else if (IS_ENABLED(CONFIG_ARCH_RV32I))
+		base = "bootriscv32";
+	else if (IS_ENABLED(CONFIG_ARCH_RV64I))
+		base = "bootriscv64";
+	else if (IS_ENABLED(CONFIG_SANDBOX))
+		base = "bootsbox";
+	else
+		return -EINVAL;
+
+	strcpy(str, base);
+	strcat(str, ".efi");
+
+	return 0;
+}
+
+static int efiload_read_file(struct blk_desc *desc, struct bootflow *bflow)
+{
+	const struct udevice *media_dev;
+	int size = bflow->size;
+	char devnum_str[9];
+	char dirname[200];
+	loff_t bytes_read;
+	char *last_slash;
+	ulong addr;
+	char *buf;
+	int ret;
+
+	/* Sadly FS closes the file after fs_size() so we must redo this */
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return log_msg_ret("set", ret);
+
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	addr = map_to_sysmem(buf);
+
+	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
+	if (ret) {
+		free(buf);
+		return log_msg_ret("read", ret);
+	}
+	if (size != bytes_read)
+		return log_msg_ret("bread", -EINVAL);
+	buf[size] = '\0';
+	bflow->state = BOOTFLOWST_READY;
+	bflow->buf = buf;
+
+	/*
+	 * This is a horrible hack to tell EFI about this boot device. Once we
+	 * unify EFI with the rest of U-Boot we can clean this up. The same hack
+	 * exists in multiple places, e.g. in the fs, tftp and load commands.
+	 *
+	 * Once we can clean up the EFI code to make proper use of driver model,
+	 * this can go away.
+	 */
+	media_dev = dev_get_parent(bflow->dev);
+	snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
+
+	strlcpy(dirname, bflow->fname, sizeof(dirname));
+	last_slash = strrchr(dirname, '/');
+	if (last_slash)
+		*last_slash = '\0';
+
+	efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
+			bflow->buf, size);
+
+	return 0;
+}
+
+static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	int ret;
+
+	/* This only works on block devices */
+	ret = bootflow_iter_uses_blk_dev(iter);
+	if (ret)
+		return log_msg_ret("blk", ret);
+
+	return 0;
+}
+
+static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	char fname[sizeof(EFI_DIRNAME) + 16];
+	loff_t size;
+	int ret;
+
+	/* We require a partition table */
+	if (!bflow->part)
+		return -ENOENT;
+
+	strcpy(fname, EFI_DIRNAME);
+	ret = get_efi_leafname(fname + strlen(fname),
+			       sizeof(fname) - strlen(fname));
+	if (ret)
+		return log_msg_ret("leaf", ret);
+
+	bflow->fname = strdup(fname);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+	ret = fs_size(bflow->fname, &size);
+	bflow->size = size;
+	if (ret)
+		return log_msg_ret("size", ret);
+	bflow->state = BOOTFLOWST_FILE;
+	log_debug("   - distro file size %x\n", (uint)size);
+	if (size > 0x2000000)
+		return log_msg_ret("chk", -E2BIG);
+
+	ret = efiload_read_file(desc, bflow);
+	if (ret)
+		return log_msg_ret("read", -EINVAL);
+
+	return 0;
+}
+
+static int distro_efi_read_file(struct udevice *dev, struct bootflow *bflow,
+				const char *file_path, ulong addr, ulong *sizep)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	const struct udevice *media_dev;
+	int size = bflow->size;
+	char devnum_str[9];
+	char dirname[200];
+	loff_t bytes_read;
+	char *last_slash;
+	char *buf;
+	int ret;
+
+	/* Sadly FS closes the file after fs_size() so we must redo this */
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return log_msg_ret("set", ret);
+
+	buf = malloc(size + 1);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+	addr = map_to_sysmem(buf);
+
+	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
+	if (ret) {
+		free(buf);
+		return log_msg_ret("read", ret);
+	}
+	if (size != bytes_read)
+		return log_msg_ret("bread", -EINVAL);
+	buf[size] = '\0';
+	bflow->state = BOOTFLOWST_READY;
+	bflow->buf = buf;
+
+	/*
+	 * This is a horrible hack to tell EFI about this boot device. Once we
+	 * unify EFI with the rest of U-Boot we can clean this up. The same hack
+	 * exists in multiple places, e.g. in the fs, tftp and load commands.
+	 *
+	 * Once we can clean up the EFI code to make proper use of driver model,
+	 * this can go away.
+	 */
+	media_dev = dev_get_parent(bflow->dev);
+	snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
+
+	strlcpy(dirname, bflow->fname, sizeof(dirname));
+	last_slash = strrchr(dirname, '/');
+	if (last_slash)
+		*last_slash = '\0';
+
+	efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
+			bflow->buf, size);
+
+	return 0;
+}
+
+int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	char cmd[50];
+
+	/*
+	 * At some point we can add a real interface to bootefi so we can call
+	 * this directly. For now, go through the CLI like distro boot.
+	 */
+	snprintf(cmd, sizeof(cmd), "bootefi %lx %lx",
+		 (ulong)map_to_sysmem(bflow->buf),
+		 (ulong)map_to_sysmem(gd->fdt_blob));
+	if (run_command(cmd, 0))
+		return log_msg_ret("run", -EINVAL);
+
+	return 0;
+}
+
+static int distro_bootmeth_efi_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "EFI boot from a .efi file";
+
+	return 0;
+}
+
+static struct bootmeth_ops distro_efi_bootmeth_ops = {
+	.check		= distro_efi_check,
+	.read_bootflow	= distro_efi_read_bootflow,
+	.read_file	= distro_efi_read_file,
+	.boot		= distro_efi_boot,
+};
+
+static const struct udevice_id distro_efi_bootmeth_ids[] = {
+	{ .compatible = "u-boot,distro-efi" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_efi) = {
+	.name		= "bootmeth_efi",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= distro_efi_bootmeth_ids,
+	.ops		= &distro_efi_bootmeth_ops,
+	.bind		= distro_bootmeth_efi_bind,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 32/41] bootstd: Add a system bootdev for strange boot methods
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (30 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 31/41] bootstd: Add an implementation of EFI boot Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 33/41] bootstd: Add an implementation of EFI bootmgr Simon Glass
                     ` (25 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Some boot methods don't act on a single bootdev but instead do their own
thing. An example is EFI bootmgr which scan various devices using its own
logic. Add a bootdev to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Makefile         |  2 +-
 boot/bootstd-uclass.c |  6 ++++
 boot/system_bootdev.c | 64 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 boot/system_bootdev.c

diff --git a/boot/Makefile b/boot/Makefile
index c2345435201..795665f7ce5 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -23,7 +23,7 @@ obj-y += image.o image-board.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 
-obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o system_bootdev.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index 7dddd72bc4a..3952560eee5 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -143,6 +143,12 @@ int dm_scan_other(bool pre_reloc_only)
 		}
 	}
 
+	/* Create the system bootdev too */
+	ret = device_bind_driver(bootstd, "system_bootdev", "system-bootdev",
+				 &dev);
+	if (ret)
+		return log_msg_ret("sys", ret);
+
 	return 0;
 }
 
diff --git a/boot/system_bootdev.c b/boot/system_bootdev.c
new file mode 100644
index 00000000000..2cf7cd4dc11
--- /dev/null
+++ b/boot/system_bootdev.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for system, used for bootmeths not tied to any partition device
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <log.h>
+#include <net.h>
+
+static int system_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			       struct bootflow *bflow)
+{
+	int ret;
+
+	/* Must be an bootstd device */
+	ret = bootflow_iter_uses_system(iter);
+	if (ret)
+		return log_msg_ret("net", ret);
+
+	ret = bootmeth_check(bflow->method, iter);
+	if (ret)
+		return log_msg_ret("check", ret);
+
+	ret = bootmeth_read_bootflow(bflow->method, bflow);
+	if (ret)
+		return log_msg_ret("method", ret);
+
+	return 0;
+}
+
+static int system_bootdev_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	ucp->prio = BOOTDEVP_6_SYSTEM;
+
+	return 0;
+}
+
+struct bootdev_ops system_bootdev_ops = {
+	.get_bootflow	= system_get_bootflow,
+};
+
+static const struct udevice_id system_bootdev_ids[] = {
+	{ .compatible = "u-boot,bootdev-system" },
+	{ }
+};
+
+U_BOOT_DRIVER(system_bootdev) = {
+	.name		= "system_bootdev",
+	.id		= UCLASS_BOOTDEV,
+	.ops		= &system_bootdev_ops,
+	.bind		= system_bootdev_bind,
+	.of_match	= system_bootdev_ids,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 33/41] bootstd: Add an implementation of EFI bootmgr
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (31 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 32/41] bootstd: Add a system bootdev for strange boot methods Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 34/41] bootstd: Add a sandbox bootmeth driver Simon Glass
                     ` (24 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootmeth driver which handles EFI boot manager, using EFI_LOADER.

In effect, this provides the same functionality as the 'bootefi bootmgr'
command and shares the same code. But the interface into it is via a
bootmeth, so it does not require any special scripts, etc.

For now this requires the 'bootefi' command be enabled. Future work may
tidy this up so that it can be used without CONFIG_CMDLINE being enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Makefile           |  3 ++
 boot/bootmeth_efi_mgr.c | 84 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 boot/bootmeth_efi_mgr.c

diff --git a/boot/Makefile b/boot/Makefile
index 795665f7ce5..0bbda0e5364 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -31,6 +31,9 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
+ifdef CONFIG_$(SPL_TPL_)BOOTSTD
+obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
+endif
 
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c
new file mode 100644
index 00000000000..3b67cd24984
--- /dev/null
+++ b/boot/bootmeth_efi_mgr.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for EFI boot manager
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <command.h>
+#include <dm.h>
+
+static int efi_mgr_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	int ret;
+
+	/* Must be an bootstd device */
+	ret = bootflow_iter_uses_system(iter);
+	if (ret)
+		return log_msg_ret("net", ret);
+
+	return 0;
+}
+
+static int efi_mgr_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	/*
+	 * Just assume there is something to boot since we don't have any way
+	 * of knowing in advance
+	 */
+	bflow->state = BOOTFLOWST_READY;
+
+	return 0;
+}
+
+static int efi_mgr_read_file(struct udevice *dev, struct bootflow *bflow,
+				const char *file_path, ulong addr, ulong *sizep)
+{
+	/* Files are loaded by the 'bootefi bootmgr' command */
+
+	return -ENOSYS;
+}
+
+static int efi_mgr_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	int ret;
+
+	/* Booting is handled by the 'bootefi bootmgr' command */
+	ret = run_command("bootefi bootmgr", 0);
+
+	return 0;
+}
+
+static int bootmeth_efi_mgr_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "EFI bootmgr flow";
+
+	return 0;
+}
+
+static struct bootmeth_ops efi_mgr_bootmeth_ops = {
+	.check		= efi_mgr_check,
+	.read_bootflow	= efi_mgr_read_bootflow,
+	.read_file	= efi_mgr_read_file,
+	.boot		= efi_mgr_boot,
+};
+
+static const struct udevice_id efi_mgr_bootmeth_ids[] = {
+	{ .compatible = "u-boot,efi-bootmgr" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_zefi_mgr) = {
+	.name		= "bootmeth_efi_mgr",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= efi_mgr_bootmeth_ids,
+	.ops		= &efi_mgr_bootmeth_ops,
+	.bind		= bootmeth_efi_mgr_bind,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 34/41] bootstd: Add a sandbox bootmeth driver
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (32 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 33/41] bootstd: Add an implementation of EFI bootmgr Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 35/41] bootstd: usb: Add a bootdev driver Simon Glass
                     ` (23 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a bootmeth driver for sandbox, used for testing.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Kconfig            |  7 +++++
 boot/Makefile           |  1 +
 boot/bootmeth_sandbox.c | 67 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)
 create mode 100644 boot/bootmeth_sandbox.c

diff --git a/boot/Kconfig b/boot/Kconfig
index ebbd7427d7f..2862bd10710 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -339,6 +339,13 @@ config BOOTMETH_EFILOADER
 
 	  This provides a way to try out standard boot on an existing boot flow.
 
+config BOOTMETH_SANDBOX
+	def_bool y
+	depends on SANDBOX
+	help
+	  This is a sandbox bootmeth driver used for testing. It always returns
+	  -ENOTSUPP when attempting to boot.
+
 endif
 
 config LEGACY_IMAGE_FORMAT
diff --git a/boot/Makefile b/boot/Makefile
index 0bbda0e5364..a2722072753 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
 ifdef CONFIG_$(SPL_TPL_)BOOTSTD
 obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
 endif
diff --git a/boot/bootmeth_sandbox.c b/boot/bootmeth_sandbox.c
new file mode 100644
index 00000000000..928cd5ac6a5
--- /dev/null
+++ b/boot/bootmeth_sandbox.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for sandbox testing
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <dm.h>
+
+static int sandbox_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	return 0;
+}
+
+static int sandbox_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	/* pretend we are ready */
+	bflow->state = BOOTFLOWST_READY;
+
+	return 0;
+}
+
+static int sandbox_read_file(struct udevice *dev, struct bootflow *bflow,
+			     const char *file_path, ulong addr, ulong *sizep)
+{
+	return -ENOSYS;
+}
+
+static int sandbox_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	/* always fail: see bootflow_iter_disable() */
+	return -ENOTSUPP;
+}
+
+static int sandbox_bootmeth_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "Sandbox boot for testing";
+
+	return 0;
+}
+
+static struct bootmeth_ops sandbox_bootmeth_ops = {
+	.check		= sandbox_check,
+	.read_bootflow	= sandbox_read_bootflow,
+	.read_file	= sandbox_read_file,
+	.boot		= sandbox_boot,
+};
+
+static const struct udevice_id sandbox_bootmeth_ids[] = {
+	{ .compatible = "u-boot,sandbox-syslinux" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_sandbox) = {
+	.name		= "bootmeth_sandbox",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= sandbox_bootmeth_ids,
+	.ops		= &sandbox_bootmeth_ops,
+	.bind		= sandbox_bootmeth_bind,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 35/41] bootstd: usb: Add a bootdev driver
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (33 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 34/41] bootstd: Add a sandbox bootmeth driver Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 36/41] test: fastboot: Avoid using mmc1 Simon Glass
                     ` (22 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut

Add a bootdev driver for USB host. It can use the distro boot mechanism to
locate a file, or any other available bootmeth.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 common/usb_storage.c           | 12 +++++++
 drivers/usb/host/Makefile      |  4 +++
 drivers/usb/host/usb_bootdev.c | 61 ++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)
 create mode 100644 drivers/usb/host/usb_bootdev.c

diff --git a/common/usb_storage.c b/common/usb_storage.c
index c9e2d7343ce..24ccb21701c 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -34,6 +34,7 @@
 
 #include <common.h>
 #include <blk.h>
+#include <bootdev.h>
 #include <command.h>
 #include <dm.h>
 #include <errno.h>
@@ -239,6 +240,17 @@ static int usb_stor_probe_device(struct usb_device *udev)
 			if (ret)
 				return ret;
 		}
+
+		ret = bootdev_setup_sibling_blk(dev, "usb_bootdev");
+		if (ret) {
+			int ret2;
+
+			ret2 = device_unbind(dev);
+			if (ret2)
+				return log_msg_ret("bootdev", ret2);
+			return log_msg_ret("bootdev", ret);
+		}
+
 	}
 #else
 	/* We don't have space to even probe if we hit the maximum */
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index eb6fe9f6b30..742957d199c 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -8,6 +8,10 @@ obj-y += usb-uclass.o
 obj-$(CONFIG_SANDBOX) += usb-sandbox.o
 endif
 
+ifdef CONFIG_$(SPL_TPL_)USB_STORAGE
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += usb_bootdev.o
+endif
+
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
 obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c
new file mode 100644
index 00000000000..b85f699933d
--- /dev/null
+++ b/drivers/usb/host/usb_bootdev.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for USB
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <usb.h>
+
+static int usb_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+			    struct bootflow *bflow)
+{
+	struct udevice *blk;
+	int ret;
+
+	ret = bootdev_get_sibling_blk(dev, &blk);
+	/*
+	 * If there is no media, indicate that no more partitions should be
+	 * checked
+	 */
+	if (ret == -EOPNOTSUPP)
+		ret = -ESHUTDOWN;
+	if (ret)
+		return log_msg_ret("blk", ret);
+	assert(blk);
+	ret = bootdev_find_in_blk(dev, blk, iter, bflow);
+	if (ret)
+		return log_msg_ret("find", ret);
+
+	return 0;
+}
+
+static int usb_bootdev_bind(struct udevice *dev)
+{
+	struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	ucp->prio = BOOTDEVP_3_SCAN_SLOW;
+
+	return 0;
+}
+
+struct bootdev_ops usb_bootdev_ops = {
+	.get_bootflow	= usb_get_bootflow,
+};
+
+static const struct udevice_id usb_bootdev_ids[] = {
+	{ .compatible = "u-boot,bootdev-usb" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_bootdev) = {
+	.name		= "usb_bootdev",
+	.id		= UCLASS_BOOTDEV,
+	.ops		= &usb_bootdev_ops,
+	.bind		= usb_bootdev_bind,
+	.of_match	= usb_bootdev_ids,
+};
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 36/41] test: fastboot: Avoid using mmc1
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (34 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 35/41] bootstd: usb: Add a bootdev driver Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 37/41] test: dm: Restart USB before assuming it is stopped Simon Glass
                     ` (21 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

The bootflow tests need to use an MMC with an associated backing file
containing a filesystem. Update the fastboot tests to cope with this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/dm/fastboot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/dm/fastboot.c b/test/dm/fastboot.c
index e7f8c362b85..758538d0e85 100644
--- a/test/dm/fastboot.c
+++ b/test/dm/fastboot.c
@@ -81,9 +81,9 @@ static int dm_test_fastboot_mmc_part(struct unit_test_state *uts)
 						  &part_info, response));
 	ut_asserteq(0, fastboot_mmc_get_part_info("0.0:0", &fb_dev_desc,
 						  &part_info, response));
-	ut_asserteq(0, fastboot_mmc_get_part_info("1", &fb_dev_desc,
+	ut_asserteq(0, fastboot_mmc_get_part_info("2", &fb_dev_desc,
 						  &part_info, response));
-	ut_asserteq(0, fastboot_mmc_get_part_info("1.0", &fb_dev_desc,
+	ut_asserteq(0, fastboot_mmc_get_part_info("2.0", &fb_dev_desc,
 						  &part_info, response));
 	ut_asserteq(1, fastboot_mmc_get_part_info(":1", &fb_dev_desc,
 						  &part_info, response));
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 37/41] test: dm: Restart USB before assuming it is stopped
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (35 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 36/41] test: fastboot: Avoid using mmc1 Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 38/41] bootstd: Add tests for bootstd including all uclasses Simon Glass
                     ` (20 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass, Marek Vasut,
	Pavel Herrmann

Update the blk test to stop USB first, in case another test has started
it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/dm/blk.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/test/dm/blk.c b/test/dm/blk.c
index deccf05289b..b5957a20fb0 100644
--- a/test/dm/blk.c
+++ b/test/dm/blk.c
@@ -15,6 +15,9 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Allow resetting the USB-started flag */
+extern char usb_started;
+
 /* Test that block devices can be created */
 static int dm_test_blk_base(struct unit_test_state *uts)
 {
@@ -66,8 +69,11 @@ static int dm_test_blk_usb(struct unit_test_state *uts)
 	struct udevice *usb_dev, *dev;
 	struct blk_desc *dev_desc;
 
+	usb_started = false;
+
 	/* Get a flash device */
 	state_set_skip_delays(true);
+	ut_assertok(usb_stop());
 	ut_assertok(usb_init());
 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
 	ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 38/41] bootstd: Add tests for bootstd including all uclasses
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (36 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 37/41] test: dm: Restart USB before assuming it is stopped Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 39/41] bootstd: Add setup for the bootflow tests Simon Glass
                     ` (19 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add a set of combined tests for the bootdev, bootflow and bootmeth
commands, along with associated functionality.

Expand the sandbox console-recording limit so that these can work.

These tests rely on a filesystem script which is not yet added to the
Python tests. It is included here as a shell script.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS                        |   1 +
 arch/sandbox/dts/test.dts          |  18 ++
 configs/sandbox_defconfig          |   3 +-
 configs/sandbox_flattree_defconfig |   3 +-
 include/test/suites.h              |   2 +
 test/Makefile                      |   1 +
 test/boot/Makefile                 |   5 +
 test/boot/bootdev.c                | 200 +++++++++++++++
 test/boot/bootflow.c               | 398 +++++++++++++++++++++++++++++
 test/boot/bootmeth.c               |  90 +++++++
 test/boot/bootstd_common.c         |  35 +++
 test/boot/bootstd_common.h         |  27 ++
 test/cmd_ut.c                      |   7 +
 13 files changed, 788 insertions(+), 2 deletions(-)
 create mode 100644 test/boot/Makefile
 create mode 100644 test/boot/bootdev.c
 create mode 100644 test/boot/bootflow.c
 create mode 100644 test/boot/bootmeth.c
 create mode 100644 test/boot/bootstd_common.c
 create mode 100644 test/boot/bootstd_common.h

diff --git a/MAINTAINERS b/MAINTAINERS
index ae0b1613fe2..886802c81a4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -648,6 +648,7 @@ F:	include/bootflow.h
 F:	include/bootmeth.h
 F:	include/bootstd.h
 F:	net/eth_bootdevice.c
+F:	test/boot/
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 07a5118babe..b330f00cd7b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -71,6 +71,21 @@
 		};
 	};
 
+	bootstd {
+		compatible = "u-boot,boot-std";
+
+		filename-prefixes = "/", "/boot/";
+		bootdev-order = "mmc2", "mmc1";
+
+		syslinux {
+			compatible = "u-boot,distro-syslinux";
+		};
+
+		efi {
+			compatible = "u-boot,distro-efi";
+		};
+	};
+
 	reboot-mode0 {
 		compatible = "reboot-mode-gpio";
 		gpios = <&gpio_c 0 GPIO_ACTIVE_HIGH>, <&gpio_c 1 GPIO_ACTIVE_HIGH>;
@@ -882,10 +897,13 @@
 		non-removable;
 	};
 
+	/* This is used for the bootdev tests */
 	mmc1 {
 		compatible = "sandbox,mmc";
+		filename = "mmc1.img";
 	};
 
+	/* This is used for the fastboot tests */
 	mmc0 {
 		compatible = "sandbox,mmc";
 	};
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 9a462cb57c4..9978c6ab69a 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -28,7 +28,7 @@ CONFIG_AUTOBOOT_NEVER_TIMEOUT=y
 CONFIG_AUTOBOOT_STOP_STR_ENABLE=y
 CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9"
 CONFIG_CONSOLE_RECORD=y
-CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_LOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
@@ -119,6 +119,7 @@ CONFIG_ENV_IS_IN_EXT4=y
 CONFIG_ENV_EXT4_INTERFACE="host"
 CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_ENV_IMPORT_FDT=y
+# CONFIG_BOOTDEV_ETH is not set
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index be129133d3d..42ed24ed0c5 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -18,7 +18,7 @@ CONFIG_BOOTSTAGE_FDT=y
 CONFIG_BOOTSTAGE_STASH=y
 CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
 CONFIG_CONSOLE_RECORD=y
-CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_MISC_INIT_F=y
 CONFIG_CMD_CPU=y
@@ -74,6 +74,7 @@ CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_EXT4=y
 CONFIG_ENV_EXT4_INTERFACE="host"
 CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+# CONFIG_BOOTDEV_ETH is not set
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
diff --git a/include/test/suites.h b/include/test/suites.h
index d35cd83a4eb..bf79b008c1a 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -29,6 +29,8 @@ int cmd_ut_category(const char *name, const char *prefix,
 int do_ut_addrmap(struct cmd_tbl *cmdtp, int flag, int argc,
 		  char *const argv[]);
 int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc,
+		  char *const argv[]);
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
 		   char *const argv[]);
 int do_ut_common(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/test/Makefile b/test/Makefile
index b3b2902e2e7..abd605a4351 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o
 obj-y += ut.o
 
 ifeq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_UNIT_TEST) += boot/
 obj-$(CONFIG_UNIT_TEST) += common/
 obj-$(CONFIG_UNIT_TEST) += lib/
 obj-y += log/
diff --git a/test/boot/Makefile b/test/boot/Makefile
new file mode 100644
index 00000000000..1730792b5fa
--- /dev/null
+++ b/test/boot/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+
+obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
new file mode 100644
index 00000000000..5a6130fc0f0
--- /dev/null
+++ b/test/boot/bootdev.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for bootdev functions. All start with 'bootdev'
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <mapmem.h>
+#include <os.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+
+/* Allow reseting the USB-started flag */
+extern char usb_started;
+
+/* Check 'bootdev list' command */
+static int bootdev_test_cmd_list(struct unit_test_state *uts)
+{
+	int probed;
+
+	console_record_reset_enable();
+	for (probed = 0; probed < 2; probed++) {
+		int probe_ch = probed ? '+' : ' ';
+
+		ut_assertok(run_command(probed ? "bootdev list -p" :
+			"bootdev list", 0));
+		ut_assert_nextline("Seq  Probed  Status  Uclass    Name");
+		ut_assert_nextlinen("---");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 0, probe_ch, "OK",
+				   "mmc", "mmc2.bootdev");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 1, probe_ch, "OK",
+				   "mmc", "mmc1.bootdev");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 2, probe_ch, "OK",
+				   "mmc", "mmc0.bootdev");
+		ut_assert_nextlinen("---");
+		ut_assert_nextline("(3 bootdevs)");
+		ut_assert_console_end();
+	}
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootdev select' and 'info' commands */
+static int bootdev_test_cmd_select(struct unit_test_state *uts)
+{
+	struct bootstd_priv *std;
+
+	/* get access to the CLI's cur_bootdev */
+	ut_assertok(bootstd_get_priv(&std));
+
+	console_record_reset_enable();
+	ut_asserteq(1, run_command("bootdev info", 0));
+	ut_assert_nextlinen("Please use");
+	ut_assert_console_end();
+
+	/* select by sequence */
+	ut_assertok(run_command("bootdev select 0", 0));
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootdev info", 0));
+	ut_assert_nextline("Name:      mmc2.bootdev");
+	ut_assert_nextline("Sequence:  0");
+	ut_assert_nextline("Status:    Probed");
+	ut_assert_nextline("Uclass:    mmc");
+	ut_assert_nextline("Bootflows: 0 (0 valid)");
+	ut_assert_console_end();
+
+	/* select by bootdev name */
+	ut_assertok(run_command("bootdev select mmc1.bootdev", 0));
+	ut_assert_console_end();
+	ut_assertnonnull(std->cur_bootdev);
+	ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
+
+	/* select by bootdev label*/
+	ut_assertok(run_command("bootdev select mmc1", 0));
+	ut_assert_console_end();
+	ut_assertnonnull(std->cur_bootdev);
+	ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
+
+	/* deselect */
+	ut_assertok(run_command("bootdev select", 0));
+	ut_assert_console_end();
+	ut_assertnull(std->cur_bootdev);
+
+	ut_asserteq(1, run_command("bootdev info", 0));
+	ut_assert_nextlinen("Please use");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check bootdev labels */
+static int bootdev_test_labels(struct unit_test_state *uts)
+{
+	struct udevice *dev, *media;
+
+	ut_assertok(bootdev_find_by_label("mmc2", &dev));
+	ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+	media = dev_get_parent(dev);
+	ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
+	ut_asserteq_str("mmc2", media->name);
+
+	/* Check invalid uclass */
+	ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev));
+
+	/* Check unknown sequence number */
+	ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev));
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check bootdev ordering with the bootdev-order property */
+static int bootdev_test_order(struct unit_test_state *uts)
+{
+	struct bootflow_iter iter;
+	struct bootflow bflow;
+
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(2, iter.num_devs);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+	ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
+	bootflow_iter_uninit(&iter);
+
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(3, iter.num_devs);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+	ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
+	ut_asserteq_str("mmc0.bootdev", iter.dev_order[2]->name);
+
+	/*
+	 * Check that adding aliases for the bootdevs works. We just fake it by
+	 * setting the sequence numbers directly.
+	 */
+	iter.dev_order[0]->seq_ = 0;
+	iter.dev_order[1]->seq_ = 3;
+	iter.dev_order[2]->seq_ = 2;
+	bootflow_iter_uninit(&iter);
+
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(3, iter.num_devs);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+	ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name);
+	ut_asserteq_str("mmc1.bootdev", iter.dev_order[2]->name);
+	bootflow_iter_uninit(&iter);
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check bootdev ordering with the uclass priority */
+static int bootdev_test_prio(struct unit_test_state *uts)
+{
+	struct bootdev_uc_plat *ucp;
+	struct bootflow_iter iter;
+	struct bootflow bflow;
+	struct udevice *blk;
+
+	/* Start up USB which gives us three additional bootdevs */
+	usb_started = false;
+	ut_assertok(run_command("usb start", 0));
+
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	/* 3 MMC and 3 USB bootdevs: MMC should come before USB */
+	console_record_reset_enable();
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(6, iter.num_devs);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+	ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+			iter.dev_order[3]->name);
+
+	ut_assertok(bootdev_get_sibling_blk(iter.dev_order[3], &blk));
+	ut_asserteq_str("usb_mass_storage.lun0", blk->name);
+
+	/* adjust the priority of the first USB bootdev to the highest */
+	ucp = dev_get_uclass_plat(iter.dev_order[3]);
+	ucp->prio = 1;
+
+	bootflow_iter_uninit(&iter);
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(6, iter.num_devs);
+	ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+			iter.dev_order[0]->name);
+	ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name);
+
+	return 0;
+}
+BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
new file mode 100644
index 00000000000..b1287958eb5
--- /dev/null
+++ b/test/boot/bootflow.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for bootdev functions. All start with 'bootdev'
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+
+/* Check 'bootflow scan/list' commands */
+static int bootflow_cmd(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootdev select 1", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan' with a name / label / seq */
+static int bootflow_cmd_label(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -l mmc1", 0));
+	ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
+	ut_assert_skip_to_line("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0));
+	ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'");
+	ut_assert_skip_to_line("(0 bootflows, 0 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow scan -l 0", 0));
+	ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'");
+	ut_assert_skip_to_line("(0 bootflows, 0 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan/list' commands using all bootdevs */
+static int bootflow_cmd_glob(struct unit_test_state *uts)
+{
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootdevs");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
+	ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
+	ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
+	ut_assert_nextline("No more bootdevs");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing all bootflows");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -e' */
+static int bootflow_cmd_scan_e(struct unit_test_state *uts)
+{
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -ale", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootdevs");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
+	ut_assert_nextline("  0  syslinux     media   mmc          0  mmc2.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
+	ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
+
+	ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
+	ut_assert_nextline("  2  syslinux     media   mmc          0  mmc1.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-2");
+	ut_assert_nextline("  3  efi          media   mmc          0  mmc1.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-2");
+	ut_assert_nextline("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_nextline("  5  efi          fs      mmc          1  mmc1.bootdev.part_1       efi/boot/bootsbox.efi");
+
+	ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
+	ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
+	ut_assert_nextline("No more bootdevs");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(64 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing all bootflows");
+	ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  syslinux     media   mmc          0  mmc2.bootdev.whole        <NULL>");
+	ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
+	ut_assert_skip_to_line("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
+	ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(64 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow info' */
+static int bootflow_cmd_info(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootdev select 1", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow select 0", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow info", 0));
+	ut_assert_nextline("Name:      mmc1.bootdev.part_1");
+	ut_assert_nextline("Device:    mmc1.bootdev");
+	ut_assert_nextline("Block dev: mmc1.blk");
+	ut_assert_nextline("Method:    syslinux");
+	ut_assert_nextline("State:     ready");
+	ut_assert_nextline("Partition: 1");
+	ut_assert_nextline("Subdir:    (none)");
+	ut_assert_nextline("Filename:  /extlinux/extlinux.conf");
+	ut_assert_nextlinen("Buffer:    ");
+	ut_assert_nextline("Size:      253 (595 bytes)");
+	ut_assert_nextline("Error:     0");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow info -d", 0));
+	ut_assert_nextline("Name:      mmc1.bootdev.part_1");
+	ut_assert_skip_to_line("Error:     0");
+	ut_assert_nextline("Contents:");
+	ut_assert_nextline("%s", "");
+	ut_assert_nextline("# extlinux.conf generated by appliance-creator");
+	ut_assert_skip_to_line("        initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -b' to boot the first available bootdev */
+static int bootflow_scan_boot(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -b", 0));
+	ut_assert_nextline("** Booting bootflow 'mmc1.bootdev.part_1'");
+	ut_assert_nextline("Ignoring unknown command: ui");
+
+	/*
+	 * We expect it to get through to boot although sandbox always returns
+	 * -EFAULT as it cannot actually boot the kernel
+	 */
+	ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
+	ut_assert_nextline("Boot failed (err=-14)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check iterating through available bootflows */
+static int bootflow_iter(struct unit_test_state *uts)
+{
+	struct bootflow_iter iter;
+	struct bootflow bflow;
+
+	bootstd_clear_glob();
+
+	/* The first device is mmc2.bootdev which has no media */
+	ut_asserteq(-EPROTONOSUPPORT,
+		    bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(0, iter.cur_method);
+	ut_asserteq(0, iter.part);
+	ut_asserteq(0, iter.max_part);
+	ut_asserteq_str("syslinux", iter.method->name);
+	ut_asserteq(0, bflow.err);
+
+	/*
+	 * This shows MEDIA even though there is none, since int
+	 * bootdev_find_in_blk() we call part_get_info() which returns
+	 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
+	 * know.
+	 */
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+
+	ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(1, iter.cur_method);
+	ut_asserteq(0, iter.part);
+	ut_asserteq(0, iter.max_part);
+	ut_asserteq_str("efi", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+	bootflow_free(&bflow);
+
+	/* The next device is mmc1.bootdev - at first we use the whole device */
+	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(0, iter.cur_method);
+	ut_asserteq(0, iter.part);
+	ut_asserteq(0x1e, iter.max_part);
+	ut_asserteq_str("syslinux", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+	bootflow_free(&bflow);
+
+	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(1, iter.cur_method);
+	ut_asserteq(0, iter.part);
+	ut_asserteq(0x1e, iter.max_part);
+	ut_asserteq_str("efi", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+	bootflow_free(&bflow);
+
+	/* Then more to partition 1 where we find something */
+	ut_assertok(bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(0, iter.cur_method);
+	ut_asserteq(1, iter.part);
+	ut_asserteq(0x1e, iter.max_part);
+	ut_asserteq_str("syslinux", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_READY, bflow.state);
+	bootflow_free(&bflow);
+
+	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(1, iter.cur_method);
+	ut_asserteq(1, iter.part);
+	ut_asserteq(0x1e, iter.max_part);
+	ut_asserteq_str("efi", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_FS, bflow.state);
+	bootflow_free(&bflow);
+
+	/* Then more to partition 2 which doesn't exist */
+	ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+	ut_asserteq(2, iter.num_methods);
+	ut_asserteq(0, iter.cur_method);
+	ut_asserteq(2, iter.part);
+	ut_asserteq(0x1e, iter.max_part);
+	ut_asserteq_str("syslinux", iter.method->name);
+	ut_asserteq(0, bflow.err);
+	ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
+	bootflow_free(&bflow);
+
+	bootflow_iter_uninit(&iter);
+
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check using the system bootdev */
+static int bootflow_system(struct unit_test_state *uts)
+{
+	struct udevice *bootstd, *dev;
+
+	/* Add the EFI bootmgr driver */
+	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+	ut_assertok(device_bind_driver(bootstd, "bootmeth_efi_mgr", "bootmgr",
+				       &dev));
+
+	/* Add the system bootdev that it uses */
+	ut_assertok(device_bind_driver(bootstd, "system_bootdev",
+				       "system-bootdev", &dev));
+
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	/* We should get a single 'bootmgr' method right at the end */
+	bootstd_clear_glob();
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_skip_to_line("  1  bootmgr      ready   bootstd      0  <NULL>                    <NULL>");
+	ut_assert_nextline("No more bootdevs");
+	ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check disabling a bootmethod if it requests it */
+static int bootflow_iter_disable(struct unit_test_state *uts)
+{
+	struct udevice *bootstd, *dev;
+	struct bootflow_iter iter;
+	struct bootflow bflow;
+	int i;
+
+	/* Add the EFI bootmgr driver */
+	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+	ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox",
+				       &dev));
+
+	/* Add the system bootdev that it uses */
+	ut_assertok(device_bind_driver(bootstd, "system_bootdev",
+				       "system-bootdev", &dev));
+
+	ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+	bootstd_clear_glob();
+	ut_assertok(run_command("bootflow scan -lb", 0));
+
+	/* Try to boot the bootmgr flow, which will fail */
+	console_record_reset_enable();
+	ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+	ut_asserteq(3, iter.num_methods);
+	ut_asserteq_str("sandbox", iter.method->name);
+	ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
+
+	ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried");
+	ut_assert_console_end();
+
+	/* Check that the sandbox bootmeth has been removed */
+	ut_asserteq(2, iter.num_methods);
+	for (i = 0; i < iter.num_methods; i++)
+		ut_assert(strcmp("sandbox", iter.method_order[i]->name));
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow boot' to boot a selected bootflow */
+static int bootflow_cmd_boot(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootdev select 1", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow select 0", 0));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("bootflow boot", 0));
+	ut_assert_nextline("** Booting bootflow 'mmc1.bootdev.part_1'");
+	ut_assert_nextline("Ignoring unknown command: ui");
+
+	/*
+	 * We expect it to get through to boot although sandbox always returns
+	 * -EFAULT as it cannot actually boot the kernel
+	 */
+	ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
+	ut_assert_nextline("Boot failed (err=-14)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c
new file mode 100644
index 00000000000..d157fd3858a
--- /dev/null
+++ b/test/boot/bootmeth.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for bootdev functions. All start with 'bootdev'
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+
+/* Check 'bootmeth list' command */
+static int bootmeth_cmd_list(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmeth list", 0));
+	ut_assert_nextline("Order  Seq  Name                Description");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("    0    0  syslinux            Syslinux boot from a block device");
+	ut_assert_nextline("    1    1  efi                 EFI boot from a .efi file");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootmeth_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootmeth order' command */
+static int bootmeth_cmd_order(struct unit_test_state *uts)
+{
+	/* Select just one bootmethod */
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmeth order syslinux", 0));
+	ut_assert_console_end();
+
+	/* Only that one should be listed */
+	ut_assertok(run_command("bootmeth list", 0));
+	ut_assert_nextline("Order  Seq  Name                Description");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("    0    0  syslinux            Syslinux boot from a block device");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootmeth)");
+	ut_assert_console_end();
+
+	/* Check the -a flag, efi should show as not in the order ("-") */
+	ut_assertok(run_command("bootmeth list -a", 0));
+	ut_assert_nextline("Order  Seq  Name                Description");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("    0    0  syslinux            Syslinux boot from a block device");
+	ut_assert_nextline("    -    1  efi                 EFI boot from a .efi file");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_console_end();
+
+	/* Check the -a flag with the reverse order */
+	ut_assertok(run_command("bootmeth order efi syslinux", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootmeth list -a", 0));
+	ut_assert_nextline("Order  Seq  Name                Description");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("    1    0  syslinux            Syslinux boot from a block device");
+	ut_assert_nextline("    0    1  efi                 EFI boot from a .efi file");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_console_end();
+
+	/* Now reset the order to empty, which should show all of them again */
+	ut_assertok(run_command("bootmeth order", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootmeth list", 0));
+	ut_assert_skip_to_line("(2 bootmeths)");
+
+	/* Try reverse order */
+	ut_assertok(run_command("bootmeth order efi syslinux", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootmeth list", 0));
+	ut_assert_nextline("Order  Seq  Name                Description");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("    0    1  efi                 EFI boot from a .efi file");
+	ut_assert_nextline("    1    0  syslinux            Syslinux boot from a block device");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(2 bootmeths)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootmeth_cmd_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/boot/bootstd_common.c b/test/boot/bootstd_common.c
new file mode 100644
index 00000000000..05347d87106
--- /dev/null
+++ b/test/boot/bootstd_common.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for bootdev functions. All start with 'bootdev'
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootstd.h>
+#include <dm.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+
+int bootstd_test_drop_bootdev_order(struct unit_test_state *uts)
+{
+	struct bootstd_priv *priv;
+	struct udevice *bootstd;
+
+	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+	priv = dev_get_priv(bootstd);
+	priv->bootdev_order = NULL;
+
+	return 0;
+}
+
+int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(bootstd_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(bootstd_test);
+
+	return cmd_ut_category("bootstd", "bootstd_test_",
+			       tests, n_ents, argc, argv);
+}
diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h
new file mode 100644
index 00000000000..676ef0a57f9
--- /dev/null
+++ b/test/boot/bootstd_common.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common header file for bootdev, bootflow, bootmeth tests
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootstd_common_h
+#define __bootstd_common_h
+
+/* Declare a new bootdev test */
+#define BOOTSTD_TEST(_name, _flags) \
+		UNIT_TEST(_name, _flags, bootstd_test)
+
+struct unit_test_state;
+
+/**
+ * bootstd_test_drop_bootdev_order() - Remove the existing boot order
+ *
+ * Drop the boot order so that all bootdevs are used in their alias order
+ *
+ * @uts: Unit test state to use for ut_assert...() functions
+ */
+int bootstd_test_drop_bootdev_order(struct unit_test_state *uts);
+
+#endif
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 90b260f72d6..67a13ee32b8 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -28,6 +28,10 @@ int cmd_ut_category(const char *name, const char *prefix,
 
 static struct cmd_tbl cmd_ut_sub[] = {
 	U_BOOT_CMD_MKENT(all, CONFIG_SYS_MAXARGS, 1, do_ut_all, "", ""),
+#ifdef CONFIG_BOOTSTD
+	U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd,
+			 "", ""),
+#endif
 	U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""),
 #if defined(CONFIG_UT_DM)
 	U_BOOT_CMD_MKENT(dm, CONFIG_SYS_MAXARGS, 1, do_ut_dm, "", ""),
@@ -115,6 +119,9 @@ static char ut_help_text[] =
 	"ut bloblist - Test bloblist implementation\n"
 	"ut compression - Test compressors and bootm decompression\n"
 #endif
+#ifdef CONFIG_BOOTSTD
+	"ut bootstd - Test standard boot implementation\n"
+#endif
 #ifdef CONFIG_UT_DM
 	"ut dm [test-name]\n"
 #endif
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 39/41] bootstd: Add setup for the bootflow tests
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (37 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 38/41] bootstd: Add tests for bootstd including all uclasses Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 40/41] bootstd: doc: Add documentation Simon Glass
                     ` (18 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

We need to create a disk image with a partition table and a DOS-format
filesystem containing a few files. Provide a fallback binary for CI since
it does not seem able to detect the loopback partitions.

Add this to a dm_init test so that it happens when needed.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/tests/bootstd/mmc1.img.xz | Bin 0 -> 4448 bytes
 test/py/tests/test_ut.py          | 103 ++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 test/py/tests/bootstd/mmc1.img.xz

diff --git a/test/py/tests/bootstd/mmc1.img.xz b/test/py/tests/bootstd/mmc1.img.xz
new file mode 100644
index 0000000000000000000000000000000000000000..4e7f39b830eb4bddcb9ff6df39e89f130b5706b9
GIT binary patch
literal 4448
zcmeI0c{JOJ7RP@`Y(-R5?X`}rGNKxz9<j8IUF{-@c9c=1cC|-CYOSqGnW?SD*rkjm
zwrEML9ZRXDs3;}Y(T7+w@167BKku)3b7tQA$KUsld(Y?I^ZkC$J<$wzbOHd-@<hW;
zRzR9X2mpYfua`=g%tdzeZ2)+1a%`NFk@nORl#0;_jb!Af2?Uq<OQN^F=hL1^yra5*
z)ULN=qSItcRC)YMV_~JMi8PdmuvKSER?oUli7w*j@UDfq@L=ZOpyC)?J-1xS$XpK2
zYZF!p9&ow&?GR4z*q+#}I`^&8k@vQAr-#^4?EB>Y1f(ncsMm4@s?)THBgy{6U{9Xf
zjhWyTLq>&G;svF#Bje#;bOmkhhE$<HEn&c%2h{26<0EU8pdm?&l)=HQjSfS}ol6@x
zpzJgMv-Wm(JIu8LqHF45kPhWz@@FypAEFuOhM3ukHzDQ6k#k3RYA}0pTKq@YfHbYw
zdUq%F7k&Fy&GRZR1s1fW??laBe{OaWLwSpAO-JdpaXPcd3)>q9$<~I^9H$OcZc$TV
zMm~rDFT{WWjO6gcMYYHc+6;^JG8pkme*14Ce5le4a3Xkbt70^O7K>VGXX_ybx)*eD
zw6^43jCQ-EnZSx&neK#B$O{UBSSV)XEs1b#mSt8v(^ROEPcQ~<C-O-O`gl%=c`dC@
zZlJMG>?h~&+LRdcB!|Pg*6V;d|HfzwOc`HZ0F{bOiS(PfoQ$+96!SnBncAog%~~q+
z4pv?MwLy<7e_muzu9NC3mOJG=EjfgHZ^&EDT#iavdv!R~fYhpQHts|&4o{9py`Y_%
z31`~6QY-sMx{bA(spJ|Hg0FssAbqKREdQ!nnHCFF(SgD|u*oO@)b?YHOfi`nb2iqE
zo#dvbuHH>ts%D|qG|pzT<NA5=U}Cbr#w>pV-7MtB>3Vq!+w8Zx#o9YoLQmNagFld#
zP(41!ib&tauzdKXL3Wdvj^TFM^wfBX8wSVK3`s(RwOWClx9g+fhLgZM^F}%6wv}i0
z_2T0?&*=|tVg38)KCU;((P$nEiz00YJ12kgQ7#!ImFl3}h1PaL*2_u7xNC-Xp8x}W
zrZ#;_6cWGawviOU!FpMa4xBc8BKBpF@HY;3jrzikAK)rrz7cK3SIdLk);?Swpj+u!
zauVI(Z3zMX;2A<am3^4{a9nP@6&l!P$d!7NOA$g52)R<#;v=pvjUNMFv}5~Gpn<XO
zf&ZFXQ@4{ZzAqDJ4&Hl+Q7Ry)Vx3J)9j{n$D2$b|O9az}FRWcPYku-t()ezlD$;Tr
z{<MNtCh(+P)vKt-598=eQQ>oFtX#dnXQY97ZpySTjNrJ{%!f$Y`gK%8nEg4geO3mc
z-OP*|Ch_5AWY9NP%p&~M>ZAJ??-^R7P2+1Hb2rgsO2X$eMJ<7l))#5bjryO*Dqa)`
z%;XHzXL<#CLI9X5|4{QLx2n8#cjne^EA6#n{fUKE*apICl#Rr5`b4w-6|DH9x(%>u
zAblDl+7gOW;#{pAugK1-4d((c<m--*W%*!KZ`#Yrg*yS}QFfbytt^U?hi1<(z;~<9
z>KffC%}1y~xAgK-kIY#om$h-hU6uL%6{?p4=faq|cA$OJ7|(inY7C)NO<foyYD}kK
zpk%Vbqa~iOxE%Y9biE>BNMaX+?yr2|aOhe9tKnj)<)sFT!^mcwJjoRb=G@*C$wRry
zPTo*uOsd<i&-G@k9BIb#%Lp+wS5XrE;Ug_Ar5_L-w35%d&}Y=@X=U~b`RqY1eoyIW
z1?~tZ8PYQ9Aj}u!U;X968@+To%~0N@*zT)7XK@X?#EJH;wuw{nu8u$=o@j5zGKrX&
zJDO5(48p&Q>FL<_`GKQyEJE$O5|axr@ik&j;SomgcM_v6f@QoLawwxx>yHJePg!~N
z!c}v~e55d};P9~<!QsvJsRGm4PdupPSil^DD*B8!R^Q3Fk3Ef^!?6)FEql?IuLvyX
zEkBm|Dr@V$SFvVNmVfc^w|dGcjIoa7;`PGVTo8qCog$n4y0@}P;v)~}Zatb2m>2ji
z?smHa;#j<|fU46!w;JJ1IC}O?Fiq)m)lfbK=CSvquxAa|fn+FXteGTw`$1R2xqL53
z+Rq|Rc3KPV#k%(QqK*DO9AuCG9)ulipIS+(&QWE;*777sZ;1-R&S=7_hqYtJ>Yt>x
zRotR}1x$Vx6<|HkrtGAnCK4`M(3A?t`n@QVbzN5+h#$$$O^Q~|*ii`H7a_Cfn&+NO
z){dt`y5(&cyBP>LxU_EbL6@I7if1I_d_}d}Uo+;vP2meZmVEF3+S&?&e02uw_ZaxU
zc6A2q_a>e*VE<)AJOg$H?0@1nXBu{<VSjS)`j13&c42?u!f>3A05H(`mV)`mrvw0O
h4`jqrLheQZEG;rP9FCigsLUjGdmgd=vj{>v{RVxmraJ%t

literal 0
HcmV?d00001

diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index 01c2b3ffa12..dd1a6696da1 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -1,9 +1,102 @@
 # SPDX-License-Identifier: GPL-2.0
 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
 
+import gzip
+import os
 import os.path
 import pytest
 
+import u_boot_utils
+
+def mkdir_cond(dirname):
+    """Create a directory if it doesn't already exist
+
+    Args:
+        dirname: Name of directory to create
+    """
+    if not os.path.exists(dirname):
+        os.mkdir(dirname)
+
+def setup_bootflow_image(u_boot_console):
+    """Create a 20MB disk image with a single FAT partition"""
+    cons = u_boot_console
+    fname = os.path.join(cons.config.source_dir, 'mmc1.img')
+    mnt = os.path.join(cons.config.persistent_data_dir, 'mnt')
+    mkdir_cond(mnt)
+
+    u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname)
+    u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname,
+                             stdin=b'type=c')
+
+    loop = None
+    mounted = False
+    complete = False
+    try:
+        out = u_boot_utils.run_and_log(cons,
+                                       'sudo losetup --show -f -P %s' % fname)
+        loop = out.strip()
+        fatpart = '%sp1' % loop
+        u_boot_utils.run_and_log(cons, 'sudo mkfs.vfat %s' % fatpart)
+        u_boot_utils.run_and_log(
+            cons, 'sudo mount -o loop %s %s -o uid=%d,gid=%d' %
+            (fatpart, mnt, os.getuid(), os.getgid()))
+        mounted = True
+
+        vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl'
+        initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img'
+        dtbdir = 'dtb-5.3.7-301.fc31.armv7hl'
+        script = '''# extlinux.conf generated by appliance-creator
+ui menu.c32
+menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options.
+menu title Fedora-Workstation-armhfp-31-1.9 Boot Options.
+menu hidden
+timeout 20
+totaltimeout 600
+
+label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+        kernel /%s
+        append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
+        fdtdir /%s/
+        initrd /%s''' % (vmlinux, dtbdir, initrd)
+        ext = os.path.join(mnt, 'extlinux')
+        mkdir_cond(ext)
+
+        with open(os.path.join(ext, 'extlinux.conf'), 'w') as fd:
+            print(script, file=fd)
+
+        inf = os.path.join(cons.config.persistent_data_dir, 'inf')
+        with open(inf, 'wb') as fd:
+            fd.write(gzip.compress(b'vmlinux'))
+        u_boot_utils.run_and_log(cons, 'mkimage -f auto -d %s %s' %
+                                 (inf, os.path.join(mnt, vmlinux)))
+
+        with open(os.path.join(mnt, initrd), 'w') as fd:
+            print('initrd', file=fd)
+
+        mkdir_cond(os.path.join(mnt, dtbdir))
+
+        dtb_file = os.path.join(mnt, '%s/sandbox.dtb' % dtbdir)
+        u_boot_utils.run_and_log(
+            cons, 'dtc -o %s' % dtb_file, stdin=b'/dts-v1/; / {};')
+        complete = True
+    except ValueError as exc:
+        print('Falled to create image, failing back to prepared copy: %s',
+              str(exc))
+    finally:
+        if mounted:
+            u_boot_utils.run_and_log(cons, 'sudo umount %s' % mnt)
+        if loop:
+            u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop)
+
+    if not complete:
+        # Use a prepared image since we cannot create one
+        infname = os.path.join(cons.config.source_dir,
+                               'test/py/tests/bootstd/mmc1.img.xz')
+        u_boot_utils.run_and_log(
+            cons,
+            ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)])
+
+
 @pytest.mark.buildconfigspec('ut_dm')
 def test_ut_dm_init(u_boot_console):
     """Initialize data for ut dm tests."""
@@ -21,6 +114,16 @@ def test_ut_dm_init(u_boot_console):
         with open(fn, 'wb') as fh:
             fh.write(data)
 
+@pytest.mark.buildconfigspec('cmd_bootstd')
+def test_ut_dm_init_bootstd(u_boot_console):
+    """Initialise data for bootflow tests"""
+
+    setup_bootflow_image(u_boot_console)
+
+    # Restart so that the new mmc1.img is picked up
+    u_boot_console.restart_uboot()
+
+
 def test_ut(u_boot_console, ut_subtest):
     """Execute a "ut" subtest.
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 40/41] bootstd: doc: Add documentation
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (38 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 39/41] bootstd: Add setup for the bootflow tests Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-23 23:26   ` [PATCH v2 41/41] RFC: Switch rpi over to use bootstd Simon Glass
                     ` (17 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Add documentation for this feature, including the commands and full
devicetree bindings.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 MAINTAINERS                           |   4 +
 doc/develop/bootstd.rst               | 600 ++++++++++++++++++++++++++
 doc/develop/distro.rst                |   3 +
 doc/develop/index.rst                 |   1 +
 doc/device-tree-bindings/bootdev.txt  |  18 +
 doc/device-tree-bindings/bootmeth.txt |  31 ++
 doc/device-tree-bindings/bootstd.txt  |   8 +
 doc/usage/bootdev.rst                 | 135 ++++++
 doc/usage/bootflow.rst                | 427 ++++++++++++++++++
 doc/usage/bootmeth.rst                | 106 +++++
 doc/usage/index.rst                   |   3 +
 11 files changed, 1336 insertions(+)
 create mode 100644 doc/develop/bootstd.rst
 create mode 100644 doc/device-tree-bindings/bootmeth.txt
 create mode 100644 doc/usage/bootdev.rst
 create mode 100644 doc/usage/bootflow.rst
 create mode 100644 doc/usage/bootmeth.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 886802c81a4..f2964ec2eb0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -642,6 +642,10 @@ F:	boot/bootmeth*.c
 F:	boot/bootstd.c
 F:	cmd/bootdev.c
 F:	cmd/bootflow.c
+F:	doc/develop/bootstd.rst
+F:	doc/usage/bootdev.rst
+F:	doc/usage/bootflow.rst
+F:	doc/usage/bootmeth.rst
 F:	drivers/mmc/mmc_bootdev.c
 F:	include/bootdev.h
 F:	include/bootflow.h
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
new file mode 100644
index 00000000000..8b27549601a
--- /dev/null
+++ b/doc/develop/bootstd.rst
@@ -0,0 +1,600 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+U-Boot Standard Boot
+====================
+
+Introduction
+------------
+
+Standard boot provides a built-in way for U-Boot to automatically boot
+an Operating System without custom scripting and other customisation. It
+introduces the following concepts:
+
+   - bootdev  - a device which can hold or access a distro (e.g. MMC, Ethernet)
+   - bootmeth - a method to scan a bootdev to find bootflows (e.g. distro boot)
+   - bootflow - a description of how to boot (provided by the distro)
+
+For Linux, the distro (Linux distribution, e.g. Debian, Fedora) is responsible
+for creating a bootflow for each kernel combination that it wants to offer.
+These bootflows are stored on media so they can be discovered by U-Boot. This
+feature is typically called `distro boot` (see :doc:`distro`) because it is
+a way for distributions to boot on any hardware.
+
+Traditionally U-Boot has relied on scripts to implement this feature. See
+disto_boodcmd_ for details. This is done because U-Boot has no native support
+for scanning devices. While the scripts work remarkably well, they can be hard
+to understand and extend, and the feature does not include tests. They are also
+making it difficult to move away from ad-hoc CONFIGs, since they are implemented
+using the environment and a lot of #defines.
+
+Standard boot is a generalisation of distro boot. It provides a more built-in
+way to boot with U-Boot. The feature is extensible to different Operating
+Systems (such as Chromium OS) and devices (beyond just block and network
+devices). It supports EFI boot and EFI bootmgr too.
+
+
+Bootflow
+--------
+
+A bootflow is a file that describes how to boot a distro. Conceptually there can
+be different formats for that file but at present U-Boot only supports the
+BootLoaderSpec_ format. which looks something like this::
+
+   menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options.
+   menu title Fedora-Workstation-armhfp-31-1.9 Boot Options.
+   menu hidden
+
+   label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+       kernel /vmlinuz-5.3.7-301.fc31.armv7hl
+       append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
+       fdtdir /dtb-5.3.7-301.fc31.armv7hl/
+       initrd /initramfs-5.3.7-301.fc31.armv7hl.img
+
+As you can see it specifies a kernel, a ramdisk (initrd) and a directory from
+which to load devicetree files. The details are described in disto_boodcmd_.
+
+The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job
+is simply to interpret the file and carry out the instructions. This allows
+distros to boot on essentially any device supported by U-Boot.
+
+Typically the first available bootflow is selected and booted. If that fails,
+then the next one is tried.
+
+
+Bootdev
+-------
+
+Where does U-Boot find the media that holds the operating systems? That is the
+job of bootdev. A bootdev is simply a layer on top of a media device (such as
+MMC, NVMe). The bootdev accesses the device, including partitions and
+filesystems that might contain things related to an operating system.
+
+For example, an MMC bootdev provides access to the individual partitions on the
+MMC device. It scans through these to find filesystems, then provides a list of
+these for consideration.
+
+
+Bootmeth
+--------
+
+Once the list of filesystems is provided, how does U-Boot find the bootflow
+files in these filesystems. That is the job of bootmeth. Each boot method has
+its own way of doing this.
+
+For example, the distro bootmeth simply looks through the provided filesystem
+for a file called `extlinux/extlinux.conf`. This files constitutes a bootflow.
+If the distro bootmeth is used on multiple partitions it may produce multiple
+bootflows.
+
+Note: it is possible to have a bootmeth that uses a partition or a whole device
+directly, but it is more common to use a filesystem.
+
+
+Boot process
+------------
+
+U-Boot tries to use the 'lazy init' approach whereever possible and distro boot
+is no exception. The algorithm is::
+
+   while (get next bootdev)
+      while (get next bootmeth)
+          while (get next bootflow)
+              try to boot it
+
+So U-Boot works its way through the bootdevs, trying each bootmeth in turn to
+obtain bootflows, until it either boots or exhausts the available options.
+
+Instead of 500 lines of #defines and a 4KB boot script, all that is needed is
+the following command::
+
+   bootflow scan -lb
+
+which scans for available bootflows, optionally listing each find it finds (-l)
+and trying to boot it (-b).
+
+
+Bootdev uclass
+--------------
+
+The bootdev uclass provides an simple API call to obtain a bootflows from a
+device::
+
+   int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+                            struct bootflow *bflow);
+
+This takes a iterator which indicates the bootdev, partition and bootmeth to
+use. It returns a bootflow. This is the core of the bootdev implementation. The
+bootdev drivers that implement this differ depending on the media they are
+reading from, but each is responsible for returning a valid bootflow if
+available.
+
+A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this
+function for each media device uclass, in a few lines of code.
+
+
+Bootdev drivers
+---------------
+
+A bootdev driver is typically fairly simple. Here is one for mmc::
+
+    static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+                    struct bootflow *bflow)
+    {
+        struct udevice *mmc_dev = dev_get_parent(dev);
+        struct udevice *blk;
+        int ret;
+
+        ret = mmc_get_blk(mmc_dev, &blk);
+        /*
+         * If there is no media, indicate that no more partitions should be
+         * checked
+         */
+        if (ret == -EOPNOTSUPP)
+            ret = -ESHUTDOWN;
+        if (ret)
+            return log_msg_ret("blk", ret);
+        assert(blk);
+        ret = bootdev_find_in_blk(dev, blk, iter, bflow);
+        if (ret)
+            return log_msg_ret("find", ret);
+
+        return 0;
+    }
+
+    static int mmc_bootdev_bind(struct udevice *dev)
+    {
+        struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+        ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
+
+        return 0;
+    }
+
+    struct bootdev_ops mmc_bootdev_ops = {
+        .get_bootflow    = mmc_get_bootflow,
+    };
+
+    static const struct udevice_id mmc_bootdev_ids[] = {
+        { .compatible = "u-boot,bootdev-mmc" },
+        { }
+    };
+
+    U_BOOT_DRIVER(mmc_bootdev) = {
+        .name        = "mmc_bootdev",
+        .id        = UCLASS_BOOTDEV,
+        .ops        = &mmc_bootdev_ops,
+        .bind        = mmc_bootdev_bind,
+        .of_match    = mmc_bootdev_ids,
+    };
+
+The implementation of the `get_bootflow()` method is simply to obtain the
+block device and call a bootdev helper function to do the rest. The
+implementation of `bootdev_find_in_blk()` checks the partition table, and
+attempts to read a file from a filesystem on the partition number given by the
+`@iter->part` parameter.
+
+Each bootdev has a priority, which indicates the order in which it is used.
+Faster bootdevs are used first, since they are more likely to be able to boot
+the device quickly.
+
+
+Device hierarchy
+----------------
+
+A bootdev device is a child of the media device. In this example, you can see
+that the bootdev is a sibling of the block device and both are children of
+media device::
+
+    mmc           0  [ + ]   bcm2835-sdhost        |   |-- mmc@7e202000
+    blk           0  [ + ]   mmc_blk               |   |   |-- mmc@7e202000.blk
+    bootdev       0  [   ]   mmc_bootdev           |   |   `-- mmc@7e202000.bootdev
+    mmc           1  [ + ]   sdhci-bcm2835         |   |-- sdhci@7e300000
+    blk           1  [   ]   mmc_blk               |   |   |-- sdhci@7e300000.blk
+    bootdev       1  [   ]   mmc_bootdev           |   |   `-- sdhci@7e300000.bootdev
+
+The bootdev device is typically created automatically in the media uclass'
+`post_bind()` method by calling `bootdev_setup_for_dev()`. The code typically
+something like this::
+
+    ret = bootdev_setup_for_dev(dev, "eth_bootdev");
+    if (ret)
+        return log_msg_ret("bootdev", ret);
+
+Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev`
+is the ethernet device. This function is safe to call even if standard boot is
+not enabled, since it does nothing in that case. It can be added to all uclasses
+which implement suitable media.
+
+
+The bootstd device
+------------------
+
+Standard boot requires a single instance of the bootstd device to make things
+work. This includes global information about the state of standard boot. See
+`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
+
+Within the devicetree, if you add bootmeth devices or a system bootdev, they
+should be children of the bootstd device. See `arch/sandbox/dts/test.dts` for
+an example of this.
+
+
+The system bootdev
+------------------
+
+Some bootmeths don't operate on individual bootdevs, but on the whole system.
+For example, the EFI boot manager does its own device scanning and does not
+make use of the bootdev devices. Such bootmeths can make use of the system
+bootdev, typically considered last, after everything else has been tried.
+
+
+.. _`Automatic Devices`:
+
+Automatic devices
+-----------------
+
+It is possible to define all the required devices in the devicetree manually,
+but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
+function which creates the bootstd device if not found. If no bootmeth devices
+are found at all, it creates one for each available bootmeth driver as well as a
+system bootdev.
+
+If your devicetree has any bootmeth device it must have all of them that you
+want to use, as well as the system bootdev if needed, since no bootmeth devices
+will be created automatically in that case.
+
+
+Using devicetree
+----------------
+
+If a bootdev is complicated or needs configuration information, it can be
+added to the devicetree as a child of the media device. For example, imagine a
+bootdev which reads a bootflow from SPI flash. The devicetree fragment might
+look like this::
+
+    spi@0 {
+        flash@0 {
+            reg = <0>;
+            compatible = "spansion,m25p16", "jedec,spi-nor";
+            spi-max-frequency = <40000000>;
+
+            bootdev {
+                compatible = "u-boot,sf-bootdev";
+                offset = <0x2000>;
+                size = <0x1000>;
+            };
+        };
+    };
+
+The `sf-bootdev` driver can implement a way to read from the SPI flash, using
+the offset and size provided, and return that bootflow file back to the caller.
+When distro boot wants to read the kernel it calls disto_getfile() which must
+provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_
+for more details.
+
+Of course this is all internal to U-Boot. All the distro sees is another way
+to boot.
+
+
+Configuration
+-------------
+
+Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG
+option also. For example, `CONFIG_BOOTMETH_DISTRO` enables support for distro
+boot from a disk.
+
+
+Available bootmeth drivers
+--------------------------
+
+Bootmeth drivers are provided for:
+
+   - distro boot from a disk (syslinux)
+   - distro boot from a network (PXE)
+   - EFI boot using bootefi
+   - EFI boot using boot manager
+
+
+Command interface
+-----------------
+
+Three commands are available:
+
+`bootdev`
+    Allows listing of available bootdevs, selecting a particular one and
+    getting information about it. See :doc:`../usage/bootdev`
+
+`bootflow`
+    Allows scanning one or more bootdevs for bootflows, listing available
+    bootflows, selecting one, obtaining information about it and booting it.
+    See :doc:`../usage/bootflow`
+
+`bootmeth`
+    Allow listing of available bootmethds and setting the order in which they
+    are tried. See :doc:`../usage/bootmeth`
+
+.. _BootflowStates:
+
+Bootflow states
+---------------
+
+Here is a list of states that a bootflow can be in:
+
+=======  =======================================================================
+State    Meaning
+=======  =======================================================================
+base     Starting-out state, indicates that no media/partition was found. For an
+         SD card socket it may indicate that the card is not inserted.
+media    Media was found (e.g. SD card is inserted) but no partition information
+         was found. It might lack a partition table or have a read error.
+part     Partition was found but a filesystem could not be read. This could be
+         because the partition does not hold a filesystem or the filesystem is
+         very corrupted.
+fs       Filesystem was found but the file could not be read. It could be
+         missing or in the wrong subdirectory.
+file     File was found and its size detected, but it could not be read. This
+         could indicate filesystem corruption.
+ready    File was loaded and is ready for use. In this state the bootflow is
+         ready to be booted.
+=======  =======================================================================
+
+
+Theory of operation
+-------------------
+
+This describes how standard boot progresses through to booting an operating
+system.
+
+To start. all the necessary devices must be bound, including bootstd, which
+provides the top-level `struct bootstd_priv` containing optional configuration
+information. The bootstd device is also holds the various lists used while
+scanning. This step is normally handled automatically by driver model, as
+described in `Automatic Devices`_.
+
+Bootdevs are also required, to provide access to the media to use. These are not
+useful by themselves: bootmeths are needed to provide the means of scanning
+those bootdevs. So, all up, we need a single bootstd device, one or more bootdev
+devices and one or more bootmeth devices.
+
+Once these are ready, typically a `bootflow scan` command is issued. This kicks
+of the iteration process, which involves looking through the bootdevs and their
+partitions one by one to find bootflows.
+
+Iteration is kicked off using `bootflow_scan_first()`, which calls
+`bootflow_scan_bootdev()`.
+
+The iterator is set up with `bootflow_iter_init()`. This simply creates an
+empty one with the given flags. Flags are used to control whether each
+iteration is displayed, whether to return iterations even if they did not result
+in a valid bootflow, whether to iterate through just a single bootdev, etc.
+
+Then the ordering of bootdevs is determined, by `setup_bootdev_order()`. By
+default, the bootdevs are used in their sequence order, as determined by the
+`/aliases` node, or failing that their order in the devicetree. But if there is
+a `bootdev-order` property in the bootstd node, then this is used instead. In
+any case, the iterator ends up with a `dev_order` array containing the bootdevs
+that are going to be used, with `num_devs` set to the number of bootdevs and
+`cur_dev` starting at 0.
+
+Next, the ordering of bootdevs is determined, by `setup_bootmeth_order()`. By
+default the ordering is again by sequence number, i.e. the `/aliases` node, or
+failing that the order in the devicetree. But the `bootmeth order` command can
+be used to set up an ordering. If that has been done, the ordering is in
+`struct bootstd_priv`, so that ordering is simply copied into the iterator.
+Either way, the `method_order` array it set up, along with `num_methods`. Then
+`cur_method` is set to 0.
+
+At this point the iterator is ready to use, with the first bootdev and bootmeth
+selected. All the other fields are 0. This means that the current partition is
+0, which is taken to mean the whole device, since partition numbers start at 1.
+It also means that `max_part` is 0, i.e. the maximum partition number we know
+about is 0, meaning that, as far as we know, there is no partition table on this
+bootdev.
+
+With the iterator ready, `bootflow_scan_bootdev()` checks whether the current
+settings produce a valid bootflow. This is handled by `bootflow_check()`, which
+either returns 0 (if it got something) or an error if not (more on that later).
+If the `BOOTFLOWF_ALL` iterator flag is set, even errors are returned as
+incomplete bootflows, but normally an error results in moving onto the next
+iteration.
+
+The `bootflow_scan_next()` function handles moving onto the next iteration and
+checking it. In fact it sits in a loop doing that repeatedly until it finds
+something it wants to return.
+
+The actual 'moving on' part is implemented in `iter_incr()`. This is a very
+simple function. It increments the first counter. If that hits its maximum, it
+sets it to zero and increments the second counter. You can think of all the
+counters together as a number with three digits which increment in order, with
+the least-sigificant digit on the right, counting like this:
+
+   ========    =======    =======
+   bootdev     part       method
+   ========    =======    =======
+   0           0          0
+   0           0          1
+   0           0          2
+   0           1          0
+   0           1          1
+   0           1          1
+   1           0          0
+   1           0          1
+   ========    =======    =======
+
+The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
+goes back to 0 and the next `part` is considered. The maximum value for that is
+`max_part`, which is initially zero for all bootdevs. If we find a partition
+table on that bootdev, `max_part` can be updated during the iteration to a
+higher value - see `bootdev_find_in_blk()` for that, described later. If that
+exceeds its maximum, then the next bootdev is used. In this way, iter_incr()
+works its way through all possibilities, moving forward one each time it is
+called.
+
+There is no expectation that iteration will actually finish. Quite often a
+valid bootflow is found early on. With `bootflow scan -b`, that causes the
+bootflow to be immediately booted. Assuming it is successful, the iteration never
+completes.
+
+Also note that the iterator hold the **current** combination being considered.
+So when `iter_incr()` is called, it increments to the next one and returns it,
+the new **current** combination.
+
+Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has
+thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error,
+it indicates to the iterator what it should do when called. It can force moving
+to the next partition, or bootdev, for example. The special values
+`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees
+`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev.
+When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do
+so it should immediately return. The caller of `iter_incr()` is responsible for
+updating the `err` field, based on the return value it sees.
+
+The above describes the iteration process at a high level. It is basically a
+very simple increment function with a checker called `bootflow_check()` that
+checks the result of each iteration generated, to determine whether it can
+produce a bootflow.
+
+So what happens inside of `bootflow_check()`? It simply calls the uclass
+method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It
+passes the iterator to the bootdev method, so that function knows what we are
+talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
+with just the `method` and `dev` intiialised. But the bootdev may fill in more,
+e.g. updating the state, depending on what it finds.
+
+Based on what the bootdev responds with, `bootflow_check()` either
+returns a valid bootflow, or a partial one with an error. A partial bootflow
+is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
+state. As noted before, if the `BOOTFLOWF_ALL` iterator flag is set, then all
+bootflows are returned, even partial ones. This can help with debugging.
+
+So at this point you can see that total control over whether a bootflow can
+be generated from a particular iteration, or not, rests with the bootdev.
+Each one can adopt its own approach.
+
+Going down a level, what does the bootdev do in its `get_bootflow()` method?
+Let us consider the MMC bootdev. In that case the call to
+`bootdev_get_bootflow()` ends up in `mmc_get_bootflow()`. It locates the parent
+device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds the block
+device associated with it. It then calls the helper function
+`bootdev_find_in_blk()` to do all the work. This is common with just about any
+bootdev that is based on a media device.
+
+The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It
+names the bootflow and copies the partition number in from the iterator. Then it
+calls the bootmeth device to check if it can support this device. This is
+important since some bootmeths only work with network devices, for example. If
+that check fails, it stops.
+
+Assuming the bootmeth is happy, or at least indicates that it is willing to try
+(by returning 0 from its `check()` method), the next step is to try the
+partition. If that works it tries to detect a file system. If that works then it
+calls the bootmeth device once more, this time to read the bootflow.
+
+Note: At present a filesystem is needed for the bootmeth to be called on block
+devices, simply because we don't have any examples where this is not the case.
+This feature can be added as needed.
+
+If we take the example of the `bootmeth_distro` driver, this call ends up at
+`distro_read_bootflow()`. It has the filesystem ready, so tries various
+filenames to try to find the `extlinux.conf` file, reading it if possible. If
+all goes well the bootflow ends up in the `BOOTFLOWST_READY` state.
+
+At this point, we fall back from the bootmeth driver, to
+`bootdev_find_in_blk()`, then back to `mmc_get_bootflow()`, then to
+`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller,
+either `bootflow_scan_bootdev()` or `bootflow_scan_next()`. In either case,
+the bootflow is returned as the result of this iteration, assuming it made it to
+the  `BOOTFLOWST_READY` state.
+
+That is the basic operation of scanning for bootflows. The process of booting a
+bootflow is handled by the bootmeth driver for that bootflow. In the case of
+distro boot, this parses and processes the `extlinux.conf` file that was read.
+See `distro_boot()` for how that works. The processing may involve reading
+additional files, which is handled by the `read_file()` method, which is
+`distro_read_file()` in this case. All bootmethds should support reading files,
+since the bootflow is typically only the basic instructions and does not include
+the operating system itself, ramdisk, device tree, etc.
+
+The vast majority of the bootstd code is concerned with iterating through
+partitions on bootdevs and using bootmethds to find bootflows.
+
+How about bootdevs which are not block devices? They are handled by the same
+methods as above, but with a different implementation. For example, the bootmeth
+for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`.
+But other that that it is very similar.
+
+
+Tests
+-----
+
+Tests are located in `test/boot` and cover the core functionality as well as
+the commands. All tests use sandbox so can be run on a standard Linux computer
+and in U-Boot's CI.
+
+For testing, a DOS-formatted disk image is used with a single FAT partition on
+it. This is created in `setup_bootflow_image()`, with a canned one from the
+source tree used if it cannot be created (e.g. in CI).
+
+
+Bootflow internals
+------------------
+
+The bootstd device holds a linked list of scanned bootflows as well as the
+currently selected bootdev and bootflow (for use by commands). This is in
+`struct bootstd_priv`.
+
+Each bootdev device has its own `struct bootdev_uc_plat` which holds a
+list of scanned bootflows just for that device.
+
+The bootflow itself is documented in bootflow_h_. It includes various bits of
+information about the bootflow and a buffer to hold the file.
+
+
+Future
+------
+
+Apart from the to-do items below, different types of bootflow files may be
+implemented in future, e.g. Chromium OS support which is currently only
+available as a script in chromebook_coral.
+
+
+To do
+-----
+
+Some things that need to be done to completely replace the distro-boot scripts:
+
+- add bootdev drivers for dhcp, sata, scsi, ide, virtio
+- PXE boot for EFI
+- support for loading U-Boot scripts
+
+Other ideas:
+
+- `bootflow prep` to load everything preparing for boot, so that `bootflow boot`
+  can just do the boot.
+- automatically load kernel, FDT, etc. to suitable addresses so the board does
+  not need to specify things like `pxefile_addr_r`
+
+
+.. _disto_boodcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h
+.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
+.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c
+.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h
diff --git a/doc/develop/distro.rst b/doc/develop/distro.rst
index c522be69349..7ea84b5793c 100644
--- a/doc/develop/distro.rst
+++ b/doc/develop/distro.rst
@@ -157,6 +157,9 @@ a line with "CONFIG_DISTRO_DEFAULTS=y". If you want to enable this
 from Kconfig itself, for e.g. all boards using a specific SoC then
 add a "imply DISTRO_DEFAULTS" to your SoC CONFIG option.
 
+
+TO BE UPDATED:
+
 In your board configuration file, include the following::
 
     #ifndef CONFIG_SPL_BUILD
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index b3871b16f35..dbd66b68870 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -10,6 +10,7 @@ Implementation
    :maxdepth: 1
 
    bloblist
+   bootstd
    ci_testing
    commands
    config_binding
diff --git a/doc/device-tree-bindings/bootdev.txt b/doc/device-tree-bindings/bootdev.txt
index 95b7fec8212..4bb2345a0b9 100644
--- a/doc/device-tree-bindings/bootdev.txt
+++ b/doc/device-tree-bindings/bootdev.txt
@@ -6,3 +6,21 @@ child of the media device (UCLASS_MMC, UCLASS_SPI_FLASH, etc.)
 
 The bootdev driver is provided by the media devices. The bindings for each
 are described in this file (to come).
+
+Required properties:
+
+compatible:
+   "u-boot,bootdev-eth" - Ethernet bootdev
+   "u-boot,bootdev-mmc" - MMC bootdev
+   "u-boot,bootdev-usb" - USB bootdev
+
+
+Example:
+
+	mmc1 {
+		compatible = "sandbox,mmc";
+
+		mmc-bootdev {
+			compatible = "u-boot,bootdev-eth";
+		};
+	};
diff --git a/doc/device-tree-bindings/bootmeth.txt b/doc/device-tree-bindings/bootmeth.txt
new file mode 100644
index 00000000000..cba2dbe871c
--- /dev/null
+++ b/doc/device-tree-bindings/bootmeth.txt
@@ -0,0 +1,31 @@
+U-Boot standard boot methods (bootmeth)
+======================================
+
+This provides methods (called bootmeths) for locating bootflows on a boot
+device (bootdev). These are normally created as children of the bootstd device.
+
+Required properties:
+
+compatible:
+   "u-boot,distro-syslinux" - distro boot from a block device
+   "u-boot,distro-pxe" - distro boot from a network device
+   "u-boot,distro-efi" - EFI boot from a .efi file
+   "u-boot,efi-bootmgr" - EFI boot using boot manager (bootmgr)
+
+
+Example:
+
+	bootstd {
+		compatible = "u-boot,boot-std";
+
+		filename-prefixes = "/", "/boot/";
+		bootdev-order = "mmc2", "mmc1";
+
+		syslinux {
+			compatible = "u-boot,distro-syslinux";
+		};
+
+		efi {
+			compatible = "u-boot,distro-efi";
+		};
+	};
diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt
index f048b9dd327..8706c5f4993 100644
--- a/doc/device-tree-bindings/bootstd.txt
+++ b/doc/device-tree-bindings/bootstd.txt
@@ -25,4 +25,12 @@ Example:
 
 		filename-prefixes = "/", "/boot/";
 		bootdev-order = "mmc2", "mmc1";
+
+		syslinux {
+			compatible = "u-boot,distro-syslinux";
+		};
+
+		efi {
+			compatible = "u-boot,distro-efi";
+		};
 	};
diff --git a/doc/usage/bootdev.rst b/doc/usage/bootdev.rst
new file mode 100644
index 00000000000..ca5671e6f74
--- /dev/null
+++ b/doc/usage/bootdev.rst
@@ -0,0 +1,135 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+bootdev command
+===============
+
+Synopis
+-------
+
+::
+
+    bootdev list [-p]      - list all available bootdevs (-p to probe)\n"
+    bootdev select <bm>    - select a bootdev by name\n"
+    bootdev info [-p]      - show information about a bootdev";
+
+Description
+-----------
+
+The `bootdev` command is used to manage bootdevs. It can list available
+bootdevs, select one and obtain information about it.
+
+See :doc:`../develop/bootstd` for more information about bootdevs in general.
+
+
+bootdev list
+~~~~~~~~~~~~
+
+This lists available bootdevs
+
+Scanning with `-p` causes the bootdevs to be probed. This happens automatically
+when they are used.
+
+The list looks something like this:
+
+===  ======  ======  ========  =========================
+Seq  Probed  Status  Uclass    Name
+===  ======  ======  ========  =========================
+  0   [ + ]      OK  mmc       mmc@7e202000.bootdev
+  1   [   ]      OK  mmc       sdhci@7e300000.bootdev
+  2   [   ]      OK  ethernet  smsc95xx_eth.bootdev
+===  ======  ======  ========  =========================
+
+
+The fields are as follows:
+
+Seq:
+    Sequence number in the scan, used to reference the bootflow later
+
+Probed:
+    Shows a plus (+) if the device is probed, empty if not.
+
+Status:
+    Shows the status of the device. Typically this is `OK` meaning that there is
+    no error. If you use -p and an error occurs when probing, then this shows
+    the error number. You can look up Linux error codes to find the meaning of
+    the number.
+
+Uclass:
+    Name of the media device's Uclass. This indicates the type of the parent
+    device (e.g. MMC, Ethernet).
+
+Name:
+    Name of the bootdev. This is generated from the media device appended
+    with `.bootdev`
+
+
+bootdev select
+~~~~~~~~~~~~~~~~~
+
+Use this to select a particular bootdev. You can select it by the sequence
+number or name, as shown in `bootdev list`.
+
+Once a bootdev is selected, you can use `bootdev info` to look at it or
+`bootflow scan` to scan it.
+
+If no bootdev name or number is provided, then any existing bootdev is
+unselected.
+
+
+bootdev info
+~~~~~~~~~~~~~~~
+
+This shows information on the current bootdev, with the format looking like
+this:
+
+=========  =======================
+Name       mmc@7e202000.bootdev
+Sequence   0
+Status     Probed
+Uclass     mmc
+Bootflows  1 (1 valid)
+=========  =======================
+
+Most of the information is the same as `bootdev list` above. The new fields
+are:
+
+Device
+    Name of the bootdev
+
+Status
+    Shows `Probed` if the device is probed, `OK` if not. If `-p` is used and the
+    device fails to probe, an error code is shown.
+
+Bootflows
+    Indicates the number of bootflows attached to the bootdev. This is 0
+    unless you have used 'bootflow scan' on the bootflow, or on all bootflows.
+
+
+Example
+-------
+
+This example shows listing available bootdev and getting information about
+one of them::
+
+   U-Boot> bootdev list
+   Seq  Probed  Status  Uclass    Name
+   ---  ------  ------  --------  ------------------
+     0   [ + ]      OK  mmc       mmc@7e202000.bootdev
+     1   [   ]      OK  mmc       sdhci@7e300000.bootdev
+     2   [   ]      OK  ethernet  smsc95xx_eth.bootdev
+   ---  ------  ------  --------  ------------------
+   (3 devices)
+   U-Boot> bootdev sel 0
+   U-Boot> bootflow scan
+   U-Boot> bootdev info
+   Name:      mmc@7e202000.bootdev
+   Sequence:  0
+   Status:    Probed
+   Uclass:    mmc
+   Bootflows: 1 (1 valid)
+
+
+Return value
+------------
+
+The return value $? is always 0 (true).
diff --git a/doc/usage/bootflow.rst b/doc/usage/bootflow.rst
new file mode 100644
index 00000000000..347cc181bc5
--- /dev/null
+++ b/doc/usage/bootflow.rst
@@ -0,0 +1,427 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+bootflow command
+================
+
+Synopis
+-------
+
+::
+
+    bootflow scan [-abel] [bootdev]
+    bootflow list [-e]
+    bootflow select [<num|name>]
+    bootflow info [-d]
+    bootflow boot
+
+
+Description
+-----------
+
+The `bootflow` command is used to manage bootflows. It can scan bootdevs to
+locate bootflows, list them and boot them.
+
+See :doc:`../develop/bootstd` for more information.
+
+
+bootflow scan
+~~~~~~~~~~~~~
+
+Scans for available bootflows, optionally booting the first valid one it finds.
+This operates in two modes:
+
+- If no bootdev is selected (see `bootdev select`) it scans bootflows one
+  by one, extracting all the bootdevs from each
+- If a bootdev is selected, it just scans that one bootflow
+
+Flags are:
+
+-a
+    Collect all bootflows, even those that cannot be loaded. Normally if a file
+    is not where it is expected, then the bootflow fails and so is dropped
+    during the scan. With this option you can see why each bootflow would be
+    dropped.
+
+-b
+    Boot each valid bootflow as it is scanned. Typically only the first bootflow
+    matters, since by then the system boots in the OS and U-Boot is no-longer
+    running. `bootflow scan -b` is a quick way to boot the first available OS.
+    A valid bootflow is one that made it all the way to the `loaded` state.
+
+-e
+    Used with -l to also show errors for each bootflow. The shows detailed error
+    information for each bootflow that failed to make it to the `loaded` state.
+
+-l
+    List bootflows while scanning. This is helpful when you want to see what
+    is happening during scanning. Use it with the `-b` flag to see which
+    bootdev and bootflows are being tried.
+
+The optional argument specifies a particular bootdev to scan. This can either be
+the name of a bootdev or its sequence number (both shown with `bootdev list`).
+Alternatively a convenience label can be used, like `mmc0`, which is the type of
+device and an optional sequence number. Specifically, the label is the uclass of
+the bootdev's parent followed by the sequence number of that parent. Sequence
+numbers are typically set by aliases, so if you have 'mmc0' in your devicetree
+alias section, then `mmc0` refers to the bootdev attached to that device.
+
+
+bootflow list
+~~~~~~~~~~~~~
+
+Lists the previously scanned bootflows. You must use `bootflow scan` before this
+to see anything.
+
+If you scanned with -a and have bootflows with errors, -e can be used to show
+those errors.
+
+The list looks something like this:
+
+===  ======  ======  ========  ====  ===============================   ================
+Seq  Method  State   Uclass    Part  Name                              Filename
+===  ======  ======  ========  ====  ===============================   ================
+  0  distro  ready   mmc          2  mmc\@7e202000.bootdev.part_2      /boot/extlinux/extlinux.conf
+  1  pxe     ready   ethernet     0  smsc95xx_eth.bootdev.0            rpi.pxe/extlinux/extlinux.conf
+===  ======  ======  ========  ====  ===============================   ================
+
+The fields are as follows:
+
+Seq:
+    Sequence number in the scan, used to reference the bootflow later
+
+Method:
+    The boot method (bootmeth) used to find the bootflow. Several methods are
+    included in U-Boot.
+
+State:
+    Current state of the bootflow, indicating how far the bootdev got in
+    obtaining a valid one. See :ref:`BootflowStates` for a list of states.
+
+Uclass:
+    Name of the media device's Uclass. This indicates the type of the parent
+    device (e.g. MMC, Ethernet).
+
+Part:
+    Partition number being accesseed, numbered from 1. Normally a device will
+    have a partition table with a small number of partitions. For devices
+    without partition tables (e.g. network) this field is 0.
+
+Name:
+    Name of the bootflow. This is generated from the bootdev appended with
+    the partition information
+
+Filename:
+    Name of the bootflow file. This indicates where the file is on the
+    filesystem or network device.
+
+
+bootflow select
+~~~~~~~~~~~~~~~
+
+Use this to select a particular bootflow. You can select it by the sequence
+number or name, as shown in `bootflow list`.
+
+Once a bootflow is selected, you can use `bootflow info` and `bootflow boot`.
+
+If no bootflow name or number is provided, then any existing bootflow is
+unselected.
+
+
+bootflow info
+~~~~~~~~~~~~~
+
+This shows information on the current bootflow, with the format looking like
+this:
+
+=========  ===============================
+Name       mmc\@7e202000.bootdev.part_2
+Device     mmc\@7e202000.bootdev
+Block dev  mmc\@7e202000.blk
+Type       distro
+Method:    syslinux
+State      ready
+Partition  2
+Subdir     (none)
+Filename   /extlinux/extlinux.conf
+Buffer     3db7ad48
+Size       232 (562 bytes)
+Error      0
+=========  ===============================
+
+Most of the information is the same as `bootflow list` above. The new fields
+are:
+
+Device
+    Name of the bootdev
+
+Block dev
+    Name of the block device, if any. Network devices don't have a block device.
+
+Subdir
+    Subdirectory used for retrieving files. For network bootdevs this is the
+    directory of the 'bootfile' parameter passed from DHCP. All file retrievals
+    when booting are relative to this.
+
+Buffer
+    Buffer containing the bootflow file. You can use the :doc:`md` to look at
+    it, or dump it with `bootflow info -d`.
+
+Size
+    Size of the bootflow file
+
+Error
+    Error number returned from scanning for the bootflow. This is 0 if the
+    bootflow is in the 'loaded' state, or a negative error value on error. You
+    can look up Linux error codes to find the meaning of the number.
+
+Use the `-d` flag to dump out the contents of the bootfile file.
+
+
+bootflow boot
+~~~~~~~~~~~~~
+
+This boots the current bootflow.
+
+
+Example
+-------
+
+Here is an example of scanning for bootflows, then listing them::
+
+    U-Boot> bootflow scan -l
+    Scanning for bootflows in all bootdevs
+    Seq  Type         State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    Scanning bootdev 'mmc@7e202000.bootdev':
+      0  distro       ready   mmc          2  mmc@7e202000.bootdev.p    /extlinux/extlinux.conf
+    Scanning bootdev 'sdhci@7e300000.bootdev':
+    Card did not respond to voltage select! : -110
+    Scanning bootdev 'smsc95xx_eth.bootdev':
+    Waiting for Ethernet connection... done.
+    BOOTP broadcast 1
+    DHCP client bound to address 192.168.4.30 (4 ms)
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe/'.
+    Load address: 0x200000
+    Loading: *
+    TFTP error: 'Is a directory' (0)
+    Starting again
+
+    missing environment variable: pxeuuid
+    Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1
+    Waiting for Ethernet connection... done.
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'.
+    Load address: 0x2500000
+    Loading: ##################################################  566 Bytes
+    	 45.9 KiB/s
+    done
+    Bytes transferred = 566 (236 hex)
+      1  distro       ready   ethernet     0  smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf
+    No more bootdevs
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    (2 bootflows, 2 valid)
+    U-Boot> bootflow l
+    Showing all bootflows
+    Seq  Type         State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+      0  distro       ready   mmc          2  mmc@7e202000.bootdev.p    /extlinux/extlinux.conf
+      1  pxe          ready   ethernet     0  smsc95xx_eth.bootdev.0     rpi.pxe/extlinux/extlinux.conf
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    (2 bootflows, 2 valid)
+
+
+The second one is then selected by name (we could instead use `bootflow sel 0`),
+displayed and booted::
+
+    U-Boot> bootflow info
+    No bootflow selected
+    U-Boot> bootflow sel mmc@7e202000.bootdev.part_2
+    U-Boot> bootflow info
+    Name:      mmc@7e202000.bootdev.part_2
+    Device:    mmc@7e202000.bootdev
+    Block dev: mmc@7e202000.blk
+    Sequence:  1
+    Method:    distro
+    State:     ready
+    Partition: 2
+    Subdir:    (none)
+    Filename:  extlinux/extlinux.conf
+    Buffer:    3db7ae88
+    Size:      232 (562 bytes)
+    Error:     0
+    U-Boot> bootflow boot
+    ** Booting bootflow 'smsc95xx_eth.bootdev.0'
+    Ignoring unknown command: ui
+    Ignoring malformed menu command:  autoboot
+    Ignoring malformed menu command:  hidden
+    Ignoring unknown command: totaltimeout
+    1:	Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+    Retrieving file: rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img
+    get 2700000 rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img
+    Waiting for Ethernet connection... done.
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img'.
+    Load address: 0x2700000
+    Loading: ###################################T ###############  57.7 MiB
+    	 1.9 MiB/s
+    done
+    Bytes transferred = 60498594 (39b22a2 hex)
+    Retrieving file: rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl
+    get 80000 rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl
+    Waiting for Ethernet connection... done.
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl'.
+    Load address: 0x80000
+    Loading: ##################################################  7.2 MiB
+    	 2.3 MiB/s
+    done
+    Bytes transferred = 7508480 (729200 hex)
+    append: ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
+    Retrieving file: rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb
+    get 2600000 rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb
+    Waiting for Ethernet connection... done.
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb'.
+    Load address: 0x2600000
+    Loading: ##################################################  13.8 KiB
+    	 764.6 KiB/s
+    done
+    Bytes transferred = 14102 (3716 hex)
+    Kernel image @ 0x080000 [ 0x000000 - 0x729200 ]
+    ## Flattened Device Tree blob at 02600000
+       Booting using the fdt blob at 0x2600000
+       Using Device Tree in place at 02600000, end 02606715
+
+    Starting kernel ...
+
+    [  OK  ] Started Show Plymouth Boot Screen.
+    [  OK  ] Started Forward Password R…s to Plymouth Directory Watch.
+    [  OK  ] Reached target Local Encrypted Volumes.
+    [  OK  ] Reached target Paths.
+    ....
+
+
+Here we scan for bootflows and boot the first one found::
+
+    U-Boot> bootflow scan -bl
+    Scanning for bootflows in all bootdevs
+    Seq  Method       State   Uclass    Part  Name                    Filename
+    ---  -----------  ------  --------  ----  ----------------------  ----------------
+    Scanning bootdev 'mmc@7e202000.bootdev':
+      0  distro       ready   mmc          2  mmc@7e202000.bootdev.p  /extlinux/extlinux.conf
+    ** Booting bootflow 'mmc@7e202000.bootdev.part_2'
+    Ignoring unknown command: ui
+    Ignoring malformed menu command:  autoboot
+    Ignoring malformed menu command:  hidden
+    Ignoring unknown command: totaltimeout
+    1:	Fedora-KDE-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+    Retrieving file: /initramfs-5.3.7-301.fc31.armv7hl.img
+    getfile 2700000 /initramfs-5.3.7-301.fc31.armv7hl.img
+    Retrieving file: /vmlinuz-5.3.7-301.fc31.armv7hl
+    getfile 80000 /vmlinuz-5.3.7-301.fc31.armv7hl
+    append: ro root=UUID=b8781f09-e2dd-4cb8-979b-7df5eeaaabea rhgb LANG=en_US.UTF-8 cma=192MB console=tty0 console=ttyS1,115200
+    Retrieving file: /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb
+    getfile 2600000 /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb
+    Kernel image @ 0x080000 [ 0x000000 - 0x729200 ]
+    ## Flattened Device Tree blob at 02600000
+       Booting using the fdt blob at 0x2600000
+       Using Device Tree in place at 02600000, end 02606715
+
+    Starting kernel ...
+
+    [    0.000000] Booting Linux on physical CPU 0x0
+
+
+Here is am example using the -e flag to see all errors::
+
+    U-Boot> bootflow scan -a
+    Card did not respond to voltage select! : -110
+    Waiting for Ethernet connection... done.
+    BOOTP broadcast 1
+    DHCP client bound to address 192.168.4.30 (4 ms)
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe/'.
+    Load address: 0x200000
+    Loading: *
+    TFTP error: 'Is a directory' (0)
+    Starting again
+
+    missing environment variable: pxeuuid
+    Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1
+    Waiting for Ethernet connection... done.
+    Using smsc95xx_eth device
+    TFTP from server 192.168.4.1; our IP address is 192.168.4.30
+    Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'.
+    Load address: 0x2500000
+    Loading: ##################################################  566 Bytes
+    	 49.8 KiB/s
+    done
+    Bytes transferred = 566 (236 hex)
+    U-Boot> bootflow l -e
+    Showing all bootflows
+    Seq  Type         State   Uclass    Part  Name                   Filename
+    ---  -----------  ------  --------  ----  ---------------------  ----------------
+      0  distro       fs      mmc          1  mmc@7e202000.bootdev.p /extlinux/extlinux.conf
+         ** File not found, err=-2
+      1  distro       ready   mmc          2  mmc@7e202000.bootdev.p /extlinux/extlinux.conf
+      2  distro       fs      mmc          3  mmc@7e202000.bootdev.p /extlinux/extlinux.conf
+         ** File not found, err=-1
+      3  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      4  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      5  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      6  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      7  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      8  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      9  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      a  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      b  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      c  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      d  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      e  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+      f  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+     10  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+     11  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+     12  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+     13  distro       media   mmc          0  mmc@7e202000.bootdev.p <NULL>
+         ** No partition found, err=-2
+     14  distro       ready   ethernet     0  smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf
+    ---  -----------  ------  --------  ----  ---------------------  ----------------
+    (21 bootflows, 2 valid)
+    U-Boot>
+
+
+Return value
+------------
+
+On success `bootflow boot` normally boots into the Operating System and does not
+return to U-Boot. If something about the U-Boot processing fails, then the
+return value $? is 1. If the boot succeeds but for some reason the Operating
+System returns, then $? is 0, indicating success.
+
+For other subcommands, the return value $? is always 0 (true).
+
+
+.. BootflowStates_:
diff --git a/doc/usage/bootmeth.rst b/doc/usage/bootmeth.rst
new file mode 100644
index 00000000000..2e6cc2a77e6
--- /dev/null
+++ b/doc/usage/bootmeth.rst
@@ -0,0 +1,106 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+bootmeth command
+================
+
+Synopis
+-------
+
+::
+
+    bootmeth list [-a]       - list selected bootmeths (-a for all)
+    bootmeth order [<bm>...] - select the order of bootmeths\n"
+
+
+Description
+-----------
+
+The `bootmeth` command is used to manage bootmeths. It can list them and change
+the order in which they are used.
+
+See :doc:`../develop/bootstd` for more information.
+
+
+bootmeth order
+~~~~~~~~~~~~~~
+
+Selects which bootmeths to use and the order in which they are invoked. When
+scanning bootdevs, each bootmeth is tried in turn to see if it can find a valid
+bootflow. You can use this command to adjust the order or even to omit some
+boomeths.
+
+The arguments are a list of bootmeths to use, by name.
+
+
+bootmeth list
+~~~~~~~~~~~~~
+
+This lists the selected bootmeths, or all of them, if the `-a` flag is used.
+The format looks like this:
+
+=====  ===  ==================  =================================
+Order  Seq  Name                Description
+=====  ===  ==================  =================================
+    0    0  distro              Syslinux boot from a block device
+    1    1  efi                 EFI boot from a .efi file
+    2    2  pxe                 PXE boot from a network device
+    3    3  sandbox             Sandbox boot for testing
+    4    4  efi_mgr             EFI bootmgr flow
+=====  ===  ==================  =================================
+
+The fields are as follows:
+
+Order:
+    The order in which these bootmeths are invoked for each bootdev. If this
+    shows as a hyphen, then the bootmeth is not in the current ordering.
+
+Seq:
+    The sequence number of the bootmeth, i.e. the normal ordering if none is set
+
+Name:
+    Name of the bootmeth
+
+Description:
+    A friendly description for the bootmeth
+
+
+Example
+-------
+
+This shows listing bootmeths. All are present and in the normal order::
+
+    => bootmeth list
+    Order  Seq  Name                Description
+    -----  ---  ------------------  ------------------
+        0    0  distro              Syslinux boot from a block device
+        1    1  efi                 EFI boot from a .efi file
+        2    2  pxe                 PXE boot from a network device
+        3    3  sandbox             Sandbox boot for testing
+        4    4  efi_mgr             EFI bootmgr flow
+    -----  ---  ------------------  ------------------
+    (5 bootmeths)
+
+Now the order is changed, to include only two of them::
+
+    => bootmeth order sandbox distro
+    => bootmeth list
+    Order  Seq  Name                Description
+    -----  ---  ------------------  ------------------
+        0    3  sandbox             Sandbox boot for testing
+        1    0  distro              Syslinux boot from a block device
+    -----  ---  ------------------  ------------------
+    (2 bootmeths)
+
+The -a flag shows all bootmeths so you can clearly see which ones are used and
+which are not::
+
+    => bootmeth list -a
+    Order  Seq  Name                Description
+    -----  ---  ------------------  ------------------
+        1    0  distro              Syslinux boot from a block device
+        -    1  efi                 EFI boot from a .efi file
+        -    2  pxe                 PXE boot from a network device
+        0    3  sandbox             Sandbox boot for testing
+        -    4  efi_mgr             EFI bootmgr flow
+    -----  ---  ------------------  ------------------
+    (5 bootmeths)
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 356f2a56181..6e96504142c 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -20,9 +20,12 @@ Shell commands
    addrmap
    askenv
    base
+   bootdev
    bootefi
+   bootflow
    booti
    bootmenu
+   bootmeth
    button
    x86/cbsysinfo
    conitrace
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 41/41] RFC: Switch rpi over to use bootstd
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (39 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 40/41] bootstd: doc: Add documentation Simon Glass
@ 2021-10-23 23:26   ` Simon Glass
  2021-10-28 15:13     ` Tom Rini
  2021-10-28 16:43     ` Tom Rini
  2021-10-23 23:27   ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (16 subsequent siblings)
  57 siblings, 2 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:26 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Switch this over, for testing purposes.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 boot/Kconfig          |  3 ++-
 include/configs/rpi.h | 41 ++++-------------------------------------
 2 files changed, 6 insertions(+), 38 deletions(-)

diff --git a/boot/Kconfig b/boot/Kconfig
index 2862bd10710..ce4686d8d15 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1061,7 +1061,8 @@ config USE_BOOTCOMMAND
 config BOOTCOMMAND
 	string "bootcmd value"
 	depends on USE_BOOTCOMMAND && !USE_DEFAULT_ENV_FILE
-	default "run distro_bootcmd" if DISTRO_DEFAULTS
+	default "bootflow scan -lb" if BOOTSTD
+	default "run distro_bootcmd" if !BOOTSTD && DISTRO_DEFAULTS
 	help
 	  This is the string of commands that will be used as bootcmd and if
 	  AUTOBOOT is set, automatically run.
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index 55768a46da2..0c236579b55 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -132,48 +132,15 @@
 	"scriptaddr=0x02400000\0" \
 	"pxefile_addr_r=0x02500000\0" \
 	"fdt_addr_r=0x02600000\0" \
-	"ramdisk_addr_r=0x02700000\0"
-
-#if CONFIG_IS_ENABLED(CMD_MMC)
-	#define BOOT_TARGET_MMC(func) \
-		func(MMC, mmc, 0) \
-		func(MMC, mmc, 1)
-#else
-	#define BOOT_TARGET_MMC(func)
-#endif
-
-#if CONFIG_IS_ENABLED(CMD_USB)
-	#define BOOT_TARGET_USB(func) func(USB, usb, 0)
-#else
-	#define BOOT_TARGET_USB(func)
-#endif
-
-#if CONFIG_IS_ENABLED(CMD_PXE)
-	#define BOOT_TARGET_PXE(func) func(PXE, pxe, na)
-#else
-	#define BOOT_TARGET_PXE(func)
-#endif
-
-#if CONFIG_IS_ENABLED(CMD_DHCP)
-	#define BOOT_TARGET_DHCP(func) func(DHCP, dhcp, na)
-#else
-	#define BOOT_TARGET_DHCP(func)
-#endif
-
-#define BOOT_TARGET_DEVICES(func) \
-	BOOT_TARGET_MMC(func) \
-	BOOT_TARGET_USB(func) \
-	BOOT_TARGET_PXE(func) \
-	BOOT_TARGET_DHCP(func)
-
-#include <config_distro_bootcmd.h>
+	"ramdisk_addr_r=0x02700000\0" \
+	"ethaddr=b8:27:eb:a6:61:e1\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \
+	"boot_targets=mmc0 mmc1 usb0 pxe dhcp\0" \
 	ENV_DEVICE_SETTINGS \
 	ENV_DFU_SETTINGS \
-	ENV_MEM_LAYOUT_SETTINGS \
-	BOOTENV
+	ENV_MEM_LAYOUT_SETTINGS
 
 
 #endif
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (40 preceding siblings ...)
  2021-10-23 23:26   ` [PATCH v2 41/41] RFC: Switch rpi over to use bootstd Simon Glass
@ 2021-10-23 23:27   ` Simon Glass
  2021-10-27 11:38   ` Heinrich Schuchardt
                     ` (15 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-23 23:27 UTC (permalink / raw)
  To: U-Boot Mailing List, u-boot-board-maintainers, u-boot-custodians
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren

+u-boot-board-maintainers@lists.denx.de
+u-boot-custodians@lists.denx.de

On Sat, 23 Oct 2021 at 17:26, Simon Glass <sjg@chromium.org> wrote:
>
>
> The bootflow feature provide a built-in way for U-Boot to automatically
> boot an Operating System without custom scripting and other customisation.
> This is called 'standard boot' since it provides a standard way for
> U-Boot to boot a distro, without scripting.
>
> It introduces the following concepts:
>
>    - bootdev - a device which can hold a distro
>    - bootmeth - a method to scan a bootdev to find bootflows (owned by
>                 U-Boot)
>    - bootflow - a description of how to boot (owned by the distro)
>
> This series provides an implementation of these, enabled to scan for
> bootflows from MMC, USB and Ethernet. It supports the existing distro
> boot as well as the EFI loader flow (bootefi/bootmgr). It works
> similiarly to the existing script-based approach, but is native to
> U-Boot.
>
> With this we can boot on a Raspberry Pi 3 with just one command:
>
>    bootflow scan -lb
>
> which means to scan, listing (-l) each bootflow and trying to boot each
> one (-b). The final patch shows this.
>
> With a standard way to identify boot devices, booting become easier. It
> also should be possible to support U-Boot scripts, for backwards
> compatibility only.
>
> This series relies on the PXE clean-up series, posted here:
>
>    https://patchwork.ozlabs.org/project/uboot/list/?series=267078
>
> For documentation, see the 'doc' patch.
>
> For version 2, a new naming scheme is used as above:
>
>    - bootdev is used instead of bootdevice, because 'device' is overused,
>        is everywhere in U-Boot, can be confused with udevice
>    - bootmeth - because 'method' is too vanilla, appears 1300 times in
>        U-Boot
>
> Also in version 2, drivers are introduced for the boot methods, to make
> it more extensible. Booting a custom OS is simply a matter of creating a
> bootmeth for it and implementing the read_file() and boot() methods.
>
> The design is described in these two documents:
>
> https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
>
> https://drive.google.com/file/d/1kTrflO9vvGlKp-ZH_jlgb9TY3WYG6FF9/view?usp=sharing
>
> The series is available at u-boot-dm/bme-working
>
> Sample log on rpi_3_32b:
>
> U-Boot 2021.10-rc2-00043-gccd453aa918-dirty (Aug 28 2021 - 13:58:46 -0600)
>
> DRAM:  992 MiB
> RPI 3 Model B (0xa22082)
> MMC:   mmc@7e202000: 0, sdhci@7e300000: 1
> Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:    serial
> Out:   vidconsole
> Err:   vidconsole
> Net:   No ethernet found.
> starting USB...
> Bus usb@7e980000: USB DWC2
> scanning bus usb@7e980000 for devices... usb_kbd usb_kbd: Timeout poll on interrupt endpoint
> Failed to get keyboard state from device 0c40:8000
> 4 USB Device(s) found
>        scanning usb for storage devices... 0 Storage Device(s) found
> Hit any key to stop autoboot:  0
> Scanning for bootflows in all bootmethods
> Seq  Type         State   Uclass    Part  Name                      Filename
> ---  -----------  ------  --------  ----  ------------------------  ----------------
> Scanning bootmethod 'mmc@7e202000.bootmethod':
>   0  efi-loader   loaded  mmc          1  mmc@7e202000.bootmethod.p efi/boot/bootarm.efi
> ** Booting bootflow 'mmc@7e202000.bootmethod.part_1'
> Scanning disk mmc@7e202000.blk...
> ** Unrecognized filesystem type **
> Card did not respond to voltage select! : -110
> Scanning disk sdhci@7e300000.blk...
> Disk sdhci@7e300000.blk not ready
> Found 4 disks
> No EFI system partition
> Booting /efi\boot
> Waiting for Ethernet connection... done.
>
>       Fedora (5.11.12-300.fc34.armv7hl) 34 (Workstation Edition)
>       UEFI Firmware Settings
>
>       Use the ▲ and ▼ keys to change the selection.
>       Press 'e' to edit the selected item, or 'c' for a command prompt. Press Escape to return to the previous menu.
>    The selected entry will be started automatically in 0s.
>
> Changes in v2:
> - Free the memory buffer, to avoid running out of memory
> - Unmap the file
> - Reorder struct sandbox_mmc_priv
>
> Simon Glass (41):
>   lib: Add a way to find the postiion of a trailing number
>   Makefile: Allow LTO to be disabled for a build
>   test/py: Allow passing input to a program
>   sandbox: Support unmapping a file
>   sandbox: mmc: Support a backing file
>   mmc: Allow for children other than the block device
>   mbr: Correct verification check
>   disk: part_dos: Fix a NULL pointer error
>   common: Allow a smaller console-recording pre-reloc
>   dm: core: Add tests for stringlist functions
>   dm: core: Fix handling of uclass pre_unbind method
>   dm: core: Fix up string-function documentation
>   dm: core: Add a way to obtain a string list
>   dm: core: Allow finding children / uclasses by partial name
>   dm: core: Add a way to count the devices in a uclass
>   sandbox: Enable HEXDUMP for sandbox_flattree
>   test/py: Relax the naming rules for unit tests
>   test/py: Raise a ValueError if a command fails
>   bootstd: Add the concept of a bootflow
>   bootstd: Add the bootstd uclass and core implementation
>   bootstd: Add the bootdev uclass
>   bootstd: Add the bootmeth uclass and helpers
>   bootstd: Add support for bootflows
>   bootstd: Add a bootdev command
>   bootstd: Add a bootflow ommand
>   bootstd: Add a bootmeth command
>   bootstd: Add an implementation of distro boot
>   bootstd: mmc: Add a bootdev driver
>   bootstd: ethernet: Add a bootdev driver
>   bootstd: Add an implementation of distro PXE boot
>   bootstd: Add an implementation of EFI boot
>   bootstd: Add a system bootdev for strange boot methods
>   bootstd: Add an implementation of EFI bootmgr
>   bootstd: Add a sandbox bootmeth driver
>   bootstd: usb: Add a bootdev driver
>   test: fastboot: Avoid using mmc1
>   test: dm: Restart USB before assuming it is stopped
>   bootstd: Add tests for bootstd including all uclasses
>   bootstd: Add setup for the bootflow tests
>   bootstd: doc: Add documentation
>   RFC: Switch rpi over to use bootstd
>
>  MAINTAINERS                                  |  21 +
>  Makefile                                     |  18 +-
>  arch/arm/config.mk                           |   4 +-
>  arch/arm/include/asm/global_data.h           |   2 +-
>  arch/sandbox/cpu/os.c                        |  10 +
>  arch/sandbox/dts/test.dts                    |  19 +
>  boot/Kconfig                                 |  77 ++-
>  boot/Makefile                                |  14 +
>  boot/bootdev-uclass.c                        | 439 ++++++++++++++
>  boot/bootflow.c                              | 576 ++++++++++++++++++
>  boot/bootmeth-uclass.c                       |  59 ++
>  boot/bootmeth_distro.c                       | 217 +++++++
>  boot/bootmeth_efi.c                          | 263 ++++++++
>  boot/bootmeth_efi_mgr.c                      |  84 +++
>  boot/bootmeth_pxe.c                          | 183 ++++++
>  boot/bootmeth_sandbox.c                      |  67 +++
>  boot/bootstd-uclass.c                        | 176 ++++++
>  boot/system_bootdev.c                        |  64 ++
>  cmd/Kconfig                                  |  15 +
>  cmd/Makefile                                 |   1 +
>  cmd/bootdev.c                                | 120 ++++
>  cmd/bootflow.c                               | 386 ++++++++++++
>  cmd/bootmeth.c                               | 158 +++++
>  cmd/mbr.c                                    |   8 +-
>  common/Kconfig                               |  10 +
>  common/console.c                             |   4 +-
>  common/usb_storage.c                         |  12 +
>  configs/amcore_defconfig                     |   1 +
>  configs/rcar3_salvator-x_defconfig           |   1 +
>  configs/sandbox_defconfig                    |   3 +-
>  configs/sandbox_flattree_defconfig           |   4 +-
>  configs/tbs2910_defconfig                    |   1 +
>  disk/part_dos.c                              |  10 +-
>  doc/build/gcc.rst                            |  17 +
>  doc/develop/bootstd.rst                      | 600 +++++++++++++++++++
>  doc/develop/distro.rst                       |   3 +
>  doc/develop/index.rst                        |   1 +
>  doc/device-tree-bindings/bootdev.txt         |  26 +
>  doc/device-tree-bindings/bootmeth.txt        |  31 +
>  doc/device-tree-bindings/bootstd.txt         |  36 ++
>  doc/device-tree-bindings/mmc/sandbox,mmc.txt |  18 +
>  doc/usage/bootdev.rst                        | 135 +++++
>  doc/usage/bootflow.rst                       | 427 +++++++++++++
>  doc/usage/bootmeth.rst                       | 106 ++++
>  doc/usage/index.rst                          |   3 +
>  drivers/core/device-remove.c                 |   9 +-
>  drivers/core/device.c                        |  13 +-
>  drivers/core/of_access.c                     |   3 +-
>  drivers/core/ofnode.c                        |  26 +
>  drivers/core/read.c                          |   6 +
>  drivers/core/uclass.c                        |  29 +-
>  drivers/mmc/Makefile                         |   5 +
>  drivers/mmc/mmc-uclass.c                     |  27 +-
>  drivers/mmc/mmc_bootdev.c                    |  62 ++
>  drivers/mmc/sandbox_mmc.c                    |  60 +-
>  drivers/usb/host/Makefile                    |   4 +
>  drivers/usb/host/usb_bootdev.c               |  61 ++
>  include/bootdev.h                            | 258 ++++++++
>  include/bootflow.h                           | 304 ++++++++++
>  include/bootmeth.h                           | 156 +++++
>  include/bootstd.h                            |  80 +++
>  include/configs/rpi.h                        |  41 +-
>  include/distro.h                             |  24 +
>  include/dm/device.h                          |  12 +
>  include/dm/ofnode.h                          |  24 +-
>  include/dm/read.h                            |  28 +
>  include/dm/uclass-id.h                       |   3 +
>  include/dm/uclass-internal.h                 |  14 +-
>  include/dm/uclass.h                          |  17 +
>  include/mmc.h                                |  12 +-
>  include/os.h                                 |   9 +
>  include/test/suites.h                        |   2 +
>  include/vsprintf.h                           |  18 +
>  lib/strto.c                                  |  14 +-
>  net/Kconfig                                  |   9 +
>  net/Makefile                                 |   1 +
>  net/eth-uclass.c                             |   8 +
>  net/eth_bootdev.c                            | 101 ++++
>  test/Makefile                                |   1 +
>  test/boot/Makefile                           |   5 +
>  test/boot/bootdev.c                          | 200 +++++++
>  test/boot/bootflow.c                         | 398 ++++++++++++
>  test/boot/bootmeth.c                         |  90 +++
>  test/boot/bootstd_common.c                   |  35 ++
>  test/boot/bootstd_common.h                   |  27 +
>  test/cmd_ut.c                                |   7 +
>  test/dm/blk.c                                |   6 +
>  test/dm/fastboot.c                           |   4 +-
>  test/dm/ofnode.c                             |  96 +++
>  test/py/conftest.py                          |   2 +-
>  test/py/multiplexed_log.py                   |  10 +-
>  test/py/tests/bootstd/mmc1.img.xz            | Bin 0 -> 4448 bytes
>  test/py/tests/test_ut.py                     | 103 ++++
>  test/py/u_boot_utils.py                      |   5 +-
>  94 files changed, 6765 insertions(+), 94 deletions(-)
>  create mode 100644 boot/bootdev-uclass.c
>  create mode 100644 boot/bootflow.c
>  create mode 100644 boot/bootmeth-uclass.c
>  create mode 100644 boot/bootmeth_distro.c
>  create mode 100644 boot/bootmeth_efi.c
>  create mode 100644 boot/bootmeth_efi_mgr.c
>  create mode 100644 boot/bootmeth_pxe.c
>  create mode 100644 boot/bootmeth_sandbox.c
>  create mode 100644 boot/bootstd-uclass.c
>  create mode 100644 boot/system_bootdev.c
>  create mode 100644 cmd/bootdev.c
>  create mode 100644 cmd/bootflow.c
>  create mode 100644 cmd/bootmeth.c
>  create mode 100644 doc/develop/bootstd.rst
>  create mode 100644 doc/device-tree-bindings/bootdev.txt
>  create mode 100644 doc/device-tree-bindings/bootmeth.txt
>  create mode 100644 doc/device-tree-bindings/bootstd.txt
>  create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt
>  create mode 100644 doc/usage/bootdev.rst
>  create mode 100644 doc/usage/bootflow.rst
>  create mode 100644 doc/usage/bootmeth.rst
>  create mode 100644 drivers/mmc/mmc_bootdev.c
>  create mode 100644 drivers/usb/host/usb_bootdev.c
>  create mode 100644 include/bootdev.h
>  create mode 100644 include/bootflow.h
>  create mode 100644 include/bootmeth.h
>  create mode 100644 include/bootstd.h
>  create mode 100644 include/distro.h
>  create mode 100644 net/eth_bootdev.c
>  create mode 100644 test/boot/Makefile
>  create mode 100644 test/boot/bootdev.c
>  create mode 100644 test/boot/bootflow.c
>  create mode 100644 test/boot/bootmeth.c
>  create mode 100644 test/boot/bootstd_common.c
>  create mode 100644 test/boot/bootstd_common.h
>  create mode 100644 test/py/tests/bootstd/mmc1.img.xz
>
> --
> 2.33.0.1079.g6e70778dc9-goog
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/41] dm: core: Add a way to obtain a string list
  2021-10-23 23:26   ` [PATCH v2 13/41] dm: core: Add a way to obtain a string list Simon Glass
@ 2021-10-26 19:20     ` Ilias Apalodimas
  2021-11-24 22:22       ` Simon Glass
  2021-11-24 22:23       ` Simon Glass
  0 siblings, 2 replies; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-26 19:20 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann

On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
>
> At present we support reading a string list a string at a time. Apart
> from being inefficient, this makes it impossible to separate reading of
> the devicetree into the of_to_plat() method where it belongs, since any
> code which needs access to the string must read it from the devicetree.
>
> Add a function which returns the string property as an array of pointers
> to the strings, which is easily used by clients.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>  drivers/core/ofnode.c | 26 ++++++++++++++++++++++++++
>  drivers/core/read.c   |  6 ++++++
>  include/dm/ofnode.h   | 20 ++++++++++++++++++++
>  include/dm/read.h     | 28 ++++++++++++++++++++++++++++
>  test/dm/ofnode.c      | 20 ++++++++++++++++++++
>  5 files changed, 100 insertions(+)
>
> diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
> index 08705ef8d99..709bea272a6 100644
> --- a/drivers/core/ofnode.c
> +++ b/drivers/core/ofnode.c
> @@ -456,6 +456,32 @@ int ofnode_read_string_count(ofnode node, const char *property)
>         }
>  }
>
> +int ofnode_read_string_list(ofnode node, const char *property,
> +                           const char ***listp)
> +{
> +       const char **prop;
> +       int count;
> +       int i;
> +
> +       *listp = NULL;
> +       count = ofnode_read_string_count(node, property);
> +       if (count < 0)
> +               return count;
> +       if (!count)
> +               return 0;

Those can fold into a single if and always return 'count'.
if (count <= 0)
    return count;

> +
> +       prop = calloc(count + 1, sizeof(char *));
[...]

Regards
/Ilias

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 23/41] bootstd: Add support for bootflows
  2021-10-23 23:26   ` [PATCH v2 23/41] bootstd: Add support for bootflows Simon Glass
@ 2021-10-27  7:37     ` Ilias Apalodimas
  2022-03-12  2:24       ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-27  7:37 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Simon,

> +

[...]

> +/* error codes used to signal running out of things */
> +enum {
> +	BF_NO_MORE_PARTS	= -ESHUTDOWN,
> +	BF_NO_MORE_DEVICES	= -ENODEV,
> +};
> +
> +static const char *const bootflow_state[BOOTFLOWST_COUNT] = {
> +	"base",
> +	"media",
> +	"part",
> +	"fs",
> +	"file",
> +	"ready",

I can understand 'ready' as a boot state.  What are the rest supposed to be
?

> +};
> +
> +const char *bootflow_state_get_name(enum bootflow_state_t state)
> +{
> +	if (state < 0 || state >= BOOTFLOWST_COUNT)
> +		return "?";

s/?/Unknown/ or invalid maybe?

> +
> +	return bootflow_state[state];
> +}
> +
> +int bootflow_first_glob(struct bootflow **bflowp)
> +{
> +	struct bootstd_priv *std;

[...]

Regards
/Ilias

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/41] mbr: Correct verification check
  2021-10-23 23:26   ` [PATCH v2 07/41] mbr: Correct verification check Simon Glass
@ 2021-10-27  7:41     ` Ilias Apalodimas
  2021-11-24 22:22     ` Simon Glass
  1 sibling, 0 replies; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-27  7:41 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Simon,

On Sat, Oct 23, 2021 at 05:26:01PM -0600, Simon Glass wrote:
> At present this command considers the partitions to be identical if the
> start and size are smaller than expected. It should check that they are
> the same. Fix this and tidy up the code style a little.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> (no changes since v1)
> 
>  cmd/mbr.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/cmd/mbr.c b/cmd/mbr.c
> index e7e22980969..c269833eb82 100644
> --- a/cmd/mbr.c
> +++ b/cmd/mbr.c
> @@ -244,12 +244,12 @@ static int do_verify_mbr(struct blk_desc *dev, const char *str)
>  	for (i = 0; i < count; i++) {
>  		struct disk_partition p;
>  
> -		if (part_get_info(dev, i+1, &p))
> +		if (part_get_info(dev, i + 1, &p))
>  			goto fail;
>  
> -		if ((partitions[i].size && p.size < partitions[i].size) ||
> -		    (partitions[i].start && p.start < partitions[i].start) ||
> -		    (p.sys_ind != partitions[i].sys_ind))
> +		if ((partitions[i].size && p.size != partitions[i].size) ||
> +		    (partitions[i].start && p.start != partitions[i].start) ||
> +		    p.sys_ind != partitions[i].sys_ind)
>  			goto fail;
>  	}
>  	ret = 0;
> -- 
> 2.33.0.1079.g6e70778dc9-goog
> 

This seems irrelevant to the series and a general fix. Can you send it as
such?

Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-23 23:26   ` [PATCH v2 31/41] bootstd: Add an implementation of EFI boot Simon Glass
@ 2021-10-27  8:35     ` Ilias Apalodimas
  2021-10-27 14:09       ` Simon Glass
  2021-10-27 11:57     ` Heinrich Schuchardt
  1 sibling, 1 reply; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-27  8:35 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Simon,

On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
>
> Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
>
> In effect, this provides the same functionality as the 'bootefi' command
> and shares the same code. But the interface into it is via a bootmeth,
> so it does not require any special scripts, etc.
>
> For now this requires the 'bootefi' command be enabled. Future work may
> tidy this up so that it can be used without CONFIG_CMDLINE being enabled.

I'll leave this up to Heinrich, but personally I wouldn't include this
patch at all. EFI has it's bootmgr which can handle booting just fine.
I don't see why we should duplicate the functionality.  The new boot
method can just have an entry called 'EFI' and then let the existing
EFI code to decide.
Regards
/Ilias

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>  boot/Kconfig        |  21 ++++
>  boot/Makefile       |   1 +
>  boot/bootmeth_efi.c | 263 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 285 insertions(+)
>  create mode 100644 boot/bootmeth_efi.c
>
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 7e948f95e92..ebbd7427d7f 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -318,6 +318,27 @@ config BOOTMETH_DISTRO_PXE
>
>           This provides a way to try out standard boot on an existing boot flow.
>
> +config BOOTMETH_EFILOADER
> +       bool "Bootdev support for EFI boot"
> +       depends on CMD_BOOTEFI
> +       default y
> +       help
> +         Enables support for EFI boot using bootdevs. This makes the
> +         bootdevs look for a 'boot<arch>.efi' on each filesystem
> +         they scan. The resulting file is booted after enabling U-Boot's
> +         EFI loader support.
> +
> +         The <arch> depends on the architecture of the board:
> +
> +            aa64      - aarch64 (ARM 64-bit)
> +            arm       - ARM 32-bit
> +            ia32      - x86 32-bit
> +            x64       - x86 64-bit
> +            riscv32   - RISC-V 32-bit
> +            riscv64   - RISC-V 64-bit
> +
> +         This provides a way to try out standard boot on an existing boot flow.
> +
>  endif
>
>  config LEGACY_IMAGE_FORMAT
> diff --git a/boot/Makefile b/boot/Makefile
> index 170fcac8ec4..c2345435201 100644
> --- a/boot/Makefile
> +++ b/boot/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
>
>  obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
>  obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
> +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
>
>  obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
>  obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
> diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
> new file mode 100644
> index 00000000000..eeb8f377c50
> --- /dev/null
> +++ b/boot/bootmeth_efi.c
> @@ -0,0 +1,263 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Bootmethod for distro boot via EFI
> + *
> + * Copyright 2021 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <bootdev.h>
> +#include <bootflow.h>
> +#include <bootmeth.h>
> +#include <command.h>
> +#include <dm.h>
> +#include <efi_loader.h>
> +#include <fs.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <mmc.h>
> +#include <pxe_utils.h>
> +
> +#define EFI_DIRNAME    "efi/boot/"
> +
> +/**
> + * get_efi_leafname() - Get the leaf name for the EFI file we expect
> + *
> + * @str: Place to put leaf name for this architecture, e.g. "bootaa64.efi".
> + *     Must have at least 16 bytes of space
> + * @max_len: Length of @str, must be >=16
> + */
> +static int get_efi_leafname(char *str, int max_len)
> +{
> +       const char *base;
> +
> +       if (max_len < 16)
> +               return log_msg_ret("spc", -ENOSPC);
> +       if (IS_ENABLED(CONFIG_ARM64))
> +               base = "bootaa64";
> +       else if (IS_ENABLED(CONFIG_ARM))
> +               base = "bootarm";
> +       else if (IS_ENABLED(CONFIG_X86_RUN_32BIT))
> +               base = "bootia32";
> +       else if (IS_ENABLED(CONFIG_X86_RUN_64BIT))
> +               base = "bootx64";
> +       else if (IS_ENABLED(CONFIG_ARCH_RV32I))
> +               base = "bootriscv32";
> +       else if (IS_ENABLED(CONFIG_ARCH_RV64I))
> +               base = "bootriscv64";
> +       else if (IS_ENABLED(CONFIG_SANDBOX))
> +               base = "bootsbox";
> +       else
> +               return -EINVAL;
> +
> +       strcpy(str, base);
> +       strcat(str, ".efi");
> +
> +       return 0;
> +}
> +
> +static int efiload_read_file(struct blk_desc *desc, struct bootflow *bflow)
> +{
> +       const struct udevice *media_dev;
> +       int size = bflow->size;
> +       char devnum_str[9];
> +       char dirname[200];
> +       loff_t bytes_read;
> +       char *last_slash;
> +       ulong addr;
> +       char *buf;
> +       int ret;
> +
> +       /* Sadly FS closes the file after fs_size() so we must redo this */
> +       ret = fs_set_blk_dev_with_part(desc, bflow->part);
> +       if (ret)
> +               return log_msg_ret("set", ret);
> +
> +       buf = malloc(size + 1);
> +       if (!buf)
> +               return log_msg_ret("buf", -ENOMEM);
> +       addr = map_to_sysmem(buf);
> +
> +       ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
> +       if (ret) {
> +               free(buf);
> +               return log_msg_ret("read", ret);
> +       }
> +       if (size != bytes_read)
> +               return log_msg_ret("bread", -EINVAL);
> +       buf[size] = '\0';
> +       bflow->state = BOOTFLOWST_READY;
> +       bflow->buf = buf;
> +
> +       /*
> +        * This is a horrible hack to tell EFI about this boot device. Once we
> +        * unify EFI with the rest of U-Boot we can clean this up. The same hack
> +        * exists in multiple places, e.g. in the fs, tftp and load commands.
> +        *
> +        * Once we can clean up the EFI code to make proper use of driver model,
> +        * this can go away.
> +        */
> +       media_dev = dev_get_parent(bflow->dev);
> +       snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
> +
> +       strlcpy(dirname, bflow->fname, sizeof(dirname));
> +       last_slash = strrchr(dirname, '/');
> +       if (last_slash)
> +               *last_slash = '\0';
> +
> +       efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
> +                       bflow->buf, size);
> +
> +       return 0;
> +}
> +
> +static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
> +{
> +       int ret;
> +
> +       /* This only works on block devices */
> +       ret = bootflow_iter_uses_blk_dev(iter);
> +       if (ret)
> +               return log_msg_ret("blk", ret);
> +
> +       return 0;
> +}
> +
> +static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
> +{
> +       struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +       char fname[sizeof(EFI_DIRNAME) + 16];
> +       loff_t size;
> +       int ret;
> +
> +       /* We require a partition table */
> +       if (!bflow->part)
> +               return -ENOENT;
> +
> +       strcpy(fname, EFI_DIRNAME);
> +       ret = get_efi_leafname(fname + strlen(fname),
> +                              sizeof(fname) - strlen(fname));
> +       if (ret)
> +               return log_msg_ret("leaf", ret);
> +
> +       bflow->fname = strdup(fname);
> +       if (!bflow->fname)
> +               return log_msg_ret("name", -ENOMEM);
> +       ret = fs_size(bflow->fname, &size);
> +       bflow->size = size;
> +       if (ret)
> +               return log_msg_ret("size", ret);
> +       bflow->state = BOOTFLOWST_FILE;
> +       log_debug("   - distro file size %x\n", (uint)size);
> +       if (size > 0x2000000)
> +               return log_msg_ret("chk", -E2BIG);
> +
> +       ret = efiload_read_file(desc, bflow);
> +       if (ret)
> +               return log_msg_ret("read", -EINVAL);
> +
> +       return 0;
> +}
> +
> +static int distro_efi_read_file(struct udevice *dev, struct bootflow *bflow,
> +                               const char *file_path, ulong addr, ulong *sizep)
> +{
> +       struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +       const struct udevice *media_dev;
> +       int size = bflow->size;
> +       char devnum_str[9];
> +       char dirname[200];
> +       loff_t bytes_read;
> +       char *last_slash;
> +       char *buf;
> +       int ret;
> +
> +       /* Sadly FS closes the file after fs_size() so we must redo this */
> +       ret = fs_set_blk_dev_with_part(desc, bflow->part);
> +       if (ret)
> +               return log_msg_ret("set", ret);
> +
> +       buf = malloc(size + 1);
> +       if (!buf)
> +               return log_msg_ret("buf", -ENOMEM);
> +       addr = map_to_sysmem(buf);
> +
> +       ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
> +       if (ret) {
> +               free(buf);
> +               return log_msg_ret("read", ret);
> +       }
> +       if (size != bytes_read)
> +               return log_msg_ret("bread", -EINVAL);
> +       buf[size] = '\0';
> +       bflow->state = BOOTFLOWST_READY;
> +       bflow->buf = buf;
> +
> +       /*
> +        * This is a horrible hack to tell EFI about this boot device. Once we
> +        * unify EFI with the rest of U-Boot we can clean this up. The same hack
> +        * exists in multiple places, e.g. in the fs, tftp and load commands.
> +        *
> +        * Once we can clean up the EFI code to make proper use of driver model,
> +        * this can go away.
> +        */
> +       media_dev = dev_get_parent(bflow->dev);
> +       snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
> +
> +       strlcpy(dirname, bflow->fname, sizeof(dirname));
> +       last_slash = strrchr(dirname, '/');
> +       if (last_slash)
> +               *last_slash = '\0';
> +
> +       efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
> +                       bflow->buf, size);
> +
> +       return 0;
> +}
> +
> +int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
> +{
> +       char cmd[50];
> +
> +       /*
> +        * At some point we can add a real interface to bootefi so we can call
> +        * this directly. For now, go through the CLI like distro boot.
> +        */
> +       snprintf(cmd, sizeof(cmd), "bootefi %lx %lx",
> +                (ulong)map_to_sysmem(bflow->buf),
> +                (ulong)map_to_sysmem(gd->fdt_blob));
> +       if (run_command(cmd, 0))
> +               return log_msg_ret("run", -EINVAL);
> +
> +       return 0;
> +}
> +
> +static int distro_bootmeth_efi_bind(struct udevice *dev)
> +{
> +       struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
> +
> +       plat->desc = "EFI boot from a .efi file";
> +
> +       return 0;
> +}
> +
> +static struct bootmeth_ops distro_efi_bootmeth_ops = {
> +       .check          = distro_efi_check,
> +       .read_bootflow  = distro_efi_read_bootflow,
> +       .read_file      = distro_efi_read_file,
> +       .boot           = distro_efi_boot,
> +};
> +
> +static const struct udevice_id distro_efi_bootmeth_ids[] = {
> +       { .compatible = "u-boot,distro-efi" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(bootmeth_efi) = {
> +       .name           = "bootmeth_efi",
> +       .id             = UCLASS_BOOTMETH,
> +       .of_match       = distro_efi_bootmeth_ids,
> +       .ops            = &distro_efi_bootmeth_ops,
> +       .bind           = distro_bootmeth_efi_bind,
> +};
> --
> 2.33.0.1079.g6e70778dc9-goog
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-23 23:25   ` [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build Simon Glass
@ 2021-10-27  8:50     ` Ilias Apalodimas
  2021-10-27 12:21       ` Heinrich Schuchardt
  0 siblings, 1 reply; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-27  8:50 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada

Hi Simon

How does this patch related to the standard boot series? Shouldn't
this be a completely separate patch?

Thanks
/Ilias

On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
>
> LTO (Link-Time Optimisation) is an very useful feature which can
> significantly reduce the size of U-Boot binaries. So far it has been
> made available for selected ARM boards and sandbox.
>
> However, incremental builds are much slower when LTO is used. For example,
> an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> seconds with LTO enabled.
>
> Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> development if needed, for faster builds.
>
> Add some documentation about LTO while we are here.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>  Makefile                           | 18 +++++++++++++-----
>  arch/arm/config.mk                 |  4 ++--
>  arch/arm/include/asm/global_data.h |  2 +-
>  doc/build/gcc.rst                  | 17 +++++++++++++++++
>  4 files changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index b79b2319ff6..7057723e046 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
>  KBUILD_AFLAGS   := -D__ASSEMBLY__
>  KBUILD_LDFLAGS  :=
>
> +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> +LTO_BUILD      ?= y
> +
>  ifeq ($(cc-name),clang)
>  ifneq ($(CROSS_COMPILE),)
>  CLANG_TARGET   := --target=$(notdir $(CROSS_COMPILE:%-=%))
> @@ -641,6 +644,11 @@ 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
> +LTO_ENABLE=$(if $(CONFIG_LTO),$(LTO_BUILD),)
> +
>  # 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.
> @@ -688,16 +696,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
> @@ -1717,7 +1725,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))
>
> @@ -1739,7 +1747,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 b107b1af27a..065dbec4064 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/global_data.h b/arch/arm/include/asm/global_data.h
> index 085e12b5d4d..b255b195aa0 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -98,7 +98,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/doc/build/gcc.rst b/doc/build/gcc.rst
> index cdd79700326..136c318727d 100644
> --- a/doc/build/gcc.rst
> +++ b/doc/build/gcc.rst
> @@ -141,6 +141,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 `LTO_BUILD` to `n`.
> +
> +.. code-block:: bash
> +
> +    LTO_BUILD=n make
> +
>  Other build targets
>  ~~~~~~~~~~~~~~~~~~~
>
> --
> 2.33.0.1079.g6e70778dc9-goog
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (41 preceding siblings ...)
  2021-10-23 23:27   ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
@ 2021-10-27 11:38   ` Heinrich Schuchardt
  2021-10-27 14:11     ` Simon Glass
                       ` (2 more replies)
  2021-10-28 16:27   ` Tom Rini
                     ` (14 subsequent siblings)
  57 siblings, 3 replies; 116+ messages in thread
From: Heinrich Schuchardt @ 2021-10-27 11:38 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Jaehoon Chung, Marek Vasut, Masahiro Yamada, Pavel Herrmann,
	Peng Fan, Stephen Warren, Stephen Warren, François Ozog,
	Heinrich Schuchardt, U-Boot Mailing List



On 10/24/21 01:25, Simon Glass wrote:
> 
> The bootflow feature provide a built-in way for U-Boot to automatically
> boot an Operating System without custom scripting and other customisation.
> This is called 'standard boot' since it provides a standard way for
> U-Boot to boot a distro, without scripting.
> 
> It introduces the following concepts:
> 
>     - bootdev - a device which can hold a distro
>     - bootmeth - a method to scan a bootdev to find bootflows (owned by
>                  U-Boot)
>     - bootflow - a description of how to boot (owned by the distro)

Please, describe why you are suggesting this change.

Replacing a script by a devicetree chunk is just decreasing flexibility 
and increasing complexity. Where is the benefit?

I am missing a description here of where and how a boot flow shall be 
defined. Describing some device-tree binding in patch 40/41 does not 
replace describing the development and usage workflow. Who will provide 
which bootflow information when?

You still have an open discussion with Linaro about the source of 
devicetrees. This discussion needs to be finalized before considering 
this series.

In my view bootflows cannot be defined in the devicetree because prior 
firmware providing a devicetree is completely independent of any distro 
and therefore cannot provide a distro specific bootflow.

Best regards

Heinrich

> 
> This series provides an implementation of these, enabled to scan for
> bootflows from MMC, USB and Ethernet. It supports the existing distro
> boot as well as the EFI loader flow (bootefi/bootmgr). It works
> similiarly to the existing script-based approach, but is native to
> U-Boot.
> 
> With this we can boot on a Raspberry Pi 3 with just one command:
> 
>     bootflow scan -lb
> 
> which means to scan, listing (-l) each bootflow and trying to boot each
> one (-b). The final patch shows this.
> 
> With a standard way to identify boot devices, booting become easier. It
> also should be possible to support U-Boot scripts, for backwards
> compatibility only.
> 
> This series relies on the PXE clean-up series, posted here:
> 
>     https://patchwork.ozlabs.org/project/uboot/list/?series=267078
> 
> For documentation, see the 'doc' patch.
> 
> For version 2, a new naming scheme is used as above:
> 
>     - bootdev is used instead of bootdevice, because 'device' is overused,
>         is everywhere in U-Boot, can be confused with udevice
>     - bootmeth - because 'method' is too vanilla, appears 1300 times in
>         U-Boot
> 
> Also in version 2, drivers are introduced for the boot methods, to make
> it more extensible. Booting a custom OS is simply a matter of creating a
> bootmeth for it and implementing the read_file() and boot() methods.
> 
> The design is described in these two documents:
> 
> https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> 
> https://drive.google.com/file/d/1kTrflO9vvGlKp-ZH_jlgb9TY3WYG6FF9/view?usp=sharing
> 
> The series is available at u-boot-dm/bme-working
> 
> Sample log on rpi_3_32b:
> 
> U-Boot 2021.10-rc2-00043-gccd453aa918-dirty (Aug 28 2021 - 13:58:46 -0600)
> 
> DRAM:  992 MiB
> RPI 3 Model B (0xa22082)
> MMC:   mmc@7e202000: 0, sdhci@7e300000: 1
> Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... In:    serial
> Out:   vidconsole
> Err:   vidconsole
> Net:   No ethernet found.
> starting USB...
> Bus usb@7e980000: USB DWC2
> scanning bus usb@7e980000 for devices... usb_kbd usb_kbd: Timeout poll on interrupt endpoint
> Failed to get keyboard state from device 0c40:8000
> 4 USB Device(s) found
>         scanning usb for storage devices... 0 Storage Device(s) found
> Hit any key to stop autoboot:  0
> Scanning for bootflows in all bootmethods
> Seq  Type         State   Uclass    Part  Name                      Filename
> ---  -----------  ------  --------  ----  ------------------------  ----------------
> Scanning bootmethod 'mmc@7e202000.bootmethod':
>    0  efi-loader   loaded  mmc          1  mmc@7e202000.bootmethod.p efi/boot/bootarm.efi
> ** Booting bootflow 'mmc@7e202000.bootmethod.part_1'
> Scanning disk mmc@7e202000.blk...
> ** Unrecognized filesystem type **
> Card did not respond to voltage select! : -110
> Scanning disk sdhci@7e300000.blk...
> Disk sdhci@7e300000.blk not ready
> Found 4 disks
> No EFI system partition
> Booting /efi\boot
> Waiting for Ethernet connection... done.
> 
>        Fedora (5.11.12-300.fc34.armv7hl) 34 (Workstation Edition)
>        UEFI Firmware Settings
> 
>        Use the ▲ and ▼ keys to change the selection.
>        Press 'e' to edit the selected item, or 'c' for a command prompt. Press Escape to return to the previous menu.
>     The selected entry will be started automatically in 0s.
> 
> Changes in v2:
> - Free the memory buffer, to avoid running out of memory
> - Unmap the file
> - Reorder struct sandbox_mmc_priv
> 
> Simon Glass (41):
>    lib: Add a way to find the postiion of a trailing number
>    Makefile: Allow LTO to be disabled for a build
>    test/py: Allow passing input to a program
>    sandbox: Support unmapping a file
>    sandbox: mmc: Support a backing file
>    mmc: Allow for children other than the block device
>    mbr: Correct verification check
>    disk: part_dos: Fix a NULL pointer error
>    common: Allow a smaller console-recording pre-reloc
>    dm: core: Add tests for stringlist functions
>    dm: core: Fix handling of uclass pre_unbind method
>    dm: core: Fix up string-function documentation
>    dm: core: Add a way to obtain a string list
>    dm: core: Allow finding children / uclasses by partial name
>    dm: core: Add a way to count the devices in a uclass
>    sandbox: Enable HEXDUMP for sandbox_flattree
>    test/py: Relax the naming rules for unit tests
>    test/py: Raise a ValueError if a command fails
>    bootstd: Add the concept of a bootflow
>    bootstd: Add the bootstd uclass and core implementation
>    bootstd: Add the bootdev uclass
>    bootstd: Add the bootmeth uclass and helpers
>    bootstd: Add support for bootflows
>    bootstd: Add a bootdev command
>    bootstd: Add a bootflow ommand
>    bootstd: Add a bootmeth command
>    bootstd: Add an implementation of distro boot
>    bootstd: mmc: Add a bootdev driver
>    bootstd: ethernet: Add a bootdev driver
>    bootstd: Add an implementation of distro PXE boot
>    bootstd: Add an implementation of EFI boot
>    bootstd: Add a system bootdev for strange boot methods
>    bootstd: Add an implementation of EFI bootmgr
>    bootstd: Add a sandbox bootmeth driver
>    bootstd: usb: Add a bootdev driver
>    test: fastboot: Avoid using mmc1
>    test: dm: Restart USB before assuming it is stopped
>    bootstd: Add tests for bootstd including all uclasses
>    bootstd: Add setup for the bootflow tests
>    bootstd: doc: Add documentation
>    RFC: Switch rpi over to use bootstd
> 
>   MAINTAINERS                                  |  21 +
>   Makefile                                     |  18 +-
>   arch/arm/config.mk                           |   4 +-
>   arch/arm/include/asm/global_data.h           |   2 +-
>   arch/sandbox/cpu/os.c                        |  10 +
>   arch/sandbox/dts/test.dts                    |  19 +
>   boot/Kconfig                                 |  77 ++-
>   boot/Makefile                                |  14 +
>   boot/bootdev-uclass.c                        | 439 ++++++++++++++
>   boot/bootflow.c                              | 576 ++++++++++++++++++
>   boot/bootmeth-uclass.c                       |  59 ++
>   boot/bootmeth_distro.c                       | 217 +++++++
>   boot/bootmeth_efi.c                          | 263 ++++++++
>   boot/bootmeth_efi_mgr.c                      |  84 +++
>   boot/bootmeth_pxe.c                          | 183 ++++++
>   boot/bootmeth_sandbox.c                      |  67 +++
>   boot/bootstd-uclass.c                        | 176 ++++++
>   boot/system_bootdev.c                        |  64 ++
>   cmd/Kconfig                                  |  15 +
>   cmd/Makefile                                 |   1 +
>   cmd/bootdev.c                                | 120 ++++
>   cmd/bootflow.c                               | 386 ++++++++++++
>   cmd/bootmeth.c                               | 158 +++++
>   cmd/mbr.c                                    |   8 +-
>   common/Kconfig                               |  10 +
>   common/console.c                             |   4 +-
>   common/usb_storage.c                         |  12 +
>   configs/amcore_defconfig                     |   1 +
>   configs/rcar3_salvator-x_defconfig           |   1 +
>   configs/sandbox_defconfig                    |   3 +-
>   configs/sandbox_flattree_defconfig           |   4 +-
>   configs/tbs2910_defconfig                    |   1 +
>   disk/part_dos.c                              |  10 +-
>   doc/build/gcc.rst                            |  17 +
>   doc/develop/bootstd.rst                      | 600 +++++++++++++++++++
>   doc/develop/distro.rst                       |   3 +
>   doc/develop/index.rst                        |   1 +
>   doc/device-tree-bindings/bootdev.txt         |  26 +
>   doc/device-tree-bindings/bootmeth.txt        |  31 +
>   doc/device-tree-bindings/bootstd.txt         |  36 ++
>   doc/device-tree-bindings/mmc/sandbox,mmc.txt |  18 +
>   doc/usage/bootdev.rst                        | 135 +++++
>   doc/usage/bootflow.rst                       | 427 +++++++++++++
>   doc/usage/bootmeth.rst                       | 106 ++++
>   doc/usage/index.rst                          |   3 +
>   drivers/core/device-remove.c                 |   9 +-
>   drivers/core/device.c                        |  13 +-
>   drivers/core/of_access.c                     |   3 +-
>   drivers/core/ofnode.c                        |  26 +
>   drivers/core/read.c                          |   6 +
>   drivers/core/uclass.c                        |  29 +-
>   drivers/mmc/Makefile                         |   5 +
>   drivers/mmc/mmc-uclass.c                     |  27 +-
>   drivers/mmc/mmc_bootdev.c                    |  62 ++
>   drivers/mmc/sandbox_mmc.c                    |  60 +-
>   drivers/usb/host/Makefile                    |   4 +
>   drivers/usb/host/usb_bootdev.c               |  61 ++
>   include/bootdev.h                            | 258 ++++++++
>   include/bootflow.h                           | 304 ++++++++++
>   include/bootmeth.h                           | 156 +++++
>   include/bootstd.h                            |  80 +++
>   include/configs/rpi.h                        |  41 +-
>   include/distro.h                             |  24 +
>   include/dm/device.h                          |  12 +
>   include/dm/ofnode.h                          |  24 +-
>   include/dm/read.h                            |  28 +
>   include/dm/uclass-id.h                       |   3 +
>   include/dm/uclass-internal.h                 |  14 +-
>   include/dm/uclass.h                          |  17 +
>   include/mmc.h                                |  12 +-
>   include/os.h                                 |   9 +
>   include/test/suites.h                        |   2 +
>   include/vsprintf.h                           |  18 +
>   lib/strto.c                                  |  14 +-
>   net/Kconfig                                  |   9 +
>   net/Makefile                                 |   1 +
>   net/eth-uclass.c                             |   8 +
>   net/eth_bootdev.c                            | 101 ++++
>   test/Makefile                                |   1 +
>   test/boot/Makefile                           |   5 +
>   test/boot/bootdev.c                          | 200 +++++++
>   test/boot/bootflow.c                         | 398 ++++++++++++
>   test/boot/bootmeth.c                         |  90 +++
>   test/boot/bootstd_common.c                   |  35 ++
>   test/boot/bootstd_common.h                   |  27 +
>   test/cmd_ut.c                                |   7 +
>   test/dm/blk.c                                |   6 +
>   test/dm/fastboot.c                           |   4 +-
>   test/dm/ofnode.c                             |  96 +++
>   test/py/conftest.py                          |   2 +-
>   test/py/multiplexed_log.py                   |  10 +-
>   test/py/tests/bootstd/mmc1.img.xz            | Bin 0 -> 4448 bytes
>   test/py/tests/test_ut.py                     | 103 ++++
>   test/py/u_boot_utils.py                      |   5 +-
>   94 files changed, 6765 insertions(+), 94 deletions(-)
>   create mode 100644 boot/bootdev-uclass.c
>   create mode 100644 boot/bootflow.c
>   create mode 100644 boot/bootmeth-uclass.c
>   create mode 100644 boot/bootmeth_distro.c
>   create mode 100644 boot/bootmeth_efi.c
>   create mode 100644 boot/bootmeth_efi_mgr.c
>   create mode 100644 boot/bootmeth_pxe.c
>   create mode 100644 boot/bootmeth_sandbox.c
>   create mode 100644 boot/bootstd-uclass.c
>   create mode 100644 boot/system_bootdev.c
>   create mode 100644 cmd/bootdev.c
>   create mode 100644 cmd/bootflow.c
>   create mode 100644 cmd/bootmeth.c
>   create mode 100644 doc/develop/bootstd.rst
>   create mode 100644 doc/device-tree-bindings/bootdev.txt
>   create mode 100644 doc/device-tree-bindings/bootmeth.txt
>   create mode 100644 doc/device-tree-bindings/bootstd.txt
>   create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt
>   create mode 100644 doc/usage/bootdev.rst
>   create mode 100644 doc/usage/bootflow.rst
>   create mode 100644 doc/usage/bootmeth.rst
>   create mode 100644 drivers/mmc/mmc_bootdev.c
>   create mode 100644 drivers/usb/host/usb_bootdev.c
>   create mode 100644 include/bootdev.h
>   create mode 100644 include/bootflow.h
>   create mode 100644 include/bootmeth.h
>   create mode 100644 include/bootstd.h
>   create mode 100644 include/distro.h
>   create mode 100644 net/eth_bootdev.c
>   create mode 100644 test/boot/Makefile
>   create mode 100644 test/boot/bootdev.c
>   create mode 100644 test/boot/bootflow.c
>   create mode 100644 test/boot/bootmeth.c
>   create mode 100644 test/boot/bootstd_common.c
>   create mode 100644 test/boot/bootstd_common.h
>   create mode 100644 test/py/tests/bootstd/mmc1.img.xz
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-23 23:26   ` [PATCH v2 31/41] bootstd: Add an implementation of EFI boot Simon Glass
  2021-10-27  8:35     ` Ilias Apalodimas
@ 2021-10-27 11:57     ` Heinrich Schuchardt
  2021-10-27 14:08       ` Simon Glass
  1 sibling, 1 reply; 116+ messages in thread
From: Heinrich Schuchardt @ 2021-10-27 11:57 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	U-Boot Mailing List



On 10/24/21 01:26, Simon Glass wrote:
> Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
>
> In effect, this provides the same functionality as the 'bootefi' command
> and shares the same code. But the interface into it is via a bootmeth,
> so it does not require any special scripts, etc.
>
> For now this requires the 'bootefi' command be enabled. Future work may
> tidy this up so that it can be used without CONFIG_CMDLINE being enabled.

Booting via the boot manager must occur without issuing a command on the
command line. How will the boot method in this file be invoked?

The bootefi command may be implemented by invoking a boot method. A boot
method invoking a command does not make sense to me.

Best regards

Heinrich

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>   boot/Kconfig        |  21 ++++
>   boot/Makefile       |   1 +
>   boot/bootmeth_efi.c | 263 ++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 285 insertions(+)
>   create mode 100644 boot/bootmeth_efi.c
>
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 7e948f95e92..ebbd7427d7f 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -318,6 +318,27 @@ config BOOTMETH_DISTRO_PXE
>
>   	  This provides a way to try out standard boot on an existing boot flow.
>
> +config BOOTMETH_EFILOADER
> +	bool "Bootdev support for EFI boot"
> +	depends on CMD_BOOTEFI
> +	default y
> +	help
> +	  Enables support for EFI boot using bootdevs. This makes the
> +	  bootdevs look for a 'boot<arch>.efi' on each filesystem
> +	  they scan. The resulting file is booted after enabling U-Boot's
> +	  EFI loader support.
> +
> +	  The <arch> depends on the architecture of the board:
> +
> +	     aa64      - aarch64 (ARM 64-bit)
> +	     arm       - ARM 32-bit
> +	     ia32      - x86 32-bit
> +	     x64       - x86 64-bit
> +	     riscv32   - RISC-V 32-bit
> +	     riscv64   - RISC-V 64-bit
> +
> +	  This provides a way to try out standard boot on an existing boot flow.
> +
>   endif
>
>   config LEGACY_IMAGE_FORMAT
> diff --git a/boot/Makefile b/boot/Makefile
> index 170fcac8ec4..c2345435201 100644
> --- a/boot/Makefile
> +++ b/boot/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
>
>   obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o
>   obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o
> +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
>
>   obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
>   obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
> diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
> new file mode 100644
> index 00000000000..eeb8f377c50
> --- /dev/null
> +++ b/boot/bootmeth_efi.c
> @@ -0,0 +1,263 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Bootmethod for distro boot via EFI
> + *
> + * Copyright 2021 Google LLC
> + * Written by Simon Glass <sjg@chromium.org>
> + */
> +
> +#include <common.h>
> +#include <bootdev.h>
> +#include <bootflow.h>
> +#include <bootmeth.h>
> +#include <command.h>
> +#include <dm.h>
> +#include <efi_loader.h>
> +#include <fs.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <mmc.h>
> +#include <pxe_utils.h>
> +
> +#define EFI_DIRNAME	"efi/boot/"
> +
> +/**
> + * get_efi_leafname() - Get the leaf name for the EFI file we expect
> + *
> + * @str: Place to put leaf name for this architecture, e.g. "bootaa64.efi".
> + *	Must have at least 16 bytes of space
> + * @max_len: Length of @str, must be >=16
> + */
> +static int get_efi_leafname(char *str, int max_len)
> +{
> +	const char *base;
> +
> +	if (max_len < 16)
> +		return log_msg_ret("spc", -ENOSPC);
> +	if (IS_ENABLED(CONFIG_ARM64))
> +		base = "bootaa64";
> +	else if (IS_ENABLED(CONFIG_ARM))
> +		base = "bootarm";
> +	else if (IS_ENABLED(CONFIG_X86_RUN_32BIT))
> +		base = "bootia32";
> +	else if (IS_ENABLED(CONFIG_X86_RUN_64BIT))
> +		base = "bootx64";
> +	else if (IS_ENABLED(CONFIG_ARCH_RV32I))
> +		base = "bootriscv32";
> +	else if (IS_ENABLED(CONFIG_ARCH_RV64I))
> +		base = "bootriscv64";
> +	else if (IS_ENABLED(CONFIG_SANDBOX))
> +		base = "bootsbox";
> +	else
> +		return -EINVAL;
> +
> +	strcpy(str, base);
> +	strcat(str, ".efi");
> +
> +	return 0;
> +}
> +
> +static int efiload_read_file(struct blk_desc *desc, struct bootflow *bflow)
> +{
> +	const struct udevice *media_dev;
> +	int size = bflow->size;
> +	char devnum_str[9];
> +	char dirname[200];
> +	loff_t bytes_read;
> +	char *last_slash;
> +	ulong addr;
> +	char *buf;
> +	int ret;
> +
> +	/* Sadly FS closes the file after fs_size() so we must redo this */
> +	ret = fs_set_blk_dev_with_part(desc, bflow->part);
> +	if (ret)
> +		return log_msg_ret("set", ret);
> +
> +	buf = malloc(size + 1);
> +	if (!buf)
> +		return log_msg_ret("buf", -ENOMEM);
> +	addr = map_to_sysmem(buf);
> +
> +	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
> +	if (ret) {
> +		free(buf);
> +		return log_msg_ret("read", ret);
> +	}
> +	if (size != bytes_read)
> +		return log_msg_ret("bread", -EINVAL);
> +	buf[size] = '\0';
> +	bflow->state = BOOTFLOWST_READY;
> +	bflow->buf = buf;
> +
> +	/*
> +	 * This is a horrible hack to tell EFI about this boot device. Once we
> +	 * unify EFI with the rest of U-Boot we can clean this up. The same hack
> +	 * exists in multiple places, e.g. in the fs, tftp and load commands.
> +	 *
> +	 * Once we can clean up the EFI code to make proper use of driver model,
> +	 * this can go away.
> +	 */
> +	media_dev = dev_get_parent(bflow->dev);
> +	snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
> +
> +	strlcpy(dirname, bflow->fname, sizeof(dirname));
> +	last_slash = strrchr(dirname, '/');
> +	if (last_slash)
> +		*last_slash = '\0';
> +
> +	efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
> +			bflow->buf, size);
> +
> +	return 0;
> +}
> +
> +static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
> +{
> +	int ret;
> +
> +	/* This only works on block devices */
> +	ret = bootflow_iter_uses_blk_dev(iter);
> +	if (ret)
> +		return log_msg_ret("blk", ret);
> +
> +	return 0;
> +}
> +
> +static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	char fname[sizeof(EFI_DIRNAME) + 16];
> +	loff_t size;
> +	int ret;
> +
> +	/* We require a partition table */
> +	if (!bflow->part)
> +		return -ENOENT;
> +
> +	strcpy(fname, EFI_DIRNAME);
> +	ret = get_efi_leafname(fname + strlen(fname),
> +			       sizeof(fname) - strlen(fname));
> +	if (ret)
> +		return log_msg_ret("leaf", ret);
> +
> +	bflow->fname = strdup(fname);
> +	if (!bflow->fname)
> +		return log_msg_ret("name", -ENOMEM);
> +	ret = fs_size(bflow->fname, &size);
> +	bflow->size = size;
> +	if (ret)
> +		return log_msg_ret("size", ret);
> +	bflow->state = BOOTFLOWST_FILE;
> +	log_debug("   - distro file size %x\n", (uint)size);
> +	if (size > 0x2000000)
> +		return log_msg_ret("chk", -E2BIG);
> +
> +	ret = efiload_read_file(desc, bflow);
> +	if (ret)
> +		return log_msg_ret("read", -EINVAL);
> +
> +	return 0;
> +}
> +
> +static int distro_efi_read_file(struct udevice *dev, struct bootflow *bflow,
> +				const char *file_path, ulong addr, ulong *sizep)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	const struct udevice *media_dev;
> +	int size = bflow->size;
> +	char devnum_str[9];
> +	char dirname[200];
> +	loff_t bytes_read;
> +	char *last_slash;
> +	char *buf;
> +	int ret;
> +
> +	/* Sadly FS closes the file after fs_size() so we must redo this */
> +	ret = fs_set_blk_dev_with_part(desc, bflow->part);
> +	if (ret)
> +		return log_msg_ret("set", ret);
> +
> +	buf = malloc(size + 1);
> +	if (!buf)
> +		return log_msg_ret("buf", -ENOMEM);
> +	addr = map_to_sysmem(buf);
> +
> +	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
> +	if (ret) {
> +		free(buf);
> +		return log_msg_ret("read", ret);
> +	}
> +	if (size != bytes_read)
> +		return log_msg_ret("bread", -EINVAL);
> +	buf[size] = '\0';
> +	bflow->state = BOOTFLOWST_READY;
> +	bflow->buf = buf;
> +
> +	/*
> +	 * This is a horrible hack to tell EFI about this boot device. Once we
> +	 * unify EFI with the rest of U-Boot we can clean this up. The same hack
> +	 * exists in multiple places, e.g. in the fs, tftp and load commands.
> +	 *
> +	 * Once we can clean up the EFI code to make proper use of driver model,
> +	 * this can go away.
> +	 */
> +	media_dev = dev_get_parent(bflow->dev);
> +	snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev));
> +
> +	strlcpy(dirname, bflow->fname, sizeof(dirname));
> +	last_slash = strrchr(dirname, '/');
> +	if (last_slash)
> +		*last_slash = '\0';
> +
> +	efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, dirname,
> +			bflow->buf, size);
> +
> +	return 0;
> +}
> +
> +int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
> +{
> +	char cmd[50];
> +
> +	/*
> +	 * At some point we can add a real interface to bootefi so we can call
> +	 * this directly. For now, go through the CLI like distro boot.
> +	 */
> +	snprintf(cmd, sizeof(cmd), "bootefi %lx %lx",
> +		 (ulong)map_to_sysmem(bflow->buf),
> +		 (ulong)map_to_sysmem(gd->fdt_blob));
> +	if (run_command(cmd, 0))
> +		return log_msg_ret("run", -EINVAL);
> +
> +	return 0;
> +}
> +
> +static int distro_bootmeth_efi_bind(struct udevice *dev)
> +{
> +	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
> +
> +	plat->desc = "EFI boot from a .efi file";
> +
> +	return 0;
> +}
> +
> +static struct bootmeth_ops distro_efi_bootmeth_ops = {
> +	.check		= distro_efi_check,
> +	.read_bootflow	= distro_efi_read_bootflow,
> +	.read_file	= distro_efi_read_file,
> +	.boot		= distro_efi_boot,
> +};
> +
> +static const struct udevice_id distro_efi_bootmeth_ids[] = {
> +	{ .compatible = "u-boot,distro-efi" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(bootmeth_efi) = {
> +	.name		= "bootmeth_efi",
> +	.id		= UCLASS_BOOTMETH,
> +	.of_match	= distro_efi_bootmeth_ids,
> +	.ops		= &distro_efi_bootmeth_ops,
> +	.bind		= distro_bootmeth_efi_bind,
> +};
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number
  2021-10-23 23:25   ` [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number Simon Glass
@ 2021-10-27 12:13     ` Heinrich Schuchardt
  0 siblings, 0 replies; 116+ messages in thread
From: Heinrich Schuchardt @ 2021-10-27 12:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Heinrich Schuchardt, U-Boot Mailing List



On 10/24/21 01:25, Simon Glass wrote:
> At present it is not possible to find out which part of the string is the
> number part and which is before it. Add a new variant which provides this
> feature, so we can separate the two in the caller.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> (no changes since v1)
> 
>   include/vsprintf.h | 18 ++++++++++++++++++
>   lib/strto.c        | 14 ++++++++++++--
>   2 files changed, 30 insertions(+), 2 deletions(-)
> 
> diff --git a/include/vsprintf.h b/include/vsprintf.h
> index b4746301462..8230e7a5126 100644
> --- a/include/vsprintf.h
> +++ b/include/vsprintf.h
> @@ -118,6 +118,24 @@ long trailing_strtol(const char *str);
>    */
>   long trailing_strtoln(const char *str, const char *end);
>   
> +/**
> + * trailing_strtoln() - extract a trailing integer from a fixed-length string
> + *
> + * Given a fixed-length string this finds a trailing number on the string
> + * and returns it. For example, "abc123" would return 123. Only the
> + * characters between @str and @end - 1 are examined. If @end is NULL, it is
> + * set to str + strlen(str).

Please, provide a test with as string like 'abc123def456'.

> + *
> + * @str:	String to exxamine
> + * @end:	Pointer to end of string to examine, or NULL to use the
> + *		whole string
> + * @lenp:	If non-NULL, this is set to the number of characters before the
> + *	number starts, e.g. for "mmc0" this would be 3; if no trailing number is
> + *	found, it is set to the length of the whole string
> + * @return training number if found, else -1
> + */
> +long trailing_strtoln_len(const char *str, const char *end, int *lenp);

Usage in a caller would be easier if you would return a pointer to the 
first digit instead of a length.

Best regards

Heinrich

> +
>   /**
>    * panic() - Print a message and reset/hang
>    *
> diff --git a/lib/strto.c b/lib/strto.c
> index 7bba1e3e549..13ae22a87a1 100644
> --- a/lib/strto.c
> +++ b/lib/strto.c
> @@ -183,7 +183,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base)
>   	return simple_strtoull(cp, endp, base);
>   }
>   
> -long trailing_strtoln(const char *str, const char *end)
> +long trailing_strtoln_len(const char *str, const char *end, int *lenp)
>   {
>   	const char *p;
>   
> @@ -191,14 +191,24 @@ long trailing_strtoln(const char *str, const char *end)
>   		end = str + strlen(str);
>   	if (isdigit(end[-1])) {
>   		for (p = end - 1; p > str; p--) {
> -			if (!isdigit(*p))
> +			if (!isdigit(*p)) {
> +				if (lenp)
> +					*lenp = p - str + 1;
>   				return dectoul(p + 1, NULL);
> +			}
>   		}
>   	}
> +	if (lenp)
> +		*lenp = end - str;
>   
>   	return -1;
>   }
>   
> +long trailing_strtoln(const char *str, const char *end)
> +{
> +	return trailing_strtoln_len(str, end, NULL);
> +}
> +
>   long trailing_strtol(const char *str)
>   {
>   	return trailing_strtoln(str, NULL);
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-27  8:50     ` Ilias Apalodimas
@ 2021-10-27 12:21       ` Heinrich Schuchardt
  2021-10-27 13:13         ` Tom Rini
  2021-10-31 23:45         ` Simon Glass
  0 siblings, 2 replies; 116+ messages in thread
From: Heinrich Schuchardt @ 2021-10-27 12:21 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Tom Rini, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Masahiro Yamada, Ilias Apalodimas, Heinrich Schuchardt



On 10/27/21 10:50, Ilias Apalodimas wrote:
> Hi Simon
> 
> How does this patch related to the standard boot series? Shouldn't
> this be a completely separate patch?
> 
> Thanks
> /Ilias
> 
> On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
>>
>> LTO (Link-Time Optimisation) is an very useful feature which can
>> significantly reduce the size of U-Boot binaries. So far it has been
>> made available for selected ARM boards and sandbox.
>>
>> However, incremental builds are much slower when LTO is used. For example,
>> an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
>> seconds with LTO enabled.
>>
>> Add a LTO_BUILD=n parameter to the build, so it can be disabled during
>> development if needed, for faster builds.
>>
>> Add some documentation about LTO while we are here.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> (no changes since v1)
>>
>>   Makefile                           | 18 +++++++++++++-----
>>   arch/arm/config.mk                 |  4 ++--
>>   arch/arm/include/asm/global_data.h |  2 +-
>>   doc/build/gcc.rst                  | 17 +++++++++++++++++
>>   4 files changed, 33 insertions(+), 8 deletions(-)
>>
>> diff --git a/Makefile b/Makefile
>> index b79b2319ff6..7057723e046 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
>>   KBUILD_AFLAGS   := -D__ASSEMBLY__
>>   KBUILD_LDFLAGS  :=
>>
>> +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
>> +LTO_BUILD      ?= y

This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.

We should have something like

LTO_CONFIG ?= $CONFIG_LTO

Best regards

Heinrich

>> +
>>   ifeq ($(cc-name),clang)
>>   ifneq ($(CROSS_COMPILE),)
>>   CLANG_TARGET   := --target=$(notdir $(CROSS_COMPILE:%-=%))
>> @@ -641,6 +644,11 @@ 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
>> +LTO_ENABLE=$(if $(CONFIG_LTO),$(LTO_BUILD),)
>> +
>>   # 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.
>> @@ -688,16 +696,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
>> @@ -1717,7 +1725,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))
>>
>> @@ -1739,7 +1747,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 b107b1af27a..065dbec4064 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/global_data.h b/arch/arm/include/asm/global_data.h
>> index 085e12b5d4d..b255b195aa0 100644
>> --- a/arch/arm/include/asm/global_data.h
>> +++ b/arch/arm/include/asm/global_data.h
>> @@ -98,7 +98,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/doc/build/gcc.rst b/doc/build/gcc.rst
>> index cdd79700326..136c318727d 100644
>> --- a/doc/build/gcc.rst
>> +++ b/doc/build/gcc.rst
>> @@ -141,6 +141,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 `LTO_BUILD` to `n`.
>> +
>> +.. code-block:: bash
>> +
>> +    LTO_BUILD=n make
>> +
>>   Other build targets
>>   ~~~~~~~~~~~~~~~~~~~
>>
>> --
>> 2.33.0.1079.g6e70778dc9-goog
>>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-27 12:21       ` Heinrich Schuchardt
@ 2021-10-27 13:13         ` Tom Rini
  2021-10-31 23:46           ` Simon Glass
  2021-10-31 23:45         ` Simon Glass
  1 sibling, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-27 13:13 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Simon Glass, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

[-- Attachment #1: Type: text/plain, Size: 2386 bytes --]

On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> 
> 
> On 10/27/21 10:50, Ilias Apalodimas wrote:
> > Hi Simon
> > 
> > How does this patch related to the standard boot series? Shouldn't
> > this be a completely separate patch?
> > 
> > Thanks
> > /Ilias
> > 
> > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > 
> > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > significantly reduce the size of U-Boot binaries. So far it has been
> > > made available for selected ARM boards and sandbox.
> > > 
> > > However, incremental builds are much slower when LTO is used. For example,
> > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > seconds with LTO enabled.
> > > 
> > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > development if needed, for faster builds.
> > > 
> > > Add some documentation about LTO while we are here.
> > > 
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > > 
> > > (no changes since v1)
> > > 
> > >   Makefile                           | 18 +++++++++++++-----
> > >   arch/arm/config.mk                 |  4 ++--
> > >   arch/arm/include/asm/global_data.h |  2 +-
> > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/Makefile b/Makefile
> > > index b79b2319ff6..7057723e046 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > >   KBUILD_LDFLAGS  :=
> > > 
> > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > +LTO_BUILD      ?= y
> 
> This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.

I don't understand why we need this patch at all.  If you want to
disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
be annoying on iterative development.  I have a few different "HACK: DO
NOT PUSH:  ..." things I git am at the start of a branch, depending on
needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
in arch/Kconfig.  We do not need a whole thing around a CONFIG option
that can be disabled in the defconfig, or local .config file even.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-27 11:57     ` Heinrich Schuchardt
@ 2021-10-27 14:08       ` Simon Glass
  0 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-27 14:08 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	U-Boot Mailing List

Hi Heinrich, Ilias,

On Wed, 27 Oct 2021 at 06:03, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
>
>
> On 10/24/21 01:26, Simon Glass wrote:
> > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> >
> > In effect, this provides the same functionality as the 'bootefi' command
> > and shares the same code. But the interface into it is via a bootmeth,
> > so it does not require any special scripts, etc.
> >
> > For now this requires the 'bootefi' command be enabled. Future work may
> > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
>
> Booting via the boot manager must occur without issuing a command on the
> command line. How will the boot method in this file be invoked?
>
> The bootefi command may be implemented by invoking a boot method. A boot
> method invoking a command does not make sense to me.

What do you mean? What other way is there to boot an image at present?

The same thing happens with PXE, for example today, although I have
sent a series to start to change that.

The idea here is that to boot something on U-Boot you use 'bootflow
scan -b' and everything happens automatically. In all cases (at
present) this involves running commands, whether it is bootm, bootefi,
etc.

>
> Best regards
>
> Heinrich
>
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-27  8:35     ` Ilias Apalodimas
@ 2021-10-27 14:09       ` Simon Glass
  2021-10-27 14:47         ` Ilias Apalodimas
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-27 14:09 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Ilias,

On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> >
> > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> >
> > In effect, this provides the same functionality as the 'bootefi' command
> > and shares the same code. But the interface into it is via a bootmeth,
> > so it does not require any special scripts, etc.
> >
> > For now this requires the 'bootefi' command be enabled. Future work may
> > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
>
> I'll leave this up to Heinrich, but personally I wouldn't include this
> patch at all. EFI has it's bootmgr which can handle booting just fine.
> I don't see why we should duplicate the functionality.  The new boot
> method can just have an entry called 'EFI' and then let the existing
> EFI code to decide.

This is needed so that EFI boot is actually invoked. If bootmgr starts
being used then it can still be invoked from standard boot. The point
is that there is a standard way of booting that supports EFI and other
things.

This series is about replacing the scripts we currently have with a
proper C implementation that uses driver model.

> Regards
> /Ilias
>
[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-27 11:38   ` Heinrich Schuchardt
@ 2021-10-27 14:11     ` Simon Glass
  2021-10-28 17:37       ` Peter Robinson
  2021-10-27 15:20     ` François Ozog
  2021-10-27 18:33     ` Simon Glass
  2 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-27 14:11 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Jaehoon Chung, Marek Vasut, Masahiro Yamada, Pavel Herrmann,
	Peng Fan, Stephen Warren, Stephen Warren, François Ozog,
	Heinrich Schuchardt, U-Boot Mailing List

Hi Heinrich,

On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
<heinrich.schuchardt@canonical.com> wrote:
>
>
>
> On 10/24/21 01:25, Simon Glass wrote:
> >
> > The bootflow feature provide a built-in way for U-Boot to automatically
> > boot an Operating System without custom scripting and other customisation.
> > This is called 'standard boot' since it provides a standard way for
> > U-Boot to boot a distro, without scripting.
> >
> > It introduces the following concepts:
> >
> >     - bootdev - a device which can hold a distro
> >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> >                  U-Boot)
> >     - bootflow - a description of how to boot (owned by the distro)
>
> Please, describe why you are suggesting this change.
>
> Replacing a script by a devicetree chunk is just decreasing flexibility
> and increasing complexity. Where is the benefit?
>
> I am missing a description here of where and how a boot flow shall be
> defined. Describing some device-tree binding in patch 40/41 does not
> replace describing the development and usage workflow. Who will provide
> which bootflow information when?
>
> You still have an open discussion with Linaro about the source of
> devicetrees. This discussion needs to be finalized before considering
> this series.
>
> In my view bootflows cannot be defined in the devicetree because prior
> firmware providing a devicetree is completely independent of any distro
> and therefore cannot provide a distro specific bootflow.

There is actually no need to use devicetree here. I think you might
have the wrong end of the stick. It is certainly possible to add nodes
to configure things, if needed, but it works find without any changes
to the devicetree, as you can see from the rpi_3 patch.

There are several aims with this effort:

- Provide a standard way to boot anything on U-Boot, that everyone can
plug into (distros, board vendors, people using a custom flow)
- Move all this stuff out of the environment so we can move to a
text-based environment that doesn't rely on ad-hoc CONFIG options
   (this unblocks the 7-year-old CONFIG migration)
- Add proper tests to cover this important functionality (the scripts
have no tests)
   (this makes development much easier and faster)
- Provide a path to booting more 'directly' without needing the CLI
(which adds size / security risk)

This initial series is not the end of the matter. I expect various
other people will contribute to cover their use cases and additional
features, but at least now we have good basis for this development and
innovation.

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-27 14:09       ` Simon Glass
@ 2021-10-27 14:47         ` Ilias Apalodimas
  2021-10-27 18:34           ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-27 14:47 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Simon,

On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> Hi Ilias,
> 
> On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > >
> > > In effect, this provides the same functionality as the 'bootefi' command
> > > and shares the same code. But the interface into it is via a bootmeth,
> > > so it does not require any special scripts, etc.
> > >
> > > For now this requires the 'bootefi' command be enabled. Future work may
> > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> >
> > I'll leave this up to Heinrich, but personally I wouldn't include this
> > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > I don't see why we should duplicate the functionality.  The new boot
> > method can just have an entry called 'EFI' and then let the existing
> > EFI code to decide.
> 
> This is needed so that EFI boot is actually invoked. If bootmgr starts
> being used then it can still be invoked from standard boot. The point
> is that there is a standard way of booting that supports EFI and other
> things.

This patch tries to reason about the default naming EFI imposes on it's 
boot files. distro_efi_read_bootflow() will try to find files following the
EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are 
found it will try to boot them right?  That's not the right thing to do though.
On the EFI spec these files are tried if no Boot#### variables are found.  
So we can get rid of this entirely,  add a dummy entry on the bootflow that 
says 'boot the efi manager' (which is what the next patch does).  

The efibootmgr then will check Boot#### variables and if none are found,
it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
essentially offering identical functionality.

Regards
/Ilias
> 
> This series is about replacing the scripts we currently have with a
> proper C implementation that uses driver model.
> 
> > Regards
> > /Ilias
> >
> [..]
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-27 11:38   ` Heinrich Schuchardt
  2021-10-27 14:11     ` Simon Glass
@ 2021-10-27 15:20     ` François Ozog
  2021-10-27 18:33     ` Simon Glass
  2 siblings, 0 replies; 116+ messages in thread
From: François Ozog @ 2021-10-27 15:20 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Simon Glass, Michal Simek, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, Heinrich Schuchardt, U-Boot Mailing List

Hi Heinrich,

On Wed, 27 Oct 2021 at 13:38, Heinrich Schuchardt <
heinrich.schuchardt@canonical.com> wrote:

>
>
> On 10/24/21 01:25, Simon Glass wrote:
> >
> > The bootflow feature provide a built-in way for U-Boot to automatically
> > boot an Operating System without custom scripting and other
> customisation.
> > This is called 'standard boot' since it provides a standard way for
> > U-Boot to boot a distro, without scripting.
> >
> > It introduces the following concepts:
> >
> >     - bootdev - a device which can hold a distro
> >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> >                  U-Boot)
> >     - bootflow - a description of how to boot (owned by the distro)
>
> Please, describe why you are suggesting this change.
>
> Replacing a script by a devicetree chunk is just decreasing flexibility
> and increasing complexity. Where is the benefit?
>
> I am missing a description here of where and how a boot flow shall be
> defined. Describing some device-tree binding in patch 40/41 does not
> replace describing the development and usage workflow. Who will provide
> which bootflow information when?
>
> You still have an open discussion with Linaro about the source of
> devicetrees. This discussion needs to be finalized before considering
> this series.
>
> In my view bootflows cannot be defined in the devicetree because prior
> firmware providing a devicetree is completely independent of any distro
> and therefore cannot provide a distro specific bootflow.
>
Agreed if we talk about the DT passed to the OS.
There are discussions in System Device Tree to represent partition booting
orchestration information in a System Device Tree.
This information may end-up being integrated in "a" device tree that will
be used only by hypervisor as dynamic config.
The same applies to secure world partitions: manifest are declared in "a"
device tree that is consumed only by secure hypervisor (hafnium for the
moment) as dynamic configuration, passed as a separate entity from a FIP
section (I think it is TOS_CONFIG)
https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html
The other pattern is firmware component DT binding can be standardized
separately from platform device tree.

>
> Best regards
>
> Heinrich
>
> >
> > This series provides an implementation of these, enabled to scan for
> > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > similiarly to the existing script-based approach, but is native to
> > U-Boot.
> >
> > With this we can boot on a Raspberry Pi 3 with just one command:
> >
> >     bootflow scan -lb
> >
> > which means to scan, listing (-l) each bootflow and trying to boot each
> > one (-b). The final patch shows this.
> >
> > With a standard way to identify boot devices, booting become easier. It
> > also should be possible to support U-Boot scripts, for backwards
> > compatibility only.
> >
> > This series relies on the PXE clean-up series, posted here:
> >
> >     https://patchwork.ozlabs.org/project/uboot/list/?series=267078
> >
> > For documentation, see the 'doc' patch.
> >
> > For version 2, a new naming scheme is used as above:
> >
> >     - bootdev is used instead of bootdevice, because 'device' is
> overused,
> >         is everywhere in U-Boot, can be confused with udevice
> >     - bootmeth - because 'method' is too vanilla, appears 1300 times in
> >         U-Boot
> >
> > Also in version 2, drivers are introduced for the boot methods, to make
> > it more extensible. Booting a custom OS is simply a matter of creating a
> > bootmeth for it and implementing the read_file() and boot() methods.
> >
> > The design is described in these two documents:
> >
> >
> https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> >
> >
> https://drive.google.com/file/d/1kTrflO9vvGlKp-ZH_jlgb9TY3WYG6FF9/view?usp=sharing
> >
> > The series is available at u-boot-dm/bme-working
> >
> > Sample log on rpi_3_32b:
> >
> > U-Boot 2021.10-rc2-00043-gccd453aa918-dirty (Aug 28 2021 - 13:58:46
> -0600)
> >
> > DRAM:  992 MiB
> > RPI 3 Model B (0xa22082)
> > MMC:   mmc@7e202000: 0, sdhci@7e300000: 1
> > Loading Environment from FAT... Unable to read "uboot.env" from
> mmc0:1... In:    serial
> > Out:   vidconsole
> > Err:   vidconsole
> > Net:   No ethernet found.
> > starting USB...
> > Bus usb@7e980000: USB DWC2
> > scanning bus usb@7e980000 for devices... usb_kbd usb_kbd: Timeout poll
> on interrupt endpoint
> > Failed to get keyboard state from device 0c40:8000
> > 4 USB Device(s) found
> >         scanning usb for storage devices... 0 Storage Device(s) found
> > Hit any key to stop autoboot:  0
> > Scanning for bootflows in all bootmethods
> > Seq  Type         State   Uclass    Part  Name
> Filename
> > ---  -----------  ------  --------  ----  ------------------------
> ----------------
> > Scanning bootmethod 'mmc@7e202000.bootmethod':
> >    0  efi-loader   loaded  mmc          1  mmc@7e202000.bootmethod.p
> efi/boot/bootarm.efi
> > ** Booting bootflow 'mmc@7e202000.bootmethod.part_1'
> > Scanning disk mmc@7e202000.blk...
> > ** Unrecognized filesystem type **
> > Card did not respond to voltage select! : -110
> > Scanning disk sdhci@7e300000.blk...
> > Disk sdhci@7e300000.blk not ready
> > Found 4 disks
> > No EFI system partition
> > Booting /efi\boot
> > Waiting for Ethernet connection... done.
> >
> >        Fedora (5.11.12-300.fc34.armv7hl) 34 (Workstation Edition)
> >        UEFI Firmware Settings
> >
> >        Use the ▲ and ▼ keys to change the selection.
> >        Press 'e' to edit the selected item, or 'c' for a command prompt.
> Press Escape to return to the previous menu.
> >     The selected entry will be started automatically in 0s.
> >
> > Changes in v2:
> > - Free the memory buffer, to avoid running out of memory
> > - Unmap the file
> > - Reorder struct sandbox_mmc_priv
> >
> > Simon Glass (41):
> >    lib: Add a way to find the postiion of a trailing number
> >    Makefile: Allow LTO to be disabled for a build
> >    test/py: Allow passing input to a program
> >    sandbox: Support unmapping a file
> >    sandbox: mmc: Support a backing file
> >    mmc: Allow for children other than the block device
> >    mbr: Correct verification check
> >    disk: part_dos: Fix a NULL pointer error
> >    common: Allow a smaller console-recording pre-reloc
> >    dm: core: Add tests for stringlist functions
> >    dm: core: Fix handling of uclass pre_unbind method
> >    dm: core: Fix up string-function documentation
> >    dm: core: Add a way to obtain a string list
> >    dm: core: Allow finding children / uclasses by partial name
> >    dm: core: Add a way to count the devices in a uclass
> >    sandbox: Enable HEXDUMP for sandbox_flattree
> >    test/py: Relax the naming rules for unit tests
> >    test/py: Raise a ValueError if a command fails
> >    bootstd: Add the concept of a bootflow
> >    bootstd: Add the bootstd uclass and core implementation
> >    bootstd: Add the bootdev uclass
> >    bootstd: Add the bootmeth uclass and helpers
> >    bootstd: Add support for bootflows
> >    bootstd: Add a bootdev command
> >    bootstd: Add a bootflow ommand
> >    bootstd: Add a bootmeth command
> >    bootstd: Add an implementation of distro boot
> >    bootstd: mmc: Add a bootdev driver
> >    bootstd: ethernet: Add a bootdev driver
> >    bootstd: Add an implementation of distro PXE boot
> >    bootstd: Add an implementation of EFI boot
> >    bootstd: Add a system bootdev for strange boot methods
> >    bootstd: Add an implementation of EFI bootmgr
> >    bootstd: Add a sandbox bootmeth driver
> >    bootstd: usb: Add a bootdev driver
> >    test: fastboot: Avoid using mmc1
> >    test: dm: Restart USB before assuming it is stopped
> >    bootstd: Add tests for bootstd including all uclasses
> >    bootstd: Add setup for the bootflow tests
> >    bootstd: doc: Add documentation
> >    RFC: Switch rpi over to use bootstd
> >
> >   MAINTAINERS                                  |  21 +
> >   Makefile                                     |  18 +-
> >   arch/arm/config.mk                           |   4 +-
> >   arch/arm/include/asm/global_data.h           |   2 +-
> >   arch/sandbox/cpu/os.c                        |  10 +
> >   arch/sandbox/dts/test.dts                    |  19 +
> >   boot/Kconfig                                 |  77 ++-
> >   boot/Makefile                                |  14 +
> >   boot/bootdev-uclass.c                        | 439 ++++++++++++++
> >   boot/bootflow.c                              | 576 ++++++++++++++++++
> >   boot/bootmeth-uclass.c                       |  59 ++
> >   boot/bootmeth_distro.c                       | 217 +++++++
> >   boot/bootmeth_efi.c                          | 263 ++++++++
> >   boot/bootmeth_efi_mgr.c                      |  84 +++
> >   boot/bootmeth_pxe.c                          | 183 ++++++
> >   boot/bootmeth_sandbox.c                      |  67 +++
> >   boot/bootstd-uclass.c                        | 176 ++++++
> >   boot/system_bootdev.c                        |  64 ++
> >   cmd/Kconfig                                  |  15 +
> >   cmd/Makefile                                 |   1 +
> >   cmd/bootdev.c                                | 120 ++++
> >   cmd/bootflow.c                               | 386 ++++++++++++
> >   cmd/bootmeth.c                               | 158 +++++
> >   cmd/mbr.c                                    |   8 +-
> >   common/Kconfig                               |  10 +
> >   common/console.c                             |   4 +-
> >   common/usb_storage.c                         |  12 +
> >   configs/amcore_defconfig                     |   1 +
> >   configs/rcar3_salvator-x_defconfig           |   1 +
> >   configs/sandbox_defconfig                    |   3 +-
> >   configs/sandbox_flattree_defconfig           |   4 +-
> >   configs/tbs2910_defconfig                    |   1 +
> >   disk/part_dos.c                              |  10 +-
> >   doc/build/gcc.rst                            |  17 +
> >   doc/develop/bootstd.rst                      | 600 +++++++++++++++++++
> >   doc/develop/distro.rst                       |   3 +
> >   doc/develop/index.rst                        |   1 +
> >   doc/device-tree-bindings/bootdev.txt         |  26 +
> >   doc/device-tree-bindings/bootmeth.txt        |  31 +
> >   doc/device-tree-bindings/bootstd.txt         |  36 ++
> >   doc/device-tree-bindings/mmc/sandbox,mmc.txt |  18 +
> >   doc/usage/bootdev.rst                        | 135 +++++
> >   doc/usage/bootflow.rst                       | 427 +++++++++++++
> >   doc/usage/bootmeth.rst                       | 106 ++++
> >   doc/usage/index.rst                          |   3 +
> >   drivers/core/device-remove.c                 |   9 +-
> >   drivers/core/device.c                        |  13 +-
> >   drivers/core/of_access.c                     |   3 +-
> >   drivers/core/ofnode.c                        |  26 +
> >   drivers/core/read.c                          |   6 +
> >   drivers/core/uclass.c                        |  29 +-
> >   drivers/mmc/Makefile                         |   5 +
> >   drivers/mmc/mmc-uclass.c                     |  27 +-
> >   drivers/mmc/mmc_bootdev.c                    |  62 ++
> >   drivers/mmc/sandbox_mmc.c                    |  60 +-
> >   drivers/usb/host/Makefile                    |   4 +
> >   drivers/usb/host/usb_bootdev.c               |  61 ++
> >   include/bootdev.h                            | 258 ++++++++
> >   include/bootflow.h                           | 304 ++++++++++
> >   include/bootmeth.h                           | 156 +++++
> >   include/bootstd.h                            |  80 +++
> >   include/configs/rpi.h                        |  41 +-
> >   include/distro.h                             |  24 +
> >   include/dm/device.h                          |  12 +
> >   include/dm/ofnode.h                          |  24 +-
> >   include/dm/read.h                            |  28 +
> >   include/dm/uclass-id.h                       |   3 +
> >   include/dm/uclass-internal.h                 |  14 +-
> >   include/dm/uclass.h                          |  17 +
> >   include/mmc.h                                |  12 +-
> >   include/os.h                                 |   9 +
> >   include/test/suites.h                        |   2 +
> >   include/vsprintf.h                           |  18 +
> >   lib/strto.c                                  |  14 +-
> >   net/Kconfig                                  |   9 +
> >   net/Makefile                                 |   1 +
> >   net/eth-uclass.c                             |   8 +
> >   net/eth_bootdev.c                            | 101 ++++
> >   test/Makefile                                |   1 +
> >   test/boot/Makefile                           |   5 +
> >   test/boot/bootdev.c                          | 200 +++++++
> >   test/boot/bootflow.c                         | 398 ++++++++++++
> >   test/boot/bootmeth.c                         |  90 +++
> >   test/boot/bootstd_common.c                   |  35 ++
> >   test/boot/bootstd_common.h                   |  27 +
> >   test/cmd_ut.c                                |   7 +
> >   test/dm/blk.c                                |   6 +
> >   test/dm/fastboot.c                           |   4 +-
> >   test/dm/ofnode.c                             |  96 +++
> >   test/py/conftest.py                          |   2 +-
> >   test/py/multiplexed_log.py                   |  10 +-
> >   test/py/tests/bootstd/mmc1.img.xz            | Bin 0 -> 4448 bytes
> >   test/py/tests/test_ut.py                     | 103 ++++
> >   test/py/u_boot_utils.py                      |   5 +-
> >   94 files changed, 6765 insertions(+), 94 deletions(-)
> >   create mode 100644 boot/bootdev-uclass.c
> >   create mode 100644 boot/bootflow.c
> >   create mode 100644 boot/bootmeth-uclass.c
> >   create mode 100644 boot/bootmeth_distro.c
> >   create mode 100644 boot/bootmeth_efi.c
> >   create mode 100644 boot/bootmeth_efi_mgr.c
> >   create mode 100644 boot/bootmeth_pxe.c
> >   create mode 100644 boot/bootmeth_sandbox.c
> >   create mode 100644 boot/bootstd-uclass.c
> >   create mode 100644 boot/system_bootdev.c
> >   create mode 100644 cmd/bootdev.c
> >   create mode 100644 cmd/bootflow.c
> >   create mode 100644 cmd/bootmeth.c
> >   create mode 100644 doc/develop/bootstd.rst
> >   create mode 100644 doc/device-tree-bindings/bootdev.txt
> >   create mode 100644 doc/device-tree-bindings/bootmeth.txt
> >   create mode 100644 doc/device-tree-bindings/bootstd.txt
> >   create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt
> >   create mode 100644 doc/usage/bootdev.rst
> >   create mode 100644 doc/usage/bootflow.rst
> >   create mode 100644 doc/usage/bootmeth.rst
> >   create mode 100644 drivers/mmc/mmc_bootdev.c
> >   create mode 100644 drivers/usb/host/usb_bootdev.c
> >   create mode 100644 include/bootdev.h
> >   create mode 100644 include/bootflow.h
> >   create mode 100644 include/bootmeth.h
> >   create mode 100644 include/bootstd.h
> >   create mode 100644 include/distro.h
> >   create mode 100644 net/eth_bootdev.c
> >   create mode 100644 test/boot/Makefile
> >   create mode 100644 test/boot/bootdev.c
> >   create mode 100644 test/boot/bootflow.c
> >   create mode 100644 test/boot/bootmeth.c
> >   create mode 100644 test/boot/bootstd_common.c
> >   create mode 100644 test/boot/bootstd_common.h
> >   create mode 100644 test/py/tests/bootstd/mmc1.img.xz
> >
>


-- 
François-Frédéric Ozog | *Director Business Development*
T: +33.67221.6485
francois.ozog@linaro.org | Skype: ffozog

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-27 11:38   ` Heinrich Schuchardt
  2021-10-27 14:11     ` Simon Glass
  2021-10-27 15:20     ` François Ozog
@ 2021-10-27 18:33     ` Simon Glass
  2 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-27 18:33 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Michal Simek, Tom Rini, Ilias Apalodimas, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Jaehoon Chung, Marek Vasut, Masahiro Yamada, Pavel Herrmann,
	Peng Fan, Stephen Warren, Stephen Warren, François Ozog,
	Heinrich Schuchardt, U-Boot Mailing List

Hi Heinrich,

On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
<heinrich.schuchardt@canonical.com> wrote:
>
>
>
> On 10/24/21 01:25, Simon Glass wrote:
> >
> > The bootflow feature provide a built-in way for U-Boot to automatically
> > boot an Operating System without custom scripting and other customisation.
> > This is called 'standard boot' since it provides a standard way for
> > U-Boot to boot a distro, without scripting.
> >
> > It introduces the following concepts:
> >
> >     - bootdev - a device which can hold a distro
> >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> >                  U-Boot)
> >     - bootflow - a description of how to boot (owned by the distro)
>
> Please, describe why you are suggesting this change.
>
> Replacing a script by a devicetree chunk is just decreasing flexibility
> and increasing complexity. Where is the benefit?

See previous email in thread. Continuing here on a few of your other points...

>
> I am missing a description here of where and how a boot flow shall be
> defined. Describing some device-tree binding in patch 40/41 does not
> replace describing the development and usage workflow. Who will provide
> which bootflow information when?

We already have this with distro boot, so nothing really changes
there. Think of this as a generalised 'standard boot' implementation,
which can support distro boot and anything else we need in the future.

There is nothing required in the devicetree for normal operation.

>
> You still have an open discussion with Linaro about the source of
> devicetrees. This discussion needs to be finalized before considering
> this series.

Why is that? They don't seem to be at all related to me.

>
> In my view bootflows cannot be defined in the devicetree because prior
> firmware providing a devicetree is completely independent of any distro
> and therefore cannot provide a distro specific bootflow.

See previous post, they are not defined in the devicetree. Can you
suggest how I can change the language to make that clear?

Regards,
Simon

>
> >
> > This series provides an implementation of these, enabled to scan for
> > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > similiarly to the existing script-based approach, but is native to
> > U-Boot.
> >
> > With this we can boot on a Raspberry Pi 3 with just one command:
> >
> >     bootflow scan -lb
> >
> > which means to scan, listing (-l) each bootflow and trying to boot each
> > one (-b). The final patch shows this.
> >
> > With a standard way to identify boot devices, booting become easier. It
> > also should be possible to support U-Boot scripts, for backwards
> > compatibility only.
> >
> >
[..]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-27 14:47         ` Ilias Apalodimas
@ 2021-10-27 18:34           ` Simon Glass
  2021-10-29  5:45             ` Ilias Apalodimas
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-27 18:34 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Ilias,

On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > Hi Ilias,
> >
> > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > >
> > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > so it does not require any special scripts, etc.
> > > >
> > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > >
> > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > I don't see why we should duplicate the functionality.  The new boot
> > > method can just have an entry called 'EFI' and then let the existing
> > > EFI code to decide.
> >
> > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > being used then it can still be invoked from standard boot. The point
> > is that there is a standard way of booting that supports EFI and other
> > things.
>
> This patch tries to reason about the default naming EFI imposes on it's
> boot files. distro_efi_read_bootflow() will try to find files following the
> EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> found it will try to boot them right?  That's not the right thing to do though.
> On the EFI spec these files are tried if no Boot#### variables are found.
> So we can get rid of this entirely,  add a dummy entry on the bootflow that
> says 'boot the efi manager' (which is what the next patch does).
>
> The efibootmgr then will check Boot#### variables and if none are found,
> it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> essentially offering identical functionality.

Yes that's fine, and when EFI's boot manager is in use I have a driver
for that too, as you can see in the other patch. We may need to adjust
the order, by the sound of it, if it needs to run before EFI things.
But that is easy enough.

But we do need to provide the existing functionality for now, as I
understand it.

> > This series is about replacing the scripts we currently have with a
> > proper C implementation that uses driver model.
> >

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 41/41] RFC: Switch rpi over to use bootstd
  2021-10-23 23:26   ` [PATCH v2 41/41] RFC: Switch rpi over to use bootstd Simon Glass
@ 2021-10-28 15:13     ` Tom Rini
  2021-10-28 16:43     ` Tom Rini
  1 sibling, 0 replies; 116+ messages in thread
From: Tom Rini @ 2021-10-28 15:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

[-- Attachment #1: Type: text/plain, Size: 343 bytes --]

On Sat, Oct 23, 2021 at 05:26:35PM -0600, Simon Glass wrote:

> Switch this over, for testing purposes.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
[snip]
> +	"ramdisk_addr_r=0x02700000\0" \
> +	"ethaddr=b8:27:eb:a6:61:e1\0"

I know this is just testing, but, you cannot hard-code the ethaddr to
the environment.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (42 preceding siblings ...)
  2021-10-27 11:38   ` Heinrich Schuchardt
@ 2021-10-28 16:27   ` Tom Rini
  2021-10-28 17:29     ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
                     ` (13 subsequent siblings)
  57 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 16:27 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 1543 bytes --]

On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:

> The bootflow feature provide a built-in way for U-Boot to automatically
> boot an Operating System without custom scripting and other customisation.
> This is called 'standard boot' since it provides a standard way for
> U-Boot to boot a distro, without scripting.
> 
> It introduces the following concepts:
> 
>    - bootdev - a device which can hold a distro
>    - bootmeth - a method to scan a bootdev to find bootflows (owned by
>                 U-Boot)
>    - bootflow - a description of how to boot (owned by the distro)
> 
> This series provides an implementation of these, enabled to scan for
> bootflows from MMC, USB and Ethernet. It supports the existing distro
> boot as well as the EFI loader flow (bootefi/bootmgr). It works
> similiarly to the existing script-based approach, but is native to
> U-Boot.

I'm going to break my feedback down in to a few threads, to hopefully
not confuse things too much.  My first comment is that rpi_arm64 grows
in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
And while there's a few small changes in the pxe cleanup I'm going to
re-investigate on their own, it's really just this series, right here,
adding tons of code.  To replace an admittedly complex bit of
environment scripting, with C.  It's not even the earlier parts of the
series to clean up / prepare, it starts at "bootstd: Add the bootstd
uclass and core implementation" and keeps going from there.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 41/41] RFC: Switch rpi over to use bootstd
  2021-10-23 23:26   ` [PATCH v2 41/41] RFC: Switch rpi over to use bootstd Simon Glass
  2021-10-28 15:13     ` Tom Rini
@ 2021-10-28 16:43     ` Tom Rini
  2021-10-28 17:16       ` Simon Glass
  1 sibling, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 16:43 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

[-- Attachment #1: Type: text/plain, Size: 647 bytes --]

On Sat, Oct 23, 2021 at 05:26:35PM -0600, Simon Glass wrote:

> Switch this over, for testing purposes.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
[snip]
>  #define CONFIG_EXTRA_ENV_SETTINGS \
>  	"dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \
> +	"boot_targets=mmc0 mmc1 usb0 pxe dhcp\0" \

So, based on this patch I went "oh, so we can still easily control the
device order, per board and also for users to tweak".  Then I looked for
where boot_targets was used, saw it wasn't and looked over the
documentation patch previous to this.   That's not looking easier to
configure than what we have now either.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 41/41] RFC: Switch rpi over to use bootstd
  2021-10-28 16:43     ` Tom Rini
@ 2021-10-28 17:16       ` Simon Glass
  2021-10-28 17:29         ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-28 17:16 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

Hi Tom,

On Thu, 28 Oct 2021 at 10:43, Tom Rini <trini@konsulko.com> wrote:
>
> On Sat, Oct 23, 2021 at 05:26:35PM -0600, Simon Glass wrote:
>
> > Switch this over, for testing purposes.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> [snip]
> >  #define CONFIG_EXTRA_ENV_SETTINGS \
> >       "dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \
> > +     "boot_targets=mmc0 mmc1 usb0 pxe dhcp\0" \
>
> So, based on this patch I went "oh, so we can still easily control the
> device order, per board and also for users to tweak".  Then I looked for
> where boot_targets was used, saw it wasn't and looked over the
> documentation patch previous to this.   That's not looking easier to
> configure than what we have now either.

Yes, I did originally implement the boot_targets env var, then decided
it should be in the device tree instead, since you can do:

bootstd {
   compatible = "u-boot,boot-std";
   bootdev-order = "mmc2", "mmc1";
};

(with nothing else in the devicetree)

I made this change since it seems that boot_targets is always set in
the env and should not be touched by the distro. If that is not
correct I can bring the code back...

BTW the MAC address was just for my testing.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 41/41] RFC: Switch rpi over to use bootstd
  2021-10-28 17:16       ` Simon Glass
@ 2021-10-28 17:29         ` Tom Rini
  0 siblings, 0 replies; 116+ messages in thread
From: Tom Rini @ 2021-10-28 17:29 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

[-- Attachment #1: Type: text/plain, Size: 2082 bytes --]

On Thu, Oct 28, 2021 at 11:16:31AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 28 Oct 2021 at 10:43, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Sat, Oct 23, 2021 at 05:26:35PM -0600, Simon Glass wrote:
> >
> > > Switch this over, for testing purposes.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > [snip]
> > >  #define CONFIG_EXTRA_ENV_SETTINGS \
> > >       "dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \
> > > +     "boot_targets=mmc0 mmc1 usb0 pxe dhcp\0" \
> >
> > So, based on this patch I went "oh, so we can still easily control the
> > device order, per board and also for users to tweak".  Then I looked for
> > where boot_targets was used, saw it wasn't and looked over the
> > documentation patch previous to this.   That's not looking easier to
> > configure than what we have now either.
> 
> Yes, I did originally implement the boot_targets env var, then decided
> it should be in the device tree instead, since you can do:
> 
> bootstd {
>    compatible = "u-boot,boot-std";
>    bootdev-order = "mmc2", "mmc1";
> };
> 
> (with nothing else in the devicetree)
> 
> I made this change since it seems that boot_targets is always set in
> the env and should not be touched by the distro. If that is not
> correct I can bring the code back...

Aside from what I said to the cover letter, I think all of the device
tree stuff is taking it the wrong direction.  The environment is
something that can easily be manipulated in a persistent and well
understood manner by a number of tools, and is done so today.  Defining
the boot order to start with in a device tree fragment is going to be
annoying for all of the platforms where the device tree comes from
somewhere else.  But it's going to suck even more for users to
manipulate (now that we've installed, we don't want to probe the whole
world normally, just check where it's installed).

I'm not seeing this as a better step forward at all right now, sorry.

> BTW the MAC address was just for my testing.

Hoped so, thanks :)

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 16:27   ` Tom Rini
@ 2021-10-28 17:29     ` Simon Glass
  2021-10-28 17:52       ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-28 17:29 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Tom,

On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
>
> On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
>
> > The bootflow feature provide a built-in way for U-Boot to automatically
> > boot an Operating System without custom scripting and other customisation.
> > This is called 'standard boot' since it provides a standard way for
> > U-Boot to boot a distro, without scripting.
> >
> > It introduces the following concepts:
> >
> >    - bootdev - a device which can hold a distro
> >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> >                 U-Boot)
> >    - bootflow - a description of how to boot (owned by the distro)
> >
> > This series provides an implementation of these, enabled to scan for
> > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > similiarly to the existing script-based approach, but is native to
> > U-Boot.
>
> I'm going to break my feedback down in to a few threads, to hopefully
> not confuse things too much.  My first comment is that rpi_arm64 grows
> in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> And while there's a few small changes in the pxe cleanup I'm going to
> re-investigate on their own, it's really just this series, right here,
> adding tons of code.  To replace an admittedly complex bit of
> environment scripting, with C.  It's not even the earlier parts of the
> series to clean up / prepare, it starts at "bootstd: Add the bootstd
> uclass and core implementation" and keeps going from there.

Yes it does add a lot of code, although it is a lot less if the
commands are disabled or simplified, e.g. to only support 'bootflow
scan -b'. At the moment it enables all dev features.

It does save a small amount of data. E.g. rpi_3_32b environment goes
drops by 3.5KB.

We should compare this with the EFI support which is about 90KB, as I recall.

If we continue down the path of making this feature use U-Boot
functions directly, instead the command line, I suspect we can save
quite a bit more, since there is a lot of overhead with these
commands. At present it is impossible to boot without CONFIG_CMDLINE
enabled, for example.

In any case, I think this feature is filling a gap in U-Boot since at
present everything about boot is ad-hoc. This gives us a base to build
on. Nothing is for free.

Anyway, I can look at what the minimum size is with the above points
and send that info through.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-27 14:11     ` Simon Glass
@ 2021-10-28 17:37       ` Peter Robinson
  2021-10-28 17:47         ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Peter Robinson @ 2021-10-28 17:37 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, Michal Simek, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, Heinrich Schuchardt,
	U-Boot Mailing List

On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Heinrich,
>
> On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> <heinrich.schuchardt@canonical.com> wrote:
> >
> >
> >
> > On 10/24/21 01:25, Simon Glass wrote:
> > >
> > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > boot an Operating System without custom scripting and other customisation.
> > > This is called 'standard boot' since it provides a standard way for
> > > U-Boot to boot a distro, without scripting.
> > >
> > > It introduces the following concepts:
> > >
> > >     - bootdev - a device which can hold a distro
> > >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > >                  U-Boot)
> > >     - bootflow - a description of how to boot (owned by the distro)
> >
> > Please, describe why you are suggesting this change.
> >
> > Replacing a script by a devicetree chunk is just decreasing flexibility
> > and increasing complexity. Where is the benefit?
> >
> > I am missing a description here of where and how a boot flow shall be
> > defined. Describing some device-tree binding in patch 40/41 does not
> > replace describing the development and usage workflow. Who will provide
> > which bootflow information when?
> >
> > You still have an open discussion with Linaro about the source of
> > devicetrees. This discussion needs to be finalized before considering
> > this series.
> >
> > In my view bootflows cannot be defined in the devicetree because prior
> > firmware providing a devicetree is completely independent of any distro
> > and therefore cannot provide a distro specific bootflow.
>
> There is actually no need to use devicetree here. I think you might
> have the wrong end of the stick. It is certainly possible to add nodes
> to configure things, if needed, but it works find without any changes
> to the devicetree, as you can see from the rpi_3 patch.
>
> There are several aims with this effort:
>
> - Provide a standard way to boot anything on U-Boot, that everyone can
> plug into (distros, board vendors, people using a custom flow)

I as a distro maintainer don't want this, we already get the "standard
way to boot" from UEFI, this just feels like another unnecessary
abstraction to that.

I do actually like a bunch of the ideas in here, random scripts in
distro_boot were a big step forward for straight forward booting a
decade or so when everything prior was random board specific boot.scr
and uImage but things have evolved into booting via UEFI which is very
standard across the general purpose compute devices style industries
and clearing up the random behind the scenes hush scripting is
definitely long overdue but I don't feel there needs to be another
layer of unnecessary indirection here.

> - Move all this stuff out of the environment so we can move to a
> text-based environment that doesn't rely on ad-hoc CONFIG options
>    (this unblocks the 7-year-old CONFIG migration)
> - Add proper tests to cover this important functionality (the scripts
> have no tests)
>    (this makes development much easier and faster)
> - Provide a path to booting more 'directly' without needing the CLI
> (which adds size / security risk)
>
> This initial series is not the end of the matter. I expect various
> other people will contribute to cover their use cases and additional
> features, but at least now we have good basis for this development and
> innovation.
>
> [..]
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:37       ` Peter Robinson
@ 2021-10-28 17:47         ` Tom Rini
  2021-10-28 17:50           ` Peter Robinson
  2021-10-28 21:40           ` Mark Kettenis
  0 siblings, 2 replies; 116+ messages in thread
From: Tom Rini @ 2021-10-28 17:47 UTC (permalink / raw)
  To: Peter Robinson
  Cc: Simon Glass, Heinrich Schuchardt, Michal Simek, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, Heinrich Schuchardt,
	U-Boot Mailing List

[-- Attachment #1: Type: text/plain, Size: 2653 bytes --]

On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Heinrich,
> >
> > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > <heinrich.schuchardt@canonical.com> wrote:
> > >
> > >
> > >
> > > On 10/24/21 01:25, Simon Glass wrote:
> > > >
> > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > boot an Operating System without custom scripting and other customisation.
> > > > This is called 'standard boot' since it provides a standard way for
> > > > U-Boot to boot a distro, without scripting.
> > > >
> > > > It introduces the following concepts:
> > > >
> > > >     - bootdev - a device which can hold a distro
> > > >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > >                  U-Boot)
> > > >     - bootflow - a description of how to boot (owned by the distro)
> > >
> > > Please, describe why you are suggesting this change.
> > >
> > > Replacing a script by a devicetree chunk is just decreasing flexibility
> > > and increasing complexity. Where is the benefit?
> > >
> > > I am missing a description here of where and how a boot flow shall be
> > > defined. Describing some device-tree binding in patch 40/41 does not
> > > replace describing the development and usage workflow. Who will provide
> > > which bootflow information when?
> > >
> > > You still have an open discussion with Linaro about the source of
> > > devicetrees. This discussion needs to be finalized before considering
> > > this series.
> > >
> > > In my view bootflows cannot be defined in the devicetree because prior
> > > firmware providing a devicetree is completely independent of any distro
> > > and therefore cannot provide a distro specific bootflow.
> >
> > There is actually no need to use devicetree here. I think you might
> > have the wrong end of the stick. It is certainly possible to add nodes
> > to configure things, if needed, but it works find without any changes
> > to the devicetree, as you can see from the rpi_3 patch.
> >
> > There are several aims with this effort:
> >
> > - Provide a standard way to boot anything on U-Boot, that everyone can
> > plug into (distros, board vendors, people using a custom flow)
> 
> I as a distro maintainer don't want this, we already get the "standard
> way to boot" from UEFI, this just feels like another unnecessary
> abstraction to that.

Right.  But part of the problem is "How do I find UEFI".  Something
somewhere needs to be configurable to say where to look, yes?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:47         ` Tom Rini
@ 2021-10-28 17:50           ` Peter Robinson
  2021-10-28 17:59             ` Tom Rini
  2021-10-28 21:40           ` Mark Kettenis
  1 sibling, 1 reply; 116+ messages in thread
From: Peter Robinson @ 2021-10-28 17:50 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, Heinrich Schuchardt, Michal Simek, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, Heinrich Schuchardt,
	U-Boot Mailing List

On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Heinrich,
> > >
> > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > <heinrich.schuchardt@canonical.com> wrote:
> > > >
> > > >
> > > >
> > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > >
> > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > boot an Operating System without custom scripting and other customisation.
> > > > > This is called 'standard boot' since it provides a standard way for
> > > > > U-Boot to boot a distro, without scripting.
> > > > >
> > > > > It introduces the following concepts:
> > > > >
> > > > >     - bootdev - a device which can hold a distro
> > > > >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > >                  U-Boot)
> > > > >     - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > Please, describe why you are suggesting this change.
> > > >
> > > > Replacing a script by a devicetree chunk is just decreasing flexibility
> > > > and increasing complexity. Where is the benefit?
> > > >
> > > > I am missing a description here of where and how a boot flow shall be
> > > > defined. Describing some device-tree binding in patch 40/41 does not
> > > > replace describing the development and usage workflow. Who will provide
> > > > which bootflow information when?
> > > >
> > > > You still have an open discussion with Linaro about the source of
> > > > devicetrees. This discussion needs to be finalized before considering
> > > > this series.
> > > >
> > > > In my view bootflows cannot be defined in the devicetree because prior
> > > > firmware providing a devicetree is completely independent of any distro
> > > > and therefore cannot provide a distro specific bootflow.
> > >
> > > There is actually no need to use devicetree here. I think you might
> > > have the wrong end of the stick. It is certainly possible to add nodes
> > > to configure things, if needed, but it works find without any changes
> > > to the devicetree, as you can see from the rpi_3 patch.
> > >
> > > There are several aims with this effort:
> > >
> > > - Provide a standard way to boot anything on U-Boot, that everyone can
> > > plug into (distros, board vendors, people using a custom flow)
> >
> > I as a distro maintainer don't want this, we already get the "standard
> > way to boot" from UEFI, this just feels like another unnecessary
> > abstraction to that.
>
> Right.  But part of the problem is "How do I find UEFI".  Something
> somewhere needs to be configurable to say where to look, yes?

Is this question from the board PoV, the developer of U-Boot or the
distro trying to boot?

If you mean from a boot flow PoV for UEFI to find the HW that contains
the OS to boot I thought that was handled elsewhere in the series.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:29     ` Simon Glass
@ 2021-10-28 17:52       ` Tom Rini
  2021-10-28 18:13         ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 17:52 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 3818 bytes --]

On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> >
> > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > boot an Operating System without custom scripting and other customisation.
> > > This is called 'standard boot' since it provides a standard way for
> > > U-Boot to boot a distro, without scripting.
> > >
> > > It introduces the following concepts:
> > >
> > >    - bootdev - a device which can hold a distro
> > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > >                 U-Boot)
> > >    - bootflow - a description of how to boot (owned by the distro)
> > >
> > > This series provides an implementation of these, enabled to scan for
> > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > similiarly to the existing script-based approach, but is native to
> > > U-Boot.
> >
> > I'm going to break my feedback down in to a few threads, to hopefully
> > not confuse things too much.  My first comment is that rpi_arm64 grows
> > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > And while there's a few small changes in the pxe cleanup I'm going to
> > re-investigate on their own, it's really just this series, right here,
> > adding tons of code.  To replace an admittedly complex bit of
> > environment scripting, with C.  It's not even the earlier parts of the
> > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > uclass and core implementation" and keeps going from there.
> 
> Yes it does add a lot of code, although it is a lot less if the
> commands are disabled or simplified, e.g. to only support 'bootflow
> scan -b'. At the moment it enables all dev features.

OK, for the next go-round yes, please show what a typical enablement
would look like on Pi, for example.

> It does save a small amount of data. E.g. rpi_3_32b environment goes
> drops by 3.5KB.

So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
win.

> We should compare this with the EFI support which is about 90KB, as I recall.

No, we shouldn't.  This isn't about replacing EFI, this is about
replacing the generic distro boot macros, so that's what the size
comparison is to.  At the end of the day, and looking towards non-legacy
uses, a big common use case is "Find the EFI app to run".

> If we continue down the path of making this feature use U-Boot
> functions directly, instead the command line, I suspect we can save
> quite a bit more, since there is a lot of overhead with these
> commands. At present it is impossible to boot without CONFIG_CMDLINE
> enabled, for example.

Yes, this should be using the API and not the command interface.

> In any case, I think this feature is filling a gap in U-Boot since at
> present everything about boot is ad-hoc. This gives us a base to build
> on. Nothing is for free.

I disagree.  At present, booting is either intentionally per-board, or
it's using the generic distro boot framework.  That framework is what to
further build on or perhaps make more readily simplified (for example,
making it just be "scan around for EFI" or just be "scan around of
extlinux.conf").

> Anyway, I can look at what the minimum size is with the above points
> and send that info through.

I looked at the PXE stuff, and I think the minimal growth there ends up
being reasonable, fwiw.  It comes down to adding sanity checks in places
where the code wasn't always sanity checking, as you reduced
duplication.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:50           ` Peter Robinson
@ 2021-10-28 17:59             ` Tom Rini
  2021-10-28 18:09               ` Heinrich Schuchardt
  2021-10-28 18:17               ` François Ozog
  0 siblings, 2 replies; 116+ messages in thread
From: Tom Rini @ 2021-10-28 17:59 UTC (permalink / raw)
  To: Peter Robinson
  Cc: Simon Glass, Heinrich Schuchardt, Michal Simek, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, Heinrich Schuchardt,
	U-Boot Mailing List

[-- Attachment #1: Type: text/plain, Size: 4022 bytes --]

On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
> On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Heinrich,
> > > >
> > > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > > <heinrich.schuchardt@canonical.com> wrote:
> > > > >
> > > > >
> > > > >
> > > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > > >
> > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > U-Boot to boot a distro, without scripting.
> > > > > >
> > > > > > It introduces the following concepts:
> > > > > >
> > > > > >     - bootdev - a device which can hold a distro
> > > > > >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > >                  U-Boot)
> > > > > >     - bootflow - a description of how to boot (owned by the distro)
> > > > >
> > > > > Please, describe why you are suggesting this change.
> > > > >
> > > > > Replacing a script by a devicetree chunk is just decreasing flexibility
> > > > > and increasing complexity. Where is the benefit?
> > > > >
> > > > > I am missing a description here of where and how a boot flow shall be
> > > > > defined. Describing some device-tree binding in patch 40/41 does not
> > > > > replace describing the development and usage workflow. Who will provide
> > > > > which bootflow information when?
> > > > >
> > > > > You still have an open discussion with Linaro about the source of
> > > > > devicetrees. This discussion needs to be finalized before considering
> > > > > this series.
> > > > >
> > > > > In my view bootflows cannot be defined in the devicetree because prior
> > > > > firmware providing a devicetree is completely independent of any distro
> > > > > and therefore cannot provide a distro specific bootflow.
> > > >
> > > > There is actually no need to use devicetree here. I think you might
> > > > have the wrong end of the stick. It is certainly possible to add nodes
> > > > to configure things, if needed, but it works find without any changes
> > > > to the devicetree, as you can see from the rpi_3 patch.
> > > >
> > > > There are several aims with this effort:
> > > >
> > > > - Provide a standard way to boot anything on U-Boot, that everyone can
> > > > plug into (distros, board vendors, people using a custom flow)
> > >
> > > I as a distro maintainer don't want this, we already get the "standard
> > > way to boot" from UEFI, this just feels like another unnecessary
> > > abstraction to that.
> >
> > Right.  But part of the problem is "How do I find UEFI".  Something
> > somewhere needs to be configurable to say where to look, yes?
> 
> Is this question from the board PoV, the developer of U-Boot or the
> distro trying to boot?
> 
> If you mean from a boot flow PoV for UEFI to find the HW that contains
> the OS to boot I thought that was handled elsewhere in the series.

What I mean is that today looking at Pi we have:
#define BOOT_TARGET_DEVICES(func) \
        BOOT_TARGET_MMC(func) \
        BOOT_TARGET_USB(func) \
        BOOT_TARGET_PXE(func) \
        BOOT_TARGET_DHCP(func)

As the board maintainer set that as the list of places to start looking
for the next payload (say the GRUB EFI binary).  Simon's series replaces
that with I think he said "bootflow scan -b".  And then the above env
portion is replaced with, well, what's documented in patch #40 if you
don't just want to rely on device probe order.

Because we need to have _something_ that says where to look for what,
yes?  Or should that be replaced entirely with efi vars and
BootOrder/BootXXX and "bootefi bootmgr $fdt_addr_r" ?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:59             ` Tom Rini
@ 2021-10-28 18:09               ` Heinrich Schuchardt
  2021-10-28 18:13                 ` Tom Rini
  2021-10-28 18:17               ` François Ozog
  1 sibling, 1 reply; 116+ messages in thread
From: Heinrich Schuchardt @ 2021-10-28 18:09 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, Heinrich Schuchardt, Michal Simek, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, U-Boot Mailing List,
	Peter Robinson

On 10/28/21 7:59 PM, Tom Rini wrote:
> On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
>> On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
>>>
>>> On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
>>>> On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
>>>>>
>>>>> Hi Heinrich,
>>>>>
>>>>> On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
>>>>> <heinrich.schuchardt@canonical.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 10/24/21 01:25, Simon Glass wrote:
>>>>>>>
>>>>>>> The bootflow feature provide a built-in way for U-Boot to automatically
>>>>>>> boot an Operating System without custom scripting and other customisation.
>>>>>>> This is called 'standard boot' since it provides a standard way for
>>>>>>> U-Boot to boot a distro, without scripting.
>>>>>>>
>>>>>>> It introduces the following concepts:
>>>>>>>
>>>>>>>      - bootdev - a device which can hold a distro
>>>>>>>      - bootmeth - a method to scan a bootdev to find bootflows (owned by
>>>>>>>                   U-Boot)
>>>>>>>      - bootflow - a description of how to boot (owned by the distro)
>>>>>>
>>>>>> Please, describe why you are suggesting this change.
>>>>>>
>>>>>> Replacing a script by a devicetree chunk is just decreasing flexibility
>>>>>> and increasing complexity. Where is the benefit?
>>>>>>
>>>>>> I am missing a description here of where and how a boot flow shall be
>>>>>> defined. Describing some device-tree binding in patch 40/41 does not
>>>>>> replace describing the development and usage workflow. Who will provide
>>>>>> which bootflow information when?
>>>>>>
>>>>>> You still have an open discussion with Linaro about the source of
>>>>>> devicetrees. This discussion needs to be finalized before considering
>>>>>> this series.
>>>>>>
>>>>>> In my view bootflows cannot be defined in the devicetree because prior
>>>>>> firmware providing a devicetree is completely independent of any distro
>>>>>> and therefore cannot provide a distro specific bootflow.
>>>>>
>>>>> There is actually no need to use devicetree here. I think you might
>>>>> have the wrong end of the stick. It is certainly possible to add nodes
>>>>> to configure things, if needed, but it works find without any changes
>>>>> to the devicetree, as you can see from the rpi_3 patch.
>>>>>
>>>>> There are several aims with this effort:
>>>>>
>>>>> - Provide a standard way to boot anything on U-Boot, that everyone can
>>>>> plug into (distros, board vendors, people using a custom flow)
>>>>
>>>> I as a distro maintainer don't want this, we already get the "standard
>>>> way to boot" from UEFI, this just feels like another unnecessary
>>>> abstraction to that.
>>>
>>> Right.  But part of the problem is "How do I find UEFI".  Something
>>> somewhere needs to be configurable to say where to look, yes?
>>
>> Is this question from the board PoV, the developer of U-Boot or the
>> distro trying to boot?
>>
>> If you mean from a boot flow PoV for UEFI to find the HW that contains
>> the OS to boot I thought that was handled elsewhere in the series.
>
> What I mean is that today looking at Pi we have:
> #define BOOT_TARGET_DEVICES(func) \
>          BOOT_TARGET_MMC(func) \
>          BOOT_TARGET_USB(func) \
>          BOOT_TARGET_PXE(func) \
>          BOOT_TARGET_DHCP(func)
>
> As the board maintainer set that as the list of places to start looking
> for the next payload (say the GRUB EFI binary).  Simon's series replaces
> that with I think he said "bootflow scan -b".  And then the above env
> portion is replaced with, well, what's documented in patch #40 if you
> don't just want to rely on device probe order.
>
> Because we need to have _something_ that says where to look for what,
> yes?  Or should that be replaced entirely with efi vars and
> BootOrder/BootXXX and "bootefi bootmgr $fdt_addr_r" ?
>

UEFI variables must be supported for booting via UEFI. But if no valid
image can be found via the UEFI variables you have to scan the EFI
system partition for the file EFI/BOOT/BOOT<arch>.EFI and run it. This
requires to scan all block devices for the ESP.

Furthermore not all distributions use UEFI by default on all systems.

Best regards

Heinrich


^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:09               ` Heinrich Schuchardt
@ 2021-10-28 18:13                 ` Tom Rini
  0 siblings, 0 replies; 116+ messages in thread
From: Tom Rini @ 2021-10-28 18:13 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Simon Glass, Heinrich Schuchardt, Michal Simek, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Marek Vasut,
	Masahiro Yamada, Pavel Herrmann, Peng Fan, Stephen Warren,
	Stephen Warren, François Ozog, U-Boot Mailing List,
	Peter Robinson

[-- Attachment #1: Type: text/plain, Size: 5169 bytes --]

On Thu, Oct 28, 2021 at 08:09:35PM +0200, Heinrich Schuchardt wrote:
> On 10/28/21 7:59 PM, Tom Rini wrote:
> > On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
> > > On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
> > > > 
> > > > On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > > > > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > 
> > > > > > Hi Heinrich,
> > > > > > 
> > > > > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > > > > <heinrich.schuchardt@canonical.com> wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > > > > > 
> > > > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > > 
> > > > > > > > It introduces the following concepts:
> > > > > > > > 
> > > > > > > >      - bootdev - a device which can hold a distro
> > > > > > > >      - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > > > >                   U-Boot)
> > > > > > > >      - bootflow - a description of how to boot (owned by the distro)
> > > > > > > 
> > > > > > > Please, describe why you are suggesting this change.
> > > > > > > 
> > > > > > > Replacing a script by a devicetree chunk is just decreasing flexibility
> > > > > > > and increasing complexity. Where is the benefit?
> > > > > > > 
> > > > > > > I am missing a description here of where and how a boot flow shall be
> > > > > > > defined. Describing some device-tree binding in patch 40/41 does not
> > > > > > > replace describing the development and usage workflow. Who will provide
> > > > > > > which bootflow information when?
> > > > > > > 
> > > > > > > You still have an open discussion with Linaro about the source of
> > > > > > > devicetrees. This discussion needs to be finalized before considering
> > > > > > > this series.
> > > > > > > 
> > > > > > > In my view bootflows cannot be defined in the devicetree because prior
> > > > > > > firmware providing a devicetree is completely independent of any distro
> > > > > > > and therefore cannot provide a distro specific bootflow.
> > > > > > 
> > > > > > There is actually no need to use devicetree here. I think you might
> > > > > > have the wrong end of the stick. It is certainly possible to add nodes
> > > > > > to configure things, if needed, but it works find without any changes
> > > > > > to the devicetree, as you can see from the rpi_3 patch.
> > > > > > 
> > > > > > There are several aims with this effort:
> > > > > > 
> > > > > > - Provide a standard way to boot anything on U-Boot, that everyone can
> > > > > > plug into (distros, board vendors, people using a custom flow)
> > > > > 
> > > > > I as a distro maintainer don't want this, we already get the "standard
> > > > > way to boot" from UEFI, this just feels like another unnecessary
> > > > > abstraction to that.
> > > > 
> > > > Right.  But part of the problem is "How do I find UEFI".  Something
> > > > somewhere needs to be configurable to say where to look, yes?
> > > 
> > > Is this question from the board PoV, the developer of U-Boot or the
> > > distro trying to boot?
> > > 
> > > If you mean from a boot flow PoV for UEFI to find the HW that contains
> > > the OS to boot I thought that was handled elsewhere in the series.
> > 
> > What I mean is that today looking at Pi we have:
> > #define BOOT_TARGET_DEVICES(func) \
> >          BOOT_TARGET_MMC(func) \
> >          BOOT_TARGET_USB(func) \
> >          BOOT_TARGET_PXE(func) \
> >          BOOT_TARGET_DHCP(func)
> > 
> > As the board maintainer set that as the list of places to start looking
> > for the next payload (say the GRUB EFI binary).  Simon's series replaces
> > that with I think he said "bootflow scan -b".  And then the above env
> > portion is replaced with, well, what's documented in patch #40 if you
> > don't just want to rely on device probe order.
> > 
> > Because we need to have _something_ that says where to look for what,
> > yes?  Or should that be replaced entirely with efi vars and
> > BootOrder/BootXXX and "bootefi bootmgr $fdt_addr_r" ?
> > 
> 
> UEFI variables must be supported for booting via UEFI. But if no valid
> image can be found via the UEFI variables you have to scan the EFI
> system partition for the file EFI/BOOT/BOOT<arch>.EFI and run it. This
> requires to scan all block devices for the ESP.
> 
> Furthermore not all distributions use UEFI by default on all systems.

Assume a UEFI distribution for the moment.  What should the default boot
command look like, these days?  Can U-Boot have persistent UEFI
variables directly (rather than say indirectly with a preboot=... to set
them) or no?  Or should it continue to be the EFI-related logic in
include/config_distro_bootcmd.h ?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:52       ` Tom Rini
@ 2021-10-28 18:13         ` Simon Glass
  2021-10-28 18:36           ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-28 18:13 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Tom,

On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > >
> > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > boot an Operating System without custom scripting and other customisation.
> > > > This is called 'standard boot' since it provides a standard way for
> > > > U-Boot to boot a distro, without scripting.
> > > >
> > > > It introduces the following concepts:
> > > >
> > > >    - bootdev - a device which can hold a distro
> > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > >                 U-Boot)
> > > >    - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > This series provides an implementation of these, enabled to scan for
> > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > similiarly to the existing script-based approach, but is native to
> > > > U-Boot.
> > >
> > > I'm going to break my feedback down in to a few threads, to hopefully
> > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > And while there's a few small changes in the pxe cleanup I'm going to
> > > re-investigate on their own, it's really just this series, right here,
> > > adding tons of code.  To replace an admittedly complex bit of
> > > environment scripting, with C.  It's not even the earlier parts of the
> > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > uclass and core implementation" and keeps going from there.
> >
> > Yes it does add a lot of code, although it is a lot less if the
> > commands are disabled or simplified, e.g. to only support 'bootflow
> > scan -b'. At the moment it enables all dev features.
>
> OK, for the next go-round yes, please show what a typical enablement
> would look like on Pi, for example.

OK. Do understand that conceiving of this and implementing it is quite
a bit of effort. At some point I just send things out, to get feedback
and to think some more. Apart from anything else, there is a risk of
going into the weeds or never finishing it.

>
> > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > drops by 3.5KB.
>
> So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> win.

Certainly not on size! On testing, debug, visibility and control of
the boot process, there are wins.

>
> > We should compare this with the EFI support which is about 90KB, as I recall.
>
> No, we shouldn't.  This isn't about replacing EFI, this is about
> replacing the generic distro boot macros, so that's what the size
> comparison is to.  At the end of the day, and looking towards non-legacy
> uses, a big common use case is "Find the EFI app to run".

I just mean that EFI has been accepted as part of U-Boot and adds 90KB.

>
> > If we continue down the path of making this feature use U-Boot
> > functions directly, instead the command line, I suspect we can save
> > quite a bit more, since there is a lot of overhead with these
> > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > enabled, for example.
>
> Yes, this should be using the API and not the command interface.

Right, but that's not something I am taking on right now. The PXE
refactoring gives an idea of what is needed. I did that work mainly
because I don't like adding to code that desperately needs
refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
that might take a year.

>
> > In any case, I think this feature is filling a gap in U-Boot since at
> > present everything about boot is ad-hoc. This gives us a base to build
> > on. Nothing is for free.
>
> I disagree.  At present, booting is either intentionally per-board, or
> it's using the generic distro boot framework.  That framework is what to
> further build on or perhaps make more readily simplified (for example,
> making it just be "scan around for EFI" or just be "scan around of
> extlinux.conf").

Well if the Universal Bootloader is only going to exist to boot EFI,
then we should rename it :-)

I am not sure that anyone wants something intentionally per-board,
it's just that everything about the boot in U-Boot is really low-level
(bootm, fixed addresses, etc.) We need the layer on top that can deal
with these silly details. For example, yes there is a Chrome OS boot
script in chromebook_coral, but it is the same on all devices. I would
rather just enable that bootmethod so that if Chrome OS is present it
will boot.

Re the memory side, i don't like the vars that define the kernel
address, FDT address, etc. It seems to me that most/all are
unnecessary, if there is something able to deal with memory allocatoin
automatically. Perhaps we should use malloc() more, or use LMB more
proactively.

Even for custom flows, creating a bootmethod will have advantages, I think.

The other thing is that this allows further innovation. For verified
boot, it makes it possible to sensibly deal with A/B;recovery, whereas
at present that is all just scripting, certainly not handled by distro
boot.

>
> > Anyway, I can look at what the minimum size is with the above points
> > and send that info through.
>
> I looked at the PXE stuff, and I think the minimal growth there ends up
> being reasonable, fwiw.  It comes down to adding sanity checks in places
> where the code wasn't always sanity checking, as you reduced
> duplication.

Yes and perhaps the growth can be reduced, too.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:59             ` Tom Rini
  2021-10-28 18:09               ` Heinrich Schuchardt
@ 2021-10-28 18:17               ` François Ozog
  2021-10-28 18:27                 ` Tom Rini
  1 sibling, 1 reply; 116+ messages in thread
From: François Ozog @ 2021-10-28 18:17 UTC (permalink / raw)
  To: Tom Rini
  Cc: Daniel Schwierzeck, Dennis Gilmore, Heinrich Schuchardt,
	Heinrich Schuchardt, Ilias Apalodimas, Jaehoon Chung, Lukas Auer,
	Marek Behún, Marek Vasut, Masahiro Yamada, Michal Simek,
	Pavel Herrmann, Peng Fan, Peter Robinson, Simon Glass,
	Steffen Jaeckel, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

Hi Tom,

Le jeu. 28 oct. 2021 à 19:59, Tom Rini <trini@konsulko.com> a écrit :

> On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
> > On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > > > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org>
> wrote:
> > > > >
> > > > > Hi Heinrich,
> > > > >
> > > > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > > > <heinrich.schuchardt@canonical.com> wrote:
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > > > >
> > > > > > > The bootflow feature provide a built-in way for U-Boot to
> automatically
> > > > > > > boot an Operating System without custom scripting and other
> customisation.
> > > > > > > This is called 'standard boot' since it provides a standard
> way for
> > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > >
> > > > > > > It introduces the following concepts:
> > > > > > >
> > > > > > >     - bootdev - a device which can hold a distro
> > > > > > >     - bootmeth - a method to scan a bootdev to find bootflows
> (owned by
> > > > > > >                  U-Boot)
> > > > > > >     - bootflow - a description of how to boot (owned by the
> distro)
> > > > > >
> > > > > > Please, describe why you are suggesting this change.
> > > > > >
> > > > > > Replacing a script by a devicetree chunk is just decreasing
> flexibility
> > > > > > and increasing complexity. Where is the benefit?
> > > > > >
> > > > > > I am missing a description here of where and how a boot flow
> shall be
> > > > > > defined. Describing some device-tree binding in patch 40/41 does
> not
> > > > > > replace describing the development and usage workflow. Who will
> provide
> > > > > > which bootflow information when?
> > > > > >
> > > > > > You still have an open discussion with Linaro about the source of
> > > > > > devicetrees. This discussion needs to be finalized before
> considering
> > > > > > this series.
> > > > > >
> > > > > > In my view bootflows cannot be defined in the devicetree because
> prior
> > > > > > firmware providing a devicetree is completely independent of any
> distro
> > > > > > and therefore cannot provide a distro specific bootflow.
> > > > >
> > > > > There is actually no need to use devicetree here. I think you might
> > > > > have the wrong end of the stick. It is certainly possible to add
> nodes
> > > > > to configure things, if needed, but it works find without any
> changes
> > > > > to the devicetree, as you can see from the rpi_3 patch.
> > > > >
> > > > > There are several aims with this effort:
> > > > >
> > > > > - Provide a standard way to boot anything on U-Boot, that everyone
> can
> > > > > plug into (distros, board vendors, people using a custom flow)
> > > >
> > > > I as a distro maintainer don't want this, we already get the
> "standard
> > > > way to boot" from UEFI, this just feels like another unnecessary
> > > > abstraction to that.
> > >
> > > Right.  But part of the problem is "How do I find UEFI".  Something
> > > somewhere needs to be configurable to say where to look, yes?
> >
> > Is this question from the board PoV, the developer of U-Boot or the
> > distro trying to boot?
> >
> > If you mean from a boot flow PoV for UEFI to find the HW that contains
> > the OS to boot I thought that was handled elsewhere in the series.
>
> What I mean is that today looking at Pi we have:
> #define BOOT_TARGET_DEVICES(func) \
>         BOOT_TARGET_MMC(func) \
>         BOOT_TARGET_USB(func) \
>         BOOT_TARGET_PXE(func) \
>         BOOT_TARGET_DHCP(func)
>
> As the board maintainer set that as the list of places to start looking
> for the next payload (say the GRUB EFI binary).  Simon's series replaces
> that with I think he said "bootflow scan -b".  And then the above env
> portion is replaced with, well, what's documented in patch #40 if you
> don't just want to rely on device probe order.
>
> Because we need to have _something_ that says where to look for what,
> yes?


Shouldn’t we describe the user point of view ?

Even before EFI existed on x86 it went like (this is not intending to be
exhaustive or even exact):
Start a non installed system: the boot goes through a device list much like
distro_boot_CMd works except if the user select a manual boot selection
(the boot devices goes into a menu)
When the installer finishes it “informs” the firmware with the desired boot
target.
When the OS runs it can select the next boot (transient or permanent)
option. This usually involves grub rather than firmware but the user can
decide if the boot target change is driven by the firmware.
(For SystemReady we want to have an option to live without shim and grub so
the boot target change will involve setting BootXXXX.)

I think it is first important to describe the observable behavior before
jumping into implementation. Scenarios involving développer systems may be
different from the ones for consumer products.

Or should that be replaced entirely with efi vars and
> BootOrder/BootXXX and "bootefi bootmgr $fdt_addr_r" ?

for EFI there is also the last resort /BOOT/BOOT${arch}.efi in ESP


>
> --
> Tom
>
-- 
François-Frédéric Ozog | *Director Business Development*
T: +33.67221.6485
francois.ozog@linaro.org | Skype: ffozog

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:17               ` François Ozog
@ 2021-10-28 18:27                 ` Tom Rini
  2021-10-28 18:28                   ` François Ozog
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 18:27 UTC (permalink / raw)
  To: François Ozog
  Cc: Daniel Schwierzeck, Dennis Gilmore, Heinrich Schuchardt,
	Heinrich Schuchardt, Ilias Apalodimas, Jaehoon Chung, Lukas Auer,
	Marek Behún, Marek Vasut, Masahiro Yamada, Michal Simek,
	Pavel Herrmann, Peng Fan, Peter Robinson, Simon Glass,
	Steffen Jaeckel, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

[-- Attachment #1: Type: text/plain, Size: 4752 bytes --]

On Thu, Oct 28, 2021 at 08:17:50PM +0200, François Ozog wrote:
> Hi Tom,
> 
> Le jeu. 28 oct. 2021 à 19:59, Tom Rini <trini@konsulko.com> a écrit :
> 
> > On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
> > > On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > > > > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org>
> > wrote:
> > > > > >
> > > > > > Hi Heinrich,
> > > > > >
> > > > > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > > > > <heinrich.schuchardt@canonical.com> wrote:
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > > > > >
> > > > > > > > The bootflow feature provide a built-in way for U-Boot to
> > automatically
> > > > > > > > boot an Operating System without custom scripting and other
> > customisation.
> > > > > > > > This is called 'standard boot' since it provides a standard
> > way for
> > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > >
> > > > > > > > It introduces the following concepts:
> > > > > > > >
> > > > > > > >     - bootdev - a device which can hold a distro
> > > > > > > >     - bootmeth - a method to scan a bootdev to find bootflows
> > (owned by
> > > > > > > >                  U-Boot)
> > > > > > > >     - bootflow - a description of how to boot (owned by the
> > distro)
> > > > > > >
> > > > > > > Please, describe why you are suggesting this change.
> > > > > > >
> > > > > > > Replacing a script by a devicetree chunk is just decreasing
> > flexibility
> > > > > > > and increasing complexity. Where is the benefit?
> > > > > > >
> > > > > > > I am missing a description here of where and how a boot flow
> > shall be
> > > > > > > defined. Describing some device-tree binding in patch 40/41 does
> > not
> > > > > > > replace describing the development and usage workflow. Who will
> > provide
> > > > > > > which bootflow information when?
> > > > > > >
> > > > > > > You still have an open discussion with Linaro about the source of
> > > > > > > devicetrees. This discussion needs to be finalized before
> > considering
> > > > > > > this series.
> > > > > > >
> > > > > > > In my view bootflows cannot be defined in the devicetree because
> > prior
> > > > > > > firmware providing a devicetree is completely independent of any
> > distro
> > > > > > > and therefore cannot provide a distro specific bootflow.
> > > > > >
> > > > > > There is actually no need to use devicetree here. I think you might
> > > > > > have the wrong end of the stick. It is certainly possible to add
> > nodes
> > > > > > to configure things, if needed, but it works find without any
> > changes
> > > > > > to the devicetree, as you can see from the rpi_3 patch.
> > > > > >
> > > > > > There are several aims with this effort:
> > > > > >
> > > > > > - Provide a standard way to boot anything on U-Boot, that everyone
> > can
> > > > > > plug into (distros, board vendors, people using a custom flow)
> > > > >
> > > > > I as a distro maintainer don't want this, we already get the
> > "standard
> > > > > way to boot" from UEFI, this just feels like another unnecessary
> > > > > abstraction to that.
> > > >
> > > > Right.  But part of the problem is "How do I find UEFI".  Something
> > > > somewhere needs to be configurable to say where to look, yes?
> > >
> > > Is this question from the board PoV, the developer of U-Boot or the
> > > distro trying to boot?
> > >
> > > If you mean from a boot flow PoV for UEFI to find the HW that contains
> > > the OS to boot I thought that was handled elsewhere in the series.
> >
> > What I mean is that today looking at Pi we have:
> > #define BOOT_TARGET_DEVICES(func) \
> >         BOOT_TARGET_MMC(func) \
> >         BOOT_TARGET_USB(func) \
> >         BOOT_TARGET_PXE(func) \
> >         BOOT_TARGET_DHCP(func)
> >
> > As the board maintainer set that as the list of places to start looking
> > for the next payload (say the GRUB EFI binary).  Simon's series replaces
> > that with I think he said "bootflow scan -b".  And then the above env
> > portion is replaced with, well, what's documented in patch #40 if you
> > don't just want to rely on device probe order.
> >
> > Because we need to have _something_ that says where to look for what,
> > yes?
> 
> Shouldn’t we describe the user point of view ?

No, because to extend the x86 metaphor we're talking about the defaults
here, not what the user has configured later on.  The user has and
continues to be able to configure the system afterwards, if desired.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:27                 ` Tom Rini
@ 2021-10-28 18:28                   ` François Ozog
  0 siblings, 0 replies; 116+ messages in thread
From: François Ozog @ 2021-10-28 18:28 UTC (permalink / raw)
  To: Tom Rini
  Cc: Daniel Schwierzeck, Dennis Gilmore, Heinrich Schuchardt,
	Heinrich Schuchardt, Ilias Apalodimas, Jaehoon Chung, Lukas Auer,
	Marek Behún, Marek Vasut, Masahiro Yamada, Michal Simek,
	Pavel Herrmann, Peng Fan, Peter Robinson, Simon Glass,
	Steffen Jaeckel, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

Hi Tom

Le jeu. 28 oct. 2021 à 20:27, Tom Rini <trini@konsulko.com> a écrit :

> On Thu, Oct 28, 2021 at 08:17:50PM +0200, François Ozog wrote:
> > Hi Tom,
> >
> > Le jeu. 28 oct. 2021 à 19:59, Tom Rini <trini@konsulko.com> a écrit :
> >
> > > On Thu, Oct 28, 2021 at 06:50:02PM +0100, Peter Robinson wrote:
> > > > On Thu, Oct 28, 2021 at 6:47 PM Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > > > > > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org>
> > > wrote:
> > > > > > >
> > > > > > > Hi Heinrich,
> > > > > > >
> > > > > > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > > > > > <heinrich.schuchardt@canonical.com> wrote:
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > > > > > >
> > > > > > > > > The bootflow feature provide a built-in way for U-Boot to
> > > automatically
> > > > > > > > > boot an Operating System without custom scripting and other
> > > customisation.
> > > > > > > > > This is called 'standard boot' since it provides a standard
> > > way for
> > > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > > >
> > > > > > > > > It introduces the following concepts:
> > > > > > > > >
> > > > > > > > >     - bootdev - a device which can hold a distro
> > > > > > > > >     - bootmeth - a method to scan a bootdev to find
> bootflows
> > > (owned by
> > > > > > > > >                  U-Boot)
> > > > > > > > >     - bootflow - a description of how to boot (owned by the
> > > distro)
> > > > > > > >
> > > > > > > > Please, describe why you are suggesting this change.
> > > > > > > >
> > > > > > > > Replacing a script by a devicetree chunk is just decreasing
> > > flexibility
> > > > > > > > and increasing complexity. Where is the benefit?
> > > > > > > >
> > > > > > > > I am missing a description here of where and how a boot flow
> > > shall be
> > > > > > > > defined. Describing some device-tree binding in patch 40/41
> does
> > > not
> > > > > > > > replace describing the development and usage workflow. Who
> will
> > > provide
> > > > > > > > which bootflow information when?
> > > > > > > >
> > > > > > > > You still have an open discussion with Linaro about the
> source of
> > > > > > > > devicetrees. This discussion needs to be finalized before
> > > considering
> > > > > > > > this series.
> > > > > > > >
> > > > > > > > In my view bootflows cannot be defined in the devicetree
> because
> > > prior
> > > > > > > > firmware providing a devicetree is completely independent of
> any
> > > distro
> > > > > > > > and therefore cannot provide a distro specific bootflow.
> > > > > > >
> > > > > > > There is actually no need to use devicetree here. I think you
> might
> > > > > > > have the wrong end of the stick. It is certainly possible to
> add
> > > nodes
> > > > > > > to configure things, if needed, but it works find without any
> > > changes
> > > > > > > to the devicetree, as you can see from the rpi_3 patch.
> > > > > > >
> > > > > > > There are several aims with this effort:
> > > > > > >
> > > > > > > - Provide a standard way to boot anything on U-Boot, that
> everyone
> > > can
> > > > > > > plug into (distros, board vendors, people using a custom flow)
> > > > > >
> > > > > > I as a distro maintainer don't want this, we already get the
> > > "standard
> > > > > > way to boot" from UEFI, this just feels like another unnecessary
> > > > > > abstraction to that.
> > > > >
> > > > > Right.  But part of the problem is "How do I find UEFI".  Something
> > > > > somewhere needs to be configurable to say where to look, yes?
> > > >
> > > > Is this question from the board PoV, the developer of U-Boot or the
> > > > distro trying to boot?
> > > >
> > > > If you mean from a boot flow PoV for UEFI to find the HW that
> contains
> > > > the OS to boot I thought that was handled elsewhere in the series.
> > >
> > > What I mean is that today looking at Pi we have:
> > > #define BOOT_TARGET_DEVICES(func) \
> > >         BOOT_TARGET_MMC(func) \
> > >         BOOT_TARGET_USB(func) \
> > >         BOOT_TARGET_PXE(func) \
> > >         BOOT_TARGET_DHCP(func)
> > >
> > > As the board maintainer set that as the list of places to start looking
> > > for the next payload (say the GRUB EFI binary).  Simon's series
> replaces
> > > that with I think he said "bootflow scan -b".  And then the above env
> > > portion is replaced with, well, what's documented in patch #40 if you
> > > don't just want to rely on device probe order.
> > >
> > > Because we need to have _something_ that says where to look for what,
> > > yes?
> >
> > Shouldn’t we describe the user point of view ?
>
> No, because to extend the x86 metaphor we're talking about the defaults
> here, not what the user has configured later on.  The user has and
> continues to be able to configure the system afterwards, if desired.
>
Sorry , missed this “detail”…

>
> --
> Tom
>
-- 
François-Frédéric Ozog | *Director Business Development*
T: +33.67221.6485
francois.ozog@linaro.org | Skype: ffozog

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:13         ` Simon Glass
@ 2021-10-28 18:36           ` Tom Rini
  2021-10-28 18:48             ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 18:36 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 7413 bytes --]

On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > >
> > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > boot an Operating System without custom scripting and other customisation.
> > > > > This is called 'standard boot' since it provides a standard way for
> > > > > U-Boot to boot a distro, without scripting.
> > > > >
> > > > > It introduces the following concepts:
> > > > >
> > > > >    - bootdev - a device which can hold a distro
> > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > >                 U-Boot)
> > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > >
> > > > > This series provides an implementation of these, enabled to scan for
> > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > similiarly to the existing script-based approach, but is native to
> > > > > U-Boot.
> > > >
> > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > re-investigate on their own, it's really just this series, right here,
> > > > adding tons of code.  To replace an admittedly complex bit of
> > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > uclass and core implementation" and keeps going from there.
> > >
> > > Yes it does add a lot of code, although it is a lot less if the
> > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > scan -b'. At the moment it enables all dev features.
> >
> > OK, for the next go-round yes, please show what a typical enablement
> > would look like on Pi, for example.
> 
> OK. Do understand that conceiving of this and implementing it is quite
> a bit of effort. At some point I just send things out, to get feedback
> and to think some more. Apart from anything else, there is a risk of
> going into the weeds or never finishing it.
> 
> >
> > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > drops by 3.5KB.
> >
> > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > win.
> 
> Certainly not on size! On testing, debug, visibility and control of
> the boot process, there are wins.

I'm not sure if there's wins on those grounds either, and certainly not
enough to justify what this adds.

> > > We should compare this with the EFI support which is about 90KB, as I recall.
> >
> > No, we shouldn't.  This isn't about replacing EFI, this is about
> > replacing the generic distro boot macros, so that's what the size
> > comparison is to.  At the end of the day, and looking towards non-legacy
> > uses, a big common use case is "Find the EFI app to run".
> 
> I just mean that EFI has been accepted as part of U-Boot and adds 90KB.

OK?  I still don't see the relevance here.

> > > If we continue down the path of making this feature use U-Boot
> > > functions directly, instead the command line, I suspect we can save
> > > quite a bit more, since there is a lot of overhead with these
> > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > enabled, for example.
> >
> > Yes, this should be using the API and not the command interface.
> 
> Right, but that's not something I am taking on right now. The PXE
> refactoring gives an idea of what is needed. I did that work mainly
> because I don't like adding to code that desperately needs
> refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> that might take a year.

Well, maybe this particular part of things get set aside for now, and
the generic distro boot framework just needs to be moved to the env
update you did.

> > > In any case, I think this feature is filling a gap in U-Boot since at
> > > present everything about boot is ad-hoc. This gives us a base to build
> > > on. Nothing is for free.
> >
> > I disagree.  At present, booting is either intentionally per-board, or
> > it's using the generic distro boot framework.  That framework is what to
> > further build on or perhaps make more readily simplified (for example,
> > making it just be "scan around for EFI" or just be "scan around of
> > extlinux.conf").
> 
> Well if the Universal Bootloader is only going to exist to boot EFI,
> then we should rename it :-)
> 
> I am not sure that anyone wants something intentionally per-board,

There's some cases, yes, where the system is supposed to do X (or Y, or
Z).  Otherwise there's the generic framework.  Or...

> it's just that everything about the boot in U-Boot is really low-level
> (bootm, fixed addresses, etc.) We need the layer on top that can deal
> with these silly details. For example, yes there is a Chrome OS boot
> script in chromebook_coral, but it is the same on all devices. I would
> rather just enable that bootmethod so that if Chrome OS is present it
> will boot.

there's things like what Chrome OS wants.

> Re the memory side, i don't like the vars that define the kernel
> address, FDT address, etc. It seems to me that most/all are
> unnecessary, if there is something able to deal with memory allocatoin
> automatically. Perhaps we should use malloc() more, or use LMB more
> proactively.

Well, in that for Linux, arm64 the Image format has a header that lets
us avoid a number of problems that weren't possible on arm32, there's a
tiny bit more flexibility there.  But it sounds like you're talking
about "bootm_size" and "bootm_low" now.

> Even for custom flows, creating a bootmethod will have advantages, I think.
> 
> The other thing is that this allows further innovation. For verified
> boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> at present that is all just scripting, certainly not handled by distro
> boot.

No distros implement A/B updates directly.  When implemented on top of
them it's done via the environment, yes.  I don't think adding Mender
and RAUC and swupdate specific bootflow commands is a step in the right
direction at all.

> > > Anyway, I can look at what the minimum size is with the above points
> > > and send that info through.
> >
> > I looked at the PXE stuff, and I think the minimal growth there ends up
> > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > where the code wasn't always sanity checking, as you reduced
> > duplication.
> 
> Yes and perhaps the growth can be reduced, too.

It must be.  You need to be a lot closer to parity with the existing
generic boot mechanism and around that size.  I am not liking what I'm
seeing here so far.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:36           ` Tom Rini
@ 2021-10-28 18:48             ` Simon Glass
  2021-10-28 19:19               ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-28 18:48 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Tom,

On Thu, 28 Oct 2021 at 12:36, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > > >
> > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > U-Boot to boot a distro, without scripting.
> > > > > >
> > > > > > It introduces the following concepts:
> > > > > >
> > > > > >    - bootdev - a device which can hold a distro
> > > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > >                 U-Boot)
> > > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > > >
> > > > > > This series provides an implementation of these, enabled to scan for
> > > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > > similiarly to the existing script-based approach, but is native to
> > > > > > U-Boot.
> > > > >
> > > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > > re-investigate on their own, it's really just this series, right here,
> > > > > adding tons of code.  To replace an admittedly complex bit of
> > > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > > uclass and core implementation" and keeps going from there.
> > > >
> > > > Yes it does add a lot of code, although it is a lot less if the
> > > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > > scan -b'. At the moment it enables all dev features.
> > >
> > > OK, for the next go-round yes, please show what a typical enablement
> > > would look like on Pi, for example.
> >
> > OK. Do understand that conceiving of this and implementing it is quite
> > a bit of effort. At some point I just send things out, to get feedback
> > and to think some more. Apart from anything else, there is a risk of
> > going into the weeds or never finishing it.
> >
> > >
> > > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > > drops by 3.5KB.
> > >
> > > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > > win.
> >
> > Certainly not on size! On testing, debug, visibility and control of
> > the boot process, there are wins.
>
> I'm not sure if there's wins on those grounds either, and certainly not
> enough to justify what this adds.
>
> > > > We should compare this with the EFI support which is about 90KB, as I recall.
> > >
> > > No, we shouldn't.  This isn't about replacing EFI, this is about
> > > replacing the generic distro boot macros, so that's what the size
> > > comparison is to.  At the end of the day, and looking towards non-legacy
> > > uses, a big common use case is "Find the EFI app to run".
> >
> > I just mean that EFI has been accepted as part of U-Boot and adds 90KB.
>
> OK?  I still don't see the relevance here.
>
> > > > If we continue down the path of making this feature use U-Boot
> > > > functions directly, instead the command line, I suspect we can save
> > > > quite a bit more, since there is a lot of overhead with these
> > > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > > enabled, for example.
> > >
> > > Yes, this should be using the API and not the command interface.
> >
> > Right, but that's not something I am taking on right now. The PXE
> > refactoring gives an idea of what is needed. I did that work mainly
> > because I don't like adding to code that desperately needs
> > refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> > that might take a year.
>
> Well, maybe this particular part of things get set aside for now, and
> the generic distro boot framework just needs to be moved to the env
> update you did.
>
> > > > In any case, I think this feature is filling a gap in U-Boot since at
> > > > present everything about boot is ad-hoc. This gives us a base to build
> > > > on. Nothing is for free.
> > >
> > > I disagree.  At present, booting is either intentionally per-board, or
> > > it's using the generic distro boot framework.  That framework is what to
> > > further build on or perhaps make more readily simplified (for example,
> > > making it just be "scan around for EFI" or just be "scan around of
> > > extlinux.conf").
> >
> > Well if the Universal Bootloader is only going to exist to boot EFI,
> > then we should rename it :-)
> >
> > I am not sure that anyone wants something intentionally per-board,
>
> There's some cases, yes, where the system is supposed to do X (or Y, or
> Z).  Otherwise there's the generic framework.  Or...
>
> > it's just that everything about the boot in U-Boot is really low-level
> > (bootm, fixed addresses, etc.) We need the layer on top that can deal
> > with these silly details. For example, yes there is a Chrome OS boot
> > script in chromebook_coral, but it is the same on all devices. I would
> > rather just enable that bootmethod so that if Chrome OS is present it
> > will boot.
>
> there's things like what Chrome OS wants.
>
> > Re the memory side, i don't like the vars that define the kernel
> > address, FDT address, etc. It seems to me that most/all are
> > unnecessary, if there is something able to deal with memory allocatoin
> > automatically. Perhaps we should use malloc() more, or use LMB more
> > proactively.
>
> Well, in that for Linux, arm64 the Image format has a header that lets
> us avoid a number of problems that weren't possible on arm32, there's a
> tiny bit more flexibility there.  But it sounds like you're talking
> about "bootm_size" and "bootm_low" now.
>
> > Even for custom flows, creating a bootmethod will have advantages, I think.
> >
> > The other thing is that this allows further innovation. For verified
> > boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> > at present that is all just scripting, certainly not handled by distro
> > boot.
>
> No distros implement A/B updates directly.  When implemented on top of
> them it's done via the environment, yes.  I don't think adding Mender
> and RAUC and swupdate specific bootflow commands is a step in the right
> direction at all.
>
> > > > Anyway, I can look at what the minimum size is with the above points
> > > > and send that info through.
> > >
> > > I looked at the PXE stuff, and I think the minimal growth there ends up
> > > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > > where the code wasn't always sanity checking, as you reduced
> > > duplication.
> >
> > Yes and perhaps the growth can be reduced, too.
>
> It must be.  You need to be a lot closer to parity with the existing
> generic boot mechanism and around that size.  I am not liking what I'm
> seeing here so far.

Just on this point, I'm pretty sure this will kill it. We cannot add
code without increasing the size! It sounds like 17KB on ARM64 is too
much (perhaps 13.5KB including env reduction). Firstly, why, and
secondly, how much is acceptable? If the answer is zero, we are not
going to go anywhere with this, at least without a huge amount of
future refactoring, which is not going to happen since we cannot land
100s of patches all at once.

The big prize would be to be able to disable CONFIG_CMDLINE and still
boot. That saves 200KB or more.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 18:48             ` Simon Glass
@ 2021-10-28 19:19               ` Tom Rini
  2021-10-28 22:22                 ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 19:19 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 9261 bytes --]

On Thu, Oct 28, 2021 at 12:48:50PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 28 Oct 2021 at 12:36, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > > > >
> > > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > >
> > > > > > > It introduces the following concepts:
> > > > > > >
> > > > > > >    - bootdev - a device which can hold a distro
> > > > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > > >                 U-Boot)
> > > > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > > > >
> > > > > > > This series provides an implementation of these, enabled to scan for
> > > > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > > > similiarly to the existing script-based approach, but is native to
> > > > > > > U-Boot.
> > > > > >
> > > > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > > > re-investigate on their own, it's really just this series, right here,
> > > > > > adding tons of code.  To replace an admittedly complex bit of
> > > > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > > > uclass and core implementation" and keeps going from there.
> > > > >
> > > > > Yes it does add a lot of code, although it is a lot less if the
> > > > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > > > scan -b'. At the moment it enables all dev features.
> > > >
> > > > OK, for the next go-round yes, please show what a typical enablement
> > > > would look like on Pi, for example.
> > >
> > > OK. Do understand that conceiving of this and implementing it is quite
> > > a bit of effort. At some point I just send things out, to get feedback
> > > and to think some more. Apart from anything else, there is a risk of
> > > going into the weeds or never finishing it.
> > >
> > > >
> > > > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > > > drops by 3.5KB.
> > > >
> > > > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > > > win.
> > >
> > > Certainly not on size! On testing, debug, visibility and control of
> > > the boot process, there are wins.
> >
> > I'm not sure if there's wins on those grounds either, and certainly not
> > enough to justify what this adds.
> >
> > > > > We should compare this with the EFI support which is about 90KB, as I recall.
> > > >
> > > > No, we shouldn't.  This isn't about replacing EFI, this is about
> > > > replacing the generic distro boot macros, so that's what the size
> > > > comparison is to.  At the end of the day, and looking towards non-legacy
> > > > uses, a big common use case is "Find the EFI app to run".
> > >
> > > I just mean that EFI has been accepted as part of U-Boot and adds 90KB.
> >
> > OK?  I still don't see the relevance here.
> >
> > > > > If we continue down the path of making this feature use U-Boot
> > > > > functions directly, instead the command line, I suspect we can save
> > > > > quite a bit more, since there is a lot of overhead with these
> > > > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > > > enabled, for example.
> > > >
> > > > Yes, this should be using the API and not the command interface.
> > >
> > > Right, but that's not something I am taking on right now. The PXE
> > > refactoring gives an idea of what is needed. I did that work mainly
> > > because I don't like adding to code that desperately needs
> > > refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> > > that might take a year.
> >
> > Well, maybe this particular part of things get set aside for now, and
> > the generic distro boot framework just needs to be moved to the env
> > update you did.
> >
> > > > > In any case, I think this feature is filling a gap in U-Boot since at
> > > > > present everything about boot is ad-hoc. This gives us a base to build
> > > > > on. Nothing is for free.
> > > >
> > > > I disagree.  At present, booting is either intentionally per-board, or
> > > > it's using the generic distro boot framework.  That framework is what to
> > > > further build on or perhaps make more readily simplified (for example,
> > > > making it just be "scan around for EFI" or just be "scan around of
> > > > extlinux.conf").
> > >
> > > Well if the Universal Bootloader is only going to exist to boot EFI,
> > > then we should rename it :-)
> > >
> > > I am not sure that anyone wants something intentionally per-board,
> >
> > There's some cases, yes, where the system is supposed to do X (or Y, or
> > Z).  Otherwise there's the generic framework.  Or...
> >
> > > it's just that everything about the boot in U-Boot is really low-level
> > > (bootm, fixed addresses, etc.) We need the layer on top that can deal
> > > with these silly details. For example, yes there is a Chrome OS boot
> > > script in chromebook_coral, but it is the same on all devices. I would
> > > rather just enable that bootmethod so that if Chrome OS is present it
> > > will boot.
> >
> > there's things like what Chrome OS wants.
> >
> > > Re the memory side, i don't like the vars that define the kernel
> > > address, FDT address, etc. It seems to me that most/all are
> > > unnecessary, if there is something able to deal with memory allocatoin
> > > automatically. Perhaps we should use malloc() more, or use LMB more
> > > proactively.
> >
> > Well, in that for Linux, arm64 the Image format has a header that lets
> > us avoid a number of problems that weren't possible on arm32, there's a
> > tiny bit more flexibility there.  But it sounds like you're talking
> > about "bootm_size" and "bootm_low" now.
> >
> > > Even for custom flows, creating a bootmethod will have advantages, I think.
> > >
> > > The other thing is that this allows further innovation. For verified
> > > boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> > > at present that is all just scripting, certainly not handled by distro
> > > boot.
> >
> > No distros implement A/B updates directly.  When implemented on top of
> > them it's done via the environment, yes.  I don't think adding Mender
> > and RAUC and swupdate specific bootflow commands is a step in the right
> > direction at all.
> >
> > > > > Anyway, I can look at what the minimum size is with the above points
> > > > > and send that info through.
> > > >
> > > > I looked at the PXE stuff, and I think the minimal growth there ends up
> > > > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > > > where the code wasn't always sanity checking, as you reduced
> > > > duplication.
> > >
> > > Yes and perhaps the growth can be reduced, too.
> >
> > It must be.  You need to be a lot closer to parity with the existing
> > generic boot mechanism and around that size.  I am not liking what I'm
> > seeing here so far.
> 
> Just on this point, I'm pretty sure this will kill it. We cannot add
> code without increasing the size! It sounds like 17KB on ARM64 is too
> much (perhaps 13.5KB including env reduction). Firstly, why, and
> secondly, how much is acceptable? If the answer is zero, we are not
> going to go anywhere with this, at least without a huge amount of
> future refactoring, which is not going to happen since we cannot land
> 100s of patches all at once.
> 
> The big prize would be to be able to disable CONFIG_CMDLINE and still
> boot. That saves 200KB or more.

I think the problem is this just needs to get put on hold for a while.
I am not convinced this is moving things in the right direction.
Conceptually, it's duplicating a lot of the efi bootmgr functionality,
but also adding in non-block devices.  And I am not liking configuring
this via device tree, rather than environment.  Lets move the generic
distro framework to the new env framework and continue finishing off
other technical debts that we have, before we re-visit a brand new way
of handling booting.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 17:47         ` Tom Rini
  2021-10-28 17:50           ` Peter Robinson
@ 2021-10-28 21:40           ` Mark Kettenis
  1 sibling, 0 replies; 116+ messages in thread
From: Mark Kettenis @ 2021-10-28 21:40 UTC (permalink / raw)
  To: Tom Rini
  Cc: pbrobinson, sjg, heinrich.schuchardt, michal.simek,
	ilias.apalodimas, daniel.schwierzeck, jaeckel-floss, marek.behun,
	lukas.auer, dennis, jh80.chung, marex, yamada.masahiro,
	morpheus.ibis, peng.fan, swarren, swarren, francois.ozog,
	xypron.glpk, u-boot

> Date: Thu, 28 Oct 2021 13:47:21 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Thu, Oct 28, 2021 at 06:37:42PM +0100, Peter Robinson wrote:
> > On Wed, Oct 27, 2021 at 3:11 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Heinrich,
> > >
> > > On Wed, 27 Oct 2021 at 05:38, Heinrich Schuchardt
> > > <heinrich.schuchardt@canonical.com> wrote:
> > > >
> > > >
> > > >
> > > > On 10/24/21 01:25, Simon Glass wrote:
> > > > >
> > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > boot an Operating System without custom scripting and other customisation.
> > > > > This is called 'standard boot' since it provides a standard way for
> > > > > U-Boot to boot a distro, without scripting.
> > > > >
> > > > > It introduces the following concepts:
> > > > >
> > > > >     - bootdev - a device which can hold a distro
> > > > >     - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > >                  U-Boot)
> > > > >     - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > Please, describe why you are suggesting this change.
> > > >
> > > > Replacing a script by a devicetree chunk is just decreasing flexibility
> > > > and increasing complexity. Where is the benefit?
> > > >
> > > > I am missing a description here of where and how a boot flow shall be
> > > > defined. Describing some device-tree binding in patch 40/41 does not
> > > > replace describing the development and usage workflow. Who will provide
> > > > which bootflow information when?
> > > >
> > > > You still have an open discussion with Linaro about the source of
> > > > devicetrees. This discussion needs to be finalized before considering
> > > > this series.
> > > >
> > > > In my view bootflows cannot be defined in the devicetree because prior
> > > > firmware providing a devicetree is completely independent of any distro
> > > > and therefore cannot provide a distro specific bootflow.
> > >
> > > There is actually no need to use devicetree here. I think you might
> > > have the wrong end of the stick. It is certainly possible to add nodes
> > > to configure things, if needed, but it works find without any changes
> > > to the devicetree, as you can see from the rpi_3 patch.
> > >
> > > There are several aims with this effort:
> > >
> > > - Provide a standard way to boot anything on U-Boot, that everyone can
> > > plug into (distros, board vendors, people using a custom flow)
> > 
> > I as a distro maintainer don't want this, we already get the "standard
> > way to boot" from UEFI, this just feels like another unnecessary
> > abstraction to that.
> 
> Right.  But part of the problem is "How do I find UEFI".  Something
> somewhere needs to be configurable to say where to look, yes?

Before we had "bootefi bootmgr", this was done using "setenv
boot_targets ...", where you would specify a list of devices to try
and boot from.  This is effectively a command line version of the menu
that most x86 BIOS (and UEFI) implementations offer to specify the
order of devices to boot from.  We document this in the OpenBSD/arm64
installtion instructions and it wouldn't surprise me of some of the
Linux distro's do this as well.  This still works fine, unless you set
the UEFI variables that "bootefi bootmgr" looks at.  But I fear
Simon's patch series breaks this.  I didn't try the patch series yet
though, so I might be mistaken.

When "bootefi bootmgr" is used, the device/OS to boot is specified by
the Boot#### and BootOrder UEFI variables.  I believe these can be set
from the U-Boot command line, but doing so in the right way isn't
trivial.  The way this is supposed to work I think is that the OS
installer defines an appropriate Boot#### variable and adds it to tje
BootOrder variable.  But that pretty much relies on on the ability to
set those variables at OS runtime using EFI runtime services.  And as
was pointed out that doesn't really work for most U-Boot targets.  To
be honest, I don't really understand how "bootefi bootmgr" is used in
the real world right now.

There is a lot of good work done in this area in U-Boot.  But I get
the feeling that too much of it is driven by meeting requirements of
specs and that there is too little thought put into the practicalities
of actually booting a general purpose OS (e.g. a mainstrain Linux
distro) on a board with U-Boot support.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 19:19               ` Tom Rini
@ 2021-10-28 22:22                 ` Simon Glass
  2021-10-28 22:50                   ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-28 22:22 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Tom,

On Thu, 28 Oct 2021 at 13:19, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 28, 2021 at 12:48:50PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 28 Oct 2021 at 12:36, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > > > > Hi Tom,
> > > > > >
> > > > > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > > > > >
> > > > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > >
> > > > > > > > It introduces the following concepts:
> > > > > > > >
> > > > > > > >    - bootdev - a device which can hold a distro
> > > > > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > > > >                 U-Boot)
> > > > > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > > > > >
> > > > > > > > This series provides an implementation of these, enabled to scan for
> > > > > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > > > > similiarly to the existing script-based approach, but is native to
> > > > > > > > U-Boot.
> > > > > > >
> > > > > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > > > > re-investigate on their own, it's really just this series, right here,
> > > > > > > adding tons of code.  To replace an admittedly complex bit of
> > > > > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > > > > uclass and core implementation" and keeps going from there.
> > > > > >
> > > > > > Yes it does add a lot of code, although it is a lot less if the
> > > > > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > > > > scan -b'. At the moment it enables all dev features.
> > > > >
> > > > > OK, for the next go-round yes, please show what a typical enablement
> > > > > would look like on Pi, for example.
> > > >
> > > > OK. Do understand that conceiving of this and implementing it is quite
> > > > a bit of effort. At some point I just send things out, to get feedback
> > > > and to think some more. Apart from anything else, there is a risk of
> > > > going into the weeds or never finishing it.
> > > >
> > > > >
> > > > > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > > > > drops by 3.5KB.
> > > > >
> > > > > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > > > > win.
> > > >
> > > > Certainly not on size! On testing, debug, visibility and control of
> > > > the boot process, there are wins.
> > >
> > > I'm not sure if there's wins on those grounds either, and certainly not
> > > enough to justify what this adds.
> > >
> > > > > > We should compare this with the EFI support which is about 90KB, as I recall.
> > > > >
> > > > > No, we shouldn't.  This isn't about replacing EFI, this is about
> > > > > replacing the generic distro boot macros, so that's what the size
> > > > > comparison is to.  At the end of the day, and looking towards non-legacy
> > > > > uses, a big common use case is "Find the EFI app to run".
> > > >
> > > > I just mean that EFI has been accepted as part of U-Boot and adds 90KB.
> > >
> > > OK?  I still don't see the relevance here.
> > >
> > > > > > If we continue down the path of making this feature use U-Boot
> > > > > > functions directly, instead the command line, I suspect we can save
> > > > > > quite a bit more, since there is a lot of overhead with these
> > > > > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > > > > enabled, for example.
> > > > >
> > > > > Yes, this should be using the API and not the command interface.
> > > >
> > > > Right, but that's not something I am taking on right now. The PXE
> > > > refactoring gives an idea of what is needed. I did that work mainly
> > > > because I don't like adding to code that desperately needs
> > > > refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> > > > that might take a year.
> > >
> > > Well, maybe this particular part of things get set aside for now, and
> > > the generic distro boot framework just needs to be moved to the env
> > > update you did.
> > >
> > > > > > In any case, I think this feature is filling a gap in U-Boot since at
> > > > > > present everything about boot is ad-hoc. This gives us a base to build
> > > > > > on. Nothing is for free.
> > > > >
> > > > > I disagree.  At present, booting is either intentionally per-board, or
> > > > > it's using the generic distro boot framework.  That framework is what to
> > > > > further build on or perhaps make more readily simplified (for example,
> > > > > making it just be "scan around for EFI" or just be "scan around of
> > > > > extlinux.conf").
> > > >
> > > > Well if the Universal Bootloader is only going to exist to boot EFI,
> > > > then we should rename it :-)
> > > >
> > > > I am not sure that anyone wants something intentionally per-board,
> > >
> > > There's some cases, yes, where the system is supposed to do X (or Y, or
> > > Z).  Otherwise there's the generic framework.  Or...
> > >
> > > > it's just that everything about the boot in U-Boot is really low-level
> > > > (bootm, fixed addresses, etc.) We need the layer on top that can deal
> > > > with these silly details. For example, yes there is a Chrome OS boot
> > > > script in chromebook_coral, but it is the same on all devices. I would
> > > > rather just enable that bootmethod so that if Chrome OS is present it
> > > > will boot.
> > >
> > > there's things like what Chrome OS wants.
> > >
> > > > Re the memory side, i don't like the vars that define the kernel
> > > > address, FDT address, etc. It seems to me that most/all are
> > > > unnecessary, if there is something able to deal with memory allocatoin
> > > > automatically. Perhaps we should use malloc() more, or use LMB more
> > > > proactively.
> > >
> > > Well, in that for Linux, arm64 the Image format has a header that lets
> > > us avoid a number of problems that weren't possible on arm32, there's a
> > > tiny bit more flexibility there.  But it sounds like you're talking
> > > about "bootm_size" and "bootm_low" now.
> > >
> > > > Even for custom flows, creating a bootmethod will have advantages, I think.
> > > >
> > > > The other thing is that this allows further innovation. For verified
> > > > boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> > > > at present that is all just scripting, certainly not handled by distro
> > > > boot.
> > >
> > > No distros implement A/B updates directly.  When implemented on top of
> > > them it's done via the environment, yes.  I don't think adding Mender
> > > and RAUC and swupdate specific bootflow commands is a step in the right
> > > direction at all.
> > >
> > > > > > Anyway, I can look at what the minimum size is with the above points
> > > > > > and send that info through.
> > > > >
> > > > > I looked at the PXE stuff, and I think the minimal growth there ends up
> > > > > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > > > > where the code wasn't always sanity checking, as you reduced
> > > > > duplication.
> > > >
> > > > Yes and perhaps the growth can be reduced, too.
> > >
> > > It must be.  You need to be a lot closer to parity with the existing
> > > generic boot mechanism and around that size.  I am not liking what I'm
> > > seeing here so far.
> >
> > Just on this point, I'm pretty sure this will kill it. We cannot add
> > code without increasing the size! It sounds like 17KB on ARM64 is too
> > much (perhaps 13.5KB including env reduction). Firstly, why, and
> > secondly, how much is acceptable? If the answer is zero, we are not
> > going to go anywhere with this, at least without a huge amount of
> > future refactoring, which is not going to happen since we cannot land
> > 100s of patches all at once.
> >
> > The big prize would be to be able to disable CONFIG_CMDLINE and still
> > boot. That saves 200KB or more.
>
> I think the problem is this just needs to get put on hold for a while.
> I am not convinced this is moving things in the right direction.
> Conceptually, it's duplicating a lot of the efi bootmgr functionality,
> but also adding in non-block devices.  And I am not liking configuring
> this via device tree, rather than environment.  Lets move the generic
> distro framework to the new env framework and continue finishing off
> other technical debts that we have, before we re-visit a brand new way
> of handling booting.

OMG, please, no :-)  That would be a mess IMO. We should have done a
proper boot framework when distroboot was created, instead of all the
scripts.

Now it's seems we need to stick with that, or move to EFI bootmgr?

Is the new env framework agreed? I'd love to see some reviews from Wolfgang.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 22:22                 ` Simon Glass
@ 2021-10-28 22:50                   ` Tom Rini
  2021-10-29  1:13                     ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-28 22:50 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 10901 bytes --]

On Thu, Oct 28, 2021 at 04:22:11PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 28 Oct 2021 at 13:19, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 28, 2021 at 12:48:50PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Thu, 28 Oct 2021 at 12:36, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > > > > > Hi Tom,
> > > > > > >
> > > > > > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > >
> > > > > > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > > > > > >
> > > > > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > > >
> > > > > > > > > It introduces the following concepts:
> > > > > > > > >
> > > > > > > > >    - bootdev - a device which can hold a distro
> > > > > > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > > > > >                 U-Boot)
> > > > > > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > >
> > > > > > > > > This series provides an implementation of these, enabled to scan for
> > > > > > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > > > > > similiarly to the existing script-based approach, but is native to
> > > > > > > > > U-Boot.
> > > > > > > >
> > > > > > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > > > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > > > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > > > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > > > > > re-investigate on their own, it's really just this series, right here,
> > > > > > > > adding tons of code.  To replace an admittedly complex bit of
> > > > > > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > > > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > > > > > uclass and core implementation" and keeps going from there.
> > > > > > >
> > > > > > > Yes it does add a lot of code, although it is a lot less if the
> > > > > > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > > > > > scan -b'. At the moment it enables all dev features.
> > > > > >
> > > > > > OK, for the next go-round yes, please show what a typical enablement
> > > > > > would look like on Pi, for example.
> > > > >
> > > > > OK. Do understand that conceiving of this and implementing it is quite
> > > > > a bit of effort. At some point I just send things out, to get feedback
> > > > > and to think some more. Apart from anything else, there is a risk of
> > > > > going into the weeds or never finishing it.
> > > > >
> > > > > >
> > > > > > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > > > > > drops by 3.5KB.
> > > > > >
> > > > > > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > > > > > win.
> > > > >
> > > > > Certainly not on size! On testing, debug, visibility and control of
> > > > > the boot process, there are wins.
> > > >
> > > > I'm not sure if there's wins on those grounds either, and certainly not
> > > > enough to justify what this adds.
> > > >
> > > > > > > We should compare this with the EFI support which is about 90KB, as I recall.
> > > > > >
> > > > > > No, we shouldn't.  This isn't about replacing EFI, this is about
> > > > > > replacing the generic distro boot macros, so that's what the size
> > > > > > comparison is to.  At the end of the day, and looking towards non-legacy
> > > > > > uses, a big common use case is "Find the EFI app to run".
> > > > >
> > > > > I just mean that EFI has been accepted as part of U-Boot and adds 90KB.
> > > >
> > > > OK?  I still don't see the relevance here.
> > > >
> > > > > > > If we continue down the path of making this feature use U-Boot
> > > > > > > functions directly, instead the command line, I suspect we can save
> > > > > > > quite a bit more, since there is a lot of overhead with these
> > > > > > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > > > > > enabled, for example.
> > > > > >
> > > > > > Yes, this should be using the API and not the command interface.
> > > > >
> > > > > Right, but that's not something I am taking on right now. The PXE
> > > > > refactoring gives an idea of what is needed. I did that work mainly
> > > > > because I don't like adding to code that desperately needs
> > > > > refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> > > > > that might take a year.
> > > >
> > > > Well, maybe this particular part of things get set aside for now, and
> > > > the generic distro boot framework just needs to be moved to the env
> > > > update you did.
> > > >
> > > > > > > In any case, I think this feature is filling a gap in U-Boot since at
> > > > > > > present everything about boot is ad-hoc. This gives us a base to build
> > > > > > > on. Nothing is for free.
> > > > > >
> > > > > > I disagree.  At present, booting is either intentionally per-board, or
> > > > > > it's using the generic distro boot framework.  That framework is what to
> > > > > > further build on or perhaps make more readily simplified (for example,
> > > > > > making it just be "scan around for EFI" or just be "scan around of
> > > > > > extlinux.conf").
> > > > >
> > > > > Well if the Universal Bootloader is only going to exist to boot EFI,
> > > > > then we should rename it :-)
> > > > >
> > > > > I am not sure that anyone wants something intentionally per-board,
> > > >
> > > > There's some cases, yes, where the system is supposed to do X (or Y, or
> > > > Z).  Otherwise there's the generic framework.  Or...
> > > >
> > > > > it's just that everything about the boot in U-Boot is really low-level
> > > > > (bootm, fixed addresses, etc.) We need the layer on top that can deal
> > > > > with these silly details. For example, yes there is a Chrome OS boot
> > > > > script in chromebook_coral, but it is the same on all devices. I would
> > > > > rather just enable that bootmethod so that if Chrome OS is present it
> > > > > will boot.
> > > >
> > > > there's things like what Chrome OS wants.
> > > >
> > > > > Re the memory side, i don't like the vars that define the kernel
> > > > > address, FDT address, etc. It seems to me that most/all are
> > > > > unnecessary, if there is something able to deal with memory allocatoin
> > > > > automatically. Perhaps we should use malloc() more, or use LMB more
> > > > > proactively.
> > > >
> > > > Well, in that for Linux, arm64 the Image format has a header that lets
> > > > us avoid a number of problems that weren't possible on arm32, there's a
> > > > tiny bit more flexibility there.  But it sounds like you're talking
> > > > about "bootm_size" and "bootm_low" now.
> > > >
> > > > > Even for custom flows, creating a bootmethod will have advantages, I think.
> > > > >
> > > > > The other thing is that this allows further innovation. For verified
> > > > > boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> > > > > at present that is all just scripting, certainly not handled by distro
> > > > > boot.
> > > >
> > > > No distros implement A/B updates directly.  When implemented on top of
> > > > them it's done via the environment, yes.  I don't think adding Mender
> > > > and RAUC and swupdate specific bootflow commands is a step in the right
> > > > direction at all.
> > > >
> > > > > > > Anyway, I can look at what the minimum size is with the above points
> > > > > > > and send that info through.
> > > > > >
> > > > > > I looked at the PXE stuff, and I think the minimal growth there ends up
> > > > > > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > > > > > where the code wasn't always sanity checking, as you reduced
> > > > > > duplication.
> > > > >
> > > > > Yes and perhaps the growth can be reduced, too.
> > > >
> > > > It must be.  You need to be a lot closer to parity with the existing
> > > > generic boot mechanism and around that size.  I am not liking what I'm
> > > > seeing here so far.
> > >
> > > Just on this point, I'm pretty sure this will kill it. We cannot add
> > > code without increasing the size! It sounds like 17KB on ARM64 is too
> > > much (perhaps 13.5KB including env reduction). Firstly, why, and
> > > secondly, how much is acceptable? If the answer is zero, we are not
> > > going to go anywhere with this, at least without a huge amount of
> > > future refactoring, which is not going to happen since we cannot land
> > > 100s of patches all at once.
> > >
> > > The big prize would be to be able to disable CONFIG_CMDLINE and still
> > > boot. That saves 200KB or more.
> >
> > I think the problem is this just needs to get put on hold for a while.
> > I am not convinced this is moving things in the right direction.
> > Conceptually, it's duplicating a lot of the efi bootmgr functionality,
> > but also adding in non-block devices.  And I am not liking configuring
> > this via device tree, rather than environment.  Lets move the generic
> > distro framework to the new env framework and continue finishing off
> > other technical debts that we have, before we re-visit a brand new way
> > of handling booting.
> 
> OMG, please, no :-)  That would be a mess IMO. We should have done a
> proper boot framework when distroboot was created, instead of all the
> scripts.
> 
> Now it's seems we need to stick with that, or move to EFI bootmgr?

I'm not sure if EFI bootmgr is going to cover the cases, or not.  But
yes, in so far as I have problems with the current distro boot, it's
that dealing with strings in C kinda sucks.  Having that be plain text
will be good.

> Is the new env framework agreed? I'd love to see some reviews from Wolfgang.

I believe the new env framework is agreed, yes.  So long as "complex"
environments can be constructed and dropped in some way or another
outside of the new tooling, that's good enough.

> 
> Regards,
> Simon

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/41] Initial implementation of standard boot
  2021-10-28 22:50                   ` Tom Rini
@ 2021-10-29  1:13                     ` Simon Glass
  0 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-29  1:13 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Ilias Apalodimas, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore, Jaehoon Chung,
	Marek Vasut, Masahiro Yamada, Pavel Herrmann, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Tom,

On Thu, 28 Oct 2021 at 16:50, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 28, 2021 at 04:22:11PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 28 Oct 2021 at 13:19, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Oct 28, 2021 at 12:48:50PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Thu, 28 Oct 2021 at 12:36, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Thu, Oct 28, 2021 at 12:13:56PM -0600, Simon Glass wrote:
> > > > > > Hi Tom,
> > > > > >
> > > > > > On Thu, 28 Oct 2021 at 11:52, Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > On Thu, Oct 28, 2021 at 11:29:35AM -0600, Simon Glass wrote:
> > > > > > > > Hi Tom,
> > > > > > > >
> > > > > > > > On Thu, 28 Oct 2021 at 10:27, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > >
> > > > > > > > > On Sat, Oct 23, 2021 at 05:25:54PM -0600, Simon Glass wrote:
> > > > > > > > >
> > > > > > > > > > The bootflow feature provide a built-in way for U-Boot to automatically
> > > > > > > > > > boot an Operating System without custom scripting and other customisation.
> > > > > > > > > > This is called 'standard boot' since it provides a standard way for
> > > > > > > > > > U-Boot to boot a distro, without scripting.
> > > > > > > > > >
> > > > > > > > > > It introduces the following concepts:
> > > > > > > > > >
> > > > > > > > > >    - bootdev - a device which can hold a distro
> > > > > > > > > >    - bootmeth - a method to scan a bootdev to find bootflows (owned by
> > > > > > > > > >                 U-Boot)
> > > > > > > > > >    - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > >
> > > > > > > > > > This series provides an implementation of these, enabled to scan for
> > > > > > > > > > bootflows from MMC, USB and Ethernet. It supports the existing distro
> > > > > > > > > > boot as well as the EFI loader flow (bootefi/bootmgr). It works
> > > > > > > > > > similiarly to the existing script-based approach, but is native to
> > > > > > > > > > U-Boot.
> > > > > > > > >
> > > > > > > > > I'm going to break my feedback down in to a few threads, to hopefully
> > > > > > > > > not confuse things too much.  My first comment is that rpi_arm64 grows
> > > > > > > > > in size by 17 kilobytes, with the whole series (pxe, env, this) applied.
> > > > > > > > > And while there's a few small changes in the pxe cleanup I'm going to
> > > > > > > > > re-investigate on their own, it's really just this series, right here,
> > > > > > > > > adding tons of code.  To replace an admittedly complex bit of
> > > > > > > > > environment scripting, with C.  It's not even the earlier parts of the
> > > > > > > > > series to clean up / prepare, it starts at "bootstd: Add the bootstd
> > > > > > > > > uclass and core implementation" and keeps going from there.
> > > > > > > >
> > > > > > > > Yes it does add a lot of code, although it is a lot less if the
> > > > > > > > commands are disabled or simplified, e.g. to only support 'bootflow
> > > > > > > > scan -b'. At the moment it enables all dev features.
> > > > > > >
> > > > > > > OK, for the next go-round yes, please show what a typical enablement
> > > > > > > would look like on Pi, for example.
> > > > > >
> > > > > > OK. Do understand that conceiving of this and implementing it is quite
> > > > > > a bit of effort. At some point I just send things out, to get feedback
> > > > > > and to think some more. Apart from anything else, there is a risk of
> > > > > > going into the weeds or never finishing it.
> > > > > >
> > > > > > >
> > > > > > > > It does save a small amount of data. E.g. rpi_3_32b environment goes
> > > > > > > > drops by 3.5KB.
> > > > > > >
> > > > > > > So we're replacing 3.5KB of scripts with 17KB of code.  That is not a
> > > > > > > win.
> > > > > >
> > > > > > Certainly not on size! On testing, debug, visibility and control of
> > > > > > the boot process, there are wins.
> > > > >
> > > > > I'm not sure if there's wins on those grounds either, and certainly not
> > > > > enough to justify what this adds.
> > > > >
> > > > > > > > We should compare this with the EFI support which is about 90KB, as I recall.
> > > > > > >
> > > > > > > No, we shouldn't.  This isn't about replacing EFI, this is about
> > > > > > > replacing the generic distro boot macros, so that's what the size
> > > > > > > comparison is to.  At the end of the day, and looking towards non-legacy
> > > > > > > uses, a big common use case is "Find the EFI app to run".
> > > > > >
> > > > > > I just mean that EFI has been accepted as part of U-Boot and adds 90KB.
> > > > >
> > > > > OK?  I still don't see the relevance here.
> > > > >
> > > > > > > > If we continue down the path of making this feature use U-Boot
> > > > > > > > functions directly, instead the command line, I suspect we can save
> > > > > > > > quite a bit more, since there is a lot of overhead with these
> > > > > > > > commands. At present it is impossible to boot without CONFIG_CMDLINE
> > > > > > > > enabled, for example.
> > > > > > >
> > > > > > > Yes, this should be using the API and not the command interface.
> > > > > >
> > > > > > Right, but that's not something I am taking on right now. The PXE
> > > > > > refactoring gives an idea of what is needed. I did that work mainly
> > > > > > because I don't like adding to code that desperately needs
> > > > > > refactoring. We need to do the same for dhcp, EFI and bootm/zboot, but
> > > > > > that might take a year.
> > > > >
> > > > > Well, maybe this particular part of things get set aside for now, and
> > > > > the generic distro boot framework just needs to be moved to the env
> > > > > update you did.
> > > > >
> > > > > > > > In any case, I think this feature is filling a gap in U-Boot since at
> > > > > > > > present everything about boot is ad-hoc. This gives us a base to build
> > > > > > > > on. Nothing is for free.
> > > > > > >
> > > > > > > I disagree.  At present, booting is either intentionally per-board, or
> > > > > > > it's using the generic distro boot framework.  That framework is what to
> > > > > > > further build on or perhaps make more readily simplified (for example,
> > > > > > > making it just be "scan around for EFI" or just be "scan around of
> > > > > > > extlinux.conf").
> > > > > >
> > > > > > Well if the Universal Bootloader is only going to exist to boot EFI,
> > > > > > then we should rename it :-)
> > > > > >
> > > > > > I am not sure that anyone wants something intentionally per-board,
> > > > >
> > > > > There's some cases, yes, where the system is supposed to do X (or Y, or
> > > > > Z).  Otherwise there's the generic framework.  Or...
> > > > >
> > > > > > it's just that everything about the boot in U-Boot is really low-level
> > > > > > (bootm, fixed addresses, etc.) We need the layer on top that can deal
> > > > > > with these silly details. For example, yes there is a Chrome OS boot
> > > > > > script in chromebook_coral, but it is the same on all devices. I would
> > > > > > rather just enable that bootmethod so that if Chrome OS is present it
> > > > > > will boot.
> > > > >
> > > > > there's things like what Chrome OS wants.
> > > > >
> > > > > > Re the memory side, i don't like the vars that define the kernel
> > > > > > address, FDT address, etc. It seems to me that most/all are
> > > > > > unnecessary, if there is something able to deal with memory allocatoin
> > > > > > automatically. Perhaps we should use malloc() more, or use LMB more
> > > > > > proactively.
> > > > >
> > > > > Well, in that for Linux, arm64 the Image format has a header that lets
> > > > > us avoid a number of problems that weren't possible on arm32, there's a
> > > > > tiny bit more flexibility there.  But it sounds like you're talking
> > > > > about "bootm_size" and "bootm_low" now.
> > > > >
> > > > > > Even for custom flows, creating a bootmethod will have advantages, I think.
> > > > > >
> > > > > > The other thing is that this allows further innovation. For verified
> > > > > > boot, it makes it possible to sensibly deal with A/B;recovery, whereas
> > > > > > at present that is all just scripting, certainly not handled by distro
> > > > > > boot.
> > > > >
> > > > > No distros implement A/B updates directly.  When implemented on top of
> > > > > them it's done via the environment, yes.  I don't think adding Mender
> > > > > and RAUC and swupdate specific bootflow commands is a step in the right
> > > > > direction at all.
> > > > >
> > > > > > > > Anyway, I can look at what the minimum size is with the above points
> > > > > > > > and send that info through.
> > > > > > >
> > > > > > > I looked at the PXE stuff, and I think the minimal growth there ends up
> > > > > > > being reasonable, fwiw.  It comes down to adding sanity checks in places
> > > > > > > where the code wasn't always sanity checking, as you reduced
> > > > > > > duplication.
> > > > > >
> > > > > > Yes and perhaps the growth can be reduced, too.
> > > > >
> > > > > It must be.  You need to be a lot closer to parity with the existing
> > > > > generic boot mechanism and around that size.  I am not liking what I'm
> > > > > seeing here so far.
> > > >
> > > > Just on this point, I'm pretty sure this will kill it. We cannot add
> > > > code without increasing the size! It sounds like 17KB on ARM64 is too
> > > > much (perhaps 13.5KB including env reduction). Firstly, why, and
> > > > secondly, how much is acceptable? If the answer is zero, we are not
> > > > going to go anywhere with this, at least without a huge amount of
> > > > future refactoring, which is not going to happen since we cannot land
> > > > 100s of patches all at once.
> > > >
> > > > The big prize would be to be able to disable CONFIG_CMDLINE and still
> > > > boot. That saves 200KB or more.
> > >
> > > I think the problem is this just needs to get put on hold for a while.
> > > I am not convinced this is moving things in the right direction.
> > > Conceptually, it's duplicating a lot of the efi bootmgr functionality,
> > > but also adding in non-block devices.  And I am not liking configuring
> > > this via device tree, rather than environment.  Lets move the generic
> > > distro framework to the new env framework and continue finishing off
> > > other technical debts that we have, before we re-visit a brand new way
> > > of handling booting.
> >
> > OMG, please, no :-)  That would be a mess IMO. We should have done a
> > proper boot framework when distroboot was created, instead of all the
> > scripts.
> >
> > Now it's seems we need to stick with that, or move to EFI bootmgr?
>
> I'm not sure if EFI bootmgr is going to cover the cases, or not.  But
> yes, in so far as I have problems with the current distro boot, it's
> that dealing with strings in C kinda sucks.  Having that be plain text
> will be good.

I'm sure EFI bootmgr will cover all the *EFI* cases, by definition. No
one will understand it, though...

Yes the scripts themselves are not ideal. It is great that we have
this feature but it will be even better to have proper U-Boot support
for booting, I think. But anyway, I'll do the analysis I talked about
and deal with any other feedback and we can park it for now.

I'd still like you to think about what would be an acceptable
increment in terms of code size (you cannot say zero!)

>
> > Is the new env framework agreed? I'd love to see some reviews from Wolfgang.
>
> I believe the new env framework is agreed, yes.  So long as "complex"
> environments can be constructed and dropped in some way or another
> outside of the new tooling, that's good enough.

Well I was planning on migrating env_default.h but we can leave that
for later I suppose.

I am pretty sure we will need to enhance it, but we can see how it
goes. I'd like to get rid of the sandbox config file, at least. I got
someway down the path there, so will dig up the patches.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-27 18:34           ` Simon Glass
@ 2021-10-29  5:45             ` Ilias Apalodimas
  2021-10-29 12:39               ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-29  5:45 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> Hi Ilias,
> 
> On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > Hi Ilias,
> > >
> > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > >
> > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > so it does not require any special scripts, etc.
> > > > >
> > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > >
> > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > I don't see why we should duplicate the functionality.  The new boot
> > > > method can just have an entry called 'EFI' and then let the existing
> > > > EFI code to decide.
> > >
> > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > being used then it can still be invoked from standard boot. The point
> > > is that there is a standard way of booting that supports EFI and other
> > > things.
> >
> > This patch tries to reason about the default naming EFI imposes on it's
> > boot files. distro_efi_read_bootflow() will try to find files following the
> > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > found it will try to boot them right?  That's not the right thing to do though.
> > On the EFI spec these files are tried if no Boot#### variables are found.
> > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > says 'boot the efi manager' (which is what the next patch does).
> >
> > The efibootmgr then will check Boot#### variables and if none are found,
> > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > essentially offering identical functionality.
> 
> Yes that's fine, and when EFI's boot manager is in use I have a driver
> for that too, as you can see in the other patch. We may need to adjust
> the order, by the sound of it, if it needs to run before EFI things.
> But that is easy enough.
> 

That's the point though.  I don't want to have 2 different ways of booting EFI
as I don't see any benefit.  Do you?

Regards
/Ilias

> But we do need to provide the existing functionality for now, as I
> understand it.
> 
> > > This series is about replacing the scripts we currently have with a
> > > proper C implementation that uses driver model.
> > >
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29  5:45             ` Ilias Apalodimas
@ 2021-10-29 12:39               ` Tom Rini
  2021-10-29 13:42                 ` Ilias Apalodimas
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-10-29 12:39 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Simon Glass, U-Boot Mailing List, Michal Simek,
	Heinrich Schuchardt, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

[-- Attachment #1: Type: text/plain, Size: 3299 bytes --]

On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > Hi Ilias,
> > 
> > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > Hi Ilias,
> > > >
> > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > >
> > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > so it does not require any special scripts, etc.
> > > > > >
> > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > >
> > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > EFI code to decide.
> > > >
> > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > being used then it can still be invoked from standard boot. The point
> > > > is that there is a standard way of booting that supports EFI and other
> > > > things.
> > >
> > > This patch tries to reason about the default naming EFI imposes on it's
> > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > found it will try to boot them right?  That's not the right thing to do though.
> > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > says 'boot the efi manager' (which is what the next patch does).
> > >
> > > The efibootmgr then will check Boot#### variables and if none are found,
> > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > essentially offering identical functionality.
> > 
> > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > for that too, as you can see in the other patch. We may need to adjust
> > the order, by the sound of it, if it needs to run before EFI things.
> > But that is easy enough.
> 
> That's the point though.  I don't want to have 2 different ways of booting EFI
> as I don't see any benefit.  Do you?

Unless we're saying that "bootefi bootmgr" is ready to be used always
and without further pre-req support (which I don't think is quite the
case, since we don't have persistent EFI vars, so can't set Boot###
persistently or via userspace) _something_ is likely needed to either
set those, or scan a configurable list of where, to find the EFI
payload.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29 12:39               ` Tom Rini
@ 2021-10-29 13:42                 ` Ilias Apalodimas
  2021-10-29 14:03                   ` AKASHI Takahiro
  2021-10-29 16:37                   ` Mark Kettenis
  0 siblings, 2 replies; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-29 13:42 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, U-Boot Mailing List, Michal Simek,
	Heinrich Schuchardt, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Behún, Lukas Auer, Dennis Gilmore

Hi Tom,

On Fri, 29 Oct 2021 at 15:39, Tom Rini <trini@konsulko.com> wrote:
>
> On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> > On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > > Hi Ilias,
> > >
> > > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > > >
> > > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > > so it does not require any special scripts, etc.
> > > > > > >
> > > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > > >
> > > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > > EFI code to decide.
> > > > >
> > > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > > being used then it can still be invoked from standard boot. The point
> > > > > is that there is a standard way of booting that supports EFI and other
> > > > > things.
> > > >
> > > > This patch tries to reason about the default naming EFI imposes on it's
> > > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > > found it will try to boot them right?  That's not the right thing to do though.
> > > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > > says 'boot the efi manager' (which is what the next patch does).
> > > >
> > > > The efibootmgr then will check Boot#### variables and if none are found,
> > > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > > essentially offering identical functionality.
> > >
> > > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > > for that too, as you can see in the other patch. We may need to adjust
> > > the order, by the sound of it, if it needs to run before EFI things.
> > > But that is easy enough.
> >
> > That's the point though.  I don't want to have 2 different ways of booting EFI
> > as I don't see any benefit.  Do you?
>
> Unless we're saying that "bootefi bootmgr" is ready to be used always
> and without further pre-req support (which I don't think is quite the
> case, since we don't have persistent EFI vars, so can't set Boot###
> persistently or via userspace) _something_ is likely needed to either
> set those, or scan a configurable list of where, to find the EFI
> payload.

The efibootmgr will try to boot bootaa64.efi, bootarm.efi etc if
Boot### variables are not found.  The Boot#### themselves are
obviously configurable from U-Boot(at boot time).  Since this method
doesn't allow Linux to edit the boot options either, is it something
we need?  Since distros usually name their SHIM as bootaa64.efi, I am
afraid we are adding code that we will rarely (if at all) ever use.

Regards


/Ilias
>
> --
> Tom

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29 13:42                 ` Ilias Apalodimas
@ 2021-10-29 14:03                   ` AKASHI Takahiro
  2021-10-29 14:39                     ` Ilias Apalodimas
  2021-10-29 16:37                   ` Mark Kettenis
  1 sibling, 1 reply; 116+ messages in thread
From: AKASHI Takahiro @ 2021-10-29 14:03 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Simon Glass, U-Boot Mailing List, Michal Simek,
	Heinrich Schuchardt, Daniel Schwierzeck, Steffen Jaeckel,
	Marek Beh??n, Lukas Auer, Dennis Gilmore

On Fri, Oct 29, 2021 at 04:42:45PM +0300, Ilias Apalodimas wrote:
> Hi Tom,
> 
> On Fri, 29 Oct 2021 at 15:39, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> > > On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > > > Hi Ilias,
> > > >
> > > > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > > > >
> > > > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > > > so it does not require any special scripts, etc.
> > > > > > > >
> > > > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > > > >
> > > > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > > > EFI code to decide.
> > > > > >
> > > > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > > > being used then it can still be invoked from standard boot. The point
> > > > > > is that there is a standard way of booting that supports EFI and other
> > > > > > things.
> > > > >
> > > > > This patch tries to reason about the default naming EFI imposes on it's
> > > > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > > > found it will try to boot them right?  That's not the right thing to do though.
> > > > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > > > says 'boot the efi manager' (which is what the next patch does).
> > > > >
> > > > > The efibootmgr then will check Boot#### variables and if none are found,
> > > > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > > > essentially offering identical functionality.
> > > >
> > > > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > > > for that too, as you can see in the other patch. We may need to adjust
> > > > the order, by the sound of it, if it needs to run before EFI things.
> > > > But that is easy enough.
> > >
> > > That's the point though.  I don't want to have 2 different ways of booting EFI
> > > as I don't see any benefit.  Do you?
> >
> > Unless we're saying that "bootefi bootmgr" is ready to be used always
> > and without further pre-req support (which I don't think is quite the
> > case, since we don't have persistent EFI vars, so can't set Boot###
> > persistently or via userspace) _something_ is likely needed to either
> > set those, or scan a configurable list of where, to find the EFI
> > payload.
> 
> The efibootmgr will try to boot bootaa64.efi, bootarm.efi etc if
> Boot### variables are not found.

To be clear, the current efibootmgr (or "bootefi bootmgr" command)
doesn't have this feature. Instead, distro_bootcmd mimics it in some way.
# I have an experimental patch to efibootmgr for the support, though.

Nevertheless,

> The Boot#### themselves are
> obviously configurable from U-Boot(at boot time).  Since this method
> doesn't allow Linux to edit the boot options either,>

Yeah. Please remember that, even on normal PCs, specifying an order of
boot devices (for "removable media" with the default path) is done
through UEFI UI.

-Takahiro Akashi

> is it something
> we need?  Since distros usually name their SHIM as bootaa64.efi, I am
> afraid we are adding code that we will rarely (if at all) ever use.
> 
> Regards
> 
> 
> /Ilias
> >
> > --
> > Tom

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29 14:03                   ` AKASHI Takahiro
@ 2021-10-29 14:39                     ` Ilias Apalodimas
  0 siblings, 0 replies; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-29 14:39 UTC (permalink / raw)
  To: AKASHI Takahiro, Ilias Apalodimas, Tom Rini, Simon Glass,
	U-Boot Mailing List, Michal Simek, Heinrich Schuchardt,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Beh??n, Lukas Auer,
	Dennis Gilmore

On Fri, 29 Oct 2021 at 17:03, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Fri, Oct 29, 2021 at 04:42:45PM +0300, Ilias Apalodimas wrote:
> > Hi Tom,
> >
> > On Fri, 29 Oct 2021 at 15:39, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> > > > On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > > > > >
> > > > > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > > > > so it does not require any special scripts, etc.
> > > > > > > > >
> > > > > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > > > > >
> > > > > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > > > > EFI code to decide.
> > > > > > >
> > > > > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > > > > being used then it can still be invoked from standard boot. The point
> > > > > > > is that there is a standard way of booting that supports EFI and other
> > > > > > > things.
> > > > > >
> > > > > > This patch tries to reason about the default naming EFI imposes on it's
> > > > > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > > > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > > > > found it will try to boot them right?  That's not the right thing to do though.
> > > > > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > > > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > > > > says 'boot the efi manager' (which is what the next patch does).
> > > > > >
> > > > > > The efibootmgr then will check Boot#### variables and if none are found,
> > > > > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > > > > essentially offering identical functionality.
> > > > >
> > > > > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > > > > for that too, as you can see in the other patch. We may need to adjust
> > > > > the order, by the sound of it, if it needs to run before EFI things.
> > > > > But that is easy enough.
> > > >
> > > > That's the point though.  I don't want to have 2 different ways of booting EFI
> > > > as I don't see any benefit.  Do you?
> > >
> > > Unless we're saying that "bootefi bootmgr" is ready to be used always
> > > and without further pre-req support (which I don't think is quite the
> > > case, since we don't have persistent EFI vars, so can't set Boot###
> > > persistently or via userspace) _something_ is likely needed to either
> > > set those, or scan a configurable list of where, to find the EFI
> > > payload.
> >
> > The efibootmgr will try to boot bootaa64.efi, bootarm.efi etc if
> > Boot### variables are not found.
>
> To be clear, the current efibootmgr (or "bootefi bootmgr" command)
> doesn't have this feature. Instead, distro_bootcmd mimics it in some way.
> # I have an experimental patch to efibootmgr for the support, though.

Ah thanks Akashi!  I thought we had that already. In any case it makes
much more sense adding that to efibootmgr, instead of inventing yet
another way to do that, doesn't it?

>
> Nevertheless,
>
> > The Boot#### themselves are
> > obviously configurable from U-Boot(at boot time).  Since this method
> > doesn't allow Linux to edit the boot options either,>
>
> Yeah. Please remember that, even on normal PCs, specifying an order of
> boot devices (for "removable media" with the default path) is done
> through UEFI UI.
>
> -Takahiro Akashi
>
> > is it something
> > we need?  Since distros usually name their SHIM as bootaa64.efi, I am
> > afraid we are adding code that we will rarely (if at all) ever use.
> >
> > Regards
> >
> >
> > /Ilias
> > >
> > > --
> > > Tom

Regards
/Ilias

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29 13:42                 ` Ilias Apalodimas
  2021-10-29 14:03                   ` AKASHI Takahiro
@ 2021-10-29 16:37                   ` Mark Kettenis
  2021-10-29 17:08                     ` Ilias Apalodimas
  1 sibling, 1 reply; 116+ messages in thread
From: Mark Kettenis @ 2021-10-29 16:37 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: trini, sjg, u-boot, michal.simek, xypron.glpk,
	daniel.schwierzeck, jaeckel-floss, marek.behun, lukas.auer,
	dennis

> From: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Date: Fri, 29 Oct 2021 16:42:45 +0300
> 
> Hi Tom,
> 
> On Fri, 29 Oct 2021 at 15:39, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> > > On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > > > Hi Ilias,
> > > >
> > > > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > > > >
> > > > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > > > so it does not require any special scripts, etc.
> > > > > > > >
> > > > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > > > >
> > > > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > > > EFI code to decide.
> > > > > >
> > > > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > > > being used then it can still be invoked from standard boot. The point
> > > > > > is that there is a standard way of booting that supports EFI and other
> > > > > > things.
> > > > >
> > > > > This patch tries to reason about the default naming EFI imposes on it's
> > > > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > > > found it will try to boot them right?  That's not the right thing to do though.
> > > > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > > > says 'boot the efi manager' (which is what the next patch does).
> > > > >
> > > > > The efibootmgr then will check Boot#### variables and if none are found,
> > > > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > > > essentially offering identical functionality.
> > > >
> > > > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > > > for that too, as you can see in the other patch. We may need to adjust
> > > > the order, by the sound of it, if it needs to run before EFI things.
> > > > But that is easy enough.
> > >
> > > That's the point though.  I don't want to have 2 different ways of booting EFI
> > > as I don't see any benefit.  Do you?
> >
> > Unless we're saying that "bootefi bootmgr" is ready to be used always
> > and without further pre-req support (which I don't think is quite the
> > case, since we don't have persistent EFI vars, so can't set Boot###
> > persistently or via userspace) _something_ is likely needed to either
> > set those, or scan a configurable list of where, to find the EFI
> > payload.
> 
> The efibootmgr will try to boot bootaa64.efi, bootarm.efi etc if
> Boot### variables are not found.  The Boot#### themselves are
> obviously configurable from U-Boot(at boot time).  Since this method
> doesn't allow Linux to edit the boot options either, is it something
> we need?  Since distros usually name their SHIM as bootaa64.efi, I am
> afraid we are adding code that we will rarely (if at all) ever use.

Hi Ilias,

I'm still seeing:

  Device 0: Vendor: Lexar    Rev: 1100 Prod: USB Flash Drive
              Type: Removable Hard Disk
              Capacity: 30526.0 MB = 29.8 GB (62517248 x 512)
  ... is now current device
  Scanning usb 0:1...
  ** Unable to read file / **
  Failed to load '/'
  libfdt fdt_check_header(): FDT_ERR_BADMAGIC
  BootOrder not defined
  EFI boot manager: Cannot load any image
  Found EFI removable media binary efi/boot/bootaa64.efi
  170694 bytes read in 9 ms (18.1 MiB/s)
  libfdt fdt_check_header(): FDT_ERR_BADMAGIC
  Booting /efi\boot\bootaa64.efi

So it doesn't seem that efibootmgr will try to bootaa64.efi just yet.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 31/41] bootstd: Add an implementation of EFI boot
  2021-10-29 16:37                   ` Mark Kettenis
@ 2021-10-29 17:08                     ` Ilias Apalodimas
  0 siblings, 0 replies; 116+ messages in thread
From: Ilias Apalodimas @ 2021-10-29 17:08 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: trini, sjg, u-boot, michal.simek, xypron.glpk,
	daniel.schwierzeck, jaeckel-floss, marek.behun, lukas.auer,
	dennis

Hi Mark,

On Fri, 29 Oct 2021 at 19:37, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>
> > From: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Date: Fri, 29 Oct 2021 16:42:45 +0300
> >
> > Hi Tom,
> >
> > On Fri, 29 Oct 2021 at 15:39, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Fri, Oct 29, 2021 at 08:45:06AM +0300, Ilias Apalodimas wrote:
> > > > On Wed, Oct 27, 2021 at 12:34:40PM -0600, Simon Glass wrote:
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 27 Oct 2021 at 08:48, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Wed, Oct 27, 2021 at 08:09:04AM -0600, Simon Glass wrote:
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 27 Oct 2021 at 02:36, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > > On Sun, 24 Oct 2021 at 02:27, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Add a bootmeth driver which handles EFI boot, using EFI_LOADER.
> > > > > > > > >
> > > > > > > > > In effect, this provides the same functionality as the 'bootefi' command
> > > > > > > > > and shares the same code. But the interface into it is via a bootmeth,
> > > > > > > > > so it does not require any special scripts, etc.
> > > > > > > > >
> > > > > > > > > For now this requires the 'bootefi' command be enabled. Future work may
> > > > > > > > > tidy this up so that it can be used without CONFIG_CMDLINE being enabled.
> > > > > > > >
> > > > > > > > I'll leave this up to Heinrich, but personally I wouldn't include this
> > > > > > > > patch at all. EFI has it's bootmgr which can handle booting just fine.
> > > > > > > > I don't see why we should duplicate the functionality.  The new boot
> > > > > > > > method can just have an entry called 'EFI' and then let the existing
> > > > > > > > EFI code to decide.
> > > > > > >
> > > > > > > This is needed so that EFI boot is actually invoked. If bootmgr starts
> > > > > > > being used then it can still be invoked from standard boot. The point
> > > > > > > is that there is a standard way of booting that supports EFI and other
> > > > > > > things.
> > > > > >
> > > > > > This patch tries to reason about the default naming EFI imposes on it's
> > > > > > boot files. distro_efi_read_bootflow() will try to find files following the
> > > > > > EFI naming convention (e.g bootaarch64.efi, bootarm.efi etc).  If those are
> > > > > > found it will try to boot them right?  That's not the right thing to do though.
> > > > > > On the EFI spec these files are tried if no Boot#### variables are found.
> > > > > > So we can get rid of this entirely,  add a dummy entry on the bootflow that
> > > > > > says 'boot the efi manager' (which is what the next patch does).
> > > > > >
> > > > > > The efibootmgr then will check Boot#### variables and if none are found,
> > > > > > it's going to fallback into loading bootaarch64.efi, bootarm.efi etc
> > > > > > essentially offering identical functionality.
> > > > >
> > > > > Yes that's fine, and when EFI's boot manager is in use I have a driver
> > > > > for that too, as you can see in the other patch. We may need to adjust
> > > > > the order, by the sound of it, if it needs to run before EFI things.
> > > > > But that is easy enough.
> > > >
> > > > That's the point though.  I don't want to have 2 different ways of booting EFI
> > > > as I don't see any benefit.  Do you?
> > >
> > > Unless we're saying that "bootefi bootmgr" is ready to be used always
> > > and without further pre-req support (which I don't think is quite the
> > > case, since we don't have persistent EFI vars, so can't set Boot###
> > > persistently or via userspace) _something_ is likely needed to either
> > > set those, or scan a configurable list of where, to find the EFI
> > > payload.
> >
> > The efibootmgr will try to boot bootaa64.efi, bootarm.efi etc if
> > Boot### variables are not found.  The Boot#### themselves are
> > obviously configurable from U-Boot(at boot time).  Since this method
> > doesn't allow Linux to edit the boot options either, is it something
> > we need?  Since distros usually name their SHIM as bootaa64.efi, I am
> > afraid we are adding code that we will rarely (if at all) ever use.
>
> Hi Ilias,
>
> I'm still seeing:
>
>   Device 0: Vendor: Lexar    Rev: 1100 Prod: USB Flash Drive
>               Type: Removable Hard Disk
>               Capacity: 30526.0 MB = 29.8 GB (62517248 x 512)
>   ... is now current device
>   Scanning usb 0:1...
>   ** Unable to read file / **
>   Failed to load '/'
>   libfdt fdt_check_header(): FDT_ERR_BADMAGIC
>   BootOrder not defined
>   EFI boot manager: Cannot load any image
>   Found EFI removable media binary efi/boot/bootaa64.efi
>   170694 bytes read in 9 ms (18.1 MiB/s)
>   libfdt fdt_check_header(): FDT_ERR_BADMAGIC
>   Booting /efi\boot\bootaa64.efi
>
> So it doesn't seem that efibootmgr will try to bootaa64.efi just yet.

Yea Akashi-san already corrected me on this one.  I was somehow under
the impression we do that already, while it's the distro bootcmd doing
that.  In any case it would make much more sense for me to add the
missing pieces in the efibootmgr, instead of an extra app.  That way
we can either cleanup the distro bootmcd or skip this patch when
Simon's proposal gets resubmitted.

Thanks!
/Ilias
>
> Cheers,
>
> Mark

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-27 12:21       ` Heinrich Schuchardt
  2021-10-27 13:13         ` Tom Rini
@ 2021-10-31 23:45         ` Simon Glass
  1 sibling, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-10-31 23:45 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: U-Boot Mailing List, Michal Simek, Tom Rini, Daniel Schwierzeck,
	Steffen Jaeckel, Marek Behún, Lukas Auer, Dennis Gilmore,
	Masahiro Yamada, Ilias Apalodimas, Heinrich Schuchardt

Hi Heinrich,

On Wed, 27 Oct 2021 at 06:21, Heinrich Schuchardt
<heinrich.schuchardt@canonical.com> wrote:
>
>
>
> On 10/27/21 10:50, Ilias Apalodimas wrote:
> > Hi Simon
> >
> > How does this patch related to the standard boot series? Shouldn't
> > this be a completely separate patch?

Probably, but I lose track of all the branches in progress,
particularly when things sit for a while.

> >
> > Thanks
> > /Ilias
> >
> > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> >>
> >> LTO (Link-Time Optimisation) is an very useful feature which can
> >> significantly reduce the size of U-Boot binaries. So far it has been
> >> made available for selected ARM boards and sandbox.
> >>
> >> However, incremental builds are much slower when LTO is used. For example,
> >> an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> >> seconds with LTO enabled.
> >>
> >> Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> >> development if needed, for faster builds.
> >>
> >> Add some documentation about LTO while we are here.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >>
> >> (no changes since v1)
> >>
> >>   Makefile                           | 18 +++++++++++++-----
> >>   arch/arm/config.mk                 |  4 ++--
> >>   arch/arm/include/asm/global_data.h |  2 +-
> >>   doc/build/gcc.rst                  | 17 +++++++++++++++++
> >>   4 files changed, 33 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/Makefile b/Makefile
> >> index b79b2319ff6..7057723e046 100644
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> >>   KBUILD_AFLAGS   := -D__ASSEMBLY__
> >>   KBUILD_LDFLAGS  :=
> >>
> >> +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> >> +LTO_BUILD      ?= y
>
> This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
>
> We should have something like
>
> LTO_CONFIG ?= $CONFIG_LTO

The CONFIG indicates that LTO is supported, so if we want to do that,
we could fix the problems with LTO for a board/arch and send a patch
to enable it. I think we want it enabled by default.

[..]

Regards

Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-27 13:13         ` Tom Rini
@ 2021-10-31 23:46           ` Simon Glass
  2021-11-01 21:58             ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-10-31 23:46 UTC (permalink / raw)
  To: Tom Rini
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

Hi Tom,

On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> >
> >
> > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > Hi Simon
> > >
> > > How does this patch related to the standard boot series? Shouldn't
> > > this be a completely separate patch?
> > >
> > > Thanks
> > > /Ilias
> > >
> > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > made available for selected ARM boards and sandbox.
> > > >
> > > > However, incremental builds are much slower when LTO is used. For example,
> > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > seconds with LTO enabled.
> > > >
> > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > development if needed, for faster builds.
> > > >
> > > > Add some documentation about LTO while we are here.
> > > >
> > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > ---
> > > >
> > > > (no changes since v1)
> > > >
> > > >   Makefile                           | 18 +++++++++++++-----
> > > >   arch/arm/config.mk                 |  4 ++--
> > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/Makefile b/Makefile
> > > > index b79b2319ff6..7057723e046 100644
> > > > --- a/Makefile
> > > > +++ b/Makefile
> > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > >   KBUILD_LDFLAGS  :=
> > > >
> > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > +LTO_BUILD      ?= y
> >
> > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
>
> I don't understand why we need this patch at all.  If you want to
> disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> be annoying on iterative development.  I have a few different "HACK: DO
> NOT PUSH:  ..." things I git am at the start of a branch, depending on
> needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> that can be disabled in the defconfig, or local .config file even.
>

Cranky time.

Of course we don't *need* it. I could just buy a slower build machine
and type with two fingers. There are lots of ways to slow things down
and LTO is one of them. I change branches at least a dozen times a day
and am always trying things out from patchwork. I am sure others do
too. LTO dramatically slows down builds. Having a way to easily do
this from the build system saves time.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-10-31 23:46           ` Simon Glass
@ 2021-11-01 21:58             ` Tom Rini
  2021-11-04  2:49               ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-11-01 21:58 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

[-- Attachment #1: Type: text/plain, Size: 3421 bytes --]

On Sun, Oct 31, 2021 at 05:46:43PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> > >
> > >
> > > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > > Hi Simon
> > > >
> > > > How does this patch related to the standard boot series? Shouldn't
> > > > this be a completely separate patch?
> > > >
> > > > Thanks
> > > > /Ilias
> > > >
> > > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > > made available for selected ARM boards and sandbox.
> > > > >
> > > > > However, incremental builds are much slower when LTO is used. For example,
> > > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > > seconds with LTO enabled.
> > > > >
> > > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > > development if needed, for faster builds.
> > > > >
> > > > > Add some documentation about LTO while we are here.
> > > > >
> > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > ---
> > > > >
> > > > > (no changes since v1)
> > > > >
> > > > >   Makefile                           | 18 +++++++++++++-----
> > > > >   arch/arm/config.mk                 |  4 ++--
> > > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > > >
> > > > > diff --git a/Makefile b/Makefile
> > > > > index b79b2319ff6..7057723e046 100644
> > > > > --- a/Makefile
> > > > > +++ b/Makefile
> > > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > > >   KBUILD_LDFLAGS  :=
> > > > >
> > > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > > +LTO_BUILD      ?= y
> > >
> > > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
> >
> > I don't understand why we need this patch at all.  If you want to
> > disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> > be annoying on iterative development.  I have a few different "HACK: DO
> > NOT PUSH:  ..." things I git am at the start of a branch, depending on
> > needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> > in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> > that can be disabled in the defconfig, or local .config file even.
> >
> 
> Cranky time.
> 
> Of course we don't *need* it. I could just buy a slower build machine
> and type with two fingers. There are lots of ways to slow things down
> and LTO is one of them. I change branches at least a dozen times a day
> and am always trying things out from patchwork. I am sure others do
> too. LTO dramatically slows down builds. Having a way to easily do
> this from the build system saves time.

Maybe the answer is that LTO just isn't appropriate for sandbox.  We're
not doing any specific tests for LTO anywhere (nor does that seem
appropriate), and we do have platforms in CI that run tests other than
building, with LTO.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-11-01 21:58             ` Tom Rini
@ 2021-11-04  2:49               ` Simon Glass
  2021-11-04 14:55                 ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-11-04  2:49 UTC (permalink / raw)
  To: Tom Rini
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

Hi Tom,

On Mon, 1 Nov 2021 at 15:58, Tom Rini <trini@konsulko.com> wrote:
>
> On Sun, Oct 31, 2021 at 05:46:43PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> > > >
> > > >
> > > > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > > > Hi Simon
> > > > >
> > > > > How does this patch related to the standard boot series? Shouldn't
> > > > > this be a completely separate patch?
> > > > >
> > > > > Thanks
> > > > > /Ilias
> > > > >
> > > > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > > > made available for selected ARM boards and sandbox.
> > > > > >
> > > > > > However, incremental builds are much slower when LTO is used. For example,
> > > > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > > > seconds with LTO enabled.
> > > > > >
> > > > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > > > development if needed, for faster builds.
> > > > > >
> > > > > > Add some documentation about LTO while we are here.
> > > > > >
> > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > ---
> > > > > >
> > > > > > (no changes since v1)
> > > > > >
> > > > > >   Makefile                           | 18 +++++++++++++-----
> > > > > >   arch/arm/config.mk                 |  4 ++--
> > > > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > > > >
> > > > > > diff --git a/Makefile b/Makefile
> > > > > > index b79b2319ff6..7057723e046 100644
> > > > > > --- a/Makefile
> > > > > > +++ b/Makefile
> > > > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > > > >   KBUILD_LDFLAGS  :=
> > > > > >
> > > > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > > > +LTO_BUILD      ?= y
> > > >
> > > > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
> > >
> > > I don't understand why we need this patch at all.  If you want to
> > > disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> > > be annoying on iterative development.  I have a few different "HACK: DO
> > > NOT PUSH:  ..." things I git am at the start of a branch, depending on
> > > needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> > > in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> > > that can be disabled in the defconfig, or local .config file even.
> > >
> >
> > Cranky time.
> >
> > Of course we don't *need* it. I could just buy a slower build machine
> > and type with two fingers. There are lots of ways to slow things down
> > and LTO is one of them. I change branches at least a dozen times a day
> > and am always trying things out from patchwork. I am sure others do
> > too. LTO dramatically slows down builds. Having a way to easily do
> > this from the build system saves time.
>
> Maybe the answer is that LTO just isn't appropriate for sandbox.  We're
> not doing any specific tests for LTO anywhere (nor does that seem
> appropriate), and we do have platforms in CI that run tests other than
> building, with LTO.

It has value as a test, I presume, and a demo of how it works. Also it
runs most of the tests.

But I'm happy to disable it if that helps.

Still, it doesn't really solve the issue. The same thing happens when
building real boards.

Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-11-04  2:49               ` Simon Glass
@ 2021-11-04 14:55                 ` Tom Rini
  2021-11-04 15:12                   ` Simon Glass
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Rini @ 2021-11-04 14:55 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

[-- Attachment #1: Type: text/plain, Size: 4960 bytes --]

On Wed, Nov 03, 2021 at 08:49:01PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Mon, 1 Nov 2021 at 15:58, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Sun, Oct 31, 2021 at 05:46:43PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> > > > >
> > > > >
> > > > > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > > > > Hi Simon
> > > > > >
> > > > > > How does this patch related to the standard boot series? Shouldn't
> > > > > > this be a completely separate patch?
> > > > > >
> > > > > > Thanks
> > > > > > /Ilias
> > > > > >
> > > > > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > > > > made available for selected ARM boards and sandbox.
> > > > > > >
> > > > > > > However, incremental builds are much slower when LTO is used. For example,
> > > > > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > > > > seconds with LTO enabled.
> > > > > > >
> > > > > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > > > > development if needed, for faster builds.
> > > > > > >
> > > > > > > Add some documentation about LTO while we are here.
> > > > > > >
> > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > ---
> > > > > > >
> > > > > > > (no changes since v1)
> > > > > > >
> > > > > > >   Makefile                           | 18 +++++++++++++-----
> > > > > > >   arch/arm/config.mk                 |  4 ++--
> > > > > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > > > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > > > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > > > > >
> > > > > > > diff --git a/Makefile b/Makefile
> > > > > > > index b79b2319ff6..7057723e046 100644
> > > > > > > --- a/Makefile
> > > > > > > +++ b/Makefile
> > > > > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > > > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > > > > >   KBUILD_LDFLAGS  :=
> > > > > > >
> > > > > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > > > > +LTO_BUILD      ?= y
> > > > >
> > > > > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
> > > >
> > > > I don't understand why we need this patch at all.  If you want to
> > > > disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> > > > be annoying on iterative development.  I have a few different "HACK: DO
> > > > NOT PUSH:  ..." things I git am at the start of a branch, depending on
> > > > needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> > > > in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> > > > that can be disabled in the defconfig, or local .config file even.
> > > >
> > >
> > > Cranky time.
> > >
> > > Of course we don't *need* it. I could just buy a slower build machine
> > > and type with two fingers. There are lots of ways to slow things down
> > > and LTO is one of them. I change branches at least a dozen times a day
> > > and am always trying things out from patchwork. I am sure others do
> > > too. LTO dramatically slows down builds. Having a way to easily do
> > > this from the build system saves time.
> >
> > Maybe the answer is that LTO just isn't appropriate for sandbox.  We're
> > not doing any specific tests for LTO anywhere (nor does that seem
> > appropriate), and we do have platforms in CI that run tests other than
> > building, with LTO.
> 
> It has value as a test, I presume, and a demo of how it works. Also it
> runs most of the tests.
> 
> But I'm happy to disable it if that helps.
> 
> Still, it doesn't really solve the issue. The same thing happens when
> building real boards.

Well, a big part of the problem here is I strongly disagree with a
make-line flag to override a CONFIG option.  I also hear your use case
of "I build this platform so frequently per development session it's a
noticeable slowdown and a 'LOCAL:' commit will also screw up my
workflow".  So where do we go?  LTO is a size versus speed trade-off
(and -ffunction-sections/-fdata-sections/--gc-unused is a much smaller
speed trade-off) that's more important on real hardware (and also not
used as often as it might be, at least so far).  On real boards, there's
less of a "just turn it off" option because it's required to be small
enough to use on the hardware.  Since that's not the case on sandbox,
maybe we just need to turn it on in more QEMU platforms (to get broader
test coverage in CI) and off in sandbox.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-11-04 14:55                 ` Tom Rini
@ 2021-11-04 15:12                   ` Simon Glass
  2021-11-04 16:44                     ` Tom Rini
  0 siblings, 1 reply; 116+ messages in thread
From: Simon Glass @ 2021-11-04 15:12 UTC (permalink / raw)
  To: Tom Rini
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

Hi Tom,

On Thu, 4 Nov 2021 at 08:55, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Nov 03, 2021 at 08:49:01PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Mon, 1 Nov 2021 at 15:58, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Sun, Oct 31, 2021 at 05:46:43PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> > > > > >
> > > > > >
> > > > > > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > > > > > Hi Simon
> > > > > > >
> > > > > > > How does this patch related to the standard boot series? Shouldn't
> > > > > > > this be a completely separate patch?
> > > > > > >
> > > > > > > Thanks
> > > > > > > /Ilias
> > > > > > >
> > > > > > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > > > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > > > > > made available for selected ARM boards and sandbox.
> > > > > > > >
> > > > > > > > However, incremental builds are much slower when LTO is used. For example,
> > > > > > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > > > > > seconds with LTO enabled.
> > > > > > > >
> > > > > > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > > > > > development if needed, for faster builds.
> > > > > > > >
> > > > > > > > Add some documentation about LTO while we are here.
> > > > > > > >
> > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > > ---
> > > > > > > >
> > > > > > > > (no changes since v1)
> > > > > > > >
> > > > > > > >   Makefile                           | 18 +++++++++++++-----
> > > > > > > >   arch/arm/config.mk                 |  4 ++--
> > > > > > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > > > > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > > > > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/Makefile b/Makefile
> > > > > > > > index b79b2319ff6..7057723e046 100644
> > > > > > > > --- a/Makefile
> > > > > > > > +++ b/Makefile
> > > > > > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > > > > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > > > > > >   KBUILD_LDFLAGS  :=
> > > > > > > >
> > > > > > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > > > > > +LTO_BUILD      ?= y
> > > > > >
> > > > > > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
> > > > >
> > > > > I don't understand why we need this patch at all.  If you want to
> > > > > disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> > > > > be annoying on iterative development.  I have a few different "HACK: DO
> > > > > NOT PUSH:  ..." things I git am at the start of a branch, depending on
> > > > > needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> > > > > in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> > > > > that can be disabled in the defconfig, or local .config file even.
> > > > >
> > > >
> > > > Cranky time.
> > > >
> > > > Of course we don't *need* it. I could just buy a slower build machine
> > > > and type with two fingers. There are lots of ways to slow things down
> > > > and LTO is one of them. I change branches at least a dozen times a day
> > > > and am always trying things out from patchwork. I am sure others do
> > > > too. LTO dramatically slows down builds. Having a way to easily do
> > > > this from the build system saves time.
> > >
> > > Maybe the answer is that LTO just isn't appropriate for sandbox.  We're
> > > not doing any specific tests for LTO anywhere (nor does that seem
> > > appropriate), and we do have platforms in CI that run tests other than
> > > building, with LTO.
> >
> > It has value as a test, I presume, and a demo of how it works. Also it
> > runs most of the tests.
> >
> > But I'm happy to disable it if that helps.
> >
> > Still, it doesn't really solve the issue. The same thing happens when
> > building real boards.
>
> Well, a big part of the problem here is I strongly disagree with a
> make-line flag to override a CONFIG option.  I also hear your use case
> of "I build this platform so frequently per development session it's a
> noticeable slowdown and a 'LOCAL:' commit will also screw up my
> workflow".  So where do we go?  LTO is a size versus speed trade-off
> (and -ffunction-sections/-fdata-sections/--gc-unused is a much smaller
> speed trade-off) that's more important on real hardware (and also not
> used as often as it might be, at least so far).  On real boards, there's
> less of a "just turn it off" option because it's required to be small
> enough to use on the hardware.  Since that's not the case on sandbox,
> maybe we just need to turn it on in more QEMU platforms (to get broader
> test coverage in CI) and off in sandbox.

This is all true...and certainly sandbox would solve the main issue I
have. If we turn it off for sandbox we should perhaps have CI turn it
on...

It is similar to the dtc thing, where we have a DTC variable to avoid
pointlessly building dtc. I guess you are worried about having too
many of these sorts of things?

Regards,
SImon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build
  2021-11-04 15:12                   ` Simon Glass
@ 2021-11-04 16:44                     ` Tom Rini
  0 siblings, 0 replies; 116+ messages in thread
From: Tom Rini @ 2021-11-04 16:44 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, U-Boot Mailing List, Michal Simek,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Masahiro Yamada, Ilias Apalodimas,
	Heinrich Schuchardt

[-- Attachment #1: Type: text/plain, Size: 6145 bytes --]

On Thu, Nov 04, 2021 at 09:12:02AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 4 Nov 2021 at 08:55, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Nov 03, 2021 at 08:49:01PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Mon, 1 Nov 2021 at 15:58, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Sun, Oct 31, 2021 at 05:46:43PM -0600, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Wed, 27 Oct 2021 at 07:13, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Wed, Oct 27, 2021 at 02:21:17PM +0200, Heinrich Schuchardt wrote:
> > > > > > >
> > > > > > >
> > > > > > > On 10/27/21 10:50, Ilias Apalodimas wrote:
> > > > > > > > Hi Simon
> > > > > > > >
> > > > > > > > How does this patch related to the standard boot series? Shouldn't
> > > > > > > > this be a completely separate patch?
> > > > > > > >
> > > > > > > > Thanks
> > > > > > > > /Ilias
> > > > > > > >
> > > > > > > > On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > LTO (Link-Time Optimisation) is an very useful feature which can
> > > > > > > > > significantly reduce the size of U-Boot binaries. So far it has been
> > > > > > > > > made available for selected ARM boards and sandbox.
> > > > > > > > >
> > > > > > > > > However, incremental builds are much slower when LTO is used. For example,
> > > > > > > > > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7
> > > > > > > > > seconds with LTO enabled.
> > > > > > > > >
> > > > > > > > > Add a LTO_BUILD=n parameter to the build, so it can be disabled during
> > > > > > > > > development if needed, for faster builds.
> > > > > > > > >
> > > > > > > > > Add some documentation about LTO while we are here.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > > > ---
> > > > > > > > >
> > > > > > > > > (no changes since v1)
> > > > > > > > >
> > > > > > > > >   Makefile                           | 18 +++++++++++++-----
> > > > > > > > >   arch/arm/config.mk                 |  4 ++--
> > > > > > > > >   arch/arm/include/asm/global_data.h |  2 +-
> > > > > > > > >   doc/build/gcc.rst                  | 17 +++++++++++++++++
> > > > > > > > >   4 files changed, 33 insertions(+), 8 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/Makefile b/Makefile
> > > > > > > > > index b79b2319ff6..7057723e046 100644
> > > > > > > > > --- a/Makefile
> > > > > > > > > +++ b/Makefile
> > > > > > > > > @@ -434,6 +434,9 @@ KBUILD_CFLAGS       += -fshort-wchar -fno-strict-aliasing
> > > > > > > > >   KBUILD_AFLAGS   := -D__ASSEMBLY__
> > > > > > > > >   KBUILD_LDFLAGS  :=
> > > > > > > > >
> > > > > > > > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n
> > > > > > > > > +LTO_BUILD      ?= y
> > > > > > >
> > > > > > > This does not allow LTO_BUILD=y to enable LTO for CONFIG_LTO=n.
> > > > > >
> > > > > > I don't understand why we need this patch at all.  If you want to
> > > > > > disable LTO, disable LTO.  Yes, LTO makes linking take longer which can
> > > > > > be annoying on iterative development.  I have a few different "HACK: DO
> > > > > > NOT PUSH:  ..." things I git am at the start of a branch, depending on
> > > > > > needs.  You can just do that to drop "imply LTO" from the SANDBOX stanza
> > > > > > in arch/Kconfig.  We do not need a whole thing around a CONFIG option
> > > > > > that can be disabled in the defconfig, or local .config file even.
> > > > > >
> > > > >
> > > > > Cranky time.
> > > > >
> > > > > Of course we don't *need* it. I could just buy a slower build machine
> > > > > and type with two fingers. There are lots of ways to slow things down
> > > > > and LTO is one of them. I change branches at least a dozen times a day
> > > > > and am always trying things out from patchwork. I am sure others do
> > > > > too. LTO dramatically slows down builds. Having a way to easily do
> > > > > this from the build system saves time.
> > > >
> > > > Maybe the answer is that LTO just isn't appropriate for sandbox.  We're
> > > > not doing any specific tests for LTO anywhere (nor does that seem
> > > > appropriate), and we do have platforms in CI that run tests other than
> > > > building, with LTO.
> > >
> > > It has value as a test, I presume, and a demo of how it works. Also it
> > > runs most of the tests.
> > >
> > > But I'm happy to disable it if that helps.
> > >
> > > Still, it doesn't really solve the issue. The same thing happens when
> > > building real boards.
> >
> > Well, a big part of the problem here is I strongly disagree with a
> > make-line flag to override a CONFIG option.  I also hear your use case
> > of "I build this platform so frequently per development session it's a
> > noticeable slowdown and a 'LOCAL:' commit will also screw up my
> > workflow".  So where do we go?  LTO is a size versus speed trade-off
> > (and -ffunction-sections/-fdata-sections/--gc-unused is a much smaller
> > speed trade-off) that's more important on real hardware (and also not
> > used as often as it might be, at least so far).  On real boards, there's
> > less of a "just turn it off" option because it's required to be small
> > enough to use on the hardware.  Since that's not the case on sandbox,
> > maybe we just need to turn it on in more QEMU platforms (to get broader
> > test coverage in CI) and off in sandbox.
> 
> This is all true...and certainly sandbox would solve the main issue I
> have. If we turn it off for sandbox we should perhaps have CI turn it
> on...
> 
> It is similar to the dtc thing, where we have a DTC variable to avoid
> pointlessly building dtc. I guess you are worried about having too
> many of these sorts of things?

Well, the DTC thing to me is at least a case of "external tool exists,
stop building it when it's already provided, versioning tools like this
is bad".  LTO is a thing that impact the build itself and can (so long
as it fits in hardware still) be enabled/disabled by the user.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 18/41] test/py: Raise a ValueError if a command fails
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (44 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
                     ` (11 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

At present an Exception is raised if a command fails. This is a very broad
class and makes it difficult for callers to catch the error without also
catching other things, like programming bugs.

Change it to ValueError to make this easier.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/multiplexed_log.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 17/41] test/py: Relax the naming rules for unit tests
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (43 preceding siblings ...)
  2021-10-28 16:27   ` Tom Rini
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
                     ` (12 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

At present the collection function used by pytest is quite strict on the
naming of the functions it detects. In particular it requires the name of
the test to be repeated in the function name.

This is not enforced anywhere else, but instead the tests are silently
omitted from the pytest run. This affects a few dozen tests.

The rule does not seem to have any particular purpose. Relax it, so that
all tests that use the UNIT_TEST() macro will run, regardless of the name
of the test function.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/conftest.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (46 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
                     ` (9 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	U-Boot Mailing List

Add a function that returns the number of devices in a uclass. This can be
helpful in sizing an array that needs to hold a list of them.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/uclass.c | 12 ++++++++++++
 include/dm/uclass.h   |  8 ++++++++
 2 files changed, 20 insertions(+)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (45 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
                     ` (10 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, U-Boot Mailing List

At present the hexdump tests are disabled in sandbox_flattree. This is
good, because they do not pass. Enable the required Kconfig so that they
will, when enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 configs/sandbox_flattree_defconfig | 1 +
 1 file changed, 1 insertion(+)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (47 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
                     ` (8 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	U-Boot Mailing List

In some cases it is useful to search just by a partial name, such as
when looking for a sibling device that has a common name substring. Add
helper functions to handle these requirements.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/device.c | 13 ++++++++++---
 drivers/core/uclass.c |  9 +++++++--
 include/dm/device.h   | 12 ++++++++++++
 include/dm/uclass.h   |  9 +++++++++
 4 files changed, 38 insertions(+), 5 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/41] dm: core: Add a way to obtain a string list
  2021-10-26 19:20     ` Ilias Apalodimas
@ 2021-11-24 22:22       ` Simon Glass
  2021-11-24 22:23       ` Simon Glass
  1 sibling, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	Ilias Apalodimas

Hi Ilias,

On Tue, 26 Oct 2021 at 13:21, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> >
> > At present we support reading a string list a string at a time. Apart
> > from being inefficient, this makes it impossible to separate reading of
> > the devicetree into the of_to_plat() method where it belongs, since any
> > code which needs access to the string must read it from the devicetree.
> >
> > Add a function which returns the string property as an array of pointers
> > to the strings, which is easily used by clients.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > (no changes since v1)
> >
> >  drivers/core/ofnode.c | 26 ++++++++++++++++++++++++++
> >  drivers/core/read.c   |  6 ++++++
> >  include/dm/ofnode.h   | 20 ++++++++++++++++++++
> >  include/dm/read.h     | 28 ++++++++++++++++++++++++++++
> >  test/dm/ofnode.c      | 20 ++++++++++++++++++++
> >  5 files changed, 100 insertions(+)
> >
Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 12/41] dm: core: Fix up string-function documentation
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (49 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
                     ` (6 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	U-Boot Mailing List

The details for of_property_read_string_helper() and
ofnode_read_string_index() are a little inaccurate. Fix up the comments to
avoid confusion.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/of_access.c | 3 ++-
 include/dm/ofnode.h      | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (48 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
                     ` (7 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	U-Boot Mailing List

This method is currently called after the platform data has been freed.
But the pre_unbind() method may wish to access this, e.g. to free some
data structures stored there.

Split the unbinding of devices into two pieces, as is done with removal.
This corrects the problem.

Also tidy a code-style issue in device_remove() while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/core/device-remove.c |  9 +++++----
 drivers/core/uclass.c        |  8 +++++++-
 include/dm/uclass-internal.h | 14 +++++++++++++-
 3 files changed, 25 insertions(+), 6 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 10/41] dm: core: Add tests for stringlist functions
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (52 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
                     ` (3 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann,
	U-Boot Mailing List

These functions currently lack tests so add some. The error handling
differs betwee livetree and flattree at present, so only check the error
codes with livetree.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/sandbox/dts/test.dts |  1 +
 test/dm/ofnode.c          | 76 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (50 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
                     ` (5 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, U-Boot Mailing List

When ext is NULL we cannot dereference it. Update the code flow to avoid
this, so that layout_mbr_partitions() can be used with partition tables
that do not include an extended partition.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 disk/part_dos.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (51 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
                     ` (4 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, U-Boot Mailing List

Before relocation there is generally not as much available memory and not
that much console output. At present the console-output buffer is the same
side before and after relocation. Add a separate Kconfig option to remove
this limitation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 common/Kconfig   | 10 ++++++++++
 common/console.c |  4 +++-
 2 files changed, 13 insertions(+), 1 deletion(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/41] mbr: Correct verification check
  2021-10-23 23:26   ` [PATCH v2 07/41] mbr: Correct verification check Simon Glass
  2021-10-27  7:41     ` Ilias Apalodimas
@ 2021-11-24 22:22     ` Simon Glass
  1 sibling, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Simon Glass

Hi Simon,

On Sat, Oct 23, 2021 at 05:26:01PM -0600, Simon Glass wrote:
> At present this command considers the partitions to be identical if the
> start and size are smaller than expected. It should check that they are
> the same. Fix this and tidy up the code style a little.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> (no changes since v1)
>
>  cmd/mbr.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 06/41] mmc: Allow for children other than the block device
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (53 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
                     ` (2 subsequent siblings)
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Peng Fan,
	U-Boot Mailing List

At present the MMC uclass assumes that the only child it can have is a
block device. Update this so we can add a bootmethod too.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/mmc/mmc-uclass.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 04/41] sandbox: Support unmapping a file
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (55 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, U-Boot Mailing List

Add the opposite of mapping, so that we can unmap and avoid running out of
address space.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/sandbox/cpu/os.c | 10 ++++++++++
 include/os.h          |  9 +++++++++
 2 files changed, 19 insertions(+)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 05/41] sandbox: mmc: Support a backing file
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (54 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  2021-11-24 22:22   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
  2021-11-24 22:22   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Jaehoon Chung, Peng Fan,
	U-Boot Mailing List

Provide a way for sandbox MMC to present data from a backing file. This
allows a filesystem to be created on the host and easily served via an
emulated mmc device.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v2:
- Free the memory buffer, to avoid running out of memory
- Unmap the file
- Reorder struct sandbox_mmc_priv

 doc/device-tree-bindings/mmc/sandbox,mmc.txt | 18 ++++++
 drivers/mmc/sandbox_mmc.c                    | 60 +++++++++++++++++---
 2 files changed, 69 insertions(+), 9 deletions(-)
 create mode 100644 doc/device-tree-bindings/mmc/sandbox,mmc.txt

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 03/41] test/py: Allow passing input to a program
  2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
                     ` (56 preceding siblings ...)
  2021-11-24 22:22   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
@ 2021-11-24 22:22   ` Simon Glass
  57 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Michal Simek, Heinrich Schuchardt, Tom Rini, Ilias Apalodimas,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Stephen Warren, Stephen Warren,
	U-Boot Mailing List

When running a program on the host, allow input to be passed in as stdin.
This is needed for running sfdisk, for example.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 test/py/multiplexed_log.py | 8 +++++---
 test/py/u_boot_utils.py    | 5 +++--
 2 files changed, 8 insertions(+), 5 deletions(-)

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/41] dm: core: Add a way to obtain a string list
  2021-10-26 19:20     ` Ilias Apalodimas
  2021-11-24 22:22       ` Simon Glass
@ 2021-11-24 22:23       ` Simon Glass
  1 sibling, 0 replies; 116+ messages in thread
From: Simon Glass @ 2021-11-24 22:23 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore, Marek Vasut, Pavel Herrmann

Hi Ilias,

On Tue, 26 Oct 2021 at 13:21, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Sun, 24 Oct 2021 at 02:26, Simon Glass <sjg@chromium.org> wrote:
> >
> > At present we support reading a string list a string at a time. Apart
> > from being inefficient, this makes it impossible to separate reading of
> > the devicetree into the of_to_plat() method where it belongs, since any
> > code which needs access to the string must read it from the devicetree.
> >
> > Add a function which returns the string property as an array of pointers
> > to the strings, which is easily used by clients.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > (no changes since v1)
> >
> >  drivers/core/ofnode.c | 26 ++++++++++++++++++++++++++
> >  drivers/core/read.c   |  6 ++++++
> >  include/dm/ofnode.h   | 20 ++++++++++++++++++++
> >  include/dm/read.h     | 28 ++++++++++++++++++++++++++++
> >  test/dm/ofnode.c      | 20 ++++++++++++++++++++
> >  5 files changed, 100 insertions(+)
> >
> > diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
> > index 08705ef8d99..709bea272a6 100644
> > --- a/drivers/core/ofnode.c
> > +++ b/drivers/core/ofnode.c
> > @@ -456,6 +456,32 @@ int ofnode_read_string_count(ofnode node, const char *property)
> >         }
> >  }
> >
> > +int ofnode_read_string_list(ofnode node, const char *property,
> > +                           const char ***listp)
> > +{
> > +       const char **prop;
> > +       int count;
> > +       int i;
> > +
> > +       *listp = NULL;
> > +       count = ofnode_read_string_count(node, property);
> > +       if (count < 0)
> > +               return count;
> > +       if (!count)
> > +               return 0;
>
> Those can fold into a single if and always return 'count'.
> if (count <= 0)
>     return count;

Yes, but I prefer to deal with errors separately. The first case is an error.

>
> > +
> > +       prop = calloc(count + 1, sizeof(char *));
> [...]
Regards,
Simon

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 23/41] bootstd: Add support for bootflows
  2021-10-27  7:37     ` Ilias Apalodimas
@ 2022-03-12  2:24       ` Simon Glass
  0 siblings, 0 replies; 116+ messages in thread
From: Simon Glass @ 2022-03-12  2:24 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: U-Boot Mailing List, Michal Simek, Heinrich Schuchardt, Tom Rini,
	Daniel Schwierzeck, Steffen Jaeckel, Marek Behún,
	Lukas Auer, Dennis Gilmore

Hi Ilias,

On Wed, 27 Oct 2021 at 01:37, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> > +
>
> [...]
>
> > +/* error codes used to signal running out of things */
> > +enum {
> > +     BF_NO_MORE_PARTS        = -ESHUTDOWN,
> > +     BF_NO_MORE_DEVICES      = -ENODEV,
> > +};
> > +
> > +static const char *const bootflow_state[BOOTFLOWST_COUNT] = {
> > +     "base",
> > +     "media",
> > +     "part",
> > +     "fs",
> > +     "file",
> > +     "ready",
>
> I can understand 'ready' as a boot state.  What are the rest supposed to be
> ?

These are documented in the header file.

>
> > +};
> > +
> > +const char *bootflow_state_get_name(enum bootflow_state_t state)
> > +{
> > +     if (state < 0 || state >= BOOTFLOWST_COUNT)
> > +             return "?";
>
> s/?/Unknown/ or invalid maybe?

This is an invalid state so should not happen. Tom is pushing for the
minimum possible code size so it doesn't seem worth putting a
user-friendly error for a case that can't happen.


>
> > +
> > +     return bootflow_state[state];
> > +}
> > +
> > +int bootflow_first_glob(struct bootflow **bflowp)
> > +{
> > +     struct bootstd_priv *std;
>
> [...]
>
> Regards
> /Ilias

^ permalink raw reply	[flat|nested] 116+ messages in thread

end of thread, other threads:[~2022-03-12  2:25 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAPnjgZ2TFOQGoQ1+Vt6LRMk+nULj9joS0C7fMMiXfg7JNien7g@mail.gmail.com>
2021-10-23 23:25 ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
2021-10-23 23:25   ` [PATCH v2 01/41] lib: Add a way to find the postiion of a trailing number Simon Glass
2021-10-27 12:13     ` Heinrich Schuchardt
2021-10-23 23:25   ` [PATCH v2 02/41] Makefile: Allow LTO to be disabled for a build Simon Glass
2021-10-27  8:50     ` Ilias Apalodimas
2021-10-27 12:21       ` Heinrich Schuchardt
2021-10-27 13:13         ` Tom Rini
2021-10-31 23:46           ` Simon Glass
2021-11-01 21:58             ` Tom Rini
2021-11-04  2:49               ` Simon Glass
2021-11-04 14:55                 ` Tom Rini
2021-11-04 15:12                   ` Simon Glass
2021-11-04 16:44                     ` Tom Rini
2021-10-31 23:45         ` Simon Glass
2021-10-23 23:25   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass
2021-10-23 23:25   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
2021-10-23 23:25   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
2021-10-23 23:26   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
2021-10-23 23:26   ` [PATCH v2 07/41] mbr: Correct verification check Simon Glass
2021-10-27  7:41     ` Ilias Apalodimas
2021-11-24 22:22     ` Simon Glass
2021-10-23 23:26   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
2021-10-23 23:26   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
2021-10-23 23:26   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
2021-10-23 23:26   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
2021-10-23 23:26   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
2021-10-23 23:26   ` [PATCH v2 13/41] dm: core: Add a way to obtain a string list Simon Glass
2021-10-26 19:20     ` Ilias Apalodimas
2021-11-24 22:22       ` Simon Glass
2021-11-24 22:23       ` Simon Glass
2021-10-23 23:26   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
2021-10-23 23:26   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
2021-10-23 23:26   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
2021-10-23 23:26   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
2021-10-23 23:26   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
2021-10-23 23:26   ` [PATCH v2 19/41] bootstd: Add the concept of a bootflow Simon Glass
2021-10-23 23:26   ` [PATCH v2 20/41] bootstd: Add the bootstd uclass and core implementation Simon Glass
2021-10-23 23:26   ` [PATCH v2 21/41] bootstd: Add the bootdev uclass Simon Glass
2021-10-23 23:26   ` [PATCH v2 22/41] bootstd: Add the bootmeth uclass and helpers Simon Glass
2021-10-23 23:26   ` [PATCH v2 23/41] bootstd: Add support for bootflows Simon Glass
2021-10-27  7:37     ` Ilias Apalodimas
2022-03-12  2:24       ` Simon Glass
2021-10-23 23:26   ` [PATCH v2 24/41] bootstd: Add a bootdev command Simon Glass
2021-10-23 23:26   ` [PATCH v2 25/41] bootstd: Add a bootflow ommand Simon Glass
2021-10-23 23:26   ` [PATCH v2 26/41] bootstd: Add a bootmeth command Simon Glass
2021-10-23 23:26   ` [PATCH v2 27/41] bootstd: Add an implementation of distro boot Simon Glass
2021-10-23 23:26   ` [PATCH v2 28/41] bootstd: mmc: Add a bootdev driver Simon Glass
2021-10-23 23:26   ` [PATCH v2 29/41] bootstd: ethernet: " Simon Glass
2021-10-23 23:26   ` [PATCH v2 30/41] bootstd: Add an implementation of distro PXE boot Simon Glass
2021-10-23 23:26   ` [PATCH v2 31/41] bootstd: Add an implementation of EFI boot Simon Glass
2021-10-27  8:35     ` Ilias Apalodimas
2021-10-27 14:09       ` Simon Glass
2021-10-27 14:47         ` Ilias Apalodimas
2021-10-27 18:34           ` Simon Glass
2021-10-29  5:45             ` Ilias Apalodimas
2021-10-29 12:39               ` Tom Rini
2021-10-29 13:42                 ` Ilias Apalodimas
2021-10-29 14:03                   ` AKASHI Takahiro
2021-10-29 14:39                     ` Ilias Apalodimas
2021-10-29 16:37                   ` Mark Kettenis
2021-10-29 17:08                     ` Ilias Apalodimas
2021-10-27 11:57     ` Heinrich Schuchardt
2021-10-27 14:08       ` Simon Glass
2021-10-23 23:26   ` [PATCH v2 32/41] bootstd: Add a system bootdev for strange boot methods Simon Glass
2021-10-23 23:26   ` [PATCH v2 33/41] bootstd: Add an implementation of EFI bootmgr Simon Glass
2021-10-23 23:26   ` [PATCH v2 34/41] bootstd: Add a sandbox bootmeth driver Simon Glass
2021-10-23 23:26   ` [PATCH v2 35/41] bootstd: usb: Add a bootdev driver Simon Glass
2021-10-23 23:26   ` [PATCH v2 36/41] test: fastboot: Avoid using mmc1 Simon Glass
2021-10-23 23:26   ` [PATCH v2 37/41] test: dm: Restart USB before assuming it is stopped Simon Glass
2021-10-23 23:26   ` [PATCH v2 38/41] bootstd: Add tests for bootstd including all uclasses Simon Glass
2021-10-23 23:26   ` [PATCH v2 39/41] bootstd: Add setup for the bootflow tests Simon Glass
2021-10-23 23:26   ` [PATCH v2 40/41] bootstd: doc: Add documentation Simon Glass
2021-10-23 23:26   ` [PATCH v2 41/41] RFC: Switch rpi over to use bootstd Simon Glass
2021-10-28 15:13     ` Tom Rini
2021-10-28 16:43     ` Tom Rini
2021-10-28 17:16       ` Simon Glass
2021-10-28 17:29         ` Tom Rini
2021-10-23 23:27   ` [PATCH v2 00/41] Initial implementation of standard boot Simon Glass
2021-10-27 11:38   ` Heinrich Schuchardt
2021-10-27 14:11     ` Simon Glass
2021-10-28 17:37       ` Peter Robinson
2021-10-28 17:47         ` Tom Rini
2021-10-28 17:50           ` Peter Robinson
2021-10-28 17:59             ` Tom Rini
2021-10-28 18:09               ` Heinrich Schuchardt
2021-10-28 18:13                 ` Tom Rini
2021-10-28 18:17               ` François Ozog
2021-10-28 18:27                 ` Tom Rini
2021-10-28 18:28                   ` François Ozog
2021-10-28 21:40           ` Mark Kettenis
2021-10-27 15:20     ` François Ozog
2021-10-27 18:33     ` Simon Glass
2021-10-28 16:27   ` Tom Rini
2021-10-28 17:29     ` Simon Glass
2021-10-28 17:52       ` Tom Rini
2021-10-28 18:13         ` Simon Glass
2021-10-28 18:36           ` Tom Rini
2021-10-28 18:48             ` Simon Glass
2021-10-28 19:19               ` Tom Rini
2021-10-28 22:22                 ` Simon Glass
2021-10-28 22:50                   ` Tom Rini
2021-10-29  1:13                     ` Simon Glass
2021-11-24 22:22   ` [PATCH v2 17/41] test/py: Relax the naming rules for unit tests Simon Glass
2021-11-24 22:22   ` [PATCH v2 18/41] test/py: Raise a ValueError if a command fails Simon Glass
2021-11-24 22:22   ` [PATCH v2 16/41] sandbox: Enable HEXDUMP for sandbox_flattree Simon Glass
2021-11-24 22:22   ` [PATCH v2 15/41] dm: core: Add a way to count the devices in a uclass Simon Glass
2021-11-24 22:22   ` [PATCH v2 14/41] dm: core: Allow finding children / uclasses by partial name Simon Glass
2021-11-24 22:22   ` [PATCH v2 11/41] dm: core: Fix handling of uclass pre_unbind method Simon Glass
2021-11-24 22:22   ` [PATCH v2 12/41] dm: core: Fix up string-function documentation Simon Glass
2021-11-24 22:22   ` [PATCH v2 08/41] disk: part_dos: Fix a NULL pointer error Simon Glass
2021-11-24 22:22   ` [PATCH v2 09/41] common: Allow a smaller console-recording pre-reloc Simon Glass
2021-11-24 22:22   ` [PATCH v2 10/41] dm: core: Add tests for stringlist functions Simon Glass
2021-11-24 22:22   ` [PATCH v2 06/41] mmc: Allow for children other than the block device Simon Glass
2021-11-24 22:22   ` [PATCH v2 05/41] sandbox: mmc: Support a backing file Simon Glass
2021-11-24 22:22   ` [PATCH v2 04/41] sandbox: Support unmapping a file Simon Glass
2021-11-24 22:22   ` [PATCH v2 03/41] test/py: Allow passing input to a program Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.