mbox series

[00/10] efi_loader: add capsule update support

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

Message

AKASHI Takahiro April 27, 2020, 9:48 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, suported 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 will be, by nature, system/platform-specific. So you can and should
implement your own FMP driver(s) based on your system requirements.
Only a simple FMP driver based on FIT image for a single region is
provided here.  (So it is "for reference only")
                           ^^^^^^^^^^^^^^^^^^
See more details in the commit, "efi_loader: capsule: add simple firmware
management protocol."

Patch structure
===============
Patch#1-#2: preparatory patches
Patch#3-#7: main part of implementation
Patch#8-#10: utilities and tests

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

Prerequisite patches
====================
[2] part: detect EFI system partition
    https://lists.denx.de/pipermail/u-boot/2020-March/403562.html
[3] common: update_tftp: remove unnecessary build check
    https://lists.denx.de/pipermail/u-boot/2020-March/401727.html
[4] sandbox: drop CONFIG_SYS_RELOC_GD_ENV_ADDR
    https://lists.denx.de/pipermail/u-boot/2020-April/408711.html

Test
====
* passed all the pytests which are included in this patch series
  on sandbox build.
* passed Travis CI.

Please note that, while Travic CI passed, the capsule pytest
itself won't be run in the CI because some specific configuration
for sandbox build is required. 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#4 for my proposal

TODO's
======
(May not be addressed in future versions of this series.)
* capsule authentication
* capsule dependency (dependency expression instruction set)
* 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
=======
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 (10):
  efi_loader: disk: add efi_disk_is_system_part()
  efi_loader: add option to initialise EFI subsystem early
  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 simple firmware management protocol for FIT image
  cmd: add "efidebug capsule" command
  tools: add mkeficapsule command for UEFI capsule update test
  test/py: add a test for efi firmware update capsule

 cmd/efidebug.c                                | 234 +++++
 common/board_r.c                              |   6 +
 common/main.c                                 |   4 +
 include/efi_api.h                             | 156 ++++
 include/efi_loader.h                          |  35 +
 lib/efi_loader/Kconfig                        |  69 ++
 lib/efi_loader/Makefile                       |   2 +
 lib/efi_loader/efi_capsule.c                  | 802 ++++++++++++++++++
 lib/efi_loader/efi_disk.c                     |  22 +
 lib/efi_loader/efi_firmware.c                 | 191 +++++
 lib/efi_loader/efi_runtime.c                  | 104 ++-
 lib/efi_loader/efi_setup.c                    |  44 +-
 test/py/tests/test_efi_capsule/conftest.py    |  73 ++
 test/py/tests/test_efi_capsule/defs.py        |  24 +
 .../test_efi_capsule/test_capsule_firmware.py | 198 +++++
 test/py/tests/test_efi_capsule/uboot_env.its  |  25 +
 tools/Makefile                                |   3 +
 tools/mkeficapsule.c                          | 209 +++++
 18 files changed, 2150 insertions(+), 51 deletions(-)
 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_env.its
 create mode 100644 tools/mkeficapsule.c

Comments

Heinrich Schuchardt April 27, 2020, 8:33 p.m. UTC | #1
On 4/27/20 11:48 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, suported 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 will be, by nature, system/platform-specific. So you can and should
> implement your own FMP driver(s) based on your system requirements.
> Only a simple FMP driver based on FIT image for a single region is
> provided here.  (So it is "for reference only")

Do think this FMP driver will be actually used?
Or should it be moved to lib/efi_selftest?

>                            ^^^^^^^^^^^^^^^^^^
> See more details in the commit, "efi_loader: capsule: add simple firmware
> management protocol."

In this patch series I am missing the update of the documentation in
doc/uefi/.

Best regards

Heinrich

>
> Patch structure
> ===============
> Patch#1-#2: preparatory patches
> Patch#3-#7: main part of implementation
> Patch#8-#10: utilities and tests
>
> [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
>
> Prerequisite patches
> ====================
> [2] part: detect EFI system partition
>     https://lists.denx.de/pipermail/u-boot/2020-March/403562.html
> [3] common: update_tftp: remove unnecessary build check
>     https://lists.denx.de/pipermail/u-boot/2020-March/401727.html
> [4] sandbox: drop CONFIG_SYS_RELOC_GD_ENV_ADDR
>     https://lists.denx.de/pipermail/u-boot/2020-April/408711.html
>
> Test
> ====
> * passed all the pytests which are included in this patch series
>   on sandbox build.
> * passed Travis CI.
>
> Please note that, while Travic CI passed, the capsule pytest
> itself won't be run in the CI because some specific configuration
> for sandbox build is required. 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#4 for my proposal
>
> TODO's
> ======
> (May not be addressed in future versions of this series.)
> * capsule authentication
> * capsule dependency (dependency expression instruction set)
> * 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
> =======
> 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 (10):
>   efi_loader: disk: add efi_disk_is_system_part()
>   efi_loader: add option to initialise EFI subsystem early
>   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 simple firmware management protocol for FIT image
>   cmd: add "efidebug capsule" command
>   tools: add mkeficapsule command for UEFI capsule update test
>   test/py: add a test for efi firmware update capsule
>
>  cmd/efidebug.c                                | 234 +++++
>  common/board_r.c                              |   6 +
>  common/main.c                                 |   4 +
>  include/efi_api.h                             | 156 ++++
>  include/efi_loader.h                          |  35 +
>  lib/efi_loader/Kconfig                        |  69 ++
>  lib/efi_loader/Makefile                       |   2 +
>  lib/efi_loader/efi_capsule.c                  | 802 ++++++++++++++++++
>  lib/efi_loader/efi_disk.c                     |  22 +
>  lib/efi_loader/efi_firmware.c                 | 191 +++++
>  lib/efi_loader/efi_runtime.c                  | 104 ++-
>  lib/efi_loader/efi_setup.c                    |  44 +-
>  test/py/tests/test_efi_capsule/conftest.py    |  73 ++
>  test/py/tests/test_efi_capsule/defs.py        |  24 +
>  .../test_efi_capsule/test_capsule_firmware.py | 198 +++++
>  test/py/tests/test_efi_capsule/uboot_env.its  |  25 +
>  tools/Makefile                                |   3 +
>  tools/mkeficapsule.c                          | 209 +++++
>  18 files changed, 2150 insertions(+), 51 deletions(-)
>  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_env.its
>  create mode 100644 tools/mkeficapsule.c
>
AKASHI Takahiro April 27, 2020, 11:45 p.m. UTC | #2
Heinrich,

On Mon, Apr 27, 2020 at 10:33:41PM +0200, Heinrich Schuchardt wrote:
> On 4/27/20 11:48 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, suported 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 will be, by nature, system/platform-specific. So you can and should
> > implement your own FMP driver(s) based on your system requirements.
> > Only a simple FMP driver based on FIT image for a single region is
> > provided here.  (So it is "for reference only")
> 
> Do think this FMP driver will be actually used?

It's totally up to users (and their requirements).

> Or should it be moved to lib/efi_selftest?

Well, I hope that someone will come in and add more features
that will meet additional requirements.
So I would like you to keep it under lib/efi_loader for now.

> >                            ^^^^^^^^^^^^^^^^^^
> > See more details in the commit, "efi_loader: capsule: add simple firmware
> > management protocol."
> 
> In this patch series I am missing the update of the documentation in
> doc/uefi/.

Okay.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> >
> > Patch structure
> > ===============
> > Patch#1-#2: preparatory patches
> > Patch#3-#7: main part of implementation
> > Patch#8-#10: utilities and tests
> >
> > [1] https://git.linaro.org/people/takahiro.akashi/u-boot.git efi/capsule
> >
> > Prerequisite patches
> > ====================
> > [2] part: detect EFI system partition
> >     https://lists.denx.de/pipermail/u-boot/2020-March/403562.html
> > [3] common: update_tftp: remove unnecessary build check
> >     https://lists.denx.de/pipermail/u-boot/2020-March/401727.html
> > [4] sandbox: drop CONFIG_SYS_RELOC_GD_ENV_ADDR
> >     https://lists.denx.de/pipermail/u-boot/2020-April/408711.html
> >
> > Test
> > ====
> > * passed all the pytests which are included in this patch series
> >   on sandbox build.
> > * passed Travis CI.
> >
> > Please note that, while Travic CI passed, the capsule pytest
> > itself won't be run in the CI because some specific configuration
> > for sandbox build is required. 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#4 for my proposal
> >
> > TODO's
> > ======
> > (May not be addressed in future versions of this series.)
> > * capsule authentication
> > * capsule dependency (dependency expression instruction set)
> > * 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
> > =======
> > 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 (10):
> >   efi_loader: disk: add efi_disk_is_system_part()
> >   efi_loader: add option to initialise EFI subsystem early
> >   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 simple firmware management protocol for FIT image
> >   cmd: add "efidebug capsule" command
> >   tools: add mkeficapsule command for UEFI capsule update test
> >   test/py: add a test for efi firmware update capsule
> >
> >  cmd/efidebug.c                                | 234 +++++
> >  common/board_r.c                              |   6 +
> >  common/main.c                                 |   4 +
> >  include/efi_api.h                             | 156 ++++
> >  include/efi_loader.h                          |  35 +
> >  lib/efi_loader/Kconfig                        |  69 ++
> >  lib/efi_loader/Makefile                       |   2 +
> >  lib/efi_loader/efi_capsule.c                  | 802 ++++++++++++++++++
> >  lib/efi_loader/efi_disk.c                     |  22 +
> >  lib/efi_loader/efi_firmware.c                 | 191 +++++
> >  lib/efi_loader/efi_runtime.c                  | 104 ++-
> >  lib/efi_loader/efi_setup.c                    |  44 +-
> >  test/py/tests/test_efi_capsule/conftest.py    |  73 ++
> >  test/py/tests/test_efi_capsule/defs.py        |  24 +
> >  .../test_efi_capsule/test_capsule_firmware.py | 198 +++++
> >  test/py/tests/test_efi_capsule/uboot_env.its  |  25 +
> >  tools/Makefile                                |   3 +
> >  tools/mkeficapsule.c                          | 209 +++++
> >  18 files changed, 2150 insertions(+), 51 deletions(-)
> >  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_env.its
> >  create mode 100644 tools/mkeficapsule.c
> >
>