mbox series

[v7,00/17] efi_loader: add capsule update support

Message ID 20201029044757.183262-1-takahiro.akashi@linaro.org
Headers show
Series efi_loader: add capsule update support | expand

Message

AKASHI Takahiro Oct. 29, 2020, 4:47 a.m. UTC
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

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

Please note that the capsule pytest itself won't be run in the CI
partly because some specific configuration for sandbox build is
required and partly because there is a problem with virt-make-fs.
See test_efi_capsule_firmware.py.

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
=======
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 (17):
  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

 cmd/efidebug.c                                | 235 +++++
 common/Kconfig                                |  15 +
 common/Makefile                               |   3 +-
 common/board_r.c                              |   6 +
 common/main.c                                 |   4 +
 common/update.c                               |  77 +-
 drivers/dfu/Kconfig                           |   6 +
 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 +-
 test/py/tests/test_efi_capsule/conftest.py    |  72 ++
 test/py/tests/test_efi_capsule/defs.py        |  12 +
 .../test_efi_capsule/test_capsule_firmware.py | 241 +++++
 .../tests/test_efi_capsule/uboot_bin_env.its  |  36 +
 tools/Makefile                                |   2 +
 tools/mkeficapsule.c                          | 239 +++++
 27 files changed, 2871 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/conftest.py
 create mode 100644 test/py/tests/test_efi_capsule/defs.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

Comments

Tom Rini Oct. 29, 2020, 2:43 p.m. UTC | #1
On Thu, Oct 29, 2020 at 01:47:40PM +0900, 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
> 
> [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.
> 
> Please note that the capsule pytest itself won't be run in the CI
> partly because some specific configuration for sandbox build is
> required and partly because there is a problem with virt-make-fs.
> See test_efi_capsule_firmware.py.

Maybe we need to talk about this differently then.  Today, the tests
start on CI and then fail to run.  That's a problem that needs to be
fixed, they must "skip" properly.  I would really like to see these
tests run with every CI loop.  That means doing a "try virt-make-fs, if
that fails, try sudo, if that fails, skip".  That also means updating
some other tests that have logic for virt-make-fs, but it then causes CI
to fail rather than try sudo.

What I see as the worst case is that we have tests for this feature that
are only ever run when someone runs them intentionally, and CI skips
them all the time.
Heinrich Schuchardt Oct. 30, 2020, 7:54 a.m. UTC | #2
On 10/29/20 5:47 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.

Gitlab CI fails:

https://gitlab.denx.de/u-boot/custodians/u-boot-efi/-/jobs/172745
https://gitlab.denx.de/u-boot/custodians/u-boot-efi/-/jobs/172744

             # Create signature database
             # PK
             check_call('cd %s; openssl req -x509 -sha256 -newkey
rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365'
                        % mnt_point, shell=True)
             check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt
PK.esl; %ssign-efi-sig-list -t "2020-04-01" -c PK.crt -k PK.key PK
PK.esl PK.auth'
 >                      % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                        shell=True)
E                      NameError: name 'EFITOOLS_PATH' is not defined
test/py/tests/test_efi_secboot/conftest.py:50: NameError


To get the series merged, please, provide the necessary patches for
.azure-pipelines.yml, .gitlab-ci.yml, .travis.yml.

Possibly you will have to adjust
https://gitlab.denx.de/u-boot/gitlab-ci-runner

Best regards

Heinrich



>
> 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
>
> [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.
>
> Please note that the capsule pytest itself won't be run in the CI
> partly because some specific configuration for sandbox build is
> required and partly because there is a problem with virt-make-fs.
> See test_efi_capsule_firmware.py.
>
> 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
> =======
> 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 (17):
>    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
>
>   cmd/efidebug.c                                | 235 +++++
>   common/Kconfig                                |  15 +
>   common/Makefile                               |   3 +-
>   common/board_r.c                              |   6 +
>   common/main.c                                 |   4 +
>   common/update.c                               |  77 +-
>   drivers/dfu/Kconfig                           |   6 +
>   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 +-
>   test/py/tests/test_efi_capsule/conftest.py    |  72 ++
>   test/py/tests/test_efi_capsule/defs.py        |  12 +
>   .../test_efi_capsule/test_capsule_firmware.py | 241 +++++
>   .../tests/test_efi_capsule/uboot_bin_env.its  |  36 +
>   tools/Makefile                                |   2 +
>   tools/mkeficapsule.c                          | 239 +++++
>   27 files changed, 2871 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/conftest.py
>   create mode 100644 test/py/tests/test_efi_capsule/defs.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
>
Heinrich Schuchardt Oct. 30, 2020, 7:59 a.m. UTC | #3
On 10/30/20 8:54 AM, Heinrich Schuchardt wrote:
> On 10/29/20 5:47 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.
>
> Gitlab CI fails:
>
> https://gitlab.denx.de/u-boot/custodians/u-boot-efi/-/jobs/172745
> https://gitlab.denx.de/u-boot/custodians/u-boot-efi/-/jobs/172744
>
>              # Create signature database
>              # PK
>              check_call('cd %s; openssl req -x509 -sha256 -newkey
> rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365'
>                         % mnt_point, shell=True)
>              check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt
> PK.esl; %ssign-efi-sig-list -t "2020-04-01" -c PK.crt -k PK.key PK
> PK.esl PK.auth'
>  >                      % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
>                         shell=True)
> E                      NameError: name 'EFITOOLS_PATH' is not defined
> test/py/tests/test_efi_secboot/conftest.py:50: NameError
>
>
> To get the series merged, please, provide the necessary patches for
> .azure-pipelines.yml, .gitlab-ci.yml, .travis.yml.
>
> Possibly you will have to adjust
> https://gitlab.denx.de/u-boot/gitlab-ci-runner
>
> Best regards
>
> Heinrich
>

Hello Lukasz,

I would like to get at least get the DFU part merged. So I suggest to
add the DFU patches to my next pull request for Tom.

Is that fine with you?

Best regards

Heinrich
AKASHI Takahiro Nov. 4, 2020, 9:36 a.m. UTC | #4
Hi Tom,

On Thu, Oct 29, 2020 at 10:43:01AM -0400, Tom Rini wrote:
> On Thu, Oct 29, 2020 at 01:47:40PM +0900, 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
> > 
> > [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.
> > 
> > Please note that the capsule pytest itself won't be run in the CI
> > partly because some specific configuration for sandbox build is
> > required and partly because there is a problem with virt-make-fs.
> > See test_efi_capsule_firmware.py.
> 
> Maybe we need to talk about this differently then.  Today, the tests
> start on CI and then fail to run.  That's a problem that needs to be
> fixed, they must "skip" properly.  I would really like to see these
> tests run with every CI loop.  That means doing a "try virt-make-fs, if
> that fails, try sudo, if that fails, skip".  That also means updating
> some other tests that have logic for virt-make-fs, but it then causes CI
> to fail rather than try sudo.

I think that you still misunderstand the point.
Whatever you expect by saying "try virt-make-fs, if that fails, try sudo,
if that fails, skip," Heinrich will *not* accept any test script that
contains "sudo" command.
I can do nothing here unless he changes his mind.

Or do you want to see the solution like "try virt-make-fs, if
that fails, skip"?

-Takahiro Akashi

> What I see as the worst case is that we have tests for this feature that
> are only ever run when someone runs them intentionally, and CI skips
> them all the time.
> 
> -- 
> Tom
Tom Rini Nov. 4, 2020, 12:57 p.m. UTC | #5
On Wed, Nov 04, 2020 at 06:36:24PM +0900, AKASHI Takahiro wrote:
> Hi Tom,
> 
> On Thu, Oct 29, 2020 at 10:43:01AM -0400, Tom Rini wrote:
> > On Thu, Oct 29, 2020 at 01:47:40PM +0900, 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
> > > 
> > > [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.
> > > 
> > > Please note that the capsule pytest itself won't be run in the CI
> > > partly because some specific configuration for sandbox build is
> > > required and partly because there is a problem with virt-make-fs.
> > > See test_efi_capsule_firmware.py.
> > 
> > Maybe we need to talk about this differently then.  Today, the tests
> > start on CI and then fail to run.  That's a problem that needs to be
> > fixed, they must "skip" properly.  I would really like to see these
> > tests run with every CI loop.  That means doing a "try virt-make-fs, if
> > that fails, try sudo, if that fails, skip".  That also means updating
> > some other tests that have logic for virt-make-fs, but it then causes CI
> > to fail rather than try sudo.
> 
> I think that you still misunderstand the point.
> Whatever you expect by saying "try virt-make-fs, if that fails, try sudo,
> if that fails, skip," Heinrich will *not* accept any test script that
> contains "sudo" command.
> I can do nothing here unless he changes his mind.
> 
> Or do you want to see the solution like "try virt-make-fs, if
> that fails, skip"?

Yes, you need to figure out some way to make the tests pass, without
sudo being present.  You also need to CI not fail if we can't run the
tests.  Further, it would be really nice if we could also run these
tests in CI.  Running the tests in CI may require sudo being used, just
like how that's the only way other tests are run in CI today.  That will
be acceptable.  Right Heinrich?