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-#5,#12: preparatory patches
Patch#6-#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 as all have been merged as of v2020.07-rc4)
Test
====
* passed all the pytests which are included in this patch series
on sandbox build.
* passed Travis CI, except "buildman samsumg softfpga".
(I don't know what this build failed yet.)
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#6 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 doesn't improve anything.
* Add a document in uefi.rst
TODO's
======
(Won't be addressed in 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
=======
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):
common: update_tftp: remove unnecessary build check
dfu: add a hidden reverse-dependency on UPDATE_TFTP
dfu: rename dfu_tftp_write() to dfu_write_by_name()
common: update: add a generic interface for FIT image
dfu: export dfu_list
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 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: add a test for efi firmware update capsule of FIT image
test/py: add a test for uefi firmware update capsule of raw image
cmd/efidebug.c | 235 +++++
common/Kconfig | 16 +
common/Makefile | 2 +-
common/board_r.c | 6 +
common/main.c | 4 +
common/update.c | 83 +-
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 | 160 +++
include/efi_loader.h | 34 +
include/image.h | 12 +
lib/efi_loader/Kconfig | 72 ++
lib/efi_loader/Makefile | 2 +
lib/efi_loader/efi_capsule.c | 925 ++++++++++++++++++
lib/efi_loader/efi_firmware.c | 432 ++++++++
lib/efi_loader/efi_runtime.c | 104 +-
lib/efi_loader/efi_setup.c | 43 +-
test/py/tests/test_efi_capsule/conftest.py | 102 ++
test/py/tests/test_efi_capsule/defs.py | 24 +
.../test_efi_capsule/test_capsule_firmware.py | 383 ++++++++
.../tests/test_efi_capsule/uboot_bin_env.its | 36 +
test/py/tests/test_efi_capsule/uboot_env.its | 25 +
tools/Makefile | 3 +
tools/mkeficapsule.c | 237 +++++
28 files changed, 3056 insertions(+), 141 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 test/py/tests/test_efi_capsule/uboot_env.its
create mode 100644 tools/mkeficapsule.c