All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/28] Initial implementation of bootmethod/bootflow
@ 2021-08-19  3:45 Simon Glass
  2021-08-19  3:45 ` [PATCH 01/28] Create a new boot/ directory Simon Glass
                   ` (29 more replies)
  0 siblings, 30 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren


Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
an Operating System without custom scripting and other customisation:

  - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
  - bootflow - a description of how to boot (owned by the distro)

This series provides an initial implementation of these, enable to scan
for bootflows from MMC and Ethernet. The only bootflow supported is
distro boot, i.e. an extlinux.conf file included on a filesystem or
tftp server. 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.

It is intended that this approach be expanded to support mechanisms other
than distro boot, including EFI-related ones. With a standard way to
identify boot devices, these features become easier. It also should
support U-Boot scripts, for backwards compatibility only.

The first patch of this series moves boot-related code out of common/ and
into a new boot/ directory. This helps to collect these related files
in one place, as common/ is quite large.

Like sysboot, this feature makes use of the existing PXE implementation.
Much of this series consists of cleaning up that code and refactoring it
into something closer to a module that can be called, teasing apart its
reliance on the command-line interpreter to access filesystems and the
like. Also it now uses function arguments and its own context struct
internally rather than environment variables, which is very hard to
follow. No core functional change is included in the included PXE patches.

For documentation, see the 'doc' patch.

There is quite a long list of future work included in the documentation.
One question is the choice of naming. Since this is a bootloader, should
we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
shared by other commands like bootm, booti, etc.

The design is described here:

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

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



Simon Glass (28):
  Create a new boot/ directory
  pxe: Move API comments to the header files
  pxe: Use a context pointer
  pxe: Move do_getfile() into the context
  pxe: Add a userdata field to the context
  pxe: Tidy up the is_pxe global
  pxe: Move pxe_utils files
  pxe: Tidy up some comments in pxe_utils
  pxe: Tidy up code style a little in pxe_utils
  pxe: Move common parsing coding into pxe_util
  pxe: Clean up the use of bootfile
  pxe: Drop get_bootfile_path()
  lib: Add tests for simple_itoa()
  lib: Add a function to convert a string to a hex value
  pxe: Return the file size from the getfile() function
  pxe: Refactor sysboot to have one helper
  doc: Move distro boot doc to rST
  pxe: Allow calling the pxe_get logic directly
  bootmethod: Add the uclass and core implementation
  bootmethod: Add an implementation of distro boot
  bootmethod: Add a command
  bootflow: Add a command
  bootmethod: Add tests for bootmethod and bootflow
  bootmethod: doc: Add documentation
  mmc: Allow for children other than the block device
  mmc: Add a bootmethod
  ethernet: Add a bootmethod
  RFC: rpi: Switch over to use bootflow

 Kconfig                                   |   2 +
 MAINTAINERS                               |  16 +
 Makefile                                  |   3 +-
 README                                    |   1 +
 common/Kconfig.boot => boot/Kconfig       |  22 +-
 boot/Makefile                             |  39 ++
 {common => boot}/android_ab.c             |   0
 {common => boot}/boot_fit.c               |   0
 {common => boot}/bootm.c                  |   0
 {common => boot}/bootm_os.c               |   0
 boot/bootmethod.c                         | 485 ++++++++++++++++++++
 {common => boot}/bootretry.c              |   0
 {common => boot}/common_fit.c             |   0
 boot/distro.c                             | 194 ++++++++
 {common => boot}/fdt_region.c             |   0
 {common => boot}/image-android-dt.c       |   0
 {common => boot}/image-android.c          |   0
 {common => boot}/image-cipher.c           |   0
 {common => boot}/image-fdt.c              |   0
 {common => boot}/image-fit-sig.c          |   0
 {common => boot}/image-fit.c              |   0
 {common => boot}/image-sig.c              |   0
 {common => boot}/image.c                  |   0
 {cmd => boot}/pxe_utils.c                 | 512 +++++++++++-----------
 cmd/Kconfig                               |   8 +
 cmd/Makefile                              |   5 +-
 cmd/bootflow.c                            | 399 +++++++++++++++++
 cmd/bootmethod.c                          | 130 ++++++
 cmd/pxe.c                                 | 136 +++---
 cmd/pxe_utils.h                           |  91 ----
 cmd/sysboot.c                             | 114 +++--
 common/Kconfig                            |   2 -
 common/Makefile                           |  22 -
 configs/sandbox_defconfig                 |   3 +-
 doc/android/boot-image.rst                |   2 +-
 doc/develop/bootflow.rst                  | 323 ++++++++++++++
 doc/{README.distro => develop/distro.rst} | 180 ++++----
 doc/develop/index.rst                     |   2 +
 doc/device-tree-bindings/bootmethod.txt   |  14 +
 doc/usage/bootflow.rst                    | 419 ++++++++++++++++++
 doc/usage/bootmethod.rst                  | 138 ++++++
 doc/usage/index.rst                       |   2 +
 drivers/mmc/Makefile                      |   5 +
 drivers/mmc/mmc-uclass.c                  |  23 +-
 drivers/mmc/mmc_bootmethod.c              |  46 ++
 include/bootmethod.h                      | 357 +++++++++++++++
 include/configs/rpi.h                     |  37 +-
 include/distro.h                          |  62 +++
 include/dm/uclass-id.h                    |   1 +
 include/mmc.h                             |  12 +-
 include/pxe_utils.h                       | 253 +++++++++++
 include/test/suites.h                     |   2 +
 include/vsprintf.h                        |  25 +-
 lib/vsprintf.c                            |  20 +-
 net/Kconfig                               |   9 +
 net/Makefile                              |   1 +
 net/eth-uclass.c                          |   8 +
 net/eth_bootmethod.c                      |  76 ++++
 scripts/Makefile.spl                      |   4 +-
 test/Makefile                             |   1 +
 test/boot/Makefile                        |   5 +
 test/boot/bootmethod.c                    | 271 ++++++++++++
 test/cmd_ut.c                             |   4 +
 test/print_ut.c                           |  33 ++
 tools/Makefile                            |  16 +-
 try.sh                                    | 131 ++++++
 66 files changed, 4035 insertions(+), 631 deletions(-)
 rename common/Kconfig.boot => boot/Kconfig (98%)
 create mode 100644 boot/Makefile
 rename {common => boot}/android_ab.c (100%)
 rename {common => boot}/boot_fit.c (100%)
 rename {common => boot}/bootm.c (100%)
 rename {common => boot}/bootm_os.c (100%)
 create mode 100644 boot/bootmethod.c
 rename {common => boot}/bootretry.c (100%)
 rename {common => boot}/common_fit.c (100%)
 create mode 100644 boot/distro.c
 rename {common => boot}/fdt_region.c (100%)
 rename {common => boot}/image-android-dt.c (100%)
 rename {common => boot}/image-android.c (100%)
 rename {common => boot}/image-cipher.c (100%)
 rename {common => boot}/image-fdt.c (100%)
 rename {common => boot}/image-fit-sig.c (100%)
 rename {common => boot}/image-fit.c (100%)
 rename {common => boot}/image-sig.c (100%)
 rename {common => boot}/image.c (100%)
 rename {cmd => boot}/pxe_utils.c (74%)
 create mode 100644 cmd/bootflow.c
 create mode 100644 cmd/bootmethod.c
 delete mode 100644 cmd/pxe_utils.h
 create mode 100644 doc/develop/bootflow.rst
 rename doc/{README.distro => develop/distro.rst} (76%)
 create mode 100644 doc/device-tree-bindings/bootmethod.txt
 create mode 100644 doc/usage/bootflow.rst
 create mode 100644 doc/usage/bootmethod.rst
 create mode 100644 drivers/mmc/mmc_bootmethod.c
 create mode 100644 include/bootmethod.h
 create mode 100644 include/distro.h
 create mode 100644 include/pxe_utils.h
 create mode 100644 net/eth_bootmethod.c
 create mode 100644 test/boot/Makefile
 create mode 100644 test/boot/bootmethod.c
 create mode 100755 try.sh

-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 01/28] Create a new boot/ directory
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 02/28] pxe: Move API comments to the header files Simon Glass
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Quite a lot of the code in common/relates to booting and images. Before
adding more it seems like a good time to move the code into its own
directory.

Most files with 'boot' or 'image' in them are moved, except:

- autoboot.c which relates to U-Boot automatically running a script
- bootstage.c which relates to U-Boot timing

Drop the removal of boot* files from the output directory, since this
interfers with the symlinks created by tools and there does not appear
to be any such file from my brief testing.

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

 Kconfig                             |  2 ++
 Makefile                            |  3 ++-
 README                              |  1 +
 common/Kconfig.boot => boot/Kconfig |  0
 boot/Makefile                       | 34 +++++++++++++++++++++++++++++
 {common => boot}/android_ab.c       |  0
 {common => boot}/boot_fit.c         |  0
 {common => boot}/bootm.c            |  0
 {common => boot}/bootm_os.c         |  0
 {common => boot}/bootretry.c        |  0
 {common => boot}/common_fit.c       |  0
 {common => boot}/fdt_region.c       |  0
 {common => boot}/image-android-dt.c |  0
 {common => boot}/image-android.c    |  0
 {common => boot}/image-cipher.c     |  0
 {common => boot}/image-fdt.c        |  0
 {common => boot}/image-fit-sig.c    |  0
 {common => boot}/image-fit.c        |  0
 {common => boot}/image-sig.c        |  0
 {common => boot}/image.c            |  0
 common/Kconfig                      |  2 --
 common/Makefile                     | 22 -------------------
 doc/android/boot-image.rst          |  2 +-
 scripts/Makefile.spl                |  4 ++--
 tools/Makefile                      | 16 +++++++-------
 25 files changed, 50 insertions(+), 36 deletions(-)
 rename common/Kconfig.boot => boot/Kconfig (100%)
 create mode 100644 boot/Makefile
 rename {common => boot}/android_ab.c (100%)
 rename {common => boot}/boot_fit.c (100%)
 rename {common => boot}/bootm.c (100%)
 rename {common => boot}/bootm_os.c (100%)
 rename {common => boot}/bootretry.c (100%)
 rename {common => boot}/common_fit.c (100%)
 rename {common => boot}/fdt_region.c (100%)
 rename {common => boot}/image-android-dt.c (100%)
 rename {common => boot}/image-android.c (100%)
 rename {common => boot}/image-cipher.c (100%)
 rename {common => boot}/image-fdt.c (100%)
 rename {common => boot}/image-fit-sig.c (100%)
 rename {common => boot}/image-fit.c (100%)
 rename {common => boot}/image-sig.c (100%)
 rename {common => boot}/image.c (100%)

diff --git a/Kconfig b/Kconfig
index a6c42b902f7..56ae57930f3 100644
--- a/Kconfig
+++ b/Kconfig
@@ -455,6 +455,8 @@ endmenu		# General setup
 
 source "api/Kconfig"
 
+source "boot/Kconfig"
+
 source "common/Kconfig"
 
 source "cmd/Kconfig"
diff --git a/Makefile b/Makefile
index 3c8437d21af..3a50ad2188e 100644
--- a/Makefile
+++ b/Makefile
@@ -804,6 +804,7 @@ HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makef
 
 libs-$(CONFIG_API) += api/
 libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
+libs-y += boot/
 libs-y += cmd/
 libs-y += common/
 libs-$(CONFIG_OF_EMBED) += dts/
@@ -2092,7 +2093,7 @@ CLEAN_DIRS  += $(MODVERDIR) \
 			$(filter-out include, $(shell ls -1 $d 2>/dev/null))))
 
 CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h tools/version.h \
-	       boot* u-boot* MLO* SPL System.map fit-dtb.blob* \
+	       u-boot* MLO* SPL System.map fit-dtb.blob* \
 	       u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log \
 	       lpc32xx-* bl31.c bl31.elf bl31_*.bin image.map tispl.bin* \
 	       idbloader.img flash.bin flash.log defconfig keep-syms-lto.c
diff --git a/README b/README
index 1c1db980987..1a74616d60e 100644
--- a/README
+++ b/README
@@ -144,6 +144,7 @@ Directory Hierarchy:
   /xtensa		Files generic to Xtensa architecture
 /api			Machine/arch-independent API for external apps
 /board			Board-dependent files
+/boot			Support for images and booting
 /cmd			U-Boot commands functions
 /common			Misc architecture-independent functions
 /configs		Board default configuration files
diff --git a/common/Kconfig.boot b/boot/Kconfig
similarity index 100%
rename from common/Kconfig.boot
rename to boot/Kconfig
diff --git a/boot/Makefile b/boot/Makefile
new file mode 100644
index 00000000000..57d26346afb
--- /dev/null
+++ b/boot/Makefile
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2004-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ifndef CONFIG_SPL_BUILD
+
+# This option is not just y/n - it can have a numeric value
+ifdef CONFIG_BOOT_RETRY_TIME
+obj-y += bootretry.o
+endif
+
+obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
+obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
+obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
+
+endif
+
+obj-y += image.o
+obj-$(CONFIG_ANDROID_AB) += android_ab.o
+obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.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
+obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
+obj-$(CONFIG_$(SPL_TPL_)IMAGE_SIGN_INFO) += image-sig.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o
+
+obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o
+
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
+endif
diff --git a/common/android_ab.c b/boot/android_ab.c
similarity index 100%
rename from common/android_ab.c
rename to boot/android_ab.c
diff --git a/common/boot_fit.c b/boot/boot_fit.c
similarity index 100%
rename from common/boot_fit.c
rename to boot/boot_fit.c
diff --git a/common/bootm.c b/boot/bootm.c
similarity index 100%
rename from common/bootm.c
rename to boot/bootm.c
diff --git a/common/bootm_os.c b/boot/bootm_os.c
similarity index 100%
rename from common/bootm_os.c
rename to boot/bootm_os.c
diff --git a/common/bootretry.c b/boot/bootretry.c
similarity index 100%
rename from common/bootretry.c
rename to boot/bootretry.c
diff --git a/common/common_fit.c b/boot/common_fit.c
similarity index 100%
rename from common/common_fit.c
rename to boot/common_fit.c
diff --git a/common/fdt_region.c b/boot/fdt_region.c
similarity index 100%
rename from common/fdt_region.c
rename to boot/fdt_region.c
diff --git a/common/image-android-dt.c b/boot/image-android-dt.c
similarity index 100%
rename from common/image-android-dt.c
rename to boot/image-android-dt.c
diff --git a/common/image-android.c b/boot/image-android.c
similarity index 100%
rename from common/image-android.c
rename to boot/image-android.c
diff --git a/common/image-cipher.c b/boot/image-cipher.c
similarity index 100%
rename from common/image-cipher.c
rename to boot/image-cipher.c
diff --git a/common/image-fdt.c b/boot/image-fdt.c
similarity index 100%
rename from common/image-fdt.c
rename to boot/image-fdt.c
diff --git a/common/image-fit-sig.c b/boot/image-fit-sig.c
similarity index 100%
rename from common/image-fit-sig.c
rename to boot/image-fit-sig.c
diff --git a/common/image-fit.c b/boot/image-fit.c
similarity index 100%
rename from common/image-fit.c
rename to boot/image-fit.c
diff --git a/common/image-sig.c b/boot/image-sig.c
similarity index 100%
rename from common/image-sig.c
rename to boot/image-sig.c
diff --git a/common/image.c b/boot/image.c
similarity index 100%
rename from common/image.c
rename to boot/image.c
diff --git a/common/Kconfig b/common/Kconfig
index 2ab20a6c85b..f8afa2ceff1 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1,5 +1,3 @@
-source "common/Kconfig.boot"
-
 menu "Console"
 
 config MENU
diff --git a/common/Makefile b/common/Makefile
index 9063ed93910..de993700dd5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -12,21 +12,12 @@ obj-$(CONFIG_HASH) += hash.o
 obj-$(CONFIG_HUSH_PARSER) += cli_hush.o
 obj-$(CONFIG_AUTOBOOT) += autoboot.o
 
-# This option is not just y/n - it can have a numeric value
-ifdef CONFIG_BOOT_RETRY_TIME
-obj-y += bootretry.o
-endif
-
 # # boards
 obj-y += board_f.o
 obj-y += board_r.o
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
 obj-$(CONFIG_DISPLAY_BOARDINFO_LATE) += board_info.o
 
-obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
-obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
-obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
-
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
 obj-$(CONFIG_MII) += miiphyutil.o
@@ -68,7 +59,6 @@ obj-$(CONFIG_DFU_OVER_USB) += dfu.o
 endif
 obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o
 obj-$(CONFIG_TPL_HASH_SUPPORT) += hash.o
-obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
 obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
 
@@ -104,22 +94,10 @@ obj-y += malloc_simple.o
 endif
 endif
 
-obj-y += image.o
-obj-$(CONFIG_ANDROID_AB) += android_ab.o
-obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.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
-obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
-obj-$(CONFIG_$(SPL_TPL_)IMAGE_SIGN_INFO) += image-sig.o
-obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o
-obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o
 obj-$(CONFIG_IO_TRACE) += iotrace.o
 obj-y += memsize.o
 obj-y += stdio.o
 
-obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o
-
 ifdef CONFIG_CMD_EEPROM_LAYOUT
 obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o
 endif
diff --git a/doc/android/boot-image.rst b/doc/android/boot-image.rst
index fa8f2a47ee3..71db02521b0 100644
--- a/doc/android/boot-image.rst
+++ b/doc/android/boot-image.rst
@@ -139,7 +139,7 @@ overview on the whole Android 10 boot process can be found at [8]_.
 C API for working with Android Boot Image format
 ------------------------------------------------
 
-.. kernel-doc:: common/image-android.c
+.. kernel-doc:: boot/image-android.c
    :internal:
 
 References
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 25a3e7fa52e..f2a619e28a7 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -92,10 +92,10 @@ libs-y += common/init/
 
 # Special handling for a few options which support SPL/TPL
 ifeq ($(CONFIG_TPL_BUILD),y)
-libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
+libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += boot/ common/ cmd/ env/
 libs-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/
 else
-libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
+libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += boot/ common/ cmd/ env/
 libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
 ifdef CONFIG_SPL_FRAMEWORK
 libs-$(CONFIG_PARTITIONS) += disk/
diff --git a/tools/Makefile b/tools/Makefile
index 4a86321f646..2cda7cdd75f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -76,9 +76,9 @@ hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fit_info fit_check_sign
 
 hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include
 
-FIT_OBJS-y := fit_common.o fit_image.o image-host.o common/image-fit.o
-FIT_SIG_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := image-sig-host.o common/image-fit-sig.o
-FIT_CIPHER_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := common/image-cipher.o
+FIT_OBJS-y := fit_common.o fit_image.o image-host.o boot/image-fit.o
+FIT_SIG_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := image-sig-host.o boot/image-fit-sig.o
+FIT_CIPHER_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := boot/image-cipher.o
 
 # The following files are synced with upstream DTC.
 # Use synced versions from scripts/dtc/libfdt/.
@@ -106,13 +106,13 @@ dumpimage-mkimage-objs := aisimage.o \
 			$(FIT_OBJS-y) \
 			$(FIT_SIG_OBJS-y) \
 			$(FIT_CIPHER_OBJS-y) \
-			common/fdt_region.o \
-			common/bootm.o \
+			boot/fdt_region.o \
+			boot/bootm.o \
 			lib/crc32.o \
 			default_image.o \
 			lib/fdtdec_common.o \
 			lib/fdtdec.o \
-			common/image.o \
+			boot/image.o \
 			imagetool.o \
 			imximage.o \
 			imx8image.o \
@@ -226,7 +226,7 @@ hostprogs-$(CONFIG_ARCH_OCTEON) += update_octeon_header
 update_octeon_header-objs := update_octeon_header.o lib/crc32.o
 
 hostprogs-y += fdtgrep
-fdtgrep-objs += $(LIBFDT_OBJS) common/fdt_region.o fdtgrep.o
+fdtgrep-objs += $(LIBFDT_OBJS) boot/fdt_region.o fdtgrep.o
 
 ifneq ($(TOOLS_ONLY),y)
 hostprogs-y += spl_size_limit
@@ -253,7 +253,7 @@ HOSTCFLAGS_sha512.o := -pedantic -DCONFIG_SHA512 -DCONFIG_SHA384
 quiet_cmd_wrap = WRAP    $@
 cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@
 
-$(obj)/lib/%.c $(obj)/common/%.c $(obj)/env/%.c:
+$(obj)/boot/%.c $(obj)/common/%.c $(obj)/env/%.c $(obj)/lib/%.c:
 	$(call cmd,wrap)
 
 clean-dirs := lib common
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 02/28] pxe: Move API comments to the header files
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
  2021-08-19  3:45 ` [PATCH 01/28] Create a new boot/ directory Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 03/28] pxe: Use a context pointer Simon Glass
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Put the function comments in the header file so that the full API can we
examined in one place.

Expand the comments to cover parameters and return values.

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

 cmd/pxe_utils.c | 45 -----------------------------
 cmd/pxe_utils.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 74 insertions(+), 48 deletions(-)

diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index 067c24e5ff4..d7f4017efeb 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -32,16 +32,6 @@
 
 bool is_pxe;
 
-/*
- * Convert an ethaddr from the environment to the format used by pxelinux
- * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to
- * the beginning of the ethernet address to indicate a hardware type of
- * Ethernet. Also converts uppercase hex characters into lowercase, to match
- * pxelinux's behavior.
- *
- * Returns 1 for success, -ENOENT if 'ethaddr' is undefined in the
- * environment, or some other value < 0 on error.
- */
 int format_mac_pxe(char *outbuf, size_t outbuf_len)
 {
 	uchar ethaddr[6];
@@ -146,13 +136,6 @@ static int get_relfile(struct cmd_tbl *cmdtp, const char *file_path,
 	return do_getfile(cmdtp, relfile, addr_buf);
 }
 
-/*
- * Retrieve the file at 'file_path' to the locate given by 'file_addr'. If
- * 'bootfile' was specified in the environment, the path to bootfile will be
- * prepended to 'file_path' and the resulting path will be used.
- *
- * Returns 1 on success, or < 0 for error.
- */
 int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
 		 unsigned long file_addr)
 {
@@ -187,13 +170,6 @@ int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
 
 #define PXELINUX_DIR "pxelinux.cfg/"
 
-/*
- * Retrieves a file in the 'pxelinux.cfg' folder. Since this uses get_pxe_file
- * to do the hard work, the location of the 'pxelinux.cfg' folder is generated
- * from the bootfile path, as described above.
- *
- * Returns 1 on success or < 0 on error.
- */
 int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
 		      unsigned long pxefile_addr_r)
 {
@@ -1309,15 +1285,6 @@ void destroy_pxe_menu(struct pxe_menu *cfg)
 	free(cfg);
 }
 
-/*
- * Entry point for parsing a pxe file. This is only used for the top level
- * file.
- *
- * Returns NULL if there is an error, otherwise, returns a pointer to a
- * pxe_menu struct populated with the results of parsing the pxe file (and any
- * files it includes). The resulting pxe_menu struct can be free()'d by using
- * the destroy_pxe_menu() function.
- */
 struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg)
 {
 	struct pxe_menu *cfg;
@@ -1415,18 +1382,6 @@ static void boot_unattempted_labels(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
 	}
 }
 
-/*
- * Boot the system as prescribed by a pxe_menu.
- *
- * Use the menu system to either get the user's choice or the default, based
- * on config or user input.  If there is no default or user's choice,
- * attempted to boot labels in the order they were given in pxe files.
- * If the default or user's choice fails to boot, attempt to boot other
- * labels in the order they were given in pxe files.
- *
- * If this function returns, there weren't any labels that successfully
- * booted, or the user interrupted the menu selection via ctrl+c.
- */
 void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
 {
 	void *choice;
diff --git a/cmd/pxe_utils.h b/cmd/pxe_utils.h
index bf58e15347c..441beefa2bc 100644
--- a/cmd/pxe_utils.h
+++ b/cmd/pxe_utils.h
@@ -80,12 +80,83 @@ extern bool is_pxe;
 extern int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
 			 char *file_addr);
 void destroy_pxe_menu(struct pxe_menu *cfg);
+
+/**
+ * get_pxe_file() - Read a file
+ *
+ * Retrieve the file at 'file_path' to the locate given by 'file_addr'. If
+ * 'bootfile' was specified in the environment, the path to bootfile will be
+ * prepended to 'file_path' and the resulting path will be used.
+ *
+ * @cmdtp: Pointer to command-table entry for the initiating command
+ * @file_path: Path to file
+ * @file_addr: Address to place file
+ * Returns 1 on success, or < 0 for error
+ */
 int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
-		 unsigned long file_addr);
+		 ulong file_addr);
+
+/**
+ * get_pxelinux_path() - Read a file from the same place as pxelinux.cfg
+ *
+ * Retrieves a file in the 'pxelinux.cfg' folder. Since this uses get_pxe_file()
+ * to do the hard work, the location of the 'pxelinux.cfg' folder is generated
+ * from the bootfile path, as described in get_pxe_file().
+ *
+ * @cmdtp: Pointer to command-table entry for the initiating command
+ * @file: Relative path to file
+ * @pxefile_addr_r: Address to load file
+ * Returns 1 on success or < 0 on error.
+ */
 int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
-		      unsigned long pxefile_addr_r);
+		      ulong pxefile_addr_r);
+
+/**
+ * handle_pxe_menu() - Boot the system as prescribed by a pxe_menu.
+ *
+ * Use the menu system to either get the user's choice or the default, based
+ * on config or user input.  If there is no default or user's choice,
+ * attempted to boot labels in the order they were given in pxe files.
+ * If the default or user's choice fails to boot, attempt to boot other
+ * labels in the order they were given in pxe files.
+ *
+ * If this function returns, there weren't any labels that successfully
+ * booted, or the user interrupted the menu selection via ctrl+c.
+ *
+ * @cmdtp: Pointer to command-table entry for the initiating command
+ * @cfg: PXE menu
+ */
 void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg);
-struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg);
+
+/**
+ * parse_pxefile() - Parsing a pxe file
+ *
+ * This is only used for the top-level file.
+ *
+ * @cmdtp: Pointer to command-table entry for the initiating command
+ * @menucfg: Address of PXE file
+ *
+ * Returns NULL if there is an error, otherwise, returns a pointer to a
+ * pxe_menu struct populated with the results of parsing the pxe file (and any
+ * files it includes). The resulting pxe_menu struct can be free()'d by using
+ * the destroy_pxe_menu() function.
+ */
+struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, ulong menucfg);
+
+/**
+ * format_mac_pxe() - Convert a MAC address to PXE format
+ *
+ * Convert an ethaddr from the environment to the format used by pxelinux
+ * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to
+ * the beginning of the ethernet address to indicate a hardware type of
+ * Ethernet. Also converts uppercase hex characters into lowercase, to match
+ * pxelinux's behavior.
+ *
+ * @outbuf: Buffer to hold the output (must hold 22 bytes)
+ * @outbuf_len: Length of buffer
+ * Returns 1 for success, -ENOENT if 'ethaddr' is undefined in the
+ * environment, or some other value < 0 on error.
+ */
 int format_mac_pxe(char *outbuf, size_t outbuf_len);
 
 #endif /* __PXE_UTILS_H */
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 03/28] pxe: Use a context pointer
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
  2021-08-19  3:45 ` [PATCH 01/28] Create a new boot/ directory Simon Glass
  2021-08-19  3:45 ` [PATCH 02/28] pxe: Move API comments to the header files Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 04/28] pxe: Move do_getfile() into the context Simon Glass
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

At present the PXE functions pass around a pointer to command-table entry
which is very strange. It is only needed in a few places and it is odd to
pass around a data structure from another module in this way.

For bootmethod we will need to provide some context information when
reading files.

Create a PXE context struct to hold the command-table-entry pointer and
pass that around instead. We can then add more things to the context as
needed.

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

 cmd/pxe.c       | 28 +++++++++--------
 cmd/pxe_utils.c | 80 ++++++++++++++++++++++++++-----------------------
 cmd/pxe_utils.h | 43 +++++++++++++++++++-------
 cmd/sysboot.c   |  8 +++--
 4 files changed, 97 insertions(+), 62 deletions(-)

diff --git a/cmd/pxe.c b/cmd/pxe.c
index 46ac08fa3a0..17ce54fc049 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -43,7 +43,7 @@ static int do_get_tftp(struct cmd_tbl *cmdtp, const char *file_path,
  *
  * Returns 1 on success or < 0 on error.
  */
-static int pxe_uuid_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_uuid_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
 {
 	char *uuid_str;
 
@@ -52,7 +52,7 @@ static int pxe_uuid_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
 	if (!uuid_str)
 		return -ENOENT;
 
-	return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r);
+	return get_pxelinux_path(ctx, uuid_str, pxefile_addr_r);
 }
 
 /*
@@ -61,7 +61,7 @@ static int pxe_uuid_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
  *
  * Returns 1 on success or < 0 on error.
  */
-static int pxe_mac_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_mac_path(struct pxe_context *ctx, unsigned long pxefile_addr_r)
 {
 	char mac_str[21];
 	int err;
@@ -71,7 +71,7 @@ static int pxe_mac_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
 	if (err < 0)
 		return err;
 
-	return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r);
+	return get_pxelinux_path(ctx, mac_str, pxefile_addr_r);
 }
 
 /*
@@ -81,7 +81,7 @@ static int pxe_mac_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
  *
  * Returns 1 on success or < 0 on error.
  */
-static int pxe_ipaddr_paths(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+static int pxe_ipaddr_paths(struct pxe_context *ctx, unsigned long pxefile_addr_r)
 {
 	char ip_addr[9];
 	int mask_pos, err;
@@ -89,7 +89,7 @@ static int pxe_ipaddr_paths(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
 	sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr));
 
 	for (mask_pos = 7; mask_pos >= 0;  mask_pos--) {
-		err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r);
+		err = get_pxelinux_path(ctx, ip_addr, pxefile_addr_r);
 
 		if (err > 0)
 			return err;
@@ -118,8 +118,10 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	char *pxefile_addr_str;
 	unsigned long pxefile_addr_r;
+	struct pxe_context ctx;
 	int err, i = 0;
 
+	pxe_setup_ctx(&ctx, cmdtp);
 	do_getfile = do_get_tftp;
 
 	if (argc != 1)
@@ -139,16 +141,16 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	 * Keep trying paths until we successfully get a file we're looking
 	 * for.
 	 */
-	if (pxe_uuid_path(cmdtp, pxefile_addr_r) > 0 ||
-	    pxe_mac_path(cmdtp, pxefile_addr_r) > 0 ||
-	    pxe_ipaddr_paths(cmdtp, pxefile_addr_r) > 0) {
+	if (pxe_uuid_path(&ctx, pxefile_addr_r) > 0 ||
+	    pxe_mac_path(&ctx, pxefile_addr_r) > 0 ||
+	    pxe_ipaddr_paths(&ctx, pxefile_addr_r) > 0) {
 		printf("Config file found\n");
 
 		return 0;
 	}
 
 	while (pxe_default_paths[i]) {
-		if (get_pxelinux_path(cmdtp, pxe_default_paths[i],
+		if (get_pxelinux_path(&ctx, pxe_default_paths[i],
 				      pxefile_addr_r) > 0) {
 			printf("Config file found\n");
 			return 0;
@@ -172,7 +174,9 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	unsigned long pxefile_addr_r;
 	struct pxe_menu *cfg;
 	char *pxefile_addr_str;
+	struct pxe_context ctx;
 
+	pxe_setup_ctx(&ctx, cmdtp);
 	do_getfile = do_get_tftp;
 
 	if (argc == 1) {
@@ -191,14 +195,14 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		return 1;
 	}
 
-	cfg = parse_pxefile(cmdtp, pxefile_addr_r);
+	cfg = parse_pxefile(&ctx, pxefile_addr_r);
 
 	if (!cfg) {
 		printf("Error parsing config file\n");
 		return 1;
 	}
 
-	handle_pxe_menu(cmdtp, cfg);
+	handle_pxe_menu(&ctx, cfg);
 
 	destroy_pxe_menu(cfg);
 
diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index d7f4017efeb..280be55d9b3 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -105,7 +105,7 @@ int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
  *
  * Returns 1 for success, or < 0 on error.
  */
-static int get_relfile(struct cmd_tbl *cmdtp, const char *file_path,
+static int get_relfile(struct pxe_context *ctx, const char *file_path,
 		       unsigned long file_addr)
 {
 	size_t path_len;
@@ -133,10 +133,10 @@ static int get_relfile(struct cmd_tbl *cmdtp, const char *file_path,
 
 	sprintf(addr_buf, "%lx", file_addr);
 
-	return do_getfile(cmdtp, relfile, addr_buf);
+	return do_getfile(ctx->cmdtp, relfile, addr_buf);
 }
 
-int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 		 unsigned long file_addr)
 {
 	unsigned long config_file_size;
@@ -144,7 +144,7 @@ int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
 	int err;
 	char *buf;
 
-	err = get_relfile(cmdtp, file_path, file_addr);
+	err = get_relfile(ctx, file_path, file_addr);
 
 	if (err < 0)
 		return err;
@@ -170,7 +170,7 @@ int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
 
 #define PXELINUX_DIR "pxelinux.cfg/"
 
-int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+int get_pxelinux_path(struct pxe_context *ctx, const char *file,
 		      unsigned long pxefile_addr_r)
 {
 	size_t base_len = strlen(PXELINUX_DIR);
@@ -184,7 +184,7 @@ int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
 
 	sprintf(path, PXELINUX_DIR "%s", file);
 
-	return get_pxe_file(cmdtp, path, pxefile_addr_r);
+	return get_pxe_file(ctx, path, pxefile_addr_r);
 }
 
 /*
@@ -194,7 +194,7 @@ int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
  *
  * Returns 1 on success or < 0 on error.
  */
-static int get_relfile_envaddr(struct cmd_tbl *cmdtp, const char *file_path,
+static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
 			       const char *envaddr_name)
 {
 	unsigned long file_addr;
@@ -208,7 +208,7 @@ static int get_relfile_envaddr(struct cmd_tbl *cmdtp, const char *file_path,
 	if (strict_strtoul(envaddr, 16, &file_addr) < 0)
 		return -EINVAL;
 
-	return get_relfile(cmdtp, file_path, file_addr);
+	return get_relfile(ctx, file_path, file_addr);
 }
 
 /*
@@ -317,7 +317,8 @@ static int label_localboot(struct pxe_label *label)
  * Loads fdt overlays specified in 'fdtoverlays'.
  */
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
-static void label_boot_fdtoverlay(struct cmd_tbl *cmdtp, struct pxe_label *label)
+static void label_boot_fdtoverlay(struct pxe_context *ctx,
+				  struct pxe_label *label)
 {
 	char *fdtoverlay = label->fdtoverlays;
 	struct fdt_header *working_fdt;
@@ -367,7 +368,7 @@ static void label_boot_fdtoverlay(struct cmd_tbl *cmdtp, struct pxe_label *label
 			goto skip_overlay;
 
 		/* Load overlay file */
-		err = get_relfile_envaddr(cmdtp, overlayfile,
+		err = get_relfile_envaddr(ctx, overlayfile,
 					  "fdtoverlay_addr_r");
 		if (err < 0) {
 			printf("Failed loading overlay %s\n", overlayfile);
@@ -414,7 +415,7 @@ skip_overlay:
  * If the label specifies an 'append' line, its contents will overwrite that
  * of the 'bootargs' environment variable.
  */
-static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
+static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 {
 	char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
 	char initrd_str[28];
@@ -443,7 +444,7 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
 	}
 
 	if (label->initrd) {
-		if (get_relfile_envaddr(cmdtp, label->initrd, "ramdisk_addr_r") < 0) {
+		if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
 			printf("Skipping %s for failure retrieving initrd\n",
 			       label->name);
 			return 1;
@@ -456,7 +457,7 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
 		bootm_argc = 3;
 	}
 
-	if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) {
+	if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
 		printf("Skipping %s for failure retrieving kernel\n",
 		       label->name);
 		return 1;
@@ -596,7 +597,7 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
 		}
 
 		if (fdtfile) {
-			int err = get_relfile_envaddr(cmdtp, fdtfile,
+			int err = get_relfile_envaddr(ctx, fdtfile,
 						      "fdt_addr_r");
 
 			free(fdtfilefree);
@@ -612,7 +613,7 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
 
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
 			if (label->fdtoverlays)
-				label_boot_fdtoverlay(cmdtp, label);
+				label_boot_fdtoverlay(ctx, label);
 #endif
 		} else {
 			bootm_argv[3] = NULL;
@@ -632,16 +633,16 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
 	buf = map_sysmem(kernel_addr, 0);
 	/* Try bootm for legacy and FIT format image */
 	if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
-		do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
+		do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting an AArch64 Linux kernel image */
 	else if (IS_ENABLED(CONFIG_CMD_BOOTI))
-		do_booti(cmdtp, 0, bootm_argc, bootm_argv);
+		do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting a Image */
 	else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
-		do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
+		do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting an x86_64 Linux kernel image */
 	else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
-		do_zboot_parent(cmdtp, 0, bootm_argc, bootm_argv, NULL);
+		do_zboot_parent(ctx->cmdtp, 0, bootm_argc, bootm_argv, NULL);
 
 	unmap_sysmem(buf);
 
@@ -917,7 +918,7 @@ static int parse_integer(char **c, int *dst)
 	return 1;
 }
 
-static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+static int parse_pxefile_top(struct pxe_context *ctx, char *p, ulong base,
 			     struct pxe_menu *cfg, int nest_level);
 
 /*
@@ -928,7 +929,7 @@ static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
  * include, nest_level has already been incremented and doesn't need to be
  * incremented here.
  */
-static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
+static int handle_include(struct pxe_context *ctx, char **c, unsigned long base,
 			  struct pxe_menu *cfg, int nest_level)
 {
 	char *include_path;
@@ -944,7 +945,7 @@ static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
 		return err;
 	}
 
-	err = get_pxe_file(cmdtp, include_path, base);
+	err = get_pxe_file(ctx, include_path, base);
 
 	if (err < 0) {
 		printf("Couldn't retrieve %s\n", include_path);
@@ -952,7 +953,7 @@ static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
 	}
 
 	buf = map_sysmem(base, 0);
-	ret = parse_pxefile_top(cmdtp, buf, base, cfg, nest_level);
+	ret = parse_pxefile_top(ctx, buf, base, cfg, nest_level);
 	unmap_sysmem(buf);
 
 	return ret;
@@ -968,7 +969,7 @@ static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
  * nest_level should be 1 when parsing the top level pxe file, 2 when parsing
  * a file it includes, 3 when parsing a file included by that file, and so on.
  */
-static int parse_menu(struct cmd_tbl *cmdtp, char **c, struct pxe_menu *cfg,
+static int parse_menu(struct pxe_context *ctx, char **c, struct pxe_menu *cfg,
 		      unsigned long base, int nest_level)
 {
 	struct token t;
@@ -984,7 +985,7 @@ static int parse_menu(struct cmd_tbl *cmdtp, char **c, struct pxe_menu *cfg,
 		break;
 
 	case T_INCLUDE:
-		err = handle_include(cmdtp, c, base, cfg, nest_level + 1);
+		err = handle_include(ctx, c, base, cfg, nest_level + 1);
 		break;
 
 	case T_BACKGROUND:
@@ -1186,7 +1187,7 @@ static int parse_label(char **c, struct pxe_menu *cfg)
  *
  * Returns 1 on success, < 0 on error.
  */
-static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long base,
 			     struct pxe_menu *cfg, int nest_level)
 {
 	struct token t;
@@ -1209,7 +1210,7 @@ static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
 		switch (t.type) {
 		case T_MENU:
 			cfg->prompt = 1;
-			err = parse_menu(cmdtp, &p, cfg,
+			err = parse_menu(ctx, &p, cfg,
 					 base + ALIGN(strlen(b) + 1, 4),
 					 nest_level);
 			break;
@@ -1236,7 +1237,7 @@ static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
 			break;
 
 		case T_INCLUDE:
-			err = handle_include(cmdtp, &p,
+			err = handle_include(ctx, &p,
 					     base + ALIGN(strlen(b), 4), cfg,
 					     nest_level + 1);
 			break;
@@ -1263,7 +1264,6 @@ static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
 }
 
 /*
- * Free the memory used by a pxe_menu and its labels.
  */
 void destroy_pxe_menu(struct pxe_menu *cfg)
 {
@@ -1285,7 +1285,7 @@ void destroy_pxe_menu(struct pxe_menu *cfg)
 	free(cfg);
 }
 
-struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg)
+struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
 {
 	struct pxe_menu *cfg;
 	char *buf;
@@ -1301,7 +1301,7 @@ struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg)
 	INIT_LIST_HEAD(&cfg->labels);
 
 	buf = map_sysmem(menucfg, 0);
-	r = parse_pxefile_top(cmdtp, buf, menucfg, cfg, 1);
+	r = parse_pxefile_top(ctx, buf, menucfg, cfg, 1);
 	unmap_sysmem(buf);
 
 	if (r < 0) {
@@ -1369,7 +1369,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
 /*
  * Try to boot any labels we have yet to attempt to boot.
  */
-static void boot_unattempted_labels(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+static void boot_unattempted_labels(struct pxe_context *ctx,
+				    struct pxe_menu *cfg)
 {
 	struct list_head *pos;
 	struct pxe_label *label;
@@ -1378,11 +1379,11 @@ static void boot_unattempted_labels(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
 		label = list_entry(pos, struct pxe_label, list);
 
 		if (!label->attempted)
-			label_boot(cmdtp, label);
+			label_boot(ctx, label);
 	}
 }
 
-void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 {
 	void *choice;
 	struct menu *m;
@@ -1391,7 +1392,7 @@ void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
 	if (IS_ENABLED(CONFIG_CMD_BMP)) {
 		/* display BMP if available */
 		if (cfg->bmp) {
-			if (get_relfile(cmdtp, cfg->bmp, image_load_addr)) {
+			if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
 				if (CONFIG_IS_ENABLED(CMD_CLS))
 					run_command("cls", 0);
 				bmp_display(image_load_addr,
@@ -1423,12 +1424,17 @@ void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
 	 */
 
 	if (err == 1) {
-		err = label_boot(cmdtp, choice);
+		err = label_boot(ctx, choice);
 		if (!err)
 			return;
 	} else if (err != -ENOENT) {
 		return;
 	}
 
-	boot_unattempted_labels(cmdtp, cfg);
+	boot_unattempted_labels(ctx, cfg);
+}
+
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp)
+{
+	ctx->cmdtp = cmdtp;
 }
diff --git a/cmd/pxe_utils.h b/cmd/pxe_utils.h
index 441beefa2bc..cd0d3371765 100644
--- a/cmd/pxe_utils.h
+++ b/cmd/pxe_utils.h
@@ -79,6 +79,23 @@ extern bool is_pxe;
 
 extern int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
 			 char *file_addr);
+
+/**
+ * struct pxe_context - context information for PXE parsing
+ *
+ * @cmdtp: Pointer to command table to use when calling other commands
+ */
+struct pxe_context {
+	struct cmd_tbl *cmdtp;
+};
+
+/**
+ * destroy_pxe_menu() - Destroy an allocated pxe structure
+ *
+ * Free the memory used by a pxe_menu and its labels
+ *
+ * @cfg: Config to destroy, previous returned from parse_pxefile()
+ */
 void destroy_pxe_menu(struct pxe_menu *cfg);
 
 /**
@@ -88,12 +105,12 @@ void destroy_pxe_menu(struct pxe_menu *cfg);
  * 'bootfile' was specified in the environment, the path to bootfile will be
  * prepended to 'file_path' and the resulting path will be used.
  *
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
  * @file_path: Path to file
  * @file_addr: Address to place file
  * Returns 1 on success, or < 0 for error
  */
-int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 		 ulong file_addr);
 
 /**
@@ -103,12 +120,12 @@ int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
  * to do the hard work, the location of the 'pxelinux.cfg' folder is generated
  * from the bootfile path, as described in get_pxe_file().
  *
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
  * @file: Relative path to file
  * @pxefile_addr_r: Address to load file
  * Returns 1 on success or < 0 on error.
  */
-int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+int get_pxelinux_path(struct pxe_context *ctx, const char *file,
 		      ulong pxefile_addr_r);
 
 /**
@@ -123,25 +140,23 @@ int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
  * If this function returns, there weren't any labels that successfully
  * booted, or the user interrupted the menu selection via ctrl+c.
  *
- * @cmdtp: Pointer to command-table entry for the initiating command
+ * @ctx: PXE context
  * @cfg: PXE menu
  */
-void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg);
+void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg);
 
 /**
  * parse_pxefile() - Parsing a pxe file
  *
  * This is only used for the top-level file.
  *
- * @cmdtp: Pointer to command-table entry for the initiating command
- * @menucfg: Address of PXE file
- *
+ * @ctx: PXE context (provided by the caller)
  * Returns NULL if there is an error, otherwise, returns a pointer to a
  * pxe_menu struct populated with the results of parsing the pxe file (and any
  * files it includes). The resulting pxe_menu struct can be free()'d by using
  * the destroy_pxe_menu() function.
  */
-struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, ulong menucfg);
+struct pxe_menu *parse_pxefile(struct pxe_context *ctx, ulong menucfg);
 
 /**
  * format_mac_pxe() - Convert a MAC address to PXE format
@@ -159,4 +174,12 @@ struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, ulong menucfg);
  */
 int format_mac_pxe(char *outbuf, size_t outbuf_len);
 
+/**
+ * pxe_setup_ctx() - Setup a new PXE context
+ *
+ * @ctx: Context to set up
+ * @cmdtp: Command table entry which started this action
+ */
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp);
+
 #endif /* __PXE_UTILS_H */
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index af6a2f1b7f1..9ba713c8aae 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -59,6 +59,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
 	unsigned long pxefile_addr_r;
+	struct pxe_context ctx;
 	struct pxe_menu *cfg;
 	char *pxefile_addr_str;
 	char *filename;
@@ -90,6 +91,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		env_set("bootfile", filename);
 	}
 
+	pxe_setup_ctx(&ctx, cmdtp);
 	if (strstr(argv[3], "ext2")) {
 		do_getfile = do_get_ext2;
 	} else if (strstr(argv[3], "fat")) {
@@ -108,12 +110,12 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		return 1;
 	}
 
-	if (get_pxe_file(cmdtp, filename, pxefile_addr_r) < 0) {
+	if (get_pxe_file(&ctx, filename, pxefile_addr_r) < 0) {
 		printf("Error reading config file\n");
 		return 1;
 	}
 
-	cfg = parse_pxefile(cmdtp, pxefile_addr_r);
+	cfg = parse_pxefile(&ctx, pxefile_addr_r);
 
 	if (!cfg) {
 		printf("Error parsing config file\n");
@@ -123,7 +125,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 	if (prompt)
 		cfg->prompt = 1;
 
-	handle_pxe_menu(cmdtp, cfg);
+	handle_pxe_menu(&ctx, cfg);
 
 	destroy_pxe_menu(cfg);
 
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 04/28] pxe: Move do_getfile() into the context
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (2 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 03/28] pxe: Use a context pointer Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 05/28] pxe: Add a userdata field to " Simon Glass
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Rather than having a global variable, pass the function as part of the
context.

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

 cmd/pxe.c       | 10 ++++------
 cmd/pxe_utils.c |  9 ++++-----
 cmd/pxe_utils.h | 20 +++++++++++++++++---
 cmd/sysboot.c   | 20 ++++++++++----------
 4 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/cmd/pxe.c b/cmd/pxe.c
index 17ce54fc049..70dbde3a636 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -24,7 +24,7 @@ const char *pxe_default_paths[] = {
 	NULL
 };
 
-static int do_get_tftp(struct cmd_tbl *cmdtp, const char *file_path,
+static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
 		       char *file_addr)
 {
 	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
@@ -32,7 +32,7 @@ static int do_get_tftp(struct cmd_tbl *cmdtp, const char *file_path,
 	tftp_argv[1] = file_addr;
 	tftp_argv[2] = (void *)file_path;
 
-	if (do_tftpb(cmdtp, 0, 3, tftp_argv))
+	if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
 		return -ENOENT;
 
 	return 1;
@@ -121,8 +121,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	struct pxe_context ctx;
 	int err, i = 0;
 
-	pxe_setup_ctx(&ctx, cmdtp);
-	do_getfile = do_get_tftp;
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp);
 
 	if (argc != 1)
 		return CMD_RET_USAGE;
@@ -176,8 +175,7 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	char *pxefile_addr_str;
 	struct pxe_context ctx;
 
-	pxe_setup_ctx(&ctx, cmdtp);
-	do_getfile = do_get_tftp;
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp);
 
 	if (argc == 1) {
 		pxefile_addr_str = from_env("pxefile_addr_r");
diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index 280be55d9b3..2caae6d1555 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -94,9 +94,6 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
 	return 1;
 }
 
-int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
-		  char *file_addr);
-
 /*
  * As in pxelinux, paths to files referenced from files we retrieve are
  * relative to the location of bootfile. get_relfile takes such a path and
@@ -133,7 +130,7 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 
 	sprintf(addr_buf, "%lx", file_addr);
 
-	return do_getfile(ctx->cmdtp, relfile, addr_buf);
+	return ctx->getfile(ctx, relfile, addr_buf);
 }
 
 int get_pxe_file(struct pxe_context *ctx, const char *file_path,
@@ -1434,7 +1431,9 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 	boot_unattempted_labels(ctx, cfg);
 }
 
-void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp)
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
+		   pxe_getfile_func getfile)
 {
 	ctx->cmdtp = cmdtp;
+	ctx->getfile = getfile;
 }
diff --git a/cmd/pxe_utils.h b/cmd/pxe_utils.h
index cd0d3371765..ca2696f48b0 100644
--- a/cmd/pxe_utils.h
+++ b/cmd/pxe_utils.h
@@ -77,16 +77,28 @@ struct pxe_menu {
 
 extern bool is_pxe;
 
-extern int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
-			 char *file_addr);
+struct pxe_context;
+typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
+				char *file_addr);
 
 /**
  * struct pxe_context - context information for PXE parsing
  *
  * @cmdtp: Pointer to command table to use when calling other commands
+ * @getfile: Function called by PXE to read a file
  */
 struct pxe_context {
 	struct cmd_tbl *cmdtp;
+	/**
+	 * getfile() - read a file
+	 *
+	 * @ctx: PXE context
+	 * @file_path: Path to the file
+	 * @file_addr: String containing the hex address to put the file in
+	 *	memory
+	 * Return 0 if OK, -ve on error
+	 */
+	pxe_getfile_func getfile;
 };
 
 /**
@@ -179,7 +191,9 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
  *
  * @ctx: Context to set up
  * @cmdtp: Command table entry which started this action
+ * @getfile: Function to call to read a file
  */
-void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp);
+void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
+		   pxe_getfile_func getfile);
 
 #endif /* __PXE_UTILS_H */
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 9ba713c8aae..082f23543d1 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -8,7 +8,7 @@
 
 static char *fs_argv[5];
 
-static int do_get_ext2(struct cmd_tbl *cmdtp, const char *file_path,
+static int do_get_ext2(struct pxe_context *ctx, const char *file_path,
 		       char *file_addr)
 {
 #ifdef CONFIG_CMD_EXT2
@@ -16,13 +16,13 @@ static int do_get_ext2(struct cmd_tbl *cmdtp, const char *file_path,
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
-	if (!do_ext2load(cmdtp, 0, 5, fs_argv))
+	if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv))
 		return 1;
 #endif
 	return -ENOENT;
 }
 
-static int do_get_fat(struct cmd_tbl *cmdtp, const char *file_path,
+static int do_get_fat(struct pxe_context *ctx, const char *file_path,
 		      char *file_addr)
 {
 #ifdef CONFIG_CMD_FAT
@@ -30,13 +30,13 @@ static int do_get_fat(struct cmd_tbl *cmdtp, const char *file_path,
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
-	if (!do_fat_fsload(cmdtp, 0, 5, fs_argv))
+	if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv))
 		return 1;
 #endif
 	return -ENOENT;
 }
 
-static int do_get_any(struct cmd_tbl *cmdtp, const char *file_path,
+static int do_get_any(struct pxe_context *ctx, const char *file_path,
 		      char *file_addr)
 {
 #ifdef CONFIG_CMD_FS_GENERIC
@@ -44,7 +44,7 @@ static int do_get_any(struct cmd_tbl *cmdtp, const char *file_path,
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
-	if (!do_load(cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
+	if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
 		return 1;
 #endif
 	return -ENOENT;
@@ -91,13 +91,13 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		env_set("bootfile", filename);
 	}
 
-	pxe_setup_ctx(&ctx, cmdtp);
+	pxe_setup_ctx(&ctx, cmdtp, NULL);
 	if (strstr(argv[3], "ext2")) {
-		do_getfile = do_get_ext2;
+		ctx.getfile = do_get_ext2;
 	} else if (strstr(argv[3], "fat")) {
-		do_getfile = do_get_fat;
+		ctx.getfile = do_get_fat;
 	} else if (strstr(argv[3], "any")) {
-		do_getfile = do_get_any;
+		ctx.getfile = do_get_any;
 	} else {
 		printf("Invalid filesystem: %s\n", argv[3]);
 		return 1;
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 05/28] pxe: Add a userdata field to the context
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (3 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 04/28] pxe: Move do_getfile() into the context Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 06/28] pxe: Tidy up the is_pxe global Simon Glass
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Allow the caller to provide some info which is passed back to the
readfile() method.

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

 cmd/pxe.c       | 4 ++--
 cmd/pxe_utils.c | 3 ++-
 cmd/pxe_utils.h | 6 +++++-
 cmd/sysboot.c   | 2 +-
 4 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/cmd/pxe.c b/cmd/pxe.c
index 70dbde3a636..d79b9b733d7 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -121,7 +121,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	struct pxe_context ctx;
 	int err, i = 0;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp);
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL);
 
 	if (argc != 1)
 		return CMD_RET_USAGE;
@@ -175,7 +175,7 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	char *pxefile_addr_str;
 	struct pxe_context ctx;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp);
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL);
 
 	if (argc == 1) {
 		pxefile_addr_str = from_env("pxefile_addr_r");
diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index 2caae6d1555..5ad6d3e3d44 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -1432,8 +1432,9 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 }
 
 void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile)
+		   pxe_getfile_func getfile, void *userdata)
 {
 	ctx->cmdtp = cmdtp;
 	ctx->getfile = getfile;
+	ctx->userdata = userdata;
 }
diff --git a/cmd/pxe_utils.h b/cmd/pxe_utils.h
index ca2696f48b0..921455f694e 100644
--- a/cmd/pxe_utils.h
+++ b/cmd/pxe_utils.h
@@ -86,6 +86,7 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
  *
  * @cmdtp: Pointer to command table to use when calling other commands
  * @getfile: Function called by PXE to read a file
+ * @userdata: Data the caller requires for @getfile
  */
 struct pxe_context {
 	struct cmd_tbl *cmdtp;
@@ -99,6 +100,8 @@ struct pxe_context {
 	 * Return 0 if OK, -ve on error
 	 */
 	pxe_getfile_func getfile;
+
+	void *userdata;
 };
 
 /**
@@ -192,8 +195,9 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
  * @ctx: Context to set up
  * @cmdtp: Command table entry which started this action
  * @getfile: Function to call to read a file
+ * @userdata: Data the caller requires for @getfile - stored in ctx->userdata
  */
 void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile);
+		   pxe_getfile_func getfile, void *userdata);
 
 #endif /* __PXE_UTILS_H */
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 082f23543d1..5615e81e9ca 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -91,7 +91,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		env_set("bootfile", filename);
 	}
 
-	pxe_setup_ctx(&ctx, cmdtp, NULL);
+	pxe_setup_ctx(&ctx, cmdtp, NULL, NULL);
 	if (strstr(argv[3], "ext2")) {
 		ctx.getfile = do_get_ext2;
 	} else if (strstr(argv[3], "fat")) {
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 06/28] pxe: Tidy up the is_pxe global
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (4 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 05/28] pxe: Add a userdata field to " Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 07/28] pxe: Move pxe_utils files Simon Glass
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Move this into the context to avoid a global variable. Also rename it
since the current name does not explain what it actually affects.

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

 cmd/pxe.c       |  6 ++----
 cmd/pxe_utils.c | 13 +++++++------
 cmd/pxe_utils.h |  8 +++++---
 cmd/sysboot.c   |  4 +---
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/cmd/pxe.c b/cmd/pxe.c
index d79b9b733d7..17fe364bed9 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -121,7 +121,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	struct pxe_context ctx;
 	int err, i = 0;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL);
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false);
 
 	if (argc != 1)
 		return CMD_RET_USAGE;
@@ -175,7 +175,7 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	char *pxefile_addr_str;
 	struct pxe_context ctx;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL);
+	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false);
 
 	if (argc == 1) {
 		pxefile_addr_str = from_env("pxefile_addr_r");
@@ -235,8 +235,6 @@ static int do_pxe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	is_pxe = true;
-
 	/* drop initial "pxe" arg */
 	argc--;
 	argv++;
diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index 5ad6d3e3d44..7d15c75dd87 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -30,8 +30,6 @@
 
 #define MAX_TFTP_PATH_LEN 512
 
-bool is_pxe;
-
 int format_mac_pxe(char *outbuf, size_t outbuf_len)
 {
 	uchar ethaddr[6];
@@ -58,13 +56,13 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
  * be interpreted as "don't prepend anything to paths".
  */
 static int get_bootfile_path(const char *file_path, char *bootfile_path,
-			     size_t bootfile_path_size)
+			     size_t bootfile_path_size, bool allow_abs_path)
 {
 	char *bootfile, *last_slash;
 	size_t path_len = 0;
 
 	/* Only syslinux allows absolute paths */
-	if (file_path[0] == '/' && !is_pxe)
+	if (file_path[0] == '/' && allow_abs_path)
 		goto ret;
 
 	bootfile = from_env("bootfile");
@@ -110,7 +108,8 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 	char addr_buf[18];
 	int err;
 
-	err = get_bootfile_path(file_path, relfile, sizeof(relfile));
+	err = get_bootfile_path(file_path, relfile, sizeof(relfile),
+				ctx->allow_abs_path);
 
 	if (err < 0)
 		return err;
@@ -1432,9 +1431,11 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 }
 
 void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile, void *userdata)
+		   pxe_getfile_func getfile, void *userdata,
+		   bool allow_abs_path)
 {
 	ctx->cmdtp = cmdtp;
 	ctx->getfile = getfile;
 	ctx->userdata = userdata;
+	ctx->allow_abs_path = allow_abs_path;
 }
diff --git a/cmd/pxe_utils.h b/cmd/pxe_utils.h
index 921455f694e..6681442ea55 100644
--- a/cmd/pxe_utils.h
+++ b/cmd/pxe_utils.h
@@ -75,8 +75,6 @@ struct pxe_menu {
 	struct list_head labels;
 };
 
-extern bool is_pxe;
-
 struct pxe_context;
 typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
 				char *file_addr);
@@ -87,6 +85,7 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
  * @cmdtp: Pointer to command table to use when calling other commands
  * @getfile: Function called by PXE to read a file
  * @userdata: Data the caller requires for @getfile
+ * @allow_abs_path: true to allow absolute paths
  */
 struct pxe_context {
 	struct cmd_tbl *cmdtp;
@@ -102,6 +101,7 @@ struct pxe_context {
 	pxe_getfile_func getfile;
 
 	void *userdata;
+	bool allow_abs_path;
 };
 
 /**
@@ -196,8 +196,10 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
  * @cmdtp: Command table entry which started this action
  * @getfile: Function to call to read a file
  * @userdata: Data the caller requires for @getfile - stored in ctx->userdata
+ * @allow_abs_path: true to allow absolute paths
  */
 void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile, void *userdata);
+		   pxe_getfile_func getfile, void *userdata,
+		   bool allow_abs_path);
 
 #endif /* __PXE_UTILS_H */
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 5615e81e9ca..85fa5d8aa01 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -65,8 +65,6 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 	char *filename;
 	int prompt = 0;
 
-	is_pxe = false;
-
 	if (argc > 1 && strstr(argv[1], "-p")) {
 		prompt = 1;
 		argc--;
@@ -91,7 +89,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		env_set("bootfile", filename);
 	}
 
-	pxe_setup_ctx(&ctx, cmdtp, NULL, NULL);
+	pxe_setup_ctx(&ctx, cmdtp, NULL, NULL, true);
 	if (strstr(argv[3], "ext2")) {
 		ctx.getfile = do_get_ext2;
 	} else if (strstr(argv[3], "fat")) {
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 07/28] pxe: Move pxe_utils files
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (5 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 06/28] pxe: Tidy up the is_pxe global Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 08/28] pxe: Tidy up some comments in pxe_utils Simon Glass
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Move the header file into the main include/ directory so we can use it
from the bootmethod code. Move the C file into boot/ since it relates to
booting.

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

 boot/Makefile                | 3 +++
 {cmd => boot}/pxe_utils.c    | 0
 cmd/Makefile                 | 4 ++--
 cmd/sysboot.c                | 2 +-
 {cmd => include}/pxe_utils.h | 0
 5 files changed, 6 insertions(+), 3 deletions(-)
 rename {cmd => boot}/pxe_utils.c (100%)
 rename {cmd => include}/pxe_utils.h (100%)

diff --git a/boot/Makefile b/boot/Makefile
index 57d26346afb..e8f984248e6 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -14,6 +14,9 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o
 obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o
 
+obj-$(CONFIG_CMD_PXE) += pxe_utils.o
+obj-$(CONFIG_CMD_SYSBOOT) += pxe_utils.o
+
 endif
 
 obj-y += image.o
diff --git a/cmd/pxe_utils.c b/boot/pxe_utils.c
similarity index 100%
rename from cmd/pxe_utils.c
rename to boot/pxe_utils.c
diff --git a/cmd/Makefile b/cmd/Makefile
index ed3669411e6..891819ae0f6 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -123,7 +123,7 @@ obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PMC) += pmc.o
 obj-$(CONFIG_CMD_PSTORE) += pstore.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
-obj-$(CONFIG_CMD_PXE) += pxe.o pxe_utils.o
+obj-$(CONFIG_CMD_PXE) += pxe.o
 obj-$(CONFIG_CMD_WOL) += wol.o
 obj-$(CONFIG_CMD_QFW) += qfw.o
 obj-$(CONFIG_CMD_READ) += read.o
@@ -145,7 +145,7 @@ obj-$(CONFIG_CMD_SETEXPR_FMT) += printf.o
 obj-$(CONFIG_CMD_SPI) += spi.o
 obj-$(CONFIG_CMD_STRINGS) += strings.o
 obj-$(CONFIG_CMD_SMC) += smccc.o
-obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o pxe_utils.o
+obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o
 obj-$(CONFIG_CMD_STACKPROTECTOR_TEST) += stackprot_test.o
 obj-$(CONFIG_CMD_TERMINAL) += terminal.o
 obj-$(CONFIG_CMD_TIME) += time.o
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 85fa5d8aa01..b81255e155a 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -4,7 +4,7 @@
 #include <command.h>
 #include <env.h>
 #include <fs.h>
-#include "pxe_utils.h"
+#include <pxe_utils.h>
 
 static char *fs_argv[5];
 
diff --git a/cmd/pxe_utils.h b/include/pxe_utils.h
similarity index 100%
rename from cmd/pxe_utils.h
rename to include/pxe_utils.h
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 08/28] pxe: Tidy up some comments in pxe_utils
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (6 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 07/28] pxe: Move pxe_utils files Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 09/28] pxe: Tidy up code style a little " Simon Glass
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Some of these functions are a big vague in the comments. Tidy them up a
bit.

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

 boot/pxe_utils.c | 189 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 138 insertions(+), 51 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 7d15c75dd87..7a2213a5925 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -30,6 +30,21 @@
 
 #define MAX_TFTP_PATH_LEN 512
 
+/**
+ * format_mac_pxe() - obtain a MAC address in the PXE format
+ *
+ * This produces a MAC-address string in the format for the current ethernet
+ * device:
+ *
+ *   01-aa-bb-cc-dd-ee-ff
+ *
+ * where aa-ff is the MAC address in hex
+ *
+ * @outbuf: Buffer to write string to
+ * @outbuf_len: length of buffer
+ * @return 1 if OK, -ENOSPC if buffer is too small, -ENOENT is there is no
+ *	current ethernet device
+ */
 int format_mac_pxe(char *outbuf, size_t outbuf_len)
 {
 	uchar ethaddr[6];
@@ -37,7 +52,7 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
 	if (outbuf_len < 21) {
 		printf("outbuf is too small (%zd < 21)\n", outbuf_len);
 
-		return -EINVAL;
+		return -ENOSPC;
 	}
 
 	if (!eth_env_get_enetaddr_by_index("eth", eth_get_dev_index(), ethaddr))
@@ -50,10 +65,20 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
 	return 1;
 }
 
-/*
- * Returns the directory the file specified in the bootfile env variable is
+/**
+ * get_bootfile_path() - Figure out the path of a file to read
+ *
+ * Returns the directory the file specified in the 'bootfile' env variable is
  * in. If bootfile isn't defined in the environment, return NULL, which should
  * be interpreted as "don't prepend anything to paths".
+ *
+ * @file_path: File path to read (relative to the PXE file)
+ * @bootfile_path: Place to put the bootfile path
+ * @bootfile_path_size: Size of @bootfile_path in bytes
+ * @allow_abs_path: true to allow an absolute path (where @file_path starts with
+ *	'/', false to return an empty path (and success) in that case
+ * Returns 1 for success, -ENOSPC if bootfile_path_size is to small to hold the
+ *	resulting path
  */
 static int get_bootfile_path(const char *file_path, char *bootfile_path,
 			     size_t bootfile_path_size, bool allow_abs_path)
@@ -81,7 +106,7 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
 		printf("bootfile_path too small. (%zd < %zd)\n",
 		       bootfile_path_size, path_len);
 
-		return -1;
+		return -ENOSPC;
 	}
 
 	strncpy(bootfile_path, bootfile, path_len);
@@ -92,13 +117,18 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
 	return 1;
 }
 
-/*
+/**
+ * get_relfile() - read a file relative to the PXE file
+ *
  * As in pxelinux, paths to files referenced from files we retrieve are
  * relative to the location of bootfile. get_relfile takes such a path and
  * joins it with the bootfile path to get the full path to the target file. If
  * the bootfile path is NULL, we use file_path as is.
  *
- * Returns 1 for success, or < 0 on error.
+ * @ctx: PXE context
+ * @file_path: File path to read (relative to the PXE file)
+ * @file_addr: Address to load file to
+ * Returns 1 for success, or < 0 on error
  */
 static int get_relfile(struct pxe_context *ctx, const char *file_path,
 		       unsigned long file_addr)
@@ -132,6 +162,16 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 	return ctx->getfile(ctx, relfile, addr_buf);
 }
 
+/**
+ * get_pxe_file() - read a file
+ *
+ * The file is read and nul-terminated
+ *
+ * @ctx: PXE context
+ * @file_path: File path to read (relative to the PXE file)
+ * @file_addr: Address to load file to
+ * Returns 1 for success, or < 0 on error
+ */
 int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 		 unsigned long file_addr)
 {
@@ -166,6 +206,14 @@ int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 
 #define PXELINUX_DIR "pxelinux.cfg/"
 
+/**
+ * get_pxelinux_path() - Get a file in the pxelinux.cfg/ directory
+ *
+ * @ctx: PXE context
+ * @file: Filename to process (relative to pxelinux.cfg/)
+ * Returns 1 for success, -ENAMETOOLONG if the resulting path is too long.
+ *	or other value < 0 on other error
+ */
 int get_pxelinux_path(struct pxe_context *ctx, const char *file,
 		      unsigned long pxefile_addr_r)
 {
@@ -183,12 +231,20 @@ int get_pxelinux_path(struct pxe_context *ctx, const char *file,
 	return get_pxe_file(ctx, path, pxefile_addr_r);
 }
 
-/*
+/**
+ * get_relfile_envaddr() - read a file to an address in an env var
+ *
  * Wrapper to make it easier to store the file at file_path in the location
  * specified by envaddr_name. file_path will be joined to the bootfile path,
  * if any is specified.
  *
- * Returns 1 on success or < 0 on error.
+ * @ctx: PXE context
+ * @file_path: File path to read (relative to the PXE file)
+ * @envaddr_name: Name of environment variable which contains the address to
+ *	load to
+ * Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
+ *	environment variable, -EINVAL if its format is not valid hex, or other
+ *	value < 0 on other error
  */
 static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
 			       const char *envaddr_name)
@@ -207,11 +263,13 @@ static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
 	return get_relfile(ctx, file_path, file_addr);
 }
 
-/*
+/**
+ * label_create() - crate a new PXE label
+ *
  * Allocates memory for and initializes a pxe_label. This uses malloc, so the
  * result must be free()'d to reclaim the memory.
  *
- * Returns NULL if malloc fails.
+ * Returns a pointer to the label, or NULL if out of memory
  */
 static struct pxe_label *label_create(void)
 {
@@ -227,13 +285,18 @@ static struct pxe_label *label_create(void)
 	return label;
 }
 
-/*
- * Free the memory used by a pxe_label, including that used by its name,
- * kernel, append and initrd members, if they're non NULL.
+/**
+ * label_destroy() - free the memory used by a pxe_label
+ *
+ * This frees @label itself as well as memory used by its name,
+ * kernel, config, append, initrd, fdt, fdtdir and fdtoverlay members, if
+ * they're non-NULL.
  *
  * So - be sure to only use dynamically allocated memory for the members of
  * the pxe_label struct, unless you want to clean it up first. These are
  * currently only created by the pxe file parsing code.
+ *
+ * @label: Label to free
  */
 static void label_destroy(struct pxe_label *label)
 {
@@ -264,11 +327,13 @@ static void label_destroy(struct pxe_label *label)
 	free(label);
 }
 
-/*
- * Print a label and its string members if they're defined.
+/**
+ * label_print() - Print a label and its string members if they're defined
  *
  * This is passed as a callback to the menu code for displaying each
  * menu entry.
+ *
+ * @data: Label to print (is cast to struct pxe_label *)
  */
 static void label_print(void *data)
 {
@@ -278,14 +343,16 @@ static void label_print(void *data)
 	printf("%s:\t%s\n", label->num, c);
 }
 
-/*
- * Boot a label that specified 'localboot'. This requires that the 'localcmd'
- * environment variable is defined. Its contents will be executed as U-Boot
- * command.  If the label specified an 'append' line, its contents will be
- * used to overwrite the contents of the 'bootargs' environment variable prior
- * to running 'localcmd'.
+/**
+ * label_localboot() - Boot a label that specified 'localboot'
+ *
+ * This requires that the 'localcmd' environment variable is defined. Its
+ * contents will be executed as U-Boot commands.  If the label specified an
+ * 'append' line, its contents will be used to overwrite the contents of the
+ * 'bootargs' environment variable prior to running 'localcmd'.
  *
- * Returns 1 on success or < 0 on error.
+ * @label: Label to process
+ * Returns 1 on success or < 0 on error
  */
 static int label_localboot(struct pxe_label *label)
 {
@@ -309,8 +376,11 @@ static int label_localboot(struct pxe_label *label)
 	return run_command_list(localcmd, strlen(localcmd), 0);
 }
 
-/*
- * Loads fdt overlays specified in 'fdtoverlays'.
+/**
+ * label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
+ *
+ * @ctx: PXE context
+ * @label: Label to process
  */
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
 static void label_boot_fdtoverlay(struct pxe_context *ctx,
@@ -396,8 +466,8 @@ skip_overlay:
 }
 #endif
 
-/*
- * Boot according to the contents of a pxe_label.
+/**
+ * label_boot() - Boot according to the contents of a pxe_label
  *
  * If we can't boot for any reason, we return.  A successful boot never
  * returns.
@@ -410,6 +480,11 @@ skip_overlay:
  *
  * If the label specifies an 'append' line, its contents will overwrite that
  * of the 'bootargs' environment variable.
+ *
+ * @ctx: PXE context
+ * @label: Label to process
+ * Returns does not return on success, otherwise returns 0 if a localboot
+ *	label was processed, or 1 on error
  */
 static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 {
@@ -648,9 +723,7 @@ cleanup:
 	return 1;
 }
 
-/*
- * Tokens for the pxe file parser.
- */
+/** enum token_type - Tokens for the pxe file parser */
 enum token_type {
 	T_EOL,
 	T_STRING,
@@ -676,17 +749,13 @@ enum token_type {
 	T_INVALID
 };
 
-/*
- * A token - given by a value and a type.
- */
+/** struct token - token - given by a value and a type */
 struct token {
 	char *val;
 	enum token_type type;
 };
 
-/*
- * Keywords recognized.
- */
+/* Keywords recognized */
 static const struct token keywords[] = {
 	{"menu", T_MENU},
 	{"title", T_TITLE},
@@ -711,7 +780,9 @@ static const struct token keywords[] = {
 	{NULL, T_INVALID}
 };
 
-/*
+/**
+ * enum lex_state - lexer state
+ *
  * Since pxe(linux) files don't have a token to identify the start of a
  * literal, we have to keep track of when we're in a state where a literal is
  * expected vs when we're in a state a keyword is expected.
@@ -722,11 +793,10 @@ enum lex_state {
 	L_SLITERAL
 };
 
-/*
- * get_string retrieves a string from *p and stores it as a token in
- * *t.
+/**
+ * get_string() - retrieves a string from *p and stores it as a token in *t.
  *
- * get_string used for scanning both string literals and keywords.
+ * This is used for scanning both string literals and keywords.
  *
  * Characters from *p are copied into t-val until a character equal to
  * delim is found, or a NUL byte is reached. If delim has the special value of
@@ -739,9 +809,15 @@ enum lex_state {
  * The location of *p is updated to point to the first character after the end
  * of the token - the ending delimiter.
  *
- * On success, the new value of t->val is returned. Memory for t->val is
- * allocated using malloc and must be free()'d to reclaim it.  If insufficient
- * memory is available, NULL is returned.
+ * Memory for t->val is allocated using malloc and must be free()'d to reclaim
+ * it.
+ *
+ * @p: Points to a pointer to the current position in the input being processed.
+ *	Updated to point at the first character after the current token
+ * @t: Pointers to a token to fill in
+ * @delim: Delimiter character to look for, either newline or space
+ * @lower: true to convert the string to lower case when storing
+ * Returns the new value of t->val, on success, NULL if out of memory
  */
 static char *get_string(char **p, struct token *t, char delim, int lower)
 {
@@ -792,8 +868,11 @@ static char *get_string(char **p, struct token *t, char delim, int lower)
 	return t->val;
 }
 
-/*
- * Populate a keyword token with a type and value.
+/**
+ * get_keyword() - Populate a keyword token with a type and value
+ *
+ * Updates the ->type field based on the keyword string in @val
+ * @t: Token to populate
  */
 static void get_keyword(struct token *t)
 {
@@ -807,11 +886,14 @@ static void get_keyword(struct token *t)
 	}
 }
 
-/*
- * Get the next token.  We have to keep track of which state we're in to know
- * if we're looking to get a string literal or a keyword.
+/**
+ * get_token() - Get the next token
+ *
+ * We have to keep track of which state we're in to know if we're looking to get
+ * a string literal or a keyword.
  *
- * *p is updated to point at the first character after the current token.
+ * @p: Points to a pointer to the current position in the input being processed.
+ *	Updated to point at the first character after the current token
  */
 static void get_token(char **p, struct token *t, enum lex_state state)
 {
@@ -855,8 +937,13 @@ static void get_token(char **p, struct token *t, enum lex_state state)
 	*p = c;
 }
 
-/*
- * Increment *c until we get to the end of the current line, or EOF.
+/**
+ * eol_or_eof() - Find end of line
+ *
+ * Increment *c until we get to the end of the current line, or EOF
+ *
+ * @c: Points to a pointer to the current position in the input being processed.
+ *	Updated to point at the first character after the current token
  */
 static void eol_or_eof(char **c)
 {
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 09/28] pxe: Tidy up code style a little in pxe_utils
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (7 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 08/28] pxe: Tidy up some comments in pxe_utils Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 10/28] pxe: Move common parsing coding into pxe_util Simon Glass
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

There are a few more blank lines than makes sense for readability. Also
free() handles a NULL pointer so drop the pointless checks.

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

 boot/pxe_utils.c | 66 ++++++++++--------------------------------------
 1 file changed, 13 insertions(+), 53 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 7a2213a5925..9f3edeab06a 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -51,7 +51,6 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
 
 	if (outbuf_len < 21) {
 		printf("outbuf is too small (%zd < 21)\n", outbuf_len);
-
 		return -ENOSPC;
 	}
 
@@ -91,12 +90,10 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
 		goto ret;
 
 	bootfile = from_env("bootfile");
-
 	if (!bootfile)
 		goto ret;
 
 	last_slash = strrchr(bootfile, '/');
-
 	if (!last_slash)
 		goto ret;
 
@@ -140,7 +137,6 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 
 	err = get_bootfile_path(file_path, relfile, sizeof(relfile),
 				ctx->allow_abs_path);
-
 	if (err < 0)
 		return err;
 
@@ -181,7 +177,6 @@ int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 	char *buf;
 
 	err = get_relfile(ctx, file_path, file_addr);
-
 	if (err < 0)
 		return err;
 
@@ -190,7 +185,6 @@ int get_pxe_file(struct pxe_context *ctx, const char *file_path,
 	 * and add the NUL byte.
 	 */
 	tftp_filesize = from_env("filesize");
-
 	if (!tftp_filesize)
 		return -ENOENT;
 
@@ -253,7 +247,6 @@ static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
 	char *envaddr;
 
 	envaddr = from_env(envaddr_name);
-
 	if (!envaddr)
 		return -ENOENT;
 
@@ -276,7 +269,6 @@ static struct pxe_label *label_create(void)
 	struct pxe_label *label;
 
 	label = malloc(sizeof(struct pxe_label));
-
 	if (!label)
 		return NULL;
 
@@ -300,30 +292,14 @@ static struct pxe_label *label_create(void)
  */
 static void label_destroy(struct pxe_label *label)
 {
-	if (label->name)
-		free(label->name);
-
-	if (label->kernel)
-		free(label->kernel);
-
-	if (label->config)
-		free(label->config);
-
-	if (label->append)
-		free(label->append);
-
-	if (label->initrd)
-		free(label->initrd);
-
-	if (label->fdt)
-		free(label->fdt);
-
-	if (label->fdtdir)
-		free(label->fdtdir);
-
-	if (label->fdtoverlays)
-		free(label->fdtoverlays);
-
+	free(label->name);
+	free(label->kernel);
+	free(label->config);
+	free(label->append);
+	free(label->initrd);
+	free(label->fdt);
+	free(label->fdtdir);
+	free(label->fdtoverlays);
 	free(label);
 }
 
@@ -359,7 +335,6 @@ static int label_localboot(struct pxe_label *label)
 	char *localcmd;
 
 	localcmd = from_env("localcmd");
-
 	if (!localcmd)
 		return -ENOENT;
 
@@ -718,8 +693,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 	unmap_sysmem(buf);
 
 cleanup:
-	if (fit_addr)
-		free(fit_addr);
+	free(fit_addr);
+
 	return 1;
 }
 
@@ -832,7 +807,6 @@ static char *get_string(char **p, struct token *t, char delim, int lower)
 	 */
 	b = *p;
 	e = *p;
-
 	while (*e) {
 		if ((delim == ' ' && isspace(*e)) || delim == *e)
 			break;
@@ -858,11 +832,8 @@ static char *get_string(char **p, struct token *t, char delim, int lower)
 
 	t->val[len] = '\0';
 
-	/*
-	 * Update *p so the caller knows where to continue scanning.
-	 */
+	/* Update *p so the caller knows where to continue scanning */
 	*p = e;
-
 	t->type = T_STRING;
 
 	return t->val;
@@ -988,7 +959,6 @@ static int parse_integer(char **c, int *dst)
 	char *s = *c;
 
 	get_token(c, &t, L_SLITERAL);
-
 	if (t.type != T_STRING) {
 		printf("Expected string: %.*s\n", (int)(*c - s), s);
 		return -EINVAL;
@@ -1022,14 +992,12 @@ static int handle_include(struct pxe_context *ctx, char **c, unsigned long base,
 	int ret;
 
 	err = parse_sliteral(c, &include_path);
-
 	if (err < 0) {
 		printf("Expected include path: %.*s\n", (int)(*c - s), s);
 		return err;
 	}
 
 	err = get_pxe_file(ctx, include_path, base);
-
 	if (err < 0) {
 		printf("Couldn't retrieve %s\n", include_path);
 		return err;
@@ -1079,7 +1047,6 @@ static int parse_menu(struct pxe_context *ctx, char **c, struct pxe_menu *cfg,
 		printf("Ignoring malformed menu command: %.*s\n",
 		       (int)(*c - s), s);
 	}
-
 	if (err < 0)
 		return err;
 
@@ -1353,11 +1320,8 @@ void destroy_pxe_menu(struct pxe_menu *cfg)
 	struct list_head *pos, *n;
 	struct pxe_label *label;
 
-	if (cfg->title)
-		free(cfg->title);
-
-	if (cfg->default_label)
-		free(cfg->default_label);
+	free(cfg->title);
+	free(cfg->default_label);
 
 	list_for_each_safe(pos, n, &cfg->labels) {
 		label = list_entry(pos, struct pxe_label, list);
@@ -1375,7 +1339,6 @@ struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
 	int r;
 
 	cfg = malloc(sizeof(struct pxe_menu));
-
 	if (!cfg)
 		return NULL;
 
@@ -1386,7 +1349,6 @@ struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
 	buf = map_sysmem(menucfg, 0);
 	r = parse_pxefile_top(ctx, buf, menucfg, cfg, 1);
 	unmap_sysmem(buf);
-
 	if (r < 0) {
 		destroy_pxe_menu(cfg);
 		return NULL;
@@ -1413,7 +1375,6 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
 	 */
 	m = menu_create(cfg->title, DIV_ROUND_UP(cfg->timeout, 10),
 			cfg->prompt, NULL, label_print, NULL, NULL);
-
 	if (!m)
 		return NULL;
 
@@ -1492,7 +1453,6 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 		return;
 
 	err = menu_get_choice(m, &choice);
-
 	menu_destroy(m);
 
 	/*
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 10/28] pxe: Move common parsing coding into pxe_util
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (8 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 09/28] pxe: Tidy up code style a little " Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 11/28] pxe: Clean up the use of bootfile Simon Glass
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Both the syslinux and pxe commands use essentially the same code to parse
and run extlinux.conf files. Move this into a common function.

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

 boot/pxe_utils.c    | 20 ++++++++++++++++++++
 cmd/pxe.c           | 15 ++++-----------
 cmd/sysboot.c       | 18 ++++--------------
 include/pxe_utils.h |  9 +++++++++
 4 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 9f3edeab06a..225729ce57f 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -1486,3 +1486,23 @@ void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
 	ctx->userdata = userdata;
 	ctx->allow_abs_path = allow_abs_path;
 }
+
+int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
+{
+	struct pxe_menu *cfg;
+
+	cfg = parse_pxefile(ctx, pxefile_addr_r);
+	if (!cfg) {
+		printf("Error parsing config file\n");
+		return 1;
+	}
+
+	if (prompt)
+		cfg->prompt = 1;
+
+	handle_pxe_menu(ctx, cfg);
+
+	destroy_pxe_menu(cfg);
+
+	return 0;
+}
diff --git a/cmd/pxe.c b/cmd/pxe.c
index 17fe364bed9..4fa51d2e053 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -171,9 +171,9 @@ static int
 do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	unsigned long pxefile_addr_r;
-	struct pxe_menu *cfg;
 	char *pxefile_addr_str;
 	struct pxe_context ctx;
+	int ret;
 
 	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false);
 
@@ -193,16 +193,9 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		return 1;
 	}
 
-	cfg = parse_pxefile(&ctx, pxefile_addr_r);
-
-	if (!cfg) {
-		printf("Error parsing config file\n");
-		return 1;
-	}
-
-	handle_pxe_menu(&ctx, cfg);
-
-	destroy_pxe_menu(cfg);
+	ret = pxe_process(&ctx, pxefile_addr_r, false);
+	if (ret)
+		return CMD_RET_FAILURE;
 
 	copy_filename(net_boot_file_name, "", sizeof(net_boot_file_name));
 
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index b81255e155a..7ee14df79e5 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -60,10 +60,10 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 {
 	unsigned long pxefile_addr_r;
 	struct pxe_context ctx;
-	struct pxe_menu *cfg;
 	char *pxefile_addr_str;
 	char *filename;
 	int prompt = 0;
+	int ret;
 
 	if (argc > 1 && strstr(argv[1], "-p")) {
 		prompt = 1;
@@ -113,19 +113,9 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		return 1;
 	}
 
-	cfg = parse_pxefile(&ctx, pxefile_addr_r);
-
-	if (!cfg) {
-		printf("Error parsing config file\n");
-		return 1;
-	}
-
-	if (prompt)
-		cfg->prompt = 1;
-
-	handle_pxe_menu(&ctx, cfg);
-
-	destroy_pxe_menu(cfg);
+	ret = pxe_process(&ctx, pxefile_addr_r, prompt);
+	if (ret)
+		return CMD_RET_FAILURE;
 
 	return 0;
 }
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 6681442ea55..0cae0dabec3 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -202,4 +202,13 @@ void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
 		   pxe_getfile_func getfile, void *userdata,
 		   bool allow_abs_path);
 
+/**
+ * pxe_process() - Process a PXE file through to boot
+ *
+ * @ctx: PXE context created with pxe_setup_ctx()
+ * @pxefile_addr_r: Address to load file
+ * @prompt: Force a prompt for the user
+ */
+int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt);
+
 #endif /* __PXE_UTILS_H */
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 11/28] pxe: Clean up the use of bootfile
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (9 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 10/28] pxe: Move common parsing coding into pxe_util Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 12/28] pxe: Drop get_bootfile_path() Simon Glass
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

The 'bootfile' environment variable is read in the bowels of pxe_util to
provide a directory to which all loaded files are relative.

This is not obvious from the API to PXE and it is strange to make the
caller set an environment variable rather than pass this as a parameter.

The code is also convoluted, which this feature implemented by
get_bootfile_path().

Update the API to improve this. Unfortunately this means that
pxe_setup_ctx() can fail, so add error checking.

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

 boot/pxe_utils.c    | 60 ++++++++++++++++++++++++++++-----------------
 cmd/pxe.c           | 18 +++++++++++---
 cmd/sysboot.c       | 15 +++++++++---
 include/pxe_utils.h | 19 +++++++++++---
 4 files changed, 79 insertions(+), 33 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 225729ce57f..c04be110ea4 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -67,10 +67,10 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
 /**
  * get_bootfile_path() - Figure out the path of a file to read
  *
- * Returns the directory the file specified in the 'bootfile' env variable is
- * in. If bootfile isn't defined in the environment, return NULL, which should
- * be interpreted as "don't prepend anything to paths".
+ * Copies the boot directory into the supplied buffer. If there is no boot
+ * directory, set it to ""
  *
+ * @ctx: PXE context
  * @file_path: File path to read (relative to the PXE file)
  * @bootfile_path: Place to put the bootfile path
  * @bootfile_path_size: Size of @bootfile_path in bytes
@@ -79,34 +79,25 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
  * Returns 1 for success, -ENOSPC if bootfile_path_size is to small to hold the
  *	resulting path
  */
-static int get_bootfile_path(const char *file_path, char *bootfile_path,
-			     size_t bootfile_path_size, bool allow_abs_path)
+static int get_bootfile_path(struct pxe_context *ctx, const char *file_path,
+			     char *bootfile_path, size_t bootfile_path_size,
+			     bool allow_abs_path)
 {
-	char *bootfile, *last_slash;
 	size_t path_len = 0;
 
 	/* Only syslinux allows absolute paths */
 	if (file_path[0] == '/' && allow_abs_path)
 		goto ret;
 
-	bootfile = from_env("bootfile");
-	if (!bootfile)
-		goto ret;
-
-	last_slash = strrchr(bootfile, '/');
-	if (!last_slash)
-		goto ret;
-
-	path_len = (last_slash - bootfile) + 1;
-
-	if (bootfile_path_size < path_len) {
+	path_len = strlen(ctx->bootdir);
+	if (bootfile_path_size < path_len + 1) {
 		printf("bootfile_path too small. (%zd < %zd)\n",
 		       bootfile_path_size, path_len);
 
 		return -ENOSPC;
 	}
 
-	strncpy(bootfile_path, bootfile, path_len);
+	strncpy(bootfile_path, ctx->bootdir, path_len);
 
  ret:
 	bootfile_path[path_len] = '\0';
@@ -135,7 +126,7 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 	char addr_buf[18];
 	int err;
 
-	err = get_bootfile_path(file_path, relfile, sizeof(relfile),
+	err = get_bootfile_path(ctx, file_path, relfile, sizeof(relfile),
 				ctx->allow_abs_path);
 	if (err < 0)
 		return err;
@@ -1477,14 +1468,39 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 	boot_unattempted_labels(ctx, cfg);
 }
 
-void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile, void *userdata,
-		   bool allow_abs_path)
+int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
+		  pxe_getfile_func getfile, void *userdata,
+		  bool allow_abs_path, const char *bootfile)
 {
+	const char *last_slash;
+	size_t path_len = 0;
+
+	memset(ctx, '\0', sizeof(*ctx));
 	ctx->cmdtp = cmdtp;
 	ctx->getfile = getfile;
 	ctx->userdata = userdata;
 	ctx->allow_abs_path = allow_abs_path;
+
+	/* figure out the boot directory, if there is one */
+	if (bootfile && strlen(bootfile) >= MAX_TFTP_PATH_LEN)
+		return -ENOSPC;
+	ctx->bootdir = strdup(bootfile ? bootfile : "");
+	if (!ctx->bootdir)
+		return -ENOMEM;
+
+	if (bootfile) {
+		last_slash = strrchr(bootfile, '/');
+		if (last_slash)
+			path_len = (last_slash - bootfile) + 1;
+	}
+	ctx->bootdir[path_len] = '\0';
+
+	return 0;
+}
+
+void pxe_destroy_ctx(struct pxe_context *ctx)
+{
+	free(ctx->bootdir);
 }
 
 int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
diff --git a/cmd/pxe.c b/cmd/pxe.c
index 4fa51d2e053..e319db51ef5 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -121,8 +121,6 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	struct pxe_context ctx;
 	int err, i = 0;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false);
-
 	if (argc != 1)
 		return CMD_RET_USAGE;
 
@@ -136,6 +134,11 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	if (err < 0)
 		return 1;
 
+	if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
+			  env_get("bootfile"))) {
+		printf("Out of memory\n");
+		return CMD_RET_FAILURE;
+	}
 	/*
 	 * Keep trying paths until we successfully get a file we're looking
 	 * for.
@@ -144,6 +147,7 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	    pxe_mac_path(&ctx, pxefile_addr_r) > 0 ||
 	    pxe_ipaddr_paths(&ctx, pxefile_addr_r) > 0) {
 		printf("Config file found\n");
+		pxe_destroy_ctx(&ctx);
 
 		return 0;
 	}
@@ -152,12 +156,14 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		if (get_pxelinux_path(&ctx, pxe_default_paths[i],
 				      pxefile_addr_r) > 0) {
 			printf("Config file found\n");
+			pxe_destroy_ctx(&ctx);
 			return 0;
 		}
 		i++;
 	}
 
 	printf("Config file not found\n");
+	pxe_destroy_ctx(&ctx);
 
 	return 1;
 }
@@ -175,8 +181,6 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	struct pxe_context ctx;
 	int ret;
 
-	pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false);
-
 	if (argc == 1) {
 		pxefile_addr_str = from_env("pxefile_addr_r");
 		if (!pxefile_addr_str)
@@ -193,7 +197,13 @@ do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		return 1;
 	}
 
+	if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
+			  env_get("bootfile"))) {
+		printf("Out of memory\n");
+		return CMD_RET_FAILURE;
+	}
 	ret = pxe_process(&ctx, pxefile_addr_r, false);
+	pxe_destroy_ctx(&ctx);
 	if (ret)
 		return CMD_RET_FAILURE;
 
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 7ee14df79e5..c45fed774d6 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -59,6 +59,7 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
 	unsigned long pxefile_addr_r;
+	pxe_getfile_func getfile;
 	struct pxe_context ctx;
 	char *pxefile_addr_str;
 	char *filename;
@@ -89,13 +90,12 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		env_set("bootfile", filename);
 	}
 
-	pxe_setup_ctx(&ctx, cmdtp, NULL, NULL, true);
 	if (strstr(argv[3], "ext2")) {
-		ctx.getfile = do_get_ext2;
+		getfile = do_get_ext2;
 	} else if (strstr(argv[3], "fat")) {
-		ctx.getfile = do_get_fat;
+		getfile = do_get_fat;
 	} else if (strstr(argv[3], "any")) {
-		ctx.getfile = do_get_any;
+		getfile = do_get_any;
 	} else {
 		printf("Invalid filesystem: %s\n", argv[3]);
 		return 1;
@@ -108,12 +108,19 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		return 1;
 	}
 
+	if (pxe_setup_ctx(&ctx, cmdtp, getfile, NULL, true, filename)) {
+		printf("Out of memory\n");
+		return CMD_RET_FAILURE;
+	}
+
 	if (get_pxe_file(&ctx, filename, pxefile_addr_r) < 0) {
 		printf("Error reading config file\n");
+		pxe_destroy_ctx(&ctx);
 		return 1;
 	}
 
 	ret = pxe_process(&ctx, pxefile_addr_r, prompt);
+	pxe_destroy_ctx(&ctx);
 	if (ret)
 		return CMD_RET_FAILURE;
 
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 0cae0dabec3..543d0245c8a 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -86,6 +86,8 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
  * @getfile: Function called by PXE to read a file
  * @userdata: Data the caller requires for @getfile
  * @allow_abs_path: true to allow absolute paths
+ * @bootdir: Directory that files are loaded from ("" if no directory). This is
+ *	allocated
  */
 struct pxe_context {
 	struct cmd_tbl *cmdtp;
@@ -102,6 +104,7 @@ struct pxe_context {
 
 	void *userdata;
 	bool allow_abs_path;
+	char *bootdir;
 };
 
 /**
@@ -197,10 +200,20 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
  * @getfile: Function to call to read a file
  * @userdata: Data the caller requires for @getfile - stored in ctx->userdata
  * @allow_abs_path: true to allow absolute paths
+ * @bootfile: Bootfile whose directory loaded files are relative to, NULL if
+ *	none
+ * @return 0 if OK, -ENOMEM if out of memory
  */
-void pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
-		   pxe_getfile_func getfile, void *userdata,
-		   bool allow_abs_path);
+int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
+		  pxe_getfile_func getfile, void *userdata,
+		  bool allow_abs_path, const char *bootfile);
+
+/**
+ * pxe_destroy_ctx() - Destroy a PXE context
+ *
+ * @ctx: Context to destroy
+ */
+void pxe_destroy_ctx(struct pxe_context *ctx);
 
 /**
  * pxe_process() - Process a PXE file through to boot
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 12/28] pxe: Drop get_bootfile_path()
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (10 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 11/28] pxe: Clean up the use of bootfile Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 13/28] lib: Add tests for simple_itoa() Simon Glass
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

This function no longer makes sense, since it is pretty easy to prepend
the boot directory to the filename. Drop it and update its only caller.

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

 boot/pxe_utils.c    | 53 +++++----------------------------------------
 include/pxe_utils.h |  3 ++-
 2 files changed, 7 insertions(+), 49 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index c04be110ea4..f36f1f8a60c 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -64,47 +64,6 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
 	return 1;
 }
 
-/**
- * get_bootfile_path() - Figure out the path of a file to read
- *
- * Copies the boot directory into the supplied buffer. If there is no boot
- * directory, set it to ""
- *
- * @ctx: PXE context
- * @file_path: File path to read (relative to the PXE file)
- * @bootfile_path: Place to put the bootfile path
- * @bootfile_path_size: Size of @bootfile_path in bytes
- * @allow_abs_path: true to allow an absolute path (where @file_path starts with
- *	'/', false to return an empty path (and success) in that case
- * Returns 1 for success, -ENOSPC if bootfile_path_size is to small to hold the
- *	resulting path
- */
-static int get_bootfile_path(struct pxe_context *ctx, const char *file_path,
-			     char *bootfile_path, size_t bootfile_path_size,
-			     bool allow_abs_path)
-{
-	size_t path_len = 0;
-
-	/* Only syslinux allows absolute paths */
-	if (file_path[0] == '/' && allow_abs_path)
-		goto ret;
-
-	path_len = strlen(ctx->bootdir);
-	if (bootfile_path_size < path_len + 1) {
-		printf("bootfile_path too small. (%zd < %zd)\n",
-		       bootfile_path_size, path_len);
-
-		return -ENOSPC;
-	}
-
-	strncpy(bootfile_path, ctx->bootdir, path_len);
-
- ret:
-	bootfile_path[path_len] = '\0';
-
-	return 1;
-}
-
 /**
  * get_relfile() - read a file relative to the PXE file
  *
@@ -124,15 +83,13 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 	size_t path_len;
 	char relfile[MAX_TFTP_PATH_LEN + 1];
 	char addr_buf[18];
-	int err;
 
-	err = get_bootfile_path(ctx, file_path, relfile, sizeof(relfile),
-				ctx->allow_abs_path);
-	if (err < 0)
-		return err;
+	if (file_path[0] == '/' && ctx->allow_abs_path)
+		*relfile = '\0';
+	else
+		strncpy(relfile, ctx->bootdir, MAX_TFTP_PATH_LEN);
 
-	path_len = strlen(file_path);
-	path_len += strlen(relfile);
+	path_len = strlen(file_path) + strlen(relfile);
 
 	if (path_len > MAX_TFTP_PATH_LEN) {
 		printf("Base path too long (%s%s)\n", relfile, file_path);
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 543d0245c8a..8b50f2e6861 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -202,7 +202,8 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len);
  * @allow_abs_path: true to allow absolute paths
  * @bootfile: Bootfile whose directory loaded files are relative to, NULL if
  *	none
- * @return 0 if OK, -ENOMEM if out of memory
+ * @return 0 if OK, -ENOMEM if out of memory, -E2BIG if bootfile is larger than
+ *	MAX_TFTP_PATH_LEN bytes
  */
 int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
 		  pxe_getfile_func getfile, void *userdata,
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 13/28] lib: Add tests for simple_itoa()
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (11 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 12/28] pxe: Drop get_bootfile_path() Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 14/28] lib: Add a function to convert a string to a hex value Simon Glass
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add test and a comment for this function.

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

 include/vsprintf.h | 13 ++++++++++++-
 test/print_ut.c    | 17 +++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 83d187e53d4..4479df0af3f 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -172,7 +172,18 @@ int sprintf(char *buf, const char *fmt, ...)
  * See the vsprintf() documentation for format string extensions over C99.
  */
 int vsprintf(char *buf, const char *fmt, va_list args);
-char *simple_itoa(ulong i);
+
+/**
+ * simple_itoa() - convert an unsigned integer to a string
+ *
+ * This returns a static string containing the decimal representation of the
+ * given value. The returned value may be overwritten by other calls to the
+ * same function, so should be used immediately
+ *
+ * @val: Value to convert
+ * @return string containing the decimal representation of @val
+ */
+char *simple_itoa(ulong val);
 
 /**
  * Format a string and place it in a buffer
diff --git a/test/print_ut.c b/test/print_ut.c
index e2bcfbef007..737845afd33 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -10,6 +10,7 @@
 #include <log.h>
 #include <mapmem.h>
 #include <version.h>
+#include <vsprintf.h>
 #include <test/suites.h>
 #include <test/test.h>
 #include <test/ut.h>
@@ -328,6 +329,22 @@ static int print_do_hex_dump(struct unit_test_state *uts)
 }
 PRINT_TEST(print_do_hex_dump, UT_TESTF_CONSOLE_REC);
 
+static int print_itoa(struct unit_test_state *uts)
+{
+	ut_asserteq_str("123", simple_itoa(123));
+	ut_asserteq_str("0", simple_itoa(0));
+	ut_asserteq_str("2147483647", simple_itoa(0x7fffffff));
+	ut_asserteq_str("4294967295", simple_itoa(0xffffffff));
+	if (sizeof(ulong) == 8) {
+		ut_asserteq_str("9223372036854775807",
+				simple_itoa((1UL << 63) - 1));
+		ut_asserteq_str("18446744073709551615", simple_itoa(-1));
+	}
+
+	return 0;
+}
+PRINT_TEST(print_itoa, 0);
+
 int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	struct unit_test *tests = UNIT_TEST_SUITE_START(print_test);
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 14/28] lib: Add a function to convert a string to a hex value
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (12 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 13/28] lib: Add tests for simple_itoa() Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 15/28] pxe: Return the file size from the getfile() function Simon Glass
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add an xtoa() function, similar to itoa() but for hex instead.

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

 include/vsprintf.h | 16 ++++++++++++++--
 lib/vsprintf.c     | 20 ++++++++++++++++++--
 test/print_ut.c    | 16 ++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 4479df0af3f..b4746301462 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -177,14 +177,26 @@ int vsprintf(char *buf, const char *fmt, va_list args);
  * simple_itoa() - convert an unsigned integer to a string
  *
  * This returns a static string containing the decimal representation of the
- * given value. The returned value may be overwritten by other calls to the
- * same function, so should be used immediately
+ * given value. The returned value may be overwritten by other calls to other
+ * simple_... functions, so should be used immediately
  *
  * @val: Value to convert
  * @return string containing the decimal representation of @val
  */
 char *simple_itoa(ulong val);
 
+/**
+ * simple_xtoa() - convert an unsigned integer to a hex string
+ *
+ * This returns a static string containing the hexadecimal representation of the
+ * given value. The returned value may be overwritten by other calls to other
+ * simple_... functions, so should be used immediately
+ *
+ * @val: Value to convert
+ * @return string containing the hexecimal representation of @val
+ */
+char *simple_xtoa(ulong num);
+
 /**
  * Format a string and place it in a buffer
  *
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d7ee35b4773..e634bd70b66 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -816,11 +816,12 @@ int vprintf(const char *fmt, va_list args)
 }
 #endif
 
+static char local_toa[22];
+
 char *simple_itoa(ulong i)
 {
 	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
-	static char local[22];
-	char *p = &local[21];
+	char *p = &local_toa[21];
 
 	*p-- = '\0';
 	do {
@@ -830,6 +831,21 @@ char *simple_itoa(ulong i)
 	return p + 1;
 }
 
+char *simple_xtoa(ulong num)
+{
+	/* 16 digits plus nul terminator, good for 64-bit or smaller ints */
+	char *p = &local_toa[17];
+
+	*--p = '\0';
+	do {
+		p -= 2;
+		hex_byte_pack(p, num & 0xff);
+		num >>= 8;
+	} while (num > 0);
+
+	return p;
+}
+
 /* We don't seem to have %'d in U-Boot */
 void print_grouped_ull(unsigned long long int_val, int digits)
 {
diff --git a/test/print_ut.c b/test/print_ut.c
index 737845afd33..13068bc619d 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -345,6 +345,22 @@ static int print_itoa(struct unit_test_state *uts)
 }
 PRINT_TEST(print_itoa, 0);
 
+static int print_xtoa(struct unit_test_state *uts)
+{
+	ut_asserteq_str("7f", simple_xtoa(127));
+	ut_asserteq_str("00", simple_xtoa(0));
+	ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff));
+	ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff));
+	if (sizeof(ulong) == 8) {
+		ut_asserteq_str("7fffffffffffffff",
+				simple_xtoa((1UL << 63) - 1));
+		ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1));
+	}
+
+	return 0;
+}
+PRINT_TEST(print_xtoa, 0);
+
 int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	struct unit_test *tests = UNIT_TEST_SUITE_START(print_test);
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 15/28] pxe: Return the file size from the getfile() function
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (13 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 14/28] lib: Add a function to convert a string to a hex value Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 16/28] pxe: Refactor sysboot to have one helper Simon Glass
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

It is pretty strange that the pxe code uses the 'filesize' environment
variable find the size of a file it has just read.

Partly this is because it uses the command-line interpreter to parse its
request to load the file.

As a first step towards unwinding this, return it directly from the
getfile() function. This makes the code a bit longer, for now, but will be
cleaned up in future patches.

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

 boot/pxe_utils.c    | 70 ++++++++++++++++++++++++++++-----------------
 cmd/pxe.c           |  7 ++++-
 cmd/sysboot.c       | 21 ++++++++++++--
 include/pxe_utils.h | 13 ++++++++-
 4 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index f36f1f8a60c..e377e16be56 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -30,6 +30,20 @@
 
 #define MAX_TFTP_PATH_LEN 512
 
+int pxe_get_file_size(ulong *sizep)
+{
+	const char *val;
+
+	val = from_env("filesize");
+	if (!val)
+		return -ENOENT;
+
+	if (strict_strtoul(val, 16, sizep) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
 /**
  * format_mac_pxe() - obtain a MAC address in the PXE format
  *
@@ -75,14 +89,17 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len)
  * @ctx: PXE context
  * @file_path: File path to read (relative to the PXE file)
  * @file_addr: Address to load file to
+ * @filesizep: If not NULL, returns the file size in bytes
  * Returns 1 for success, or < 0 on error
  */
 static int get_relfile(struct pxe_context *ctx, const char *file_path,
-		       unsigned long file_addr)
+		       unsigned long file_addr, ulong *filesizep)
 {
 	size_t path_len;
 	char relfile[MAX_TFTP_PATH_LEN + 1];
 	char addr_buf[18];
+	ulong size;
+	int ret;
 
 	if (file_path[0] == '/' && ctx->allow_abs_path)
 		*relfile = '\0';
@@ -103,7 +120,13 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
 
 	sprintf(addr_buf, "%lx", file_addr);
 
-	return ctx->getfile(ctx, relfile, addr_buf);
+	ret = ctx->getfile(ctx, relfile, addr_buf, &size);
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+	if (filesizep)
+		*filesizep = size;
+
+	return 1;
 }
 
 /**
@@ -117,29 +140,17 @@ static int get_relfile(struct pxe_context *ctx, const char *file_path,
  * Returns 1 for success, or < 0 on error
  */
 int get_pxe_file(struct pxe_context *ctx, const char *file_path,
-		 unsigned long file_addr)
+		 ulong file_addr)
 {
-	unsigned long config_file_size;
-	char *tftp_filesize;
+	ulong size;
 	int err;
 	char *buf;
 
-	err = get_relfile(ctx, file_path, file_addr);
+	err = get_relfile(ctx, file_path, file_addr, &size);
 	if (err < 0)
 		return err;
 
-	/*
-	 * the file comes without a NUL byte at the end, so find out its size
-	 * and add the NUL byte.
-	 */
-	tftp_filesize = from_env("filesize");
-	if (!tftp_filesize)
-		return -ENOENT;
-
-	if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0)
-		return -EINVAL;
-
-	buf = map_sysmem(file_addr + config_file_size, 1);
+	buf = map_sysmem(file_addr + size, 1);
 	*buf = '\0';
 	unmap_sysmem(buf);
 
@@ -184,12 +195,13 @@ int get_pxelinux_path(struct pxe_context *ctx, const char *file,
  * @file_path: File path to read (relative to the PXE file)
  * @envaddr_name: Name of environment variable which contains the address to
  *	load to
+ * @filesizep: Returns the file size in bytes
  * Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
  *	environment variable, -EINVAL if its format is not valid hex, or other
  *	value < 0 on other error
  */
 static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
-			       const char *envaddr_name)
+			       const char *envaddr_name, ulong *filesizep)
 {
 	unsigned long file_addr;
 	char *envaddr;
@@ -201,7 +213,7 @@ static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
 	if (strict_strtoul(envaddr, 16, &file_addr) < 0)
 		return -EINVAL;
 
-	return get_relfile(ctx, file_path, file_addr);
+	return get_relfile(ctx, file_path, file_addr, filesizep);
 }
 
 /**
@@ -357,8 +369,8 @@ static void label_boot_fdtoverlay(struct pxe_context *ctx,
 			goto skip_overlay;
 
 		/* Load overlay file */
-		err = get_relfile_envaddr(ctx, overlayfile,
-					  "fdtoverlay_addr_r");
+		err = get_relfile_envaddr(ctx, overlayfile, "fdtoverlay_addr_r",
+					  NULL);
 		if (err < 0) {
 			printf("Failed loading overlay %s\n", overlayfile);
 			goto skip_overlay;
@@ -438,7 +450,10 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 	}
 
 	if (label->initrd) {
-		if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
+		ulong size;
+
+		if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
+					&size) < 0) {
 			printf("Skipping %s for failure retrieving initrd\n",
 			       label->name);
 			return 1;
@@ -447,11 +462,12 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 		bootm_argv[2] = initrd_str;
 		strncpy(bootm_argv[2], env_get("ramdisk_addr_r"), 18);
 		strcat(bootm_argv[2], ":");
-		strncat(bootm_argv[2], env_get("filesize"), 9);
+		strcat(bootm_argv[2], simple_xtoa(size));
 		bootm_argc = 3;
 	}
 
-	if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
+	if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
+				NULL) < 0) {
 		printf("Skipping %s for failure retrieving kernel\n",
 		       label->name);
 		return 1;
@@ -592,7 +608,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 
 		if (fdtfile) {
 			int err = get_relfile_envaddr(ctx, fdtfile,
-						      "fdt_addr_r");
+						      "fdt_addr_r", NULL);
 
 			free(fdtfilefree);
 			if (err < 0) {
@@ -1384,7 +1400,7 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
 	if (IS_ENABLED(CONFIG_CMD_BMP)) {
 		/* display BMP if available */
 		if (cfg->bmp) {
-			if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
+			if (get_relfile(ctx, cfg->bmp, image_load_addr, NULL)) {
 				if (CONFIG_IS_ENABLED(CMD_CLS))
 					run_command("cls", 0);
 				bmp_display(image_load_addr,
diff --git a/cmd/pxe.c b/cmd/pxe.c
index e319db51ef5..81703386c42 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -25,15 +25,20 @@ const char *pxe_default_paths[] = {
 };
 
 static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
-		       char *file_addr)
+		       char *file_addr, ulong *sizep)
 {
 	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+	int ret;
 
 	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(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
+	ctx->pxe_file_size = *sizep;
 
 	return 1;
 }
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index c45fed774d6..6344ecd357b 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -9,43 +9,58 @@
 static char *fs_argv[5];
 
 static int do_get_ext2(struct pxe_context *ctx, const char *file_path,
-		       char *file_addr)
+		       char *file_addr, ulong *sizep)
 {
 #ifdef CONFIG_CMD_EXT2
+	int ret;
+
 	fs_argv[0] = "ext2load";
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
 	if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv))
 		return 1;
+	ret = pxe_get_file_size(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
 #endif
 	return -ENOENT;
 }
 
 static int do_get_fat(struct pxe_context *ctx, const char *file_path,
-		      char *file_addr)
+		      char *file_addr, ulong *sizep)
 {
 #ifdef CONFIG_CMD_FAT
+	int ret;
+
 	fs_argv[0] = "fatload";
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
 	if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv))
 		return 1;
+	ret = pxe_get_file_size(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
 #endif
 	return -ENOENT;
 }
 
 static int do_get_any(struct pxe_context *ctx, const char *file_path,
-		      char *file_addr)
+		      char *file_addr, ulong *sizep)
 {
 #ifdef CONFIG_CMD_FS_GENERIC
+	int ret;
+
 	fs_argv[0] = "load";
 	fs_argv[3] = file_addr;
 	fs_argv[4] = (void *)file_path;
 
 	if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
 		return 1;
+	ret = pxe_get_file_size(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
 #endif
 	return -ENOENT;
 }
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 8b50f2e6861..194a5ed8cc7 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -77,7 +77,7 @@ struct pxe_menu {
 
 struct pxe_context;
 typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
-				char *file_addr);
+				char *file_addr, ulong *filesizep);
 
 /**
  * struct pxe_context - context information for PXE parsing
@@ -88,6 +88,7 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
  * @allow_abs_path: true to allow absolute paths
  * @bootdir: Directory that files are loaded from ("" if no directory). This is
  *	allocated
+ * @pxe_file_size: Size of the PXE file
  */
 struct pxe_context {
 	struct cmd_tbl *cmdtp;
@@ -98,6 +99,7 @@ struct pxe_context {
 	 * @file_path: Path to the file
 	 * @file_addr: String containing the hex address to put the file in
 	 *	memory
+	 * @filesizep: Returns the file size in bytes
 	 * Return 0 if OK, -ve on error
 	 */
 	pxe_getfile_func getfile;
@@ -105,6 +107,7 @@ struct pxe_context {
 	void *userdata;
 	bool allow_abs_path;
 	char *bootdir;
+	ulong pxe_file_size;
 };
 
 /**
@@ -225,4 +228,12 @@ void pxe_destroy_ctx(struct pxe_context *ctx);
  */
 int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt);
 
+/**
+ * pxe_get_file_size() - Read the value of the 'filesize' environment variable
+ *
+ * @sizep: Place to put the value
+ * @return 0 if OK, -ENOENT if no such variable, -EINVAL if format is invalid
+ */
+int pxe_get_file_size(ulong *sizep);
+
 #endif /* __PXE_UTILS_H */
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 16/28] pxe: Refactor sysboot to have one helper
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (14 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 15/28] pxe: Return the file size from the getfile() function Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 17/28] doc: Move distro boot doc to rST Simon Glass
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

The only difference between the three helpers is the filesystem type.
Factor this out and call the filesystem functions directly, instead of
through the command-line interpreter. This allows the file size to be
obtained directly, instead of via an environment variable.

We cannot do the same thing with PXE's tftpboot since there is no API
at present to obtain information about the file that was read. So there
is no point in changing pxe_getfile_func to use a ulong for the address,
for example.

This is as far as the refactoring can go for the present.

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

 cmd/sysboot.c | 94 ++++++++++++++++++++-------------------------------
 1 file changed, 36 insertions(+), 58 deletions(-)

diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 6344ecd357b..04c07020269 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -6,63 +6,40 @@
 #include <fs.h>
 #include <pxe_utils.h>
 
-static char *fs_argv[5];
-
-static int do_get_ext2(struct pxe_context *ctx, const char *file_path,
-		       char *file_addr, ulong *sizep)
+/**
+ * struct sysboot_info - useful information for sysboot helpers
+ *
+ * @fstype: Filesystem type (FS_TYPE_...)
+ * @ifname: Interface name (e.g. "ide", "scsi")
+ * @dev_part_str is in the format:
+ *	<dev>.<hw_part>:<part> where <dev> is the device number,
+ *	<hw_part> is the optional hardware partition number and
+ *	<part> is the partition number
+ */
+struct sysboot_info {
+	int fstype;
+	const char *ifname;
+	const char *dev_part_str;
+};
+
+static int sysboot_read_file(struct pxe_context *ctx, const char *file_path,
+			     char *file_addr, ulong *sizep)
 {
-#ifdef CONFIG_CMD_EXT2
+	struct sysboot_info *info = ctx->userdata;
+	loff_t len_read;
+	ulong addr;
 	int ret;
 
-	fs_argv[0] = "ext2load";
-	fs_argv[3] = file_addr;
-	fs_argv[4] = (void *)file_path;
-
-	if (!do_ext2load(ctx->cmdtp, 0, 5, fs_argv))
-		return 1;
-	ret = pxe_get_file_size(sizep);
+	addr = simple_strtoul(file_addr, NULL, 16);
+	ret = fs_set_blk_dev(info->ifname, info->dev_part_str, info->fstype);
 	if (ret)
-		return log_msg_ret("tftp", ret);
-#endif
-	return -ENOENT;
-}
-
-static int do_get_fat(struct pxe_context *ctx, const char *file_path,
-		      char *file_addr, ulong *sizep)
-{
-#ifdef CONFIG_CMD_FAT
-	int ret;
-
-	fs_argv[0] = "fatload";
-	fs_argv[3] = file_addr;
-	fs_argv[4] = (void *)file_path;
-
-	if (!do_fat_fsload(ctx->cmdtp, 0, 5, fs_argv))
-		return 1;
-	ret = pxe_get_file_size(sizep);
+		return ret;
+	ret = fs_read(file_path, addr, 0, 0, &len_read);
 	if (ret)
-		return log_msg_ret("tftp", ret);
-#endif
-	return -ENOENT;
-}
-
-static int do_get_any(struct pxe_context *ctx, const char *file_path,
-		      char *file_addr, ulong *sizep)
-{
-#ifdef CONFIG_CMD_FS_GENERIC
-	int ret;
-
-	fs_argv[0] = "load";
-	fs_argv[3] = file_addr;
-	fs_argv[4] = (void *)file_path;
+		return ret;
+	*sizep = len_read;
 
-	if (!do_load(ctx->cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
-		return 1;
-	ret = pxe_get_file_size(sizep);
-	if (ret)
-		return log_msg_ret("tftp", ret);
-#endif
-	return -ENOENT;
+	return 0;
 }
 
 /*
@@ -74,9 +51,9 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
 	unsigned long pxefile_addr_r;
-	pxe_getfile_func getfile;
 	struct pxe_context ctx;
 	char *pxefile_addr_str;
+	struct sysboot_info info;
 	char *filename;
 	int prompt = 0;
 	int ret;
@@ -106,24 +83,25 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
 	}
 
 	if (strstr(argv[3], "ext2")) {
-		getfile = do_get_ext2;
+		info.fstype = FS_TYPE_EXT;
 	} else if (strstr(argv[3], "fat")) {
-		getfile = do_get_fat;
+		info.fstype = FS_TYPE_FAT;
 	} else if (strstr(argv[3], "any")) {
-		getfile = do_get_any;
+		info.fstype = FS_TYPE_ANY;
 	} else {
 		printf("Invalid filesystem: %s\n", argv[3]);
 		return 1;
 	}
-	fs_argv[1] = argv[1];
-	fs_argv[2] = argv[2];
+	info.ifname = argv[1];
+	info.dev_part_str = argv[2];
 
 	if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
 		printf("Invalid pxefile address: %s\n", pxefile_addr_str);
 		return 1;
 	}
 
-	if (pxe_setup_ctx(&ctx, cmdtp, getfile, NULL, true, filename)) {
+	if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true,
+			  filename)) {
 		printf("Out of memory\n");
 		return CMD_RET_FAILURE;
 	}
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 17/28] doc: Move distro boot doc to rST
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (15 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 16/28] pxe: Refactor sysboot to have one helper Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 18/28] pxe: Allow calling the pxe_get logic directly Simon Glass
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Move this over to the new rST format.

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

 doc/{README.distro => develop/distro.rst} | 177 ++++++++++------------
 doc/develop/index.rst                     |   1 +
 2 files changed, 80 insertions(+), 98 deletions(-)
 rename doc/{README.distro => develop/distro.rst} (76%)

diff --git a/doc/README.distro b/doc/develop/distro.rst
similarity index 76%
rename from doc/README.distro
rename to doc/develop/distro.rst
index c4f041ca712..105dcf28190 100644
--- a/doc/README.distro
+++ b/doc/develop/distro.rst
@@ -1,9 +1,4 @@
-SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2014 Red Hat Inc.
- * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
- * Copyright (C) 2015 K. Merker <merker@debian.org>
- */
+.. SPDX-License-Identifier: GPL-2.0+
 
 Generic Distro Configuration Concept
 ====================================
@@ -73,9 +68,8 @@ Boot Configuration Files
 
 The standard format for boot configuration files is that of extlinux.conf, as
 handled by U-Boot's "syslinux" (disk) or "pxe boot" (network). This is roughly
-as specified at:
+as specified at BootLoaderSpec_:
 
-http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
 
 ... with the exceptions that the BootLoaderSpec document:
 
@@ -87,73 +81,70 @@ http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
 * Does not document the fdtdir option, which automatically selects the DTB to
   pass to the kernel.
 
-One example extlinux.conf generated by the Fedora installer is:
+One example extlinux.conf generated by the Fedora installer is::
 
-------------------------------------------------------------
-# extlinux.conf generated by anaconda
+    # extlinux.conf generated by anaconda
 
-ui menu.c32
+    ui menu.c32
 
-menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options.
-menu title Fedora Boot Options.
-menu hidden
+    menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options.
+    menu title Fedora Boot Options.
+    menu hidden
 
-timeout 50
-#totaltimeout 9000
+    timeout 50
+    #totaltimeout 9000
 
-default Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
+    default Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
 
-label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl) 22 (Rawhide)
-	kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl
-	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
-	fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl
-	initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl.img
+    label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl) 22 (Rawhide)
+        kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl
+        append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
+        fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl
+        initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl.img
 
-label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
-	kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
-	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
-	fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
-	initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae.img
+    label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
+        kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
+        append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
+        fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
+        initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae.img
 
-label Fedora-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc (0-rescue-8f6ba7b039524e0eb957d2c9203f04bc)
-	kernel /boot/vmlinuz-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc
-	initrd /boot/initramfs-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc.img
-	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8
-	fdtdir /boot/dtb-3.16.0-0.rc6.git1.1.fc22.armv7hl+lpae
-------------------------------------------------------------
+    label Fedora-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc (0-rescue-8f6ba7b039524e0eb957d2c9203f04bc)
+        kernel /boot/vmlinuz-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc
+        initrd /boot/initramfs-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc.img
+        append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8
+        fdtdir /boot/dtb-3.16.0-0.rc6.git1.1.fc22.armv7hl+lpae
 
-Another hand-crafted network boot configuration file is:
 
-------------------------------------------------------------
-TIMEOUT 100
+Another hand-crafted network boot configuration file is::
 
-MENU TITLE TFTP boot options
+    TIMEOUT 100
 
-LABEL jetson-tk1-emmc
-        MENU LABEL ../zImage root on Jetson TK1 eMMC
-        LINUX ../zImage
-        FDTDIR ../
-        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=80a5a8e9-c744-491a-93c1-4f4194fd690b
+    MENU TITLE TFTP boot options
 
-LABEL venice2-emmc
-        MENU LABEL ../zImage root on Venice2 eMMC
-        LINUX ../zImage
-        FDTDIR ../
-        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=5f71e06f-be08-48ed-b1ef-ee4800cc860f
+    LABEL jetson-tk1-emmc
+            MENU LABEL ../zImage root on Jetson TK1 eMMC
+            LINUX ../zImage
+            FDTDIR ../
+            APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=80a5a8e9-c744-491a-93c1-4f4194fd690b
 
-LABEL sdcard
-        MENU LABEL ../zImage, root on 2GB sdcard
-        LINUX ../zImage
-        FDTDIR ../
-        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=b2f82cda-2535-4779-b467-094a210fbae7
+    LABEL venice2-emmc
+            MENU LABEL ../zImage root on Venice2 eMMC
+            LINUX ../zImage
+            FDTDIR ../
+            APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=5f71e06f-be08-48ed-b1ef-ee4800cc860f
 
-LABEL fedora-installer-fk
-        MENU LABEL Fedora installer w/ Fedora kernel
-        LINUX fedora-installer/vmlinuz
-        INITRD fedora-installer/initrd.img.orig
-        FDTDIR fedora-installer/dtb
-        APPEND loglevel=8 ip=dhcp inst.repo=http://10.0.0.2/mirrors/fedora/linux/development/rawhide/armhfp/os/ rd.shell cma=64M
-------------------------------------------------------------
+    LABEL sdcard
+            MENU LABEL ../zImage, root on 2GB sdcard
+            LINUX ../zImage
+            FDTDIR ../
+            APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=b2f82cda-2535-4779-b467-094a210fbae7
+
+    LABEL fedora-installer-fk
+            MENU LABEL Fedora installer w/ Fedora kernel
+            LINUX fedora-installer/vmlinuz
+            INITRD fedora-installer/initrd.img.orig
+            FDTDIR fedora-installer/dtb
+            APPEND loglevel=8 ip=dhcp inst.repo=http://10.0.0.2/mirrors/fedora/linux/development/rawhide/armhfp/os/ rd.shell cma=64M
 
 U-Boot Implementation
 =====================
@@ -166,13 +157,11 @@ 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.
 
-In your board configuration file, include the following:
+In your board configuration file, include the following::
 
-------------------------------------------------------------
-#ifndef CONFIG_SPL_BUILD
-#include <config_distro_bootcmd.h>
-#endif
-------------------------------------------------------------
+    #ifndef CONFIG_SPL_BUILD
+    #include <config_distro_bootcmd.h>
+    #endif
 
 The first of those headers primarily enables a core set of U-Boot features,
 such as support for MBR and GPT partitions, ext* and FAT filesystems, booting
@@ -205,7 +194,6 @@ CONFIG_EXTRA_ENV_SETTINGS in the board's U-Boot configuration file, so that
 the user doesn't have to configure them.
 
 fdt_addr:
-
   Mandatory for any system that provides the DTB in HW (e.g. ROM) and wishes
   to pass that DTB to Linux, rather than loading a DTB from the boot
   filesystem. Prohibited for any other system.
@@ -214,7 +202,6 @@ fdt_addr:
   address.
 
 fdt_addr_r:
-
   Mandatory. The location in RAM where the DTB will be loaded or copied to when
   processing the fdtdir/devicetreedir or fdt/devicetree options in
   extlinux.conf.
@@ -225,7 +212,6 @@ fdt_addr_r:
   A size of 1MB for the FDT/DTB seems reasonable.
 
 fdtfile:
-
   Mandatory. the name of the DTB file for the specific board for instance
   the espressobin v5 board the value is "marvell/armada-3720-espressobin.dtb"
   while on a clearfog pro it is "armada-388-clearfog-pro.dtb" in the case of
@@ -236,16 +222,14 @@ fdtfile:
   SoC vendor directories. 
 
 ramdisk_addr_r:
-
   Mandatory. The location in RAM where the initial ramdisk will be loaded to
   when processing the initrd option in extlinux.conf.
 
-  It is recommended that this location be highest in RAM out of fdt_addr_,
+  It is recommended that this location be highest in RAM out of fdt_addr_r,
   kernel_addr_r, and ramdisk_addr_r, so that the RAM disk can vary in size
   and use any available RAM.
 
 kernel_addr_r:
-
   Mandatory. The location in RAM where the kernel will be loaded to when
   processing the kernel option in the extlinux.conf.
 
@@ -270,14 +254,12 @@ kernel_comp_size:
   size has to at least the size of loaded image for decompression to succeed.
 
 pxefile_addr_r:
-
   Mandatory. The location in RAM where extlinux.conf will be loaded to prior
   to processing.
 
   A size of 1MB for extlinux.conf is more than adequate.
 
 scriptaddr:
-
   Mandatory, if the boot script is boot.scr rather than extlinux.conf. The
   location in RAM where boot.scr will be loaded to prior to execution.
 
@@ -292,24 +274,22 @@ MEM_LAYOUT_ENV_SETTINGS in include/configs/tegra124-common.h.
 Boot Target Configuration
 -------------------------
 
-<config_distro_bootcmd.h> defines $bootcmd and many helper command variables
-that automatically search attached disks for boot configuration files and
-execute them. Boards must provide configure <config_distro_bootcmd.h> so that
-it supports the correct set of possible boot device types. To provide this
+The `config_distro_bootcmd.h` file defines $bootcmd and many helper command
+variables that automatically search attached disks for boot configuration files
+and execute them. Boards must provide configure <config_distro_bootcmd.h> so
+that it supports the correct set of possible boot device types. To provide this
 configuration, simply define macro BOOT_TARGET_DEVICES prior to including
-<config_distro_bootcmd.h>. For example:
-
-------------------------------------------------------------
-#ifndef CONFIG_SPL_BUILD
-#define BOOT_TARGET_DEVICES(func) \
-        func(MMC, mmc, 1) \
-        func(MMC, mmc, 0) \
-        func(USB, usb, 0) \
-        func(PXE, pxe, na) \
-        func(DHCP, dhcp, na)
-#include <config_distro_bootcmd.h>
-#endif
-------------------------------------------------------------
+<config_distro_bootcmd.h>. For example::
+
+    #ifndef CONFIG_SPL_BUILD
+    #define BOOT_TARGET_DEVICES(func) \
+            func(MMC, mmc, 1) \
+            func(MMC, mmc, 0) \
+            func(USB, usb, 0) \
+            func(PXE, pxe, na) \
+            func(DHCP, dhcp, na)
+    #include <config_distro_bootcmd.h>
+    #endif
 
 Each entry in the macro defines a single boot device (e.g. a specific eMMC
 device or SD card) or type of boot device (e.g. USB disk). The parameters to
@@ -328,7 +308,6 @@ up by <config_distro_bootcmd.h>. After this, various environment variables may
 be altered to influence the boot process:
 
 boot_targets:
-
   The list of boot locations searched.
 
   Example: mmc0, mmc1, usb, pxe
@@ -336,7 +315,6 @@ boot_targets:
   Entries may be removed or re-ordered in this list to affect the boot order.
 
 boot_prefixes:
-
   For disk-based booting, the list of directories within a partition that are
   searched for boot configuration files (extlinux.conf, boot.scr).
 
@@ -346,7 +324,6 @@ boot_prefixes:
   directories which are searched.
 
 boot_scripts:
-
   The name of U-Boot style boot.scr files that $bootcmd searches for.
 
   Example: boot.scr.uimg boot.scr
@@ -358,17 +335,14 @@ boot_scripts:
   filenames which are supported.
 
 scan_dev_for_extlinux:
-
   If you want to disable extlinux.conf on all disks, set the value to something
   innocuous, e.g. setenv scan_dev_for_extlinux true.
 
 scan_dev_for_scripts:
-
   If you want to disable boot.scr on all disks, set the value to something
   innocuous, e.g. setenv scan_dev_for_scripts true.
 
 boot_net_usb_start:
-
   If you want to prevent USB enumeration by distro boot commands which execute
   network operations, set the value to something innocuous, e.g. setenv
   boot_net_usb_start true. This would be useful if you know your Ethernet
@@ -376,7 +350,6 @@ boot_net_usb_start:
   avoiding unnecessary actions.
 
 boot_net_pci_enum:
-
   If you want to prevent PCI enumeration by distro boot commands which execute
   network operations, set the value to something innocuous, e.g. setenv
   boot_net_pci_enum true. This would be useful if you know your Ethernet
@@ -412,10 +385,12 @@ Examples:
 The list of possible targets consists of:
 
 - network targets
+
   * dhcp
   * pxe
 
 - storage targets (to which a device number must be appended)
+
   * mmc
   * sata
   * scsi
@@ -428,3 +403,9 @@ of the boot environment and are not guaranteed to exist or work in the same
 way in future u-boot versions.  In particular the <device type>_boot
 variables (e.g. mmc_boot, usb_boot) are a strictly internal implementation
 detail and must not be used as a public interface.
+
+.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
+
+.. sectionauthor:: (C) Copyright 2014 Red Hat Inc.
+.. sectionauthor:: Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
+.. sectionauthor:: Copyright (C) 2015 K. Merker <merker@debian.org>
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index 83c929babda..1fb0f06f6e8 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -12,6 +12,7 @@ Implementation
    ci_testing
    commands
    devicetree/index
+   distro
    driver-model/index
    global_data
    logging
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 18/28] pxe: Allow calling the pxe_get logic directly
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (16 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 17/28] doc: Move distro boot doc to rST Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 19/28] bootmethod: Add the uclass and core implementation Simon Glass
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Refactor this code so that we can call the 'pxe get' command without going
through the command-line interpreter. This makes it easier to get the
information we need, without going through environment variables.

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

 cmd/pxe.c           | 92 +++++++++++++++++++++++++++++----------------
 include/pxe_utils.h | 14 +++++++
 2 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/cmd/pxe.c b/cmd/pxe.c
index 81703386c42..db8e4697f24 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -104,6 +104,49 @@ static int pxe_ipaddr_paths(struct pxe_context *ctx, unsigned long pxefile_addr_
 
 	return -ENOENT;
 }
+
+int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep)
+{
+	struct cmd_tbl cmdtp[] = {};	/* dummy */
+	struct pxe_context ctx;
+	int i;
+
+	if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
+			  env_get("bootfile")))
+		return -ENOMEM;
+	/*
+	 * Keep trying paths until we successfully get a file we're looking
+	 * for.
+	 */
+	if (pxe_uuid_path(&ctx, pxefile_addr_r) > 0 ||
+	    pxe_mac_path(&ctx, pxefile_addr_r) > 0 ||
+	    pxe_ipaddr_paths(&ctx, pxefile_addr_r) > 0)
+		goto done;
+
+	i = 0;
+	while (pxe_default_paths[i]) {
+		if (get_pxelinux_path(&ctx, pxe_default_paths[i],
+				      pxefile_addr_r) > 0)
+			goto done;
+		i++;
+	}
+
+	pxe_destroy_ctx(&ctx);
+
+	return -ENOENT;
+done:
+	*bootdirp = env_get("bootfile");
+
+	/*
+	 * The PXE file size is returned but not the name. It is probably not
+	 * that useful.
+	 */
+	*sizep = ctx.pxe_file_size;
+	pxe_destroy_ctx(&ctx);
+
+	return 0;
+}
+
 /*
  * Entry point for the 'pxe get' command.
  * This Follows pxelinux's rules to download a config file from a tftp server.
@@ -122,9 +165,10 @@ static int
 do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	char *pxefile_addr_str;
-	unsigned long pxefile_addr_r;
-	struct pxe_context ctx;
-	int err, i = 0;
+	ulong pxefile_addr_r;
+	char *fname;
+	ulong size;
+	int ret;
 
 	if (argc != 1)
 		return CMD_RET_USAGE;
@@ -134,43 +178,25 @@ do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	if (!pxefile_addr_str)
 		return 1;
 
-	err = strict_strtoul(pxefile_addr_str, 16,
+	ret = strict_strtoul(pxefile_addr_str, 16,
 			     (unsigned long *)&pxefile_addr_r);
-	if (err < 0)
+	if (ret < 0)
 		return 1;
 
-	if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
-			  env_get("bootfile"))) {
+	ret = pxe_get(pxefile_addr_r, &fname, &size);
+	switch (ret) {
+	case 0:
+		printf("Config file '%s' found\n", fname);
+		break;
+	case -ENOMEM:
 		printf("Out of memory\n");
 		return CMD_RET_FAILURE;
+	default:
+		printf("Config file not found\n");
+		return CMD_RET_FAILURE;
 	}
-	/*
-	 * Keep trying paths until we successfully get a file we're looking
-	 * for.
-	 */
-	if (pxe_uuid_path(&ctx, pxefile_addr_r) > 0 ||
-	    pxe_mac_path(&ctx, pxefile_addr_r) > 0 ||
-	    pxe_ipaddr_paths(&ctx, pxefile_addr_r) > 0) {
-		printf("Config file found\n");
-		pxe_destroy_ctx(&ctx);
-
-		return 0;
-	}
-
-	while (pxe_default_paths[i]) {
-		if (get_pxelinux_path(&ctx, pxe_default_paths[i],
-				      pxefile_addr_r) > 0) {
-			printf("Config file found\n");
-			pxe_destroy_ctx(&ctx);
-			return 0;
-		}
-		i++;
-	}
-
-	printf("Config file not found\n");
-	pxe_destroy_ctx(&ctx);
 
-	return 1;
+	return 0;
 }
 
 /*
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 194a5ed8cc7..b7037f841a6 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -236,4 +236,18 @@ int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt);
  */
 int pxe_get_file_size(ulong *sizep);
 
+/**
+ * pxe_get() - Get the PXE file from the server
+ *
+ * This tries various filenames to obtain a PXE file
+ *
+ * @pxefile_addr_r: Address to put file
+ * @bootdirp: Returns the boot filename, or NULL if none. This is the 'bootfile'
+ *	option provided by the DHCP server. If none, returns NULL. For example,
+ *	"rpi/info", which indicates that all files should be fetched from the
+ *	"rpi/" subdirectory
+ * @sizep: Size of the PXE file (not bootfile)
+ */
+int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep);
+
 #endif /* __PXE_UTILS_H */
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 19/28] bootmethod: Add the uclass and core implementation
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (17 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 18/28] pxe: Allow calling the pxe_get logic directly Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 20/28] bootmethod: Add an implementation of distro boot Simon Glass
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add a uclass for bootmethod and the various helpers needed to make it
work.

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

 MAINTAINERS            |   6 +
 boot/Kconfig           |   9 +
 boot/Makefile          |   1 +
 boot/bootmethod.c      | 445 +++++++++++++++++++++++++++++++++++++++++
 include/bootmethod.h   | 355 ++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h |   1 +
 6 files changed, 817 insertions(+)
 create mode 100644 boot/bootmethod.c
 create mode 100644 include/bootmethod.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 776ff703b9b..d977cee562b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -630,6 +630,12 @@ M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	tools/binman/
 
+BOOTMETHOD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	boot/bootmethod.c
+F:	include/bootmethod.h
+
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
 R:	Qu Wenruo <wqu@suse.com>
diff --git a/boot/Kconfig b/boot/Kconfig
index 0d4c38402c1..90f716c3ef1 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -290,6 +290,15 @@ endif # SPL
 
 endif # FIT
 
+config BOOTMETHOD
+	bool "Bootmethod support"
+	default y
+	help
+	  A bootmethod is a standard way of locating something to boot,
+	  typically an Operating System such as Linux. Enable this to support
+	  iterating through available bootmethods to find a bootflow suitable
+	  for booting.
+
 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 e8f984248e6..10d427e115c 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -22,6 +22,7 @@ endif
 obj-y += image.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += bootmethod.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/bootmethod.c b/boot/bootmethod.c
new file mode 100644
index 00000000000..8e4157c6a47
--- /dev/null
+++ b/boot/bootmethod.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <bootmethod.h>
+#include <dm.h>
+#include <fs.h>
+#include <log.h>
+#include <malloc.h>
+#include <part.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+
+enum {
+	/*
+	 * Set some sort of limit on the number of bootflows a bootmethod can
+	 * return. Note that for disks this limits the partitions numbers that
+	 * are scanned to 1..MAX_BOOTFLOWS_PER_BOOTMETHOD
+	 */
+	MAX_BOOTFLOWS_PER_BOOTMETHOD	= 20,
+};
+
+static const char *const bootmethod_state[BOOTFLOWST_COUNT] = {
+	"base",
+	"media",
+	"part",
+	"fs",
+	"file",
+	"loaded",
+};
+
+static const char *const bootmethod_type[BOOTFLOWT_COUNT] = {
+};
+
+int bootmethod_get_state(struct bootflow_state **statep)
+{
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_BOOTMETHOD, &uc);
+	if (ret)
+		return ret;
+	*statep = uclass_get_priv(uc);
+
+	return 0;
+}
+
+const char *bootmethod_state_get_name(enum bootflow_state_t state)
+{
+	if (state < 0 || state >= BOOTFLOWST_COUNT)
+		return "?";
+
+	return bootmethod_state[state];
+}
+
+const char *bootmethod_type_get_name(enum bootflow_type_t type)
+{
+	if (type < 0 || type >= BOOTFLOWT_COUNT)
+		return "?";
+
+	return bootmethod_type[type];
+}
+
+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);
+}
+
+void bootmethod_clear_bootflows(struct udevice *dev)
+{
+	struct bootmethod_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);
+		bootflow_remove(bflow);
+	}
+}
+
+void bootmethod_clear_glob(void)
+{
+	struct bootflow_state *state;
+
+	if (bootmethod_get_state(&state))
+		return;
+
+	while (!list_empty(&state->glob_head)) {
+		struct bootflow *bflow;
+
+		bflow = list_first_entry(&state->glob_head, struct bootflow,
+					 glob_node);
+		bootflow_remove(bflow);
+	}
+}
+
+int bootmethod_add_bootflow(struct bootflow *bflow)
+{
+	struct bootmethod_uc_plat *ucp = dev_get_uclass_plat(bflow->dev);
+	struct bootflow_state *state;
+	struct bootflow *new;
+	int ret;
+
+	assert(bflow->dev);
+	ret = bootmethod_get_state(&state);
+	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, &state->glob_head);
+	list_add_tail(&new->bm_node, &ucp->bootflow_head);
+
+	return 0;
+}
+
+int bootmethod_first_bootflow(struct udevice *dev, struct bootflow **bflowp)
+{
+	struct bootmethod_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 bootmethod_next_bootflow(struct bootflow **bflowp)
+{
+	struct bootflow *bflow = *bflowp;
+	struct bootmethod_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 bootflow_first_glob(struct bootflow **bflowp)
+{
+	struct bootflow_state *state;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return ret;
+
+	if (list_empty(&state->glob_head))
+		return -ENOENT;
+
+	*bflowp = list_first_entry(&state->glob_head, struct bootflow,
+				   glob_node);
+
+	return 0;
+}
+
+int bootflow_next_glob(struct bootflow **bflowp)
+{
+	struct bootflow_state *state;
+	struct bootflow *bflow = *bflowp;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return ret;
+
+	*bflowp = NULL;
+
+	if (list_is_last(&bflow->glob_node, &state->glob_head))
+		return -ENOENT;
+
+	*bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node);
+
+	return 0;
+}
+
+int bootmethod_get_bootflow(struct udevice *dev, int seq,
+			    struct bootflow *bflow)
+{
+	const struct bootmethod_ops *ops = bootmethod_get_ops(dev);
+
+	if (!ops->get_bootflow)
+		return -ENOSYS;
+	memset(bflow, '\0', sizeof(*bflow));
+	bflow->dev = dev;
+	bflow->seq = seq;
+
+	return ops->get_bootflow(dev, seq, bflow);
+}
+
+static int next_bootflow(struct udevice *dev, int seq, struct bootflow *bflow)
+{
+	int ret;
+
+	ret = bootmethod_get_bootflow(dev, seq, bflow);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void bootmethod_iter_set_dev(struct bootmethod_iter *iter,
+				    struct udevice *dev)
+{
+	iter->dev = dev;
+	if (iter->flags & BOOTFLOWF_SHOW) {
+		if (dev)
+			printf("Scanning bootmethod '%s':\n", dev->name);
+		else
+			printf("No more bootmethods\n");
+	}
+}
+
+int bootmethod_scan_first_bootflow(struct bootmethod_iter *iter, int flags,
+				   struct bootflow *bflow)
+{
+	struct udevice *dev;
+	int ret;
+
+	iter->flags = flags;
+	iter->seq = 0;
+	ret = uclass_first_device_err(UCLASS_BOOTMETHOD, &dev);
+	if (ret)
+		return ret;
+	bootmethod_iter_set_dev(iter, dev);
+
+	ret = bootmethod_scan_next_bootflow(iter, bflow);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int bootmethod_scan_next_bootflow(struct bootmethod_iter *iter,
+				  struct bootflow *bflow)
+{
+	struct udevice *dev;
+	int ret;
+
+	do {
+		dev = iter->dev;
+		ret = next_bootflow(dev, iter->seq, bflow);
+
+		/* If we got a valid bootflow, return it */
+		if (!ret) {
+			log_debug("Bootmethod '%s' seq %d: Found bootflow\n",
+				  dev->name, iter->seq);
+			iter->seq++;
+			return 0;
+		}
+
+		/*
+		 * Unless there are no more partitions or no bootflow support,
+		 * try the next partition
+		 */
+		else if (ret != -ESHUTDOWN && ret != -ENOSYS) {
+			log_debug("Bootmethod '%s' seq %d: Error %d\n",
+				  dev->name, iter->seq, ret);
+			if ((iter->seq++ != MAX_BOOTFLOWS_PER_BOOTMETHOD) &&
+			    (iter->flags & BOOTFLOWF_ALL))
+				return log_msg_ret("all", ret);
+		}
+
+		/* we got to the end of that bootmethod, try the next */
+		ret = uclass_next_device_err(&dev);
+		bootmethod_iter_set_dev(iter, dev);
+
+		/* if there are no more bootmethods, give up */
+		if (ret)
+			return ret;
+
+		/* start at the beginning of this bootmethod */
+		iter->seq = 0;
+	} while (1);
+}
+
+int bootmethod_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;
+	*devp = dev;
+
+	return 0;
+}
+
+int bootmethod_find_in_blk(struct udevice *dev, struct udevice *blk, int seq,
+			   struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(blk);
+	struct disk_partition info;
+	char name[60];
+	int partnum = seq + 1;
+	int ret;
+
+	if (seq >= MAX_BOOTFLOWS_PER_BOOTMETHOD)
+		return -ESHUTDOWN;
+
+	bflow->blk = blk;
+	bflow->seq = seq;
+	snprintf(name, sizeof(name), "%s.part_%x", dev->name, partnum);
+	bflow->name = strdup(name);
+	if (!bflow->name)
+		return log_msg_ret("name", -ENOMEM);
+
+	bflow->state = BOOTFLOWST_BASE;
+	ret = part_get_info(desc, partnum, &info);
+
+	/* This error indicates the media is not present */
+	if (ret != -EOPNOTSUPP)
+		bflow->state = BOOTFLOWST_MEDIA;
+	if (ret)
+		return log_msg_ret("part", ret);
+
+	bflow->state = BOOTFLOWST_PART;
+	bflow->part = partnum;
+	ret = fs_set_blk_dev_with_part(desc, partnum);
+#ifdef CONFIG_DOS_PARTITION
+	log_debug("%s: Found partition %x type %x fstype %d\n", blk->name,
+		  partnum, info.sys_ind, ret ? -1 : fs_get_type());
+#endif
+	if (ret)
+		return log_msg_ret("fs", ret);
+
+	bflow->state = BOOTFLOWST_FS;
+
+	return 0;
+}
+
+int bootflow_boot(struct bootflow *bflow)
+{
+	bool done = false;
+	int ret;
+
+	if (bflow->state != BOOTFLOWST_LOADED)
+		return log_msg_ret("load", -EPROTO);
+
+	switch (bflow->type) {
+	case BOOTFLOWT_COUNT:
+		break;
+	}
+
+	if (!done)
+		return log_msg_ret("type", -ENOSYS);
+
+	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 bootmethod_setup_for_dev(struct udevice *parent, const char *drv_name)
+{
+	struct udevice *bm;
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(BOOTMETHOD))
+		return 0;
+
+	ret = device_find_first_child_by_uclass(parent, UCLASS_BOOTMETHOD,
+						&bm);
+	if (ret) {
+		if (ret != -ENODEV) {
+			log_debug("Cannot access bootmethod device\n");
+			return ret;
+		}
+
+		ret = bootmethod_bind(parent, drv_name, "bootmethod", &bm);
+		if (ret) {
+			log_debug("Cannot create bootmethod device\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int bootmethod_init(struct uclass *uc)
+{
+	struct bootflow_state *state = uclass_get_priv(uc);
+
+	INIT_LIST_HEAD(&state->glob_head);
+
+	return 0;
+}
+
+static int bootmethod_post_bind(struct udevice *dev)
+{
+	struct bootmethod_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+	INIT_LIST_HEAD(&ucp->bootflow_head);
+
+	return 0;
+}
+
+UCLASS_DRIVER(bootmethod) = {
+	.id		= UCLASS_BOOTMETHOD,
+	.name		= "bootmethod",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.priv_auto	= sizeof(struct bootflow_state),
+	.per_device_plat_auto	= sizeof(struct bootmethod_uc_plat),
+	.init		= bootmethod_init,
+	.post_bind	= bootmethod_post_bind,
+};
diff --git a/include/bootmethod.h b/include/bootmethod.h
new file mode 100644
index 00000000000..a45897b0c0c
--- /dev/null
+++ b/include/bootmethod.h
@@ -0,0 +1,355 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __bootmethod_h
+#define __bootmethod_h
+
+#include <linux/list.h>
+
+/**
+ * enum bootflow_state_t - states that a particular bootflow can be in
+ */
+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_LOADED,	/**< Bootflow file loaded */
+
+	BOOTFLOWST_COUNT
+};
+
+enum bootflow_type_t {
+	BOOTFLOWT_COUNT,
+};
+
+/**
+ * struct bootflow_state - information about available bootflows, etc.
+ *
+ * This is attached to the bootmethod uclass so there is only one of them. It
+ * provides overall information about bootmethods and bootflows.
+ *
+ * @cur_bootmethod: Currently selected bootmethod (for commands)
+ * @cur_bootflow: Currently selected bootflow (for commands)
+ * @glob_head: Head for the global list of all bootmethods across all bootflows
+ */
+struct bootflow_state {
+	struct udevice *cur_bootmethod;
+	struct bootflow *cur_bootflow;
+	struct list_head glob_head;
+};
+
+/**
+ * struct bootmethod_uc_plat - uclass information about a bootmethod
+ *
+ * This is attached to each device in the bootmethod uclass and accessible via
+ * dev_get_uclass_plat(dev)
+ *
+ * @bootflows: List of available bootflows for this bootmethod
+ */
+struct bootmethod_uc_plat {
+	struct list_head bootflow_head;
+};
+
+extern struct bootflow_cmds g_bootflow_cmds;
+
+/**
+ * struct bootflow - information about a bootflow
+ *
+ * This is connected into two separate linked lists:
+ *
+ *   bm_sibling - links all bootflows in the same bootmethod
+ *   glob_sibling - links all bootflows in all bootmethods
+ *
+ * @bm_node: Points to siblings in the same bootmethod
+ * @glob_node: Points to siblings in the global list (all bootmethod)
+ * @dev: Bootmethod device which produced this bootflow
+ * @blk: Block device which contains this bootflow, NULL if this is a network
+ *	device
+ * @seq: Sequence number of bootflow within its bootmethod, typically the
+ *	partition number (0...)
+ * @name: Name of bootflow (allocated)
+ * @type: Bootflow type (enum bootflow_type_t)
+ * @state: Current state (enum bootflow_state_t)
+ * @part: Partition number
+ * @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 seq;
+	char *name;
+	enum bootflow_type_t type;
+	enum bootflow_state_t state;
+	int part;
+	char *subdir;
+	char *fname;
+	char *buf;
+	int size;
+	int err;
+};
+
+/**
+ * enum bootflow_flags_t - flags for the bootflow
+ *
+ * @BOOTFLOWF_FIXED: Only used fixed/internal media
+ * @BOOTFLOWF_SHOW: Show each bootmethod before scanning it
+ * @BOOTFLOWF_ALL: Return bootflows with errors as well
+ */
+enum bootflow_flags_t {
+	BOOTFLOWF_FIXED		= 1 << 0,
+	BOOTFLOWF_SHOW		= 1 << 1,
+	BOOTFLOWF_ALL		= 1 << 2,
+};
+
+/**
+ * struct bootmethod_iter - state for iterating through bootflows
+ *
+ * @flags: Flags to use (see enum bootflow_flags_t)
+ * @dev: Current bootmethod
+ * @seq: Current sequence number within that bootmethod (determines partition
+ *	number, for example)
+ */
+struct bootmethod_iter {
+	int flags;
+	struct udevice *dev;
+	int seq;
+};
+
+/**
+ * struct bootmethod_ops - Operations for the Platform Controller Hub
+ *
+ * Consider using ioctl() to add rarely used or driver-specific operations.
+ */
+struct bootmethod_ops {
+	/**
+	 * get_bootflow() - get a bootflow
+	 *
+	 * @dev:	Bootflow device to check
+	 * @seq:	Sequence number of bootflow to read (0 for first)
+	 * @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 (*get_bootflow)(struct udevice *dev, int seq,
+			    struct bootflow *bflow);
+};
+
+#define bootmethod_get_ops(dev)  ((struct bootmethod_ops *)(dev)->driver->ops)
+
+/**
+ * bootmethod_get_bootflow() - get a bootflow
+ *
+ * @dev:	Bootflow device to check
+ * @seq:	Sequence number of bootflow to read (0 for first)
+ * @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 bootmethod_get_bootflow(struct udevice *dev, int seq,
+			    struct bootflow *bflow);
+
+/**
+ * bootmethod_scan_first_bootflow() - find the first bootflow
+ *
+ * This works through the available bootmethod 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)
+ * @flags:	Flags for bootmethod (enum bootflow_flags_t)
+ * @bflow:	Place to put the bootflow if found
+ * @return 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
+ */
+int bootmethod_scan_first_bootflow(struct bootmethod_iter *iter, int flags,
+				   struct bootflow *bflow);
+
+/**
+ * bootmethod_scan_next_bootflow() - find the next bootflow
+ *
+ * This works through the available bootmethod devices until it finds one that
+ * can supply a bootflow. It then returns that bootflow
+ *
+ * @iter:	Private info (as set up by bootmethod_scan_first_bootflow())
+ * @bflow:	Place to put the bootflow if found
+ * @return 0 if found, -ESHUTDOWN if no more bootflows, -ve on error
+ */
+int bootmethod_scan_next_bootflow(struct bootmethod_iter *iter,
+				  struct bootflow *bflow);
+
+/**
+ * bootmethod_bind() - Bind a new named bootmethod device
+ *
+ * @parent:	Parent of the new device
+ * @drv_name:	Driver name to use for the bootmethod device
+ * @name:	Name for the device (parent name is prepended)
+ * @devp:	the new device (which has not been probed)
+ */
+int bootmethod_bind(struct udevice *parent, const char *drv_name,
+		    const char *name, struct udevice **devp);
+
+/**
+ * bootmethod_find_in_blk() - Find a bootmethod in a block device
+ *
+ * @dev: Bootflow device associated with this block device
+ * @blk: Block device to search
+ * @seq: Sequence number within block device, used as the partition number,
+ *	after adding 1
+ * @bflow:	Returns bootflow if found
+ * @return 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
+ */
+int bootmethod_find_in_blk(struct udevice *dev, struct udevice *blk, int seq,
+			   struct bootflow *bflow);
+
+/**
+ * bootmethod_list() - List all available bootmethods
+ *
+ * @probe: true to probe devices, false to leave them as is
+ */
+void bootmethod_list(bool probe);
+
+/**
+ * bootmethod_state_get_name() - Get the name of a bootflow state
+ *
+ * @state: State to check
+ * @return name, or "?" if invalid
+ */
+const char *bootmethod_state_get_name(enum bootflow_state_t state);
+
+/**
+ * bootmethod_type_get_name() - Get the name of a bootflow state
+ *
+ * @type: Type to check
+ * @return name, or "?" if invalid
+ */
+const char *bootmethod_type_get_name(enum bootflow_type_t type);
+
+/**
+ * bootmethod_get_state() - Get the (single) state for the bootmethod 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 bootmethod_get_state(struct bootflow_state **statep);
+
+/**
+ * bootmethod_clear_bootflows() - Clear bootflows from a bootmethod
+ *
+ * Each bootmethod maintains a list of discovered bootflows. This provides a
+ * way to clear it. These bootflows are removed from the global list too.
+ *
+ * @dev: bootmethod device to update
+ */
+void bootmethod_clear_bootflows(struct udevice *dev);
+
+/**
+ * bootmethod_clear_glob() - Clear the global list of bootflows
+ *
+ * This removes all bootflows globally and across all bootmethods.
+ */
+void bootmethod_clear_glob(void);
+
+/**
+ * bootmethod_add_bootflow() - Add a bootflow to the bootmethod's list
+ *
+ * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
+ * bootflow to that device.
+ *
+ * @dev: Bootmethod 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 bootmethod_add_bootflow(struct bootflow *bflow);
+
+/**
+ * bootmethod_first_bootflow() - Get the first bootflow from a bootmethod
+ *
+ * Returns the first bootflow attached to a bootmethod
+ *
+ * @dev: bootmethod device
+ * @bflowp: Returns a pointer to the bootflow
+ * @return 0 if found, -ENOENT if there are no bootflows
+ */
+int bootmethod_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
+
+/**
+ * bootmethod_next_bootflow() - Get the next bootflow from a bootmethod
+ *
+ * Returns the next bootflow attached to a bootmethod
+ *
+ * @bflowp: On entry, the last bootflow returned , e.g. from
+ *	bootmethod_first_bootflow()
+ * @return 0 if found, -ENOENT if there are no more bootflows
+ */
+int bootmethod_next_bootflow(struct bootflow **bflowp);
+
+/**
+ * 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
+ */
+int bootflow_boot(struct bootflow *bflow);
+
+/**
+ * bootmethod_setup_for_dev() - Bind a new bootmethod device
+ *
+ * Creates a bootmethod device as a child of @parent. This should be called from
+ * the driver's bind() method or its uclass' post_bind() method.
+ *
+ * @parent: Parent device (e.g. MMC or Ethernet)
+ * @drv_name: Name of bootmethod driver to bind
+ * @return 0 if OK, -ve on error
+ */
+int bootmethod_setup_for_dev(struct udevice *parent, const char *drv_name);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index e7edd409f30..116d2f02f26 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_BOOTMETHOD,	/* Bootmethod for locating an OS to boot*/
 	UCLASS_BUTTON,		/* Button */
 	UCLASS_CACHE,		/* Cache controller */
 	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 20/28] bootmethod: Add an implementation of distro boot
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (18 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 19/28] bootmethod: Add the uclass and core implementation Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 21/28] bootmethod: Add a command Simon Glass
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add a bootmethod type which handles distro boot, so we can boot a bootflow
using this commonly used mechanism.

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

For now this requires the 'pxe' command be enabled.

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

 MAINTAINERS          |   2 +
 boot/Kconfig         |  11 +++
 boot/Makefile        |   1 +
 boot/bootmethod.c    |  14 ++++
 boot/distro.c        | 194 +++++++++++++++++++++++++++++++++++++++++++
 include/bootmethod.h |   2 +
 include/distro.h     |  62 ++++++++++++++
 7 files changed, 286 insertions(+)
 create mode 100644 boot/distro.c
 create mode 100644 include/distro.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d977cee562b..f78141c138b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -634,7 +634,9 @@ BOOTMETHOD
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	boot/bootmethod.c
+F:	boot/distro.c
 F:	include/bootmethod.h
+F:	include/distro.h
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/boot/Kconfig b/boot/Kconfig
index 90f716c3ef1..8565fbeab84 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -299,6 +299,17 @@ config BOOTMETHOD
 	  iterating through available bootmethods to find a bootflow suitable
 	  for booting.
 
+config BOOTMETHOD_DISTRO
+	bool "Bootmethod support for distro boot"
+	depends on BOOTMETHOD && CMD_PXE
+	default y
+	help
+	  Enables support for distro boot using bootmethods. This makes the
+	  bootmethods look for a 'extlinux/extlinux.conf' on each filesystem
+	  they scan.
+
+	  This provides a way to try out bootmethod on an existing boot flow.
+
 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 10d427e115c..4ce721242b0 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -23,6 +23,7 @@ obj-y += image.o
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += bootmethod.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD_DISTRO) += 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/bootmethod.c b/boot/bootmethod.c
index 8e4157c6a47..be9d4aa02cc 100644
--- a/boot/bootmethod.c
+++ b/boot/bootmethod.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <blk.h>
 #include <bootmethod.h>
+#include <distro.h>
 #include <dm.h>
 #include <fs.h>
 #include <log.h>
@@ -34,6 +35,7 @@ static const char *const bootmethod_state[BOOTFLOWST_COUNT] = {
 };
 
 static const char *const bootmethod_type[BOOTFLOWT_COUNT] = {
+	"distro-boot",
 };
 
 int bootmethod_get_state(struct bootflow_state **statep)
@@ -360,6 +362,12 @@ int bootmethod_find_in_blk(struct udevice *dev, struct udevice *blk, int seq,
 
 	bflow->state = BOOTFLOWST_FS;
 
+	if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) {
+		ret = distro_boot_setup(desc, partnum, bflow);
+		if (ret)
+			return log_msg_ret("distro", ret);
+	}
+
 	return 0;
 }
 
@@ -372,6 +380,12 @@ int bootflow_boot(struct bootflow *bflow)
 		return log_msg_ret("load", -EPROTO);
 
 	switch (bflow->type) {
+	case BOOTFLOWT_DISTRO:
+		if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) {
+			done = true;
+			ret = distro_boot(bflow);
+		}
+		break;
 	case BOOTFLOWT_COUNT:
 		break;
 	}
diff --git a/boot/distro.c b/boot/distro.c
new file mode 100644
index 00000000000..062a8535ef1
--- /dev/null
+++ b/boot/distro.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * distro boot implementation for bootflow
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <bootmethod.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <net.h>
+#include <pxe_utils.h>
+#include <vsprintf.h>
+
+#define DISTRO_FNAME	"extlinux/extlinux.conf"
+
+/**
+ * struct distro_info - useful information for distro_getfile()
+ *
+ * @bflow: bootflow being booted
+ */
+struct distro_info {
+	struct bootflow *bflow;
+};
+
+static int distro_net_getfile(struct pxe_context *ctx, const char *file_path,
+			      char *file_addr, ulong *sizep)
+{
+	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+	int ret;
+
+	printf("get %s %s\n", file_addr, file_path);
+	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(sizep);
+	if (ret)
+		return log_msg_ret("tftp", ret);
+
+	return 0;
+}
+
+int distro_net_setup(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);
+
+	bflow->type = BOOTFLOWT_DISTRO;
+	ret = pxe_get(addr, &bootdir, &size);
+	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_LOADED;
+
+	/* 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;
+}
+
+int distro_boot_setup(struct blk_desc *desc, int partnum,
+		      struct bootflow *bflow)
+{
+	loff_t size, bytes_read;
+	ulong addr;
+	char *buf;
+	int ret;
+
+	bflow->type = BOOTFLOWT_DISTRO;
+	bflow->fname = strdup(DISTRO_FNAME);
+	if (!bflow->fname)
+		return log_msg_ret("name", -ENOMEM);
+	ret = fs_size(bflow->fname, &size);
+	if (ret)
+		return log_msg_ret("size", ret);
+	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, partnum);
+	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_LOADED;
+	bflow->buf = buf;
+
+	return 0;
+}
+
+static int disto_getfile(struct pxe_context *ctx, const char *file_path,
+			 char *file_addr, ulong *sizep)
+{
+	struct distro_info *info = ctx->userdata;
+	struct bootflow *bflow = info->bflow;
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	loff_t len_read;
+	ulong addr;
+	int ret;
+
+	addr = simple_strtoul(file_addr, NULL, 16);
+	ret = fs_set_blk_dev_with_part(desc, bflow->part);
+	if (ret)
+		return ret;
+	ret = fs_read(file_path, addr, 0, 0, &len_read);
+	if (ret)
+		return ret;
+	*sizep = len_read;
+
+	return 0;
+}
+
+int distro_boot(struct bootflow *bflow)
+{
+	struct cmd_tbl cmdtp = {};	/* dummy */
+	struct pxe_context ctx;
+	struct distro_info info;
+	bool is_net = !bflow->blk;
+	ulong addr;
+	int ret;
+
+	addr = map_to_sysmem(bflow->buf);
+	info.bflow = bflow;
+	ret = pxe_setup_ctx(&ctx, &cmdtp,
+			    is_net ? distro_net_getfile : disto_getfile,
+			    &info, !is_net, 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;
+}
diff --git a/include/bootmethod.h b/include/bootmethod.h
index a45897b0c0c..d80be556b8a 100644
--- a/include/bootmethod.h
+++ b/include/bootmethod.h
@@ -24,6 +24,8 @@ enum bootflow_state_t {
 };
 
 enum bootflow_type_t {
+	BOOTFLOWT_DISTRO,	/**< Distro boot */
+
 	BOOTFLOWT_COUNT,
 };
 
diff --git a/include/distro.h b/include/distro.h
new file mode 100644
index 00000000000..80b8da4bed3
--- /dev/null
+++ b/include/distro.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __distro_h
+#define __distro_h
+
+struct blk_desc;
+
+/**
+ * distro_boot_setup() - Set up a bootflow for distro boot from a block device
+ *
+ * This fills out a bootflow for a particular boot device and partition. It
+ * scans for a filesystem and suitable file, updating the bootflow accordingly.
+ *
+ * This sets the following fields in @bflow:
+ *
+ *	type, size, fname, state, subdir, buf
+ *
+ * The caller mast have already set the other fields.
+ *
+ * @desc: Block-device descriptor
+ * @partnum: Partition number (1..)
+ * @bflow: Partial bootflow to be completed by this function
+ * @return 0 on success (bootflow got to 'loaded' state), -ve on error
+ */
+int distro_boot_setup(struct blk_desc *desc, int partnum,
+		      struct bootflow *bflow);
+
+/**
+ * distro_boot_setup() - Set up a bootflow for distro boot from a network device
+ *
+ * This fills out a bootflow for a network device. It scans the tftp server for
+ * a suitable file, updating the bootflow accordingly.
+ *
+ * At present no control is provided as to which network device is used.
+ *
+ * This sets the following fields in @bflow:
+ *
+ *	type, size, fname, state,, buf
+ *
+ * The caller mast have already set the other fields.
+ *
+ * @bflow: Partial bootflow to be completed by this function
+ * @return 0 on success (bootflow got to 'loaded' state), -ve on error
+ */
+int distro_net_setup(struct bootflow *bflow);
+
+/**
+ * distro_boot() - Boot a distro
+ *
+ * Boots a bootflow of type BOOTFLOWT_DISTRO. This typically needs to load more
+ * files as it processes and this is done via the same media as the bootflow
+ * was loaded
+ *
+ * @bflow: Bootflow to boot
+*/
+int distro_boot(struct bootflow *bflow);
+
+#endif
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 21/28] bootmethod: Add a command
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (19 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 20/28] bootmethod: Add an implementation of distro boot Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 22/28] bootflow: " Simon Glass
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add a 'bootmethod' command to handle listing and selection of bootmethods.

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

 MAINTAINERS      |   1 +
 cmd/Kconfig      |   8 +++
 cmd/bootmethod.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 cmd/bootmethod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f78141c138b..655746265f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -635,6 +635,7 @@ M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	boot/bootmethod.c
 F:	boot/distro.c
+F:	cmd/bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index ffef3cc76ca..eec0dee8773 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -194,6 +194,14 @@ config CMD_BOOTM
 	help
 	  Boot an application image from the memory.
 
+config CMD_BOOTMETHOD
+	bool "bootmethod"
+	default y if BOOTMETHOD
+	help
+	  Support working with bootmethods, including listing available ones
+	  and showing information about a particular one. It also allows
+	  looking at bootflows available with the bootmethod.
+
 config BOOTM_EFI
 	bool "Support booting UEFI FIT images"
 	depends on CMD_BOOTEFI && CMD_BOOTM && FIT
diff --git a/cmd/bootmethod.c b/cmd/bootmethod.c
new file mode 100644
index 00000000000..2620ff61eb2
--- /dev/null
+++ b/cmd/bootmethod.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootmethod' command
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmethod.h>
+#include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+static int bootmethod_check_state(struct bootflow_state **statep)
+{
+	struct bootflow_state *state;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return ret;
+	if (!state->cur_bootmethod) {
+		printf("Please use 'bootmethod select' first\n");
+		return -ENOENT;
+	}
+	*statep = state;
+
+	return 0;
+}
+
+static int do_bootmethod_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	bool probe;
+
+	probe = argc >= 2 && !strcmp(argv[1], "-p");
+	bootmethod_list(probe);
+
+	return 0;
+}
+
+static int do_bootmethod_select(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct bootflow_state *state;
+	struct udevice *dev;
+	const char *name;
+	char *endp;
+	int seq;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+	if (argc < 2) {
+		state->cur_bootmethod = NULL;
+		return 0;
+	}
+	name = argv[1];
+	seq = simple_strtol(name, &endp, 16);
+
+	/* Select by name or number */
+	if (*endp)
+		ret = uclass_get_device_by_name(UCLASS_BOOTMETHOD, name, &dev);
+	else
+		ret = uclass_get_device_by_seq(UCLASS_BOOTMETHOD, seq, &dev);
+	if (ret) {
+		printf("Cannot find '%s' (err=%d)\n", name, ret);
+		return CMD_RET_FAILURE;
+	}
+	state->cur_bootmethod = dev;
+
+	return 0;
+}
+
+static int do_bootmethod_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	struct bootflow_state *state;
+	struct bootflow *bflow;
+	int ret, i, num_valid;
+	struct udevice *dev;
+	bool probe;
+
+	probe = argc >= 2 && !strcmp(argv[1], "-p");
+
+	ret = bootmethod_check_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	dev = state->cur_bootmethod;
+
+	/* Count the number of bootflows, including how many are valid*/
+	num_valid = 0;
+	for (ret = bootmethod_first_bootflow(dev, &bflow), i = 0;
+	     !ret;
+	     ret = bootmethod_next_bootflow(&bflow), i++)
+		num_valid += bflow->state == BOOTFLOWST_LOADED;
+
+	/*
+	 * 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 bootmethod_help_text[] =
+	"list [-p]      - list all available bootmethods (-p to probe)\n"
+	"bootmethod select <bm>    - select a bootmethod by name\n"
+	"bootmethod info [-p]      - show information about a bootmethod (-p to probe)";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(bootmethod, "Bootmethods", bootmethod_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmethod_list),
+	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootmethod_select),
+	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootmethod_info));
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 22/28] bootflow: Add a command
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (20 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 21/28] bootmethod: Add a command Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow Simon Glass
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

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

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

 MAINTAINERS       |   1 +
 boot/bootmethod.c |  26 +++
 cmd/Makefile      |   1 +
 cmd/bootflow.c    | 399 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 427 insertions(+)
 create mode 100644 cmd/bootflow.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 655746265f8..367193358b7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -635,6 +635,7 @@ M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	boot/bootmethod.c
 F:	boot/distro.c
+F:	cmd/bootflow.c
 F:	cmd/bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
diff --git a/boot/bootmethod.c b/boot/bootmethod.c
index be9d4aa02cc..b9752f75e54 100644
--- a/boot/bootmethod.c
+++ b/boot/bootmethod.c
@@ -404,6 +404,32 @@ int bootflow_boot(struct bootflow *bflow)
 	return log_msg_ret("end", -EFAULT);
 }
 
+void bootmethod_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_BOOTMETHOD, &dev);
+	else
+		ret = uclass_find_first_device(UCLASS_BOOTMETHOD, &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 device%s)\n", i, i != 1 ? "s" : "");
+}
+
 int bootmethod_setup_for_dev(struct udevice *parent, const char *drv_name)
 {
 	struct udevice *bm;
diff --git a/cmd/Makefile b/cmd/Makefile
index 891819ae0f6..f6ad648c94e 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_BOOTMETHOD) += bootmethod.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..4c619f0063b
--- /dev/null
+++ b/cmd/bootflow.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 'bootflow' command
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmethod.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 'Type' */
+	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_LOADED:
+		printf("File loaded");
+		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,
+	       bootmethod_type_get_name(bflow->type),
+	       bootmethod_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  Type         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 bootflow_state *state;
+	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 = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+	dev = state->cur_bootmethod;
+
+	/* If we have a device, just list bootflows attached to that device */
+	if (dev) {
+		printf("Showing bootflows for bootmethod '%s'\n", dev->name);
+		show_header();
+		for (ret = bootmethod_first_bootflow(dev, &bflow), i = 0;
+		     !ret;
+		     ret = bootmethod_next_bootflow(&bflow), i++) {
+			num_valid += bflow->state == BOOTFLOWST_LOADED;
+			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_LOADED;
+			show_bootflow(i, bflow, errors);
+		}
+	}
+	show_footer(i, num_valid);
+
+	return 0;
+}
+
+static int bootflow_run_boot(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",
+		       bootmethod_state_get_name(bflow->state));
+		break;
+	case -ENOSYS:
+		printf("Boot type '%s' not supported\n",
+		       bootmethod_type_get_name(bflow->type));
+		break;
+	default:
+		printf("Boot failed (err=%d)\n", ret);
+		break;
+	}
+
+	return 0;
+}
+
+static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootflow_state *state;
+	struct bootmethod_iter iter;
+	struct udevice *dev;
+	struct bootflow bflow;
+	bool all = false, boot = false, errors = false, list = false;
+	int num_valid = 0;
+	int ret, i;
+
+	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');
+	}
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+	dev = state->cur_bootmethod;
+	state->cur_bootflow = NULL;
+
+	/*
+	 * If we have a device, just scan for bootflows attached to that device
+	 */
+	if (dev) {
+		if (list) {
+			printf("Scanning for bootflows in bootmethod '%s'\n",
+			       dev->name);
+			show_header();
+		}
+		bootmethod_clear_bootflows(dev);
+		for (i = 0, ret = 0; i < 100 && ret != -ESHUTDOWN; i++) {
+			ret = bootmethod_get_bootflow(dev, i, &bflow);
+			if ((ret && !all) || ret == -ESHUTDOWN) {
+				bootflow_free(&bflow);
+				continue;
+			}
+			bflow.err = ret;
+			ret = bootmethod_add_bootflow(&bflow);
+			if (ret) {
+				printf("Out of memory\n");
+				return CMD_RET_FAILURE;
+			}
+			num_valid++;
+			if (list)
+				show_bootflow(i, &bflow, errors);
+			if (boot && !bflow.err)
+				bootflow_run_boot(&bflow);
+		}
+	} else {
+		int flags = 0;
+
+		if (list) {
+			printf("Scanning for bootflows in all bootmethods\n");
+			show_header();
+		}
+		bootmethod_clear_glob();
+		if (list)
+			flags |= BOOTFLOWF_SHOW;
+		if (all)
+			flags |= BOOTFLOWF_ALL;
+		for (i = 0,
+		     ret = bootmethod_scan_first_bootflow(&iter, flags, &bflow);
+		     i < 1000 && ret != -ENODEV;
+		     i++, ret = bootmethod_scan_next_bootflow(&iter, &bflow)) {
+			bflow.err = ret;
+			if (!ret)
+				num_valid++;
+			ret = bootmethod_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(&bflow);
+		}
+	}
+	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 bootflow_state *state;
+	struct bootflow *bflow, *found;
+	struct udevice *dev;
+	const char *name;
+	char *endp;
+	int seq, i;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+;
+	if (argc < 2) {
+		state->cur_bootflow = NULL;
+		return 0;
+	}
+	dev = state->cur_bootmethod;
+
+	name = argv[1];
+	seq = simple_strtol(name, &endp, 16);
+	found = NULL;
+
+	/*
+	 * If we have a bootmethod device, only allow selection of bootflows
+	 * attached to that device
+	 */
+	if (dev) {
+		for (ret = bootmethod_first_bootflow(dev, &bflow), i = 0;
+		     !ret;
+		     ret = bootmethod_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 bootmethod '%s' ", dev->name);
+		printf("(err=%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+	state->cur_bootflow = found;
+
+	return 0;
+}
+
+static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	struct bootflow_state *state;
+	struct bootflow *bflow;
+	bool dump = false;
+	int ret;
+
+	if (argc > 1 && *argv[1] == '-')
+		dump = strchr(argv[1], 'd');
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (!state->cur_bootflow) {
+		printf("No bootflow selected\n");
+		return CMD_RET_FAILURE;
+	}
+	bflow = state->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("Sequence:  %d\n", bflow->seq);
+	printf("Type:      %s\n", bootmethod_type_get_name(bflow->type));
+	printf("State:     %s\n", bootmethod_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 bootflow_state *state;
+	struct bootflow *bflow;
+	int ret;
+
+	ret = bootmethod_get_state(&state);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/*
+	 * Require a current bootflow. Users can use 'bootflow scan -b' to
+	 * automatically scan and boot, if needed.
+	 */
+	if (!state->cur_bootflow) {
+		printf("No bootflow selected\n");
+		return CMD_RET_FAILURE;
+	}
+	bflow = state->cur_bootflow;
+	ret = bootflow_run_boot(bflow);
+	if (ret) {
+		printf("Boot failed (err %d)n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootflow_help_text[] =
+	"scan [-abel] - scan for valid bootflows (-l list, -a all, -e errors, -b boot)\n"
+	"bootflow list [-e]    - list scanned bootflows (-e errors)\n"
+	"bootflow select       - 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, "Bootflows", bootflow_help_text,
+	U_BOOT_SUBCMD_MKENT(scan, 2, 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.rc1.237.g0d66db33f3-goog


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

* [PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (21 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 22/28] bootflow: " Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 24/28] bootmethod: doc: Add documentation Simon Glass
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add a set of combined tests for these two commands.

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>
---

 MAINTAINERS               |   1 +
 configs/sandbox_defconfig |   2 +-
 include/test/suites.h     |   2 +
 test/Makefile             |   1 +
 test/boot/Makefile        |   5 +
 test/boot/bootmethod.c    | 271 ++++++++++++++++++++++++++++++++++++++
 test/cmd_ut.c             |   4 +
 try.sh                    | 131 ++++++++++++++++++
 8 files changed, 416 insertions(+), 1 deletion(-)
 create mode 100644 test/boot/Makefile
 create mode 100644 test/boot/bootmethod.c
 create mode 100755 try.sh

diff --git a/MAINTAINERS b/MAINTAINERS
index 367193358b7..2f74f7dbb19 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -639,6 +639,7 @@ F:	cmd/bootflow.c
 F:	cmd/bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
+F:	test/boot/bootmethod.c
 
 BTRFS
 M:	Marek Behun <marek.behun@nic.cz>
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 952d430304c..31a8d6a1d90 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -26,7 +26,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=0x2000
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_LOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
diff --git a/include/test/suites.h b/include/test/suites.h
index d35cd83a4eb..c36aa568e78 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_bootmethod(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..bb1599b9c0d
--- /dev/null
+++ b/test/boot/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+
+obj-$(CONFIG_BOOTMETHOD) += bootmethod.o
diff --git a/test/boot/bootmethod.c b/test/boot/bootmethod.c
new file mode 100644
index 00000000000..4467625c0fd
--- /dev/null
+++ b/test/boot/bootmethod.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <bootmethod.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+/* Declare a new bootmethod test */
+#define BOOTMETHOD_TEST(_name, _flags) \
+		UNIT_TEST(_name, _flags, bootmethod_test)
+
+/* Check 'bootmethod list' command */
+static int bootmethod_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 ? "bootmethod list -p" :
+			"bootmethod 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.bootmethod");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 1, probe_ch, "OK",
+				   "mmc", "mmc1.bootmethod");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 2, probe_ch, "OK",
+				   "mmc", "mmc0.bootmethod");
+		ut_assert_nextlinen("---");
+		ut_assert_nextline("(3 devices)");
+		ut_assert_console_end();
+	}
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootmethod select' and 'info' commands */
+static int bootmethod_test_cmd_select(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_asserteq(1, run_command("bootmethod info", 0));
+	ut_assert_nextlinen("Please use");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootmethod select 0", 0));
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootmethod info", 0));
+	ut_assert_nextline("Name:      mmc2.bootmethod");
+	ut_assert_nextline("Uclass:    mmc");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan/list' commands */
+static int bootmethod_test_cmd_bootflow(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in bootmethod 'mmc0.bootmethod'");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(21 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing bootflows for bootmethod 'mmc0.bootmethod'");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan/list' commands using all bootmethods */
+static int bootmethod_test_cmd_bootflow_glob(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootmethods");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':");
+	ut_assert_nextline("Scanning bootmethod 'mmc1.bootmethod':");
+	ut_assert_nextline("Scanning bootmethod 'mmc0.bootmethod':");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextline("No more bootmethods");
+	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  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_glob,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -e' */
+static int bootmethod_test_cmd_bootflow_scan_e(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -ale", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootmethods");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':");
+	ut_assert_nextline("  0  distro-boot  media   mmc          0  mmc2.bootmethod.part_1    <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
+	ut_assert_nextline("  1  distro-boot  media   mmc          0  mmc2.bootmethod.part_2    <NULL>");
+
+	ut_assert_skip_to_line("Scanning bootmethod 'mmc1.bootmethod':");
+	ut_assert_skip_to_line("Scanning bootmethod 'mmc0.bootmethod':");
+	ut_assert_nextline(" 28  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextline(" 29  distro-boot  media   mmc          0  mmc0.bootmethod.part_2    <NULL>");
+	ut_assert_skip_to_line(" 3b  distro-boot  media   mmc          0  mmc0.bootmethod.part_14   <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-2");
+	ut_assert_nextline("No more bootmethods");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(60 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing all bootflows");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  media   mmc          0  mmc2.bootmethod.part_1    <NULL>");
+	ut_assert_skip_to_line(" 28  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_skip_to_line(" 3b  distro-boot  media   mmc          0  mmc0.bootmethod.part_14   <NULL>");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(60 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_e,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow info' */
+static int bootmethod_test_cmd_bootflow_info(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 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:      mmc0.bootmethod.part_1");
+	ut_assert_nextline("Device:    mmc0.bootmethod");
+	ut_assert_nextline("Block dev: mmc0.blk");
+	ut_assert_nextline("Sequence:  0");
+	ut_assert_nextline("Type:      distro-boot");
+	ut_assert_nextline("State:     loaded");
+	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:      237 (567 bytes)");
+	ut_assert_nextline("Error:     0");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow info -d", 0));
+	ut_assert_nextline("Name:      mmc0.bootmethod.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;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_info,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -b' to boot the first available bootmethod */
+static int bootmethod_test_cmd_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 'mmc0.bootmethod.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;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_boot,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow boot' to boot a selected bootflow */
+static int bootmethod_test_cmd_bootflow_boot(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 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 boot", 0));
+	ut_assert_nextline("** Booting bootflow 'mmc0.bootmethod.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;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_boot,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check we can get a bootmethod */
+static int bootmethod_test_get(struct unit_test_state *uts)
+{
+	struct bootmethod_iter iter;
+	struct bootflow bflow;
+
+	ut_assertok(bootmethod_scan_first_bootflow(&iter, 0, &bflow));
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_get, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+int do_ut_bootmethod(struct cmd_tbl *cmdtp, int flag, int argc,
+		     char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(bootmethod_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(bootmethod_test);
+
+	return cmd_ut_category("bootmethod", "bootmethod_test_",
+			       tests, n_ents, argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 90b260f72d6..c71f5575a04 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_BOOTMETHOD
+	U_BOOT_CMD_MKENT(bootmethod, CONFIG_SYS_MAXARGS, 1, do_ut_bootmethod,
+			 "", ""),
+#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, "", ""),
diff --git a/try.sh b/try.sh
new file mode 100755
index 00000000000..14519c3144c
--- /dev/null
+++ b/try.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+
+set -e
+
+file=mmc.img
+mnt=/mnt/x
+fat=/mnt/y
+dstdir=$fat/extlinux
+
+vmlinux=vmlinuz-5.3.7-301.fc31.armv7hl
+initrd=initramfs-5.3.7-301.fc31.armv7hl.img
+dtb=dtb-5.3.7-301.fc31.armv7hl/sandbox.dtb
+
+old() {
+	mkfs.vfat $file
+	sudo mount -o loop $file $mnt
+	#sudo cp /tmp/b/efi-x86_payload64/u-boot-payload.efi /mnt/x
+	#sudo cp /tmp/efi64/startup.nsh  $mnt
+	#sudo cp /tmp/efi64/vmlinuz $mnt
+	echo >>/tmp/extlinux.conf <<EOF
+ui menu.c32
+
+menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options.
+menu title Arch Boot Options.
+menu hidden
+
+timeout 50
+
+default Arch
+
+label Arch
+    kernel /zImage
+    append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8
+    fdtdir /dtbs
+    initrd /initramfs-linux.img
+EOF
+	sudo cp /tmp/extlinux.conf $mnt
+	ls $mnt
+	sudo umount $mnt
+}
+
+
+fat_setup() {
+	echo 'type=c' | sudo sfdisk $file
+	#sudo kpartx -a $file
+	loop=$(sudo losetup --show -f -P $file)
+	echo "Mounted to $loop"
+	fatpart="${loop}p1"
+ 	sudo mkfs.vfat $fatpart
+	sudo mount -o loop ${fatpart} $fat
+}
+
+
+fat_finish() {
+	sudo mkdir -p $dstdir
+	sudo cp /tmp/extlinux.conf $dstdir
+
+	echo "vmlinux" | gzip >/tmp/inf
+	mkimage -f auto -d /tmp/inf /tmp/$vmlinux
+
+	sudo cp /tmp/$vmlinux $fat
+
+	echo "initd" >/tmp/$initrd
+	sudo cp /tmp/$initrd $fat
+
+	dtb_dir="$(dirname /tmp/$dtb)"
+	mkdir -p $dtb_dir
+	echo "/dts-v1/; / {};" | dtc >/tmp/$dtb
+	sudo cp -r $dtb_dir $fat
+
+	ls $dstdir
+
+	sudo umount $fat
+
+	losetup -d $loop
+}
+
+
+new() {
+	fat_setup
+	cat >/tmp/extlinux.conf << EOF
+ui menu.c32
+
+menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options.
+menu title Arch Boot Options.
+menu hidden
+
+timeout 50
+
+default Arch
+
+label Arch
+    kernel /zImage
+    append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8
+    fdtdir /dtbs
+    initrd /initramfs-linux.img
+EOF
+	fat_finish
+}
+
+
+fedora31() {
+	fat_setup
+	cat >/tmp/extlinux.conf << EOF
+# 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 /$vmlinux
+	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 /$initrd
+EOF
+	fat_finish
+}
+
+# Remove old devices
+for dev in $(losetup |grep $file | awk '{print $1}'); do
+	echo "Remove $dev"
+	losetup -d $dev
+done
+
+qemu-img create $file 20M
+#old
+#new
+fedora31
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 24/28] bootmethod: doc: Add documentation
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (22 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 25/28] mmc: Allow for children other than the block device Simon Glass
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add documentation for this feature, including the commands.

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

 MAINTAINERS                             |   3 +
 doc/develop/bootflow.rst                | 323 ++++++++++++++++++
 doc/develop/index.rst                   |   1 +
 doc/device-tree-bindings/bootmethod.txt |  14 +
 doc/usage/bootflow.rst                  | 419 ++++++++++++++++++++++++
 doc/usage/bootmethod.rst                | 138 ++++++++
 doc/usage/index.rst                     |   2 +
 7 files changed, 900 insertions(+)
 create mode 100644 doc/develop/bootflow.rst
 create mode 100644 doc/device-tree-bindings/bootmethod.txt
 create mode 100644 doc/usage/bootflow.rst
 create mode 100644 doc/usage/bootmethod.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f74f7dbb19..f472a589f61 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -637,6 +637,9 @@ F:	boot/bootmethod.c
 F:	boot/distro.c
 F:	cmd/bootflow.c
 F:	cmd/bootmethod.c
+F:	doc/develop/bootflow.rst
+F:	doc/usage/bootflow.rst
+F:	doc/usage/bootmethod.rst
 F:	include/bootmethod.h
 F:	include/distro.h
 F:	test/boot/bootmethod.c
diff --git a/doc/develop/bootflow.rst b/doc/develop/bootflow.rst
new file mode 100644
index 00000000000..930952cf2c4
--- /dev/null
+++ b/doc/develop/bootflow.rst
@@ -0,0 +1,323 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+Bootmethod and Bootflow
+=======================
+
+Introduction
+------------
+
+Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
+an Operating System without custom scripting and other customisation:
+
+  - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
+  - bootflow - a description of how to boot (owned 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.
+
+Bootmethod and bootflow together provide 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).
+
+
+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.
+
+
+Bootmethod
+----------
+
+How does U-Boot find the bootflow files? That is the job of bootmethods.
+A bootmethod is simply a device that locates bootflow files. For example, an
+MMC bootmethod for distro boot would simply scan through the partitions on the
+MMC to find valid filesystems, then search each filesystem for a file called
+`extlinux/extlinux.conf`. Each of those files constitutes a bootflow, so the
+MMC device may produce multiple bootflows. Of course that is under control of
+the bootmethod.
+
+
+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 bootmethod)
+      while (get next bootflow)
+          try to boot it
+
+So U-Boot works its way through the bootmethods, trying in turn the bootflows
+provided by each, until it either boots or exhausts the available options.
+
+If you are familiar with the producer–consumer model, bootmethods are the
+producers and bootflows are the items produced. The consumer is the 'booter'
+which tries to boot each produced item.
+
+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, listing each find it finds (-l) and trying
+to boot it (-b).
+
+
+Bootmethod uclass
+-----------------
+
+The bootmethod uclass provides an simple API call to obtain one or more
+bootflows from a device::
+
+   int bootmethod_get_bootflow(struct udevice *dev, int seq,
+                               struct bootflow *bflow);
+
+This takes a sequence number (0 for the first bootflow, 1 for the next) and
+returnS a bootflow. This is the core of the bootmethod implementation. The
+bootmethod drivers that implement this differ depending on the media they are
+reading from, but each is responsible for returning a valid bootflow if
+available.
+
+
+Bootmethod drivers
+------------------
+
+A bootmethod driver is typically fairly simple. Here is one for mmc::
+
+    static int mmc_get_bootflow(struct udevice *dev, int seq,
+                    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 = bootmethod_find_in_blk(dev, blk, seq, bflow);
+        if (ret)
+            return log_msg_ret("find", ret);
+
+        return 0;
+    }
+
+    struct bootmethod_ops mmc_bootmethod_ops = {
+        .get_bootflow    = mmc_get_bootflow,
+    };
+
+    U_BOOT_DRIVER(mmc_bootmethod) = {
+        .name        = "mmc_bootmethod",
+        .id        = UCLASS_BOOTMETHOD,
+        .ops        = &mmc_bootmethod_ops,
+    };
+
+The implementation of the `get_bootflow` method is simply to obtain the
+block device and call a bootmethod helper function to do the rest. The
+implementation of `bootmethod_find_in_blk()` checks the partition table, and
+attempts to read a file from a filesystem on the partition number given by the
+@seq parameter.
+
+
+Device hierarchy
+----------------
+
+A bootmethod device is a child of the media device. In this example, you can see
+that the bootmethod 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
+    bootmethod    0  [   ]   mmc_bootmethod        |   |   `-- mmc@7e202000.bootmethod
+    mmc           1  [ + ]   sdhci-bcm2835         |   |-- sdhci@7e300000
+    blk           1  [   ]   mmc_blk               |   |   |-- sdhci@7e300000.blk
+    bootmethod    1  [   ]   mmc_bootmethod        |   |   `-- sdhci@7e300000.bootmethod
+
+The bootmethod device is typically created automatically in the media uclass'
+`post_bind()` method. This is typically something like this::
+
+    ret = bootmethod_setup_for_dev(dev, "eth_bootmethod");
+        if (ret)
+            return log_msg_ret("bootmethod", ret);
+
+Here, `eth_bootmethod` is the name of the Ethernet bootmethod driver and `dev`
+is the ethernet device. This function is safe to call even if bootmethod is
+not enabled, since it does nothing in that case. It can be added to all uclasses
+which implement suitable media.
+
+
+Using devicetree
+----------------
+
+If a bootmethod is complicated or needs configuration information, it can be
+added to the devicetree as a child of the media device. For example, imagine a
+bootmethod 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>;
+
+            bootmethod {
+                compatible = "sf-bootmethod";
+                offset = <0x2000>;
+                size = <0x1000>;
+            };
+        };
+    };
+
+The `sf-bootmethod` 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
+-------------
+
+The bootmethod/bootflow feature can be enabled with `CONFIG_BOOTMETHOD`. Each
+type of bootflow has its own CONFIG option also. For example,
+`CONFIG_BOOTMETHOD_DISTRO` enables support for distro boot.
+
+
+Command interface
+-----------------
+
+Two commands are available:
+
+`bootmethod`
+    Allows listing of available bootmethods, selecting a particular one and
+    getting information about it. See :doc:`../usage/bootmethod`
+
+`bootflow`
+    Allows scanning one or more bootmethods for bootflows, listing available
+    bootflows, selecting one, obtaining information about it and booting it.
+    See :doc:`../usage/bootflow`
+
+
+.. _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.
+loaded   File was loaded and is ready for use. In this state the bootflow can
+         be booted.
+=======  =======================================================================
+
+
+Bootflow internals
+------------------
+
+The bootflow uclass holds a linked list of scanned bootflows as well as the
+currently selected bootmethod and bootflow (for use by commands). This is in
+`struct bootflow_state`.
+
+Each bootmethod device has its own `struct bootmethod_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. EFI support and Chromium OS support.
+
+
+To do
+-----
+
+Most of the following things will be completd as part of initial development,
+before a final series is sent:
+
+- use `ready` instead of `loaded` for the state name?
+- `bootflow prep` to load everything preparing for boot, so that `bootflow boot`
+  can just do the boot.
+- check ordering of bootmethods (should it use aliases?)
+- check ordering of bootflows within bootmethods (needed)
+- implement boot_targets env var?
+- quick way to boot from particular media - 'bootflow boot mmc1' ?
+- add bootmethod drivers for dhcp, sata, scsi, ide, usb, virtio
+- introduce an interface for disto_getfile() and disto_net_getfile() provided
+  by the bootmethod
+- better name for this feature? It is clearly not auto-boot or distro-boot,
+  but perhaps standard boot?
+
+Other ideas:
+
+- rename bootflow to flow, bootmethod to method (since this is a bootloader
+  after all)
+- bootmethod flags for speed (e.g. network and USB are slow)
+- should the means of scanning for particular files on a bootmethod device be
+  moved into a driver architecture, so we have drivers for distro boot,
+  Chromium OS, etc.?
+- automatically load kernel, FDT, etc. to suitable addresses so the board does
+  not need to specific 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/index.rst b/doc/develop/index.rst
index 1fb0f06f6e8..e87bac0185b 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -9,6 +9,7 @@ Implementation
 .. toctree::
    :maxdepth: 1
 
+   bootflow
    ci_testing
    commands
    devicetree/index
diff --git a/doc/device-tree-bindings/bootmethod.txt b/doc/device-tree-bindings/bootmethod.txt
new file mode 100644
index 00000000000..ef2545cab68
--- /dev/null
+++ b/doc/device-tree-bindings/bootmethod.txt
@@ -0,0 +1,14 @@
+U-Boot Bootmethod
+=================
+
+A bootmethod 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 bootmethod driver is provided by the media devices. The bindings for each
+are described in this file.
+
+
+MMC bootmethod
+--------------
+
+Optional properties:
diff --git a/doc/usage/bootflow.rst b/doc/usage/bootflow.rst
new file mode 100644
index 00000000000..39cae8beed9
--- /dev/null
+++ b/doc/usage/bootflow.rst
@@ -0,0 +1,419 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+bootflow command
+================
+
+Synopis
+-------
+
+::
+
+    bootflow scan [-abel]
+    bootflow list [-e]
+    bootflow select [<num|name>]
+    bootflow info [-d]
+    bootflow boot
+
+
+Description
+-----------
+
+The `bootflow` command is used to manage bootflows. It can scan bootmethods to
+locate bootflows, list them and boot them.
+
+See :doc:`../develop/bootflow` for more information.
+
+
+bootflow scan
+~~~~~~~~~~~~~
+
+Scans for available bootflows, optionally booting the first valid one it finds.
+This operates in two modes:
+
+- If no bootmethod is selected (see `bootmethod select`) it scans bootflows one
+  by one, extracting all the bootmethods from each
+- If a bootmethod 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
+    bootmethod and bootflows are being tried.
+
+
+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  Type         State   Uclass    Part  Name                              Filename
+===  ===========  ======  ========  ====  ===============================   ================
+  0  distro-boot  loaded  mmc          2  mmc\@7e202000.bootmethod.part_2   extlinux/extlinux.conf
+  1  distro-boot  loaded  ethernet     0  smsc95xx_eth.bootmethod.0         rpi.pxe/extlinux/extlinux.conf
+===  ===========  ======  ========  ====  ===============================   ================
+
+The fields are as follows:
+
+Seq:
+    Sequence number in the scan, used to reference the bootflow later
+
+Type:
+    Type of the bootflow. Currently this is always 'distro-boot', indicating
+    that it is an extlinux.conf file.
+
+State:
+    Current state of the bootflow, indicating how far the bootmethod 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 bootmethod 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.bootmethod.part_2
+Device     mmc\@7e202000.bootmethod
+Block dev  mmc\@7e202000.blk
+Sequence   1
+Type       distro-boot
+State      loaded
+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 bootmethod
+
+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 bootmethods 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 bootmethods
+    Seq  Type         State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    Scanning bootmethod 'mmc@7e202000.bootmethod':
+      0  distro-boot  loaded  mmc          2  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+    Scanning bootmethod 'sdhci@7e300000.bootmethod':
+    Card did not respond to voltage select! : -110
+    Scanning bootmethod 'smsc95xx_eth.bootmethod':
+    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-boot  loaded  ethernet     0  smsc95xx_eth.bootmethod.0 rpi.pxe/extlinux/extlinux.conf
+    No more bootmethods
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    (2 bootflows, 2 valid)
+    U-Boot> bootflow l
+    Showing all bootflows
+    Seq  Type         State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+      0  distro-boot  loaded  mmc          2  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+      1  distro-boot  loaded  ethernet     0  smsc95xx_eth.bootmethod.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.bootmethod.part_2
+    U-Boot> bootflow info
+    Name:      mmc@7e202000.bootmethod.part_2
+    Device:    mmc@7e202000.bootmethod
+    Block dev: mmc@7e202000.blk
+    Sequence:  1
+    Type:      distro-boot
+    State:     loaded
+    Partition: 2
+    Subdir:    (none)
+    Filename:  extlinux/extlinux.conf
+    Buffer:    3db7ae88
+    Size:      232 (562 bytes)
+    Error:     0
+    U-Boot> bootflow boot
+    ** Booting bootflow 'smsc95xx_eth.bootmethod.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 bootmethods
+    Seq  Type         State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    Scanning bootmethod 'mmc@7e202000.bootmethod':
+      0  distro-boot  loaded  mmc          2  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+    ** Booting bootflow 'mmc@7e202000.bootmethod.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-boot  fs      mmc          1  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+         ** File not found, err=-2
+      1  distro-boot  loaded  mmc          2  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+      2  distro-boot  fs      mmc          3  mmc@7e202000.bootmethod.p extlinux/extlinux.conf
+         ** File not found, err=-1
+      3  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      4  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      5  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      6  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      7  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      8  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      9  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      a  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      b  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      c  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      d  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      e  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+      f  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+     10  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+     11  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+     12  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+     13  distro-boot  media   mmc          0  mmc@7e202000.bootmethod.p <NULL>
+         ** No partition found, err=-2
+     14  distro-boot  loaded  ethernet     0  smsc95xx_eth.bootmethod.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/bootmethod.rst b/doc/usage/bootmethod.rst
new file mode 100644
index 00000000000..28afe09f06f
--- /dev/null
+++ b/doc/usage/bootmethod.rst
@@ -0,0 +1,138 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+bootmethod command
+==================
+
+Synopis
+-------
+
+::
+
+    bootmethod list [-p]      - list all available bootmethods (-p to probe)\n"
+    bootmethod select <bm>    - select a bootmethod by name\n"
+    bootmethod info [-p]      - show information about a bootmethod";
+
+Description
+-----------
+
+The `` command is used to manage bootmethods. It can list available
+bootmethods, select one and obtain information about it.
+
+See :doc:`../develop/bootflow` for more information about bootmethods in
+general.
+
+
+bootmethod list
+~~~~~~~~~~~~~~~
+
+This lists available bootmethods
+
+Scanning with -p causes the bootmethods 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.bootmethod
+  1   [   ]      OK  mmc       sdhci@7e300000.bootmethod
+  2   [   ]      OK  ethernet  smsc95xx_eth.bootmethod
+===  ======  ======  ========  =========================
+
+
+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 bootmethod. This is generated from the media device appended
+    with `.bootmethod`
+
+
+bootmethod select
+~~~~~~~~~~~~~~~~~
+
+Use this to select a particular bootmethod. You can select it by the sequence
+number or name, as shown in `bootmethod list`.
+
+Once a bootmethod is selected, you can use `bootmethod info` to look at it or
+`bootflow scan` to scan it.
+
+If no bootmethod name or number is provided, then any existing bootmethod is
+unselected.
+
+
+bootmethod info
+~~~~~~~~~~~~~~~
+
+This shows information on the current bootmethod, with the format looking like
+this:
+
+=========  =======================
+Name       mmc@7e202000.bootmethod
+Sequence   0
+Status     Probed
+Uclass     mmc
+Bootflows  1 (1 valid)
+=========  =======================
+
+Most of the information is the same as `bootmethod list` above. The new fields
+are:
+
+Device
+    Name of the bootmethod
+
+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 bootmethod. This is 0
+    unless you have used 'bootflow scan' on the bootflow, or on all bootflows.
+
+
+Example
+-------
+
+This example shows listing available bootmethod and getting information about
+one of them::
+
+   U-Boot> bootmethod list
+   Seq  Probed  Status  Uclass    Name
+   ---  ------  ------  --------  ------------------
+     0   [ + ]      OK  mmc       mmc@7e202000.bootmethod
+     1   [   ]      OK  mmc       sdhci@7e300000.bootmethod
+     2   [   ]      OK  ethernet  smsc95xx_eth.bootmethod
+   ---  ------  ------  --------  ------------------
+   (3 devices)
+   U-Boot> bootmethod sel 0
+   U-Boot> bootflow scan
+   U-Boot> bootmethod info
+   Name:      mmc@7e202000.bootmethod
+   Sequence:  0
+   Status:    Probed
+   Uclass:    mmc
+   Bootflows: 1 (1 valid)
+
+
+Return value
+------------
+
+The return value $? is always 0 (true).
+
+
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 356f2a56181..0abfad26e8e 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -21,8 +21,10 @@ Shell commands
    askenv
    base
    bootefi
+   bootflow
    booti
    bootmenu
+   bootmethod
    button
    x86/cbsysinfo
    conitrace
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 25/28] mmc: Allow for children other than the block device
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (23 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 24/28] bootmethod: doc: Add documentation Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:45 ` [PATCH 26/28] mmc: Add a bootmethod Simon Glass
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, 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>
---

 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 0e13238c7e7..9e39fdd6c44 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);
@@ -422,7 +422,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.rc1.237.g0d66db33f3-goog


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

* [PATCH 26/28] mmc: Add a bootmethod
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (24 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 25/28] mmc: Allow for children other than the block device Simon Glass
@ 2021-08-19  3:45 ` Simon Glass
  2021-08-19  3:46 ` [PATCH 27/28] ethernet: " Simon Glass
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:45 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass,
	Jaehoon Chung, Peng Fan

Add a bootmethod for MMC. It mostly just calls the bootmethod 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>
---

 MAINTAINERS                  |  1 +
 drivers/mmc/Makefile         |  5 ++++
 drivers/mmc/mmc-uclass.c     | 19 +++++++++++++++
 drivers/mmc/mmc_bootmethod.c | 46 ++++++++++++++++++++++++++++++++++++
 include/mmc.h                | 12 +++++++++-
 5 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/mmc_bootmethod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f472a589f61..246c5e60270 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -640,6 +640,7 @@ F:	cmd/bootmethod.c
 F:	doc/develop/bootflow.rst
 F:	doc/usage/bootflow.rst
 F:	doc/usage/bootmethod.rst
+F:	drivers/mmc/mmc_bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
 F:	test/boot/bootmethod.c
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index dde6cd563ff..0b6ddfb5165 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_)BOOTMETHOD) += mmc_bootmethod.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 9e39fdd6c44..42474bc197e 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 <bootmethod.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;
@@ -403,6 +418,10 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
 	mmc->cfg = cfg;
 	mmc->priv = dev;
 
+	ret = bootmethod_setup_for_dev(dev, "mmc_bootmethod");
+	if (ret)
+		return log_msg_ret("bootmethod", ret);
+
 	/* the following chunk was from mmc_register() */
 
 	/* Setup dsr related values */
diff --git a/drivers/mmc/mmc_bootmethod.c b/drivers/mmc/mmc_bootmethod.c
new file mode 100644
index 00000000000..eab13036d89
--- /dev/null
+++ b/drivers/mmc/mmc_bootmethod.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for MMC
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmethod.h>
+#include <dm.h>
+#include <mmc.h>
+
+static int mmc_get_bootflow(struct udevice *dev, int seq,
+			    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 = bootmethod_find_in_blk(dev, blk, seq, bflow);
+	if (ret)
+		return log_msg_ret("find", ret);
+
+	return 0;
+}
+
+struct bootmethod_ops mmc_bootmethod_ops = {
+	.get_bootflow	= mmc_get_bootflow,
+};
+
+U_BOOT_DRIVER(mmc_bootmethod) = {
+	.name		= "mmc_bootmethod",
+	.id		= UCLASS_BOOTMETHOD,
+	.ops		= &mmc_bootmethod_ops,
+};
diff --git a/include/mmc.h b/include/mmc.h
index 0bf19de20e5..1cd274f6253 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -959,10 +959,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.rc1.237.g0d66db33f3-goog


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

* [PATCH 27/28] ethernet: Add a bootmethod
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (25 preceding siblings ...)
  2021-08-19  3:45 ` [PATCH 26/28] mmc: Add a bootmethod Simon Glass
@ 2021-08-19  3:46 ` Simon Glass
  2021-08-19  3:46 ` [PATCH 28/28] RFC: rpi: Switch over to use bootflow Simon Glass
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass

Add a bootmethod for Ethernet. It uses the distro boot mechanism to
locate a file.

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

 MAINTAINERS               |  1 +
 configs/sandbox_defconfig |  1 +
 net/Kconfig               |  9 +++++
 net/Makefile              |  1 +
 net/eth-uclass.c          |  8 +++++
 net/eth_bootmethod.c      | 76 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 96 insertions(+)
 create mode 100644 net/eth_bootmethod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 246c5e60270..74e8eaafb10 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -643,6 +643,7 @@ F:	doc/usage/bootmethod.rst
 F:	drivers/mmc/mmc_bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
+F:	net/eth_bootmethod.c
 F:	test/boot/bootmethod.c
 
 BTRFS
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 31a8d6a1d90..321d32be73e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -116,6 +116,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_BOOTMETHOD_ETH is not set
 CONFIG_BOOTP_SEND_HOSTNAME=y
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
diff --git a/net/Kconfig b/net/Kconfig
index ba0ca813ce5..6f92fe44a8c 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 BOOTMETHOD_ETH
+	bool "Enable bootmethod for ethernet"
+	depends on BOOTMETHOD
+	default y
+	help
+	  Provide a bootmethod 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..c86bbd90349 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_)BOOTMETHOD_ETH) += eth_bootmethod.o
 else
 obj-$(CONFIG_NET)      += eth_legacy.o
 endif
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 0da0e85be03..0284215b113 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY UCLASS_ETH
 
 #include <common.h>
+#include <bootmethod.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(BOOTMETHOD_ETH)) {
+		ret = bootmethod_setup_for_dev(dev, "eth_bootmethod");
+		if (ret)
+			return log_msg_ret("bootmethod", ret);
+	}
 
 	return 0;
 }
diff --git a/net/eth_bootmethod.c b/net/eth_bootmethod.c
new file mode 100644
index 00000000000..bc8843add80
--- /dev/null
+++ b/net/eth_bootmethod.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for ethernet
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootmethod.h>
+#include <command.h>
+#include <distro.h>
+#include <dm.h>
+#include <net.h>
+
+static int eth_get_bootflow(struct udevice *dev, int seq,
+			    struct bootflow *bflow)
+{
+	char name[60];
+	int ret;
+
+	/*
+	 * Like distro boot, this assumes there is only one Ethernet device.
+	 * In this case, that means that @eth is ignored
+	 */
+	if (seq)
+		return log_msg_ret("dhcp", -ESHUTDOWN);
+
+	bflow->seq = seq;
+	snprintf(name, sizeof(name), "%s.%d", dev->name, seq);
+	bflow->name = strdup(name);
+	if (!bflow->name)
+		return log_msg_ret("name", -ENOMEM);
+	if (!bflow->name)
+		return log_msg_ret("name", -ENOMEM);
+	bflow->state = BOOTFLOWST_BASE;
+
+	/*
+	 * 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.
+	 */
+	run_command("dhcp", 0);
+	bflow->state = BOOTFLOWST_MEDIA;
+
+	if (CONFIG_IS_ENABLED(BOOTMETHOD_DISTRO)) {
+		ret = distro_net_setup(bflow);
+		if (ret)
+			return log_msg_ret("distro", ret);
+	}
+
+	return 0;
+}
+
+struct bootmethod_ops eth_bootmethod_ops = {
+	.get_bootflow	= eth_get_bootflow,
+};
+
+U_BOOT_DRIVER(eth_bootmethod) = {
+	.name		= "eth_bootmethod",
+	.id		= UCLASS_BOOTMETHOD,
+	.ops		= &eth_bootmethod_ops,
+};
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* [PATCH 28/28] RFC: rpi: Switch over to use bootflow
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (26 preceding siblings ...)
  2021-08-19  3:46 ` [PATCH 27/28] ethernet: " Simon Glass
@ 2021-08-19  3:46 ` Simon Glass
  2021-08-19 13:59 ` [PATCH 00/28] Initial implementation of bootmethod/bootflow Tom Rini
  2021-08-23 11:54 ` Mark Kettenis
  29 siblings, 0 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19  3:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Tom Rini,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Simon Glass,
	Matthias Brugger, Stephen Warren, Stephen Warren

Drop the distro boot scripts and use bootflow instead.

Note: This is just a demonstration. It does not support EFI at present.

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

 boot/Kconfig           |  2 +-
 doc/develop/distro.rst |  3 +++
 include/configs/rpi.h  | 37 +------------------------------------
 3 files changed, 5 insertions(+), 37 deletions(-)

diff --git a/boot/Kconfig b/boot/Kconfig
index 8565fbeab84..a1beb182f60 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1011,7 +1011,7 @@ 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 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/doc/develop/distro.rst b/doc/develop/distro.rst
index 105dcf28190..8b26bc1f73b 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/include/configs/rpi.h b/include/configs/rpi.h
index 522b41c02db..d2bac1e1df2 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -161,46 +161,11 @@
 	"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>
-
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \
 	ENV_DEVICE_SETTINGS \
 	ENV_DFU_SETTINGS \
-	ENV_MEM_LAYOUT_SETTINGS \
-	BOOTENV
+	ENV_MEM_LAYOUT_SETTINGS
 
 
 #endif
-- 
2.33.0.rc1.237.g0d66db33f3-goog


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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (27 preceding siblings ...)
  2021-08-19  3:46 ` [PATCH 28/28] RFC: rpi: Switch over to use bootflow Simon Glass
@ 2021-08-19 13:59 ` Tom Rini
  2021-08-19 14:25   ` Simon Glass
  2021-08-23 11:54 ` Mark Kettenis
  29 siblings, 1 reply; 60+ messages in thread
From: Tom Rini @ 2021-08-19 13:59 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

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

On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:

> Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> an Operating System without custom scripting and other customisation:
> 
>   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
>   - bootflow - a description of how to boot (owned by the distro)
> 
> This series provides an initial implementation of these, enable to scan
> for bootflows from MMC and Ethernet. The only bootflow supported is
> distro boot, i.e. an extlinux.conf file included on a filesystem or
> tftp server. 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.
> 
> It is intended that this approach be expanded to support mechanisms other
> than distro boot, including EFI-related ones. With a standard way to
> identify boot devices, these features become easier. It also should
> support U-Boot scripts, for backwards compatibility only.
> 
> The first patch of this series moves boot-related code out of common/ and
> into a new boot/ directory. This helps to collect these related files
> in one place, as common/ is quite large.
> 
> Like sysboot, this feature makes use of the existing PXE implementation.
> Much of this series consists of cleaning up that code and refactoring it
> into something closer to a module that can be called, teasing apart its
> reliance on the command-line interpreter to access filesystems and the
> like. Also it now uses function arguments and its own context struct
> internally rather than environment variables, which is very hard to
> follow. No core functional change is included in the included PXE patches.
> 
> For documentation, see the 'doc' patch.
> 
> There is quite a long list of future work included in the documentation.
> One question is the choice of naming. Since this is a bootloader, should
> we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> shared by other commands like bootm, booti, etc.
> 
> The design is described here:
> 
> https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> 
> The series is available at u-boot-dm/bmea-working

My question / concern is this.  Would the next step here be to
implement the generic UEFI boot path?  Today, I can write Fedora 34 for
AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
automatically boots.  I'm sure I could do the same with the BSDs.
Reading the documentation left me with the impression that every OSV
would be expected to write something, so that their installer / OS boot.
But there's already standards for that, which they do, and we should be
implementing (and do, via the current distro_boot) or making easier to
enable.  Thanks!

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19 13:59 ` [PATCH 00/28] Initial implementation of bootmethod/bootflow Tom Rini
@ 2021-08-19 14:25   ` Simon Glass
  2021-08-19 17:27     ` Tom Rini
  2021-08-20  3:15     ` AKASHI Takahiro
  0 siblings, 2 replies; 60+ messages in thread
From: Simon Glass @ 2021-08-19 14:25 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

Hi Tom,

On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
>
> > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > an Operating System without custom scripting and other customisation:
> >
> >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> >   - bootflow - a description of how to boot (owned by the distro)
> >
> > This series provides an initial implementation of these, enable to scan
> > for bootflows from MMC and Ethernet. The only bootflow supported is
> > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > tftp server. 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.
> >
> > It is intended that this approach be expanded to support mechanisms other
> > than distro boot, including EFI-related ones. With a standard way to
> > identify boot devices, these features become easier. It also should
> > support U-Boot scripts, for backwards compatibility only.
> >
> > The first patch of this series moves boot-related code out of common/ and
> > into a new boot/ directory. This helps to collect these related files
> > in one place, as common/ is quite large.
> >
> > Like sysboot, this feature makes use of the existing PXE implementation.
> > Much of this series consists of cleaning up that code and refactoring it
> > into something closer to a module that can be called, teasing apart its
> > reliance on the command-line interpreter to access filesystems and the
> > like. Also it now uses function arguments and its own context struct
> > internally rather than environment variables, which is very hard to
> > follow. No core functional change is included in the included PXE patches.
> >
> > For documentation, see the 'doc' patch.
> >
> > There is quite a long list of future work included in the documentation.
> > One question is the choice of naming. Since this is a bootloader, should
> > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > shared by other commands like bootm, booti, etc.
> >
> > The design is described here:
> >
> > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> >
> > The series is available at u-boot-dm/bmea-working
>
> My question / concern is this.  Would the next step here be to
> implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> automatically boots.  I'm sure I could do the same with the BSDs.
> Reading the documentation left me with the impression that every OSV
> would be expected to write something, so that their installer / OS boot.
> But there's already standards for that, which they do, and we should be
> implementing (and do, via the current distro_boot) or making easier to
> enable.  Thanks!

Here you are talking about scanning for a bootflow. It is not actually
OS-specific. If it were, there would be no point to this :-)

If you look in the distro scripts you will see 'scan_dev_for_efi' (and
also scan_dev_for_scrips). At least the first needs to be implemented
a bit like the distro boot is at present. So far I have only
implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
the concept.

Adding EFI it's likely to be about the same amount of code as distro.c
at present, perhaps a little less since we don't have the network
case. It is used by Fedora 34, I believe, so is easy enough for me to
do.  But I wanted to get something out as the concept is visible in
this series.

Regards,
Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19 14:25   ` Simon Glass
@ 2021-08-19 17:27     ` Tom Rini
  2021-08-23 12:35       ` Ilias Apalodimas
  2021-08-20  3:15     ` AKASHI Takahiro
  1 sibling, 1 reply; 60+ messages in thread
From: Tom Rini @ 2021-08-19 17:27 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

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

On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> >
> > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > an Operating System without custom scripting and other customisation:
> > >
> > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > >   - bootflow - a description of how to boot (owned by the distro)
> > >
> > > This series provides an initial implementation of these, enable to scan
> > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > tftp server. 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.
> > >
> > > It is intended that this approach be expanded to support mechanisms other
> > > than distro boot, including EFI-related ones. With a standard way to
> > > identify boot devices, these features become easier. It also should
> > > support U-Boot scripts, for backwards compatibility only.
> > >
> > > The first patch of this series moves boot-related code out of common/ and
> > > into a new boot/ directory. This helps to collect these related files
> > > in one place, as common/ is quite large.
> > >
> > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > Much of this series consists of cleaning up that code and refactoring it
> > > into something closer to a module that can be called, teasing apart its
> > > reliance on the command-line interpreter to access filesystems and the
> > > like. Also it now uses function arguments and its own context struct
> > > internally rather than environment variables, which is very hard to
> > > follow. No core functional change is included in the included PXE patches.
> > >
> > > For documentation, see the 'doc' patch.
> > >
> > > There is quite a long list of future work included in the documentation.
> > > One question is the choice of naming. Since this is a bootloader, should
> > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > shared by other commands like bootm, booti, etc.
> > >
> > > The design is described here:
> > >
> > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > >
> > > The series is available at u-boot-dm/bmea-working
> >
> > My question / concern is this.  Would the next step here be to
> > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > automatically boots.  I'm sure I could do the same with the BSDs.
> > Reading the documentation left me with the impression that every OSV
> > would be expected to write something, so that their installer / OS boot.
> > But there's already standards for that, which they do, and we should be
> > implementing (and do, via the current distro_boot) or making easier to
> > enable.  Thanks!
> 
> Here you are talking about scanning for a bootflow. It is not actually
> OS-specific. If it were, there would be no point to this :-)
> 
> If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> also scan_dev_for_scrips). At least the first needs to be implemented
> a bit like the distro boot is at present. So far I have only
> implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> the concept.
> 
> Adding EFI it's likely to be about the same amount of code as distro.c
> at present, perhaps a little less since we don't have the network
> case. It is used by Fedora 34, I believe, so is easy enough for me to
> do.  But I wanted to get something out as the concept is visible in
> this series.

OK, good.  I'd certainly like to see how this looks with EFI added.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19 14:25   ` Simon Glass
  2021-08-19 17:27     ` Tom Rini
@ 2021-08-20  3:15     ` AKASHI Takahiro
  2021-08-20 18:22       ` Simon Glass
  1 sibling, 1 reply; 60+ messages in thread
From: AKASHI Takahiro @ 2021-08-20  3:15 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

Hi Simon,

On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> >
> > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > an Operating System without custom scripting and other customisation:
> > >
> > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > >   - bootflow - a description of how to boot (owned by the distro)
> > >
> > > This series provides an initial implementation of these, enable to scan
> > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > tftp server. 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.
> > >
> > > It is intended that this approach be expanded to support mechanisms other
> > > than distro boot, including EFI-related ones. With a standard way to
> > > identify boot devices, these features become easier. It also should
> > > support U-Boot scripts, for backwards compatibility only.
> > >
> > > The first patch of this series moves boot-related code out of common/ and
> > > into a new boot/ directory. This helps to collect these related files
> > > in one place, as common/ is quite large.
> > >
> > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > Much of this series consists of cleaning up that code and refactoring it
> > > into something closer to a module that can be called, teasing apart its
> > > reliance on the command-line interpreter to access filesystems and the
> > > like. Also it now uses function arguments and its own context struct
> > > internally rather than environment variables, which is very hard to
> > > follow. No core functional change is included in the included PXE patches.
> > >
> > > For documentation, see the 'doc' patch.
> > >
> > > There is quite a long list of future work included in the documentation.
> > > One question is the choice of naming. Since this is a bootloader, should
> > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > shared by other commands like bootm, booti, etc.

Regarding the naming, I'm still a bit confused with bootmethod vs.
bootflow. Personally, I prefer a more intuitive name against bootmethod,
say, bootmedia or bootdevice (as the original distro_bootcmd uses).

> > > The design is described here:
> > >
> > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > >
> > > The series is available at u-boot-dm/bmea-working
> >
> > My question / concern is this.  Would the next step here be to
> > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > automatically boots.  I'm sure I could do the same with the BSDs.
> > Reading the documentation left me with the impression that every OSV
> > would be expected to write something, so that their installer / OS boot.
> > But there's already standards for that, which they do, and we should be
> > implementing (and do, via the current distro_boot) or making easier to
> > enable.  Thanks!

I had the same concern.

> Here you are talking about scanning for a bootflow. It is not actually
> OS-specific. If it were, there would be no point to this :-)
> 
> If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> also scan_dev_for_scrips). At least the first needs to be implemented
> a bit like the distro boot is at present. So far I have only
> implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> the concept.
> 
> Adding EFI it's likely to be about the same amount of code as distro.c
> at present, perhaps a little less since we don't have the network
> case. It is used by Fedora 34, I believe, so is easy enough for me to
> do.  But I wanted to get something out as the concept is visible in
> this series.

If I correctly understand this framework, we will have to
write several functions:
(Here I will ignore "UEFI boot manager" sequence.)

1)boot/distro_efi.c
   distro_boot_efi_setup()  ; almost the same as distro_boot_setup()
   distro_boot_efi()        ; search for /EFI/BOOT/BOOTAA64.EFI (and dtb)

2)boot/bootflow.c
   bootmethod_find_efi_in_blk()
      call distro_boot_efi_setup()
   bootflow_boot()
      CASE BOOTFLOWT_DISTRO_EFI: ; new bootflow type
          call distro_boot_efi()

3)drivers/mmc/mmc_bootmethod.c
   mmc_efi_get_bootflow()
      call bootmethod_find_efi_in_blk()
   U_BOOT_DRIVER(mmc_efi_bootmethod) =
      .name           = "mmc_efi_bootmethod",
      .id             = UCLASS_BOOTMETHOD,

4)drivers/mm/Makefile
   obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += mmc_bootmethod.o mmc_efi_bootmethod.o

Do you think that the above is correct?
If so, does (3) (+ (1)/(2)) inevitably increase the code size
as we need functions for all devices?

-Takahiro Akashi


> Regards,
> Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-20  3:15     ` AKASHI Takahiro
@ 2021-08-20 18:22       ` Simon Glass
  2021-08-23  0:46         ` AKASHI Takahiro
  0 siblings, 1 reply; 60+ messages in thread
From: Simon Glass @ 2021-08-20 18:22 UTC (permalink / raw)
  To: AKASHI Takahiro, Simon Glass, Tom Rini, U-Boot Mailing List,
	Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Dennis Gilmore,
	Daniel Schwierzeck, Lukas Auer, Jaehoon Chung, Matthias Brugger,
	Peng Fan, Stephen Warren, Stephen Warren

Hi Takahiro,

On Thu, 19 Aug 2021 at 21:15, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Hi Simon,
>
> On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> > >
> > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > an Operating System without custom scripting and other customisation:
> > > >
> > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > >   - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > This series provides an initial implementation of these, enable to scan
> > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > tftp server. 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.
> > > >
> > > > It is intended that this approach be expanded to support mechanisms other
> > > > than distro boot, including EFI-related ones. With a standard way to
> > > > identify boot devices, these features become easier. It also should
> > > > support U-Boot scripts, for backwards compatibility only.
> > > >
> > > > The first patch of this series moves boot-related code out of common/ and
> > > > into a new boot/ directory. This helps to collect these related files
> > > > in one place, as common/ is quite large.
> > > >
> > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > Much of this series consists of cleaning up that code and refactoring it
> > > > into something closer to a module that can be called, teasing apart its
> > > > reliance on the command-line interpreter to access filesystems and the
> > > > like. Also it now uses function arguments and its own context struct
> > > > internally rather than environment variables, which is very hard to
> > > > follow. No core functional change is included in the included PXE patches.
> > > >
> > > > For documentation, see the 'doc' patch.
> > > >
> > > > There is quite a long list of future work included in the documentation.
> > > > One question is the choice of naming. Since this is a bootloader, should
> > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > shared by other commands like bootm, booti, etc.
>
> Regarding the naming, I'm still a bit confused with bootmethod vs.
> bootflow. Personally, I prefer a more intuitive name against bootmethod,
> say, bootmedia or bootdevice (as the original distro_bootcmd uses).

I quite like bootmedia. Would just 'media' be OK? That would reduce
the use of the 'boot' prefix which I think is overused.

>
> > > > The design is described here:
> > > >
> > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > >
> > > > The series is available at u-boot-dm/bmea-working
> > >
> > > My question / concern is this.  Would the next step here be to
> > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > Reading the documentation left me with the impression that every OSV
> > > would be expected to write something, so that their installer / OS boot.
> > > But there's already standards for that, which they do, and we should be
> > > implementing (and do, via the current distro_boot) or making easier to
> > > enable.  Thanks!
>
> I had the same concern.

OK see my reply to Tom on this point. The separate of concerns between
providing media and booting an OS is a key purpose of this series.

I have Fedora 34 in my lab and will send an update for it next week.

>
> > Here you are talking about scanning for a bootflow. It is not actually
> > OS-specific. If it were, there would be no point to this :-)
> >
> > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > also scan_dev_for_scrips). At least the first needs to be implemented
> > a bit like the distro boot is at present. So far I have only
> > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > the concept.
> >
> > Adding EFI it's likely to be about the same amount of code as distro.c
> > at present, perhaps a little less since we don't have the network
> > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > do.  But I wanted to get something out as the concept is visible in
> > this series.
>
> If I correctly understand this framework, we will have to
> write several functions:
> (Here I will ignore "UEFI boot manager" sequence.)
>
> 1)boot/distro_efi.c
>    distro_boot_efi_setup()  ; almost the same as distro_boot_setup()
>    distro_boot_efi()        ; search for /EFI/BOOT/BOOTAA64.EFI (and dtb)

Yes

>
> 2)boot/bootflow.c
>    bootmethod_find_efi_in_blk()
>       call distro_boot_efi_setup()
>    bootflow_boot()
>       CASE BOOTFLOWT_DISTRO_EFI: ; new bootflow type
>           call distro_boot_efi()

Yes

>
> 3)drivers/mmc/mmc_bootmethod.c
>    mmc_efi_get_bootflow()
>       call bootmethod_find_efi_in_blk()
>    U_BOOT_DRIVER(mmc_efi_bootmethod) =
>       .name           = "mmc_efi_bootmethod",
>       .id             = UCLASS_BOOTMETHOD,

No, this is not needed. Bootmethod provides the media so we don't have
a separate one for EFI. It is the bootflow detection that needs to be
changed (as above).

>
> 4)drivers/mm/Makefile
>    obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += mmc_bootmethod.o mmc_efi_bootmethod.o

No, this is not needed.

See also the todo at the end of the bootflow docs. One day we may want
to expand add sort of interface for locating the files, instead of
calling it directly from bootflow.

>
> Do you think that the above is correct?
> If so, does (3) (+ (1)/(2)) inevitably increase the code size
> as we need functions for all devices?

Yes, of course any feature increases the code size., although I'd
argue this is a feature that could/should have been added instead of
the scripts approach. It is much easier to understand and test.

BTW you can try this out with sandbox.

$ u-boot -T
=> bootmethod list
=> bootflow scan

etc.

Regards,
Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-20 18:22       ` Simon Glass
@ 2021-08-23  0:46         ` AKASHI Takahiro
  0 siblings, 0 replies; 60+ messages in thread
From: AKASHI Takahiro @ 2021-08-23  0:46 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

On Fri, Aug 20, 2021 at 12:22:17PM -0600, Simon Glass wrote:
> Hi Takahiro,
> 
> On Thu, 19 Aug 2021 at 21:15, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> > > >
> > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > an Operating System without custom scripting and other customisation:
> > > > >
> > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > >
> > > > > This series provides an initial implementation of these, enable to scan
> > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > tftp server. 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.
> > > > >
> > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > identify boot devices, these features become easier. It also should
> > > > > support U-Boot scripts, for backwards compatibility only.
> > > > >
> > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > into a new boot/ directory. This helps to collect these related files
> > > > > in one place, as common/ is quite large.
> > > > >
> > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > into something closer to a module that can be called, teasing apart its
> > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > like. Also it now uses function arguments and its own context struct
> > > > > internally rather than environment variables, which is very hard to
> > > > > follow. No core functional change is included in the included PXE patches.
> > > > >
> > > > > For documentation, see the 'doc' patch.
> > > > >
> > > > > There is quite a long list of future work included in the documentation.
> > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > shared by other commands like bootm, booti, etc.
> >
> > Regarding the naming, I'm still a bit confused with bootmethod vs.
> > bootflow. Personally, I prefer a more intuitive name against bootmethod,
> > say, bootmedia or bootdevice (as the original distro_bootcmd uses).
> 
> I quite like bootmedia. Would just 'media' be OK? That would reduce
> the use of the 'boot' prefix which I think is overused.

If 'boot' prefix is removed, I'm afraid that the word, either media,
method or flow, sounds quite generic and so ambiguous.
As far as the commands are concerned, on the other hand, it might be
one way to have sub-commands under 'boot', like "boot media ..." or
"boot flow ..." although I'm not sure it is a preferred style on U-Boot.

# I have no strong opinion here.

> >
> > > > > The design is described here:
> > > > >
> > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > >
> > > > > The series is available at u-boot-dm/bmea-working
> > > >
> > > > My question / concern is this.  Would the next step here be to
> > > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > > Reading the documentation left me with the impression that every OSV
> > > > would be expected to write something, so that their installer / OS boot.
> > > > But there's already standards for that, which they do, and we should be
> > > > implementing (and do, via the current distro_boot) or making easier to
> > > > enable.  Thanks!
> >
> > I had the same concern.
> 
> OK see my reply to Tom on this point. The separate of concerns between
> providing media and booting an OS is a key purpose of this series.
> 
> I have Fedora 34 in my lab and will send an update for it next week.
> 
> >
> > > Here you are talking about scanning for a bootflow. It is not actually
> > > OS-specific. If it were, there would be no point to this :-)
> > >
> > > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > > also scan_dev_for_scrips). At least the first needs to be implemented
> > > a bit like the distro boot is at present. So far I have only
> > > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > > the concept.
> > >
> > > Adding EFI it's likely to be about the same amount of code as distro.c
> > > at present, perhaps a little less since we don't have the network
> > > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > > do.  But I wanted to get something out as the concept is visible in
> > > this series.
> >
> > If I correctly understand this framework, we will have to
> > write several functions:
> > (Here I will ignore "UEFI boot manager" sequence.)
> >
> > 1)boot/distro_efi.c
> >    distro_boot_efi_setup()  ; almost the same as distro_boot_setup()
> >    distro_boot_efi()        ; search for /EFI/BOOT/BOOTAA64.EFI (and dtb)
> 
> Yes
> 
> >
> > 2)boot/bootflow.c
> >    bootmethod_find_efi_in_blk()
> >       call distro_boot_efi_setup()
> >    bootflow_boot()
> >       CASE BOOTFLOWT_DISTRO_EFI: ; new bootflow type
> >           call distro_boot_efi()
> 
> Yes
> 
> >
> > 3)drivers/mmc/mmc_bootmethod.c
> >    mmc_efi_get_bootflow()
> >       call bootmethod_find_efi_in_blk()
> >    U_BOOT_DRIVER(mmc_efi_bootmethod) =
> >       .name           = "mmc_efi_bootmethod",
> >       .id             = UCLASS_BOOTMETHOD,
> 
> No, this is not needed. Bootmethod provides the media so we don't have
> a separate one for EFI. It is the bootflow detection that needs to be
> changed (as above).

Well, this is what I didn't really understand. How are all the boot flows
enumerated? Looking at do_bootflow_scan(),
        for (i = 0, ret = 0; i < 100 && ret != -ESHUTDOWN; i++) {
                ret = bootmethod_get_bootflow(dev, i, &bflow);

Here, the second argument, i (or seq), is used to indicate a partition
number. So how can we add more than one bootflow to the same bootmethod
(bootmedia in my language :)?

-Takahiro Akashi

> >
> > 4)drivers/mm/Makefile
> >    obj-$(CONFIG_$(SPL_TPL_)BOOTMETHOD) += mmc_bootmethod.o mmc_efi_bootmethod.o
> 
> No, this is not needed.
> 
> See also the todo at the end of the bootflow docs. One day we may want
> to expand add sort of interface for locating the files, instead of
> calling it directly from bootflow.
> 
> >
> > Do you think that the above is correct?
> > If so, does (3) (+ (1)/(2)) inevitably increase the code size
> > as we need functions for all devices?
> 
> Yes, of course any feature increases the code size., although I'd
> argue this is a feature that could/should have been added instead of
> the scripts approach. It is much easier to understand and test.
> 
> BTW you can try this out with sandbox.
> 
> $ u-boot -T
> => bootmethod list
> => bootflow scan
> 
> etc.
> 
> Regards,
> Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
                   ` (28 preceding siblings ...)
  2021-08-19 13:59 ` [PATCH 00/28] Initial implementation of bootmethod/bootflow Tom Rini
@ 2021-08-23 11:54 ` Mark Kettenis
  2021-08-23 17:25   ` Simon Glass
  29 siblings, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-23 11:54 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, ilias.apalodimas, jaeckel-floss, michal.simek, trini,
	dennis, daniel.schwierzeck, lukas.auer, sjg, jh80.chung,
	mbrugger, peng.fan, swarren, swarren

> From: Simon Glass <sjg@chromium.org>
> Date: Wed, 18 Aug 2021 21:45:33 -0600
> 
> Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> an Operating System without custom scripting and other customisation:
> 
>   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
>   - bootflow - a description of how to boot (owned by the distro)
> 
> This series provides an initial implementation of these, enable to scan
> for bootflows from MMC and Ethernet. The only bootflow supported is
> distro boot, i.e. an extlinux.conf file included on a filesystem or
> tftp server. 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.
> 
> It is intended that this approach be expanded to support mechanisms other
> than distro boot, including EFI-related ones. With a standard way to
> identify boot devices, these features become easier. It also should
> support U-Boot scripts, for backwards compatibility only.
> 
> The first patch of this series moves boot-related code out of common/ and
> into a new boot/ directory. This helps to collect these related files
> in one place, as common/ is quite large.
> 
> Like sysboot, this feature makes use of the existing PXE implementation.
> Much of this series consists of cleaning up that code and refactoring it
> into something closer to a module that can be called, teasing apart its
> reliance on the command-line interpreter to access filesystems and the
> like. Also it now uses function arguments and its own context struct
> internally rather than environment variables, which is very hard to
> follow. No core functional change is included in the included PXE patches.
> 
> For documentation, see the 'doc' patch.
> 
> There is quite a long list of future work included in the documentation.
> One question is the choice of naming. Since this is a bootloader, should
> we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> shared by other commands like bootm, booti, etc.
> 
> The design is described here:
> 
> https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> 
> The series is available at u-boot-dm/bmea-working

How does the user control the order in which devices are scanned/booted?

And how do we define the default order?

> Simon Glass (28):
>   Create a new boot/ directory
>   pxe: Move API comments to the header files
>   pxe: Use a context pointer
>   pxe: Move do_getfile() into the context
>   pxe: Add a userdata field to the context
>   pxe: Tidy up the is_pxe global
>   pxe: Move pxe_utils files
>   pxe: Tidy up some comments in pxe_utils
>   pxe: Tidy up code style a little in pxe_utils
>   pxe: Move common parsing coding into pxe_util
>   pxe: Clean up the use of bootfile
>   pxe: Drop get_bootfile_path()
>   lib: Add tests for simple_itoa()
>   lib: Add a function to convert a string to a hex value
>   pxe: Return the file size from the getfile() function
>   pxe: Refactor sysboot to have one helper
>   doc: Move distro boot doc to rST
>   pxe: Allow calling the pxe_get logic directly
>   bootmethod: Add the uclass and core implementation
>   bootmethod: Add an implementation of distro boot
>   bootmethod: Add a command
>   bootflow: Add a command
>   bootmethod: Add tests for bootmethod and bootflow
>   bootmethod: doc: Add documentation
>   mmc: Allow for children other than the block device
>   mmc: Add a bootmethod
>   ethernet: Add a bootmethod
>   RFC: rpi: Switch over to use bootflow
> 
>  Kconfig                                   |   2 +
>  MAINTAINERS                               |  16 +
>  Makefile                                  |   3 +-
>  README                                    |   1 +
>  common/Kconfig.boot => boot/Kconfig       |  22 +-
>  boot/Makefile                             |  39 ++
>  {common => boot}/android_ab.c             |   0
>  {common => boot}/boot_fit.c               |   0
>  {common => boot}/bootm.c                  |   0
>  {common => boot}/bootm_os.c               |   0
>  boot/bootmethod.c                         | 485 ++++++++++++++++++++
>  {common => boot}/bootretry.c              |   0
>  {common => boot}/common_fit.c             |   0
>  boot/distro.c                             | 194 ++++++++
>  {common => boot}/fdt_region.c             |   0
>  {common => boot}/image-android-dt.c       |   0
>  {common => boot}/image-android.c          |   0
>  {common => boot}/image-cipher.c           |   0
>  {common => boot}/image-fdt.c              |   0
>  {common => boot}/image-fit-sig.c          |   0
>  {common => boot}/image-fit.c              |   0
>  {common => boot}/image-sig.c              |   0
>  {common => boot}/image.c                  |   0
>  {cmd => boot}/pxe_utils.c                 | 512 +++++++++++-----------
>  cmd/Kconfig                               |   8 +
>  cmd/Makefile                              |   5 +-
>  cmd/bootflow.c                            | 399 +++++++++++++++++
>  cmd/bootmethod.c                          | 130 ++++++
>  cmd/pxe.c                                 | 136 +++---
>  cmd/pxe_utils.h                           |  91 ----
>  cmd/sysboot.c                             | 114 +++--
>  common/Kconfig                            |   2 -
>  common/Makefile                           |  22 -
>  configs/sandbox_defconfig                 |   3 +-
>  doc/android/boot-image.rst                |   2 +-
>  doc/develop/bootflow.rst                  | 323 ++++++++++++++
>  doc/{README.distro => develop/distro.rst} | 180 ++++----
>  doc/develop/index.rst                     |   2 +
>  doc/device-tree-bindings/bootmethod.txt   |  14 +
>  doc/usage/bootflow.rst                    | 419 ++++++++++++++++++
>  doc/usage/bootmethod.rst                  | 138 ++++++
>  doc/usage/index.rst                       |   2 +
>  drivers/mmc/Makefile                      |   5 +
>  drivers/mmc/mmc-uclass.c                  |  23 +-
>  drivers/mmc/mmc_bootmethod.c              |  46 ++
>  include/bootmethod.h                      | 357 +++++++++++++++
>  include/configs/rpi.h                     |  37 +-
>  include/distro.h                          |  62 +++
>  include/dm/uclass-id.h                    |   1 +
>  include/mmc.h                             |  12 +-
>  include/pxe_utils.h                       | 253 +++++++++++
>  include/test/suites.h                     |   2 +
>  include/vsprintf.h                        |  25 +-
>  lib/vsprintf.c                            |  20 +-
>  net/Kconfig                               |   9 +
>  net/Makefile                              |   1 +
>  net/eth-uclass.c                          |   8 +
>  net/eth_bootmethod.c                      |  76 ++++
>  scripts/Makefile.spl                      |   4 +-
>  test/Makefile                             |   1 +
>  test/boot/Makefile                        |   5 +
>  test/boot/bootmethod.c                    | 271 ++++++++++++
>  test/cmd_ut.c                             |   4 +
>  test/print_ut.c                           |  33 ++
>  tools/Makefile                            |  16 +-
>  try.sh                                    | 131 ++++++
>  66 files changed, 4035 insertions(+), 631 deletions(-)
>  rename common/Kconfig.boot => boot/Kconfig (98%)
>  create mode 100644 boot/Makefile
>  rename {common => boot}/android_ab.c (100%)
>  rename {common => boot}/boot_fit.c (100%)
>  rename {common => boot}/bootm.c (100%)
>  rename {common => boot}/bootm_os.c (100%)
>  create mode 100644 boot/bootmethod.c
>  rename {common => boot}/bootretry.c (100%)
>  rename {common => boot}/common_fit.c (100%)
>  create mode 100644 boot/distro.c
>  rename {common => boot}/fdt_region.c (100%)
>  rename {common => boot}/image-android-dt.c (100%)
>  rename {common => boot}/image-android.c (100%)
>  rename {common => boot}/image-cipher.c (100%)
>  rename {common => boot}/image-fdt.c (100%)
>  rename {common => boot}/image-fit-sig.c (100%)
>  rename {common => boot}/image-fit.c (100%)
>  rename {common => boot}/image-sig.c (100%)
>  rename {common => boot}/image.c (100%)
>  rename {cmd => boot}/pxe_utils.c (74%)
>  create mode 100644 cmd/bootflow.c
>  create mode 100644 cmd/bootmethod.c
>  delete mode 100644 cmd/pxe_utils.h
>  create mode 100644 doc/develop/bootflow.rst
>  rename doc/{README.distro => develop/distro.rst} (76%)
>  create mode 100644 doc/device-tree-bindings/bootmethod.txt
>  create mode 100644 doc/usage/bootflow.rst
>  create mode 100644 doc/usage/bootmethod.rst
>  create mode 100644 drivers/mmc/mmc_bootmethod.c
>  create mode 100644 include/bootmethod.h
>  create mode 100644 include/distro.h
>  create mode 100644 include/pxe_utils.h
>  create mode 100644 net/eth_bootmethod.c
>  create mode 100644 test/boot/Makefile
>  create mode 100644 test/boot/bootmethod.c
>  create mode 100755 try.sh
> 
> -- 
> 2.33.0.rc1.237.g0d66db33f3-goog
> 
> 

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-19 17:27     ` Tom Rini
@ 2021-08-23 12:35       ` Ilias Apalodimas
  2021-08-23 17:25         ` Simon Glass
  0 siblings, 1 reply; 60+ messages in thread
From: Ilias Apalodimas @ 2021-08-23 12:35 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, U-Boot Mailing List, Steffen Jaeckel, Michal Simek,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Jaehoon Chung,
	Matthias Brugger, Peng Fan, Stephen Warren, Stephen Warren

On Thu, Aug 19, 2021 at 01:27:50PM -0400, Tom Rini wrote:
> On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> > Hi Tom,
> > 
> > On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> > >
> > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > an Operating System without custom scripting and other customisation:
> > > >
> > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > >   - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > This series provides an initial implementation of these, enable to scan
> > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > tftp server. 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.
> > > >
> > > > It is intended that this approach be expanded to support mechanisms other
> > > > than distro boot, including EFI-related ones. With a standard way to
> > > > identify boot devices, these features become easier. It also should
> > > > support U-Boot scripts, for backwards compatibility only.
> > > >
> > > > The first patch of this series moves boot-related code out of common/ and
> > > > into a new boot/ directory. This helps to collect these related files
> > > > in one place, as common/ is quite large.
> > > >
> > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > Much of this series consists of cleaning up that code and refactoring it
> > > > into something closer to a module that can be called, teasing apart its
> > > > reliance on the command-line interpreter to access filesystems and the
> > > > like. Also it now uses function arguments and its own context struct
> > > > internally rather than environment variables, which is very hard to
> > > > follow. No core functional change is included in the included PXE patches.
> > > >
> > > > For documentation, see the 'doc' patch.
> > > >
> > > > There is quite a long list of future work included in the documentation.
> > > > One question is the choice of naming. Since this is a bootloader, should
> > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > shared by other commands like bootm, booti, etc.
> > > >
> > > > The design is described here:
> > > >
> > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > >
> > > > The series is available at u-boot-dm/bmea-working
> > >
> > > My question / concern is this.  Would the next step here be to
> > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > Reading the documentation left me with the impression that every OSV
> > > would be expected to write something, so that their installer / OS boot.
> > > But there's already standards for that, which they do, and we should be
> > > implementing (and do, via the current distro_boot) or making easier to
> > > enable.  Thanks!
> > 
> > Here you are talking about scanning for a bootflow. It is not actually
> > OS-specific. If it were, there would be no point to this :-)
> > 
> > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > also scan_dev_for_scrips). At least the first needs to be implemented
> > a bit like the distro boot is at present. So far I have only
> > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > the concept.
> > 
> > Adding EFI it's likely to be about the same amount of code as distro.c
> > at present, perhaps a little less since we don't have the network
> > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > do.  But I wanted to get something out as the concept is visible in
> > this series.
> 
> OK, good.  I'd certainly like to see how this looks with EFI added.
> 

What would be the order preference after scanning?

Keep in mind that our efibootmgr is pretty complete wrt to booting.
It can even support booting multiple OS'es without GRUB2 (even loading
different initrds is supported).  Ideally (and assuming we want to support 
EFI booting for more devices), I would map existing extlinux configs into 
efibootmgr entries. 


Regards
/Ilias
> -- 
> Tom



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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 12:35       ` Ilias Apalodimas
@ 2021-08-23 17:25         ` Simon Glass
  2021-08-23 20:08           ` Tom Rini
  0 siblings, 1 reply; 60+ messages in thread
From: Simon Glass @ 2021-08-23 17:25 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, U-Boot Mailing List, Steffen Jaeckel, Michal Simek,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Jaehoon Chung,
	Matthias Brugger, Peng Fan, Stephen Warren, Stephen Warren

Hi Ilias,

On Mon, 23 Aug 2021 at 06:35, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Thu, Aug 19, 2021 at 01:27:50PM -0400, Tom Rini wrote:
> > On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> > > >
> > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > an Operating System without custom scripting and other customisation:
> > > > >
> > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > >
> > > > > This series provides an initial implementation of these, enable to scan
> > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > tftp server. 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.
> > > > >
> > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > identify boot devices, these features become easier. It also should
> > > > > support U-Boot scripts, for backwards compatibility only.
> > > > >
> > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > into a new boot/ directory. This helps to collect these related files
> > > > > in one place, as common/ is quite large.
> > > > >
> > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > into something closer to a module that can be called, teasing apart its
> > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > like. Also it now uses function arguments and its own context struct
> > > > > internally rather than environment variables, which is very hard to
> > > > > follow. No core functional change is included in the included PXE patches.
> > > > >
> > > > > For documentation, see the 'doc' patch.
> > > > >
> > > > > There is quite a long list of future work included in the documentation.
> > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > shared by other commands like bootm, booti, etc.
> > > > >
> > > > > The design is described here:
> > > > >
> > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > >
> > > > > The series is available at u-boot-dm/bmea-working
> > > >
> > > > My question / concern is this.  Would the next step here be to
> > > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > > Reading the documentation left me with the impression that every OSV
> > > > would be expected to write something, so that their installer / OS boot.
> > > > But there's already standards for that, which they do, and we should be
> > > > implementing (and do, via the current distro_boot) or making easier to
> > > > enable.  Thanks!
> > >
> > > Here you are talking about scanning for a bootflow. It is not actually
> > > OS-specific. If it were, there would be no point to this :-)
> > >
> > > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > > also scan_dev_for_scrips). At least the first needs to be implemented
> > > a bit like the distro boot is at present. So far I have only
> > > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > > the concept.
> > >
> > > Adding EFI it's likely to be about the same amount of code as distro.c
> > > at present, perhaps a little less since we don't have the network
> > > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > > do.  But I wanted to get something out as the concept is visible in
> > > this series.
> >
> > OK, good.  I'd certainly like to see how this looks with EFI added.
> >
>
> What would be the order preference after scanning?

(from other thread)
With distro boot this is done with an environment variable, as I
understand it. That is not implemented in this series, but is easy to
do and is in the TODO. For now it can only be done with aliases to set
the order of the bootmethods and that requires adding to the DT, so I
don't think it scales well. I'm open to ideas though.

>
> Keep in mind that our efibootmgr is pretty complete wrt to booting.
> It can even support booting multiple OS'es without GRUB2 (even loading
> different initrds is supported).  Ideally (and assuming we want to support
> EFI booting for more devices), I would map existing extlinux configs into
> efibootmgr entries.

Yes I understand. I believe distro boot supports multiple OSes too,
but perhaps only on different media? I'm not sure. Anywayt ere are
always going to be people who don't want or need to use EFI (or grub)
and it would be nice to support both seamlessly with the same
concepts. From my side, my objective here is to provide suitable
frameworks for:

- locating devices we can boot from (via 'bootmethod' drivers)
- locating instructions from OSes to boot (called 'bootflows')

There are core features for a bootloader and U-Boot should probably
have had them some time ago.

From what I can tell, we can make substantial improvements to the
integration of the EFI code within U-Boot, particularly when the DM
migrations are done. I see bootmethod/bootflow as part of that.

BTW in the other direction, I have a prototype of U-Boot booting on
EFI and accessing EFI devices from which to boot. It is based on
Heinrich's work for iSCSI.

Regards,
Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 11:54 ` Mark Kettenis
@ 2021-08-23 17:25   ` Simon Glass
  2021-08-23 20:01     ` Tom Rini
  0 siblings, 1 reply; 60+ messages in thread
From: Simon Glass @ 2021-08-23 17:25 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Tom Rini, Dennis Gilmore, Daniel Schwierzeck,
	Lukas Auer, Jaehoon Chung, Matthias Brugger, Peng Fan,
	Stephen Warren, Stephen Warren

Hi Mark,

On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>
> > From: Simon Glass <sjg@chromium.org>
> > Date: Wed, 18 Aug 2021 21:45:33 -0600
> >
> > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > an Operating System without custom scripting and other customisation:
> >
> >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> >   - bootflow - a description of how to boot (owned by the distro)
> >
> > This series provides an initial implementation of these, enable to scan
> > for bootflows from MMC and Ethernet. The only bootflow supported is
> > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > tftp server. 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.
> >
> > It is intended that this approach be expanded to support mechanisms other
> > than distro boot, including EFI-related ones. With a standard way to
> > identify boot devices, these features become easier. It also should
> > support U-Boot scripts, for backwards compatibility only.
> >
> > The first patch of this series moves boot-related code out of common/ and
> > into a new boot/ directory. This helps to collect these related files
> > in one place, as common/ is quite large.
> >
> > Like sysboot, this feature makes use of the existing PXE implementation.
> > Much of this series consists of cleaning up that code and refactoring it
> > into something closer to a module that can be called, teasing apart its
> > reliance on the command-line interpreter to access filesystems and the
> > like. Also it now uses function arguments and its own context struct
> > internally rather than environment variables, which is very hard to
> > follow. No core functional change is included in the included PXE patches.
> >
> > For documentation, see the 'doc' patch.
> >
> > There is quite a long list of future work included in the documentation.
> > One question is the choice of naming. Since this is a bootloader, should
> > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > shared by other commands like bootm, booti, etc.
> >
> > The design is described here:
> >
> > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> >
> > The series is available at u-boot-dm/bmea-working
>
> How does the user control the order in which devices are scanned/booted?

That is not supported in distroboot at present, at least so far as I
can see. For Fedora it seems to happen in grub. Do I have that right?

Anyway this feature is beyond scope of the current series, which is
just to put in the basic plumbing. We need a non-volatile config file
to hold this information (in VBE this is called NVdata).

>
> And how do we define the default order?

With distro boot this is done with an environment variable, as I
understand it. That is not implemented in this series, but is easy to
do and is in the TODO. For now it can only be done with aliases to set
the order of the bootmethods and that requires adding to the DT, so I
don't think it scales well. I'm open to ideas though.

Regards,
SImon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 17:25   ` Simon Glass
@ 2021-08-23 20:01     ` Tom Rini
  2021-08-24 10:22       ` Mark Kettenis
  0 siblings, 1 reply; 60+ messages in thread
From: Tom Rini @ 2021-08-23 20:01 UTC (permalink / raw)
  To: Simon Glass
  Cc: Mark Kettenis, U-Boot Mailing List, Ilias Apalodimas,
	Steffen Jaeckel, Michal Simek, Dennis Gilmore,
	Daniel Schwierzeck, Lukas Auer, Jaehoon Chung, Matthias Brugger,
	Peng Fan, Stephen Warren, Stephen Warren

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

On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> Hi Mark,
> 
> On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> >
> > > From: Simon Glass <sjg@chromium.org>
> > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > >
> > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > an Operating System without custom scripting and other customisation:
> > >
> > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > >   - bootflow - a description of how to boot (owned by the distro)
> > >
> > > This series provides an initial implementation of these, enable to scan
> > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > tftp server. 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.
> > >
> > > It is intended that this approach be expanded to support mechanisms other
> > > than distro boot, including EFI-related ones. With a standard way to
> > > identify boot devices, these features become easier. It also should
> > > support U-Boot scripts, for backwards compatibility only.
> > >
> > > The first patch of this series moves boot-related code out of common/ and
> > > into a new boot/ directory. This helps to collect these related files
> > > in one place, as common/ is quite large.
> > >
> > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > Much of this series consists of cleaning up that code and refactoring it
> > > into something closer to a module that can be called, teasing apart its
> > > reliance on the command-line interpreter to access filesystems and the
> > > like. Also it now uses function arguments and its own context struct
> > > internally rather than environment variables, which is very hard to
> > > follow. No core functional change is included in the included PXE patches.
> > >
> > > For documentation, see the 'doc' patch.
> > >
> > > There is quite a long list of future work included in the documentation.
> > > One question is the choice of naming. Since this is a bootloader, should
> > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > shared by other commands like bootm, booti, etc.
> > >
> > > The design is described here:
> > >
> > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > >
> > > The series is available at u-boot-dm/bmea-working
> >
> > How does the user control the order in which devices are scanned/booted?
> 
> That is not supported in distroboot at present, at least so far as I
> can see. For Fedora it seems to happen in grub. Do I have that right?

Well, there's "find the next stage", which is boot_targets environment
variable, and then "where that next stage looks for stuff" which is
OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
grub to find the full grub.cfg file elsewhere, and sometimes it's a full
grub.cfg file.  I think Mark is talking about the former, and you've
said it's not part of this series, yet, but on the TODO list.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 17:25         ` Simon Glass
@ 2021-08-23 20:08           ` Tom Rini
  2021-08-24  9:29             ` Ilias Apalodimas
  0 siblings, 1 reply; 60+ messages in thread
From: Tom Rini @ 2021-08-23 20:08 UTC (permalink / raw)
  To: Simon Glass
  Cc: Ilias Apalodimas, U-Boot Mailing List, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

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

On Mon, Aug 23, 2021 at 11:25:40AM -0600, Simon Glass wrote:
> Hi Ilias,
> 
> On Mon, 23 Aug 2021 at 06:35, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > On Thu, Aug 19, 2021 at 01:27:50PM -0400, Tom Rini wrote:
> > > On Thu, Aug 19, 2021 at 08:25:33AM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Thu, 19 Aug 2021 at 07:59, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Wed, Aug 18, 2021 at 09:45:33PM -0600, Simon Glass wrote:
> > > > >
> > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > an Operating System without custom scripting and other customisation:
> > > > > >
> > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > >
> > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > tftp server. 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.
> > > > > >
> > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > identify boot devices, these features become easier. It also should
> > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > >
> > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > in one place, as common/ is quite large.
> > > > > >
> > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > internally rather than environment variables, which is very hard to
> > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > >
> > > > > > For documentation, see the 'doc' patch.
> > > > > >
> > > > > > There is quite a long list of future work included in the documentation.
> > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > shared by other commands like bootm, booti, etc.
> > > > > >
> > > > > > The design is described here:
> > > > > >
> > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > >
> > > > > > The series is available at u-boot-dm/bmea-working
> > > > >
> > > > > My question / concern is this.  Would the next step here be to
> > > > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > > > Reading the documentation left me with the impression that every OSV
> > > > > would be expected to write something, so that their installer / OS boot.
> > > > > But there's already standards for that, which they do, and we should be
> > > > > implementing (and do, via the current distro_boot) or making easier to
> > > > > enable.  Thanks!
> > > >
> > > > Here you are talking about scanning for a bootflow. It is not actually
> > > > OS-specific. If it were, there would be no point to this :-)
> > > >
> > > > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > > > also scan_dev_for_scrips). At least the first needs to be implemented
> > > > a bit like the distro boot is at present. So far I have only
> > > > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > > > the concept.
> > > >
> > > > Adding EFI it's likely to be about the same amount of code as distro.c
> > > > at present, perhaps a little less since we don't have the network
> > > > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > > > do.  But I wanted to get something out as the concept is visible in
> > > > this series.
> > >
> > > OK, good.  I'd certainly like to see how this looks with EFI added.
> > >
> >
> > What would be the order preference after scanning?
> 
> (from other thread)
> With distro boot this is done with an environment variable, as I
> understand it. That is not implemented in this series, but is easy to
> do and is in the TODO. For now it can only be done with aliases to set
> the order of the bootmethods and that requires adding to the DT, so I
> don't think it scales well. I'm open to ideas though.
> 
> >
> > Keep in mind that our efibootmgr is pretty complete wrt to booting.
> > It can even support booting multiple OS'es without GRUB2 (even loading
> > different initrds is supported).  Ideally (and assuming we want to support
> > EFI booting for more devices), I would map existing extlinux configs into
> > efibootmgr entries.
> 
> Yes I understand. I believe distro boot supports multiple OSes too,
> but perhaps only on different media? I'm not sure. Anywayt ere are
> always going to be people who don't want or need to use EFI (or grub)

Well, here's where I'm a bit curious.  I have seen at least twice "wait,
EFI stub in the linux kernel adds how much?" type commentary.  I don't
know how prevalent that type of concern will really be given just how
often I don't see the Linux kernel config shrunk down from what the
reference platform started with.  And as Ilias is pointing out, you can
do _a_lot_ with efibootmgr and without grub/whatever.  And both Arm (the
company) and RISC-V (the overarching organization) are both pushing to
standardize around the idea that if you're on something bigger than an
MCU, EFI-the-ABI should get you up and running.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 20:08           ` Tom Rini
@ 2021-08-24  9:29             ` Ilias Apalodimas
  2021-08-25 13:11               ` Simon Glass
  0 siblings, 1 reply; 60+ messages in thread
From: Ilias Apalodimas @ 2021-08-24  9:29 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, U-Boot Mailing List, Steffen Jaeckel, Michal Simek,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Jaehoon Chung,
	Matthias Brugger, Peng Fan, Stephen Warren, Stephen Warren

Hi Tom,

> > > > > > >

[...]

> > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > >
> > > > > > My question / concern is this.  Would the next step here be to
> > > > > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > > > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > > > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > > > > Reading the documentation left me with the impression that every OSV
> > > > > > would be expected to write something, so that their installer / OS boot.
> > > > > > But there's already standards for that, which they do, and we should be
> > > > > > implementing (and do, via the current distro_boot) or making easier to
> > > > > > enable.  Thanks!
> > > > >
> > > > > Here you are talking about scanning for a bootflow. It is not actually
> > > > > OS-specific. If it were, there would be no point to this :-)
> > > > >
> > > > > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > > > > also scan_dev_for_scrips). At least the first needs to be implemented
> > > > > a bit like the distro boot is at present. So far I have only
> > > > > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > > > > the concept.
> > > > >
> > > > > Adding EFI it's likely to be about the same amount of code as distro.c
> > > > > at present, perhaps a little less since we don't have the network
> > > > > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > > > > do.  But I wanted to get something out as the concept is visible in
> > > > > this series.
> > > >
> > > > OK, good.  I'd certainly like to see how this looks with EFI added.
> > > >
> > >
> > > What would be the order preference after scanning?
> > 
> > (from other thread)
> > With distro boot this is done with an environment variable, as I
> > understand it. That is not implemented in this series, but is easy to
> > do and is in the TODO. For now it can only be done with aliases to set
> > the order of the bootmethods and that requires adding to the DT, so I
> > don't think it scales well. I'm open to ideas though.
> > 
> > >
> > > Keep in mind that our efibootmgr is pretty complete wrt to booting.
> > > It can even support booting multiple OS'es without GRUB2 (even loading
> > > different initrds is supported).  Ideally (and assuming we want to support
> > > EFI booting for more devices), I would map existing extlinux configs into
> > > efibootmgr entries.
> > 
> > Yes I understand. I believe distro boot supports multiple OSes too,
> > but perhaps only on different media? I'm not sure. Anywayt ere are
> > always going to be people who don't want or need to use EFI (or grub)
> 
> Well, here's where I'm a bit curious.  I have seen at least twice "wait,
> EFI stub in the linux kernel adds how much?" type commentary.  I don't
> know how prevalent that type of concern will really be given just how
> often I don't see the Linux kernel config shrunk down from what the
> reference platform started with.  And as Ilias is pointing out, you can
> do _a_lot_ with efibootmgr and without grub/whatever.  And both Arm (the
> company) and RISC-V (the overarching organization) are both pushing to
> standardize around the idea that if you're on something bigger than an
> MCU, EFI-the-ABI should get you up and running.

Exactly. Keep in mind that RISC-V is looking into EBBR as well, so this is
far from an 'Arm thing'. Moreover, the efi stub side of the kernel for
risc-v, will only load an initrd using the EFI_LOAD_FILE2 protocol we added
support for. So right now the only way to properly boot a RISC-V with EFI is
through the manager.

Regards
/Ilias
> 
> -- 
> Tom



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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-23 20:01     ` Tom Rini
@ 2021-08-24 10:22       ` Mark Kettenis
  2021-08-25 10:45         ` Emmanuel Vadot
  0 siblings, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-24 10:22 UTC (permalink / raw)
  To: Tom Rini
  Cc: sjg, u-boot, ilias.apalodimas, jaeckel-floss, michal.simek,
	dennis, daniel.schwierzeck, lukas.auer, jh80.chung, mbrugger,
	peng.fan, swarren, swarren

> Date: Mon, 23 Aug 2021 16:01:46 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > Hi Mark,
> > 
> > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > >
> > > > From: Simon Glass <sjg@chromium.org>
> > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > >
> > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > an Operating System without custom scripting and other customisation:
> > > >
> > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > >   - bootflow - a description of how to boot (owned by the distro)
> > > >
> > > > This series provides an initial implementation of these, enable to scan
> > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > tftp server. 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.
> > > >
> > > > It is intended that this approach be expanded to support mechanisms other
> > > > than distro boot, including EFI-related ones. With a standard way to
> > > > identify boot devices, these features become easier. It also should
> > > > support U-Boot scripts, for backwards compatibility only.
> > > >
> > > > The first patch of this series moves boot-related code out of common/ and
> > > > into a new boot/ directory. This helps to collect these related files
> > > > in one place, as common/ is quite large.
> > > >
> > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > Much of this series consists of cleaning up that code and refactoring it
> > > > into something closer to a module that can be called, teasing apart its
> > > > reliance on the command-line interpreter to access filesystems and the
> > > > like. Also it now uses function arguments and its own context struct
> > > > internally rather than environment variables, which is very hard to
> > > > follow. No core functional change is included in the included PXE patches.
> > > >
> > > > For documentation, see the 'doc' patch.
> > > >
> > > > There is quite a long list of future work included in the documentation.
> > > > One question is the choice of naming. Since this is a bootloader, should
> > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > shared by other commands like bootm, booti, etc.
> > > >
> > > > The design is described here:
> > > >
> > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > >
> > > > The series is available at u-boot-dm/bmea-working
> > >
> > > How does the user control the order in which devices are scanned/booted?
> > 
> > That is not supported in distroboot at present, at least so far as I
> > can see. For Fedora it seems to happen in grub. Do I have that right?
> 
> Well, there's "find the next stage", which is boot_targets environment
> variable, and then "where that next stage looks for stuff" which is
> OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> grub.cfg file.  I think Mark is talking about the former, and you've
> said it's not part of this series, yet, but on the TODO list.

Right.  With the current distroboot code the order of the devices that
appears in boot_targets is determined by per-board/SOC/machine config
files and the order isn't the same for all of them.  Users can change
the order if necessary by modifying the environment variable and
saving the environment.  And for a one-off boot from a different
device they can simply run an appropriate boot command.  The
boot_targets variable in particular is documented in various install
documents so it would probably be good of the new "bootmethod" code
would respect this variable.

For OpenBSD I'm not really interested in the bootflow part.  As I
explained in the past, that part of the problem is solved in a
(mostly) uniform way across platforms by the OpenBSD bootloader which
can read an /etc/boot.conf that allows bootflow customization.  So as
long as the default of the new code still results in
\EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
there is no U-Boot specific bootflow configured, I'm happy.

I can't speak for the other BSDs, but my impression is that they are
pretty much in the same position.  The FreeBSD bootloader for example
supports a high-degree of "bootflow" customization and I doubt that
taking it out of the loop is a viable option for most users.

> -- 
> Tom
> 
> [2:application/pgp-signature Show Save:signature.asc (659B)]
> 

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-24 10:22       ` Mark Kettenis
@ 2021-08-25 10:45         ` Emmanuel Vadot
  2021-08-25 13:11           ` Simon Glass
  0 siblings, 1 reply; 60+ messages in thread
From: Emmanuel Vadot @ 2021-08-25 10:45 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: Tom Rini, sjg, u-boot, ilias.apalodimas, jaeckel-floss,
	michal.simek, dennis, daniel.schwierzeck, lukas.auer, jh80.chung,
	mbrugger, peng.fan, swarren, swarren

On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:

> > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > From: Tom Rini <trini@konsulko.com>
> > 
> > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > Hi Mark,
> > > 
> > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > >
> > > > > From: Simon Glass <sjg@chromium.org>
> > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > >
> > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > an Operating System without custom scripting and other customisation:
> > > > >
> > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > >
> > > > > This series provides an initial implementation of these, enable to scan
> > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > tftp server. 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.
> > > > >
> > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > identify boot devices, these features become easier. It also should
> > > > > support U-Boot scripts, for backwards compatibility only.
> > > > >
> > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > into a new boot/ directory. This helps to collect these related files
> > > > > in one place, as common/ is quite large.
> > > > >
> > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > into something closer to a module that can be called, teasing apart its
> > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > like. Also it now uses function arguments and its own context struct
> > > > > internally rather than environment variables, which is very hard to
> > > > > follow. No core functional change is included in the included PXE patches.
> > > > >
> > > > > For documentation, see the 'doc' patch.
> > > > >
> > > > > There is quite a long list of future work included in the documentation.
> > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > shared by other commands like bootm, booti, etc.
> > > > >
> > > > > The design is described here:
> > > > >
> > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > >
> > > > > The series is available at u-boot-dm/bmea-working
> > > >
> > > > How does the user control the order in which devices are scanned/booted?
> > > 
> > > That is not supported in distroboot at present, at least so far as I
> > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > 
> > Well, there's "find the next stage", which is boot_targets environment
> > variable, and then "where that next stage looks for stuff" which is
> > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > grub.cfg file.  I think Mark is talking about the former, and you've
> > said it's not part of this series, yet, but on the TODO list.
> 
> Right.  With the current distroboot code the order of the devices that
> appears in boot_targets is determined by per-board/SOC/machine config
> files and the order isn't the same for all of them.  Users can change
> the order if necessary by modifying the environment variable and
> saving the environment.  And for a one-off boot from a different
> device they can simply run an appropriate boot command.  The
> boot_targets variable in particular is documented in various install
> documents so it would probably be good of the new "bootmethod" code
> would respect this variable.
> 
> For OpenBSD I'm not really interested in the bootflow part.  As I
> explained in the past, that part of the problem is solved in a
> (mostly) uniform way across platforms by the OpenBSD bootloader which
> can read an /etc/boot.conf that allows bootflow customization.  So as
> long as the default of the new code still results in
> \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> there is no U-Boot specific bootflow configured, I'm happy.

 Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
loaded and run by default (respecting the boot_targets order) we will
be fine.

> I can't speak for the other BSDs, but my impression is that they are
> pretty much in the same position.  The FreeBSD bootloader for example
> supports a high-degree of "bootflow" customization and I doubt that
> taking it out of the loop is a viable option for most users.
> 
> > -- 
> > Tom
> > 
> > [2:application/pgp-signature Show Save:signature.asc (659B)]
> > 


-- 
Emmanuel Vadot <manu@bidouilliste.com> <manu@FreeBSD.org>

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 10:45         ` Emmanuel Vadot
@ 2021-08-25 13:11           ` Simon Glass
  2021-08-25 14:42             ` AKASHI Takahiro
  0 siblings, 1 reply; 60+ messages in thread
From: Simon Glass @ 2021-08-25 13:11 UTC (permalink / raw)
  To: Emmanuel Vadot
  Cc: Mark Kettenis, Tom Rini, U-Boot Mailing List, Ilias Apalodimas,
	Steffen Jaeckel, Michal Simek, Dennis Gilmore,
	Daniel Schwierzeck, Lukas Auer, Jaehoon Chung, Matthias Brugger,
	Peng Fan, Stephen Warren, Stephen Warren

Hi,

On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
>
> On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>
> > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > From: Tom Rini <trini@konsulko.com>
> > >
> > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > Hi Mark,
> > > >
> > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > >
> > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > >
> > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > an Operating System without custom scripting and other customisation:
> > > > > >
> > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > >
> > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > tftp server. 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.
> > > > > >
> > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > identify boot devices, these features become easier. It also should
> > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > >
> > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > in one place, as common/ is quite large.
> > > > > >
> > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > internally rather than environment variables, which is very hard to
> > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > >
> > > > > > For documentation, see the 'doc' patch.
> > > > > >
> > > > > > There is quite a long list of future work included in the documentation.
> > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > shared by other commands like bootm, booti, etc.
> > > > > >
> > > > > > The design is described here:
> > > > > >
> > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > >
> > > > > > The series is available at u-boot-dm/bmea-working
> > > > >
> > > > > How does the user control the order in which devices are scanned/booted?
> > > >
> > > > That is not supported in distroboot at present, at least so far as I
> > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > >
> > > Well, there's "find the next stage", which is boot_targets environment
> > > variable, and then "where that next stage looks for stuff" which is
> > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > said it's not part of this series, yet, but on the TODO list.
> >
> > Right.  With the current distroboot code the order of the devices that
> > appears in boot_targets is determined by per-board/SOC/machine config
> > files and the order isn't the same for all of them.  Users can change
> > the order if necessary by modifying the environment variable and
> > saving the environment.  And for a one-off boot from a different
> > device they can simply run an appropriate boot command.  The
> > boot_targets variable in particular is documented in various install
> > documents so it would probably be good of the new "bootmethod" code
> > would respect this variable.
> >
> > For OpenBSD I'm not really interested in the bootflow part.  As I
> > explained in the past, that part of the problem is solved in a
> > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > can read an /etc/boot.conf that allows bootflow customization.  So as
> > long as the default of the new code still results in
> > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > there is no U-Boot specific bootflow configured, I'm happy.
>
>  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> loaded and run by default (respecting the boot_targets order) we will
> be fine.

OK thanks for the info. My expectation is that bootmethod/bootflow can
support this easily enough (it is actually simpler than distro boot).

>
> > I can't speak for the other BSDs, but my impression is that they are
> > pretty much in the same position.  The FreeBSD bootloader for example
> > supports a high-degree of "bootflow" customization and I doubt that
> > taking it out of the loop is a viable option for most users.

I think the same may happen with grub. E.g. with Ubuntu I see quite a
bit of code in the grub.cfg file and it's not clear to me that it can
be replaced with a 'data instead of code' approach. Still, a valid
bootflow is simply to jump to an EFI app, which seems to be what is
happening here. The bootflow side is really just about describing what
to do, and this case is no different. For now I see three types of
bootflow, PXE/syslinux, EFI boot manager and EFI app.

I'm travelling for three weeks soon, so if it doesn't happen this week
I'll continue this after that.

Regards,
Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-24  9:29             ` Ilias Apalodimas
@ 2021-08-25 13:11               ` Simon Glass
  2021-08-25 13:29                 ` Peter Robinson
  0 siblings, 1 reply; 60+ messages in thread
From: Simon Glass @ 2021-08-25 13:11 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, U-Boot Mailing List, Steffen Jaeckel, Michal Simek,
	Dennis Gilmore, Daniel Schwierzeck, Lukas Auer, Jaehoon Chung,
	Matthias Brugger, Peng Fan, Stephen Warren, Stephen Warren

Hi Ilias,

On Tue, 24 Aug 2021 at 03:30, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Tom,
>
> > > > > > > >
>
> [...]
>
> > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > >
> > > > > > > My question / concern is this.  Would the next step here be to
> > > > > > > implement the generic UEFI boot path?  Today, I can write Fedora 34 for
> > > > > > > AArch64 to a USB stick, boot U-Boot off of uSD card and the installer
> > > > > > > automatically boots.  I'm sure I could do the same with the BSDs.
> > > > > > > Reading the documentation left me with the impression that every OSV
> > > > > > > would be expected to write something, so that their installer / OS boot.
> > > > > > > But there's already standards for that, which they do, and we should be
> > > > > > > implementing (and do, via the current distro_boot) or making easier to
> > > > > > > enable.  Thanks!
> > > > > >
> > > > > > Here you are talking about scanning for a bootflow. It is not actually
> > > > > > OS-specific. If it were, there would be no point to this :-)
> > > > > >
> > > > > > If you look in the distro scripts you will see 'scan_dev_for_efi' (and
> > > > > > also scan_dev_for_scrips). At least the first needs to be implemented
> > > > > > a bit like the distro boot is at present. So far I have only
> > > > > > implemented scan_dev_for_extlinux (plus pxe) as it is enough to show
> > > > > > the concept.
> > > > > >
> > > > > > Adding EFI it's likely to be about the same amount of code as distro.c
> > > > > > at present, perhaps a little less since we don't have the network
> > > > > > case. It is used by Fedora 34, I believe, so is easy enough for me to
> > > > > > do.  But I wanted to get something out as the concept is visible in
> > > > > > this series.
> > > > >
> > > > > OK, good.  I'd certainly like to see how this looks with EFI added.
> > > > >
> > > >
> > > > What would be the order preference after scanning?
> > >
> > > (from other thread)
> > > With distro boot this is done with an environment variable, as I
> > > understand it. That is not implemented in this series, but is easy to
> > > do and is in the TODO. For now it can only be done with aliases to set
> > > the order of the bootmethods and that requires adding to the DT, so I
> > > don't think it scales well. I'm open to ideas though.
> > >
> > > >
> > > > Keep in mind that our efibootmgr is pretty complete wrt to booting.
> > > > It can even support booting multiple OS'es without GRUB2 (even loading
> > > > different initrds is supported).  Ideally (and assuming we want to support
> > > > EFI booting for more devices), I would map existing extlinux configs into
> > > > efibootmgr entries.
> > >
> > > Yes I understand. I believe distro boot supports multiple OSes too,
> > > but perhaps only on different media? I'm not sure. Anywayt ere are
> > > always going to be people who don't want or need to use EFI (or grub)
> >
> > Well, here's where I'm a bit curious.  I have seen at least twice "wait,
> > EFI stub in the linux kernel adds how much?" type commentary.  I don't
> > know how prevalent that type of concern will really be given just how
> > often I don't see the Linux kernel config shrunk down from what the
> > reference platform started with.  And as Ilias is pointing out, you can
> > do _a_lot_ with efibootmgr and without grub/whatever.  And both Arm (the
> > company) and RISC-V (the overarching organization) are both pushing to
> > standardize around the idea that if you're on something bigger than an
> > MCU, EFI-the-ABI should get you up and running.
>
> Exactly. Keep in mind that RISC-V is looking into EBBR as well, so this is
> far from an 'Arm thing'. Moreover, the efi stub side of the kernel for
> risc-v, will only load an initrd using the EFI_LOAD_FILE2 protocol we added
> support for. So right now the only way to properly boot a RISC-V with EFI is
> through the manager.

I had heard that RISC-V was just going to use UEFI (and not U-Boot),
but perhaps that is not correct. So far I have not really done
anything with RISC-V so am not familiar with it.

Regards,
Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 13:11               ` Simon Glass
@ 2021-08-25 13:29                 ` Peter Robinson
  2021-08-25 21:34                   ` Mark Kettenis
  0 siblings, 1 reply; 60+ messages in thread
From: Peter Robinson @ 2021-08-25 13:29 UTC (permalink / raw)
  To: Simon Glass
  Cc: Ilias Apalodimas, Tom Rini, U-Boot Mailing List, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

> > Exactly. Keep in mind that RISC-V is looking into EBBR as well, so this is
> > far from an 'Arm thing'. Moreover, the efi stub side of the kernel for
> > risc-v, will only load an initrd using the EFI_LOAD_FILE2 protocol we added
> > support for. So right now the only way to properly boot a RISC-V with EFI is
> > through the manager.
>
> I had heard that RISC-V was just going to use UEFI (and not U-Boot),
> but perhaps that is not correct. So far I have not really done
> anything with RISC-V so am not familiar with it.

My understanding is the intention is to just use UEFI of which U-Boot
has a UEFI implementation.

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 13:11           ` Simon Glass
@ 2021-08-25 14:42             ` AKASHI Takahiro
  2021-08-25 14:56               ` Tom Rini
  0 siblings, 1 reply; 60+ messages in thread
From: AKASHI Takahiro @ 2021-08-25 14:42 UTC (permalink / raw)
  To: Simon Glass
  Cc: Emmanuel Vadot, Mark Kettenis, Tom Rini, U-Boot Mailing List,
	Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Dennis Gilmore,
	Daniel Schwierzeck, Lukas Auer, Jaehoon Chung, Matthias Brugger,
	Peng Fan, Stephen Warren, Stephen Warren

Simon,

On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> Hi,
> 
> On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> >
> > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> >
> > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > From: Tom Rini <trini@konsulko.com>
> > > >
> > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > Hi Mark,
> > > > >
> > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > >
> > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > >
> > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > >
> > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > >
> > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > tftp server. 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.
> > > > > > >
> > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > >
> > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > in one place, as common/ is quite large.
> > > > > > >
> > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > >
> > > > > > > For documentation, see the 'doc' patch.
> > > > > > >
> > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > >
> > > > > > > The design is described here:
> > > > > > >
> > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > >
> > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > >
> > > > > > How does the user control the order in which devices are scanned/booted?
> > > > >
> > > > > That is not supported in distroboot at present, at least so far as I
> > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > >
> > > > Well, there's "find the next stage", which is boot_targets environment
> > > > variable, and then "where that next stage looks for stuff" which is
> > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > said it's not part of this series, yet, but on the TODO list.
> > >
> > > Right.  With the current distroboot code the order of the devices that
> > > appears in boot_targets is determined by per-board/SOC/machine config
> > > files and the order isn't the same for all of them.  Users can change
> > > the order if necessary by modifying the environment variable and
> > > saving the environment.  And for a one-off boot from a different
> > > device they can simply run an appropriate boot command.  The
> > > boot_targets variable in particular is documented in various install
> > > documents so it would probably be good of the new "bootmethod" code
> > > would respect this variable.
> > >
> > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > explained in the past, that part of the problem is solved in a
> > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > long as the default of the new code still results in
> > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > there is no U-Boot specific bootflow configured, I'm happy.
> >
> >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > loaded and run by default (respecting the boot_targets order) we will
> > be fine.
> 
> OK thanks for the info. My expectation is that bootmethod/bootflow can
> support this easily enough (it is actually simpler than distro boot).
> 
> >
> > > I can't speak for the other BSDs, but my impression is that they are
> > > pretty much in the same position.  The FreeBSD bootloader for example
> > > supports a high-degree of "bootflow" customization and I doubt that
> > > taking it out of the loop is a viable option for most users.
> 
> I think the same may happen with grub. E.g. with Ubuntu I see quite a
> bit of code in the grub.cfg file and it's not clear to me that it can
> be replaced with a 'data instead of code' approach. Still, a valid
> bootflow is simply to jump to an EFI app, which seems to be what is
> happening here. The bootflow side is really just about describing what
> to do, and this case is no different. For now I see three types of
> bootflow, PXE/syslinux, EFI boot manager and EFI app.

By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
(default file name in case that no image path is specified)?

In fact, this behavior, or removable media support, is defined
as part of UEFI boot manager in UEFI specification. (See section 3.5)
What this means is that the boot order, including a removable media
case and user-provided BootXXXX cases, should be controlled solely
by "BootOrder" variable.
So the current combination of distro_bootcmd + UEFI boot manger doesn't
fully comply with the specification.

Even if those two cases are integrated, I don't know how "BootOrder"
semantics can be preserved in your approach.

-Takahiro Akashi


> I'm travelling for three weeks soon, so if it doesn't happen this week
> I'll continue this after that.
> 
> Regards,
> Simon

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 14:42             ` AKASHI Takahiro
@ 2021-08-25 14:56               ` Tom Rini
  2021-08-25 21:54                 ` Mark Kettenis
  2021-08-26 11:55                 ` Peter Robinson
  0 siblings, 2 replies; 60+ messages in thread
From: Tom Rini @ 2021-08-25 14:56 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Simon Glass, Emmanuel Vadot, Mark Kettenis, U-Boot Mailing List,
	Ilias Apalodimas, Steffen Jaeckel, Michal Simek, Dennis Gilmore,
	Daniel Schwierzeck, Lukas Auer, Jaehoon Chung, Matthias Brugger,
	Peng Fan, Stephen Warren, Stephen Warren

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

On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> Simon,
> 
> On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > Hi,
> > 
> > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > >
> > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > >
> > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > From: Tom Rini <trini@konsulko.com>
> > > > >
> > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > Hi Mark,
> > > > > >
> > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > >
> > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > >
> > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > >
> > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > >
> > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > tftp server. 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.
> > > > > > > >
> > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > >
> > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > in one place, as common/ is quite large.
> > > > > > > >
> > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > >
> > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > >
> > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > >
> > > > > > > > The design is described here:
> > > > > > > >
> > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > >
> > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > >
> > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > >
> > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > >
> > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > said it's not part of this series, yet, but on the TODO list.
> > > >
> > > > Right.  With the current distroboot code the order of the devices that
> > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > files and the order isn't the same for all of them.  Users can change
> > > > the order if necessary by modifying the environment variable and
> > > > saving the environment.  And for a one-off boot from a different
> > > > device they can simply run an appropriate boot command.  The
> > > > boot_targets variable in particular is documented in various install
> > > > documents so it would probably be good of the new "bootmethod" code
> > > > would respect this variable.
> > > >
> > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > explained in the past, that part of the problem is solved in a
> > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > long as the default of the new code still results in
> > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > there is no U-Boot specific bootflow configured, I'm happy.
> > >
> > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > loaded and run by default (respecting the boot_targets order) we will
> > > be fine.
> > 
> > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > support this easily enough (it is actually simpler than distro boot).
> > 
> > >
> > > > I can't speak for the other BSDs, but my impression is that they are
> > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > taking it out of the loop is a viable option for most users.
> > 
> > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > bit of code in the grub.cfg file and it's not clear to me that it can
> > be replaced with a 'data instead of code' approach. Still, a valid
> > bootflow is simply to jump to an EFI app, which seems to be what is
> > happening here. The bootflow side is really just about describing what
> > to do, and this case is no different. For now I see three types of
> > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> 
> By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> (default file name in case that no image path is specified)?
> 
> In fact, this behavior, or removable media support, is defined
> as part of UEFI boot manager in UEFI specification. (See section 3.5)
> What this means is that the boot order, including a removable media
> case and user-provided BootXXXX cases, should be controlled solely
> by "BootOrder" variable.
> So the current combination of distro_bootcmd + UEFI boot manger doesn't
> fully comply with the specification.
> 
> Even if those two cases are integrated, I don't know how "BootOrder"
> semantics can be preserved in your approach.

I think the high level answer is that whereas today part of
distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
gets run, with what Simon is proposing we would have an easier / quicker
way to get over to just running that.  Perhaps a clean-up to just use
that, even?  Or are we not to the point yet where we could remove the
direct fall-back to /efi/boot/bootXX.efi ?

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 13:29                 ` Peter Robinson
@ 2021-08-25 21:34                   ` Mark Kettenis
  2021-08-25 21:58                     ` Tom Rini
  0 siblings, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-25 21:34 UTC (permalink / raw)
  To: Peter Robinson
  Cc: sjg, ilias.apalodimas, trini, u-boot, jaeckel-floss,
	michal.simek, dennis, daniel.schwierzeck, lukas.auer, jh80.chung,
	mbrugger, peng.fan, swarren, swarren

> From: Peter Robinson <pbrobinson@gmail.com>
> Date: Wed, 25 Aug 2021 14:29:45 +0100
> 
> > > Exactly. Keep in mind that RISC-V is looking into EBBR as well,
> > > so this is far from an 'Arm thing'. Moreover, the efi stub side
> > > of the kernel for risc-v, will only load an initrd using the
> > > EFI_LOAD_FILE2 protocol we added support for. So right now the
> > > only way to properly boot a RISC-V with EFI is through the
> > > manager.
> >
> > I had heard that RISC-V was just going to use UEFI (and not U-Boot),
> > but perhaps that is not correct. So far I have not really done
> > anything with RISC-V so am not familiar with it.
> 
> My understanding is the intention is to just use UEFI of which U-Boot
> has a UEFI implementation.

The HiFive Unmatched ships with U-Boot.  I'm booting OpenBSD via UEFI
on that board by using the uSD card that came with the board.

The folks pushing the spec for RISC-V server hardware are probably
considering a more traditional UEFI implementation for those systems
since they also seem to be pushing for ACPI.  But they explicitly
mention EBBR for "embedded" systems, and EBBR was deliberately
designed to allow the implementation of compliant systems using
U-Boot's UEFI implementation.

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 14:56               ` Tom Rini
@ 2021-08-25 21:54                 ` Mark Kettenis
  2021-08-25 22:06                   ` Tom Rini
  2021-08-26 11:55                 ` Peter Robinson
  1 sibling, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-25 21:54 UTC (permalink / raw)
  To: Tom Rini
  Cc: takahiro.akashi, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

> Date: Wed, 25 Aug 2021 10:56:35 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > Simon,
> > 
> > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > Hi,
> > > 
> > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > >
> > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > >
> > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > >
> > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > Hi Mark,
> > > > > > >
> > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > >
> > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > >
> > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > >
> > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > >
> > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > tftp server. 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.
> > > > > > > > >
> > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > >
> > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > >
> > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > >
> > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > >
> > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > >
> > > > > > > > > The design is described here:
> > > > > > > > >
> > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > >
> > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > >
> > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > >
> > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > >
> > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > >
> > > > > Right.  With the current distroboot code the order of the devices that
> > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > files and the order isn't the same for all of them.  Users can change
> > > > > the order if necessary by modifying the environment variable and
> > > > > saving the environment.  And for a one-off boot from a different
> > > > > device they can simply run an appropriate boot command.  The
> > > > > boot_targets variable in particular is documented in various install
> > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > would respect this variable.
> > > > >
> > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > explained in the past, that part of the problem is solved in a
> > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > long as the default of the new code still results in
> > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > >
> > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > loaded and run by default (respecting the boot_targets order) we will
> > > > be fine.
> > > 
> > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > support this easily enough (it is actually simpler than distro boot).
> > > 
> > > >
> > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > taking it out of the loop is a viable option for most users.
> > > 
> > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > be replaced with a 'data instead of code' approach. Still, a valid
> > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > happening here. The bootflow side is really just about describing what
> > > to do, and this case is no different. For now I see three types of
> > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > 
> > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > (default file name in case that no image path is specified)?
> > 
> > In fact, this behavior, or removable media support, is defined
> > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > What this means is that the boot order, including a removable media
> > case and user-provided BootXXXX cases, should be controlled solely
> > by "BootOrder" variable.
> > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > fully comply with the specification.
> > 
> > Even if those two cases are integrated, I don't know how "BootOrder"
> > semantics can be preserved in your approach.
> 
> I think the high level answer is that whereas today part of
> distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> gets run, with what Simon is proposing we would have an easier / quicker
> way to get over to just running that.  Perhaps a clean-up to just use
> that, even?  Or are we not to the point yet where we could remove the
> direct fall-back to /efi/boot/bootXX.efi ?

I think "bootefi bootmgr" only works if the BootOrder variable is
defined, and currently that isn't the case.

The boot manager behaviour as specified in the UEFI specification is
somewhat problematic to implement in U-Boot because of the limitations
in how variables can be set at runtime.  This is one of the reasons
OpenBSD doesn't actually bother with setting the variables and simple
relies on the "removable media" support mentioned above.  All my
OpenBSD systems that use U-Boot print the follwing lines:

  BootOrder not defined
  EFI boot manager: Cannot load any image
  Found EFI removable media binary efi/boot/bootaa64.efi

But maybe that last step can be intgrated into bootefi bootmgr at some
point?

Also note that manually manipulating the EFI variables to change the
boot order is quite cumbersome; it isn't a matter of just changed the
aforementioned BootOrder variable.  That's why I think boot_targets is
the preferable way to define the order in which devices should be
booted.  I don't think that violates the UEFI specification.  It
merely is the way U-Boot implements the boot device selection that
more traditional UEFI implementations implement using a menu.

Cheers,

Mark

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 21:34                   ` Mark Kettenis
@ 2021-08-25 21:58                     ` Tom Rini
  0 siblings, 0 replies; 60+ messages in thread
From: Tom Rini @ 2021-08-25 21:58 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: Peter Robinson, sjg, ilias.apalodimas, u-boot, jaeckel-floss,
	michal.simek, dennis, daniel.schwierzeck, lukas.auer, jh80.chung,
	mbrugger, peng.fan, swarren, swarren

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

On Wed, Aug 25, 2021 at 11:34:45PM +0200, Mark Kettenis wrote:
> > From: Peter Robinson <pbrobinson@gmail.com>
> > Date: Wed, 25 Aug 2021 14:29:45 +0100
> > 
> > > > Exactly. Keep in mind that RISC-V is looking into EBBR as well,
> > > > so this is far from an 'Arm thing'. Moreover, the efi stub side
> > > > of the kernel for risc-v, will only load an initrd using the
> > > > EFI_LOAD_FILE2 protocol we added support for. So right now the
> > > > only way to properly boot a RISC-V with EFI is through the
> > > > manager.
> > >
> > > I had heard that RISC-V was just going to use UEFI (and not U-Boot),
> > > but perhaps that is not correct. So far I have not really done
> > > anything with RISC-V so am not familiar with it.
> > 
> > My understanding is the intention is to just use UEFI of which U-Boot
> > has a UEFI implementation.
> 
> The HiFive Unmatched ships with U-Boot.  I'm booting OpenBSD via UEFI
> on that board by using the uSD card that came with the board.
> 
> The folks pushing the spec for RISC-V server hardware are probably
> considering a more traditional UEFI implementation for those systems
> since they also seem to be pushing for ACPI.  But they explicitly
> mention EBBR for "embedded" systems, and EBBR was deliberately
> designed to allow the implementation of compliant systems using
> U-Boot's UEFI implementation.

I don't know if any of the "right" people are listening here, but, I
don't see why ACPI precludes U-Boot.  We ship ACPI tables for x86
already...

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 21:54                 ` Mark Kettenis
@ 2021-08-25 22:06                   ` Tom Rini
  2021-08-26  6:33                     ` AKASHI Takahiro
  2021-08-26 12:01                     ` Mark Kettenis
  0 siblings, 2 replies; 60+ messages in thread
From: Tom Rini @ 2021-08-25 22:06 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: takahiro.akashi, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

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

On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > From: Tom Rini <trini@konsulko.com>
> > 
> > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > Simon,
> > > 
> > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > Hi,
> > > > 
> > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > >
> > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > >
> > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > >
> > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > Hi Mark,
> > > > > > > >
> > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > >
> > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > >
> > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > >
> > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > >
> > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > tftp server. 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.
> > > > > > > > > >
> > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > >
> > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > >
> > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > >
> > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > >
> > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > >
> > > > > > > > > > The design is described here:
> > > > > > > > > >
> > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > >
> > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > >
> > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > >
> > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > >
> > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > >
> > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > the order if necessary by modifying the environment variable and
> > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > device they can simply run an appropriate boot command.  The
> > > > > > boot_targets variable in particular is documented in various install
> > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > would respect this variable.
> > > > > >
> > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > explained in the past, that part of the problem is solved in a
> > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > long as the default of the new code still results in
> > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > >
> > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > be fine.
> > > > 
> > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > support this easily enough (it is actually simpler than distro boot).
> > > > 
> > > > >
> > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > taking it out of the loop is a viable option for most users.
> > > > 
> > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > happening here. The bootflow side is really just about describing what
> > > > to do, and this case is no different. For now I see three types of
> > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > 
> > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > (default file name in case that no image path is specified)?
> > > 
> > > In fact, this behavior, or removable media support, is defined
> > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > What this means is that the boot order, including a removable media
> > > case and user-provided BootXXXX cases, should be controlled solely
> > > by "BootOrder" variable.
> > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > fully comply with the specification.
> > > 
> > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > semantics can be preserved in your approach.
> > 
> > I think the high level answer is that whereas today part of
> > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > gets run, with what Simon is proposing we would have an easier / quicker
> > way to get over to just running that.  Perhaps a clean-up to just use
> > that, even?  Or are we not to the point yet where we could remove the
> > direct fall-back to /efi/boot/bootXX.efi ?
> 
> I think "bootefi bootmgr" only works if the BootOrder variable is
> defined, and currently that isn't the case.
> 
> The boot manager behaviour as specified in the UEFI specification is
> somewhat problematic to implement in U-Boot because of the limitations
> in how variables can be set at runtime.  This is one of the reasons
> OpenBSD doesn't actually bother with setting the variables and simple
> relies on the "removable media" support mentioned above.  All my
> OpenBSD systems that use U-Boot print the follwing lines:
> 
>   BootOrder not defined
>   EFI boot manager: Cannot load any image
>   Found EFI removable media binary efi/boot/bootaa64.efi
> 
> But maybe that last step can be intgrated into bootefi bootmgr at some
> point?
> 
> Also note that manually manipulating the EFI variables to change the
> boot order is quite cumbersome; it isn't a matter of just changed the
> aforementioned BootOrder variable.  That's why I think boot_targets is
> the preferable way to define the order in which devices should be
> booted.  I don't think that violates the UEFI specification.  It
> merely is the way U-Boot implements the boot device selection that
> more traditional UEFI implementations implement using a menu.

As I don't want to side-track Simon's thread even further, I would like
to see a bit more detailed explanation of why U-Boot cannot support EFI
variables, or if it's just a matter of someone doing the work, and it's
not been a priority yet.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 22:06                   ` Tom Rini
@ 2021-08-26  6:33                     ` AKASHI Takahiro
  2021-08-26 13:03                       ` Tom Rini
  2021-08-26 12:01                     ` Mark Kettenis
  1 sibling, 1 reply; 60+ messages in thread
From: AKASHI Takahiro @ 2021-08-26  6:33 UTC (permalink / raw)
  To: Tom Rini
  Cc: Mark Kettenis, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

Mark, Tom,

On Wed, Aug 25, 2021 at 06:06:05PM -0400, Tom Rini wrote:
> On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > > From: Tom Rini <trini@konsulko.com>
> > > 
> > > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > > Simon,
> > > > 
> > > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > > Hi,
> > > > > 
> > > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > > >
> > > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > >
> > > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > > >
> > > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > > Hi Mark,
> > > > > > > > >
> > > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > > >
> > > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > > >
> > > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > > >
> > > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > > >
> > > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > > tftp server. 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.
> > > > > > > > > > >
> > > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > > >
> > > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > > >
> > > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > > >
> > > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > > >
> > > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > > >
> > > > > > > > > > > The design is described here:
> > > > > > > > > > >
> > > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > > >
> > > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > > >
> > > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > > >
> > > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > > >
> > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > >
> > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > would respect this variable.
> > > > > > >
> > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > long as the default of the new code still results in
> > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > >
> > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > be fine.
> > > > > 
> > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > 
> > > > > >
> > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > taking it out of the loop is a viable option for most users.
> > > > > 
> > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > happening here. The bootflow side is really just about describing what
> > > > > to do, and this case is no different. For now I see three types of
> > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > 
> > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > (default file name in case that no image path is specified)?
> > > > 
> > > > In fact, this behavior, or removable media support, is defined
> > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > What this means is that the boot order, including a removable media
> > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > by "BootOrder" variable.
> > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > fully comply with the specification.
> > > > 
> > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > semantics can be preserved in your approach.
> > > 
> > > I think the high level answer is that whereas today part of
> > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > gets run, with what Simon is proposing we would have an easier / quicker
> > > way to get over to just running that.  Perhaps a clean-up to just use
> > > that, even?  Or are we not to the point yet where we could remove the
> > > direct fall-back to /efi/boot/bootXX.efi ?
> > 
> > I think "bootefi bootmgr" only works if the BootOrder variable is
> > defined, and currently that isn't the case.
> > 
> > The boot manager behaviour as specified in the UEFI specification is
> > somewhat problematic to implement in U-Boot because of the limitations
> > in how variables can be set at runtime.  This is one of the reasons
> > OpenBSD doesn't actually bother with setting the variables and simple
> > relies on the "removable media" support mentioned above.  All my

Well, if this is everyone's consensus in (U-Boot) community,
it would be fine. But different people may have different
opinions/requirements on different systems. So I believe that
the safest way is to make UEFI implementation as compliant to
the specification as possible.

> > OpenBSD systems that use U-Boot print the follwing lines:
> > 
> >   BootOrder not defined
> >   EFI boot manager: Cannot load any image
> >   Found EFI removable media binary efi/boot/bootaa64.efi
> > 
> > But maybe that last step can be intgrated into bootefi bootmgr at some
> > point?

Yes, it is doable, even I'm now trying to examine and address this issue
as I am fully aware of the situation.

> > Also note that manually manipulating the EFI variables to change the
> > boot order is quite cumbersome; it isn't a matter of just changed the
> > aforementioned BootOrder variable.  That's why I think boot_targets is
> > the preferable way to define the order in which devices should be
> > booted.  I don't think that violates the UEFI specification.  It
> > merely is the way U-Boot implements the boot device selection that
> > more traditional UEFI implementations implement using a menu.
> 
> As I don't want to side-track Simon's thread even further, I would like
> to see a bit more detailed explanation of why U-Boot cannot support EFI
> variables, or if it's just a matter of someone doing the work, and it's
> not been a priority yet.

It is more or less a matter of implementation.
Historically, removable media support was added to distro_bootcmd first
and then boot manager was implemented later, only both were integrated
at script level. Since then, nobody, AFAIK, has complained about
the lack of integrity. That's what we see now.

One of difficulties that I found in the implementation is
how to specify preferred boot media in a form of EFI device path.
Take an example; I want to do
=> efidebug boot add -b 1 USB usb 0 "" -s ""    ; USB port-1
                              ^^^^^^^^ no image file specified
=> efidebug boot add -b 2 USB usb 1 "" -s ""    ; USB port-2
=> efidebug boot add -b 3 MMC mmc 0 "" -s ""    ; MMC slot-1
=> efidebug boot add -b 4 MYKERNEL scsi 0:1 /.../vmlinux.efi -s "..."
=> efidebug boot order 1 2 3 4
=> bootefi bootmgr

First three commands will fail now.

Under the current implementation, neither "usb 0", "usb 1" nor "mmc 0",
which is set to be converted to device path representation in BootXXXX
variable, are recognized as a valid device since there is no physical
device attached to corresponding bus/port/slots at this time.
Internally, UEFI system/efidebug always tries to look for a U-Boot's
existing block device to identify the correct device path.
(Remember that *buses* and *controller* are even not udevices?).
So we would have to manage to create a valid internal representation of
bus or port for those media.

# FYI, my current prototype work already supports the following command line
# and enables booting the system from the USB media if some storage device
# is attached to the port-1:
# => efidebug boot add -b 1 USB usb 0:1 "" -s ""    ; USB port-1
                                ^^^^^^^

As I'm not well-versed in U-Boot's device model, the rework
would be simpler than I anticipate.

-Takahiro Akashi

> -- 
> Tom



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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 14:56               ` Tom Rini
  2021-08-25 21:54                 ` Mark Kettenis
@ 2021-08-26 11:55                 ` Peter Robinson
  1 sibling, 0 replies; 60+ messages in thread
From: Peter Robinson @ 2021-08-26 11:55 UTC (permalink / raw)
  To: Tom Rini
  Cc: AKASHI Takahiro, Simon Glass, Emmanuel Vadot, Mark Kettenis,
	U-Boot Mailing List, Ilias Apalodimas, Steffen Jaeckel,
	Michal Simek, Dennis Gilmore, Daniel Schwierzeck, Lukas Auer,
	Jaehoon Chung, Matthias Brugger, Peng Fan, Stephen Warren,
	Stephen Warren

> > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > (default file name in case that no image path is specified)?
> >
> > In fact, this behavior, or removable media support, is defined
> > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > What this means is that the boot order, including a removable media
> > case and user-provided BootXXXX cases, should be controlled solely
> > by "BootOrder" variable.
> > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > fully comply with the specification.
> >
> > Even if those two cases are integrated, I don't know how "BootOrder"
> > semantics can be preserved in your approach.
>
> I think the high level answer is that whereas today part of
> distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> gets run, with what Simon is proposing we would have an easier / quicker
> way to get over to just running that.  Perhaps a clean-up to just use
> that, even?  Or are we not to the point yet where we could remove the
> direct fall-back to /efi/boot/bootXX.efi ?

I've not actually got as far as grabbing this series and trying it out
but I like a bunch of the concepts.

If we can use this to replace a bunch of the distro_boot hush script
checks for various devices in which to boot from and make it a more
standardised logic I think that's an overall win. Double bonus points
if we could have an easy way to specify a boot order and even have the
ability to have a "Press F8 to display a boot menu" style option where
a user could select the specific device they wish to attempt to boot
from without having to interrupt the boot, and often dive into
printenv and random commands to try and workout where/where/why to get
it to overide the onboarad eMMC so they can boot off a USB stick!

Peter

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-25 22:06                   ` Tom Rini
  2021-08-26  6:33                     ` AKASHI Takahiro
@ 2021-08-26 12:01                     ` Mark Kettenis
  2021-08-26 13:00                       ` Tom Rini
  1 sibling, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-26 12:01 UTC (permalink / raw)
  To: Tom Rini
  Cc: takahiro.akashi, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

> Date: Wed, 25 Aug 2021 18:06:05 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > > From: Tom Rini <trini@konsulko.com>
> > > 
> > > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > > Simon,
> > > > 
> > > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > > Hi,
> > > > > 
> > > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > > >
> > > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > >
> > > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > > >
> > > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > > Hi Mark,
> > > > > > > > >
> > > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > > >
> > > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > > >
> > > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > > >
> > > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > > >
> > > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > > tftp server. 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.
> > > > > > > > > > >
> > > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > > >
> > > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > > >
> > > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > > >
> > > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > > >
> > > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > > >
> > > > > > > > > > > The design is described here:
> > > > > > > > > > >
> > > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > > >
> > > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > > >
> > > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > > >
> > > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > > >
> > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > >
> > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > would respect this variable.
> > > > > > >
> > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > long as the default of the new code still results in
> > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > >
> > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > be fine.
> > > > > 
> > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > 
> > > > > >
> > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > taking it out of the loop is a viable option for most users.
> > > > > 
> > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > happening here. The bootflow side is really just about describing what
> > > > > to do, and this case is no different. For now I see three types of
> > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > 
> > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > (default file name in case that no image path is specified)?
> > > > 
> > > > In fact, this behavior, or removable media support, is defined
> > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > What this means is that the boot order, including a removable media
> > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > by "BootOrder" variable.
> > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > fully comply with the specification.
> > > > 
> > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > semantics can be preserved in your approach.
> > > 
> > > I think the high level answer is that whereas today part of
> > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > gets run, with what Simon is proposing we would have an easier / quicker
> > > way to get over to just running that.  Perhaps a clean-up to just use
> > > that, even?  Or are we not to the point yet where we could remove the
> > > direct fall-back to /efi/boot/bootXX.efi ?
> > 
> > I think "bootefi bootmgr" only works if the BootOrder variable is
> > defined, and currently that isn't the case.
> > 
> > The boot manager behaviour as specified in the UEFI specification is
> > somewhat problematic to implement in U-Boot because of the limitations
> > in how variables can be set at runtime.  This is one of the reasons
> > OpenBSD doesn't actually bother with setting the variables and simple
> > relies on the "removable media" support mentioned above.  All my
> > OpenBSD systems that use U-Boot print the follwing lines:
> > 
> >   BootOrder not defined
> >   EFI boot manager: Cannot load any image
> >   Found EFI removable media binary efi/boot/bootaa64.efi
> > 
> > But maybe that last step can be intgrated into bootefi bootmgr at some
> > point?
> > 
> > Also note that manually manipulating the EFI variables to change the
> > boot order is quite cumbersome; it isn't a matter of just changed the
> > aforementioned BootOrder variable.  That's why I think boot_targets is
> > the preferable way to define the order in which devices should be
> > booted.  I don't think that violates the UEFI specification.  It
> > merely is the way U-Boot implements the boot device selection that
> > more traditional UEFI implementations implement using a menu.
> 
> As I don't want to side-track Simon's thread even further, I would like
> to see a bit more detailed explanation of why U-Boot cannot support EFI
> variables, or if it's just a matter of someone doing the work, and it's
> not been a priority yet.

U-Boot has some support for EFI variables, but there are some
fundamental problems that make "full" support for them hard or even
impossible.

Some non-volatile storage is necessary for these variables such that
they can be persistent across boots.  Obviously this very much applies
to the BootOrder variable.  EFI defines calls to manipulate variables
as part of its runtime services.  This means that the NV storage has
to implemented in a way that doesn't interfere with normal OS usage of
the hardware.  That pretty much means that you need dedicated hardware
for this, which most devices supported by U-Boot simply don't have.
Having the EFI variables in the U-Boot environment on a reserved part
of a uSD card isn't going to work if the OS assumes it has full
control over the uSD controller.

Recent versions of the UEFI have made the implementation of some of
the runtime services optional (more or less at the request of the EBBR
folks) and allow certain calls (e.g. the SetVariable() call) to fail.
This poses a bit of a problem though, which I'll try to sketch here:

The way things typically work on a x86 EFI system is that you boot
your OS installer from removable media.  The OS installer does its
thing (partitions the disk, creates filesystems, installs the OS
kernel, etc.) and at the end creates a boot option for the boot
manager by creating an apropriate Boot#### variable and possibly
modifying the BootOrder variable to include the newly created boot
option.  A typical x86 Linux distro will create a Boot#### variable
that is effectively a devicepath pointing at grub.efi.  Unfortunately
that won't work if the SetVariable() EFI runtime interface doesn't
work.

I'm not sure how the EBBR folks envisaged the OS installation user
experience on these systems.  Maybe Takahiro can explain.  But as long
as you don't really care about booting multiple OSes on a system,
relying on the default removable media boot path works fine in most
cases in that it automatically boots into the installed OS when you
reboot after removing the installation media.

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-26 12:01                     ` Mark Kettenis
@ 2021-08-26 13:00                       ` Tom Rini
  2021-08-26 13:32                         ` Mark Kettenis
  0 siblings, 1 reply; 60+ messages in thread
From: Tom Rini @ 2021-08-26 13:00 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: takahiro.akashi, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

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

On Thu, Aug 26, 2021 at 02:01:07PM +0200, Mark Kettenis wrote:
> > Date: Wed, 25 Aug 2021 18:06:05 -0400
> > From: Tom Rini <trini@konsulko.com>
> > 
> > On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > > > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > > > From: Tom Rini <trini@konsulko.com>
> > > > 
> > > > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > > > Simon,
> > > > > 
> > > > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > > > Hi,
> > > > > > 
> > > > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > > > >
> > > > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > >
> > > > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > > > >
> > > > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > > > Hi Mark,
> > > > > > > > > >
> > > > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > > > >
> > > > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > > > >
> > > > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > > > >
> > > > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > > > >
> > > > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > > > tftp server. 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.
> > > > > > > > > > > >
> > > > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > > > >
> > > > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > > > >
> > > > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > > > >
> > > > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > > > >
> > > > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > > > >
> > > > > > > > > > > > The design is described here:
> > > > > > > > > > > >
> > > > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > > > >
> > > > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > > > >
> > > > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > > > >
> > > > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > > > >
> > > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > > >
> > > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > > would respect this variable.
> > > > > > > >
> > > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > > long as the default of the new code still results in
> > > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > > >
> > > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > > be fine.
> > > > > > 
> > > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > > 
> > > > > > >
> > > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > > taking it out of the loop is a viable option for most users.
> > > > > > 
> > > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > > happening here. The bootflow side is really just about describing what
> > > > > > to do, and this case is no different. For now I see three types of
> > > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > > 
> > > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > > (default file name in case that no image path is specified)?
> > > > > 
> > > > > In fact, this behavior, or removable media support, is defined
> > > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > > What this means is that the boot order, including a removable media
> > > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > > by "BootOrder" variable.
> > > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > > fully comply with the specification.
> > > > > 
> > > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > > semantics can be preserved in your approach.
> > > > 
> > > > I think the high level answer is that whereas today part of
> > > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > > gets run, with what Simon is proposing we would have an easier / quicker
> > > > way to get over to just running that.  Perhaps a clean-up to just use
> > > > that, even?  Or are we not to the point yet where we could remove the
> > > > direct fall-back to /efi/boot/bootXX.efi ?
> > > 
> > > I think "bootefi bootmgr" only works if the BootOrder variable is
> > > defined, and currently that isn't the case.
> > > 
> > > The boot manager behaviour as specified in the UEFI specification is
> > > somewhat problematic to implement in U-Boot because of the limitations
> > > in how variables can be set at runtime.  This is one of the reasons
> > > OpenBSD doesn't actually bother with setting the variables and simple
> > > relies on the "removable media" support mentioned above.  All my
> > > OpenBSD systems that use U-Boot print the follwing lines:
> > > 
> > >   BootOrder not defined
> > >   EFI boot manager: Cannot load any image
> > >   Found EFI removable media binary efi/boot/bootaa64.efi
> > > 
> > > But maybe that last step can be intgrated into bootefi bootmgr at some
> > > point?
> > > 
> > > Also note that manually manipulating the EFI variables to change the
> > > boot order is quite cumbersome; it isn't a matter of just changed the
> > > aforementioned BootOrder variable.  That's why I think boot_targets is
> > > the preferable way to define the order in which devices should be
> > > booted.  I don't think that violates the UEFI specification.  It
> > > merely is the way U-Boot implements the boot device selection that
> > > more traditional UEFI implementations implement using a menu.
> > 
> > As I don't want to side-track Simon's thread even further, I would like
> > to see a bit more detailed explanation of why U-Boot cannot support EFI
> > variables, or if it's just a matter of someone doing the work, and it's
> > not been a priority yet.
> 
> U-Boot has some support for EFI variables, but there are some
> fundamental problems that make "full" support for them hard or even
> impossible.
> 
> Some non-volatile storage is necessary for these variables such that
> they can be persistent across boots.  Obviously this very much applies
> to the BootOrder variable.  EFI defines calls to manipulate variables
> as part of its runtime services.  This means that the NV storage has
> to implemented in a way that doesn't interfere with normal OS usage of
> the hardware.  That pretty much means that you need dedicated hardware
> for this, which most devices supported by U-Boot simply don't have.
> Having the EFI variables in the U-Boot environment on a reserved part
> of a uSD card isn't going to work if the OS assumes it has full
> control over the uSD controller.
> 
> Recent versions of the UEFI have made the implementation of some of
> the runtime services optional (more or less at the request of the EBBR
> folks) and allow certain calls (e.g. the SetVariable() call) to fail.
> This poses a bit of a problem though, which I'll try to sketch here:
> 
> The way things typically work on a x86 EFI system is that you boot
> your OS installer from removable media.  The OS installer does its
> thing (partitions the disk, creates filesystems, installs the OS
> kernel, etc.) and at the end creates a boot option for the boot
> manager by creating an apropriate Boot#### variable and possibly
> modifying the BootOrder variable to include the newly created boot
> option.  A typical x86 Linux distro will create a Boot#### variable
> that is effectively a devicepath pointing at grub.efi.  Unfortunately
> that won't work if the SetVariable() EFI runtime interface doesn't
> work.
> 
> I'm not sure how the EBBR folks envisaged the OS installation user
> experience on these systems.  Maybe Takahiro can explain.  But as long
> as you don't really care about booting multiple OSes on a system,
> relying on the default removable media boot path works fine in most
> cases in that it automatically boots into the installed OS when you
> reboot after removing the installation media.

Ah right, run-time variables are where it gets tricky.  I would think
that when ENV_IS_IN_MMC/etc, where it's a hard location on something,
and not a file (which would be hard to share since it's likely mounted
via the OS) would let us get past that.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-26  6:33                     ` AKASHI Takahiro
@ 2021-08-26 13:03                       ` Tom Rini
  0 siblings, 0 replies; 60+ messages in thread
From: Tom Rini @ 2021-08-26 13:03 UTC (permalink / raw)
  To: AKASHI Takahiro, Mark Kettenis, sjg, manu, u-boot,
	ilias.apalodimas, jaeckel-floss, michal.simek, dennis,
	daniel.schwierzeck, lukas.auer, jh80.chung, mbrugger, peng.fan,
	swarren, swarren

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

On Thu, Aug 26, 2021 at 03:33:07PM +0900, AKASHI Takahiro wrote:
> Mark, Tom,
> 
> On Wed, Aug 25, 2021 at 06:06:05PM -0400, Tom Rini wrote:
> > On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > > > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > > > From: Tom Rini <trini@konsulko.com>
> > > > 
> > > > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > > > Simon,
> > > > > 
> > > > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > > > Hi,
> > > > > > 
> > > > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > > > >
> > > > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > >
> > > > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > > > >
> > > > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > > > Hi Mark,
> > > > > > > > > >
> > > > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > > > >
> > > > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > > > >
> > > > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > > > >
> > > > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > > > >
> > > > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > > > tftp server. 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.
> > > > > > > > > > > >
> > > > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > > > >
> > > > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > > > >
> > > > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > > > >
> > > > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > > > >
> > > > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > > > >
> > > > > > > > > > > > The design is described here:
> > > > > > > > > > > >
> > > > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > > > >
> > > > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > > > >
> > > > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > > > >
> > > > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > > > >
> > > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > > >
> > > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > > would respect this variable.
> > > > > > > >
> > > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > > long as the default of the new code still results in
> > > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > > >
> > > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > > be fine.
> > > > > > 
> > > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > > 
> > > > > > >
> > > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > > taking it out of the loop is a viable option for most users.
> > > > > > 
> > > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > > happening here. The bootflow side is really just about describing what
> > > > > > to do, and this case is no different. For now I see three types of
> > > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > > 
> > > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > > (default file name in case that no image path is specified)?
> > > > > 
> > > > > In fact, this behavior, or removable media support, is defined
> > > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > > What this means is that the boot order, including a removable media
> > > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > > by "BootOrder" variable.
> > > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > > fully comply with the specification.
> > > > > 
> > > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > > semantics can be preserved in your approach.
> > > > 
> > > > I think the high level answer is that whereas today part of
> > > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > > gets run, with what Simon is proposing we would have an easier / quicker
> > > > way to get over to just running that.  Perhaps a clean-up to just use
> > > > that, even?  Or are we not to the point yet where we could remove the
> > > > direct fall-back to /efi/boot/bootXX.efi ?
> > > 
> > > I think "bootefi bootmgr" only works if the BootOrder variable is
> > > defined, and currently that isn't the case.
> > > 
> > > The boot manager behaviour as specified in the UEFI specification is
> > > somewhat problematic to implement in U-Boot because of the limitations
> > > in how variables can be set at runtime.  This is one of the reasons
> > > OpenBSD doesn't actually bother with setting the variables and simple
> > > relies on the "removable media" support mentioned above.  All my
> 
> Well, if this is everyone's consensus in (U-Boot) community,
> it would be fine. But different people may have different
> opinions/requirements on different systems. So I believe that
> the safest way is to make UEFI implementation as compliant to
> the specification as possible.

Since a tangent to this has come up elsewhere recently, I just want to
be clear that we should follow the spec, when there is a spec.

> > > OpenBSD systems that use U-Boot print the follwing lines:
> > > 
> > >   BootOrder not defined
> > >   EFI boot manager: Cannot load any image
> > >   Found EFI removable media binary efi/boot/bootaa64.efi
> > > 
> > > But maybe that last step can be intgrated into bootefi bootmgr at some
> > > point?
> 
> Yes, it is doable, even I'm now trying to examine and address this issue
> as I am fully aware of the situation.

Yay.

> > > Also note that manually manipulating the EFI variables to change the
> > > boot order is quite cumbersome; it isn't a matter of just changed the
> > > aforementioned BootOrder variable.  That's why I think boot_targets is
> > > the preferable way to define the order in which devices should be
> > > booted.  I don't think that violates the UEFI specification.  It
> > > merely is the way U-Boot implements the boot device selection that
> > > more traditional UEFI implementations implement using a menu.
> > 
> > As I don't want to side-track Simon's thread even further, I would like
> > to see a bit more detailed explanation of why U-Boot cannot support EFI
> > variables, or if it's just a matter of someone doing the work, and it's
> > not been a priority yet.
> 
> It is more or less a matter of implementation.
> Historically, removable media support was added to distro_bootcmd first
> and then boot manager was implemented later, only both were integrated
> at script level. Since then, nobody, AFAIK, has complained about
> the lack of integrity. That's what we see now.
> 
> One of difficulties that I found in the implementation is
> how to specify preferred boot media in a form of EFI device path.
> Take an example; I want to do
> => efidebug boot add -b 1 USB usb 0 "" -s ""    ; USB port-1
>                               ^^^^^^^^ no image file specified
> => efidebug boot add -b 2 USB usb 1 "" -s ""    ; USB port-2
> => efidebug boot add -b 3 MMC mmc 0 "" -s ""    ; MMC slot-1
> => efidebug boot add -b 4 MYKERNEL scsi 0:1 /.../vmlinux.efi -s "..."
> => efidebug boot order 1 2 3 4
> => bootefi bootmgr
> 
> First three commands will fail now.
> 
> Under the current implementation, neither "usb 0", "usb 1" nor "mmc 0",
> which is set to be converted to device path representation in BootXXXX
> variable, are recognized as a valid device since there is no physical
> device attached to corresponding bus/port/slots at this time.
> Internally, UEFI system/efidebug always tries to look for a U-Boot's
> existing block device to identify the correct device path.
> (Remember that *buses* and *controller* are even not udevices?).
> So we would have to manage to create a valid internal representation of
> bus or port for those media.
> 
> # FYI, my current prototype work already supports the following command line
> # and enables booting the system from the USB media if some storage device
> # is attached to the port-1:
> # => efidebug boot add -b 1 USB usb 0:1 "" -s ""    ; USB port-1
>                                 ^^^^^^^
> 
> As I'm not well-versed in U-Boot's device model, the rework
> would be simpler than I anticipate.

Thanks for the update on where you're at so far.

-- 
Tom

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

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-26 13:00                       ` Tom Rini
@ 2021-08-26 13:32                         ` Mark Kettenis
  2021-08-26 13:50                           ` Ilias Apalodimas
  0 siblings, 1 reply; 60+ messages in thread
From: Mark Kettenis @ 2021-08-26 13:32 UTC (permalink / raw)
  To: Tom Rini
  Cc: takahiro.akashi, sjg, manu, u-boot, ilias.apalodimas,
	jaeckel-floss, michal.simek, dennis, daniel.schwierzeck,
	lukas.auer, jh80.chung, mbrugger, peng.fan, swarren, swarren

> Date: Thu, 26 Aug 2021 09:00:01 -0400
> From: Tom Rini <trini@konsulko.com>
> 
> On Thu, Aug 26, 2021 at 02:01:07PM +0200, Mark Kettenis wrote:
> > > Date: Wed, 25 Aug 2021 18:06:05 -0400
> > > From: Tom Rini <trini@konsulko.com>
> > > 
> > > On Wed, Aug 25, 2021 at 11:54:58PM +0200, Mark Kettenis wrote:
> > > > > Date: Wed, 25 Aug 2021 10:56:35 -0400
> > > > > From: Tom Rini <trini@konsulko.com>
> > > > > 
> > > > > On Wed, Aug 25, 2021 at 11:42:51PM +0900, AKASHI Takahiro wrote:
> > > > > > Simon,
> > > > > > 
> > > > > > On Wed, Aug 25, 2021 at 07:11:44AM -0600, Simon Glass wrote:
> > > > > > > Hi,
> > > > > > > 
> > > > > > > On Wed, 25 Aug 2021 at 04:45, Emmanuel Vadot <manu@bidouilliste.com> wrote:
> > > > > > > >
> > > > > > > > On Tue, 24 Aug 2021 12:22:42 +0200 (CEST)
> > > > > > > > Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > >
> > > > > > > > > > Date: Mon, 23 Aug 2021 16:01:46 -0400
> > > > > > > > > > From: Tom Rini <trini@konsulko.com>
> > > > > > > > > >
> > > > > > > > > > On Mon, Aug 23, 2021 at 11:25:42AM -0600, Simon Glass wrote:
> > > > > > > > > > > Hi Mark,
> > > > > > > > > > >
> > > > > > > > > > > On Mon, 23 Aug 2021 at 05:54, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > From: Simon Glass <sjg@chromium.org>
> > > > > > > > > > > > > Date: Wed, 18 Aug 2021 21:45:33 -0600
> > > > > > > > > > > > >
> > > > > > > > > > > > > Bootmethod and bootflow provide a built-in way for U-Boot to automatically boot
> > > > > > > > > > > > > an Operating System without custom scripting and other customisation:
> > > > > > > > > > > > >
> > > > > > > > > > > > >   - bootmethod - a method to scan a device to find bootflows (owned by U-Boot)
> > > > > > > > > > > > >   - bootflow - a description of how to boot (owned by the distro)
> > > > > > > > > > > > >
> > > > > > > > > > > > > This series provides an initial implementation of these, enable to scan
> > > > > > > > > > > > > for bootflows from MMC and Ethernet. The only bootflow supported is
> > > > > > > > > > > > > distro boot, i.e. an extlinux.conf file included on a filesystem or
> > > > > > > > > > > > > tftp server. 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.
> > > > > > > > > > > > >
> > > > > > > > > > > > > It is intended that this approach be expanded to support mechanisms other
> > > > > > > > > > > > > than distro boot, including EFI-related ones. With a standard way to
> > > > > > > > > > > > > identify boot devices, these features become easier. It also should
> > > > > > > > > > > > > support U-Boot scripts, for backwards compatibility only.
> > > > > > > > > > > > >
> > > > > > > > > > > > > The first patch of this series moves boot-related code out of common/ and
> > > > > > > > > > > > > into a new boot/ directory. This helps to collect these related files
> > > > > > > > > > > > > in one place, as common/ is quite large.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Like sysboot, this feature makes use of the existing PXE implementation.
> > > > > > > > > > > > > Much of this series consists of cleaning up that code and refactoring it
> > > > > > > > > > > > > into something closer to a module that can be called, teasing apart its
> > > > > > > > > > > > > reliance on the command-line interpreter to access filesystems and the
> > > > > > > > > > > > > like. Also it now uses function arguments and its own context struct
> > > > > > > > > > > > > internally rather than environment variables, which is very hard to
> > > > > > > > > > > > > follow. No core functional change is included in the included PXE patches.
> > > > > > > > > > > > >
> > > > > > > > > > > > > For documentation, see the 'doc' patch.
> > > > > > > > > > > > >
> > > > > > > > > > > > > There is quite a long list of future work included in the documentation.
> > > > > > > > > > > > > One question is the choice of naming. Since this is a bootloader, should
> > > > > > > > > > > > > we just call this a 'method' and a 'flow' ? The 'boot' prefix is already
> > > > > > > > > > > > > shared by other commands like bootm, booti, etc.
> > > > > > > > > > > > >
> > > > > > > > > > > > > The design is described here:
> > > > > > > > > > > > >
> > > > > > > > > > > > > https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
> > > > > > > > > > > > >
> > > > > > > > > > > > > The series is available at u-boot-dm/bmea-working
> > > > > > > > > > > >
> > > > > > > > > > > > How does the user control the order in which devices are scanned/booted?
> > > > > > > > > > >
> > > > > > > > > > > That is not supported in distroboot at present, at least so far as I
> > > > > > > > > > > can see. For Fedora it seems to happen in grub. Do I have that right?
> > > > > > > > > >
> > > > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > > > >
> > > > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > > > would respect this variable.
> > > > > > > > >
> > > > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > > > long as the default of the new code still results in
> > > > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > > > >
> > > > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > > > be fine.
> > > > > > > 
> > > > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > > > 
> > > > > > > >
> > > > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > > > taking it out of the loop is a viable option for most users.
> > > > > > > 
> > > > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > > > happening here. The bootflow side is really just about describing what
> > > > > > > to do, and this case is no different. For now I see three types of
> > > > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > > > 
> > > > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > > > (default file name in case that no image path is specified)?
> > > > > > 
> > > > > > In fact, this behavior, or removable media support, is defined
> > > > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > > > What this means is that the boot order, including a removable media
> > > > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > > > by "BootOrder" variable.
> > > > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > > > fully comply with the specification.
> > > > > > 
> > > > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > > > semantics can be preserved in your approach.
> > > > > 
> > > > > I think the high level answer is that whereas today part of
> > > > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > > > gets run, with what Simon is proposing we would have an easier / quicker
> > > > > way to get over to just running that.  Perhaps a clean-up to just use
> > > > > that, even?  Or are we not to the point yet where we could remove the
> > > > > direct fall-back to /efi/boot/bootXX.efi ?
> > > > 
> > > > I think "bootefi bootmgr" only works if the BootOrder variable is
> > > > defined, and currently that isn't the case.
> > > > 
> > > > The boot manager behaviour as specified in the UEFI specification is
> > > > somewhat problematic to implement in U-Boot because of the limitations
> > > > in how variables can be set at runtime.  This is one of the reasons
> > > > OpenBSD doesn't actually bother with setting the variables and simple
> > > > relies on the "removable media" support mentioned above.  All my
> > > > OpenBSD systems that use U-Boot print the follwing lines:
> > > > 
> > > >   BootOrder not defined
> > > >   EFI boot manager: Cannot load any image
> > > >   Found EFI removable media binary efi/boot/bootaa64.efi
> > > > 
> > > > But maybe that last step can be intgrated into bootefi bootmgr at some
> > > > point?
> > > > 
> > > > Also note that manually manipulating the EFI variables to change the
> > > > boot order is quite cumbersome; it isn't a matter of just changed the
> > > > aforementioned BootOrder variable.  That's why I think boot_targets is
> > > > the preferable way to define the order in which devices should be
> > > > booted.  I don't think that violates the UEFI specification.  It
> > > > merely is the way U-Boot implements the boot device selection that
> > > > more traditional UEFI implementations implement using a menu.
> > > 
> > > As I don't want to side-track Simon's thread even further, I would like
> > > to see a bit more detailed explanation of why U-Boot cannot support EFI
> > > variables, or if it's just a matter of someone doing the work, and it's
> > > not been a priority yet.
> > 
> > U-Boot has some support for EFI variables, but there are some
> > fundamental problems that make "full" support for them hard or even
> > impossible.
> > 
> > Some non-volatile storage is necessary for these variables such that
> > they can be persistent across boots.  Obviously this very much applies
> > to the BootOrder variable.  EFI defines calls to manipulate variables
> > as part of its runtime services.  This means that the NV storage has
> > to implemented in a way that doesn't interfere with normal OS usage of
> > the hardware.  That pretty much means that you need dedicated hardware
> > for this, which most devices supported by U-Boot simply don't have.
> > Having the EFI variables in the U-Boot environment on a reserved part
> > of a uSD card isn't going to work if the OS assumes it has full
> > control over the uSD controller.
> > 
> > Recent versions of the UEFI have made the implementation of some of
> > the runtime services optional (more or less at the request of the EBBR
> > folks) and allow certain calls (e.g. the SetVariable() call) to fail.
> > This poses a bit of a problem though, which I'll try to sketch here:
> > 
> > The way things typically work on a x86 EFI system is that you boot
> > your OS installer from removable media.  The OS installer does its
> > thing (partitions the disk, creates filesystems, installs the OS
> > kernel, etc.) and at the end creates a boot option for the boot
> > manager by creating an apropriate Boot#### variable and possibly
> > modifying the BootOrder variable to include the newly created boot
> > option.  A typical x86 Linux distro will create a Boot#### variable
> > that is effectively a devicepath pointing at grub.efi.  Unfortunately
> > that won't work if the SetVariable() EFI runtime interface doesn't
> > work.
> > 
> > I'm not sure how the EBBR folks envisaged the OS installation user
> > experience on these systems.  Maybe Takahiro can explain.  But as long
> > as you don't really care about booting multiple OSes on a system,
> > relying on the default removable media boot path works fine in most
> > cases in that it automatically boots into the installed OS when you
> > reboot after removing the installation media.
> 
> Ah right, run-time variables are where it gets tricky.  I would think
> that when ENV_IS_IN_MMC/etc, where it's a hard location on something,
> and not a file (which would be hard to share since it's likely mounted
> via the OS) would let us get past that.

Not really.  As soon as the OS takes over the MMC controller, U-Boot
can't touch it anymore.  The only thing that really works is using a
dedicated device that isn't exposed to the OS.  So U-Boot would need
to remove its nodes from the device tree.  But even then things get
tricky with shared clocks and such.

The only really safe option is to use something like TrustZone on ARM
devices to completely hide things from the non-secure world.  I
believe that is what Linaro is actually doing in their U-Boot based
implementation where the EFI variable store is actually implemented in
OP-TEE running in the secure world.  However that places demands on
the hardware that many SoCs and boards won't be able to fulfill.

A lot of the more advance EFI features that have been
implemented/proposed (secure boot, capsule updates) do rely on having
proper run-time variable support.  So Simon does have a point that the
EFI based approach for that has some serious issues that a "native"
U-Boot implementation could avoid and that enabling these EFI features
by default adds unecessary "bloat".

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

* Re: [PATCH 00/28] Initial implementation of bootmethod/bootflow
  2021-08-26 13:32                         ` Mark Kettenis
@ 2021-08-26 13:50                           ` Ilias Apalodimas
  0 siblings, 0 replies; 60+ messages in thread
From: Ilias Apalodimas @ 2021-08-26 13:50 UTC (permalink / raw)
  To: Mark Kettenis
  Cc: Tom Rini, takahiro.akashi, sjg, manu, u-boot, jaeckel-floss,
	michal.simek, dennis, daniel.schwierzeck, lukas.auer, jh80.chung,
	mbrugger, peng.fan, swarren, swarren

Hi Mark, 

> > > > > > > > > > >

[...]

> > > > > > > > > > > Well, there's "find the next stage", which is boot_targets environment
> > > > > > > > > > > variable, and then "where that next stage looks for stuff" which is
> > > > > > > > > > > OS-dependent.  Sometimes the ESP grub.cfg file is just enough to tell
> > > > > > > > > > > grub to find the full grub.cfg file elsewhere, and sometimes it's a full
> > > > > > > > > > > grub.cfg file.  I think Mark is talking about the former, and you've
> > > > > > > > > > > said it's not part of this series, yet, but on the TODO list.
> > > > > > > > > >
> > > > > > > > > > Right.  With the current distroboot code the order of the devices that
> > > > > > > > > > appears in boot_targets is determined by per-board/SOC/machine config
> > > > > > > > > > files and the order isn't the same for all of them.  Users can change
> > > > > > > > > > the order if necessary by modifying the environment variable and
> > > > > > > > > > saving the environment.  And for a one-off boot from a different
> > > > > > > > > > device they can simply run an appropriate boot command.  The
> > > > > > > > > > boot_targets variable in particular is documented in various install
> > > > > > > > > > documents so it would probably be good of the new "bootmethod" code
> > > > > > > > > > would respect this variable.
> > > > > > > > > >
> > > > > > > > > > For OpenBSD I'm not really interested in the bootflow part.  As I
> > > > > > > > > > explained in the past, that part of the problem is solved in a
> > > > > > > > > > (mostly) uniform way across platforms by the OpenBSD bootloader which
> > > > > > > > > > can read an /etc/boot.conf that allows bootflow customization.  So as
> > > > > > > > > > long as the default of the new code still results in
> > > > > > > > > > \EFI\BOOT\BOOT{machine type short-name}.EFI being loaded and run if
> > > > > > > > > > there is no U-Boot specific bootflow configured, I'm happy.
> > > > > > > > >
> > > > > > > > >  Mostly the same for FreeBSD, as long as the efi boot<arch>.efi is
> > > > > > > > > loaded and run by default (respecting the boot_targets order) we will
> > > > > > > > > be fine.
> > > > > > > > 
> > > > > > > > OK thanks for the info. My expectation is that bootmethod/bootflow can
> > > > > > > > support this easily enough (it is actually simpler than distro boot).
> > > > > > > > 
> > > > > > > > >
> > > > > > > > > > I can't speak for the other BSDs, but my impression is that they are
> > > > > > > > > > pretty much in the same position.  The FreeBSD bootloader for example
> > > > > > > > > > supports a high-degree of "bootflow" customization and I doubt that
> > > > > > > > > > taking it out of the loop is a viable option for most users.
> > > > > > > > 
> > > > > > > > I think the same may happen with grub. E.g. with Ubuntu I see quite a
> > > > > > > > bit of code in the grub.cfg file and it's not clear to me that it can
> > > > > > > > be replaced with a 'data instead of code' approach. Still, a valid
> > > > > > > > bootflow is simply to jump to an EFI app, which seems to be what is
> > > > > > > > happening here. The bootflow side is really just about describing what
> > > > > > > > to do, and this case is no different. For now I see three types of
> > > > > > > > bootflow, PXE/syslinux, EFI boot manager and EFI app.
> > > > > > > 
> > > > > > > By "EFI app", do you mean a way of booting "/efi/boot/bootXX.efi"
> > > > > > > (default file name in case that no image path is specified)?
> > > > > > > 
> > > > > > > In fact, this behavior, or removable media support, is defined
> > > > > > > as part of UEFI boot manager in UEFI specification. (See section 3.5)
> > > > > > > What this means is that the boot order, including a removable media
> > > > > > > case and user-provided BootXXXX cases, should be controlled solely
> > > > > > > by "BootOrder" variable.
> > > > > > > So the current combination of distro_bootcmd + UEFI boot manger doesn't
> > > > > > > fully comply with the specification.
> > > > > > > 
> > > > > > > Even if those two cases are integrated, I don't know how "BootOrder"
> > > > > > > semantics can be preserved in your approach.
> > > > > > 
> > > > > > I think the high level answer is that whereas today part of
> > > > > > distro_bootcmd (and so iterating over boot_targets) "bootefi bootmgr"
> > > > > > gets run, with what Simon is proposing we would have an easier / quicker
> > > > > > way to get over to just running that.  Perhaps a clean-up to just use
> > > > > > that, even?  Or are we not to the point yet where we could remove the
> > > > > > direct fall-back to /efi/boot/bootXX.efi ?
> > > > > 
> > > > > I think "bootefi bootmgr" only works if the BootOrder variable is
> > > > > defined, and currently that isn't the case.
> > > > > 
> > > > > The boot manager behaviour as specified in the UEFI specification is
> > > > > somewhat problematic to implement in U-Boot because of the limitations
> > > > > in how variables can be set at runtime.  This is one of the reasons
> > > > > OpenBSD doesn't actually bother with setting the variables and simple
> > > > > relies on the "removable media" support mentioned above.  All my
> > > > > OpenBSD systems that use U-Boot print the follwing lines:
> > > > > 
> > > > >   BootOrder not defined
> > > > >   EFI boot manager: Cannot load any image
> > > > >   Found EFI removable media binary efi/boot/bootaa64.efi
> > > > > 
> > > > > But maybe that last step can be intgrated into bootefi bootmgr at some
> > > > > point?
> > > > > 
> > > > > Also note that manually manipulating the EFI variables to change the
> > > > > boot order is quite cumbersome; it isn't a matter of just changed the
> > > > > aforementioned BootOrder variable.  That's why I think boot_targets is
> > > > > the preferable way to define the order in which devices should be
> > > > > booted.  I don't think that violates the UEFI specification.  It
> > > > > merely is the way U-Boot implements the boot device selection that
> > > > > more traditional UEFI implementations implement using a menu.
> > > > 
> > > > As I don't want to side-track Simon's thread even further, I would like
> > > > to see a bit more detailed explanation of why U-Boot cannot support EFI
> > > > variables, or if it's just a matter of someone doing the work, and it's
> > > > not been a priority yet.
> > > 
> > > U-Boot has some support for EFI variables, but there are some
> > > fundamental problems that make "full" support for them hard or even
> > > impossible.
> > > 
> > > Some non-volatile storage is necessary for these variables such that
> > > they can be persistent across boots.  Obviously this very much applies
> > > to the BootOrder variable.  EFI defines calls to manipulate variables
> > > as part of its runtime services.  This means that the NV storage has
> > > to implemented in a way that doesn't interfere with normal OS usage of
> > > the hardware.  That pretty much means that you need dedicated hardware
> > > for this, which most devices supported by U-Boot simply don't have.
> > > Having the EFI variables in the U-Boot environment on a reserved part
> > > of a uSD card isn't going to work if the OS assumes it has full
> > > control over the uSD controller.
> > > 
> > > Recent versions of the UEFI have made the implementation of some of
> > > the runtime services optional (more or less at the request of the EBBR
> > > folks) and allow certain calls (e.g. the SetVariable() call) to fail.
> > > This poses a bit of a problem though, which I'll try to sketch here:
> > > 
> > > The way things typically work on a x86 EFI system is that you boot
> > > your OS installer from removable media.  The OS installer does its
> > > thing (partitions the disk, creates filesystems, installs the OS
> > > kernel, etc.) and at the end creates a boot option for the boot
> > > manager by creating an apropriate Boot#### variable and possibly
> > > modifying the BootOrder variable to include the newly created boot
> > > option.  A typical x86 Linux distro will create a Boot#### variable
> > > that is effectively a devicepath pointing at grub.efi.  Unfortunately
> > > that won't work if the SetVariable() EFI runtime interface doesn't
> > > work.
> > > 
> > > I'm not sure how the EBBR folks envisaged the OS installation user
> > > experience on these systems.  Maybe Takahiro can explain.  But as long
> > > as you don't really care about booting multiple OSes on a system,
> > > relying on the default removable media boot path works fine in most
> > > cases in that it automatically boots into the installed OS when you
> > > reboot after removing the installation media.
> > 
> > Ah right, run-time variables are where it gets tricky.  I would think
> > that when ENV_IS_IN_MMC/etc, where it's a hard location on something,
> > and not a file (which would be hard to share since it's likely mounted
> > via the OS) would let us get past that.
> 
> Not really.  As soon as the OS takes over the MMC controller, U-Boot
> can't touch it anymore.  The only thing that really works is using a
> dedicated device that isn't exposed to the OS.  So U-Boot would need
> to remove its nodes from the device tree.  But even then things get
> tricky with shared clocks and such.
> 
> The only really safe option is to use something like TrustZone on ARM
> devices to completely hide things from the non-secure world. 

That's how it also works on servers. They all have dedicated hardware

> I believe that is what Linaro is actually doing in their U-Boot based
> implementation where the EFI variable store is actually implemented in
> OP-TEE running in the secure world.  However that places demands on
> the hardware that many SoCs and boards won't be able to fulfill.
> 

There's two general categories here
- SPI/whatever flash on the secure world. That pretty much solves
  everything, but as you say, imposes hardware restrictions and the runtime
  part is missing from U-Boot.
- store the variables on an RPMB partition.  This currently works on
  u-boot. It doesn't directly solve the problem with runtime variables, but
  you can get away with it if the OS agrees (which is against what EFI is
  trying to do :)).  So the RPMB variable storage goes through OP-TEE, I
  have some out of tree patches for Linux, were the bootloader is
  installing an empty config table. Upon discovery the OS changes all the
  runtime callbacks to OP-TEE provided functions, so you can read/write
  variables properly.  I understand that this isn't the best solution, but
  honestly from the discussions and thoughts I've had up to now, it seems
  the sanest way to solve the setvariable problem, if the OS is in control
  of the medium after ExitBootServices. We are in discussions internally to 
  see if there's a better way to do it, and I am open to suggestions. In
  any case the OS has to do 'something' about it, since it controls the
  device.

> A lot of the more advance EFI features that have been
> implemented/proposed (secure boot, capsule updates) do rely on having
> proper run-time variable support. 

0fa5020c024e 'fixes' capsule update on-disk (but kinda breaks the spec)

> So Simon does have a point that the
> EFI based approach for that has some serious issues that a "native"
> U-Boot implementation could avoid and that enabling these EFI features
> by default adds unecessary "bloat".

Regards
/Ilias


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

end of thread, other threads:[~2021-08-26 13:51 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-19  3:45 [PATCH 00/28] Initial implementation of bootmethod/bootflow Simon Glass
2021-08-19  3:45 ` [PATCH 01/28] Create a new boot/ directory Simon Glass
2021-08-19  3:45 ` [PATCH 02/28] pxe: Move API comments to the header files Simon Glass
2021-08-19  3:45 ` [PATCH 03/28] pxe: Use a context pointer Simon Glass
2021-08-19  3:45 ` [PATCH 04/28] pxe: Move do_getfile() into the context Simon Glass
2021-08-19  3:45 ` [PATCH 05/28] pxe: Add a userdata field to " Simon Glass
2021-08-19  3:45 ` [PATCH 06/28] pxe: Tidy up the is_pxe global Simon Glass
2021-08-19  3:45 ` [PATCH 07/28] pxe: Move pxe_utils files Simon Glass
2021-08-19  3:45 ` [PATCH 08/28] pxe: Tidy up some comments in pxe_utils Simon Glass
2021-08-19  3:45 ` [PATCH 09/28] pxe: Tidy up code style a little " Simon Glass
2021-08-19  3:45 ` [PATCH 10/28] pxe: Move common parsing coding into pxe_util Simon Glass
2021-08-19  3:45 ` [PATCH 11/28] pxe: Clean up the use of bootfile Simon Glass
2021-08-19  3:45 ` [PATCH 12/28] pxe: Drop get_bootfile_path() Simon Glass
2021-08-19  3:45 ` [PATCH 13/28] lib: Add tests for simple_itoa() Simon Glass
2021-08-19  3:45 ` [PATCH 14/28] lib: Add a function to convert a string to a hex value Simon Glass
2021-08-19  3:45 ` [PATCH 15/28] pxe: Return the file size from the getfile() function Simon Glass
2021-08-19  3:45 ` [PATCH 16/28] pxe: Refactor sysboot to have one helper Simon Glass
2021-08-19  3:45 ` [PATCH 17/28] doc: Move distro boot doc to rST Simon Glass
2021-08-19  3:45 ` [PATCH 18/28] pxe: Allow calling the pxe_get logic directly Simon Glass
2021-08-19  3:45 ` [PATCH 19/28] bootmethod: Add the uclass and core implementation Simon Glass
2021-08-19  3:45 ` [PATCH 20/28] bootmethod: Add an implementation of distro boot Simon Glass
2021-08-19  3:45 ` [PATCH 21/28] bootmethod: Add a command Simon Glass
2021-08-19  3:45 ` [PATCH 22/28] bootflow: " Simon Glass
2021-08-19  3:45 ` [PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow Simon Glass
2021-08-19  3:45 ` [PATCH 24/28] bootmethod: doc: Add documentation Simon Glass
2021-08-19  3:45 ` [PATCH 25/28] mmc: Allow for children other than the block device Simon Glass
2021-08-19  3:45 ` [PATCH 26/28] mmc: Add a bootmethod Simon Glass
2021-08-19  3:46 ` [PATCH 27/28] ethernet: " Simon Glass
2021-08-19  3:46 ` [PATCH 28/28] RFC: rpi: Switch over to use bootflow Simon Glass
2021-08-19 13:59 ` [PATCH 00/28] Initial implementation of bootmethod/bootflow Tom Rini
2021-08-19 14:25   ` Simon Glass
2021-08-19 17:27     ` Tom Rini
2021-08-23 12:35       ` Ilias Apalodimas
2021-08-23 17:25         ` Simon Glass
2021-08-23 20:08           ` Tom Rini
2021-08-24  9:29             ` Ilias Apalodimas
2021-08-25 13:11               ` Simon Glass
2021-08-25 13:29                 ` Peter Robinson
2021-08-25 21:34                   ` Mark Kettenis
2021-08-25 21:58                     ` Tom Rini
2021-08-20  3:15     ` AKASHI Takahiro
2021-08-20 18:22       ` Simon Glass
2021-08-23  0:46         ` AKASHI Takahiro
2021-08-23 11:54 ` Mark Kettenis
2021-08-23 17:25   ` Simon Glass
2021-08-23 20:01     ` Tom Rini
2021-08-24 10:22       ` Mark Kettenis
2021-08-25 10:45         ` Emmanuel Vadot
2021-08-25 13:11           ` Simon Glass
2021-08-25 14:42             ` AKASHI Takahiro
2021-08-25 14:56               ` Tom Rini
2021-08-25 21:54                 ` Mark Kettenis
2021-08-25 22:06                   ` Tom Rini
2021-08-26  6:33                     ` AKASHI Takahiro
2021-08-26 13:03                       ` Tom Rini
2021-08-26 12:01                     ` Mark Kettenis
2021-08-26 13:00                       ` Tom Rini
2021-08-26 13:32                         ` Mark Kettenis
2021-08-26 13:50                           ` Ilias Apalodimas
2021-08-26 11:55                 ` Peter Robinson

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.