All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/18] efi_loader: add capsule update support
@ 2020-11-13  4:14 AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 01/18] dfu: rename dfu_tftp_write() to dfu_write_by_name() AKASHI Takahiro
                   ` (18 more replies)
  0 siblings, 19 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

Summary
=======
'UpdateCapsule' is one of runtime services defined in UEFI specification
and its aim is to allow a caller (OS) to pass information to the firmware,
i.e. U-Boot. This is mostly used to update firmware binary on devices by
instructions from OS.

While 'UpdateCapsule' is a runtime services function, it is, at least
initially, supported only before exiting boot services alike other runtime
functions, [Get/]SetVariable. This is because modifying storage which may
be shared with OS must be carefully designed and there is no general
assumption that we can do it.

Therefore, we practically support only "capsule on disk"; any capsule can
be handed over to UEFI subsystem as a file on a specific file system.

In this patch series, all the related definitions and structures are given
as UEFI specification describes, and basic framework for capsule support
is provided. Currently supported is
 * firmware update (Firmware Management Protocol or simply FMP)

Most of functionality of firmware update is provided by FMP driver and
it can be, by nature, system/platform-specific. So you can and should
implement your own FMP driver(s) based on your system requirements.
Under the current implementation, we provide two basic but generic
drivers with two formats:
  * FIT image format (as used in TFTP update and dfu)
  * raw image format

It's totally up to users which one, or both, should be used on users'
system depending on user requirements.

Quick usage
===========
1. You can create a capsule file with the following host command:

  $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>

2. Put the file under:

  /EFI/UpdateCapsule of UEFI system partition

3. Specify firmware storage to be updated in "dfu_alt_info" variable
   (Please follow README.dfu for details.)

  ==> env set dfu_alt_info '...'

4. After setting up UEFI's OsIndications variable, reboot U-Boot:

  OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED

Patch structure
===============
Patch#1-#4,#12: preparatory patches
Patch#5-#11,#13: main part of implementation
Patch#14-#15: utilities
Patch#16-#17: pytests
Patch#18: for sandbox test

[1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule

Prerequisite patches
====================
None

Test
====
* passed all the pytests which are included in this patch series
  on sandbox build locally.
* skipped (or 'S', but it's not a failure, 'F') in Travis CI because
  "virt-make-fs" cannot be executed.

Issues
======
* Timing of executing capsules-on-disk
  Currently, processing a capsule is triggered only as part of
  UEFI subsystem initialization. This means that, for example,
  firmware update, may not take place@system booting time and
  will potentially be delayed until a first call of any UEFI functions.
    => See patch#5 for my proposal
* A bunch of warnings like
    WARNING: Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef'
    where possible
  I don't think that fixing those improves anything.
* Add a document in uefi.rst

TODO's
======
(Won't be addressed in this series.)
* capsule authentication
* capsule dependency (dependency expression instruction set, or depex)
* loading drivers in a capsule
* handling RESET flag in a capsule and QeuryCapsuleCaps
* full semantics of ESRT (EFI System Resource Table)
* enabling capsule API at runtime
* json capsule
* recovery from update failure

Changes
=======
v8 (November 13, 2020)
* fix a "not used" warning against update_load() in some configuration
  (Patch#3)
* fix failures (marked as 'F') in *secure boot* test in Travis CI by
  making "EFI_CAPSULE_ON_DISK_EARLY" 'default n' (Patch#8)
* fix failures (marked as 'E') at pytest setup in Travis CI by changing
  a python file's name along with removing unused definitions (Patch#16)
* add Patch#18 to enable tests to be run with default sandbox config
  (Patch#18)

v7 (October 29, 2020)
* rename CONFIG_DFU_ALT to CONFIG_DFU_WRITE_ALT (Patch#1,#3,#13)

v6 RESEND (October 29, 2020)
* rebased on v2021.01-rc1

v6 (September 7, 2020)
* temporarily drop the prerequisite patch[2]
* add a missing field (dependencies) in efi_api.h (but never used) (Patch#10)
* add a missing field (image_capsule_support) and related definitions
  in efi_api.h (Patch#10, #15)
* cosmetic changes on constant definitions in efi_api.h (Patch#10)
* strict check for INVALID_PARAMETER at GET_IMAGE_INFO api (Patch#11,#13)
* fix warnings in pytest (Patch#16,#17)

v5 (August 3, 2020)
* removed superfluous type conversion at dfu_write_from_mem_addr()
  (Patch#2)
* introduced a common helper function, efi_create_indexed_name()
  (Patch#6,#7,#8)
* use efi_[get|set]_variable_int(), if necessary, with READ_ONLY
  (Patch#7,#8)
* return EFI_UNSUPPORTED at Patch#7
* changed the word, number, to 'index' (Patch#7,#8)
* removed 'ifdef CONFIG_EFI_CAPSULE_ON_DISK' from a header (Patch#8)
* initialize 'CapsuleLast' in efi_init_obj_list() (Patch#7,#8)
* added 'const' qualifier for filename argument at
  efi_capsule_[read|delete]_file() (Patch#8)

v4 (July 22, 2020)
* rebased to Heinrich's current efi-2020-10
* rework dfu-related code to align with Heinrich's change (Patch#1,#3)
* change a type of 'addr' argument from int to 'void *' per Sughosh's
  comment (Patch#2-#3,#11-#12)
* rework/simplify pytests (Patch#15-#16)
  - utilize virt-make-fs
  - drop Test Case 1 (updating U-Boot environment data)
  - remove useless definitions (MNT_PNT, EFI_CAPSULE_IMAGE_NAME)
  - apply autopep8

v3 (July 10, 2020)
* rebased to Heinrich's current efi-2020-10-rc1
* refactor efi_firmware_[fit|raw]_get_image_info() (patch#11,#13)

v2 (June 17, 2020)
* rebased to v2020.07-rc4
* add preparatory patches for dfu (Patch#1-#5, #12)
* rework FIT capsule driver to utilize dfu_alt_info instead of CONFIG_xxx
  (patch#11)
* extend get_image_info() to correspond to dfu_alt_info
  (patch#11)
* add a 'raw binary' capsule support
  (patch#13, #17)
* allow multiple capsule formats (with different GUIDs) to be installed
  (patch#11, #13)
* extend mkeficapsule command to accept additional parameters, like
    version/index/hardware instance for a capsule header info.
  (patch#15)
* mkeficapsule can now also generate raw-binary capsule
  (patch#16)
* add function descriptions
* apply autopep8 to pytests and fix more against pylint

v1 (April 27, 2020)
* rebased to v2020.07-rc
* removed already-merged patches (RFC's #1 to #4)
* dropped 'variable update' capsule support (RFC's patch#10)
* dropped 'variable configuration table' support (RFC's patch#11)
  (Those two should be discussed separately.)
* add preparatory patches (patch#1/#2)
* fix several build errors
* rename some Kconfig options to be aligned with UEFI specification's terms
  (patch#3,4,6,7)
* enforce UpdateCapsule API to be disabled after ExitBootServices (patch#3)
* use config table, runtime_services_supported, instead of variable (patch#3)
* make EFI_CAPSULE_ON_DISK buildable even if UpdateCapsule API is disabled
  (patch4)
* support OsIndications, invoking capsule-on-disk only if the variable
  indicates so (patch#4)
* introduced EFI_CAPSULE_ON_DISK_EARLY to invoke capsule-on-disk in U-Boot
  initialization (patch#4)
* detect capsule files only if they are on EFI system partition (patch#4)
* use printf, rather than EFI_PRINT, in error cases (patch#4)
* use 'header_size' field to retrieve capsule data, adding sanity checks
  against capsule size (patch#6)
* call fmpt driver interfaces with EFI_CALL (patch#6)
* remove 'variable update capsule'-related code form mkeficapsule (patch#9)
* add a test case of OsIndications not being set properly (patch#10)
* adjust test scenario for EFI_CAPSULE_ON_DISK_EARLY (patch#10)
* revise pytest scripts (patch#10)

Initial release as RFC (March 17, 2020)

AKASHI Takahiro (18):
  dfu: rename dfu_tftp_write() to dfu_write_by_name()
  dfu: modify an argument type for an address
  common: update: add a generic interface for FIT image
  dfu: export dfu_list
  efi_loader: add option to initialise EFI subsystem early
  efi_loader: add efi_create_indexed_name()
  efi_loader: define UpdateCapsule api
  efi_loader: capsule: add capsule_on_disk support
  efi_loader: capsule: add memory range capsule definitions
  efi_loader: capsule: support firmware update
  efi_loader: add firmware management protocol for FIT image
  dfu: add dfu_write_by_alt()
  efi_loader: add firmware management protocol for raw image
  cmd: add "efidebug capsule" command
  tools: add mkeficapsule command for UEFI capsule update
  test/py: efi_capsule: test for FIT image capsule
  test/py: efi_capsule: test for raw image capsule
  sandbox: enable capsule update for testing

 cmd/efidebug.c                                | 235 +++++
 common/Kconfig                                |  15 +
 common/Makefile                               |   3 +-
 common/board_r.c                              |   6 +
 common/main.c                                 |   4 +
 common/update.c                               |  77 +-
 configs/sandbox64_defconfig                   |   6 +
 configs/sandbox_defconfig                     |   6 +
 drivers/dfu/Kconfig                           |   5 +
 drivers/dfu/Makefile                          |   2 +-
 drivers/dfu/dfu.c                             |   2 +-
 drivers/dfu/dfu_alt.c                         | 125 +++
 drivers/dfu/dfu_tftp.c                        |  65 --
 include/dfu.h                                 |  57 +-
 include/efi_api.h                             | 166 ++++
 include/efi_loader.h                          |  30 +
 include/image.h                               |  12 +
 lib/efi_loader/Kconfig                        |  72 ++
 lib/efi_loader/Makefile                       |   2 +
 lib/efi_loader/efi_capsule.c                  | 917 ++++++++++++++++++
 lib/efi_loader/efi_firmware.c                 | 403 ++++++++
 lib/efi_loader/efi_runtime.c                  | 104 +-
 lib/efi_loader/efi_setup.c                    | 106 +-
 .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
 test/py/tests/test_efi_capsule/conftest.py    |  74 ++
 .../test_efi_capsule/test_capsule_firmware.py | 241 +++++
 .../tests/test_efi_capsule/uboot_bin_env.its  |  36 +
 tools/Makefile                                |   2 +
 tools/mkeficapsule.c                          | 239 +++++
 29 files changed, 2877 insertions(+), 140 deletions(-)
 create mode 100644 drivers/dfu/dfu_alt.c
 delete mode 100644 drivers/dfu/dfu_tftp.c
 create mode 100644 lib/efi_loader/efi_capsule.c
 create mode 100644 lib/efi_loader/efi_firmware.c
 create mode 100644 test/py/tests/test_efi_capsule/capsule_defs.py
 create mode 100644 test/py/tests/test_efi_capsule/conftest.py
 create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py
 create mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
 create mode 100644 tools/mkeficapsule.c

-- 
2.28.0

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

* [PATCH v8 01/18] dfu: rename dfu_tftp_write() to dfu_write_by_name()
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 02/18] dfu: modify an argument type for an address AKASHI Takahiro
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

This function is essentially independent from tftp, and will also be
utilised in implementing UEFI capsule update in a later commit.
So just give it a more generic name.
In addition, a new configuration option, CONFIG_DFU_WRITE_ALT, was
introduced so that the file will be compiled with different options,
particularly one added in a later commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 common/update.c                       |  5 +++--
 drivers/dfu/Kconfig                   |  5 +++++
 drivers/dfu/Makefile                  |  2 +-
 drivers/dfu/{dfu_tftp.c => dfu_alt.c} | 17 ++++++++++++--
 include/dfu.h                         | 32 +++++++++++++--------------
 5 files changed, 40 insertions(+), 21 deletions(-)
 rename drivers/dfu/{dfu_tftp.c => dfu_alt.c} (67%)

diff --git a/common/update.c b/common/update.c
index 36b6b7523d50..39946776d74f 100644
--- a/common/update.c
+++ b/common/update.c
@@ -324,8 +324,9 @@ got_update_file:
 			}
 		} else if (fit_image_check_type(fit, noffset,
 						IH_TYPE_FIRMWARE)) {
-			ret = dfu_tftp_write(fit_image_name, update_addr,
-					     update_size, interface, devstring);
+			ret = dfu_write_by_name(fit_image_name, update_addr,
+						update_size, interface,
+						devstring);
 			if (ret)
 				return ret;
 		}
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0eec00ba734d..10196f390fcd 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -14,8 +14,13 @@ config DFU_OVER_TFTP
 	depends on NET
 
 if DFU
+config DFU_WRITE_ALT
+	bool
+	default n
+
 config DFU_TFTP
 	bool "DFU via TFTP"
+	select DFU_WRITE_ALT
 	select DFU_OVER_TFTP
 	help
 	  This option allows performing update of DFU-managed medium with data
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 0d7925c083ef..dfbf64da6677 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -9,5 +9,5 @@ obj-$(CONFIG_$(SPL_)DFU_MTD) += dfu_mtd.o
 obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o
 obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o
 obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o
-obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o
+obj-$(CONFIG_$(SPL_)DFU_WRITE_ALT) += dfu_alt.o
 obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o
diff --git a/drivers/dfu/dfu_tftp.c b/drivers/dfu/dfu_alt.c
similarity index 67%
rename from drivers/dfu/dfu_tftp.c
rename to drivers/dfu/dfu_alt.c
index ffae4bb54f80..5b1b13d7170d 100644
--- a/drivers/dfu/dfu_tftp.c
+++ b/drivers/dfu/dfu_alt.c
@@ -10,8 +10,21 @@
 #include <errno.h>
 #include <dfu.h>
 
-int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
-		   char *interface, char *devstring)
+/**
+ * dfu_write_by_name() - write data to DFU medium
+ * @dfu_entity_name:    Name of DFU entity to write
+ * @addr:               Address of data buffer to write
+ * @len:                Number of bytes
+ * @interface:          Destination DFU medium (e.g. "mmc")
+ * @devstring:          Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_entity_name.
+ *
+ * Return:              0 - on success, error code - otherwise
+ */
+int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+		      unsigned int len, char *interface, char *devstring)
 {
 	char *s, *sb;
 	int alt_setting_num, ret;
diff --git a/include/dfu.h b/include/dfu.h
index 84abdc79acd1..a4cd86c0a6c4 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -494,27 +494,27 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
 #endif
 
 /**
- * dfu_tftp_write() - write TFTP data to DFU medium
+ * dfu_write_by_name() - write data to DFU medium
+ * @dfu_entity_name:	Name of DFU entity to write
+ * @addr:		Address of data buffer to write
+ * @len:		Number of bytes
+ * @interface:		Destination DFU medium (e.g. "mmc")
+ * @devstring:		Instance number of destination DFU medium (e.g. "1")
  *
- * This function is storing data received via TFTP on DFU supported medium.
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_entity_name.
  *
- * @dfu_entity_name:	name of DFU entity to write
- * @addr:		address of data buffer to write
- * @len:		number of bytes
- * @interface:		destination DFU medium (e.g. "mmc")
- * @devstring:		instance number of destination DFU medium (e.g. "1")
- *
- * Return:		0 on success, otherwise error code
+ * Return:		0 - on success, error code - otherwise
  */
-#if CONFIG_IS_ENABLED(DFU_TFTP)
-int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
-		   char *interface, char *devstring);
+#if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
+int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+		      unsigned int len, char *interface, char *devstring);
 #else
-static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
-				 unsigned int len, char *interface,
-				 char *devstring)
+static inline int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+				    unsigned int len, char *interface,
+				    char *devstring)
 {
-	puts("TFTP write support for DFU not available!\n");
+	puts("write support for DFU not available!\n");
 	return -ENOSYS;
 }
 #endif
-- 
2.28.0

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

* [PATCH v8 02/18] dfu: modify an argument type for an address
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 01/18] dfu: rename dfu_tftp_write() to dfu_write_by_name() AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 03/18] common: update: add a generic interface for FIT image AKASHI Takahiro
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

The range of an addressable pointer can go beyond 'integer'.
So change the argument type to a void pointer.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 common/update.c       | 3 ++-
 drivers/dfu/dfu_alt.c | 6 +++---
 include/dfu.h         | 4 ++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/common/update.c b/common/update.c
index 39946776d74f..8dd6ee8b7ddb 100644
--- a/common/update.c
+++ b/common/update.c
@@ -324,7 +324,8 @@ got_update_file:
 			}
 		} else if (fit_image_check_type(fit, noffset,
 						IH_TYPE_FIRMWARE)) {
-			ret = dfu_write_by_name(fit_image_name, update_addr,
+			ret = dfu_write_by_name(fit_image_name,
+						(void *)update_addr,
 						update_size, interface,
 						devstring);
 			if (ret)
diff --git a/drivers/dfu/dfu_alt.c b/drivers/dfu/dfu_alt.c
index 5b1b13d7170d..7528806cd163 100644
--- a/drivers/dfu/dfu_alt.c
+++ b/drivers/dfu/dfu_alt.c
@@ -23,14 +23,14 @@
  *
  * Return:              0 - on success, error code - otherwise
  */
-int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+int dfu_write_by_name(char *dfu_entity_name, void *addr,
 		      unsigned int len, char *interface, char *devstring)
 {
 	char *s, *sb;
 	int alt_setting_num, ret;
 	struct dfu_entity *dfu;
 
-	debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__,
+	debug("%s: name: %s addr: 0x%p len: %d device: %s:%s\n", __func__,
 	      dfu_entity_name, addr, len, interface, devstring);
 
 	ret = dfu_init_env_entities(interface, devstring);
@@ -69,7 +69,7 @@ int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
 		goto done;
 	}
 
-	ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
+	ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
 
 done:
 	dfu_free_entities();
diff --git a/include/dfu.h b/include/dfu.h
index a4cd86c0a6c4..d3d7e07b60d8 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -507,10 +507,10 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
  * Return:		0 - on success, error code - otherwise
  */
 #if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
-int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+int dfu_write_by_name(char *dfu_entity_name, void *addr,
 		      unsigned int len, char *interface, char *devstring);
 #else
-static inline int dfu_write_by_name(char *dfu_entity_name, unsigned int addr,
+static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
 				    unsigned int len, char *interface,
 				    char *devstring)
 {
-- 
2.28.0

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

* [PATCH v8 03/18] common: update: add a generic interface for FIT image
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 01/18] dfu: rename dfu_tftp_write() to dfu_write_by_name() AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 02/18] dfu: modify an argument type for an address AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 04/18] dfu: export dfu_list AKASHI Takahiro
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

The main purpose of this patch is to separate a generic interface for
updating firmware using DFU drivers from "auto-update" via tftp.

This function will also be used in implementing UEFI capsule update
in a later commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 common/Kconfig      | 15 ++++++++++
 common/Makefile     |  3 +-
 common/update.c     | 71 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/dfu/Kconfig |  2 +-
 include/image.h     | 12 ++++++++
 5 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/common/Kconfig b/common/Kconfig
index 318d372a481b..2bce8c9ba1b9 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -599,9 +599,15 @@ endmenu
 
 menu "Update support"
 
+config UPDATE_COMMON
+	bool
+	default n
+	select DFU_WRITE_ALT
+
 config UPDATE_TFTP
 	bool "Auto-update using fitImage via TFTP"
 	depends on FIT
+	select UPDATE_COMMON
 	help
 	  This option allows performing update of NOR with data in fitImage
 	  sent via TFTP boot.
@@ -616,6 +622,15 @@ config UPDATE_TFTP_MSEC_MAX
 	default 100
 	depends on UPDATE_TFTP
 
+config UPDATE_FIT
+	bool "Firmware update using fitImage"
+	depends on FIT
+	depends on DFU
+	select UPDATE_COMMON
+	help
+	  This option allows performing update of DFU-capable storage with
+	  data in fitImage.
+
 config ANDROID_AB
 	bool "Android A/B updates"
 	default n
diff --git a/common/Makefile b/common/Makefile
index 2e7a090588d9..bcf352d01652 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -53,8 +53,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
 obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
 obj-$(CONFIG_MENU) += menu.o
-obj-$(CONFIG_UPDATE_TFTP) += update.o
-obj-$(CONFIG_DFU_TFTP) += update.o
+obj-$(CONFIG_UPDATE_COMMON) += update.o
 obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
 obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
 
diff --git a/common/update.c b/common/update.c
index 8dd6ee8b7ddb..a5879cb52c41 100644
--- a/common/update.c
+++ b/common/update.c
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <mtd/cfi_flash.h>
 
+#if defined(CONFIG_DFU_TFTP) || defined(CONFIG_UPDATE_TFTP)
 /* env variable holding the location of the update file */
 #define UPDATE_FILE_ENV		"updatefile"
 
@@ -214,6 +215,7 @@ static int update_flash(ulong addr_source, ulong addr_first, ulong size)
 #endif
 	return 0;
 }
+#endif /* CONFIG_DFU_TFTP || CONFIG_UPDATE_TFTP */
 
 static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
 						ulong *fladdr, ulong *size)
@@ -231,6 +233,7 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
 	return 0;
 }
 
+#if defined(CONFIG_DFU_TFTP) || defined(CONFIG_UPDATE_TFTP)
 int update_tftp(ulong addr, char *interface, char *devstring)
 {
 	char *filename, *env_addr, *fit_image_name;
@@ -337,3 +340,71 @@ next_node:
 
 	return ret;
 }
+#endif /* CONFIG_DFU_UPDATE || CONFIG_UPDATE_TFTP */
+
+#ifdef CONFIG_UPDATE_FIT
+/**
+ * fit_update - update storage with FIT image
+ * @fit:	Pointer to FIT image
+ *
+ * Update firmware on storage using FIT image as input.
+ * The storage area to be update will be identified by the name
+ * in FIT and matching it to "dfu_alt_info" variable.
+ *
+ * Return:      0 - on success, non-zero - otherwise
+ */
+int fit_update(const void *fit)
+{
+	char *fit_image_name;
+	ulong update_addr, update_fladdr, update_size;
+	int images_noffset, ndepth, noffset;
+	int ret = 0;
+
+	if (!fit)
+		return -EINVAL;
+
+	if (!fit_check_format((void *)fit)) {
+		printf("Bad FIT format of the update file, aborting auto-update\n");
+		return -EINVAL;
+	}
+
+	/* process updates */
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+
+	ndepth = 0;
+	noffset = fdt_next_node(fit, images_noffset, &ndepth);
+	while (noffset >= 0 && ndepth > 0) {
+		if (ndepth != 1)
+			goto next_node;
+
+		fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
+		printf("Processing update '%s' :", fit_image_name);
+
+		if (!fit_image_verify(fit, noffset)) {
+			printf("Error: invalid update hash, aborting\n");
+			ret = 1;
+			goto next_node;
+		}
+
+		printf("\n");
+		if (update_fit_getparams(fit, noffset, &update_addr,
+					 &update_fladdr, &update_size)) {
+			printf("Error: can't get update parameters, aborting\n");
+			ret = 1;
+			goto next_node;
+		}
+
+		if (fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE)) {
+			ret = dfu_write_by_name(fit_image_name,
+						(void *)update_addr,
+						update_size, NULL, NULL);
+			if (ret)
+				return ret;
+		}
+next_node:
+		noffset = fdt_next_node(fit, noffset, &ndepth);
+	}
+
+	return ret;
+}
+#endif /* CONFIG_UPDATE_FIT */
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 10196f390fcd..121dc54f5463 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -20,7 +20,7 @@ config DFU_WRITE_ALT
 
 config DFU_TFTP
 	bool "DFU via TFTP"
-	select DFU_WRITE_ALT
+	select UPDATE_COMMON
 	select DFU_OVER_TFTP
 	help
 	  This option allows performing update of DFU-managed medium with data
diff --git a/include/image.h b/include/image.h
index 4094ee588a57..00bc03bebece 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1602,4 +1602,16 @@ struct fit_loadable_tbl {
 		.handler = _handler, \
 	}
 
+/**
+ * fit_update - update storage with FIT image
+ * @fit:        Pointer to FIT image
+ *
+ * Update firmware on storage using FIT image as input.
+ * The storage area to be update will be identified by the name
+ * in FIT and matching it to "dfu_alt_info" variable.
+ *
+ * Return:      0 on success, non-zero otherwise
+ */
+int fit_update(const void *fit);
+
 #endif	/* __IMAGE_H__ */
-- 
2.28.0

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

* [PATCH v8 04/18] dfu: export dfu_list
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2020-11-13  4:14 ` [PATCH v8 03/18] common: update: add a generic interface for FIT image AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 05/18] efi_loader: add option to initialise EFI subsystem early AKASHI Takahiro
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

This variable will be utilized to enumerate all dfu entities
for UEFI capsule firmware update in a later commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 drivers/dfu/dfu.c | 2 +-
 include/dfu.h     | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index a298c2c43999..501a60b34400 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -18,7 +18,7 @@
 #include <linux/list.h>
 #include <linux/compiler.h>
 
-static LIST_HEAD(dfu_list);
+LIST_HEAD(dfu_list);
 static int dfu_alt_num;
 static int alt_num_cnt;
 static struct hash_algo *dfu_hash_algo;
diff --git a/include/dfu.h b/include/dfu.h
index d3d7e07b60d8..eaf4bfc0d5ed 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -158,6 +158,9 @@ struct dfu_entity {
 	unsigned int inited:1;
 };
 
+struct list_head;
+extern struct list_head dfu_list;
+
 #ifdef CONFIG_SET_DFU_ALT_INFO
 /**
  * set_dfu_alt_info() - set dfu_alt_info environment variable
-- 
2.28.0

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

* [PATCH v8 05/18] efi_loader: add option to initialise EFI subsystem early
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (3 preceding siblings ...)
  2020-11-13  4:14 ` [PATCH v8 04/18] dfu: export dfu_list AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:14 ` [PATCH v8 06/18] efi_loader: add efi_create_indexed_name() AKASHI Takahiro
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

If this option, CONFIG_EFI_SETUP_EARLY, is enabled, the initialisation
of UEFI subsystem will be done as part of U-Boot initialisation.

Please note that this option won't be enabled explicitly by users,
instead, should be enabled implicitly by other configuration options.

Specifically, this feature will be utilised in implementing capsule-on-disk
feature.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 common/board_r.c       | 6 ++++++
 lib/efi_loader/Kconfig | 4 ++++
 2 files changed, 10 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index b9217b2e27f0..2212d981e5ea 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -73,6 +73,9 @@
 #if defined(CONFIG_GPIO_HOG)
 #include <asm/gpio.h>
 #endif
+#ifdef CONFIG_EFI_SETUP_EARLY
+#include <efi_loader.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -889,6 +892,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #if defined(CONFIG_PRAM)
 	initr_mem,
+#endif
+#ifdef CONFIG_EFI_SETUP_EARLY
+	(init_fnc_t)efi_init_obj_list,
 #endif
 	run_main_loop,
 };
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ab42f3ba75b1..075481428cdf 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -27,6 +27,10 @@ config EFI_LOADER
 
 if EFI_LOADER
 
+config EFI_SETUP_EARLY
+	bool
+	default n
+
 choice
 	prompt "Store for non-volatile UEFI variables"
 	default EFI_VARIABLE_FILE_STORE
-- 
2.28.0

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

* [PATCH v8 06/18] efi_loader: add efi_create_indexed_name()
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (4 preceding siblings ...)
  2020-11-13  4:14 ` [PATCH v8 05/18] efi_loader: add option to initialise EFI subsystem early AKASHI Takahiro
@ 2020-11-13  4:14 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 07/18] efi_loader: define UpdateCapsule api AKASHI Takahiro
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:14 UTC (permalink / raw)
  To: u-boot

This function will be used from several places in UEFI subsystem
to generate some specific form of utf-16 variable name.
For example, L"Capsule0001"

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_loader.h       |  3 +++
 lib/efi_loader/efi_setup.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7eea5566fdc9..6865a4847d53 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -804,6 +804,9 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 /* runtime implementation of memcpy() */
 void efi_memcpy_runtime(void *dest, const void *src, size_t n);
 
+/* commonly used helper function */
+u16 *efi_create_indexed_name(u16 *buffer, const u16 *name, unsigned int index);
+
 #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 45226c5c1a53..6346eda771d0 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <charset.h>
 #include <bootm.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
@@ -235,3 +236,32 @@ out:
 	efi_obj_list_initialized = ret;
 	return ret;
 }
+
+/**
+ * efi_create_indexed_name - create a string name with an index
+ * @buffer:	Buffer
+ * @name:	Name string
+ * @index:	Index
+ *
+ * Create a utf-16 string with @name, appending @index.
+ * For example, L"Capsule0001"
+ * This function is expected to be called only from several places
+ * in EFI subsystem. A caller should ensure that the buffer have
+ * enough space for a resulting string, including L"\0".
+ * No strict check against the length will be done here.
+ *
+ * Return: A pointer to the next position after the created string
+ *		in @buffer, or NULL otherwise
+ */
+u16 *efi_create_indexed_name(u16 *buffer, const u16 *name, unsigned int index)
+{
+	u16 *p;
+	char index_buf[5];
+
+	u16_strcpy(buffer, name);
+	p = buffer + utf16_strnlen(name, SIZE_MAX);
+	sprintf(index_buf, "%04X", index);
+	utf8_utf16_strcpy(&p, index_buf);
+
+	return p;
+}
-- 
2.28.0

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

* [PATCH v8 07/18] efi_loader: define UpdateCapsule api
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (5 preceding siblings ...)
  2020-11-13  4:14 ` [PATCH v8 06/18] efi_loader: add efi_create_indexed_name() AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 08/18] efi_loader: capsule: add capsule_on_disk support AKASHI Takahiro
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

In this commit, skeleton functions for capsule-related API's are
added under CONFIG_EFI_UPDATE_CAPSULE configuration.
Detailed implementation for a specific capsule type will be added
in the succeeding patches.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h            |  12 +++
 include/efi_loader.h         |  13 +++
 lib/efi_loader/Kconfig       |  11 +++
 lib/efi_loader/Makefile      |   1 +
 lib/efi_loader/efi_capsule.c | 165 +++++++++++++++++++++++++++++++++++
 lib/efi_loader/efi_runtime.c | 104 ++++++++++++----------
 lib/efi_loader/efi_setup.c   |  64 +++++++++++---
 7 files changed, 316 insertions(+), 54 deletions(-)
 create mode 100644 lib/efi_loader/efi_capsule.c

diff --git a/include/efi_api.h b/include/efi_api.h
index 5744f6aed86d..c128a0a66ce8 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -217,6 +217,10 @@ enum efi_reset_type {
 #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE	0x00020000
 #define CAPSULE_FLAGS_INITIATE_RESET		0x00040000
 
+#define EFI_CAPSULE_REPORT_GUID \
+	EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \
+		 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3)
+
 struct efi_capsule_header {
 	efi_guid_t capsule_guid;
 	u32 header_size;
@@ -224,6 +228,14 @@ struct efi_capsule_header {
 	u32 capsule_image_size;
 } __packed;
 
+struct efi_capsule_result_variable_header {
+	u32 variable_total_size;
+	u32 reserved;
+	efi_guid_t capsule_guid;
+	struct efi_time capsule_processed;
+	efi_status_t capsule_status;
+} __packed;
+
 #define EFI_RT_SUPPORTED_GET_TIME			0x0001
 #define EFI_RT_SUPPORTED_SET_TIME			0x0002
 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME		0x0004
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 6865a4847d53..ffe772866675 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -207,6 +207,8 @@ extern const efi_guid_t efi_guid_cert_type_pkcs7;
 
 /* GUID of RNG protocol */
 extern const efi_guid_t efi_guid_rng_protocol;
+/* GUID of capsule update result */
+extern const efi_guid_t efi_guid_capsule_report;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -807,6 +809,17 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n);
 /* commonly used helper function */
 u16 *efi_create_indexed_name(u16 *buffer, const u16 *name, unsigned int index);
 
+/* Capsule update */
+efi_status_t EFIAPI efi_update_capsule(
+		struct efi_capsule_header **capsule_header_array,
+		efi_uintn_t capsule_count,
+		u64 scatter_gather_list);
+efi_status_t EFIAPI efi_query_capsule_caps(
+		struct efi_capsule_header **capsule_header_array,
+		efi_uintn_t capsule_count,
+		u64 *maximum_capsule_size,
+		u32 *reset_type);
+
 #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 075481428cdf..3ca396df3646 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -93,6 +93,17 @@ config EFI_SET_TIME
 	  Provide the SetTime() runtime service at boottime. This service
 	  can be used by an EFI application to adjust the real time clock.
 
+config EFI_HAVE_CAPSULE_SUPPORT
+	bool
+
+config EFI_RUNTIME_UPDATE_CAPSULE
+	bool "UpdateCapsule() runtime service"
+	default n
+	select EFI_HAVE_CAPSULE_SUPPORT
+	help
+	  Select this option if you want to use UpdateCapsule and
+	  QueryCapsuleCapabilities API's.
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 9bad1d159b03..c7d231f0e57d 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -23,6 +23,7 @@ endif
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_bootmgr.o
 obj-y += efi_boottime.o
+obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
 obj-y += efi_console.o
 obj-y += efi_device_path.o
 obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
new file mode 100644
index 000000000000..02a8435cd3d1
--- /dev/null
+++ b/lib/efi_loader/efi_capsule.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  EFI Capsule
+ *
+ *  Copyright (c) 2018 Linaro Limited
+ *			Author: AKASHI Takahiro
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <fs.h>
+#include <malloc.h>
+#include <sort.h>
+
+const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
+
+/**
+ * get_last_capsule - get the last capsule index
+ *
+ * Retrieve the index of the capsule invoked last time from "CapsuleLast"
+ * variable.
+ *
+ * Return:
+ * * > 0	- the last capsule index invoked
+ * * 0xffff	- on error, or no capsule invoked yet
+ */
+static __maybe_unused unsigned int get_last_capsule(void)
+{
+	u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */
+	char value[11], *p;
+	efi_uintn_t size;
+	unsigned long index = 0xffff;
+	efi_status_t ret;
+
+	size = sizeof(value16);
+	ret = efi_get_variable_int(L"CapsuleLast", &efi_guid_capsule_report,
+				   NULL, &size, value16, NULL);
+	if (ret != EFI_SUCCESS || u16_strncmp(value16, L"Capsule", 7))
+		goto err;
+
+	p = value;
+	utf16_utf8_strcpy(&p, value16);
+	strict_strtoul(&value[7], 16, &index);
+err:
+	return index;
+}
+
+/**
+ * set_capsule_result - set a result variable
+ * @capsule:		Capsule
+ * @return_status:	Return status
+ *
+ * Create and set a result variable, "CapsuleXXXX", for the capsule,
+ * @capsule.
+ */
+static __maybe_unused
+void set_capsule_result(int index, struct efi_capsule_header *capsule,
+			efi_status_t return_status)
+{
+	u16 variable_name16[12];
+	struct efi_capsule_result_variable_header result;
+	struct efi_time time;
+	efi_status_t ret;
+
+	efi_create_indexed_name(variable_name16, L"Capsule", index);
+
+	result.variable_total_size = sizeof(result);
+	result.capsule_guid = capsule->capsule_guid;
+	ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
+	if (ret == EFI_SUCCESS)
+		memcpy(&result.capsule_processed, &time, sizeof(time));
+	else
+		memset(&result.capsule_processed, 0, sizeof(time));
+	result.capsule_status = return_status;
+	ret = efi_set_variable(variable_name16, &efi_guid_capsule_report,
+			       EFI_VARIABLE_NON_VOLATILE |
+			       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+			       EFI_VARIABLE_RUNTIME_ACCESS,
+			       sizeof(result), &result);
+	if (ret)
+		printf("EFI: creating %ls failed\n", variable_name16);
+}
+
+/**
+ * efi_update_capsule() - process information from operating system
+ * @capsule_header_array:	Array of virtual address pointers
+ * @capsule_count:		Number of pointers in capsule_header_array
+ * @scatter_gather_list:	Array of physical address pointers
+ *
+ * This function implements the UpdateCapsule() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return:			status code
+ */
+efi_status_t EFIAPI efi_update_capsule(
+		struct efi_capsule_header **capsule_header_array,
+		efi_uintn_t capsule_count,
+		u64 scatter_gather_list)
+{
+	struct efi_capsule_header *capsule;
+	unsigned int i;
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count,
+		  scatter_gather_list);
+
+	if (!capsule_count) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = EFI_UNSUPPORTED;
+	for (i = 0, capsule = *capsule_header_array; i < capsule_count;
+	     i++, capsule = *(++capsule_header_array)) {
+	}
+out:
+	return EFI_EXIT(ret);
+}
+
+/**
+ * efi_query_capsule_caps() - check if capsule is supported
+ * @capsule_header_array:	Array of virtual pointers
+ * @capsule_count:		Number of pointers in capsule_header_array
+ * @maximum_capsule_size:	Maximum capsule size
+ * @reset_type:			Type of reset needed for capsule update
+ *
+ * This function implements the QueryCapsuleCapabilities() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return:			status code
+ */
+efi_status_t EFIAPI efi_query_capsule_caps(
+		struct efi_capsule_header **capsule_header_array,
+		efi_uintn_t capsule_count,
+		u64 *maximum_capsule_size,
+		u32 *reset_type)
+{
+	struct efi_capsule_header *capsule __attribute__((unused));
+	unsigned int i;
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %lu, %p, %p\n", capsule_header_array, capsule_count,
+		  maximum_capsule_size, reset_type);
+
+	if (!maximum_capsule_size) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	*maximum_capsule_size = U64_MAX;
+	*reset_type = EFI_RESET_COLD;
+
+	ret = EFI_SUCCESS;
+	for (i = 0, capsule = *capsule_header_array; i < capsule_count;
+	     i++, capsule = *(++capsule_header_array)) {
+		/* TODO */
+	}
+out:
+	return EFI_EXIT(ret);
+}
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 1fa1595e402f..0b171c1ff7bf 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -133,6 +133,10 @@ efi_status_t efi_init_runtime_supported(void)
 #ifdef CONFIG_EFI_HAVE_RUNTIME_RESET
 	rt_table->runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
 #endif
+	if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE))
+		rt_table->runtime_services_supported |=
+			(EFI_RT_SUPPORTED_UPDATE_CAPSULE |
+			 EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES);
 
 	ret = efi_install_configuration_table(&efi_rt_properties_table_guid,
 					      rt_table);
@@ -448,6 +452,50 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
 	return EFI_UNSUPPORTED;
 }
 
+/**
+ * efi_update_capsule_unsupported() - process information from operating system
+ *
+ * This function implements the UpdateCapsule() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @capsule_header_array:	pointer to array of virtual pointers
+ * @capsule_count:		number of pointers in capsule_header_array
+ * @scatter_gather_list:	pointer to array of physical pointers
+ * Returns:			status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_update_capsule_unsupported(
+			struct efi_capsule_header **capsule_header_array,
+			efi_uintn_t capsule_count,
+			u64 scatter_gather_list)
+{
+	return EFI_UNSUPPORTED;
+}
+
+/**
+ * efi_query_capsule_caps_unsupported() - check if capsule is supported
+ *
+ * This function implements the QueryCapsuleCapabilities() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @capsule_header_array:	pointer to array of virtual pointers
+ * @capsule_count:		number of pointers in capsule_header_array
+ * @maximum_capsule_size:	maximum capsule size
+ * @reset_type:			type of reset needed for capsule update
+ * Returns:			status code
+ */
+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps_unsupported(
+			struct efi_capsule_header **capsule_header_array,
+			efi_uintn_t capsule_count,
+			u64 *maximum_capsule_size,
+			u32 *reset_type)
+{
+	return EFI_UNSUPPORTED;
+}
+
 /**
  * efi_is_runtime_service_pointer() - check if pointer points to runtime table
  *
@@ -471,6 +519,13 @@ void efi_runtime_detach(void)
 	efi_runtime_services.reset_system = efi_reset_system;
 	efi_runtime_services.get_time = efi_get_time;
 	efi_runtime_services.set_time = efi_set_time;
+	if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE)) {
+		/* won't support at runtime */
+		efi_runtime_services.update_capsule =
+				efi_update_capsule_unsupported;
+		efi_runtime_services.query_capsule_caps =
+				efi_query_capsule_caps_unsupported;
+	}
 
 	/* Update CRC32 */
 	efi_update_table_header_crc32(&efi_runtime_services.hdr);
@@ -879,50 +934,6 @@ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
 	return EFI_UNSUPPORTED;
 }
 
-/**
- * efi_update_capsule() - process information from operating system
- *
- * This function implements the UpdateCapsule() runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @capsule_header_array:	pointer to array of virtual pointers
- * @capsule_count:		number of pointers in capsule_header_array
- * @scatter_gather_list:	pointer to arry of physical pointers
- * Returns:			status code
- */
-efi_status_t __efi_runtime EFIAPI efi_update_capsule(
-			struct efi_capsule_header **capsule_header_array,
-			efi_uintn_t capsule_count,
-			u64 scatter_gather_list)
-{
-	return EFI_UNSUPPORTED;
-}
-
-/**
- * efi_query_capsule_caps() - check if capsule is supported
- *
- * This function implements the QueryCapsuleCapabilities() runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @capsule_header_array:	pointer to array of virtual pointers
- * @capsule_count:		number of pointers in capsule_header_array
- * @maximum_capsule_size:	maximum capsule size
- * @reset_type:			type of reset needed for capsule update
- * Returns:			status code
- */
-efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
-			struct efi_capsule_header **capsule_header_array,
-			efi_uintn_t capsule_count,
-			u64 *maximum_capsule_size,
-			u32 *reset_type)
-{
-	return EFI_UNSUPPORTED;
-}
-
 struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
 	.hdr = {
 		.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
@@ -940,7 +951,12 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
 	.set_variable = efi_set_variable,
 	.get_next_high_mono_count = (void *)&efi_unimplemented,
 	.reset_system = &efi_reset_system_boottime,
+#ifdef CONFIG_EFI_RUNTIME_UPDATE_CAPSULE
 	.update_capsule = efi_update_capsule,
 	.query_capsule_caps = efi_query_capsule_caps,
+#else
+	.update_capsule = efi_update_capsule_unsupported,
+	.query_capsule_caps = efi_query_capsule_caps_unsupported,
+#endif
 	.query_variable_info = efi_query_variable_info,
 };
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 6346eda771d0..3a1c8ea00446 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -101,9 +101,9 @@ static efi_status_t efi_init_secure_boot(void)
 
 	ret = efi_set_variable_int(L"SignatureSupport",
 				   &efi_global_variable_guid,
+				   EFI_VARIABLE_READ_ONLY |
 				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
-				   EFI_VARIABLE_RUNTIME_ACCESS |
-				   EFI_VARIABLE_READ_ONLY,
+				   EFI_VARIABLE_RUNTIME_ACCESS,
 				   sizeof(signature_types),
 				   &signature_types, false);
 	if (ret != EFI_SUCCESS)
@@ -118,6 +118,53 @@ static efi_status_t efi_init_secure_boot(void)
 }
 #endif /* CONFIG_EFI_SECURE_BOOT */
 
+/**
+ * efi_init_capsule - initialize capsule update state
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_init_capsule(void)
+{
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) {
+		ret = efi_set_variable_int(L"CapsuleMax",
+					   &efi_guid_capsule_report,
+					   EFI_VARIABLE_READ_ONLY |
+					   EFI_VARIABLE_BOOTSERVICE_ACCESS |
+					   EFI_VARIABLE_RUNTIME_ACCESS,
+					   22, L"CapsuleFFFF", false);
+		if (ret != EFI_SUCCESS)
+			printf("EFI: cannot initialize CapsuleMax variable\n");
+	}
+
+	return ret;
+}
+
+/**
+ * efi_init_os_indications() - indicate supported features for OS requests
+ *
+ * Set the OsIndicationsSupported variable.
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_init_os_indications(void)
+{
+	u64 os_indications_supported = 0;
+
+	if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
+		os_indications_supported |=
+			EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED;
+
+	return efi_set_variable_int(L"OsIndicationsSupported",
+				    &efi_global_variable_guid,
+				    EFI_VARIABLE_BOOTSERVICE_ACCESS |
+				    EFI_VARIABLE_RUNTIME_ACCESS |
+				    EFI_VARIABLE_READ_ONLY,
+				    sizeof(os_indications_supported),
+				    &os_indications_supported, false);
+}
+
 /**
  * efi_init_obj_list() - Initialize and populate EFI object list
  *
@@ -125,7 +172,6 @@ static efi_status_t efi_init_secure_boot(void)
  */
 efi_status_t efi_init_obj_list(void)
 {
-	u64 os_indications_supported = 0; /* None */
 	efi_status_t ret = EFI_SUCCESS;
 
 	/* Initialize once only */
@@ -168,13 +214,7 @@ efi_status_t efi_init_obj_list(void)
 		goto out;
 
 	/* Indicate supported features */
-	ret = efi_set_variable_int(L"OsIndicationsSupported",
-				   &efi_global_variable_guid,
-				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
-				   EFI_VARIABLE_RUNTIME_ACCESS |
-				   EFI_VARIABLE_READ_ONLY,
-				   sizeof(os_indications_supported),
-				   &os_indications_supported, false);
+	ret = efi_init_os_indications();
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -227,6 +267,10 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 
+	ret = efi_init_capsule();
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	/* Initialize EFI runtime services */
 	ret = efi_reset_system_init();
 	if (ret != EFI_SUCCESS)
-- 
2.28.0

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

* [PATCH v8 08/18] efi_loader: capsule: add capsule_on_disk support
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (6 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 07/18] efi_loader: define UpdateCapsule api AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 09/18] efi_loader: capsule: add memory range capsule definitions AKASHI Takahiro
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

Capsule data can be loaded into the system either via UpdateCapsule
runtime service or files on a file system (of boot device).
The latter case is called "capsules on disk", and actual updates will
take place at the next boot time.

In this commit, we will support capsule on disk mechanism.

Please note that U-Boot itself has no notion of "boot device" and
all the capsule files to be executed will be detected only if they
are located in a specific directory, \EFI\UpdateCapsule, on a device
that is identified as a boot device by "BootXXXX" variables.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 common/main.c                |   4 +
 include/efi_loader.h         |   9 +
 lib/efi_loader/Kconfig       |  22 ++
 lib/efi_loader/efi_capsule.c | 498 +++++++++++++++++++++++++++++++++++
 lib/efi_loader/efi_setup.c   |   8 +
 5 files changed, 541 insertions(+)

diff --git a/common/main.c b/common/main.c
index 4b3cd302c3e2..ae5bcdb32f8b 100644
--- a/common/main.c
+++ b/common/main.c
@@ -16,6 +16,7 @@
 #include <init.h>
 #include <net.h>
 #include <version.h>
+#include <efi_loader.h>
 
 static void run_preboot_environment_command(void)
 {
@@ -53,6 +54,9 @@ void main_loop(void)
 	if (IS_ENABLED(CONFIG_UPDATE_TFTP))
 		update_tftp(0UL, NULL, NULL);
 
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
+		efi_launch_capsules();
+
 	s = bootdelay_process();
 	if (cli_process_fdt(&s))
 		cli_secure_boot_cmd(s);
diff --git a/include/efi_loader.h b/include/efi_loader.h
index ffe772866675..572cfadd491a 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -820,6 +820,11 @@ efi_status_t EFIAPI efi_query_capsule_caps(
 		u64 *maximum_capsule_size,
 		u32 *reset_type);
 
+#define EFI_CAPSULE_DIR L"\\EFI\\UpdateCapsule\\"
+
+/* Hook at initialization */
+efi_status_t efi_launch_capsules(void);
+
 #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
@@ -836,6 +841,10 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr,
 				   const char *path) { }
 static inline void efi_net_set_dhcp_ack(void *pkt, int len) { }
 static inline void efi_print_image_infos(void *pc) { }
+static inline efi_status_t efi_launch_capsules(void)
+{
+	return EFI_SUCCESS;
+}
 
 #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 3ca396df3646..e1ac5ac055de 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -104,6 +104,28 @@ config EFI_RUNTIME_UPDATE_CAPSULE
 	  Select this option if you want to use UpdateCapsule and
 	  QueryCapsuleCapabilities API's.
 
+config EFI_CAPSULE_ON_DISK
+	bool "Enable capsule-on-disk support"
+	select EFI_HAVE_CAPSULE_SUPPORT
+	default n
+	help
+	  Select this option if you want to use capsule-on-disk feature,
+	  that is, capsules can be fetched and executed from files
+	  under a specific directory on UEFI system partition instead of
+	  via UpdateCapsule API.
+
+config EFI_CAPSULE_ON_DISK_EARLY
+	bool "Initiate capsule-on-disk at U-Boot boottime"
+	depends on EFI_CAPSULE_ON_DISK
+	default n
+	select EFI_SETUP_EARLY
+	help
+	  Normally, without this option enabled, capsules will be
+	  executed only at the first time of invoking one of efi command.
+	  If this option is enabled, capsules will be enforced to be
+	  executed as part of U-Boot initialisation so that they will
+	  surely take place whatever is set to distro_bootcmd.
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 02a8435cd3d1..2259bfbf3d19 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -11,10 +11,16 @@
 #include <efi_variable.h>
 #include <fs.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <sort.h>
 
 const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
 
+#ifdef CONFIG_EFI_CAPSULE_ON_DISK
+/* for file system access */
+static struct efi_file_handle *bootdev_root;
+#endif
+
 /**
  * get_last_capsule - get the last capsule index
  *
@@ -163,3 +169,495 @@ efi_status_t EFIAPI efi_query_capsule_caps(
 out:
 	return EFI_EXIT(ret);
 }
+
+#ifdef CONFIG_EFI_CAPSULE_ON_DISK
+/**
+ * get_dp_device - retrieve a device  path from boot variable
+ * @boot_var:	Boot variable name
+ * @device_dp	Device path
+ *
+ * Retrieve a device patch from boot variable, @boot_var.
+ *
+ * Return:	status code
+ */
+static efi_status_t get_dp_device(u16 *boot_var,
+				  struct efi_device_path **device_dp)
+{
+	void *buf = NULL;
+	efi_uintn_t size;
+	struct efi_load_option lo;
+	struct efi_device_path *file_dp;
+	efi_status_t ret;
+
+	size = 0;
+	ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
+				   NULL, &size, NULL, NULL);
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		buf = malloc(size);
+		if (!buf)
+			return EFI_OUT_OF_RESOURCES;
+		ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
+					   NULL, &size, buf, NULL);
+	}
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	efi_deserialize_load_option(&lo, buf, &size);
+
+	if (lo.attributes & LOAD_OPTION_ACTIVE) {
+		efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);
+		efi_free_pool(file_dp);
+
+		ret = EFI_SUCCESS;
+	} else {
+		ret = EFI_NOT_FOUND;
+	}
+
+	free(buf);
+
+	return ret;
+}
+
+/**
+ * device_is_present_and_system_part - check if a device exists
+ * @dp		Device path
+ *
+ * Check if a device pointed to by the device path, @dp, exists and is
+ * located in UEFI system partition.
+ *
+ * Return:	true - yes, false - no
+ */
+static bool device_is_present_and_system_part(struct efi_device_path *dp)
+{
+	efi_handle_t handle;
+
+	handle = efi_dp_find_obj(dp, NULL);
+	if (!handle)
+		return false;
+
+	return efi_disk_is_system_part(handle);
+}
+
+/**
+ * find_boot_device - identify the boot device
+ *
+ * Identify the boot device from boot-related variables as UEFI
+ * specification describes and put its handle into bootdev_root.
+ *
+ * Return:	status code
+ */
+static efi_status_t find_boot_device(void)
+{
+	char boot_var[9];
+	u16 boot_var16[9], *p, bootnext, *boot_order = NULL;
+	efi_uintn_t size;
+	int i, num;
+	struct efi_simple_file_system_protocol *volume;
+	struct efi_device_path *boot_dev = NULL;
+	efi_status_t ret;
+
+	/* find active boot device in BootNext */
+	bootnext = 0;
+	size = sizeof(bootnext);
+	ret = efi_get_variable_int(L"BootNext",
+				   (efi_guid_t *)&efi_global_variable_guid,
+				   NULL, &size, &bootnext, NULL);
+	if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
+		/* BootNext does exist here */
+		if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) {
+			printf("BootNext must be 16-bit integer\n");
+			goto skip;
+		}
+		sprintf((char *)boot_var, "Boot%04X", bootnext);
+		p = boot_var16;
+		utf8_utf16_strcpy(&p, boot_var);
+
+		ret = get_dp_device(boot_var16, &boot_dev);
+		if (ret == EFI_SUCCESS) {
+			if (device_is_present_and_system_part(boot_dev)) {
+				goto out;
+			} else {
+				efi_free_pool(boot_dev);
+				boot_dev = NULL;
+			}
+		}
+	}
+
+skip:
+	/* find active boot device in BootOrder */
+	size = 0;
+	ret = efi_get_variable_int(L"BootOrder", &efi_global_variable_guid,
+				   NULL, &size, NULL, NULL);
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		boot_order = malloc(size);
+		if (!boot_order) {
+			ret = EFI_OUT_OF_RESOURCES;
+			goto out;
+		}
+
+		ret = efi_get_variable_int(L"BootOrder",
+					   &efi_global_variable_guid,
+					   NULL, &size, boot_order, NULL);
+	}
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	/* check in higher order */
+	num = size / sizeof(u16);
+	for (i = 0; i < num; i++) {
+		sprintf((char *)boot_var, "Boot%04X", boot_order[i]);
+		p = boot_var16;
+		utf8_utf16_strcpy(&p, boot_var);
+		ret = get_dp_device(boot_var16, &boot_dev);
+		if (ret != EFI_SUCCESS)
+			continue;
+
+		if (device_is_present_and_system_part(boot_dev))
+			break;
+
+		efi_free_pool(boot_dev);
+		boot_dev = NULL;
+	}
+out:
+	if (boot_dev) {
+		u16 *path_str;
+
+		path_str = efi_dp_str(boot_dev);
+		EFI_PRINT("EFI Capsule: bootdev is %ls\n", path_str);
+		efi_free_pool(path_str);
+
+		volume = efi_fs_from_path(boot_dev);
+		if (!volume)
+			ret = EFI_DEVICE_ERROR;
+		else
+			ret = EFI_CALL(volume->open_volume(volume,
+							   &bootdev_root));
+		efi_free_pool(boot_dev);
+	} else {
+		ret = EFI_NOT_FOUND;
+	}
+	free(boot_order);
+
+	return ret;
+}
+
+/**
+ * efi_capsule_scan_dir - traverse a capsule directory in boot device
+ * @files:	Array of file names
+ * @num:	Number of elements in @files
+ *
+ * Traverse a capsule directory in boot device.
+ * Called by initialization code, and returns an array of capsule file
+ * names in @files.
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
+{
+	struct efi_file_handle *dirh;
+	struct efi_file_info *dirent;
+	efi_uintn_t dirent_size, tmp_size;
+	unsigned int count;
+	u16 **tmp_files;
+	efi_status_t ret;
+
+	ret = find_boot_device();
+	if (ret == EFI_NOT_FOUND) {
+		EFI_PRINT("EFI Capsule: bootdev is not set\n");
+		*num = 0;
+		return EFI_SUCCESS;
+	} else if (ret != EFI_SUCCESS) {
+		return EFI_DEVICE_ERROR;
+	}
+
+	/* count capsule files */
+	ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
+					     EFI_CAPSULE_DIR,
+					     EFI_FILE_MODE_READ, 0));
+	if (ret != EFI_SUCCESS) {
+		*num = 0;
+		return EFI_SUCCESS;
+	}
+
+	dirent_size = 256;
+	dirent = malloc(dirent_size);
+	if (!dirent)
+		return EFI_OUT_OF_RESOURCES;
+
+	count = 0;
+	while (1) {
+		tmp_size = dirent_size;
+		ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
+		if (ret == EFI_BUFFER_TOO_SMALL) {
+			dirent = realloc(dirent, tmp_size);
+			if (!dirent) {
+				ret = EFI_OUT_OF_RESOURCES;
+				goto err;
+			}
+			dirent_size = tmp_size;
+			ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
+		}
+		if (ret != EFI_SUCCESS)
+			goto err;
+		if (!tmp_size)
+			break;
+
+		if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
+		    u16_strcmp(dirent->file_name, L".") &&
+		    u16_strcmp(dirent->file_name, L".."))
+			count++;
+	}
+
+	ret = EFI_CALL((*dirh->setpos)(dirh, 0));
+	if (ret != EFI_SUCCESS)
+		goto err;
+
+	/* make a list */
+	tmp_files = malloc(count * sizeof(*files));
+	if (!tmp_files) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto err;
+	}
+
+	count = 0;
+	while (1) {
+		tmp_size = dirent_size;
+		ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
+		if (ret != EFI_SUCCESS)
+			goto err;
+		if (!tmp_size)
+			break;
+
+		if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
+		    u16_strcmp(dirent->file_name, L".") &&
+		    u16_strcmp(dirent->file_name, L".."))
+			tmp_files[count++] = u16_strdup(dirent->file_name);
+	}
+	/* ignore an error */
+	EFI_CALL((*dirh->close)(dirh));
+
+	/* in ascii order */
+	/* FIXME: u16 version of strcasecmp */
+	qsort(tmp_files, count, sizeof(*tmp_files),
+	      (int (*)(const void *, const void *))strcasecmp);
+	*files = tmp_files;
+	*num = count;
+	ret = EFI_SUCCESS;
+err:
+	free(dirent);
+
+	return ret;
+}
+
+/**
+ * efi_capsule_read_file - read in a capsule file
+ * @filename:	File name
+ * @capsule:	Pointer to buffer for capsule
+ *
+ * Read a capsule file and put its content in @capsule.
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_capsule_read_file(const u16 *filename,
+					  struct efi_capsule_header **capsule)
+{
+	struct efi_file_handle *dirh, *fh;
+	struct efi_file_info *file_info = NULL;
+	struct efi_capsule_header *buf = NULL;
+	efi_uintn_t size;
+	efi_status_t ret;
+
+	ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
+					     EFI_CAPSULE_DIR,
+					     EFI_FILE_MODE_READ, 0));
+	if (ret != EFI_SUCCESS)
+		return ret;
+	ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
+				     EFI_FILE_MODE_READ, 0));
+	/* ignore an error */
+	EFI_CALL((*dirh->close)(dirh));
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	/* file size */
+	size = 0;
+	ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
+				      &size, file_info));
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		file_info = malloc(size);
+		if (!file_info) {
+			ret = EFI_OUT_OF_RESOURCES;
+			goto err;
+		}
+		ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
+					      &size, file_info));
+	}
+	if (ret != EFI_SUCCESS)
+		goto err;
+	size = file_info->file_size;
+	free(file_info);
+	buf = malloc(size);
+	if (!buf) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto err;
+	}
+
+	/* fetch data */
+	ret = EFI_CALL((*fh->read)(fh, &size, buf));
+	if (ret == EFI_SUCCESS) {
+		if (size >= buf->capsule_image_size) {
+			*capsule = buf;
+		} else {
+			free(buf);
+			ret = EFI_INVALID_PARAMETER;
+		}
+	} else {
+		free(buf);
+	}
+err:
+	EFI_CALL((*fh->close)(fh));
+
+	return ret;
+}
+
+/**
+ * efi_capsule_delete_file - delete a capsule file
+ * @filename:	File name
+ *
+ * Delete a capsule file from capsule directory.
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_capsule_delete_file(const u16 *filename)
+{
+	struct efi_file_handle *dirh, *fh;
+	efi_status_t ret;
+
+	ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
+					     EFI_CAPSULE_DIR,
+					     EFI_FILE_MODE_READ, 0));
+	if (ret != EFI_SUCCESS)
+		return ret;
+	ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
+				     EFI_FILE_MODE_READ, 0));
+	/* ignore an error */
+	EFI_CALL((*dirh->close)(dirh));
+
+	ret = EFI_CALL((*fh->delete)(fh));
+
+	return ret;
+}
+
+/**
+ * efi_capsule_scan_done - reset a scan help function
+ *
+ * Reset a scan help function
+ */
+static void efi_capsule_scan_done(void)
+{
+	EFI_CALL((*bootdev_root->close)(bootdev_root));
+	bootdev_root = NULL;
+}
+
+/**
+ * arch_efi_load_capsule_drivers - initialize capsule drivers
+ *
+ * Architecture or board specific initialization routine
+ *
+ * Return:	status code
+ */
+efi_status_t __weak arch_efi_load_capsule_drivers(void)
+{
+	return EFI_SUCCESS;
+}
+
+/**
+ * efi_launch_capsule - launch capsules
+ *
+ * Launch all the capsules in system at boot time.
+ * Called by efi init code
+ *
+ * Return:	status codde
+ */
+efi_status_t efi_launch_capsules(void)
+{
+	u64 os_indications;
+	efi_uintn_t size;
+	struct efi_capsule_header *capsule = NULL;
+	u16 **files;
+	unsigned int nfiles, index, i;
+	u16 variable_name16[12];
+	efi_status_t ret;
+
+	size = sizeof(os_indications);
+	ret = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid,
+				   NULL, &size, &os_indications, NULL);
+	if (ret != EFI_SUCCESS ||
+	    !(os_indications
+	      & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED))
+		return EFI_SUCCESS;
+
+	index = get_last_capsule();
+
+	/* Load capsule drivers */
+	ret = arch_efi_load_capsule_drivers();
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	/*
+	 * Find capsules on disk.
+	 * All the capsules are collected at the beginning because
+	 * capsule files will be removed instantly.
+	 */
+	nfiles = 0;
+	files = NULL;
+	ret = efi_capsule_scan_dir(&files, &nfiles);
+	if (ret != EFI_SUCCESS)
+		return ret;
+	if (!nfiles)
+		return EFI_SUCCESS;
+
+	/* Launch capsules */
+	for (i = 0, ++index; i < nfiles; i++, index++) {
+		EFI_PRINT("capsule from %ls ...\n", files[i]);
+		if (index > 0xffff)
+			index = 0;
+		ret = efi_capsule_read_file(files[i], &capsule);
+		if (ret == EFI_SUCCESS) {
+			ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0));
+			if (ret != EFI_SUCCESS)
+				printf("EFI Capsule update failed at %ls\n",
+				       files[i]);
+
+			free(capsule);
+		} else {
+			printf("EFI: reading capsule failed: %ls\n",
+			       files[i]);
+		}
+		/* create CapsuleXXXX */
+		set_capsule_result(index, capsule, ret);
+
+		/* delete a capsule either in case of success or failure */
+		ret = efi_capsule_delete_file(files[i]);
+		if (ret != EFI_SUCCESS)
+			printf("EFI: deleting a capsule file failed: %ls\n",
+			       files[i]);
+	}
+	efi_capsule_scan_done();
+
+	for (i = 0; i < nfiles; i++)
+		free(files[i]);
+	free(files);
+
+	/* CapsuleLast */
+	efi_create_indexed_name(variable_name16, L"Capsule", index - 1);
+	efi_set_variable_int(L"CapsuleLast", &efi_guid_capsule_report,
+			     EFI_VARIABLE_READ_ONLY |
+			     EFI_VARIABLE_NON_VOLATILE |
+			     EFI_VARIABLE_BOOTSERVICE_ACCESS |
+			     EFI_VARIABLE_RUNTIME_ACCESS,
+			     22, variable_name16, false);
+
+	return ret;
+}
+#endif /* CONFIG_EFI_CAPSULE_ON_DISK */
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 3a1c8ea00446..99146671c899 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -156,6 +156,10 @@ static efi_status_t efi_init_os_indications(void)
 		os_indications_supported |=
 			EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED;
 
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK))
+		os_indications_supported |=
+			EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
+
 	return efi_set_variable_int(L"OsIndicationsSupported",
 				    &efi_global_variable_guid,
 				    EFI_VARIABLE_BOOTSERVICE_ACCESS |
@@ -276,6 +280,10 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 
+	/* Execute capsules after reboot */
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) &&
+	    !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
+		ret = efi_launch_capsules();
 out:
 	efi_obj_list_initialized = ret;
 	return ret;
-- 
2.28.0

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

* [PATCH v8 09/18] efi_loader: capsule: add memory range capsule definitions
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (7 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 08/18] efi_loader: capsule: add capsule_on_disk support AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 10/18] efi_loader: capsule: support firmware update AKASHI Takahiro
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

Memory range capsule gives us a way to notify that some memory regions
should be left untouched across the next reset.
See UEFI specification, section 8.5.3.

Since how we should handle this kind of capsule is totally up to
the system, no implementation will be added in this commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/include/efi_api.h b/include/efi_api.h
index c128a0a66ce8..7a2a087c60ed 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -221,6 +221,10 @@ enum efi_reset_type {
 	EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \
 		 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3)
 
+#define EFI_MEMORY_RANGE_CAPSULE_GUID \
+	EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \
+		 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72)
+
 struct efi_capsule_header {
 	efi_guid_t capsule_guid;
 	u32 header_size;
@@ -236,6 +240,19 @@ struct efi_capsule_result_variable_header {
 	efi_status_t capsule_status;
 } __packed;
 
+struct efi_memory_range {
+	efi_physical_addr_t	address;
+	u64			length;
+};
+
+struct efi_memory_range_capsule {
+	struct efi_capsule_header *header;
+	/* EFI_MEMORY_TYPE: 0x80000000-0xFFFFFFFF */
+	enum efi_mem_type os_requested_memory_type;
+	u64 number_of_memory_ranges;
+	struct efi_memory_range memory_ranges[];
+} __packed;
+
 #define EFI_RT_SUPPORTED_GET_TIME			0x0001
 #define EFI_RT_SUPPORTED_SET_TIME			0x0002
 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME		0x0004
-- 
2.28.0

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

* [PATCH v8 10/18] efi_loader: capsule: support firmware update
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (8 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 09/18] efi_loader: capsule: add memory range capsule definitions AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 11/18] efi_loader: add firmware management protocol for FIT image AKASHI Takahiro
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

A capsule tagged with the guid, EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID,
is handled as a firmware update object.
What efi_update_capsule() basically does is to load any firmware management
protocol (or fmp) drivers contained in a capsule, find out an appropriate
fmp driver and then invoke its set_image() interface against each binary
in a capsule.
In this commit, however, loading drivers is not supported.

The result of applying a capsule is set to be stored in "CapsuleXXXX"
variable, but its implementation is deferred to a fmp driver.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h            | 129 +++++++++++++++++++
 include/efi_loader.h         |   2 +
 lib/efi_loader/Kconfig       |   8 ++
 lib/efi_loader/efi_capsule.c | 238 ++++++++++++++++++++++++++++++++++-
 lib/efi_loader/efi_setup.c   |   4 +
 5 files changed, 380 insertions(+), 1 deletion(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index 7a2a087c60ed..966bc6e590bf 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -217,6 +217,9 @@ enum efi_reset_type {
 #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE	0x00020000
 #define CAPSULE_FLAGS_INITIATE_RESET		0x00040000
 
+#define CAPSULE_SUPPORT_AUTHENTICATION		0x0000000000000001
+#define CAPSULE_SUPPORT_DEPENDENCY		0x0000000000000002
+
 #define EFI_CAPSULE_REPORT_GUID \
 	EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \
 		 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3)
@@ -225,6 +228,10 @@ enum efi_reset_type {
 	EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \
 		 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72)
 
+#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \
+	EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \
+		 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a)
+
 struct efi_capsule_header {
 	efi_guid_t capsule_guid;
 	u32 header_size;
@@ -253,6 +260,33 @@ struct efi_memory_range_capsule {
 	struct efi_memory_range memory_ranges[];
 } __packed;
 
+struct efi_firmware_management_capsule_header {
+	u32 version;
+	u16 embedded_driver_count;
+	u16 payload_item_count;
+	u64 item_offset_list[];
+} __packed;
+
+struct efi_firmware_management_capsule_image_header {
+	u32 version;
+	efi_guid_t update_image_type_id;
+	u8 update_image_index;
+	u8 reserved[3];
+	u32 update_image_size;
+	u32 update_vendor_code_size;
+	u64 update_hardware_instance;
+	u64 image_capsule_support;
+} __packed;
+
+struct efi_capsule_result_variable_fmp {
+	u16 version;
+	u8 payload_index;
+	u8 update_image_index;
+	efi_guid_t update_image_type_id;
+	// u16 capsule_file_name[];
+	// u16 capsule_target[];
+} __packed;
+
 #define EFI_RT_SUPPORTED_GET_TIME			0x0001
 #define EFI_RT_SUPPORTED_SET_TIME			0x0002
 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME		0x0004
@@ -1808,4 +1842,99 @@ struct efi_signature_list {
 /*	struct efi_signature_data signatures[...][signature_size]; */
 } __attribute__((__packed__));
 
+/*
+ * Firmware management protocol
+ */
+#define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \
+	EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \
+		 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7)
+
+#define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE		0x0000000000000001
+#define IMAGE_ATTRIBUTE_RESET_REQUIRED		0x0000000000000002
+#define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED	0x0000000000000004
+#define IMAGE_ATTRIBUTE_IN_USE			0x0000000000000008
+#define IMAGE_ATTRIBUTE_UEFI_IMAGE		0x0000000000000010
+#define IMAGE_ATTRIBUTE_DEPENDENCY		0x0000000000000020
+
+#define IMAGE_COMPATIBILITY_CHECK_SUPPORTED	0x0000000000000001
+
+#define IMAGE_UPDATABLE_VALID			0x0000000000000001
+#define IMAGE_UPDATABLE_INVALID			0x0000000000000002
+#define IMAGE_UPDATABLE_INVALID_TYPE		0x0000000000000004
+#define IMAGE_UPDATABLE_INVALID_OLLD		0x0000000000000008
+#define IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE	0x0000000000000010
+
+#define PACKAGE_ATTRIBUTE_VERSION_UPDATABLE		0x0000000000000001
+#define PACKAGE_ATTRIBUTE_RESET_REQUIRED		0x0000000000000002
+#define PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED	0x0000000000000004
+
+#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION	4
+
+typedef struct efi_firmware_image_dependencies {
+	u8 dependencies[0];
+} efi_firmware_image_dep_t;
+
+struct efi_firmware_image_descriptor {
+	u8 image_index;
+	efi_guid_t image_type_id;
+	u64 image_id;
+	u16 *image_id_name;
+	u32 version;
+	u16 *version_name;
+	efi_uintn_t size;
+	u64 attributes_supported;
+	u64 attributes_setting;
+	u64 compatibilities;
+	u32 lowest_supported_image_version;
+	u32 last_attempt_version;
+	u32 last_attempt_status;
+	u64 hardware_instance;
+	efi_firmware_image_dep_t *dependencies;
+};
+
+struct efi_firmware_management_protocol {
+	efi_status_t (EFIAPI *get_image_info)(
+			struct efi_firmware_management_protocol *this,
+			efi_uintn_t *image_info_size,
+			struct efi_firmware_image_descriptor *image_info,
+			u32 *descriptor_version,
+			u8 *descriptor_count,
+			efi_uintn_t *descriptor_size,
+			u32 *package_version,
+			u16 **package_version_name);
+	efi_status_t (EFIAPI *get_image)(
+			struct efi_firmware_management_protocol *this,
+			u8 image_index,
+			void *image,
+			efi_uintn_t *image_size);
+	efi_status_t (EFIAPI *set_image)(
+			struct efi_firmware_management_protocol *this,
+			u8 image_index,
+			const void *image,
+			efi_uintn_t image_size,
+			const void *vendor_code,
+			efi_status_t (*progress)(efi_uintn_t completion),
+			u16 **abort_reason);
+	efi_status_t (EFIAPI *check_image)(
+			struct efi_firmware_management_protocol *this,
+			u8 image_index,
+			const void *image,
+			efi_uintn_t *image_size,
+			u32 *image_updatable);
+	efi_status_t (EFIAPI *get_package_info)(
+			struct efi_firmware_management_protocol *this,
+			u32 *package_version,
+			u16 **package_version_name,
+			u32 *package_version_name_maxlen,
+			u64 *attributes_supported,
+			u64 *attributes_setting);
+	efi_status_t (EFIAPI *set_package_info)(
+			struct efi_firmware_management_protocol *this,
+			const void *image,
+			efi_uintn_t *image_size,
+			const void *vendor_code,
+			u32 package_version,
+			const u16 *package_version_name);
+};
+
 #endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 572cfadd491a..b3b575f10c6a 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -209,6 +209,8 @@ extern const efi_guid_t efi_guid_cert_type_pkcs7;
 extern const efi_guid_t efi_guid_rng_protocol;
 /* GUID of capsule update result */
 extern const efi_guid_t efi_guid_capsule_report;
+/* GUID of firmware management protocol */
+extern const efi_guid_t efi_guid_firmware_management_protocol;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e1ac5ac055de..5cb34687c26a 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -126,6 +126,14 @@ config EFI_CAPSULE_ON_DISK_EARLY
 	  executed as part of U-Boot initialisation so that they will
 	  surely take place whatever is set to distro_bootcmd.
 
+config EFI_CAPSULE_FIRMWARE_MANAGEMENT
+	bool "Capsule: Firmware Management Protocol"
+	depends on EFI_HAVE_CAPSULE_SUPPORT
+	default y
+	help
+	  Select this option if you want to enable capsule-based
+	  firmware update using Firmware Management Protocol.
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 2259bfbf3d19..2015929e3708 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -15,6 +15,10 @@
 #include <sort.h>
 
 const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
+static const efi_guid_t efi_guid_firmware_management_capsule_id =
+		EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
+const efi_guid_t efi_guid_firmware_management_protocol =
+		EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
 
 #ifdef CONFIG_EFI_CAPSULE_ON_DISK
 /* for file system access */
@@ -88,6 +92,218 @@ void set_capsule_result(int index, struct efi_capsule_header *capsule,
 		printf("EFI: creating %ls failed\n", variable_name16);
 }
 
+#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT
+/**
+ * efi_fmp_find - search for Firmware Management Protocol drivers
+ * @image_type:		Image type guid
+ * @instance:		Instance number
+ * @handles:		Handles of FMP drivers
+ * @no_handles:		Number of handles
+ *
+ * Search for Firmware Management Protocol drivers, matching the image
+ * type, @image_type and the machine instance, @instance, from the list,
+ * @handles.
+ *
+ * Return:
+ * * Protocol instance	- on success
+ * * NULL		- on failure
+ */
+static struct efi_firmware_management_protocol *
+efi_fmp_find(efi_guid_t *image_type, u64 instance, efi_handle_t *handles,
+	     efi_uintn_t no_handles)
+{
+	efi_handle_t *handle;
+	struct efi_firmware_management_protocol *fmp;
+	struct efi_firmware_image_descriptor *image_info, *desc;
+	efi_uintn_t info_size, descriptor_size;
+	u32 descriptor_version;
+	u8 descriptor_count;
+	u32 package_version;
+	u16 *package_version_name;
+	bool found = false;
+	int i, j;
+	efi_status_t ret;
+
+	for (i = 0, handle = handles; i < no_handles; i++, handle++) {
+		ret = EFI_CALL(efi_handle_protocol(
+				*handle,
+				&efi_guid_firmware_management_protocol,
+				(void **)&fmp));
+		if (ret != EFI_SUCCESS)
+			continue;
+
+		/* get device's image info */
+		info_size = 0;
+		image_info = NULL;
+		descriptor_version = 0;
+		descriptor_count = 0;
+		descriptor_size = 0;
+		package_version = 0;
+		package_version_name = NULL;
+		ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
+						   image_info,
+						   &descriptor_version,
+						   &descriptor_count,
+						   &descriptor_size,
+						   &package_version,
+						   &package_version_name));
+		if (ret != EFI_BUFFER_TOO_SMALL)
+			goto skip;
+
+		image_info = malloc(info_size);
+		if (!image_info)
+			goto skip;
+
+		ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
+						   image_info,
+						   &descriptor_version,
+						   &descriptor_count,
+						   &descriptor_size,
+						   &package_version,
+						   &package_version_name));
+		if (ret != EFI_SUCCESS)
+			goto skip;
+
+		/* matching */
+		for (j = 0, desc = image_info; j < descriptor_count;
+		     j++, desc = (void *)desc + descriptor_size) {
+			EFI_PRINT("+++ desc[%d] index: %d, name: %ls\n",
+				  j, desc->image_index, desc->image_id_name);
+			if (!guidcmp(&desc->image_type_id, image_type) &&
+			    (!instance ||
+			     !desc->hardware_instance ||
+			     (descriptor_version >= 3 &&
+			      desc->hardware_instance == instance)))
+				found = true;
+		}
+
+skip:
+		efi_free_pool(package_version_name);
+		free(image_info);
+		EFI_CALL(efi_close_protocol(
+				(efi_handle_t)fmp,
+				&efi_guid_firmware_management_protocol,
+				NULL, NULL));
+		if (found)
+			return fmp;
+	}
+
+	return NULL;
+}
+
+/**
+ * efi_capsule_update_firmware - update firmware from capsule
+ * @capsule_data:	Capsule
+ *
+ * Update firmware, using a capsule, @capsule_data. Loading any FMP
+ * drivers embedded in a capsule is not supported.
+ *
+ * Return:		status code
+ */
+static efi_status_t efi_capsule_update_firmware(
+		struct efi_capsule_header *capsule_data)
+{
+	struct efi_firmware_management_capsule_header *capsule;
+	struct efi_firmware_management_capsule_image_header *image;
+	size_t capsule_size;
+	void *image_binary, *vendor_code;
+	efi_handle_t *handles;
+	efi_uintn_t no_handles;
+	int item;
+	struct efi_firmware_management_protocol *fmp;
+	u16 *abort_reason;
+	efi_status_t ret = EFI_SUCCESS;
+
+	/* sanity check */
+	if (capsule_data->header_size < sizeof(*capsule) ||
+	    capsule_data->header_size >= capsule_data->capsule_image_size)
+		return EFI_INVALID_PARAMETER;
+
+	capsule = (void *)capsule_data + capsule_data->header_size;
+	capsule_size = capsule_data->capsule_image_size
+			- capsule_data->header_size;
+
+	if (capsule->version != 0x00000001)
+		return EFI_INVALID_PARAMETER;
+
+	/* Drivers */
+	/* TODO: support loading drivers */
+
+	handles = NULL;
+	ret = EFI_CALL(efi_locate_handle_buffer(
+			BY_PROTOCOL,
+			&efi_guid_firmware_management_protocol,
+			NULL, &no_handles, (efi_handle_t **)&handles));
+	if (ret != EFI_SUCCESS)
+		return EFI_UNSUPPORTED;
+
+	/* Payload */
+	for (item = capsule->embedded_driver_count;
+	     item < capsule->embedded_driver_count
+		    + capsule->payload_item_count; item++) {
+		/* sanity check */
+		if ((capsule->item_offset_list[item] + sizeof(*image)
+				 >= capsule_size)) {
+			printf("EFI: A capsule has not enough size of data\n");
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+
+		image = (void *)capsule + capsule->item_offset_list[item];
+
+		if (image->version != 0x00000001 &&
+		    image->version != 0x00000002 &&
+		    image->version != 0x00000003) {
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+
+		/* find a device for update firmware */
+		/* TODO: should we pass index as well, or nothing but type? */
+		fmp = efi_fmp_find(&image->update_image_type_id,
+				   image->version == 0x1 ? 0 :
+					image->update_hardware_instance,
+				   handles, no_handles);
+		if (!fmp) {
+			printf("EFI Capsule: driver not found for firmware type: %pUl, hardware instance: %lld\n",
+			       &image->update_image_type_id,
+			       image->version == 0x1 ? 0 :
+					image->update_hardware_instance);
+			ret = EFI_UNSUPPORTED;
+			goto out;
+		}
+
+		/* do it */
+		image_binary = (void *)image + sizeof(*image);
+		vendor_code = image_binary + image->update_image_size;
+
+		abort_reason = NULL;
+		ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,
+					      image_binary,
+					      image->update_image_size,
+					      vendor_code, NULL,
+					      &abort_reason));
+		if (ret != EFI_SUCCESS) {
+			printf("EFI Capsule: firmware update failed: %ls\n",
+			       abort_reason);
+			efi_free_pool(abort_reason);
+			goto out;
+		}
+	}
+
+out:
+	efi_free_pool(handles);
+
+	return ret;
+}
+#else
+static efi_status_t efi_capsule_update_firmware(
+		struct efi_capsule_header *capsule_data)
+{
+	return EFI_UNSUPPORTED;
+}
+#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
+
 /**
  * efi_update_capsule() - process information from operating system
  * @capsule_header_array:	Array of virtual address pointers
@@ -118,9 +334,29 @@ efi_status_t EFIAPI efi_update_capsule(
 		goto out;
 	}
 
-	ret = EFI_UNSUPPORTED;
+	ret = EFI_SUCCESS;
 	for (i = 0, capsule = *capsule_header_array; i < capsule_count;
 	     i++, capsule = *(++capsule_header_array)) {
+		/* sanity check */
+		if (capsule->header_size < sizeof(*capsule) ||
+		    capsule->capsule_image_size < sizeof(*capsule)) {
+			printf("EFI: A capsule has not enough size of data\n");
+			continue;
+		}
+
+		EFI_PRINT("Capsule[%d] (guid:%pUl)\n",
+			  i, &capsule->capsule_guid);
+		if (!guidcmp(&capsule->capsule_guid,
+			     &efi_guid_firmware_management_capsule_id)) {
+			ret  = efi_capsule_update_firmware(capsule);
+		} else {
+			printf("EFI: not support capsule type: %pUl\n",
+			       &capsule->capsule_guid);
+			ret = EFI_UNSUPPORTED;
+		}
+
+		if (ret != EFI_SUCCESS)
+			goto out;
 	}
 out:
 	return EFI_EXIT(ret);
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 99146671c899..b4303864bde6 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -160,6 +160,10 @@ static efi_status_t efi_init_os_indications(void)
 		os_indications_supported |=
 			EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
 
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT))
+		os_indications_supported |=
+			EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED;
+
 	return efi_set_variable_int(L"OsIndicationsSupported",
 				    &efi_global_variable_guid,
 				    EFI_VARIABLE_BOOTSERVICE_ACCESS |
-- 
2.28.0

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

* [PATCH v8 11/18] efi_loader: add firmware management protocol for FIT image
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (9 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 10/18] efi_loader: capsule: support firmware update AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 12/18] dfu: add dfu_write_by_alt() AKASHI Takahiro
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

In this commit, a very simple firmware management protocol driver
is implemented. It will take a common FIT image firmware in a capsule
file and apply the data using dfu backend storage drivers via
update_fit() interface.

So "dfu_alt_info" variable should be properly set to specify a device
and location to be updated. Please read README.dfu.

Fit image is a common file format for firmware update on U-Boot, and
this protocol works neatly just as a wrapper for one.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h             |   4 +
 include/efi_loader.h          |   2 +
 lib/efi_loader/Kconfig        |  11 ++
 lib/efi_loader/Makefile       |   1 +
 lib/efi_loader/efi_capsule.c  |  12 +-
 lib/efi_loader/efi_firmware.c | 291 ++++++++++++++++++++++++++++++++++
 6 files changed, 320 insertions(+), 1 deletion(-)
 create mode 100644 lib/efi_loader/efi_firmware.c

diff --git a/include/efi_api.h b/include/efi_api.h
index 966bc6e590bf..071d0ba866c7 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1849,6 +1849,10 @@ struct efi_signature_list {
 	EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \
 		 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7)
 
+#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID \
+	EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \
+		 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47)
+
 #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE		0x0000000000000001
 #define IMAGE_ATTRIBUTE_RESET_REQUIRED		0x0000000000000002
 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED	0x0000000000000004
diff --git a/include/efi_loader.h b/include/efi_loader.h
index b3b575f10c6a..de6d353de3b1 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -811,6 +811,8 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n);
 /* commonly used helper function */
 u16 *efi_create_indexed_name(u16 *buffer, const u16 *name, unsigned int index);
 
+extern const struct efi_firmware_management_protocol efi_fmp_fit;
+
 /* Capsule update */
 efi_status_t EFIAPI efi_update_capsule(
 		struct efi_capsule_header **capsule_header_array,
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 5cb34687c26a..159400fec39e 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -134,6 +134,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
 	  Select this option if you want to enable capsule-based
 	  firmware update using Firmware Management Protocol.
 
+config EFI_CAPSULE_FIRMWARE_FIT
+	bool "FMP driver for FIT image"
+	depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+	depends on FIT
+	select UPDATE_FIT
+	select DFU
+	default n
+	help
+	  Select this option if you want to enable firmware management protocol
+	  driver for FIT image
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index c7d231f0e57d..23b1828b0fe0 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_bootmgr.o
 obj-y += efi_boottime.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
+obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
 obj-y += efi_console.o
 obj-y += efi_device_path.o
 obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 2015929e3708..a44f81daaee9 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -804,7 +804,17 @@ static void efi_capsule_scan_done(void)
  */
 efi_status_t __weak arch_efi_load_capsule_drivers(void)
 {
-	return EFI_SUCCESS;
+	__maybe_unused efi_handle_t handle;
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)) {
+		handle = NULL;
+		ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
+				&handle, &efi_guid_firmware_management_protocol,
+				&efi_fmp_fit, NULL));
+	}
+
+	return ret;
 }
 
 /**
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
new file mode 100644
index 000000000000..4c395f4eb5d9
--- /dev/null
+++ b/lib/efi_loader/efi_firmware.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI Firmware management protocol
+ *
+ *  Copyright (c) 2020 Linaro Limited
+ *			Author: AKASHI Takahiro
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <dfu.h>
+#include <efi_loader.h>
+#include <image.h>
+#include <linux/list.h>
+
+/*
+ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
+ * method with existing FIT image format, and handles
+ *   - multiple regions of firmware via DFU
+ * but doesn't support
+ *   - versioning of firmware image
+ *   - package information
+ */
+const efi_guid_t efi_firmware_image_type_uboot_fit =
+	EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+
+/**
+ * efi_get_dfu_info - return information about the current firmware image
+ * @this:			Protocol instance
+ * @image_info_size:		Size of @image_info
+ * @image_info:			Image information
+ * @descriptor_version:		Pointer to version number
+ * @descriptor_count:		Pointer to number of descriptors
+ * @descriptor_size:		Pointer to descriptor size
+ * package_version:		Package version
+ * package_version_name:	Package version's name
+ * image_type:			Image type GUID
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ * Each descriptor will be created based on "dfu_alt_info" variable.
+ *
+ * Return		status code
+ */
+static efi_status_t efi_get_dfu_info(
+	efi_uintn_t *image_info_size,
+	struct efi_firmware_image_descriptor *image_info,
+	u32 *descriptor_version,
+	u8 *descriptor_count,
+	efi_uintn_t *descriptor_size,
+	u32 *package_version,
+	u16 **package_version_name,
+	const efi_guid_t *image_type)
+{
+	struct dfu_entity *dfu;
+	size_t names_len, total_size;
+	int dfu_num, i;
+	u16 *name, *next;
+
+	dfu_init_env_entities(NULL, NULL);
+
+	names_len = 0;
+	dfu_num = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		names_len += (utf8_utf16_strlen(dfu->name) + 1) * 2;
+		dfu_num++;
+	}
+	if (!dfu_num) {
+		EFI_PRINT("Probably dfu_alt_info not defined\n");
+		*image_info_size = 0;
+		dfu_free_entities();
+
+		return EFI_SUCCESS;
+	}
+
+	total_size = sizeof(*image_info) * dfu_num + names_len;
+	/*
+	 * we will assume that sizeof(*image_info) * dfu_name
+	 * is, at least, a multiple of 2. So the start address for
+	 * image_id_name would be aligned with 2 bytes.
+	 */
+	if (*image_info_size < total_size) {
+		*image_info_size = total_size;
+		dfu_free_entities();
+
+		return EFI_BUFFER_TOO_SMALL;
+	}
+	*image_info_size = total_size;
+
+	*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+	*descriptor_count = dfu_num;
+	*descriptor_size = sizeof(*image_info);
+	*package_version = 0xffffffff; /* not supported */
+	*package_version_name = NULL; /* not supported */
+
+	/* DFU alt number should correspond to image_index */
+	i = 0;
+	/* Name area starts just after descriptors */
+	name = (u16 *)((u8 *)image_info + sizeof(*image_info) * dfu_num);
+	next = name;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		image_info[i].image_index = dfu->alt + 1;
+		image_info[i].image_type_id = *image_type;
+		image_info[i].image_id = dfu->alt;
+
+		/* copy the DFU entity name */
+		utf8_utf16_strcpy(&next, dfu->name);
+		image_info[i].image_id_name = name;
+		name = ++next;
+
+		image_info[i].version = 0; /* not supported */
+		image_info[i].version_name = NULL; /* not supported */
+		image_info[i].size = 0;
+		image_info[i].attributes_supported =
+				IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+		image_info[i].attributes_setting =
+				IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+		image_info[i].lowest_supported_image_version = 0;
+		image_info[i].last_attempt_version = 0;
+		image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+		image_info[i].hardware_instance = 1;
+		image_info[i].dependencies = NULL;
+
+		i++;
+	}
+
+	dfu_free_entities();
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * efi_firmware_fit_get_image_info - return information about the current
+ *				     firmware image
+ * @this:			Protocol instance
+ * @image_info_size:		Size of @image_info
+ * @image_info:			Image information
+ * @descriptor_version:		Pointer to version number
+ * @descriptor_count:		Pointer to number of descriptors
+ * @descriptor_size:		Pointer to descriptor size
+ * package_version:		Package version
+ * package_version_name:	Package version's name
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ * Each descriptor will be created based on "dfu_alt_info" variable.
+ *
+ * Return		status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_fit_get_image_info(
+	struct efi_firmware_management_protocol *this,
+	efi_uintn_t *image_info_size,
+	struct efi_firmware_image_descriptor *image_info,
+	u32 *descriptor_version,
+	u8 *descriptor_count,
+	efi_uintn_t *descriptor_size,
+	u32 *package_version,
+	u16 **package_version_name)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+		  image_info_size, image_info,
+		  descriptor_version, descriptor_count, descriptor_size,
+		  package_version, package_version_name);
+
+	if (!image_info_size)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (*image_info_size &&
+	    (!image_info || !descriptor_version || !descriptor_count ||
+	     !descriptor_size || !package_version || !package_version_name))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	ret = efi_get_dfu_info(image_info_size, image_info,
+			       descriptor_version, descriptor_count,
+			       descriptor_size,
+			       package_version, package_version_name,
+			       &efi_firmware_image_type_uboot_fit);
+
+	return EFI_EXIT(ret);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	void *image,
+	efi_uintn_t *image_size)
+{
+	EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/**
+ * efi_firmware_fit_set_image - update the firmware image
+ * @this:		Protocol instance
+ * @image_index:	Image index number
+ * @image:		New image
+ * @image_size:		Size of new image
+ * @vendor_code:	Vendor-specific update policy
+ * @progress:		Function to report the progress of update
+ * @abort_reason:	Pointer to string of abort reason
+ *
+ * Update the firmware to new image, using dfu. The new image should
+ * have FIT image format commonly used in U-Boot.
+ * @vendor_code, @progress and @abort_reason are not supported.
+ *
+ * Return:		status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_fit_set_image(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	const void *image,
+	efi_uintn_t image_size,
+	const void *vendor_code,
+	efi_status_t (*progress)(efi_uintn_t completion),
+	u16 **abort_reason)
+{
+	EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image,
+		  image_size, vendor_code, progress, abort_reason);
+
+	if (!image || image_index != 1)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (fit_update(image))
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_check_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	const void *image,
+	efi_uintn_t *image_size,
+	u32 *image_updatable)
+{
+	EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
+		  image_updatable);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u32 *package_version,
+	u16 **package_version_name,
+	u32 *package_version_name_maxlen,
+	u64 *attributes_supported,
+	u64 *attributes_setting)
+{
+	EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
+		  package_version_name, package_version_name_maxlen,
+		  attributes_supported, attributes_setting);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	const void *image,
+	efi_uintn_t *image_size,
+	const void *vendor_code,
+	u32 package_version,
+	const u16 *package_version_name)
+{
+	EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
+		  package_version, package_version_name);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+const struct efi_firmware_management_protocol efi_fmp_fit = {
+	.get_image_info = efi_firmware_fit_get_image_info,
+	.get_image = efi_firmware_get_image_unsupported,
+	.set_image = efi_firmware_fit_set_image,
+	.check_image = efi_firmware_check_image_unsupported,
+	.get_package_info = efi_firmware_get_package_info_unsupported,
+	.set_package_info = efi_firmware_set_package_info_unsupported,
+};
-- 
2.28.0

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

* [PATCH v8 12/18] dfu: add dfu_write_by_alt()
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (10 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 11/18] efi_loader: add firmware management protocol for FIT image AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 13/18] efi_loader: add firmware management protocol for raw image AKASHI Takahiro
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

This function is a variant of dfu_write_by_name() and takes a DFU alt
setting number for dfu configuration.

It will be utilised to implement UEFI capsule management protocol for
raw image in a later commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 drivers/dfu/dfu_alt.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h         | 26 +++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/dfu/dfu_alt.c b/drivers/dfu/dfu_alt.c
index 7528806cd163..d5827812070c 100644
--- a/drivers/dfu/dfu_alt.c
+++ b/drivers/dfu/dfu_alt.c
@@ -76,3 +76,50 @@ done:
 
 	return ret;
 }
+
+/**
+ * dfu_write_by_alt() - write data to DFU medium
+ * @dfu_alt_num:        DFU alt setting number
+ * @addr:               Address of data buffer to write
+ * @len:                Number of bytes
+ * @interface:          Destination DFU medium (e.g. "mmc")
+ * @devstring:          Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_alt_name.
+ *
+ * Return:              0 - on success, error code - otherwise
+ */
+int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
+		     char *interface, char *devstring)
+{
+	struct dfu_entity *dfu;
+	int ret;
+
+	debug("%s: alt: %d addr: 0x%p len: %d device: %s:%s\n", __func__,
+	      dfu_alt_num, addr, len, interface, devstring);
+
+	ret = dfu_init_env_entities(interface, devstring);
+	if (ret)
+		goto done;
+
+	if (dfu_alt_num < 0) {
+		pr_err("Invalid alt number: %d", dfu_alt_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dfu = dfu_get_entity(dfu_alt_num);
+	if (!dfu) {
+		pr_err("DFU entity for alt: %d not found!", dfu_alt_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
+
+done:
+	dfu_free_entities();
+
+	return ret;
+}
diff --git a/include/dfu.h b/include/dfu.h
index eaf4bfc0d5ed..a767adee4107 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -496,6 +496,7 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
 /**
  * dfu_write_by_name() - write data to DFU medium
  * @dfu_entity_name:	Name of DFU entity to write
@@ -509,9 +510,24 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
  *
  * Return:		0 - on success, error code - otherwise
  */
-#if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
 int dfu_write_by_name(char *dfu_entity_name, void *addr,
 		      unsigned int len, char *interface, char *devstring);
+
+/**
+ * dfu_write_by_alt() - write data to DFU medium
+ * @dfu_alt_num:	DFU alt setting number
+ * @addr:		Address of data buffer to write
+ * @len:		Number of bytes
+ * @interface:		Destination DFU medium (e.g. "mmc")
+ * @devstring:		Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_alt_name.
+ *
+ * Return:		0 - on success, error code - otherwise
+ */
+int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
+		     char *interface, char *devstring);
 #else
 static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
 				    unsigned int len, char *interface,
@@ -520,6 +536,14 @@ static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
 	puts("write support for DFU not available!\n");
 	return -ENOSYS;
 }
+
+static inline int dfu_write_by_alt(int dfu_alt_num, void *addr,
+				   unsigned int len, char *interface,
+				   char *devstring)
+{
+	puts("write support for DFU not available!\n");
+	return -ENOSYS;
+}
 #endif
 
 int dfu_add(struct usb_configuration *c);
-- 
2.28.0

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

* [PATCH v8 13/18] efi_loader: add firmware management protocol for raw image
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (11 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 12/18] dfu: add dfu_write_by_alt() AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 14/18] cmd: add "efidebug capsule" command AKASHI Takahiro
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

In this commit, a very simple firmware management protocol driver
is implemented. It will take a binary image in a capsule file and
apply the data using dfu backend storage drivers via dfu_write_by_alt()
interface.

So "dfu_alt_info" variable should be properly set to specify a device
and location to be updated. Please read README.dfu.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h             |   4 +
 include/efi_loader.h          |   1 +
 lib/efi_loader/Kconfig        |  16 +++
 lib/efi_loader/Makefile       |   2 +-
 lib/efi_loader/efi_capsule.c  |   8 ++
 lib/efi_loader/efi_firmware.c | 226 +++++++++++++++++++++++++---------
 6 files changed, 199 insertions(+), 58 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index 071d0ba866c7..c7038f863ab2 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1853,6 +1853,10 @@ struct efi_signature_list {
 	EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \
 		 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47)
 
+#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID \
+	EFI_GUID(0xe2bb9c06, 0x70e9, 0x4b14, 0x97, 0xa3, \
+		 0x5a, 0x79, 0x13, 0x17, 0x6e, 0x3f)
+
 #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE		0x0000000000000001
 #define IMAGE_ATTRIBUTE_RESET_REQUIRED		0x0000000000000002
 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED	0x0000000000000004
diff --git a/include/efi_loader.h b/include/efi_loader.h
index de6d353de3b1..0f85873a72f8 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -812,6 +812,7 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n);
 u16 *efi_create_indexed_name(u16 *buffer, const u16 *name, unsigned int index);
 
 extern const struct efi_firmware_management_protocol efi_fmp_fit;
+extern const struct efi_firmware_management_protocol efi_fmp_raw;
 
 /* Capsule update */
 efi_status_t EFIAPI efi_update_capsule(
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 159400fec39e..8332a5072d42 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -126,6 +126,10 @@ config EFI_CAPSULE_ON_DISK_EARLY
 	  executed as part of U-Boot initialisation so that they will
 	  surely take place whatever is set to distro_bootcmd.
 
+config EFI_CAPSULE_FIRMWARE
+	bool
+	default n
+
 config EFI_CAPSULE_FIRMWARE_MANAGEMENT
 	bool "Capsule: Firmware Management Protocol"
 	depends on EFI_HAVE_CAPSULE_SUPPORT
@@ -140,11 +144,23 @@ config EFI_CAPSULE_FIRMWARE_FIT
 	depends on FIT
 	select UPDATE_FIT
 	select DFU
+	select EFI_CAPSULE_FIRMWARE
 	default n
 	help
 	  Select this option if you want to enable firmware management protocol
 	  driver for FIT image
 
+config EFI_CAPSULE_FIRMWARE_RAW
+	bool "FMP driver for raw image"
+	depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+	select DFU
+	select DFU_WRITE_ALT
+	select EFI_CAPSULE_FIRMWARE
+	default n
+	help
+	  Select this option if you want to enable firmware management protocol
+	  driver for raw image
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 23b1828b0fe0..a7631d92a3b0 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_bootmgr.o
 obj-y += efi_boottime.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
-obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
+obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
 obj-y += efi_console.o
 obj-y += efi_device_path.o
 obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index a44f81daaee9..af40b4a1599e 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -814,6 +814,14 @@ efi_status_t __weak arch_efi_load_capsule_drivers(void)
 				&efi_fmp_fit, NULL));
 	}
 
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)) {
+		handle = NULL;
+		ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
+				&efi_root,
+				&efi_guid_firmware_management_protocol,
+				&efi_fmp_raw, NULL));
+	}
+
 	return ret;
 }
 
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 4c395f4eb5d9..7e5607738319 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -13,16 +13,66 @@
 #include <image.h>
 #include <linux/list.h>
 
-/*
- * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
- * method with existing FIT image format, and handles
- *   - multiple regions of firmware via DFU
- * but doesn't support
- *   - versioning of firmware image
- *   - package information
- */
-const efi_guid_t efi_firmware_image_type_uboot_fit =
-	EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	void *image,
+	efi_uintn_t *image_size)
+{
+	EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_check_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	const void *image,
+	efi_uintn_t *image_size,
+	u32 *image_updatable)
+{
+	EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
+		  image_updatable);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u32 *package_version,
+	u16 **package_version_name,
+	u32 *package_version_name_maxlen,
+	u64 *attributes_supported,
+	u64 *attributes_setting)
+{
+	EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
+		  package_version_name, package_version_name_maxlen,
+		  attributes_supported, attributes_setting);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	const void *image,
+	efi_uintn_t *image_size,
+	const void *vendor_code,
+	u32 package_version,
+	const u16 *package_version_name)
+{
+	EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
+		  package_version, package_version_name);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
 
 /**
  * efi_get_dfu_info - return information about the current firmware image
@@ -129,6 +179,18 @@ static efi_status_t efi_get_dfu_info(
 	return EFI_SUCCESS;
 }
 
+#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
+/*
+ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
+ * method with existing FIT image format, and handles
+ *   - multiple regions of firmware via DFU
+ * but doesn't support
+ *   - versioning of firmware image
+ *   - package information
+ */
+const efi_guid_t efi_firmware_image_type_uboot_fit =
+	EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+
 /**
  * efi_firmware_fit_get_image_info - return information about the current
  *				     firmware image
@@ -182,19 +244,6 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
 	return EFI_EXIT(ret);
 }
 
-/* Place holder; not supported */
-static
-efi_status_t EFIAPI efi_firmware_get_image_unsupported(
-	struct efi_firmware_management_protocol *this,
-	u8 image_index,
-	void *image,
-	efi_uintn_t *image_size)
-{
-	EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
-
-	return EFI_EXIT(EFI_UNSUPPORTED);
-}
-
 /**
  * efi_firmware_fit_set_image - update the firmware image
  * @this:		Protocol instance
@@ -233,59 +282,122 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
-/* Place holder; not supported */
-static
-efi_status_t EFIAPI efi_firmware_check_image_unsupported(
-	struct efi_firmware_management_protocol *this,
-	u8 image_index,
-	const void *image,
-	efi_uintn_t *image_size,
-	u32 *image_updatable)
-{
-	EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
-		  image_updatable);
+const struct efi_firmware_management_protocol efi_fmp_fit = {
+	.get_image_info = efi_firmware_fit_get_image_info,
+	.get_image = efi_firmware_get_image_unsupported,
+	.set_image = efi_firmware_fit_set_image,
+	.check_image = efi_firmware_check_image_unsupported,
+	.get_package_info = efi_firmware_get_package_info_unsupported,
+	.set_package_info = efi_firmware_set_package_info_unsupported,
+};
+#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
 
-	return EFI_EXIT(EFI_UNSUPPORTED);
-}
+#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
+/*
+ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
+ * method with raw data.
+ */
+const efi_guid_t efi_firmware_image_type_uboot_raw =
+	EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
 
-/* Place holder; not supported */
+/**
+ * efi_firmware_raw_get_image_info - return information about the current
+				     firmware image
+ * @this:			Protocol instance
+ * @image_info_size:		Size of @image_info
+ * @image_info:			Image information
+ * @descriptor_version:		Pointer to version number
+ * @descriptor_count:		Pointer to number of descriptors
+ * @descriptor_size:		Pointer to descriptor size
+ * package_version:		Package version
+ * package_version_name:	Package version's name
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ * Each descriptor will be created based on "dfu_alt_info" variable.
+ *
+ * Return		status code
+ */
 static
-efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
+efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	struct efi_firmware_management_protocol *this,
+	efi_uintn_t *image_info_size,
+	struct efi_firmware_image_descriptor *image_info,
+	u32 *descriptor_version,
+	u8 *descriptor_count,
+	efi_uintn_t *descriptor_size,
 	u32 *package_version,
-	u16 **package_version_name,
-	u32 *package_version_name_maxlen,
-	u64 *attributes_supported,
-	u64 *attributes_setting)
+	u16 **package_version_name)
 {
-	EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
-		  package_version_name, package_version_name_maxlen,
-		  attributes_supported, attributes_setting);
+	efi_status_t ret = EFI_SUCCESS;
 
-	return EFI_EXIT(EFI_UNSUPPORTED);
+	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+		  image_info_size, image_info,
+		  descriptor_version, descriptor_count, descriptor_size,
+		  package_version, package_version_name);
+
+	if (!image_info_size)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (*image_info_size &&
+	    (!image_info || !descriptor_version || !descriptor_count ||
+	     !descriptor_size || !package_version || !package_version_name))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	ret = efi_get_dfu_info(image_info_size, image_info,
+			       descriptor_version, descriptor_count,
+			       descriptor_size,
+			       package_version, package_version_name,
+			       &efi_firmware_image_type_uboot_raw);
+
+	return EFI_EXIT(ret);
 }
 
-/* Place holder; not supported */
+/**
+ * efi_firmware_raw_set_image - update the firmware image
+ * @this:		Protocol instance
+ * @image_index:	Image index number
+ * @image:		New image
+ * @image_size:		Size of new image
+ * @vendor_code:	Vendor-specific update policy
+ * @progress:		Function to report the progress of update
+ * @abort_reason:	Pointer to string of abort reason
+ *
+ * Update the firmware to new image, using dfu. The new image should
+ * be a single raw image.
+ * @vendor_code, @progress and @abort_reason are not supported.
+ *
+ * Return:		status code
+ */
 static
-efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
+efi_status_t EFIAPI efi_firmware_raw_set_image(
 	struct efi_firmware_management_protocol *this,
+	u8 image_index,
 	const void *image,
-	efi_uintn_t *image_size,
+	efi_uintn_t image_size,
 	const void *vendor_code,
-	u32 package_version,
-	const u16 *package_version_name)
+	efi_status_t (*progress)(efi_uintn_t completion),
+	u16 **abort_reason)
 {
-	EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
-		  package_version, package_version_name);
+	EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image,
+		  image_size, vendor_code, progress, abort_reason);
 
-	return EFI_EXIT(EFI_UNSUPPORTED);
+	if (!image)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
+			     NULL, NULL))
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	return EFI_EXIT(EFI_SUCCESS);
 }
 
-const struct efi_firmware_management_protocol efi_fmp_fit = {
-	.get_image_info = efi_firmware_fit_get_image_info,
+const struct efi_firmware_management_protocol efi_fmp_raw = {
+	.get_image_info = efi_firmware_raw_get_image_info,
 	.get_image = efi_firmware_get_image_unsupported,
-	.set_image = efi_firmware_fit_set_image,
+	.set_image = efi_firmware_raw_set_image,
 	.check_image = efi_firmware_check_image_unsupported,
 	.get_package_info = efi_firmware_get_package_info_unsupported,
 	.set_package_info = efi_firmware_set_package_info_unsupported,
 };
+#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */
-- 
2.28.0

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

* [PATCH v8 14/18] cmd: add "efidebug capsule" command
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (12 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 13/18] efi_loader: add firmware management protocol for raw image AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 15/18] tools: add mkeficapsule command for UEFI capsule update AKASHI Takahiro
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

"efidebug capsule" is more or less a debugging utility.
  efidebug capsule update: invoke UpdateCapsule against data on memory
  efidebug capsule show: show a capsule header
  efidebug capsule result: dump a capsule result variable

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 cmd/efidebug.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 235 insertions(+)

diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 5288b9920b4d..7d327c82681f 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -19,6 +19,228 @@
 #include <linux/ctype.h>
 
 #define BS systab.boottime
+#define RT systab.runtime
+
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+/**
+ * do_efi_capsule_update() - process a capsule update
+ *
+ * @cmdtp:	Command table
+ * @flag:	Command flag
+ * @argc:	Number of arguments
+ * @argv:	Argument array
+ * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule update" sub-command.
+ * process a capsule update.
+ *
+ *     efidebug capsule update [-v] <capsule address>
+ */
+static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
+				 int argc, char * const argv[])
+{
+	struct efi_capsule_header *capsule;
+	int verbose = 0;
+	char *endp;
+	efi_status_t ret;
+
+	if (argc != 2 && argc != 3)
+		return CMD_RET_USAGE;
+
+	if (argc == 3) {
+		if (strcmp(argv[1], "-v"))
+			return CMD_RET_USAGE;
+
+		verbose = 1;
+		argc--;
+		argv++;
+	}
+
+	capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
+	if (endp == argv[1]) {
+		printf("Invalid address: %s", argv[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	if (verbose) {
+		printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
+		printf("Capsule flags: 0x%x\n", capsule->flags);
+		printf("Capsule header size: 0x%x\n", capsule->header_size);
+		printf("Capsule image size: 0x%x\n",
+		       capsule->capsule_image_size);
+	}
+
+	ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL));
+	if (ret) {
+		printf("Cannot handle a capsule at %p", capsule);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_efi_capsule_show() - show capsule information
+ *
+ * @cmdtp:	Command table
+ * @flag:	Command flag
+ * @argc:	Number of arguments
+ * @argv:	Argument array
+ * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule show" sub-command.
+ * show capsule information.
+ *
+ *     efidebug capsule show <capsule address>
+ */
+static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
+			       int argc, char * const argv[])
+{
+	struct efi_capsule_header *capsule;
+	char *endp;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
+	if (endp == argv[1]) {
+		printf("Invalid address: %s", argv[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
+	printf("Capsule flags: 0x%x\n", capsule->flags);
+	printf("Capsule header size: 0x%x\n", capsule->header_size);
+	printf("Capsule image size: 0x%x\n",
+	       capsule->capsule_image_size);
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_efi_capsule_res() - show a capsule update result
+ *
+ * @cmdtp:	Command table
+ * @flag:	Command flag
+ * @argc:	Number of arguments
+ * @argv:	Argument array
+ * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule result" sub-command.
+ * show a capsule update result.
+ * If result number is not specified, CapsuleLast will be shown.
+ *
+ *     efidebug capsule result [<capsule result number>]
+ */
+static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
+			      int argc, char * const argv[])
+{
+	int capsule_id;
+	char *endp;
+	char var_name[12];
+	u16 var_name16[12], *p;
+	efi_guid_t guid;
+	struct efi_capsule_result_variable_header *result = NULL;
+	efi_uintn_t size;
+	efi_status_t ret;
+
+	if (argc != 1 && argc != 2)
+		return CMD_RET_USAGE;
+
+	guid = efi_guid_capsule_report;
+	if (argc == 1) {
+		size = sizeof(var_name16);
+		ret = EFI_CALL(RT->get_variable(L"CapsuleLast", &guid, NULL,
+						&size, var_name16));
+		if (ret != EFI_SUCCESS) {
+			if (ret == EFI_NOT_FOUND)
+				printf("CapsuleLast doesn't exist\n");
+			else
+				printf("Failed to get CapsuleLast\n");
+
+			return CMD_RET_FAILURE;
+		}
+		printf("CapsuleLast is %ls\n", var_name16);
+	} else {
+		argc--;
+		argv++;
+
+		capsule_id = simple_strtoul(argv[0], &endp, 16);
+		if (capsule_id < 0 || capsule_id > 0xffff)
+			return CMD_RET_USAGE;
+
+		sprintf(var_name, "Capsule%04X", capsule_id);
+		p = var_name16;
+		utf8_utf16_strncpy(&p, var_name, 9);
+	}
+
+	size = 0;
+	ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		result = malloc(size);
+		ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
+						result));
+		if (ret != EFI_SUCCESS) {
+			free(result);
+			printf("Failed to get %ls\n", var_name16);
+
+			return CMD_RET_FAILURE;
+		}
+	}
+
+	printf("Result total size: 0x%x\n", result->variable_total_size);
+	printf("Capsule guid: %pUl\n", &result->capsule_guid);
+	printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n",
+	       result->capsule_processed.year, result->capsule_processed.month,
+	       result->capsule_processed.day, result->capsule_processed.hour,
+	       result->capsule_processed.minute,
+	       result->capsule_processed.second);
+	printf("Capsule status: 0x%lx\n", result->capsule_status);
+
+	free(result);
+
+	return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
+	U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update,
+			 "", ""),
+	U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
+			 "", ""),
+	U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
+			 "", ""),
+};
+
+/**
+ * do_efi_capsule() - manage UEFI capsules
+ *
+ * @cmdtp:	Command table
+ * @flag:	Command flag
+ * @argc:	Number of arguments
+ * @argv:	Argument array
+ * Return:	CMD_RET_SUCCESS on success,
+ *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule" sub-command.
+ */
+static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag,
+			  int argc, char * const argv[])
+{
+	struct cmd_tbl *cp;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	argc--; argv++;
+
+	cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub,
+			  ARRAY_SIZE(cmd_efidebug_capsule_sub));
+	if (!cp)
+		return CMD_RET_USAGE;
+
+	return cp->cmd(cmdtp, flag, argc, argv);
+}
+#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
 
 /**
  * efi_get_device_handle_info() - get information of UEFI device
@@ -1237,6 +1459,10 @@ static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
 
 static struct cmd_tbl cmd_efidebug_sub[] = {
 	U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+	U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
+			 "", ""),
+#endif
 	U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
 			 "", ""),
 	U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
@@ -1311,6 +1537,15 @@ static char efidebug_help_text[] =
 	"efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
 	"  - set/show UEFI boot order\n"
 	"\n"
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+	"efidebug capsule update [-v] <capsule address>\n"
+	"  - process a capsule\n"
+	"efidebug capsule show <capsule address>\n"
+	"  - show capsule information\n"
+	"efidebug capsule result [<capsule result var>]\n"
+	"  - show a capsule update result\n"
+	"\n"
+#endif
 	"efidebug devices\n"
 	"  - show UEFI devices\n"
 	"efidebug drivers\n"
-- 
2.28.0

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

* [PATCH v8 15/18] tools: add mkeficapsule command for UEFI capsule update
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (13 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 14/18] cmd: add "efidebug capsule" command AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 16/18] test/py: efi_capsule: test for FIT image capsule AKASHI Takahiro
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

This is a utility mainly for test purpose.
  mkeficapsule -f: create a test capsule file for FIT image firmware

Having said that, you will be able to customize the code to fit
your specific requirements for your platform.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 tools/Makefile       |   2 +
 tools/mkeficapsule.c | 238 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 240 insertions(+)
 create mode 100644 tools/mkeficapsule.c

diff --git a/tools/Makefile b/tools/Makefile
index 51123fd92983..66d9376803e3 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -218,6 +218,8 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
 hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
 HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
 
+hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
+
 # We build some files with extra pedantic flags to try to minimize things
 # that won't build on some weird host compiler -- though there are lots of
 # exceptions for files that aren't complaint.
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
new file mode 100644
index 000000000000..db95426457cc
--- /dev/null
+++ b/tools/mkeficapsule.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Linaro Limited
+ *		Author: AKASHI Takahiro
+ */
+
+#include <getopt.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+typedef __s16 s16;
+typedef __s32 s32;
+
+#define aligned_u64 __aligned_u64
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+#include <efi.h>
+#include <efi_api.h>
+
+static const char *tool_name = "mkeficapsule";
+
+efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
+efi_guid_t efi_guid_image_type_uboot_fit =
+		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+efi_guid_t efi_guid_image_type_uboot_raw =
+		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
+
+static struct option options[] = {
+	{"fit", required_argument, NULL, 'f'},
+	{"raw", required_argument, NULL, 'r'},
+	{"index", required_argument, NULL, 'i'},
+	{"instance", required_argument, NULL, 'I'},
+	{"version", required_argument, NULL, 'v'},
+	{"help", no_argument, NULL, 'h'},
+	{NULL, 0, NULL, 0},
+};
+
+static void print_usage(void)
+{
+	printf("Usage: %s [options] <output file>\n"
+	       "Options:\n"
+	       "\t--fit <fit image>      new FIT image file\n"
+	       "\t--raw <raw image>      new raw image file\n"
+	       "\t--index <index>        update image index\n"
+	       "\t--instance <instance>  update hardware instance\n"
+	       "\t--version <version>    firmware version\n"
+	       "\t--help                 print a help message\n",
+	       tool_name);
+}
+
+static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
+			unsigned long version, unsigned long index,
+			unsigned long instance)
+{
+	struct efi_capsule_header header;
+	struct efi_firmware_management_capsule_header capsule;
+	struct efi_firmware_management_capsule_image_header image;
+	FILE *f, *g;
+	struct stat bin_stat;
+	u8 *data;
+	size_t size;
+
+#ifdef DEBUG
+	printf("For output: %s\n", path);
+	printf("\tbin: %s\n\ttype: %pUl\n" bin, guid);
+	printf("\tversion: %ld\n\tindex: %ld\n\tinstance: %ld\n",
+	       version, index, instance);
+#endif
+
+	g = fopen(bin, "r");
+	if (!g) {
+		printf("cannot open %s\n", bin);
+		return -1;
+	}
+	if (stat(bin, &bin_stat) < 0) {
+		printf("cannot determine the size of %s\n", bin);
+		goto err_1;
+	}
+	data = malloc(bin_stat.st_size);
+	if (!data) {
+		printf("cannot allocate memory: %lx\n", bin_stat.st_size);
+		goto err_1;
+	}
+	f = fopen(path, "w");
+	if (!f) {
+		printf("cannot open %s\n", path);
+		goto err_2;
+	}
+	header.capsule_guid = efi_guid_fm_capsule;
+	header.header_size = sizeof(header);
+	header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */
+	header.capsule_image_size = sizeof(header)
+					+ sizeof(capsule) + sizeof(u64)
+					+ sizeof(image)
+					+ bin_stat.st_size;
+
+	size = fwrite(&header, 1, sizeof(header), f);
+	if (size < sizeof(header)) {
+		printf("write failed (%lx)\n", size);
+		goto err_3;
+	}
+
+	capsule.version = 0x00000001;
+	capsule.embedded_driver_count = 0;
+	capsule.payload_item_count = 1;
+	capsule.item_offset_list[0] = sizeof(capsule) + sizeof(u64);
+	size = fwrite(&capsule, 1, sizeof(capsule) + sizeof(u64), f);
+	if (size < (sizeof(capsule) + sizeof(u64))) {
+		printf("write failed (%lx)\n", size);
+		goto err_3;
+	}
+
+	image.version = version;
+	memcpy(&image.update_image_type_id, guid, sizeof(*guid));
+	image.update_image_index = index;
+	image.update_image_size = bin_stat.st_size;
+	image.update_vendor_code_size = 0; /* none */
+	image.update_hardware_instance = instance;
+	image.image_capsule_support = 0;
+
+	size = fwrite(&image, 1, sizeof(image), f);
+	if (size < sizeof(image)) {
+		printf("write failed (%lx)\n", size);
+		goto err_3;
+	}
+	size = fread(data, 1, bin_stat.st_size, g);
+	if (size < bin_stat.st_size) {
+		printf("read failed (%lx)\n", size);
+		goto err_3;
+	}
+	size = fwrite(data, 1, bin_stat.st_size, f);
+	if (size < bin_stat.st_size) {
+		printf("write failed (%lx)\n", size);
+		goto err_3;
+	}
+
+	fclose(f);
+	fclose(g);
+	free(data);
+
+	return 0;
+
+err_3:
+	fclose(f);
+err_2:
+	free(data);
+err_1:
+	fclose(g);
+
+	return -1;
+}
+
+/*
+ * Usage:
+ *   $ mkeficapsule -f <firmware binary> <output file>
+ */
+int main(int argc, char **argv)
+{
+	char *file;
+	efi_guid_t *guid;
+	unsigned long index, instance, version;
+	int c, idx;
+
+	file = NULL;
+	guid = NULL;
+	index = 0;
+	instance = 0;
+	version = 0;
+	for (;;) {
+		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'f':
+			if (file) {
+				printf("Image already specified\n");
+				return -1;
+			}
+			file = optarg;
+			guid = &efi_guid_image_type_uboot_fit;
+			break;
+		case 'r':
+			if (file) {
+				printf("Image already specified\n");
+				return -1;
+			}
+			file = optarg;
+			guid = &efi_guid_image_type_uboot_raw;
+			break;
+		case 'i':
+			index = strtoul(optarg, NULL, 0);
+			break;
+		case 'I':
+			instance = strtoul(optarg, NULL, 0);
+			break;
+		case 'v':
+			version = strtoul(optarg, NULL, 0);
+			break;
+		case 'h':
+			print_usage();
+			return 0;
+		}
+	}
+
+	/* need a output file */
+	if (argc != optind + 1) {
+		print_usage();
+		return -1;
+	}
+
+	/* need a fit image file or raw image file */
+	if (!file) {
+		print_usage();
+		return -1;
+	}
+
+	if (create_fwbin(argv[optind], file, guid, version, index, instance)
+			< 0) {
+		printf("Creating firmware capsule failed\n");
+		return -1;
+	}
+
+	return 0;
+}
-- 
2.28.0

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

* [PATCH v8 16/18] test/py: efi_capsule: test for FIT image capsule
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (14 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 15/18] tools: add mkeficapsule command for UEFI capsule update AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 17/18] test/py: efi_capsule: test for raw " AKASHI Takahiro
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

The test can run on sandbox build and it attempts to execute a firmware
update via a capsule-on-disk, using a FIT image capsule,
CONFIG_EFI_CAPSULE_FIT.

To run this test successfully, you need configure U-Boot specifically;
See test_capsule_firmware.py for requirements, and hence it won't run
on Travis CI, at least, for now.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
 test/py/tests/test_efi_capsule/conftest.py    |  71 +++++++
 .../test_efi_capsule/test_capsule_firmware.py | 178 ++++++++++++++++++
 .../tests/test_efi_capsule/uboot_bin_env.its  |  36 ++++
 tools/mkeficapsule.c                          |   3 +-
 5 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 test/py/tests/test_efi_capsule/capsule_defs.py
 create mode 100644 test/py/tests/test_efi_capsule/conftest.py
 create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py
 create mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its

diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py
new file mode 100644
index 000000000000..4fd6353c2040
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/capsule_defs.py
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier:      GPL-2.0+
+
+# Directories
+CAPSULE_DATA_DIR = '/EFI/CapsuleTestData'
+CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule'
diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
new file mode 100644
index 000000000000..147266189912
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier:      GPL-2.0+
+# Copyright (c) 2020, Linaro Limited
+# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+
+import os
+import os.path
+import re
+from subprocess import call, check_call, check_output, CalledProcessError
+import pytest
+from capsule_defs import *
+
+#
+# Fixture for UEFI secure boot test
+#
+
+
+ at pytest.fixture(scope='session')
+def efi_capsule_data(request, u_boot_config):
+    """Set up a file system to be used in UEFI capsule test.
+
+    Args:
+        request: Pytest request object.
+        u_boot_config: U-boot configuration.
+
+    Return:
+        A path to disk image to be used for testing
+    """
+    global CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR
+
+    mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule'
+    data_dir = mnt_point + CAPSULE_DATA_DIR
+    install_dir = mnt_point + CAPSULE_INSTALL_DIR
+    image_path = u_boot_config.persistent_data_dir + '/test_efi_capsule.img'
+
+    try:
+        # Create a target device
+        check_call('dd if=/dev/zero of=./spi.bin bs=1MiB count=16', shell=True)
+
+        check_call('rm -rf %s' % mnt_point, shell=True)
+        check_call('mkdir -p %s' % data_dir, shell=True)
+        check_call('mkdir -p %s' % install_dir, shell=True)
+
+        # Create capsule files
+        # two regions: one for u-boot.bin and the other for u-boot.env
+        check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old -> u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
+                   shell=True)
+        check_call('sed -e \"s?BINFILE1?u-boot.bin.new?\" -e \"s?BINFILE2?u-boot.env.new?\" %s/test/py/tests/test_efi_capsule/uboot_bin_env.its > %s/uboot_bin_env.its' %
+                   (u_boot_config.source_dir, data_dir),
+                   shell=True)
+        check_call('cd %s; %s/tools/mkimage -f uboot_bin_env.its uboot_bin_env.itb' %
+                   (data_dir, u_boot_config.build_dir),
+                   shell=True)
+        check_call('cd %s; %s/tools/mkeficapsule --fit uboot_bin_env.itb --version 1 --index 1 Test01' %
+                   (data_dir, u_boot_config.build_dir),
+                   shell=True)
+
+        # Create a disk image with EFI system partition
+        check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
+                   (mnt_point, image_path), shell=True)
+        check_call('sgdisk %s -A 1:set:0 -t 1:C12A7328-F81F-11D2-BA4B-00A0C93EC93B' %
+                   image_path, shell=True)
+
+    except CalledProcessError as exception:
+        pytest.skip('Setup failed: %s' % exception.cmd)
+        return
+    else:
+        yield image_path
+    finally:
+        call('rm -rf %s' % mnt_point, shell=True)
+        call('rm -f %s' % image_path, shell=True)
+        call('rm -f ./spi.bin', shell=True)
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
new file mode 100644
index 000000000000..d8e27707fd79
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier:      GPL-2.0+
+# Copyright (c) 2020, Linaro Limited
+# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+#
+# U-Boot UEFI: Firmware Update Test
+
+"""
+This test verifies capsule-on-disk firmware update
+"""
+
+from subprocess import check_call, check_output, CalledProcessError
+import pytest
+from capsule_defs import *
+
+
+ at pytest.mark.boardspec('sandbox')
+ at pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
+ at pytest.mark.buildconfigspec('efi_capsule_on_disk')
+ at pytest.mark.buildconfigspec('dfu')
+ at pytest.mark.buildconfigspec('dfu_sf')
+ at pytest.mark.buildconfigspec('cmd_efidebug')
+ at pytest.mark.buildconfigspec('cmd_fat')
+ at pytest.mark.buildconfigspec('cmd_memory')
+ at pytest.mark.buildconfigspec('cmd_nvedit_efi')
+ at pytest.mark.buildconfigspec('cmd_sf')
+ at pytest.mark.slow
+class TestEfiCapsuleFirmwareFit(object):
+    def test_efi_capsule_fw1(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 1 - Update U-Boot and U-Boot environment on SPI Flash
+                      but with OsIndications unset
+                      No update should happen
+                      0x100000-0x150000: U-Boot binary (but dummy)
+                      0x150000-0x200000: U-Boot environment (but dummy)
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 1-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot order 1',
+                'env set -e OsIndications',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize contents
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 150000 10',
+                'sf read 5000000 150000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test01' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 1-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test01' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e -all Capsule0000')
+
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test01' in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:Old' in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf read 4000000 150000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot-env:Old' in ''.join(output)
+
+    def test_efi_capsule_fw2(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 2 - Update U-Boot and U-Boot environment on SPI Flash
+                      0x100000-0x150000: U-Boot binary (but dummy)
+                      0x150000-0x200000: U-Boot environment (but dummy)
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 2-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot order 1',
+                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize contents
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 150000 10',
+                'sf read 5000000 150000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test01' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 2-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test01' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e -all Capsule0000')
+
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test01' not in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:New' in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf read 4000000 150000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot-env:New' in ''.join(output)
diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its
new file mode 100644
index 000000000000..31e2f8049f9a
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/uboot_bin_env.its
@@ -0,0 +1,36 @@
+/*
+ * Automatic software update for U-Boot
+ * Make sure the flashing addresses ('load' prop) is correct for your board!
+ */
+
+/dts-v1/;
+
+/ {
+	description = "Automatic U-Boot environment update";
+	#address-cells = <2>;
+
+	images {
+		u-boot-bin at 100000 {
+			description = "U-Boot binary on SPI Flash";
+			data = /incbin/("BINFILE1");
+			compression = "none";
+			type = "firmware";
+			arch = "sandbox";
+			load = <0>;
+			hash-1 {
+				algo = "sha1";
+			};
+		};
+		u-boot-env at 150000 {
+			description = "U-Boot environment on SPI Flash";
+			data = /incbin/("BINFILE2");
+			compression = "none";
+			type = "firmware";
+			arch = "sandbox";
+			load = <0>;
+			hash-1 {
+				algo = "sha1";
+			};
+		};
+	};
+};
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index db95426457cc..45e27d74a5e9 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -101,7 +101,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 	}
 	header.capsule_guid = efi_guid_fm_capsule;
 	header.header_size = sizeof(header);
-	header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */
+	/* TODO: The current implementation ignores flags */
+	header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
 	header.capsule_image_size = sizeof(header)
 					+ sizeof(capsule) + sizeof(u64)
 					+ sizeof(image)
-- 
2.28.0

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

* [PATCH v8 17/18] test/py: efi_capsule: test for raw image capsule
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (15 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 16/18] test/py: efi_capsule: test for FIT image capsule AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  4:15 ` [PATCH v8 18/18] sandbox: enable capsule update for testing AKASHI Takahiro
  2020-11-13  7:18 ` [PATCH v8 00/18] efi_loader: add capsule update support Heinrich Schuchardt
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

The test can run on sandbox build and it attempts to execute a firmware
update via a capsule-on-disk, using a raw image capsule,
CONFIG_EFI_CAPSULE_RAW.

To run this test successfully, you need configure U-Boot specifically;
See test_capsule_firmware.py for requirements, and hence it won't run
on Travis CI, at least, for now.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_capsule/conftest.py    |  3 +
 .../test_efi_capsule/test_capsule_firmware.py | 63 +++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
index 147266189912..e037bd20560d 100644
--- a/test/py/tests/test_efi_capsule/conftest.py
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -53,6 +53,9 @@ def efi_capsule_data(request, u_boot_config):
         check_call('cd %s; %s/tools/mkeficapsule --fit uboot_bin_env.itb --version 1 --index 1 Test01' %
                    (data_dir, u_boot_config.build_dir),
                    shell=True)
+        check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --version 1 --index 1 Test02' %
+                   (data_dir, u_boot_config.build_dir),
+                   shell=True)
 
         # Create a disk image with EFI system partition
         check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
index d8e27707fd79..f006fa95d650 100644
--- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
@@ -15,6 +15,7 @@ from capsule_defs import *
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
+ at pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
 @pytest.mark.buildconfigspec('efi_capsule_on_disk')
 @pytest.mark.buildconfigspec('dfu')
 @pytest.mark.buildconfigspec('dfu_sf')
@@ -176,3 +177,65 @@ class TestEfiCapsuleFirmwareFit(object):
                 'sf read 4000000 150000 10',
                 'md.b 4000000 10'])
             assert 'u-boot-env:New' in ''.join(output)
+
+    def test_efi_capsule_fw3(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 3 - Update U-Boot on SPI Flash, raw image format
+                      0x100000-0x150000: U-Boot binary (but dummy)
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 3-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+                'efidebug boot order 1',
+                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize content
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test02' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 3-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test02' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e -all Capsule0000')
+
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test02' not in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:New' in ''.join(output)
-- 
2.28.0

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

* [PATCH v8 18/18] sandbox: enable capsule update for testing
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (16 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 17/18] test/py: efi_capsule: test for raw " AKASHI Takahiro
@ 2020-11-13  4:15 ` AKASHI Takahiro
  2020-11-13  7:18 ` [PATCH v8 00/18] efi_loader: add capsule update support Heinrich Schuchardt
  18 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-13  4:15 UTC (permalink / raw)
  To: u-boot

Add more configuration options to allow for efi capsule update
on sandbox.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 configs/sandbox64_defconfig | 6 ++++++
 configs/sandbox_defconfig   | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index e9928d5fc2e7..332fbb11e4e3 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -231,3 +231,9 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+#
+CONFIG_DFU_SF=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 3043208b4b72..1011545304d0 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -274,3 +274,9 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+#
+CONFIG_DFU_SF=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
-- 
2.28.0

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
                   ` (17 preceding siblings ...)
  2020-11-13  4:15 ` [PATCH v8 18/18] sandbox: enable capsule update for testing AKASHI Takahiro
@ 2020-11-13  7:18 ` Heinrich Schuchardt
  2020-11-16  0:37   ` AKASHI Takahiro
  18 siblings, 1 reply; 42+ messages in thread
From: Heinrich Schuchardt @ 2020-11-13  7:18 UTC (permalink / raw)
  To: u-boot

On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> Summary
> =======
> 'UpdateCapsule' is one of runtime services defined in UEFI specification
> and its aim is to allow a caller (OS) to pass information to the firmware,
> i.e. U-Boot. This is mostly used to update firmware binary on devices by
> instructions from OS.
>
> While 'UpdateCapsule' is a runtime services function, it is, at least
> initially, supported only before exiting boot services alike other runtime
> functions, [Get/]SetVariable. This is because modifying storage which may
> be shared with OS must be carefully designed and there is no general
> assumption that we can do it.
>
> Therefore, we practically support only "capsule on disk"; any capsule can
> be handed over to UEFI subsystem as a file on a specific file system.
>
> In this patch series, all the related definitions and structures are given
> as UEFI specification describes, and basic framework for capsule support
> is provided. Currently supported is
>  * firmware update (Firmware Management Protocol or simply FMP)
>
> Most of functionality of firmware update is provided by FMP driver and
> it can be, by nature, system/platform-specific. So you can and should
> implement your own FMP driver(s) based on your system requirements.
> Under the current implementation, we provide two basic but generic
> drivers with two formats:
>   * FIT image format (as used in TFTP update and dfu)
>   * raw image format
>
> It's totally up to users which one, or both, should be used on users'
> system depending on user requirements.
>
> Quick usage
> ===========
> 1. You can create a capsule file with the following host command:
>
>   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
>
> 2. Put the file under:
>
>   /EFI/UpdateCapsule of UEFI system partition
>
> 3. Specify firmware storage to be updated in "dfu_alt_info" variable
>    (Please follow README.dfu for details.)
>
>   ==> env set dfu_alt_info '...'
>
> 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
>
>   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
>
> Patch structure
> ===============
> Patch#1-#4,#12: preparatory patches
> Patch#5-#11,#13: main part of implementation
> Patch#14-#15: utilities
> Patch#16-#17: pytests
> Patch#18: for sandbox test
>
> [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
>
> Prerequisite patches
> ====================
> None
>
> Test
> ====
> * passed all the pytests which are included in this patch series
>   on sandbox build locally.
> * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
>   "virt-make-fs" cannot be executed.

Dear Takahiro,

please, rebase your series on origin/master. A prior version of the
first patches is already applied.

Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
the remaining patches.

Best regards

Heinrich

>
> Issues
> ======
> * Timing of executing capsules-on-disk
>   Currently, processing a capsule is triggered only as part of
>   UEFI subsystem initialization. This means that, for example,
>   firmware update, may not take place at system booting time and
>   will potentially be delayed until a first call of any UEFI functions.
>     => See patch#5 for my proposal
> * A bunch of warnings like
>     WARNING: Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef'
>     where possible
>   I don't think that fixing those improves anything.
> * Add a document in uefi.rst
>
> TODO's
> ======
> (Won't be addressed in this series.)
> * capsule authentication
> * capsule dependency (dependency expression instruction set, or depex)
> * loading drivers in a capsule
> * handling RESET flag in a capsule and QeuryCapsuleCaps
> * full semantics of ESRT (EFI System Resource Table)
> * enabling capsule API at runtime
> * json capsule
> * recovery from update failure
>
> Changes
> =======
> v8 (November 13, 2020)
> * fix a "not used" warning against update_load() in some configuration
>   (Patch#3)
> * fix failures (marked as 'F') in *secure boot* test in Travis CI by
>   making "EFI_CAPSULE_ON_DISK_EARLY" 'default n' (Patch#8)
> * fix failures (marked as 'E') at pytest setup in Travis CI by changing
>   a python file's name along with removing unused definitions (Patch#16)
> * add Patch#18 to enable tests to be run with default sandbox config
>   (Patch#18)
>
> v7 (October 29, 2020)
> * rename CONFIG_DFU_ALT to CONFIG_DFU_WRITE_ALT (Patch#1,#3,#13)
>
> v6 RESEND (October 29, 2020)
> * rebased on v2021.01-rc1
>
> v6 (September 7, 2020)
> * temporarily drop the prerequisite patch[2]
> * add a missing field (dependencies) in efi_api.h (but never used) (Patch#10)
> * add a missing field (image_capsule_support) and related definitions
>   in efi_api.h (Patch#10, #15)
> * cosmetic changes on constant definitions in efi_api.h (Patch#10)
> * strict check for INVALID_PARAMETER at GET_IMAGE_INFO api (Patch#11,#13)
> * fix warnings in pytest (Patch#16,#17)
>
> v5 (August 3, 2020)
> * removed superfluous type conversion at dfu_write_from_mem_addr()
>   (Patch#2)
> * introduced a common helper function, efi_create_indexed_name()
>   (Patch#6,#7,#8)
> * use efi_[get|set]_variable_int(), if necessary, with READ_ONLY
>   (Patch#7,#8)
> * return EFI_UNSUPPORTED at Patch#7
> * changed the word, number, to 'index' (Patch#7,#8)
> * removed 'ifdef CONFIG_EFI_CAPSULE_ON_DISK' from a header (Patch#8)
> * initialize 'CapsuleLast' in efi_init_obj_list() (Patch#7,#8)
> * added 'const' qualifier for filename argument at
>   efi_capsule_[read|delete]_file() (Patch#8)
>
> v4 (July 22, 2020)
> * rebased to Heinrich's current efi-2020-10
> * rework dfu-related code to align with Heinrich's change (Patch#1,#3)
> * change a type of 'addr' argument from int to 'void *' per Sughosh's
>   comment (Patch#2-#3,#11-#12)
> * rework/simplify pytests (Patch#15-#16)
>   - utilize virt-make-fs
>   - drop Test Case 1 (updating U-Boot environment data)
>   - remove useless definitions (MNT_PNT, EFI_CAPSULE_IMAGE_NAME)
>   - apply autopep8
>
> v3 (July 10, 2020)
> * rebased to Heinrich's current efi-2020-10-rc1
> * refactor efi_firmware_[fit|raw]_get_image_info() (patch#11,#13)
>
> v2 (June 17, 2020)
> * rebased to v2020.07-rc4
> * add preparatory patches for dfu (Patch#1-#5, #12)
> * rework FIT capsule driver to utilize dfu_alt_info instead of CONFIG_xxx
>   (patch#11)
> * extend get_image_info() to correspond to dfu_alt_info
>   (patch#11)
> * add a 'raw binary' capsule support
>   (patch#13, #17)
> * allow multiple capsule formats (with different GUIDs) to be installed
>   (patch#11, #13)
> * extend mkeficapsule command to accept additional parameters, like
>     version/index/hardware instance for a capsule header info.
>   (patch#15)
> * mkeficapsule can now also generate raw-binary capsule
>   (patch#16)
> * add function descriptions
> * apply autopep8 to pytests and fix more against pylint
>
> v1 (April 27, 2020)
> * rebased to v2020.07-rc
> * removed already-merged patches (RFC's #1 to #4)
> * dropped 'variable update' capsule support (RFC's patch#10)
> * dropped 'variable configuration table' support (RFC's patch#11)
>   (Those two should be discussed separately.)
> * add preparatory patches (patch#1/#2)
> * fix several build errors
> * rename some Kconfig options to be aligned with UEFI specification's terms
>   (patch#3,4,6,7)
> * enforce UpdateCapsule API to be disabled after ExitBootServices (patch#3)
> * use config table, runtime_services_supported, instead of variable (patch#3)
> * make EFI_CAPSULE_ON_DISK buildable even if UpdateCapsule API is disabled
>   (patch4)
> * support OsIndications, invoking capsule-on-disk only if the variable
>   indicates so (patch#4)
> * introduced EFI_CAPSULE_ON_DISK_EARLY to invoke capsule-on-disk in U-Boot
>   initialization (patch#4)
> * detect capsule files only if they are on EFI system partition (patch#4)
> * use printf, rather than EFI_PRINT, in error cases (patch#4)
> * use 'header_size' field to retrieve capsule data, adding sanity checks
>   against capsule size (patch#6)
> * call fmpt driver interfaces with EFI_CALL (patch#6)
> * remove 'variable update capsule'-related code form mkeficapsule (patch#9)
> * add a test case of OsIndications not being set properly (patch#10)
> * adjust test scenario for EFI_CAPSULE_ON_DISK_EARLY (patch#10)
> * revise pytest scripts (patch#10)
>
> Initial release as RFC (March 17, 2020)
>
> AKASHI Takahiro (18):
>   dfu: rename dfu_tftp_write() to dfu_write_by_name()
>   dfu: modify an argument type for an address
>   common: update: add a generic interface for FIT image
>   dfu: export dfu_list
>   efi_loader: add option to initialise EFI subsystem early
>   efi_loader: add efi_create_indexed_name()
>   efi_loader: define UpdateCapsule api
>   efi_loader: capsule: add capsule_on_disk support
>   efi_loader: capsule: add memory range capsule definitions
>   efi_loader: capsule: support firmware update
>   efi_loader: add firmware management protocol for FIT image
>   dfu: add dfu_write_by_alt()
>   efi_loader: add firmware management protocol for raw image
>   cmd: add "efidebug capsule" command
>   tools: add mkeficapsule command for UEFI capsule update
>   test/py: efi_capsule: test for FIT image capsule
>   test/py: efi_capsule: test for raw image capsule
>   sandbox: enable capsule update for testing
>
>  cmd/efidebug.c                                | 235 +++++
>  common/Kconfig                                |  15 +
>  common/Makefile                               |   3 +-
>  common/board_r.c                              |   6 +
>  common/main.c                                 |   4 +
>  common/update.c                               |  77 +-
>  configs/sandbox64_defconfig                   |   6 +
>  configs/sandbox_defconfig                     |   6 +
>  drivers/dfu/Kconfig                           |   5 +
>  drivers/dfu/Makefile                          |   2 +-
>  drivers/dfu/dfu.c                             |   2 +-
>  drivers/dfu/dfu_alt.c                         | 125 +++
>  drivers/dfu/dfu_tftp.c                        |  65 --
>  include/dfu.h                                 |  57 +-
>  include/efi_api.h                             | 166 ++++
>  include/efi_loader.h                          |  30 +
>  include/image.h                               |  12 +
>  lib/efi_loader/Kconfig                        |  72 ++
>  lib/efi_loader/Makefile                       |   2 +
>  lib/efi_loader/efi_capsule.c                  | 917 ++++++++++++++++++
>  lib/efi_loader/efi_firmware.c                 | 403 ++++++++
>  lib/efi_loader/efi_runtime.c                  | 104 +-
>  lib/efi_loader/efi_setup.c                    | 106 +-
>  .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
>  test/py/tests/test_efi_capsule/conftest.py    |  74 ++
>  .../test_efi_capsule/test_capsule_firmware.py | 241 +++++
>  .../tests/test_efi_capsule/uboot_bin_env.its  |  36 +
>  tools/Makefile                                |   2 +
>  tools/mkeficapsule.c                          | 239 +++++
>  29 files changed, 2877 insertions(+), 140 deletions(-)
>  create mode 100644 drivers/dfu/dfu_alt.c
>  delete mode 100644 drivers/dfu/dfu_tftp.c
>  create mode 100644 lib/efi_loader/efi_capsule.c
>  create mode 100644 lib/efi_loader/efi_firmware.c
>  create mode 100644 test/py/tests/test_efi_capsule/capsule_defs.py
>  create mode 100644 test/py/tests/test_efi_capsule/conftest.py
>  create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py
>  create mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
>  create mode 100644 tools/mkeficapsule.c
>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-13  7:18 ` [PATCH v8 00/18] efi_loader: add capsule update support Heinrich Schuchardt
@ 2020-11-16  0:37   ` AKASHI Takahiro
  2020-11-16 16:10     ` Tom Rini
  0 siblings, 1 reply; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-16  0:37 UTC (permalink / raw)
  To: u-boot

Heinrich,

On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > Summary
> > =======
> > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > and its aim is to allow a caller (OS) to pass information to the firmware,
> > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > instructions from OS.
> >
> > While 'UpdateCapsule' is a runtime services function, it is, at least
> > initially, supported only before exiting boot services alike other runtime
> > functions, [Get/]SetVariable. This is because modifying storage which may
> > be shared with OS must be carefully designed and there is no general
> > assumption that we can do it.
> >
> > Therefore, we practically support only "capsule on disk"; any capsule can
> > be handed over to UEFI subsystem as a file on a specific file system.
> >
> > In this patch series, all the related definitions and structures are given
> > as UEFI specification describes, and basic framework for capsule support
> > is provided. Currently supported is
> >  * firmware update (Firmware Management Protocol or simply FMP)
> >
> > Most of functionality of firmware update is provided by FMP driver and
> > it can be, by nature, system/platform-specific. So you can and should
> > implement your own FMP driver(s) based on your system requirements.
> > Under the current implementation, we provide two basic but generic
> > drivers with two formats:
> >   * FIT image format (as used in TFTP update and dfu)
> >   * raw image format
> >
> > It's totally up to users which one, or both, should be used on users'
> > system depending on user requirements.
> >
> > Quick usage
> > ===========
> > 1. You can create a capsule file with the following host command:
> >
> >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> >
> > 2. Put the file under:
> >
> >   /EFI/UpdateCapsule of UEFI system partition
> >
> > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> >    (Please follow README.dfu for details.)
> >
> >   ==> env set dfu_alt_info '...'
> >
> > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> >
> >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> >
> > Patch structure
> > ===============
> > Patch#1-#4,#12: preparatory patches
> > Patch#5-#11,#13: main part of implementation
> > Patch#14-#15: utilities
> > Patch#16-#17: pytests
> > Patch#18: for sandbox test
> >
> > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> >
> > Prerequisite patches
> > ====================
> > None
> >
> > Test
> > ====
> > * passed all the pytests which are included in this patch series
> >   on sandbox build locally.
> > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> >   "virt-make-fs" cannot be executed.
> 
> Dear Takahiro,
> 
> please, rebase your series on origin/master. A prior version of the
> first patches is already applied.

You can simply pick up and apply non-merged patches without problems
except a function prototype change of efi_create_indexed_name() you made,
which is not trivial to me.

But anyway, I will post a clean patch set soon.

> Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> the remaining patches.

Where can we find the results?
I don't think there is no official information on those CI's.

# I normally watch out Travis with "github" only.

In addition, can you clarify your view about "virt-make-fs"/sudo issue?
You should have common understandings with Tom here.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> >
> > Issues
> > ======
> > * Timing of executing capsules-on-disk
> >   Currently, processing a capsule is triggered only as part of
> >   UEFI subsystem initialization. This means that, for example,
> >   firmware update, may not take place at system booting time and
> >   will potentially be delayed until a first call of any UEFI functions.
> >     => See patch#5 for my proposal
> > * A bunch of warnings like
> >     WARNING: Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef'
> >     where possible
> >   I don't think that fixing those improves anything.
> > * Add a document in uefi.rst
> >
> > TODO's
> > ======
> > (Won't be addressed in this series.)
> > * capsule authentication
> > * capsule dependency (dependency expression instruction set, or depex)
> > * loading drivers in a capsule
> > * handling RESET flag in a capsule and QeuryCapsuleCaps
> > * full semantics of ESRT (EFI System Resource Table)
> > * enabling capsule API at runtime
> > * json capsule
> > * recovery from update failure
> >
> > Changes
> > =======
> > v8 (November 13, 2020)
> > * fix a "not used" warning against update_load() in some configuration
> >   (Patch#3)
> > * fix failures (marked as 'F') in *secure boot* test in Travis CI by
> >   making "EFI_CAPSULE_ON_DISK_EARLY" 'default n' (Patch#8)
> > * fix failures (marked as 'E') at pytest setup in Travis CI by changing
> >   a python file's name along with removing unused definitions (Patch#16)
> > * add Patch#18 to enable tests to be run with default sandbox config
> >   (Patch#18)
> >
> > v7 (October 29, 2020)
> > * rename CONFIG_DFU_ALT to CONFIG_DFU_WRITE_ALT (Patch#1,#3,#13)
> >
> > v6 RESEND (October 29, 2020)
> > * rebased on v2021.01-rc1
> >
> > v6 (September 7, 2020)
> > * temporarily drop the prerequisite patch[2]
> > * add a missing field (dependencies) in efi_api.h (but never used) (Patch#10)
> > * add a missing field (image_capsule_support) and related definitions
> >   in efi_api.h (Patch#10, #15)
> > * cosmetic changes on constant definitions in efi_api.h (Patch#10)
> > * strict check for INVALID_PARAMETER at GET_IMAGE_INFO api (Patch#11,#13)
> > * fix warnings in pytest (Patch#16,#17)
> >
> > v5 (August 3, 2020)
> > * removed superfluous type conversion at dfu_write_from_mem_addr()
> >   (Patch#2)
> > * introduced a common helper function, efi_create_indexed_name()
> >   (Patch#6,#7,#8)
> > * use efi_[get|set]_variable_int(), if necessary, with READ_ONLY
> >   (Patch#7,#8)
> > * return EFI_UNSUPPORTED at Patch#7
> > * changed the word, number, to 'index' (Patch#7,#8)
> > * removed 'ifdef CONFIG_EFI_CAPSULE_ON_DISK' from a header (Patch#8)
> > * initialize 'CapsuleLast' in efi_init_obj_list() (Patch#7,#8)
> > * added 'const' qualifier for filename argument at
> >   efi_capsule_[read|delete]_file() (Patch#8)
> >
> > v4 (July 22, 2020)
> > * rebased to Heinrich's current efi-2020-10
> > * rework dfu-related code to align with Heinrich's change (Patch#1,#3)
> > * change a type of 'addr' argument from int to 'void *' per Sughosh's
> >   comment (Patch#2-#3,#11-#12)
> > * rework/simplify pytests (Patch#15-#16)
> >   - utilize virt-make-fs
> >   - drop Test Case 1 (updating U-Boot environment data)
> >   - remove useless definitions (MNT_PNT, EFI_CAPSULE_IMAGE_NAME)
> >   - apply autopep8
> >
> > v3 (July 10, 2020)
> > * rebased to Heinrich's current efi-2020-10-rc1
> > * refactor efi_firmware_[fit|raw]_get_image_info() (patch#11,#13)
> >
> > v2 (June 17, 2020)
> > * rebased to v2020.07-rc4
> > * add preparatory patches for dfu (Patch#1-#5, #12)
> > * rework FIT capsule driver to utilize dfu_alt_info instead of CONFIG_xxx
> >   (patch#11)
> > * extend get_image_info() to correspond to dfu_alt_info
> >   (patch#11)
> > * add a 'raw binary' capsule support
> >   (patch#13, #17)
> > * allow multiple capsule formats (with different GUIDs) to be installed
> >   (patch#11, #13)
> > * extend mkeficapsule command to accept additional parameters, like
> >     version/index/hardware instance for a capsule header info.
> >   (patch#15)
> > * mkeficapsule can now also generate raw-binary capsule
> >   (patch#16)
> > * add function descriptions
> > * apply autopep8 to pytests and fix more against pylint
> >
> > v1 (April 27, 2020)
> > * rebased to v2020.07-rc
> > * removed already-merged patches (RFC's #1 to #4)
> > * dropped 'variable update' capsule support (RFC's patch#10)
> > * dropped 'variable configuration table' support (RFC's patch#11)
> >   (Those two should be discussed separately.)
> > * add preparatory patches (patch#1/#2)
> > * fix several build errors
> > * rename some Kconfig options to be aligned with UEFI specification's terms
> >   (patch#3,4,6,7)
> > * enforce UpdateCapsule API to be disabled after ExitBootServices (patch#3)
> > * use config table, runtime_services_supported, instead of variable (patch#3)
> > * make EFI_CAPSULE_ON_DISK buildable even if UpdateCapsule API is disabled
> >   (patch4)
> > * support OsIndications, invoking capsule-on-disk only if the variable
> >   indicates so (patch#4)
> > * introduced EFI_CAPSULE_ON_DISK_EARLY to invoke capsule-on-disk in U-Boot
> >   initialization (patch#4)
> > * detect capsule files only if they are on EFI system partition (patch#4)
> > * use printf, rather than EFI_PRINT, in error cases (patch#4)
> > * use 'header_size' field to retrieve capsule data, adding sanity checks
> >   against capsule size (patch#6)
> > * call fmpt driver interfaces with EFI_CALL (patch#6)
> > * remove 'variable update capsule'-related code form mkeficapsule (patch#9)
> > * add a test case of OsIndications not being set properly (patch#10)
> > * adjust test scenario for EFI_CAPSULE_ON_DISK_EARLY (patch#10)
> > * revise pytest scripts (patch#10)
> >
> > Initial release as RFC (March 17, 2020)
> >
> > AKASHI Takahiro (18):
> >   dfu: rename dfu_tftp_write() to dfu_write_by_name()
> >   dfu: modify an argument type for an address
> >   common: update: add a generic interface for FIT image
> >   dfu: export dfu_list
> >   efi_loader: add option to initialise EFI subsystem early
> >   efi_loader: add efi_create_indexed_name()
> >   efi_loader: define UpdateCapsule api
> >   efi_loader: capsule: add capsule_on_disk support
> >   efi_loader: capsule: add memory range capsule definitions
> >   efi_loader: capsule: support firmware update
> >   efi_loader: add firmware management protocol for FIT image
> >   dfu: add dfu_write_by_alt()
> >   efi_loader: add firmware management protocol for raw image
> >   cmd: add "efidebug capsule" command
> >   tools: add mkeficapsule command for UEFI capsule update
> >   test/py: efi_capsule: test for FIT image capsule
> >   test/py: efi_capsule: test for raw image capsule
> >   sandbox: enable capsule update for testing
> >
> >  cmd/efidebug.c                                | 235 +++++
> >  common/Kconfig                                |  15 +
> >  common/Makefile                               |   3 +-
> >  common/board_r.c                              |   6 +
> >  common/main.c                                 |   4 +
> >  common/update.c                               |  77 +-
> >  configs/sandbox64_defconfig                   |   6 +
> >  configs/sandbox_defconfig                     |   6 +
> >  drivers/dfu/Kconfig                           |   5 +
> >  drivers/dfu/Makefile                          |   2 +-
> >  drivers/dfu/dfu.c                             |   2 +-
> >  drivers/dfu/dfu_alt.c                         | 125 +++
> >  drivers/dfu/dfu_tftp.c                        |  65 --
> >  include/dfu.h                                 |  57 +-
> >  include/efi_api.h                             | 166 ++++
> >  include/efi_loader.h                          |  30 +
> >  include/image.h                               |  12 +
> >  lib/efi_loader/Kconfig                        |  72 ++
> >  lib/efi_loader/Makefile                       |   2 +
> >  lib/efi_loader/efi_capsule.c                  | 917 ++++++++++++++++++
> >  lib/efi_loader/efi_firmware.c                 | 403 ++++++++
> >  lib/efi_loader/efi_runtime.c                  | 104 +-
> >  lib/efi_loader/efi_setup.c                    | 106 +-
> >  .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
> >  test/py/tests/test_efi_capsule/conftest.py    |  74 ++
> >  .../test_efi_capsule/test_capsule_firmware.py | 241 +++++
> >  .../tests/test_efi_capsule/uboot_bin_env.its  |  36 +
> >  tools/Makefile                                |   2 +
> >  tools/mkeficapsule.c                          | 239 +++++
> >  29 files changed, 2877 insertions(+), 140 deletions(-)
> >  create mode 100644 drivers/dfu/dfu_alt.c
> >  delete mode 100644 drivers/dfu/dfu_tftp.c
> >  create mode 100644 lib/efi_loader/efi_capsule.c
> >  create mode 100644 lib/efi_loader/efi_firmware.c
> >  create mode 100644 test/py/tests/test_efi_capsule/capsule_defs.py
> >  create mode 100644 test/py/tests/test_efi_capsule/conftest.py
> >  create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py
> >  create mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
> >  create mode 100644 tools/mkeficapsule.c
> >
> 

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-16  0:37   ` AKASHI Takahiro
@ 2020-11-16 16:10     ` Tom Rini
  2020-11-17  0:16       ` AKASHI Takahiro
  0 siblings, 1 reply; 42+ messages in thread
From: Tom Rini @ 2020-11-16 16:10 UTC (permalink / raw)
  To: u-boot

On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> Heinrich,
> 
> On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > Summary
> > > =======
> > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > instructions from OS.
> > >
> > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > initially, supported only before exiting boot services alike other runtime
> > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > be shared with OS must be carefully designed and there is no general
> > > assumption that we can do it.
> > >
> > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > be handed over to UEFI subsystem as a file on a specific file system.
> > >
> > > In this patch series, all the related definitions and structures are given
> > > as UEFI specification describes, and basic framework for capsule support
> > > is provided. Currently supported is
> > >  * firmware update (Firmware Management Protocol or simply FMP)
> > >
> > > Most of functionality of firmware update is provided by FMP driver and
> > > it can be, by nature, system/platform-specific. So you can and should
> > > implement your own FMP driver(s) based on your system requirements.
> > > Under the current implementation, we provide two basic but generic
> > > drivers with two formats:
> > >   * FIT image format (as used in TFTP update and dfu)
> > >   * raw image format
> > >
> > > It's totally up to users which one, or both, should be used on users'
> > > system depending on user requirements.
> > >
> > > Quick usage
> > > ===========
> > > 1. You can create a capsule file with the following host command:
> > >
> > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > >
> > > 2. Put the file under:
> > >
> > >   /EFI/UpdateCapsule of UEFI system partition
> > >
> > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > >    (Please follow README.dfu for details.)
> > >
> > >   ==> env set dfu_alt_info '...'
> > >
> > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > >
> > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > >
> > > Patch structure
> > > ===============
> > > Patch#1-#4,#12: preparatory patches
> > > Patch#5-#11,#13: main part of implementation
> > > Patch#14-#15: utilities
> > > Patch#16-#17: pytests
> > > Patch#18: for sandbox test
> > >
> > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > >
> > > Prerequisite patches
> > > ====================
> > > None
> > >
> > > Test
> > > ====
> > > * passed all the pytests which are included in this patch series
> > >   on sandbox build locally.
> > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > >   "virt-make-fs" cannot be executed.
> > 
> > Dear Takahiro,
> > 
> > please, rebase your series on origin/master. A prior version of the
> > first patches is already applied.
> 
> You can simply pick up and apply non-merged patches without problems
> except a function prototype change of efi_create_indexed_name() you made,
> which is not trivial to me.
> 
> But anyway, I will post a clean patch set soon.
> 
> > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > the remaining patches.
> 
> Where can we find the results?
> I don't think there is no official information on those CI's.

If you submit a pull request against https://github.com/u-boot/u-boot
Azure will run automatically and show the results.  We don't have
anything similar setup for GitLab, but since it uses the same Docker
images as Azure, so long as the syntax is right (and there are linters
if you're unsure of a change), it would be expected to work too.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20201116/6329cdf6/attachment.sig>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-16 16:10     ` Tom Rini
@ 2020-11-17  0:16       ` AKASHI Takahiro
  2020-11-17  0:36         ` Tom Rini
  0 siblings, 1 reply; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-17  0:16 UTC (permalink / raw)
  To: u-boot

On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > Heinrich,
> > 
> > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > Summary
> > > > =======
> > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > instructions from OS.
> > > >
> > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > initially, supported only before exiting boot services alike other runtime
> > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > be shared with OS must be carefully designed and there is no general
> > > > assumption that we can do it.
> > > >
> > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > >
> > > > In this patch series, all the related definitions and structures are given
> > > > as UEFI specification describes, and basic framework for capsule support
> > > > is provided. Currently supported is
> > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > >
> > > > Most of functionality of firmware update is provided by FMP driver and
> > > > it can be, by nature, system/platform-specific. So you can and should
> > > > implement your own FMP driver(s) based on your system requirements.
> > > > Under the current implementation, we provide two basic but generic
> > > > drivers with two formats:
> > > >   * FIT image format (as used in TFTP update and dfu)
> > > >   * raw image format
> > > >
> > > > It's totally up to users which one, or both, should be used on users'
> > > > system depending on user requirements.
> > > >
> > > > Quick usage
> > > > ===========
> > > > 1. You can create a capsule file with the following host command:
> > > >
> > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > >
> > > > 2. Put the file under:
> > > >
> > > >   /EFI/UpdateCapsule of UEFI system partition
> > > >
> > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > >    (Please follow README.dfu for details.)
> > > >
> > > >   ==> env set dfu_alt_info '...'
> > > >
> > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > >
> > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > >
> > > > Patch structure
> > > > ===============
> > > > Patch#1-#4,#12: preparatory patches
> > > > Patch#5-#11,#13: main part of implementation
> > > > Patch#14-#15: utilities
> > > > Patch#16-#17: pytests
> > > > Patch#18: for sandbox test
> > > >
> > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > >
> > > > Prerequisite patches
> > > > ====================
> > > > None
> > > >
> > > > Test
> > > > ====
> > > > * passed all the pytests which are included in this patch series
> > > >   on sandbox build locally.
> > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > >   "virt-make-fs" cannot be executed.
> > > 
> > > Dear Takahiro,
> > > 
> > > please, rebase your series on origin/master. A prior version of the
> > > first patches is already applied.
> > 
> > You can simply pick up and apply non-merged patches without problems
> > except a function prototype change of efi_create_indexed_name() you made,
> > which is not trivial to me.
> > 
> > But anyway, I will post a clean patch set soon.
> > 
> > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > the remaining patches.
> > 
> > Where can we find the results?
> > I don't think there is no official information on those CI's.
> 
> If you submit a pull request against https://github.com/u-boot/u-boot
> Azure will run automatically and show the results.  We don't have

We can get a free account for Azure, but yet it requires us to give
our credit card information to Azure. I don't want to accept it.
So I believe requiring Azure test results is just inappropriate.

-Takahiro Akashi


> anything similar setup for GitLab, but since it uses the same Docker
> images as Azure, so long as the syntax is right (and there are linters
> if you're unsure of a change), it would be expected to work too.
> 
> -- 
> Tom

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-17  0:16       ` AKASHI Takahiro
@ 2020-11-17  0:36         ` Tom Rini
  2020-11-17  0:44           ` AKASHI Takahiro
  0 siblings, 1 reply; 42+ messages in thread
From: Tom Rini @ 2020-11-17  0:36 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > Heinrich,
> > > 
> > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > Summary
> > > > > =======
> > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > instructions from OS.
> > > > >
> > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > initially, supported only before exiting boot services alike other runtime
> > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > be shared with OS must be carefully designed and there is no general
> > > > > assumption that we can do it.
> > > > >
> > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > >
> > > > > In this patch series, all the related definitions and structures are given
> > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > is provided. Currently supported is
> > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > >
> > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > Under the current implementation, we provide two basic but generic
> > > > > drivers with two formats:
> > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > >   * raw image format
> > > > >
> > > > > It's totally up to users which one, or both, should be used on users'
> > > > > system depending on user requirements.
> > > > >
> > > > > Quick usage
> > > > > ===========
> > > > > 1. You can create a capsule file with the following host command:
> > > > >
> > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > >
> > > > > 2. Put the file under:
> > > > >
> > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > >
> > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > >    (Please follow README.dfu for details.)
> > > > >
> > > > >   ==> env set dfu_alt_info '...'
> > > > >
> > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > >
> > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > >
> > > > > Patch structure
> > > > > ===============
> > > > > Patch#1-#4,#12: preparatory patches
> > > > > Patch#5-#11,#13: main part of implementation
> > > > > Patch#14-#15: utilities
> > > > > Patch#16-#17: pytests
> > > > > Patch#18: for sandbox test
> > > > >
> > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > >
> > > > > Prerequisite patches
> > > > > ====================
> > > > > None
> > > > >
> > > > > Test
> > > > > ====
> > > > > * passed all the pytests which are included in this patch series
> > > > >   on sandbox build locally.
> > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > >   "virt-make-fs" cannot be executed.
> > > > 
> > > > Dear Takahiro,
> > > > 
> > > > please, rebase your series on origin/master. A prior version of the
> > > > first patches is already applied.
> > > 
> > > You can simply pick up and apply non-merged patches without problems
> > > except a function prototype change of efi_create_indexed_name() you made,
> > > which is not trivial to me.
> > > 
> > > But anyway, I will post a clean patch set soon.
> > > 
> > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > the remaining patches.
> > > 
> > > Where can we find the results?
> > > I don't think there is no official information on those CI's.
> > 
> > If you submit a pull request against https://github.com/u-boot/u-boot
> > Azure will run automatically and show the results.  We don't have
> 
> We can get a free account for Azure, but yet it requires us to give
> our credit card information to Azure. I don't want to accept it.
> So I believe requiring Azure test results is just inappropriate.

That's not correct, as far as I can tell.  You just need to submit a
pull request against the repository I mentioned above and that triggers
one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
the result of one such PR.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20201116/80dfd4d4/attachment.sig>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-17  0:36         ` Tom Rini
@ 2020-11-17  0:44           ` AKASHI Takahiro
  2020-11-17  1:49             ` [BUG] Hang shortly after loading FDT when booting on RK3399 Jean Lucas
  2020-11-17 23:50             ` [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
  0 siblings, 2 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-17  0:44 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > Heinrich,
> > > > 
> > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > Summary
> > > > > > =======
> > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > instructions from OS.
> > > > > >
> > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > assumption that we can do it.
> > > > > >
> > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > >
> > > > > > In this patch series, all the related definitions and structures are given
> > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > is provided. Currently supported is
> > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > >
> > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > Under the current implementation, we provide two basic but generic
> > > > > > drivers with two formats:
> > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > >   * raw image format
> > > > > >
> > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > system depending on user requirements.
> > > > > >
> > > > > > Quick usage
> > > > > > ===========
> > > > > > 1. You can create a capsule file with the following host command:
> > > > > >
> > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > >
> > > > > > 2. Put the file under:
> > > > > >
> > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > >
> > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > >    (Please follow README.dfu for details.)
> > > > > >
> > > > > >   ==> env set dfu_alt_info '...'
> > > > > >
> > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > >
> > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > >
> > > > > > Patch structure
> > > > > > ===============
> > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > Patch#14-#15: utilities
> > > > > > Patch#16-#17: pytests
> > > > > > Patch#18: for sandbox test
> > > > > >
> > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > >
> > > > > > Prerequisite patches
> > > > > > ====================
> > > > > > None
> > > > > >
> > > > > > Test
> > > > > > ====
> > > > > > * passed all the pytests which are included in this patch series
> > > > > >   on sandbox build locally.
> > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > >   "virt-make-fs" cannot be executed.
> > > > > 
> > > > > Dear Takahiro,
> > > > > 
> > > > > please, rebase your series on origin/master. A prior version of the
> > > > > first patches is already applied.
> > > > 
> > > > You can simply pick up and apply non-merged patches without problems
> > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > which is not trivial to me.
> > > > 
> > > > But anyway, I will post a clean patch set soon.
> > > > 
> > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > the remaining patches.
> > > > 
> > > > Where can we find the results?
> > > > I don't think there is no official information on those CI's.
> > > 
> > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > Azure will run automatically and show the results.  We don't have
> > 
> > We can get a free account for Azure, but yet it requires us to give
> > our credit card information to Azure. I don't want to accept it.
> > So I believe requiring Azure test results is just inappropriate.
> 
> That's not correct, as far as I can tell.  You just need to submit a
> pull request against the repository I mentioned above and that triggers
> one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> the result of one such PR.

Okay, I will check and try.
But I hope that you should have, on the home page?, more documents
on those CI loops and requirements of test results as part of
submission process.

Thanks,
-Takahiro Akashi

> -- 
> Tom

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17  0:44           ` AKASHI Takahiro
@ 2020-11-17  1:49             ` Jean Lucas
  2020-11-17 12:43               ` Alper Nebi Yasak
  2020-11-17 23:50             ` [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
  1 sibling, 1 reply; 42+ messages in thread
From: Jean Lucas @ 2020-11-17  1:49 UTC (permalink / raw)
  To: u-boot

Hello all,

On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot 
v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF 
v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang 
shortly after loading the appropriate FDT when booting.

On a Pinebook Pro:

=> load mmc 0:1 ${kernel_addr_r} Image
32418304 bytes read in 1448 ms (21.4 MiB/s)
=> load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
80831 bytes read in 27 ms (2.9 MiB/s)
=> load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
29698825 bytes read in 1291 ms (21.9 MiB/s)
=> setenv bootargs console=ttyS2,1500000 console=tty0 
root=/dev/ghost/root audit=0
=> booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
Moving Image from 0x2080000 to 0x2200000, end=41c0000
## Flattened Device Tree blob at 01f00000
 ?? Booting using the

Behavior is the same on RockPro64.

Worth mentioning is that U-Boot from about a week ago (I think 
rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC 
results in a working boot on Pinebook Pro, so bug seems to be when 
booting from SPI.

To further the hypothesis, on RockPro64, the latest U-Boot I can use 
from SPI (defconfig) is release 2020.04, since later releases also hang 
on loading the appropriate FDT when booting as described above.

Any ideas as to what could be causing the hangs?


Regards,

Jean

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17  1:49             ` [BUG] Hang shortly after loading FDT when booting on RK3399 Jean Lucas
@ 2020-11-17 12:43               ` Alper Nebi Yasak
  2020-11-17 14:11                 ` Peter Robinson
  0 siblings, 1 reply; 42+ messages in thread
From: Alper Nebi Yasak @ 2020-11-17 12:43 UTC (permalink / raw)
  To: u-boot

On 17/11/2020 04:49, Jean Lucas wrote:
> Hello all,
> 
> On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot 
> v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF 
> v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang 
> shortly after loading the appropriate FDT when booting.
> 
> On a Pinebook Pro:
> 
> => load mmc 0:1 ${kernel_addr_r} Image
> 32418304 bytes read in 1448 ms (21.4 MiB/s)
> => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
> 80831 bytes read in 27 ms (2.9 MiB/s)
> => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
> 29698825 bytes read in 1291 ms (21.9 MiB/s)
> => setenv bootargs console=ttyS2,1500000 console=tty0 
> root=/dev/ghost/root audit=0
> => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
> Moving Image from 0x2080000 to 0x2200000, end=41c0000
> ## Flattened Device Tree blob at 01f00000
>  ?? Booting using the
> 
> Behavior is the same on RockPro64.
> 
> Worth mentioning is that U-Boot from about a week ago (I think 
> rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC 
> results in a working boot on Pinebook Pro, so bug seems to be when 
> booting from SPI.
> 
> To further the hypothesis, on RockPro64, the latest U-Boot I can use 
> from SPI (defconfig) is release 2020.04, since later releases also hang 
> on loading the appropriate FDT when booting as described above.
> 
> Any ideas as to what could be causing the hangs?
> 

My gru-kevin was hanging at that same place when I tried to boot from
USB, try running "usb stop" to see if that hangs. If so, try disabling
CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the hang in
my case.

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17 12:43               ` Alper Nebi Yasak
@ 2020-11-17 14:11                 ` Peter Robinson
  2020-11-17 14:42                   ` Alper Nebi Yasak
  0 siblings, 1 reply; 42+ messages in thread
From: Peter Robinson @ 2020-11-17 14:11 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 17, 2020 at 12:43 PM Alper Nebi Yasak
<alpernebiyasak@gmail.com> wrote:
>
> On 17/11/2020 04:49, Jean Lucas wrote:
> > Hello all,
> >
> > On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot
> > v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF
> > v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang
> > shortly after loading the appropriate FDT when booting.
> >
> > On a Pinebook Pro:
> >
> > => load mmc 0:1 ${kernel_addr_r} Image
> > 32418304 bytes read in 1448 ms (21.4 MiB/s)
> > => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
> > 80831 bytes read in 27 ms (2.9 MiB/s)
> > => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
> > 29698825 bytes read in 1291 ms (21.9 MiB/s)
> > => setenv bootargs console=ttyS2,1500000 console=tty0
> > root=/dev/ghost/root audit=0
> > => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
> > Moving Image from 0x2080000 to 0x2200000, end=41c0000
> > ## Flattened Device Tree blob at 01f00000
> >     Booting using the
> >
> > Behavior is the same on RockPro64.
> >
> > Worth mentioning is that U-Boot from about a week ago (I think
> > rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC
> > results in a working boot on Pinebook Pro, so bug seems to be when
> > booting from SPI.
> >
> > To further the hypothesis, on RockPro64, the latest U-Boot I can use
> > from SPI (defconfig) is release 2020.04, since later releases also hang
> > on loading the appropriate FDT when booting as described above.
> >
> > Any ideas as to what could be causing the hangs?
> >
>
> My gru-kevin was hanging at that same place when I tried to boot from
> USB, try running "usb stop" to see if that hangs. If so, try disabling
> CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the hang in
> my case.

Which probably breaks USB keyboards?

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17 14:11                 ` Peter Robinson
@ 2020-11-17 14:42                   ` Alper Nebi Yasak
  2020-11-17 18:28                     ` Jean Lucas
  0 siblings, 1 reply; 42+ messages in thread
From: Alper Nebi Yasak @ 2020-11-17 14:42 UTC (permalink / raw)
  To: u-boot

On 17/11/2020 17:11, Peter Robinson wrote:
> On Tue, Nov 17, 2020 at 12:43 PM Alper Nebi Yasak
> <alpernebiyasak@gmail.com> wrote:
>>
>> On 17/11/2020 04:49, Jean Lucas wrote:
>>> Hello all,
>>>
>>> On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot
>>> v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF
>>> v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang
>>> shortly after loading the appropriate FDT when booting.
>>>
>>> On a Pinebook Pro:
>>>
>>> => load mmc 0:1 ${kernel_addr_r} Image
>>> 32418304 bytes read in 1448 ms (21.4 MiB/s)
>>> => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
>>> 80831 bytes read in 27 ms (2.9 MiB/s)
>>> => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
>>> 29698825 bytes read in 1291 ms (21.9 MiB/s)
>>> => setenv bootargs console=ttyS2,1500000 console=tty0
>>> root=/dev/ghost/root audit=0
>>> => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
>>> Moving Image from 0x2080000 to 0x2200000, end=41c0000
>>> ## Flattened Device Tree blob at 01f00000
>>>     Booting using the
>>>
>>> Behavior is the same on RockPro64.
>>>
>>> Worth mentioning is that U-Boot from about a week ago (I think
>>> rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC
>>> results in a working boot on Pinebook Pro, so bug seems to be when
>>> booting from SPI.
>>>
>>> To further the hypothesis, on RockPro64, the latest U-Boot I can use
>>> from SPI (defconfig) is release 2020.04, since later releases also hang
>>> on loading the appropriate FDT when booting as described above.
>>>
>>> Any ideas as to what could be causing the hangs?
>>>
>>
>> My gru-kevin was hanging at that same place when I tried to boot from
>> USB, try running "usb stop" to see if that hangs. If so, try disabling
>> CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the hang in
>> my case.
> 
> Which probably breaks USB keyboards?

I wouldn't know, gru-kevin uses cros-ec-keyb so I never needed to try a
USB keyboard. I meant those as steps to narrow things down.

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17 14:42                   ` Alper Nebi Yasak
@ 2020-11-17 18:28                     ` Jean Lucas
  2020-11-19  5:45                       ` Jean Lucas
  0 siblings, 1 reply; 42+ messages in thread
From: Jean Lucas @ 2020-11-17 18:28 UTC (permalink / raw)
  To: u-boot

On 11/17/20 9:42 AM, Alper Nebi Yasak wrote:
> On 17/11/2020 17:11, Peter Robinson wrote:
>> On Tue, Nov 17, 2020 at 12:43 PM Alper Nebi Yasak
>> <alpernebiyasak@gmail.com> wrote:
>>> On 17/11/2020 04:49, Jean Lucas wrote:
>>>> Hello all,
>>>>
>>>> On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot
>>>> v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF
>>>> v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang
>>>> shortly after loading the appropriate FDT when booting.
>>>>
>>>> On a Pinebook Pro:
>>>>
>>>> => load mmc 0:1 ${kernel_addr_r} Image
>>>> 32418304 bytes read in 1448 ms (21.4 MiB/s)
>>>> => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
>>>> 80831 bytes read in 27 ms (2.9 MiB/s)
>>>> => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
>>>> 29698825 bytes read in 1291 ms (21.9 MiB/s)
>>>> => setenv bootargs console=ttyS2,1500000 console=tty0
>>>> root=/dev/ghost/root audit=0
>>>> => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
>>>> Moving Image from 0x2080000 to 0x2200000, end=41c0000
>>>> ## Flattened Device Tree blob at 01f00000
>>>>      Booting using the
>>>>
>>>> Behavior is the same on RockPro64.
>>>>
>>>> Worth mentioning is that U-Boot from about a week ago (I think
>>>> rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC
>>>> results in a working boot on Pinebook Pro, so bug seems to be when
>>>> booting from SPI.
>>>>
>>>> To further the hypothesis, on RockPro64, the latest U-Boot I can use
>>>> from SPI (defconfig) is release 2020.04, since later releases also hang
>>>> on loading the appropriate FDT when booting as described above.
>>>>
>>>> Any ideas as to what could be causing the hangs?
>>>>
>>> My gru-kevin was hanging at that same place when I tried to boot from
>>> USB, try running "usb stop" to see if that hangs. If so, try disabling
>>> CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the hang in
>>> my case.
>> Which probably breaks USB keyboards?
> I wouldn't know, gru-kevin uses cros-ec-keyb so I never needed to try a
> USB keyboard. I meant those as steps to narrow things down.

So, running "usb stop" resulted in a hang.

I will test a build with the OHCI options Alper mentioned disabled, this 
evening.

As far as testing goes, disabling USB is fine since I can access the 
machines over serial.

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-17  0:44           ` AKASHI Takahiro
  2020-11-17  1:49             ` [BUG] Hang shortly after loading FDT when booting on RK3399 Jean Lucas
@ 2020-11-17 23:50             ` AKASHI Takahiro
  2020-11-17 23:59               ` Tom Rini
  1 sibling, 1 reply; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-17 23:50 UTC (permalink / raw)
  To: u-boot

Tom, Heinrich,

On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> Hi Tom,
> 
> On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > Heinrich,
> > > > > 
> > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > Summary
> > > > > > > =======
> > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > instructions from OS.
> > > > > > >
> > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > assumption that we can do it.
> > > > > > >
> > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > >
> > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > is provided. Currently supported is
> > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > >
> > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > drivers with two formats:
> > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > >   * raw image format
> > > > > > >
> > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > system depending on user requirements.
> > > > > > >
> > > > > > > Quick usage
> > > > > > > ===========
> > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > >
> > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > >
> > > > > > > 2. Put the file under:
> > > > > > >
> > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > >
> > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > >    (Please follow README.dfu for details.)
> > > > > > >
> > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > >
> > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > >
> > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > >
> > > > > > > Patch structure
> > > > > > > ===============
> > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > Patch#14-#15: utilities
> > > > > > > Patch#16-#17: pytests
> > > > > > > Patch#18: for sandbox test
> > > > > > >
> > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > >
> > > > > > > Prerequisite patches
> > > > > > > ====================
> > > > > > > None
> > > > > > >
> > > > > > > Test
> > > > > > > ====
> > > > > > > * passed all the pytests which are included in this patch series
> > > > > > >   on sandbox build locally.
> > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > 
> > > > > > Dear Takahiro,
> > > > > > 
> > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > first patches is already applied.
> > > > > 
> > > > > You can simply pick up and apply non-merged patches without problems
> > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > which is not trivial to me.
> > > > > 
> > > > > But anyway, I will post a clean patch set soon.
> > > > > 
> > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > the remaining patches.

@Heinrich,

https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
https://github.com/u-boot/u-boot/pull/39

Do those results satisfy your request?
I don't know how I can deal with gitlab and amazon CI.

> > > > > Where can we find the results?
> > > > > I don't think there is no official information on those CI's.
> > > > 
> > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > Azure will run automatically and show the results.  We don't have
> > > 
> > > We can get a free account for Azure, but yet it requires us to give
> > > our credit card information to Azure. I don't want to accept it.
> > > So I believe requiring Azure test results is just inappropriate.
> > 
> > That's not correct, as far as I can tell.  You just need to submit a
> > pull request against the repository I mentioned above and that triggers
> > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > the result of one such PR.
> 
> Okay, I will check and try.
> But I hope that you should have, on the home page?, more documents
> on those CI loops and requirements of test results as part of
> submission process.

@Tom,

Again, I'd like you to add a rule and a related document with regard to
criteria for "testing before submission". Otherwise, it's confusing.

@Heinrich,

As I requested several times, please clarify your view on virt-make-fs/sudo
issue and have consensus on it with Tom.

-Takahiro Akashi

> 
> Thanks,
> -Takahiro Akashi
> 
> > -- 
> > Tom
> 
> 

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-17 23:50             ` [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
@ 2020-11-17 23:59               ` Tom Rini
  2020-11-18  0:26                 ` AKASHI Takahiro
  0 siblings, 1 reply; 42+ messages in thread
From: Tom Rini @ 2020-11-17 23:59 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> Tom, Heinrich,
> 
> On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > Hi Tom,
> > 
> > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > Heinrich,
> > > > > > 
> > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > Summary
> > > > > > > > =======
> > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > instructions from OS.
> > > > > > > >
> > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > assumption that we can do it.
> > > > > > > >
> > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > >
> > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > is provided. Currently supported is
> > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > >
> > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > drivers with two formats:
> > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > >   * raw image format
> > > > > > > >
> > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > system depending on user requirements.
> > > > > > > >
> > > > > > > > Quick usage
> > > > > > > > ===========
> > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > >
> > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > >
> > > > > > > > 2. Put the file under:
> > > > > > > >
> > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > >
> > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > >
> > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > >
> > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > >
> > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > >
> > > > > > > > Patch structure
> > > > > > > > ===============
> > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > Patch#14-#15: utilities
> > > > > > > > Patch#16-#17: pytests
> > > > > > > > Patch#18: for sandbox test
> > > > > > > >
> > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > >
> > > > > > > > Prerequisite patches
> > > > > > > > ====================
> > > > > > > > None
> > > > > > > >
> > > > > > > > Test
> > > > > > > > ====
> > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > >   on sandbox build locally.
> > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > 
> > > > > > > Dear Takahiro,
> > > > > > > 
> > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > first patches is already applied.
> > > > > > 
> > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > which is not trivial to me.
> > > > > > 
> > > > > > But anyway, I will post a clean patch set soon.
> > > > > > 
> > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > the remaining patches.
> 
> @Heinrich,
> 
> https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> https://github.com/u-boot/u-boot/pull/39
> 
> Do those results satisfy your request?
> I don't know how I can deal with gitlab and amazon CI.

I believe that was a typo of "Azure", which you have above.  And since
https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
expect that so long as you linted your .gitlab-ci.yml changes, if any,
then it too should pass.

> > > > > > Where can we find the results?
> > > > > > I don't think there is no official information on those CI's.
> > > > > 
> > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > Azure will run automatically and show the results.  We don't have
> > > > 
> > > > We can get a free account for Azure, but yet it requires us to give
> > > > our credit card information to Azure. I don't want to accept it.
> > > > So I believe requiring Azure test results is just inappropriate.
> > > 
> > > That's not correct, as far as I can tell.  You just need to submit a
> > > pull request against the repository I mentioned above and that triggers
> > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > the result of one such PR.
> > 
> > Okay, I will check and try.
> > But I hope that you should have, on the home page?, more documents
> > on those CI loops and requirements of test results as part of
> > submission process.
> 
> @Tom,
> 
> Again, I'd like you to add a rule and a related document with regard to
> criteria for "testing before submission". Otherwise, it's confusing.

I'm sorry you found it confusing.  It has been stated many times in
these threads that since you're adding tests, they're expected to not
break CI, and should even run when possible.  Updating the rST with a CI
section would be good, yes.

> @Heinrich,
> 
> As I requested several times, please clarify your view on virt-make-fs/sudo
> issue and have consensus on it with Tom.

Yes, please.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20201117/2c92d76b/attachment.sig>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-17 23:59               ` Tom Rini
@ 2020-11-18  0:26                 ` AKASHI Takahiro
  2020-11-18  3:02                   ` Tom Rini
  0 siblings, 1 reply; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-18  0:26 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 17, 2020 at 06:59:52PM -0500, Tom Rini wrote:
> On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> > Tom, Heinrich,
> > 
> > On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > > Hi Tom,
> > > 
> > > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > > Heinrich,
> > > > > > > 
> > > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > > Summary
> > > > > > > > > =======
> > > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > > instructions from OS.
> > > > > > > > >
> > > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > > assumption that we can do it.
> > > > > > > > >
> > > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > > >
> > > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > > is provided. Currently supported is
> > > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > > >
> > > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > > drivers with two formats:
> > > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > > >   * raw image format
> > > > > > > > >
> > > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > > system depending on user requirements.
> > > > > > > > >
> > > > > > > > > Quick usage
> > > > > > > > > ===========
> > > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > > >
> > > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > > >
> > > > > > > > > 2. Put the file under:
> > > > > > > > >
> > > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > > >
> > > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > > >
> > > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > > >
> > > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > > >
> > > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > > >
> > > > > > > > > Patch structure
> > > > > > > > > ===============
> > > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > > Patch#14-#15: utilities
> > > > > > > > > Patch#16-#17: pytests
> > > > > > > > > Patch#18: for sandbox test
> > > > > > > > >
> > > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > > >
> > > > > > > > > Prerequisite patches
> > > > > > > > > ====================
> > > > > > > > > None
> > > > > > > > >
> > > > > > > > > Test
> > > > > > > > > ====
> > > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > > >   on sandbox build locally.
> > > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > > 
> > > > > > > > Dear Takahiro,
> > > > > > > > 
> > > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > > first patches is already applied.
> > > > > > > 
> > > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > > which is not trivial to me.
> > > > > > > 
> > > > > > > But anyway, I will post a clean patch set soon.
> > > > > > > 
> > > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > > the remaining patches.
> > 
> > @Heinrich,
> > 
> > https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> > https://github.com/u-boot/u-boot/pull/39
> > 
> > Do those results satisfy your request?
> > I don't know how I can deal with gitlab and amazon CI.
> 
> I believe that was a typo of "Azure", which you have above.  And since
> https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
> expect that so long as you linted your .gitlab-ci.yml changes, if any,
> then it too should pass.
> 
> > > > > > > Where can we find the results?
> > > > > > > I don't think there is no official information on those CI's.
> > > > > > 
> > > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > > Azure will run automatically and show the results.  We don't have
> > > > > 
> > > > > We can get a free account for Azure, but yet it requires us to give
> > > > > our credit card information to Azure. I don't want to accept it.
> > > > > So I believe requiring Azure test results is just inappropriate.
> > > > 
> > > > That's not correct, as far as I can tell.  You just need to submit a
> > > > pull request against the repository I mentioned above and that triggers
> > > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > > the result of one such PR.
> > > 
> > > Okay, I will check and try.
> > > But I hope that you should have, on the home page?, more documents
> > > on those CI loops and requirements of test results as part of
> > > submission process.
> > 
> > @Tom,
> > 
> > Again, I'd like you to add a rule and a related document with regard to
> > criteria for "testing before submission". Otherwise, it's confusing.
> 
> I'm sorry you found it confusing.  It has been stated many times in
> these threads that since you're adding tests, they're expected to not
> break CI, and should even run when possible.  Updating the rST with a CI
> section would be good, yes.

For clarity, my claim above is not only for me, but also for "all"
contributors.
When I looked at
https://github.com/u-boot/u-boot/pulls
I was a bit disappointed as there are so few people who have actually
tried to invoke Azure CI (prior to their submissions?).
Heinrich requires CI results, but many custodians not.
Why this inconsistency?

-Takahiro Akashi


> > @Heinrich,
> > 
> > As I requested several times, please clarify your view on virt-make-fs/sudo
> > issue and have consensus on it with Tom.
> 
> Yes, please.
> 
> -- 
> Tom

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-18  0:26                 ` AKASHI Takahiro
@ 2020-11-18  3:02                   ` Tom Rini
  2020-11-18  3:11                     ` AKASHI Takahiro
  0 siblings, 1 reply; 42+ messages in thread
From: Tom Rini @ 2020-11-18  3:02 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 18, 2020 at 09:26:38AM +0900, AKASHI Takahiro wrote:
> On Tue, Nov 17, 2020 at 06:59:52PM -0500, Tom Rini wrote:
> > On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> > > Tom, Heinrich,
> > > 
> > > On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > > > Hi Tom,
> > > > 
> > > > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > > > Heinrich,
> > > > > > > > 
> > > > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > > > Summary
> > > > > > > > > > =======
> > > > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > > > instructions from OS.
> > > > > > > > > >
> > > > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > > > assumption that we can do it.
> > > > > > > > > >
> > > > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > > > >
> > > > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > > > is provided. Currently supported is
> > > > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > > > >
> > > > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > > > drivers with two formats:
> > > > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > > > >   * raw image format
> > > > > > > > > >
> > > > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > > > system depending on user requirements.
> > > > > > > > > >
> > > > > > > > > > Quick usage
> > > > > > > > > > ===========
> > > > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > > > >
> > > > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > > > >
> > > > > > > > > > 2. Put the file under:
> > > > > > > > > >
> > > > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > > > >
> > > > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > > > >
> > > > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > > > >
> > > > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > > > >
> > > > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > > > >
> > > > > > > > > > Patch structure
> > > > > > > > > > ===============
> > > > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > > > Patch#14-#15: utilities
> > > > > > > > > > Patch#16-#17: pytests
> > > > > > > > > > Patch#18: for sandbox test
> > > > > > > > > >
> > > > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > > > >
> > > > > > > > > > Prerequisite patches
> > > > > > > > > > ====================
> > > > > > > > > > None
> > > > > > > > > >
> > > > > > > > > > Test
> > > > > > > > > > ====
> > > > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > > > >   on sandbox build locally.
> > > > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > > > 
> > > > > > > > > Dear Takahiro,
> > > > > > > > > 
> > > > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > > > first patches is already applied.
> > > > > > > > 
> > > > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > > > which is not trivial to me.
> > > > > > > > 
> > > > > > > > But anyway, I will post a clean patch set soon.
> > > > > > > > 
> > > > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > > > the remaining patches.
> > > 
> > > @Heinrich,
> > > 
> > > https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> > > https://github.com/u-boot/u-boot/pull/39
> > > 
> > > Do those results satisfy your request?
> > > I don't know how I can deal with gitlab and amazon CI.
> > 
> > I believe that was a typo of "Azure", which you have above.  And since
> > https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
> > expect that so long as you linted your .gitlab-ci.yml changes, if any,
> > then it too should pass.
> > 
> > > > > > > > Where can we find the results?
> > > > > > > > I don't think there is no official information on those CI's.
> > > > > > > 
> > > > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > > > Azure will run automatically and show the results.  We don't have
> > > > > > 
> > > > > > We can get a free account for Azure, but yet it requires us to give
> > > > > > our credit card information to Azure. I don't want to accept it.
> > > > > > So I believe requiring Azure test results is just inappropriate.
> > > > > 
> > > > > That's not correct, as far as I can tell.  You just need to submit a
> > > > > pull request against the repository I mentioned above and that triggers
> > > > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > > > the result of one such PR.
> > > > 
> > > > Okay, I will check and try.
> > > > But I hope that you should have, on the home page?, more documents
> > > > on those CI loops and requirements of test results as part of
> > > > submission process.
> > > 
> > > @Tom,
> > > 
> > > Again, I'd like you to add a rule and a related document with regard to
> > > criteria for "testing before submission". Otherwise, it's confusing.
> > 
> > I'm sorry you found it confusing.  It has been stated many times in
> > these threads that since you're adding tests, they're expected to not
> > break CI, and should even run when possible.  Updating the rST with a CI
> > section would be good, yes.
> 
> For clarity, my claim above is not only for me, but also for "all"
> contributors.
> When I looked at
> https://github.com/u-boot/u-boot/pulls
> I was a bit disappointed as there are so few people who have actually
> tried to invoke Azure CI (prior to their submissions?).
> Heinrich requires CI results, but many custodians not.
> Why this inconsistency?

Given that it takes Travis-CI several hours to complete a run, and Azure
around 2 hours, most of the time it's fine the CI runs to get put off
until the PR is being made.  In _this_ case you're adding tests, and
they had previously caused CI to fail, so you needed to get CI to work.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20201117/428e520d/attachment.sig>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-18  3:02                   ` Tom Rini
@ 2020-11-18  3:11                     ` AKASHI Takahiro
  2020-11-18 14:49                       ` Tom Rini
  0 siblings, 1 reply; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-18  3:11 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 17, 2020 at 10:02:41PM -0500, Tom Rini wrote:
> On Wed, Nov 18, 2020 at 09:26:38AM +0900, AKASHI Takahiro wrote:
> > On Tue, Nov 17, 2020 at 06:59:52PM -0500, Tom Rini wrote:
> > > On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> > > > Tom, Heinrich,
> > > > 
> > > > On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > > > > Hi Tom,
> > > > > 
> > > > > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > > > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > > > > Heinrich,
> > > > > > > > > 
> > > > > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > > > > Summary
> > > > > > > > > > > =======
> > > > > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > > > > instructions from OS.
> > > > > > > > > > >
> > > > > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > > > > assumption that we can do it.
> > > > > > > > > > >
> > > > > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > > > > >
> > > > > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > > > > is provided. Currently supported is
> > > > > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > > > > >
> > > > > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > > > > drivers with two formats:
> > > > > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > > > > >   * raw image format
> > > > > > > > > > >
> > > > > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > > > > system depending on user requirements.
> > > > > > > > > > >
> > > > > > > > > > > Quick usage
> > > > > > > > > > > ===========
> > > > > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > > > > >
> > > > > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > > > > >
> > > > > > > > > > > 2. Put the file under:
> > > > > > > > > > >
> > > > > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > > > > >
> > > > > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > > > > >
> > > > > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > > > > >
> > > > > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > > > > >
> > > > > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > > > > >
> > > > > > > > > > > Patch structure
> > > > > > > > > > > ===============
> > > > > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > > > > Patch#14-#15: utilities
> > > > > > > > > > > Patch#16-#17: pytests
> > > > > > > > > > > Patch#18: for sandbox test
> > > > > > > > > > >
> > > > > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > > > > >
> > > > > > > > > > > Prerequisite patches
> > > > > > > > > > > ====================
> > > > > > > > > > > None
> > > > > > > > > > >
> > > > > > > > > > > Test
> > > > > > > > > > > ====
> > > > > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > > > > >   on sandbox build locally.
> > > > > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > > > > 
> > > > > > > > > > Dear Takahiro,
> > > > > > > > > > 
> > > > > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > > > > first patches is already applied.
> > > > > > > > > 
> > > > > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > > > > which is not trivial to me.
> > > > > > > > > 
> > > > > > > > > But anyway, I will post a clean patch set soon.
> > > > > > > > > 
> > > > > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > > > > the remaining patches.
> > > > 
> > > > @Heinrich,
> > > > 
> > > > https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> > > > https://github.com/u-boot/u-boot/pull/39
> > > > 
> > > > Do those results satisfy your request?
> > > > I don't know how I can deal with gitlab and amazon CI.
> > > 
> > > I believe that was a typo of "Azure", which you have above.  And since
> > > https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
> > > expect that so long as you linted your .gitlab-ci.yml changes, if any,
> > > then it too should pass.
> > > 
> > > > > > > > > Where can we find the results?
> > > > > > > > > I don't think there is no official information on those CI's.
> > > > > > > > 
> > > > > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > > > > Azure will run automatically and show the results.  We don't have
> > > > > > > 
> > > > > > > We can get a free account for Azure, but yet it requires us to give
> > > > > > > our credit card information to Azure. I don't want to accept it.
> > > > > > > So I believe requiring Azure test results is just inappropriate.
> > > > > > 
> > > > > > That's not correct, as far as I can tell.  You just need to submit a
> > > > > > pull request against the repository I mentioned above and that triggers
> > > > > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > > > > the result of one such PR.
> > > > > 
> > > > > Okay, I will check and try.
> > > > > But I hope that you should have, on the home page?, more documents
> > > > > on those CI loops and requirements of test results as part of
> > > > > submission process.
> > > > 
> > > > @Tom,
> > > > 
> > > > Again, I'd like you to add a rule and a related document with regard to
> > > > criteria for "testing before submission". Otherwise, it's confusing.
> > > 
> > > I'm sorry you found it confusing.  It has been stated many times in
> > > these threads that since you're adding tests, they're expected to not
> > > break CI, and should even run when possible.  Updating the rST with a CI
> > > section would be good, yes.
> > 
> > For clarity, my claim above is not only for me, but also for "all"
> > contributors.
> > When I looked at
> > https://github.com/u-boot/u-boot/pulls
> > I was a bit disappointed as there are so few people who have actually
> > tried to invoke Azure CI (prior to their submissions?).
> > Heinrich requires CI results, but many custodians not.
> > Why this inconsistency?
> 
> Given that it takes Travis-CI several hours to complete a run, and Azure
> around 2 hours, most of the time it's fine the CI runs to get put off
> until the PR is being made.  In _this_ case you're adding tests, and
> they had previously caused CI to fail, so you needed to get CI to work.

Even if we don't know how we can kick off CI jobs and see the results?
That's why I request you to make information/documents publicly available.

> > Heinrich requires CI results, but many custodians not.
> > Why this inconsistency?

You didn't give me the answer for this.
Moreover, it's not very clear in which case you demand test cases being added.
Again, that's why I request you to add information/documents about
the criteria for "testing before submission".

-Takahiro Akashi

> -- 
> Tom

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-18  3:11                     ` AKASHI Takahiro
@ 2020-11-18 14:49                       ` Tom Rini
  2020-11-19  0:51                         ` AKASHI Takahiro
  0 siblings, 1 reply; 42+ messages in thread
From: Tom Rini @ 2020-11-18 14:49 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 18, 2020 at 12:11:29PM +0900, AKASHI Takahiro wrote:
> On Tue, Nov 17, 2020 at 10:02:41PM -0500, Tom Rini wrote:
> > On Wed, Nov 18, 2020 at 09:26:38AM +0900, AKASHI Takahiro wrote:
> > > On Tue, Nov 17, 2020 at 06:59:52PM -0500, Tom Rini wrote:
> > > > On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> > > > > Tom, Heinrich,
> > > > > 
> > > > > On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > > > > > Hi Tom,
> > > > > > 
> > > > > > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > > > > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > > > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > > > > > Heinrich,
> > > > > > > > > > 
> > > > > > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > > > > > Summary
> > > > > > > > > > > > =======
> > > > > > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > > > > > instructions from OS.
> > > > > > > > > > > >
> > > > > > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > > > > > assumption that we can do it.
> > > > > > > > > > > >
> > > > > > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > > > > > >
> > > > > > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > > > > > is provided. Currently supported is
> > > > > > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > > > > > >
> > > > > > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > > > > > drivers with two formats:
> > > > > > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > > > > > >   * raw image format
> > > > > > > > > > > >
> > > > > > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > > > > > system depending on user requirements.
> > > > > > > > > > > >
> > > > > > > > > > > > Quick usage
> > > > > > > > > > > > ===========
> > > > > > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > > > > > >
> > > > > > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > > > > > >
> > > > > > > > > > > > 2. Put the file under:
> > > > > > > > > > > >
> > > > > > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > > > > > >
> > > > > > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > > > > > >
> > > > > > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > > > > > >
> > > > > > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > > > > > >
> > > > > > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > > > > > >
> > > > > > > > > > > > Patch structure
> > > > > > > > > > > > ===============
> > > > > > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > > > > > Patch#14-#15: utilities
> > > > > > > > > > > > Patch#16-#17: pytests
> > > > > > > > > > > > Patch#18: for sandbox test
> > > > > > > > > > > >
> > > > > > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > > > > > >
> > > > > > > > > > > > Prerequisite patches
> > > > > > > > > > > > ====================
> > > > > > > > > > > > None
> > > > > > > > > > > >
> > > > > > > > > > > > Test
> > > > > > > > > > > > ====
> > > > > > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > > > > > >   on sandbox build locally.
> > > > > > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > > > > > 
> > > > > > > > > > > Dear Takahiro,
> > > > > > > > > > > 
> > > > > > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > > > > > first patches is already applied.
> > > > > > > > > > 
> > > > > > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > > > > > which is not trivial to me.
> > > > > > > > > > 
> > > > > > > > > > But anyway, I will post a clean patch set soon.
> > > > > > > > > > 
> > > > > > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > > > > > the remaining patches.
> > > > > 
> > > > > @Heinrich,
> > > > > 
> > > > > https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> > > > > https://github.com/u-boot/u-boot/pull/39
> > > > > 
> > > > > Do those results satisfy your request?
> > > > > I don't know how I can deal with gitlab and amazon CI.
> > > > 
> > > > I believe that was a typo of "Azure", which you have above.  And since
> > > > https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
> > > > expect that so long as you linted your .gitlab-ci.yml changes, if any,
> > > > then it too should pass.
> > > > 
> > > > > > > > > > Where can we find the results?
> > > > > > > > > > I don't think there is no official information on those CI's.
> > > > > > > > > 
> > > > > > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > > > > > Azure will run automatically and show the results.  We don't have
> > > > > > > > 
> > > > > > > > We can get a free account for Azure, but yet it requires us to give
> > > > > > > > our credit card information to Azure. I don't want to accept it.
> > > > > > > > So I believe requiring Azure test results is just inappropriate.
> > > > > > > 
> > > > > > > That's not correct, as far as I can tell.  You just need to submit a
> > > > > > > pull request against the repository I mentioned above and that triggers
> > > > > > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > > > > > the result of one such PR.
> > > > > > 
> > > > > > Okay, I will check and try.
> > > > > > But I hope that you should have, on the home page?, more documents
> > > > > > on those CI loops and requirements of test results as part of
> > > > > > submission process.
> > > > > 
> > > > > @Tom,
> > > > > 
> > > > > Again, I'd like you to add a rule and a related document with regard to
> > > > > criteria for "testing before submission". Otherwise, it's confusing.
> > > > 
> > > > I'm sorry you found it confusing.  It has been stated many times in
> > > > these threads that since you're adding tests, they're expected to not
> > > > break CI, and should even run when possible.  Updating the rST with a CI
> > > > section would be good, yes.
> > > 
> > > For clarity, my claim above is not only for me, but also for "all"
> > > contributors.
> > > When I looked at
> > > https://github.com/u-boot/u-boot/pulls
> > > I was a bit disappointed as there are so few people who have actually
> > > tried to invoke Azure CI (prior to their submissions?).
> > > Heinrich requires CI results, but many custodians not.
> > > Why this inconsistency?
> > 
> > Given that it takes Travis-CI several hours to complete a run, and Azure
> > around 2 hours, most of the time it's fine the CI runs to get put off
> > until the PR is being made.  In _this_ case you're adding tests, and
> > they had previously caused CI to fail, so you needed to get CI to work.
> 
> Even if we don't know how we can kick off CI jobs and see the results?
> That's why I request you to make information/documents publicly available.

Yes, it would be good to add a section to the rST about CI.  I've noted
how to trigger Azure in a few threads a few times, outside of this
thread.

> > > Heinrich requires CI results, but many custodians not.
> > > Why this inconsistency?
> 
> You didn't give me the answer for this.

Yes, I did.  You, right here, are adding tests.  That's why you need to
run CI.  Custodians who don't run CI before sending me a PR, and who
then have a problem CI catches, get the PR nak'd.  Most changes are
localized and don't break builds outside of the SoC being changed.

> Moreover, it's not very clear in which case you demand test cases being added.
> Again, that's why I request you to add information/documents about
> the criteria for "testing before submission".

Well, how important is it to YOU that the EFI capsule code doesn't get
broken?  Code that we can run tests on in CI should get tests run in CI.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20201118/10ddbbdb/attachment.sig>

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

* [PATCH v8 00/18] efi_loader: add capsule update support
  2020-11-18 14:49                       ` Tom Rini
@ 2020-11-19  0:51                         ` AKASHI Takahiro
  0 siblings, 0 replies; 42+ messages in thread
From: AKASHI Takahiro @ 2020-11-19  0:51 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 18, 2020 at 09:49:22AM -0500, Tom Rini wrote:
> On Wed, Nov 18, 2020 at 12:11:29PM +0900, AKASHI Takahiro wrote:
> > On Tue, Nov 17, 2020 at 10:02:41PM -0500, Tom Rini wrote:
> > > On Wed, Nov 18, 2020 at 09:26:38AM +0900, AKASHI Takahiro wrote:
> > > > On Tue, Nov 17, 2020 at 06:59:52PM -0500, Tom Rini wrote:
> > > > > On Wed, Nov 18, 2020 at 08:50:08AM +0900, AKASHI Takahiro wrote:
> > > > > > Tom, Heinrich,
> > > > > > 
> > > > > > On Tue, Nov 17, 2020 at 09:44:36AM +0900, AKASHI Takahiro wrote:
> > > > > > > Hi Tom,
> > > > > > > 
> > > > > > > On Mon, Nov 16, 2020 at 07:36:26PM -0500, Tom Rini wrote:
> > > > > > > > On Tue, Nov 17, 2020 at 09:16:26AM +0900, AKASHI Takahiro wrote:
> > > > > > > > > On Mon, Nov 16, 2020 at 11:10:12AM -0500, Tom Rini wrote:
> > > > > > > > > > On Mon, Nov 16, 2020 at 09:37:23AM +0900, AKASHI Takahiro wrote:
> > > > > > > > > > > Heinrich,
> > > > > > > > > > > 
> > > > > > > > > > > On Fri, Nov 13, 2020 at 08:18:58AM +0100, Heinrich Schuchardt wrote:
> > > > > > > > > > > > On 11/13/20 5:14 AM, AKASHI Takahiro wrote:
> > > > > > > > > > > > > Summary
> > > > > > > > > > > > > =======
> > > > > > > > > > > > > 'UpdateCapsule' is one of runtime services defined in UEFI specification
> > > > > > > > > > > > > and its aim is to allow a caller (OS) to pass information to the firmware,
> > > > > > > > > > > > > i.e. U-Boot. This is mostly used to update firmware binary on devices by
> > > > > > > > > > > > > instructions from OS.
> > > > > > > > > > > > >
> > > > > > > > > > > > > While 'UpdateCapsule' is a runtime services function, it is, at least
> > > > > > > > > > > > > initially, supported only before exiting boot services alike other runtime
> > > > > > > > > > > > > functions, [Get/]SetVariable. This is because modifying storage which may
> > > > > > > > > > > > > be shared with OS must be carefully designed and there is no general
> > > > > > > > > > > > > assumption that we can do it.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Therefore, we practically support only "capsule on disk"; any capsule can
> > > > > > > > > > > > > be handed over to UEFI subsystem as a file on a specific file system.
> > > > > > > > > > > > >
> > > > > > > > > > > > > In this patch series, all the related definitions and structures are given
> > > > > > > > > > > > > as UEFI specification describes, and basic framework for capsule support
> > > > > > > > > > > > > is provided. Currently supported is
> > > > > > > > > > > > >  * firmware update (Firmware Management Protocol or simply FMP)
> > > > > > > > > > > > >
> > > > > > > > > > > > > Most of functionality of firmware update is provided by FMP driver and
> > > > > > > > > > > > > it can be, by nature, system/platform-specific. So you can and should
> > > > > > > > > > > > > implement your own FMP driver(s) based on your system requirements.
> > > > > > > > > > > > > Under the current implementation, we provide two basic but generic
> > > > > > > > > > > > > drivers with two formats:
> > > > > > > > > > > > >   * FIT image format (as used in TFTP update and dfu)
> > > > > > > > > > > > >   * raw image format
> > > > > > > > > > > > >
> > > > > > > > > > > > > It's totally up to users which one, or both, should be used on users'
> > > > > > > > > > > > > system depending on user requirements.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Quick usage
> > > > > > > > > > > > > ===========
> > > > > > > > > > > > > 1. You can create a capsule file with the following host command:
> > > > > > > > > > > > >
> > > > > > > > > > > > >   $ mkeficapsule [--fit <fit image> | --raw <raw image>] <output file>
> > > > > > > > > > > > >
> > > > > > > > > > > > > 2. Put the file under:
> > > > > > > > > > > > >
> > > > > > > > > > > > >   /EFI/UpdateCapsule of UEFI system partition
> > > > > > > > > > > > >
> > > > > > > > > > > > > 3. Specify firmware storage to be updated in "dfu_alt_info" variable
> > > > > > > > > > > > >    (Please follow README.dfu for details.)
> > > > > > > > > > > > >
> > > > > > > > > > > > >   ==> env set dfu_alt_info '...'
> > > > > > > > > > > > >
> > > > > > > > > > > > > 4. After setting up UEFI's OsIndications variable, reboot U-Boot:
> > > > > > > > > > > > >
> > > > > > > > > > > > >   OsIndications <= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
> > > > > > > > > > > > >
> > > > > > > > > > > > > Patch structure
> > > > > > > > > > > > > ===============
> > > > > > > > > > > > > Patch#1-#4,#12: preparatory patches
> > > > > > > > > > > > > Patch#5-#11,#13: main part of implementation
> > > > > > > > > > > > > Patch#14-#15: utilities
> > > > > > > > > > > > > Patch#16-#17: pytests
> > > > > > > > > > > > > Patch#18: for sandbox test
> > > > > > > > > > > > >
> > > > > > > > > > > > > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> > > > > > > > > > > > >
> > > > > > > > > > > > > Prerequisite patches
> > > > > > > > > > > > > ====================
> > > > > > > > > > > > > None
> > > > > > > > > > > > >
> > > > > > > > > > > > > Test
> > > > > > > > > > > > > ====
> > > > > > > > > > > > > * passed all the pytests which are included in this patch series
> > > > > > > > > > > > >   on sandbox build locally.
> > > > > > > > > > > > > * skipped (or 'S', but it's not a failure, 'F') in Travis CI because
> > > > > > > > > > > > >   "virt-make-fs" cannot be executed.
> > > > > > > > > > > > 
> > > > > > > > > > > > Dear Takahiro,
> > > > > > > > > > > > 
> > > > > > > > > > > > please, rebase your series on origin/master. A prior version of the
> > > > > > > > > > > > first patches is already applied.
> > > > > > > > > > > 
> > > > > > > > > > > You can simply pick up and apply non-merged patches without problems
> > > > > > > > > > > except a function prototype change of efi_create_indexed_name() you made,
> > > > > > > > > > > which is not trivial to me.
> > > > > > > > > > > 
> > > > > > > > > > > But anyway, I will post a clean patch set soon.
> > > > > > > > > > > 
> > > > > > > > > > > > Testing on Gitlab CI, Travis CI, Amazon CI must be addressed for merging
> > > > > > > > > > > > the remaining patches.
> > > > > > 
> > > > > > @Heinrich,
> > > > > > 
> > > > > > https://travis-ci.org/github/t-akashi/u-boot-for-travis/builds/743837907
> > > > > > https://github.com/u-boot/u-boot/pull/39
> > > > > > 
> > > > > > Do those results satisfy your request?
> > > > > > I don't know how I can deal with gitlab and amazon CI.
> > > > > 
> > > > > I believe that was a typo of "Azure", which you have above.  And since
> > > > > https://github.com/u-boot/u-boot/pull/39/checks shows green, I would
> > > > > expect that so long as you linted your .gitlab-ci.yml changes, if any,
> > > > > then it too should pass.
> > > > > 
> > > > > > > > > > > Where can we find the results?
> > > > > > > > > > > I don't think there is no official information on those CI's.
> > > > > > > > > > 
> > > > > > > > > > If you submit a pull request against https://github.com/u-boot/u-boot
> > > > > > > > > > Azure will run automatically and show the results.  We don't have
> > > > > > > > > 
> > > > > > > > > We can get a free account for Azure, but yet it requires us to give
> > > > > > > > > our credit card information to Azure. I don't want to accept it.
> > > > > > > > > So I believe requiring Azure test results is just inappropriate.
> > > > > > > > 
> > > > > > > > That's not correct, as far as I can tell.  You just need to submit a
> > > > > > > > pull request against the repository I mentioned above and that triggers
> > > > > > > > one.  For example: https://github.com/u-boot/u-boot/pull/35/checks is
> > > > > > > > the result of one such PR.
> > > > > > > 
> > > > > > > Okay, I will check and try.
> > > > > > > But I hope that you should have, on the home page?, more documents
> > > > > > > on those CI loops and requirements of test results as part of
> > > > > > > submission process.
> > > > > > 
> > > > > > @Tom,
> > > > > > 
> > > > > > Again, I'd like you to add a rule and a related document with regard to
> > > > > > criteria for "testing before submission". Otherwise, it's confusing.
> > > > > 
> > > > > I'm sorry you found it confusing.  It has been stated many times in
> > > > > these threads that since you're adding tests, they're expected to not
> > > > > break CI, and should even run when possible.  Updating the rST with a CI
> > > > > section would be good, yes.
> > > > 
> > > > For clarity, my claim above is not only for me, but also for "all"
> > > > contributors.
> > > > When I looked at
> > > > https://github.com/u-boot/u-boot/pulls
> > > > I was a bit disappointed as there are so few people who have actually
> > > > tried to invoke Azure CI (prior to their submissions?).
> > > > Heinrich requires CI results, but many custodians not.
> > > > Why this inconsistency?
> > > 
> > > Given that it takes Travis-CI several hours to complete a run, and Azure
> > > around 2 hours, most of the time it's fine the CI runs to get put off
> > > until the PR is being made.  In _this_ case you're adding tests, and
> > > they had previously caused CI to fail, so you needed to get CI to work.
> > 
> > Even if we don't know how we can kick off CI jobs and see the results?
> > That's why I request you to make information/documents publicly available.
> 
> Yes, it would be good to add a section to the rST about CI.  I've noted
> how to trigger Azure in a few threads a few times, outside of this
> thread.

Again, my point is to put such information in public space to make
it easy to find them and understand clearly what you "demand".

> > > > Heinrich requires CI results, but many custodians not.
> > > > Why this inconsistency?
> > 
> > You didn't give me the answer for this.
> 
> Yes, I did.  You, right here, are adding tests.  That's why you need to
> run CI.  Custodians who don't run CI before sending me a PR, and who
> then have a problem CI catches, get the PR nak'd.  Most changes are
> localized and don't break builds outside of the SoC being changed.

I see lots of "new features" coming in even in these days.
But I only see a very few "pull requests" on your github repository.
That is why I'm asking you for criteria for "testing".

> > Moreover, it's not very clear in which case you demand test cases being added.
> > Again, that's why I request you to add information/documents about
> > the criteria for "testing before submission".
> 
> Well, how important is it to YOU that the EFI capsule code doesn't get
> broken?  Code that we can run tests on in CI should get tests run in CI.

I totally agreed, and did submit the test results in the previous
message. But remember Heinrich demanded that even Gitlab and Amazon CI pass.
How can we do that without knowing how to run them?
What is your expectation?

That is why ... (I don't want to repeat my point again here.)

-Takahiro Akashi


> -- 
> Tom

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-17 18:28                     ` Jean Lucas
@ 2020-11-19  5:45                       ` Jean Lucas
  2020-11-19  6:08                         ` Jean Lucas
  2021-01-28 22:28                         ` Jan Palus
  0 siblings, 2 replies; 42+ messages in thread
From: Jean Lucas @ 2020-11-19  5:45 UTC (permalink / raw)
  To: u-boot

On 11/17/20 1:28 PM, Jean Lucas wrote:
> On 11/17/20 9:42 AM, Alper Nebi Yasak wrote:
>> On 17/11/2020 17:11, Peter Robinson wrote:
>>> On Tue, Nov 17, 2020 at 12:43 PM Alper Nebi Yasak
>>> <alpernebiyasak@gmail.com> wrote:
>>>> On 17/11/2020 04:49, Jean Lucas wrote:
>>>>> Hello all,
>>>>>
>>>>> On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot
>>>>> v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF
>>>>> v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang
>>>>> shortly after loading the appropriate FDT when booting.
>>>>>
>>>>> On a Pinebook Pro:
>>>>>
>>>>> => load mmc 0:1 ${kernel_addr_r} Image
>>>>> 32418304 bytes read in 1448 ms (21.4 MiB/s)
>>>>> => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
>>>>> 80831 bytes read in 27 ms (2.9 MiB/s)
>>>>> => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
>>>>> 29698825 bytes read in 1291 ms (21.9 MiB/s)
>>>>> => setenv bootargs console=ttyS2,1500000 console=tty0
>>>>> root=/dev/ghost/root audit=0
>>>>> => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
>>>>> Moving Image from 0x2080000 to 0x2200000, end=41c0000
>>>>> ## Flattened Device Tree blob at 01f00000
>>>>> ???? Booting using the
>>>>>
>>>>> Behavior is the same on RockPro64.
>>>>>
>>>>> Worth mentioning is that U-Boot from about a week ago (I think
>>>>> rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC
>>>>> results in a working boot on Pinebook Pro, so bug seems to be when
>>>>> booting from SPI.
>>>>>
>>>>> To further the hypothesis, on RockPro64, the latest U-Boot I can use
>>>>> from SPI (defconfig) is release 2020.04, since later releases also 
>>>>> hang
>>>>> on loading the appropriate FDT when booting as described above.
>>>>>
>>>>> Any ideas as to what could be causing the hangs?
>>>>>
>>>> My gru-kevin was hanging at that same place when I tried to boot from
>>>> USB, try running "usb stop" to see if that hangs. If so, try disabling
>>>> CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the 
>>>> hang in
>>>> my case.
>>> Which probably breaks USB keyboards?
>> I wouldn't know, gru-kevin uses cros-ec-keyb so I never needed to try a
>> USB keyboard. I meant those as steps to narrow things down.
> 
> So, running "usb stop" resulted in a hang.
> 
> I will test a build with the OHCI options Alper mentioned disabled, this 
> evening.
> 
> As far as testing goes, disabling USB is fine since I can access the 
> machines over serial.
> 

Hi,

Interestingly, disabling OHCI did the trick, and the Pinebook Pro and 
RockPro64 both boot normally. Unfortunately, Pinebook Pro's keyboard is 
connected to the mainboard via USB, and RockPro64 is USB-only as well, 
so OHCI support will have to be reviewed for these boards at least.

Interestingly, flashing the same U-Boot revision (except with OHCI 
enabled) to eMMC on Pinebook Pro - which results in SPL loading U-Boot 
from the eMMC by default, even when booted from SPI - results in working 
USB support. The boot hang only becomes an issue when U-Boot is loaded 
purely from SPI.

Regards,
Jean

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-19  5:45                       ` Jean Lucas
@ 2020-11-19  6:08                         ` Jean Lucas
  2021-01-28 22:28                         ` Jan Palus
  1 sibling, 0 replies; 42+ messages in thread
From: Jean Lucas @ 2020-11-19  6:08 UTC (permalink / raw)
  To: u-boot

On 11/19/20 12:45 AM, Jean Lucas wrote:
> On 11/17/20 1:28 PM, Jean Lucas wrote:
>> On 11/17/20 9:42 AM, Alper Nebi Yasak wrote:
>>> On 17/11/2020 17:11, Peter Robinson wrote:
>>>> On Tue, Nov 17, 2020 at 12:43 PM Alper Nebi Yasak
>>>> <alpernebiyasak@gmail.com> wrote:
>>>>> On 17/11/2020 04:49, Jean Lucas wrote:
>>>>>> Hello all,
>>>>>>
>>>>>> On Pine64 RockPro64 and Pinebook Pro (both RK3399), flashing U-Boot
>>>>>> v2021.01-rc2-47-g9324c9a823 defconfig and mainline ATF
>>>>>> v2.4-rc0-2-gd01f31c03 to SPI flash of both devices results in a hang
>>>>>> shortly after loading the appropriate FDT when booting.
>>>>>>
>>>>>> On a Pinebook Pro:
>>>>>>
>>>>>> => load mmc 0:1 ${kernel_addr_r} Image
>>>>>> 32418304 bytes read in 1448 ms (21.4 MiB/s)
>>>>>> => load mmc 0:1 ${fdt_addr_r} dtbs/rockchip/rk3399-pinebook-pro.dtb
>>>>>> 80831 bytes read in 27 ms (2.9 MiB/s)
>>>>>> => load mmc 0:1 ${ramdisk_addr_r} initramfs-linux.img
>>>>>> 29698825 bytes read in 1291 ms (21.9 MiB/s)
>>>>>> => setenv bootargs console=ttyS2,1500000 console=tty0
>>>>>> root=/dev/ghost/root audit=0
>>>>>> => booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r}
>>>>>> Moving Image from 0x2080000 to 0x2200000, end=41c0000
>>>>>> ## Flattened Device Tree blob at 01f00000
>>>>>> ???? Booting using the
>>>>>>
>>>>>> Behavior is the same on RockPro64.
>>>>>>
>>>>>> Worth mentioning is that U-Boot from about a week ago (I think
>>>>>> rc2-4-gf36603c7a8) with same mainline ATF version written to eMMC
>>>>>> results in a working boot on Pinebook Pro, so bug seems to be when
>>>>>> booting from SPI.
>>>>>>
>>>>>> To further the hypothesis, on RockPro64, the latest U-Boot I can use
>>>>>> from SPI (defconfig) is release 2020.04, since later releases also 
>>>>>> hang
>>>>>> on loading the appropriate FDT when booting as described above.
>>>>>>
>>>>>> Any ideas as to what could be causing the hangs?
>>>>>>
>>>>> My gru-kevin was hanging at that same place when I tried to boot from
>>>>> USB, try running "usb stop" to see if that hangs. If so, try disabling
>>>>> CONFIG_USB_OHCI_HCD and CONFIG_USB_OHCI_GENERIC, which fixed the 
>>>>> hang in
>>>>> my case.
>>>> Which probably breaks USB keyboards?
>>> I wouldn't know, gru-kevin uses cros-ec-keyb so I never needed to try a
>>> USB keyboard. I meant those as steps to narrow things down.
>>
>> So, running "usb stop" resulted in a hang.
>>
>> I will test a build with the OHCI options Alper mentioned disabled, 
>> this evening.
>>
>> As far as testing goes, disabling USB is fine since I can access the 
>> machines over serial.
>>
> 
> Hi,
> 
> Interestingly, disabling OHCI did the trick, and the Pinebook Pro and 
> RockPro64 both boot normally. Unfortunately, Pinebook Pro's keyboard is 
> connected to the mainboard via USB, and RockPro64 is USB-only as well, 
> so OHCI support will have to be reviewed for these boards at least.
> 
> Interestingly, flashing the same U-Boot revision (except with OHCI 
> enabled) to eMMC on Pinebook Pro - which results in SPL loading U-Boot 
> from the eMMC by default, even when booted from SPI - results in working 
> USB support. The boot hang only becomes an issue when U-Boot is loaded 
> purely from SPI.
> 
> Regards,
> Jean

Ah, I spoke too soon regarding U-Boot flashed to eMMC with OHCI support 
resulting in working boot, and the boot hang only being when U-Boot with 
OHCI support is loaded purely from SPI.

The hang indeed also occurs as of v2021.01-rc2-67-ge800d715e0, even when 
loaded from eMMC.

Regards

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2020-11-19  5:45                       ` Jean Lucas
  2020-11-19  6:08                         ` Jean Lucas
@ 2021-01-28 22:28                         ` Jan Palus
  2021-01-29  0:56                           ` Jan Palus
  1 sibling, 1 reply; 42+ messages in thread
From: Jan Palus @ 2021-01-28 22:28 UTC (permalink / raw)
  To: u-boot

FWIW I figured it hangs in ohci-hcd.c at:

static int hc_reset(ohci_t *ohci)
...
        if (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) {

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2021-01-28 22:28                         ` Jan Palus
@ 2021-01-29  0:56                           ` Jan Palus
  2021-01-29 18:47                             ` Jan Palus
  0 siblings, 1 reply; 42+ messages in thread
From: Jan Palus @ 2021-01-29  0:56 UTC (permalink / raw)
  To: u-boot

On 28.01.2021 23:28, Jan Palus wrote:
> FWIW I figured it hangs in ohci-hcd.c at:
> 
> static int hc_reset(ohci_t *ohci)
> ...
>         if (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) {

This appears to be caused by following events:

- usb_stop() (usb-class.c) iterates to remove every bus
- starts with ehci and goes all the way to ehci_shutdown_phy()
- there it calls generic_phy_exit() ending in rockchip_usb2phy_exit()
- where at last it disables clock with clk_disable() (rk3399_clk_disable())

After disabling clock ohci_readl(&ohci->regs->control) starts to hang so perhaps it
shouldn't be disabled until ohci is removed.

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

* [BUG] Hang shortly after loading FDT when booting on RK3399
  2021-01-29  0:56                           ` Jan Palus
@ 2021-01-29 18:47                             ` Jan Palus
  0 siblings, 0 replies; 42+ messages in thread
From: Jan Palus @ 2021-01-29 18:47 UTC (permalink / raw)
  To: u-boot

On 29.01.2021 01:56, Jan Palus wrote:
> On 28.01.2021 23:28, Jan Palus wrote:
> > FWIW I figured it hangs in ohci-hcd.c at:
> > 
> > static int hc_reset(ohci_t *ohci)
> > ...
> >         if (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) {
> 
> This appears to be caused by following events:
> 
> - usb_stop() (usb-class.c) iterates to remove every bus
> - starts with ehci and goes all the way to ehci_shutdown_phy()
> - there it calls generic_phy_exit() ending in rockchip_usb2phy_exit()
> - where at last it disables clock with clk_disable() (rk3399_clk_disable())
> 
> After disabling clock ohci_readl(&ohci->regs->control) starts to hang so perhaps it
> shouldn't be disabled until ohci is removed.

Looks like that's as far as I can go by myself. Perhaps the solution
could be CCF which appears to enable usage count tracking and prevents
disabling clock if it still has more users. Or perhaps EHCI/OHCI should
not be removed independently but instead one single remove should be
issued for usb2phy. Can't really tell.

In the meantime on Pinebook Pro more convenient workaround than
suggested disabling OHCI, is to rather disable EHCI. This way internal
keyboard works and boot process is still fine. I suppose external
keyboard wouldn't work then though.

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

end of thread, other threads:[~2021-01-29 18:47 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-13  4:14 [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 01/18] dfu: rename dfu_tftp_write() to dfu_write_by_name() AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 02/18] dfu: modify an argument type for an address AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 03/18] common: update: add a generic interface for FIT image AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 04/18] dfu: export dfu_list AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 05/18] efi_loader: add option to initialise EFI subsystem early AKASHI Takahiro
2020-11-13  4:14 ` [PATCH v8 06/18] efi_loader: add efi_create_indexed_name() AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 07/18] efi_loader: define UpdateCapsule api AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 08/18] efi_loader: capsule: add capsule_on_disk support AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 09/18] efi_loader: capsule: add memory range capsule definitions AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 10/18] efi_loader: capsule: support firmware update AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 11/18] efi_loader: add firmware management protocol for FIT image AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 12/18] dfu: add dfu_write_by_alt() AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 13/18] efi_loader: add firmware management protocol for raw image AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 14/18] cmd: add "efidebug capsule" command AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 15/18] tools: add mkeficapsule command for UEFI capsule update AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 16/18] test/py: efi_capsule: test for FIT image capsule AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 17/18] test/py: efi_capsule: test for raw " AKASHI Takahiro
2020-11-13  4:15 ` [PATCH v8 18/18] sandbox: enable capsule update for testing AKASHI Takahiro
2020-11-13  7:18 ` [PATCH v8 00/18] efi_loader: add capsule update support Heinrich Schuchardt
2020-11-16  0:37   ` AKASHI Takahiro
2020-11-16 16:10     ` Tom Rini
2020-11-17  0:16       ` AKASHI Takahiro
2020-11-17  0:36         ` Tom Rini
2020-11-17  0:44           ` AKASHI Takahiro
2020-11-17  1:49             ` [BUG] Hang shortly after loading FDT when booting on RK3399 Jean Lucas
2020-11-17 12:43               ` Alper Nebi Yasak
2020-11-17 14:11                 ` Peter Robinson
2020-11-17 14:42                   ` Alper Nebi Yasak
2020-11-17 18:28                     ` Jean Lucas
2020-11-19  5:45                       ` Jean Lucas
2020-11-19  6:08                         ` Jean Lucas
2021-01-28 22:28                         ` Jan Palus
2021-01-29  0:56                           ` Jan Palus
2021-01-29 18:47                             ` Jan Palus
2020-11-17 23:50             ` [PATCH v8 00/18] efi_loader: add capsule update support AKASHI Takahiro
2020-11-17 23:59               ` Tom Rini
2020-11-18  0:26                 ` AKASHI Takahiro
2020-11-18  3:02                   ` Tom Rini
2020-11-18  3:11                     ` AKASHI Takahiro
2020-11-18 14:49                       ` Tom Rini
2020-11-19  0:51                         ` AKASHI Takahiro

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.