[PATCH v3 00/11] Integrate EFI capsule tasks into u-boot's build flow

This patchset aims to bring two capsule related tasks under the u-boot build flow.
One is the embedding of the public key into the platform's dtb. The public key is in the form of an EFI Signature List(ESL) file and is used for capsule authentication. This is being achieved by adding the signature node containing the capsule public key in the architecture's u-boot.dtsi file. Currently, the u-boot.dtsi file has been added for the sandbox and arm architectures. The path to the ESL file is being provided through a Kconfig symbol(CONFIG_EFI_CAPSULE_ESL_FILE).
Changes have also been made to the test flow so that the keys used for signing the capsule, and the ESL file, are generated prior to invoking the u-boot's build, which enables embedding the ESL file into the dtb as part of the u-boot build.
The other task is related to generation of capsules. Support is being added to generate capsules by specifying the capsule parameters in a config file. Calling the mkeficapsule tool then results in generation of the corresponding capsule files. The capsules can be generated as part of u-boot build, and this is being achieved through binman, by adding a capsule entry type. The capsules can be generated either by specifying the capsule parameters in a config file, or through specifying them as properties under the capsule entry node. If using the config file, the path to the config file is to be specified through a Kconfig symbol(CONFIG_EFI_CAPSULE_CFG_FILE).
Changes have also been made to the efi capsule update feature testing setup on the sandbox variants. Currently, the capsule files and the public key ESL file are generated after u-boot has been built. This logic has been changed so that the capsule input files along with the keys needed for capsule signing and authentication are generated prior to initiation of the u-boot build. The placement of all the files needed for generation of capsules, along with the generated capsule files is under the /tmp/capsules/ directory.
Currently, the capsule update feature is tested on the sandbox and sandbox_flattree variants in CI. The capsule generation through config file is enabled for the sandbox variant, with the sandbox_flattree variant generating capsules through the command-line parameters.
The document has been updated to reflect the above changes.
Changes since V2: This version embeds the capsule auth related public key through the u-boot.dtsi file. The capsule generation has been moved to binman. The changes in the test setup have been split into multiple patches, instead of a single monolithic patch.
* Add the public key ESL file through the u-boot.dtsi * Add the dtsi files for sandbox and arm architectures * Add a check in the Makefile that the ESL file path is not empty. * Highlight the need to use the u-boot.dtsi file for embedding the public key ESL into the DTB. * Add a Kconfig boolean symbol CONFIG_EFI_USE_CAPSULE_CFG_FILE which can be used to generate capsules through config file or parameters. * New patch which generates capsules through binman replacing the earlier make target. * New patch setting up the capsule files needed for CI run * New patch for setting up the capsule files in the pytest setup before initiation of u-boot build. * New patch for removing the capsule key and ESL generation logic from the capsule test config file. * New patch to add the capsule generation config file for sandbox. * New patch for generating the capsules and capsule input files through binman.
Sughosh Ganu (11): nuvoton: npcm845-evb: Add a newline at the end of file capsule: authenticate: Add capsule public key in platform's dtb doc: capsule: Document the new mechanism to embed ESL file into dtb tools: mkeficapsule: Add support for parsing capsule params from config file doc: Add documentation to describe capsule config file format binman: capsule: Add support for generating capsules CI: capsule: Setup the files needed for capsule update testing test: py: Setup capsule files for testing test: capsule: Remove public key embed logic from capsule update test sandbox: capsule: Add a config file for generating capsules sandbox: capsule: Generate capsule related files through binman
.azure-pipelines.yml | 22 ++ .gitlab-ci.yml | 20 + arch/arm/dts/nuvoton-npcm845-evb.dts | 2 +- arch/arm/dts/u-boot.dtsi | 17 + arch/sandbox/dts/u-boot.dtsi | 160 ++++++++ configs/sandbox_defconfig | 3 + configs/sandbox_flattree_defconfig | 1 + doc/develop/uefi/uefi.rst | 86 ++++- lib/efi_loader/Kconfig | 11 + lib/efi_loader/Makefile | 7 + test/py/conftest.py | 92 +++++ test/py/tests/test_efi_capsule/conftest.py | 92 +---- .../test_efi_capsule/sandbox_capsule_cfg.txt | 75 ++++ test/py/tests/test_efi_capsule/signature.dts | 10 - .../tests/test_efi_capsule/uboot_bin_env.its | 36 -- tools/Kconfig | 16 + tools/Makefile | 1 + tools/binman/btool/mkeficapsule.py | 91 +++++ tools/binman/entries.rst | 27 ++ tools/binman/etype/capsule.py | 102 ++++++ tools/eficapsule.h | 110 ++++++ tools/mkeficapsule.c | 84 +++-- tools/mkeficapsule_parse.c | 345 ++++++++++++++++++ 23 files changed, 1232 insertions(+), 178 deletions(-) create mode 100644 arch/arm/dts/u-boot.dtsi create mode 100644 arch/sandbox/dts/u-boot.dtsi create mode 100644 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt delete mode 100644 test/py/tests/test_efi_capsule/signature.dts delete mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its create mode 100644 tools/binman/btool/mkeficapsule.py create mode 100644 tools/binman/etype/capsule.py create mode 100644 tools/mkeficapsule_parse.c

Add a newline at the end of the dts, without which the build fails when including the u-boot.dtsi file.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch
arch/arm/dts/nuvoton-npcm845-evb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/dts/nuvoton-npcm845-evb.dts b/arch/arm/dts/nuvoton-npcm845-evb.dts index 3cab7807e3..a93666cb41 100644 --- a/arch/arm/dts/nuvoton-npcm845-evb.dts +++ b/arch/arm/dts/nuvoton-npcm845-evb.dts @@ -354,4 +354,4 @@ &r1en_pins &r1oen_pins >; -}; \ No newline at end of file +};

On Sun, 9 Jul 2023 at 07:33, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Add a newline at the end of the dts, without which the build fails when including the u-boot.dtsi file.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch
arch/arm/dts/nuvoton-npcm845-evb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

The EFI capsule authentication logic in u-boot expects the public key in the form of an EFI Signature List(ESL) to be provided as part of the platform's dtb. Currently, the embedding of the ESL file into the dtb needs to be done manually.
Add a signature node in the u-boot dtsi file and include the public key through the capsule-key property. This file is per architecture, and is currently being added for sandbox and arm architectures. It will have to be added for other architectures which need to enable capsule authentication support.
The path to the ESL file is specified through the CONFIG_EFI_CAPSULE_ESL_FILE symbol.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * Add the public key ESL file through the u-boot.dtsi. * Add the dtsi files for sandbox and arm architectures. * Add a check in the Makefile that the ESL file path is not empty.
arch/arm/dts/u-boot.dtsi | 17 +++++++++++++++++ arch/sandbox/dts/u-boot.dtsi | 17 +++++++++++++++++ lib/efi_loader/Kconfig | 11 +++++++++++ lib/efi_loader/Makefile | 7 +++++++ 4 files changed, 52 insertions(+) create mode 100644 arch/arm/dts/u-boot.dtsi create mode 100644 arch/sandbox/dts/u-boot.dtsi
diff --git a/arch/arm/dts/u-boot.dtsi b/arch/arm/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/arm/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Devicetree file with miscellaneous nodes that will be included + * at build time into the DTB. Currently being used for including + * capsule related information. + * + */ + +#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE + signature { + capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); + }; +#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/sandbox/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Devicetree file with miscellaneous nodes that will be included + * at build time into the DTB. Currently being used for including + * capsule related information. + * + */ + +#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE + signature { + capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); + }; +#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..1326a1d109 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -234,6 +234,17 @@ config EFI_CAPSULE_MAX Select the max capsule index value used for capsule report variables. This value is used to create CapsuleMax variable.
+config EFI_CAPSULE_ESL_FILE + string "Path to the EFI Signature List File" + default "" + depends on EFI_CAPSULE_AUTHENTICATE + help + Provides the absolute path to the EFI Signature List + file which will be embedded in the platform's device + tree and used for capsule authentication at the time + of capsule update. + + 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 13a35eae6c..9fb04720d9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -86,3 +86,10 @@ obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
EFI_VAR_SEED_FILE := $(subst $",,$(CONFIG_EFI_VAR_SEED_FILE)) $(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE) + +ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y) +EFI_CAPSULE_KEY_PATH := $(subst $",,$(CONFIG_EFI_CAPSULE_ESL_FILE)) +ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","") +$(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_ESL_FILE) +endif +endif

Am 9. Juli 2023 15:33:17 MESZ schrieb Sughosh Ganu sughosh.ganu@linaro.org:
The EFI capsule authentication logic in u-boot expects the public key in the form of an EFI Signature List(ESL) to be provided as part of the platform's dtb. Currently, the embedding of the ESL file into the dtb needs to be done manually.
Add a signature node in the u-boot dtsi file and include the public key through the capsule-key property. This file is per architecture, and is currently being added for sandbox and arm architectures. It
The device-tree compiler can pick up files from /include/. If the dtsi file is not architecture specific, we should avoid code duplication.
We should treat all EFI architectures the same.
Best regards
Heinrich
will have to be added for other architectures which need to enable capsule authentication support.
The path to the ESL file is specified through the CONFIG_EFI_CAPSULE_ESL_FILE symbol.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- Add the public key ESL file through the u-boot.dtsi.
- Add the dtsi files for sandbox and arm architectures.
- Add a check in the Makefile that the ESL file path is not empty.
arch/arm/dts/u-boot.dtsi | 17 +++++++++++++++++ arch/sandbox/dts/u-boot.dtsi | 17 +++++++++++++++++ lib/efi_loader/Kconfig | 11 +++++++++++ lib/efi_loader/Makefile | 7 +++++++ 4 files changed, 52 insertions(+) create mode 100644 arch/arm/dts/u-boot.dtsi create mode 100644 arch/sandbox/dts/u-boot.dtsi
diff --git a/arch/arm/dts/u-boot.dtsi b/arch/arm/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/arm/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
- signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
- };
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/sandbox/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
- signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
- };
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..1326a1d109 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -234,6 +234,17 @@ config EFI_CAPSULE_MAX Select the max capsule index value used for capsule report variables. This value is used to create CapsuleMax variable.
+config EFI_CAPSULE_ESL_FILE
- string "Path to the EFI Signature List File"
- default ""
- depends on EFI_CAPSULE_AUTHENTICATE
- help
Provides the absolute path to the EFI Signature List
file which will be embedded in the platform's device
tree and used for capsule authentication at the time
of capsule update.
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 13a35eae6c..9fb04720d9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -86,3 +86,10 @@ obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
EFI_VAR_SEED_FILE := $(subst $",,$(CONFIG_EFI_VAR_SEED_FILE)) $(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
+ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y) +EFI_CAPSULE_KEY_PATH := $(subst $",,$(CONFIG_EFI_CAPSULE_ESL_FILE)) +ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","") +$(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_ESL_FILE) +endif +endif

hi Heinrich,
On Sun, 9 Jul 2023 at 19:22, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 9. Juli 2023 15:33:17 MESZ schrieb Sughosh Ganu sughosh.ganu@linaro.org:
The EFI capsule authentication logic in u-boot expects the public key in the form of an EFI Signature List(ESL) to be provided as part of the platform's dtb. Currently, the embedding of the ESL file into the dtb needs to be done manually.
Add a signature node in the u-boot dtsi file and include the public key through the capsule-key property. This file is per architecture, and is currently being added for sandbox and arm architectures. It
The device-tree compiler can pick up files from /include/. If the dtsi file is not architecture specific, we should avoid code duplication.
The idea here was to have the dtsi file get included automatically during build, and that happens only when the dtsi file, with a specific name, is in the same directory as the dts being built. The include directory is just a location where files would be searched for when building, but the corresponding dtsi file will have to be explicitly included in the dts being built. So this would mean every board dts file needing to include the capsule dtsi file, instead of automatic inclusion. I believe putting this dtsi file in the dts directory of an architecture which is using capsule updates is easier than including it in every board's dts.
The initial implementation was generating the signature node in a dtbo on the fly, and including it into the corresponding dtb as it was built. This is the approach that was taken in v1 [1], but Simon did not like it, and Jonas suggested this approach [2].
-sughosh
[1] - https://lists.denx.de/pipermail/u-boot/2023-June/520121.html [2] - https://lists.denx.de/pipermail/u-boot/2023-June/521195.html
We should treat all EFI architectures the same.
Best regards
Heinrich
will have to be added for other architectures which need to enable capsule authentication support.
The path to the ESL file is specified through the CONFIG_EFI_CAPSULE_ESL_FILE symbol.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- Add the public key ESL file through the u-boot.dtsi.
- Add the dtsi files for sandbox and arm architectures.
- Add a check in the Makefile that the ESL file path is not empty.
arch/arm/dts/u-boot.dtsi | 17 +++++++++++++++++ arch/sandbox/dts/u-boot.dtsi | 17 +++++++++++++++++ lib/efi_loader/Kconfig | 11 +++++++++++ lib/efi_loader/Makefile | 7 +++++++ 4 files changed, 52 insertions(+) create mode 100644 arch/arm/dts/u-boot.dtsi create mode 100644 arch/sandbox/dts/u-boot.dtsi
diff --git a/arch/arm/dts/u-boot.dtsi b/arch/arm/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/arm/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
};
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/sandbox/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
};
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..1326a1d109 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -234,6 +234,17 @@ config EFI_CAPSULE_MAX Select the max capsule index value used for capsule report variables. This value is used to create CapsuleMax variable.
+config EFI_CAPSULE_ESL_FILE
string "Path to the EFI Signature List File"
default ""
depends on EFI_CAPSULE_AUTHENTICATE
help
Provides the absolute path to the EFI Signature List
file which will be embedded in the platform's device
tree and used for capsule authentication at the time
of capsule update.
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 13a35eae6c..9fb04720d9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -86,3 +86,10 @@ obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
EFI_VAR_SEED_FILE := $(subst $",,$(CONFIG_EFI_VAR_SEED_FILE)) $(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
+ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y) +EFI_CAPSULE_KEY_PATH := $(subst $",,$(CONFIG_EFI_CAPSULE_ESL_FILE)) +ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","") +$(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_ESL_FILE) +endif +endif

Hi Sughosh, Heinrich,
On Mon, 10 Jul 2023 at 01:24, Sughosh Ganu sughosh.ganu@linaro.org wrote:
hi Heinrich,
On Sun, 9 Jul 2023 at 19:22, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 9. Juli 2023 15:33:17 MESZ schrieb Sughosh Ganu sughosh.ganu@linaro.org:
The EFI capsule authentication logic in u-boot expects the public key in the form of an EFI Signature List(ESL) to be provided as part of the platform's dtb. Currently, the embedding of the ESL file into the dtb needs to be done manually.
Add a signature node in the u-boot dtsi file and include the public key through the capsule-key property. This file is per architecture, and is currently being added for sandbox and arm architectures. It
The device-tree compiler can pick up files from /include/. If the dtsi file is not architecture specific, we should avoid code duplication.
The idea here was to have the dtsi file get included automatically during build, and that happens only when the dtsi file, with a specific name, is in the same directory as the dts being built. The include directory is just a location where files would be searched for when building, but the corresponding dtsi file will have to be explicitly included in the dts being built. So this would mean every board dts file needing to include the capsule dtsi file, instead of automatic inclusion. I believe putting this dtsi file in the dts directory of an architecture which is using capsule updates is easier than including it in every board's dts.
The initial implementation was generating the signature node in a dtbo on the fly, and including it into the corresponding dtb as it was built. This is the approach that was taken in v1 [1], but Simon did not like it, and Jonas suggested this approach [2].
-sughosh
[1] - https://lists.denx.de/pipermail/u-boot/2023-June/520121.html [2] - https://lists.denx.de/pipermail/u-boot/2023-June/521195.html
We should treat all EFI architectures the same.
I'm not saying this is a great solution. I would prefer that people add the public key to their board themselves, but we are still struggling with the concept of the DT being used for such things...
For now this seems OK. We can always clean it up later.
Best regards
Heinrich
will have to be added for other architectures which need to enable capsule authentication support.
The path to the ESL file is specified through the CONFIG_EFI_CAPSULE_ESL_FILE symbol.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- Add the public key ESL file through the u-boot.dtsi.
- Add the dtsi files for sandbox and arm architectures.
- Add a check in the Makefile that the ESL file path is not empty.
arch/arm/dts/u-boot.dtsi | 17 +++++++++++++++++ arch/sandbox/dts/u-boot.dtsi | 17 +++++++++++++++++ lib/efi_loader/Kconfig | 11 +++++++++++ lib/efi_loader/Makefile | 7 +++++++ 4 files changed, 52 insertions(+) create mode 100644 arch/arm/dts/u-boot.dtsi create mode 100644 arch/sandbox/dts/u-boot.dtsi
diff --git a/arch/arm/dts/u-boot.dtsi b/arch/arm/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/arm/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
May as well put both #ifdefs together as there is no point in declaring an empty node.
signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
};
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi new file mode 100644 index 0000000000..60bd004937 --- /dev/null +++ b/arch/sandbox/dts/u-boot.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Devicetree file with miscellaneous nodes that will be included
- at build time into the DTB. Currently being used for including
- capsule related information.
- */
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/ { +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
signature {
capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE);
};
+#endif +}; +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..1326a1d109 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -234,6 +234,17 @@ config EFI_CAPSULE_MAX Select the max capsule index value used for capsule report variables. This value is used to create CapsuleMax variable.
+config EFI_CAPSULE_ESL_FILE
string "Path to the EFI Signature List File"
default ""
depends on EFI_CAPSULE_AUTHENTICATE
help
Provides the absolute path to the EFI Signature List
file which will be embedded in the platform's device
tree and used for capsule authentication at the time
of capsule update.
Drop extra blank line.
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 13a35eae6c..9fb04720d9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -86,3 +86,10 @@ obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
EFI_VAR_SEED_FILE := $(subst $",,$(CONFIG_EFI_VAR_SEED_FILE)) $(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
+ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y) +EFI_CAPSULE_KEY_PATH := $(subst $",,$(CONFIG_EFI_CAPSULE_ESL_FILE)) +ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","") +$(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_ESL_FILE) +endif +endif
Regards, Simon

Update the document to specify how the EFI Signature List(ESL) file can be embedded into the platform's dtb as part of the u-boot build.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * Highlight the need to use the u-boot.dtsi file for embedding the public key ESL into the DTB.
doc/develop/uefi/uefi.rst | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index ffe25ca231..c04e62f3a5 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -495,20 +495,16 @@ and used by the steps highlighted below. ... }
-You can do step-4 manually with +You can perform step-4 by defining the Kconfig symbol +CONFIG_EFI_CAPSULE_ESL_FILE. Once this has been done, the signature +node can be added to the u-boot.dtsi file. For reference, check the +u-boot.dtsi file for the sandbox architecture. If this node has not +been added to the architecture's u-boot.dtsi file, this needs to be +done. The node has currently been added for the sandbox and arm +architectures' in the u-boot.dtsi file. Once the u-boot.dtsi file has +been added with the signature node, the esl file will automatically +get embedded into the platform's dtb as part of u-boot build.
-.. code-block:: console - - $ dtc -@ -I dts -O dtb -o signature.dtbo signature.dts - $ fdtoverlay -i orig.dtb -o new.dtb -v signature.dtbo - -where signature.dts looks like:: - - &{/} { - signature { - capsule-key = /incbin/("CRT.esl"); - }; - };
Executing the boot manager ~~~~~~~~~~~~~~~~~~~~~~~~~~

On Sun, 9 Jul 2023 at 07:33, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Update the document to specify how the EFI Signature List(ESL) file can be embedded into the platform's dtb as part of the u-boot build.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- Highlight the need to use the u-boot.dtsi file for embedding the public key ESL into the DTB.
doc/develop/uefi/uefi.rst | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Add support for specifying the parameters needed for capsule generation through a config file, instead of passing them through command-line. Parameters for more than a single capsule file can be specified, resulting in generation of multiple capsules through a single invocation of the command.
This path is to be used for generating capsules through a make target, with the parameters being parsed from the config file.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * Add a Kconfig boolean symbol CONFIG_EFI_USE_CAPSULE_CFG_FILE which can be used to generate capsules through config file or parameters.
tools/Kconfig | 16 ++ tools/Makefile | 1 + tools/eficapsule.h | 110 ++++++++++++ tools/mkeficapsule.c | 84 +++++---- tools/mkeficapsule_parse.c | 345 +++++++++++++++++++++++++++++++++++++ 5 files changed, 526 insertions(+), 30 deletions(-) create mode 100644 tools/mkeficapsule_parse.c
diff --git a/tools/Kconfig b/tools/Kconfig index 539708f277..9b744aba31 100644 --- a/tools/Kconfig +++ b/tools/Kconfig @@ -98,6 +98,22 @@ config TOOLS_MKEFICAPSULE optionally sign that file. If you want to enable UEFI capsule update feature on your target, you certainly need this.
+config EFI_CAPSULE_CFG_FILE + string "Path to the EFI Capsule Config File" + default "" + help + Path to the EFI capsule config file which provides the + parameters needed to build capsule(s). Parameters can be + provided for multiple payloads resulting in corresponding + capsule images being generated. + +config EFI_USE_CAPSULE_CFG_FILE + bool "Use the config file for generating capsules" + help + Boolean option used to specify if the EFI capsules are to + be generated through parameters specified via the config + file or through command line. + menuconfig FSPI_CONF_HEADER bool "FlexSPI Header Configuration" help diff --git a/tools/Makefile b/tools/Makefile index d793cf3bec..ef366f3d61 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -250,6 +250,7 @@ HOSTLDLIBS_mkeficapsule += \ HOSTLDLIBS_mkeficapsule += \ $(shell pkg-config --libs uuid 2> /dev/null || echo "-luuid") hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule +mkeficapsule-objs := mkeficapsule.o mkeficapsule_parse.o
# 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 diff --git a/tools/eficapsule.h b/tools/eficapsule.h index 072a4b5598..42e66c6d6a 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -52,6 +52,38 @@ typedef struct { /* flags */ #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+enum capsule_type { + CAPSULE_NORMAL_BLOB = 0, + CAPSULE_ACCEPT, + CAPSULE_REVERT, +}; + +/** + * struct efi_capsule_params - Capsule parameters + * @image_guid: Guid value of the payload input image + * @image_index: Image index value + * @hardware_instance: Hardware instance to be used for the image + * @monotonic_count: Monotonic count value to be used for signed capsule + * @privkey_file: Path to private key used in capsule signing + * @cert_file: Path to public key certificate used in capsule signing + * @input_file: Path to payload input image + * @capsule_file: Path to the output capsule file + * @oemflags: Oemflags to be populated in the capsule header + * @capsule: Capsule Type, normal or accept or revert + */ +struct efi_capsule_params { + efi_guid_t *image_guid; + unsigned long image_index; + unsigned long hardware_instance; + uint64_t monotonic_count; + char *privkey_file; + char *cert_file; + char *input_file; + char *capsule_file; + unsigned long oemflags; + enum capsule_type capsule; +}; + struct efi_capsule_header { efi_guid_t capsule_guid; uint32_t header_size; @@ -113,4 +145,82 @@ struct efi_firmware_image_authentication { struct win_certificate_uefi_guid auth_info; } __packed;
+/** + * capsule_with_cfg_file() - Generate capsule from config file + * @cfg_file: Path to the config file + * + * Parse the capsule parameters from the config file and use the + * parameters for generating one or more capsules. + * + * Return: None + * + */ +void capsule_with_cfg_file(const char *cfg_file); + +/** + * convert_uuid_to_guid() - convert UUID to GUID + * @buf: UUID binary + * + * UUID and GUID have the same data structure, but their binary + * formats are different due to the endianness. See lib/uuid.c. + * Since uuid_parse() can handle only UUID, this function must + * be called to get correct data for GUID when parsing a string. + * + * The correct data will be returned in @buf. + */ +void convert_uuid_to_guid(unsigned char *buf); + +/** + * create_empty_capsule() - Generate an empty capsule + * @path: Path to the empty capsule file to be generated + * @guid: Guid value of the image for which empty capsule is generated + * @fw_accept: Flag to specify whether to generate accept or revert capsule + * + * Generate an empty capsule, either an accept or a revert capsule to be + * used to flag acceptance or rejection of an earlier executed firmware + * update operation. Being used in the FWU Multi Bank firmware update + * feature. + * + * Return: 0 if OK, -ve on error + * + */ +int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept); + +/** + * create_fwbin - create an uefi capsule file + * @path: Path to a created capsule file + * @bin: Path to a firmware binary to encapsulate + * @guid: GUID of related FMP driver + * @index: Index number in capsule + * @instance: Instance number in capsule + * @mcount: Monotonic count in authentication information + * @private_file: Path to a private key file + * @cert_file: Path to a certificate file + * @oemflags: Capsule OEM Flags, bits 0-15 + * + * This function actually does the job of creating an uefi capsule file. + * All the arguments must be supplied. + * If either @private_file ror @cert_file is NULL, the capsule file + * won't be signed. + * + * Return: + * * 0 - on success + * * -1 - on failure + */ +int create_fwbin(char *path, char *bin, efi_guid_t *guid, + unsigned long index, unsigned long instance, + uint64_t mcount, char *privkey_file, char *cert_file, + uint16_t oemflags); + +/** + * print_usage() - Print the command usage string + * + * Prints the standard command usage string. Called in the case + * of incorrect parameters being passed to the tool. + * + * Return: None + * + */ +void print_usage(void); + #endif /* _EFI_CAPSULE_H */ diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index b71537beee..522dc4b474 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,13 +29,7 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
-static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR"; - -enum { - CAPSULE_NORMAL_BLOB = 0, - CAPSULE_ACCEPT, - CAPSULE_REVERT, -} capsule_type; +static const char *opts_short = "g:i:I:v:p:c:m:o:f:dhAR";
static struct option options[] = { {"guid", required_argument, NULL, 'g'}, @@ -48,11 +42,21 @@ static struct option options[] = { {"fw-accept", no_argument, NULL, 'A'}, {"fw-revert", no_argument, NULL, 'R'}, {"capoemflag", required_argument, NULL, 'o'}, + {"cfg-file", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, };
-static void print_usage(void) +/** + * print_usage() - Print the command usage string + * + * Prints the standard command usage string. Called in the case + * of incorrect parameters being passed to the tool. + * + * Return: None + * + */ +void print_usage(void) { fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n" "Options:\n" @@ -67,6 +71,7 @@ static void print_usage(void) "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n" "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n" "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n" + "\t-f, --cfg-file <config file> config file with capsule parameters\n" "\t-h, --help print a help message\n", tool_name); } @@ -400,10 +405,10 @@ static void free_sig_data(struct auth_context *ctx) * * 0 - on success * * -1 - on failure */ -static int create_fwbin(char *path, char *bin, efi_guid_t *guid, - unsigned long index, unsigned long instance, - uint64_t mcount, char *privkey_file, char *cert_file, - uint16_t oemflags) +int create_fwbin(char *path, char *bin, efi_guid_t *guid, + unsigned long index, unsigned long instance, + uint64_t mcount, char *privkey_file, char *cert_file, + uint16_t oemflags) { struct efi_capsule_header header; struct efi_firmware_management_capsule_header capsule; @@ -580,7 +585,21 @@ void convert_uuid_to_guid(unsigned char *buf) buf[7] = c; }
-static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept) +/** + * create_empty_capsule() - Generate an empty capsule + * @path: Path to the empty capsule file to be generated + * @guid: Guid value of the image for which empty capsule is generated + * @fw_accept: Flag to specify whether to generate accept or revert capsule + * + * Generate an empty capsule, either an accept or a revert capsule to be + * used to flag acceptance or rejection of an earlier executed firmware + * update operation. Being used in the FWU Multi Bank firmware update + * feature. + * + * Return: 0 if OK, -ve on error + * + */ +int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept) { struct efi_capsule_header header = { 0 }; FILE *f = NULL; @@ -643,6 +662,8 @@ int main(int argc, char **argv) uint64_t mcount; unsigned long oemflags; char *privkey_file, *cert_file; + char *cfg_file; + enum capsule_type capsule; int c, idx;
guid = NULL; @@ -651,8 +672,9 @@ int main(int argc, char **argv) mcount = 0; privkey_file = NULL; cert_file = NULL; + cfg_file = NULL; dump_sig = 0; - capsule_type = CAPSULE_NORMAL_BLOB; + capsule = CAPSULE_NORMAL_BLOB; oemflags = 0; for (;;) { c = getopt_long(argc, argv, opts_short, options, &idx); @@ -702,20 +724,20 @@ int main(int argc, char **argv) dump_sig = 1; break; case 'A': - if (capsule_type) { + if (capsule) { fprintf(stderr, "Select either of Accept or Revert capsule generation\n"); exit(1); } - capsule_type = CAPSULE_ACCEPT; + capsule = CAPSULE_ACCEPT; break; case 'R': - if (capsule_type) { + if (capsule) { fprintf(stderr, "Select either of Accept or Revert capsule generation\n"); exit(1); } - capsule_type = CAPSULE_REVERT; + capsule = CAPSULE_REVERT; break; case 'o': oemflags = strtoul(optarg, NULL, 0); @@ -725,6 +747,10 @@ int main(int argc, char **argv) exit(1); } break; + case 'f': + cfg_file = optarg; + capsule_with_cfg_file(cfg_file); + exit(EXIT_SUCCESS); default: print_usage(); exit(EXIT_SUCCESS); @@ -732,21 +758,21 @@ int main(int argc, char **argv) }
/* check necessary parameters */ - if ((capsule_type == CAPSULE_NORMAL_BLOB && - ((argc != optind + 2) || !guid || - ((privkey_file && !cert_file) || - (!privkey_file && cert_file)))) || - (capsule_type != CAPSULE_NORMAL_BLOB && - ((argc != optind + 1) || - ((capsule_type == CAPSULE_ACCEPT) && !guid) || - ((capsule_type == CAPSULE_REVERT) && guid)))) { + if ((capsule == CAPSULE_NORMAL_BLOB && + ((argc != optind + 2) || !guid || + ((privkey_file && !cert_file) || + (!privkey_file && cert_file)))) || + (capsule != CAPSULE_NORMAL_BLOB && + ((argc != optind + 1) || + (capsule == CAPSULE_ACCEPT && !guid) || + (capsule == CAPSULE_REVERT && guid)))) { print_usage(); exit(EXIT_FAILURE); }
- if (capsule_type != CAPSULE_NORMAL_BLOB) { + if (capsule != CAPSULE_NORMAL_BLOB) { if (create_empty_capsule(argv[argc - 1], guid, - capsule_type == CAPSULE_ACCEPT) < 0) { + capsule == CAPSULE_ACCEPT) < 0) { fprintf(stderr, "Creating empty capsule failed\n"); exit(EXIT_FAILURE); } @@ -756,6 +782,4 @@ int main(int argc, char **argv) fprintf(stderr, "Creating firmware capsule failed\n"); exit(EXIT_FAILURE); } - - exit(EXIT_SUCCESS); } diff --git a/tools/mkeficapsule_parse.c b/tools/mkeficapsule_parse.c new file mode 100644 index 0000000000..ef4f3f6705 --- /dev/null +++ b/tools/mkeficapsule_parse.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2023 Linaro Limited + */ + +/* + * The code in this file adds parsing ability to the mkeficapsule + * tool. This allows specifying parameters needed to build the capsule + * through the config file instead of specifying them on the command-line. + * Parameters can be specified for more than one payload, generating the + * corresponding capsule files. + * + * The parameters are specified in a "key:value" pair. All the parameters + * that are currently supported by the mkeficapsule tool can be specified + * in the config file. + * + * The example below shows four payloads. The first payload is an example + * of generating a signed capsule. The second payload is an example of + * generating an unsigned capsule. The third payload is an accept empty + * capsule, while the fourth payload is the revert empty capsule, used + * for the multi-bank firmware update feature. + * + * This functionality can be easily extended to generate a single capsule + * comprising multiple payloads. + + { + image-guid: 02f4d760-cfd5-43bd-8e2d-a42acb33c660 + hardware-instance: 0 + monotonic-count: 1 + payload: u-boot.bin + image-index: 1 + private-key: /path/to/priv/key + pub-key-cert: /path/to/pub/key + capsule: u-boot.capsule + } + { + image-guid: 4ce292da-1dd8-428d-a1c2-77743ef8b96e + hardware-instance: 0 + payload: u-boot.itb + image-index: 2 + oemflags: 0x8000 + capsule: fit.capsule + } + { + capsule-type: accept + image-guid: 4ce292da-1dd8-428d-a1c2-77743ef8b96e + capsule: accept.capsule + } + { + capsule-type: revert + capsule: revert.capsule + } +*/ + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <uuid/uuid.h> + +#include "eficapsule.h" + +#define PARAMS_START "{" +#define PARAMS_END "}" + +#define PSTART 2 +#define PEND 3 + +#define MALLOC_FAIL_STR "Unable to allocate memory\n" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +const char *capsule_params[] = { + "image-guid", "image-index", "private-key", + "pub-key-cert", "payload", "capsule", + "hardware-instance", "monotonic-count", + "capsule-type", "oemflags" }; + +static unsigned char params_start; +static unsigned char params_end; + +static void print_and_exit(const char *str) +{ + fprintf(stderr, "%s", str); + exit(EXIT_FAILURE); +} + +static int param_delim_checks(char *line, unsigned char *token) +{ + if (!strcmp(line, PARAMS_START)) { + if (params_start || !params_end) { + fprintf(stderr, "Earlier params processing still in progress. "); + fprintf(stderr, "Can't start processing a new params.\n"); + exit(EXIT_FAILURE); + } else { + params_start = 1; + params_end = 0; + *token = PSTART; + return 1; + } + } else if (!strcmp(line, PARAMS_END)) { + if (!params_start) { + fprintf(stderr, "Cannot put end braces without start braces. "); + fprintf(stderr, "Please check the documentation for reference config file syntax\n"); + exit(EXIT_FAILURE); + } else { + params_start = 0; + params_end = 1; + *token = PEND; + return 1; + } + } else if (!params_start) { + fprintf(stderr, "Params should be passed within braces. "); + fprintf(stderr, "Please check the documentation for reference config file syntax\n"); + exit(EXIT_FAILURE); + } + + return 0; +} + +static void add_guid(efi_guid_t **guid_param, char *guid) +{ + unsigned char uuid_buf[16]; + + *guid_param = malloc(sizeof(efi_guid_t)); + if (!*guid_param) + print_and_exit(MALLOC_FAIL_STR); + + if (uuid_parse(guid, uuid_buf)) + print_and_exit("Wrong guid format\n"); + + convert_uuid_to_guid(uuid_buf); + memcpy(*guid_param, uuid_buf, sizeof(efi_guid_t)); +} + +static void add_string(char **dst, char *val) +{ + *dst = strdup(val); + if (!*dst) + print_and_exit(MALLOC_FAIL_STR); +} + +static void match_and_populate_param(char *key, char *val, + struct efi_capsule_params *param) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(capsule_params); i++) { + if (!strcmp(key, capsule_params[i])) { + switch (i) { + case 0: + add_guid(¶m->image_guid, val); + return; + case 1: + param->image_index = strtoul(val, NULL, 0); + if (param->image_index == ULONG_MAX) + print_and_exit("Enter a valid value of index bewtween 1-255"); + return; + case 2: + add_string(¶m->privkey_file, val); + return; + case 3: + add_string(¶m->cert_file, val); + return; + case 4: + add_string(¶m->input_file, val); + return; + case 5: + add_string(¶m->capsule_file, val); + return; + case 6: + param->hardware_instance = strtoul(val, NULL, 0); + if (param->hardware_instance == ULONG_MAX) + print_and_exit("Enter a valid hardware instance value"); + return; + case 7: + param->monotonic_count = strtoull(val, NULL, 0); + if (param->monotonic_count == ULLONG_MAX) + print_and_exit("Enter a valid monotonic count value"); + return; + case 8: + if (!strcmp(val, "normal")) + param->capsule = CAPSULE_NORMAL_BLOB; + else if (!strcmp(val, "accept")) + param->capsule = CAPSULE_ACCEPT; + else if (!strcmp(val, "revert")) + param->capsule = CAPSULE_REVERT; + else + print_and_exit("Invalid type of capsule"); + + return; + case 9: + param->oemflags = strtoul(val, NULL, 0); + if (param->oemflags > 0xffff) + print_and_exit("OemFlags must be between 0x0 and 0xffff\n"); + return; + } + } + } + + fprintf(stderr, "Undefined param %s specified. ", key); + fprintf(stderr, "Please check the documentation for reference config file syntax\n"); + exit(EXIT_FAILURE); +} + +static int get_capsule_params(char *line, struct efi_capsule_params *params) +{ + char *key = NULL; + char *val = NULL; + unsigned char token; + + if (param_delim_checks(line, &token)) + return token; + + key = strtok(line, ":"); + if (key) + val = strtok(NULL, "\0"); + else + print_and_exit("Expect the params in a key:value pair\n"); + + match_and_populate_param(key, val, params); + + return 0; +} + +static char *skip_whitespace(char *line) +{ + char *ptr, *newline; + + ptr = malloc(strlen(line) + 1); + if (!ptr) + print_and_exit(MALLOC_FAIL_STR); + + for (newline = ptr; *line; line++) + if (!isblank(*line)) + *ptr++ = *line; + *ptr = '\0'; + return newline; +} + +static int parse_capsule_payload_params(FILE *fp, struct efi_capsule_params *params) +{ + char *line = NULL; + char *newline; + size_t n = 0; + ssize_t len; + + while ((len = getline(&line, &n, fp)) != -1) { + if (len == 1 && line[len - 1] == '\n') + continue; + + line[len - 1] = '\0'; + + newline = skip_whitespace(line); + + if (newline[0] == '#') + continue; + + if (get_capsule_params(newline, params) == PEND) + return 0; + } + + if (errno == EINVAL || errno == ENOMEM) { + fprintf(stderr, "getline() returned an error %s reading the line\n", + strerror(errno)); + exit(EXIT_FAILURE); + } else if (params_start == 1 || params_end == 0) { + fprintf(stderr, "Params should be passed within braces. "); + fprintf(stderr, "Please check the documentation for reference config file syntax\n"); + exit(EXIT_FAILURE); + } else { + return -1; + } +} + +static void params_dependency_check(struct efi_capsule_params *params) +{ + /* check necessary parameters */ + if ((params->capsule == CAPSULE_NORMAL_BLOB && + ((!params->input_file || !params->capsule_file || + !params->image_guid) || + ((params->privkey_file && !params->cert_file) || + (!params->privkey_file && params->cert_file)))) || + (params->capsule != CAPSULE_NORMAL_BLOB && + (!params->capsule_file || + (params->capsule == CAPSULE_ACCEPT && !params->image_guid) || + (params->capsule == CAPSULE_REVERT && params->image_guid)))) { + print_usage(); + exit(EXIT_FAILURE); + } +} + +static void generate_capsule(struct efi_capsule_params *params) +{ + if (params->capsule != CAPSULE_NORMAL_BLOB) { + if (create_empty_capsule(params->capsule_file, + params->image_guid, + params->capsule == + CAPSULE_ACCEPT) < 0) + print_and_exit("Creating empty capsule failed\n"); + } else if (create_fwbin(params->capsule_file, params->input_file, + params->image_guid, params->image_index, + params->hardware_instance, + params->monotonic_count, + params->privkey_file, + params->cert_file, + (uint16_t)params->oemflags) < 0) { + print_and_exit("Creating firmware capsule failed\n"); + } +} + +/** + * capsule_with_cfg_file() - Generate capsule from config file + * @cfg_file: Path to the config file + * + * Parse the capsule parameters from the config file and use the + * parameters for generating one or more capsules. + * + * Return: None + * + */ +void capsule_with_cfg_file(const char *cfg_file) +{ + FILE *fp; + struct efi_capsule_params params = { 0 }; + + fp = fopen(cfg_file, "r"); + if (!fp) { + fprintf(stderr, "Unable to open the capsule config file %s\n", + cfg_file); + exit(EXIT_FAILURE); + } + + params_start = 0; + params_end = 1; + + while (parse_capsule_payload_params(fp, ¶ms) != -1) { + params_dependency_check(¶ms); + generate_capsule(¶ms); + + memset(¶ms, 0, sizeof(struct efi_capsule_params)); + } +}

The UEFI capsule can be generated either through command-line parameters, or, by specifying those in a config file. Add documentation to describe the format of the config file.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: None
doc/develop/uefi/uefi.rst | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index c04e62f3a5..ddf8e20cb0 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -442,6 +442,70 @@ following command can be issued --guid c1b629f1-ce0e-4894-82bf-f0a38387e630 \ optee.bin optee.capsule
+Or alternatively, the capsule can be generated through a make target + +.. code-block:: bash + + $ make capsule + +Issuing the above make command requires specifying the capsule +parameters through a config file instead. The Kconfig symbol +CONFIG_EFI_CAPSULE_CFG_FILE is to be used for specifying the path to +the config file. + +The config file describes the parameters that are used for generating +one or more capsules. The parameters for a given capsule file are +specified within curly braces, in the form of "key:value" pairs. All +the parameters that are currently supported by the mkeficapsule tool +can be specified through the config file. + +The following are some example payload parameters specified through +the config file. + +.. code-block:: none + + { + image-guid: 02f4d760-cfd5-43bd-8e2d-a42acb33c660 + hardware-instance: 0 + monotonic-count: 1 + payload: u-boot.bin + image-index: 1 + private-key: /path/to/priv/key + pub-key-cert: /path/to/pub/key + capsule: u-boot.capsule + } + { + image-guid: 4ce292da-1dd8-428d-a1c2-77743ef8b96e + hardware-instance: 0 + payload: u-boot.itb + image-index: 2 + oemflags: 0x8000 + capsule: fit.capsule + } + { + capsule-type: accept + image-guid: 4ce292da-1dd8-428d-a1c2-77743ef8b96e + capsule: accept.capsule + } + { + capsule-type: revert + capsule: revert.capsule + } + +The following are the keys that specify the capsule parameters + +..code-block:: none + + image-guid: Image GUID + image-index: Image index value + private-key: Path to the private key file used for capsule signing + pub-key-cert: Path to the public key crt file used for capsule signing + payload: Path to the capsule payload file + capsule: Path to the output capsule file that is generated + hardware-instance: Hardware Instance value + monotonic-count: Monotonic count value + capsule-type: Specifies capsule type. normal(default), accept or revert + oemflags: 16bit Oemflags value to be used(populated in capsule header)
Enabling Capsule Authentication *******************************

Add support in binman for generating capsules. The capsule parameters can be specified either through a config file or through the capsule binman entry.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch which generates capsules through binman replacing the earlier make target.
tools/binman/btool/mkeficapsule.py | 91 +++++++++++++++++++++++++ tools/binman/entries.rst | 27 ++++++++ tools/binman/etype/capsule.py | 102 +++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 tools/binman/btool/mkeficapsule.py create mode 100644 tools/binman/etype/capsule.py
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py new file mode 100644 index 0000000000..9f656c12cf --- /dev/null +++ b/tools/binman/btool/mkeficapsule.py @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Linaro Limited +# +"""Bintool implementation for mkeficapsule tool + +mkeficapsule is a tool used for generating EFI capsules. + +The following are the command-line options to be provided +to the tool +Usage: mkeficapsule [options] <image blob> <output file> +Options: + -g, --guid <guid string> guid for image blob type + -i, --index <index> update image index + -I, --instance <instance> update hardware instance + -p, --private-key <privkey file> private key file + -c, --certificate <cert file> signer's certificate file + -m, --monotonic-count <count> monotonic count + -d, --dump_sig dump signature (*.p7) + -A, --fw-accept firmware accept capsule, requires GUID, no image blob + -R, --fw-revert firmware revert capsule, takes no GUID, no image blob + -o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff + -f, --cfg-file <config file> config file with capsule parameters + -h, --help print a help message + +""" + +from binman import bintool + +class Bintoolmkeficapsule(bintool.Bintool): + """Handles the 'mkeficapsule' tool + + This bintool is used for generating the EFI capsules. The + capsule generation parameters can either be specified through + command-line, or through a config file. + + """ + def __init__(self, name): + super().__init__(name, 'mkeficapsule tool for generating capsules') + + def capsule_cfg_file(self, cfg_file): + + args = [ + f'--cfg-file={cfg_file}' + ] + self.run_cmd(*args) + + def cmdline_capsule(self, image_index, image_guid, hardware_instance, + payload, output_fname): + + args = [ + f'--index={image_index}', + f'--guid={image_guid}', + f'--instance={hardware_instance}', + payload, + output_fname + ] + self.run_cmd(*args) + + def cmdline_auth_capsule(self, image_index, image_guid, hardware_instance, + monotonic_count, priv_key, pub_key, + payload, output_fname): + + args = [ + f'--index={image_index}', + f'--guid={image_guid}', + f'--instance={hardware_instance}', + f'--monotonic-count={monotonic_count}', + f'--private-key={priv_key}', + f'--certificate={pub_key}', + payload, + output_fname + ] + self.run_cmd(*args) + + def fetch(self, method): + """Fetch handler for mkeficapsule + + This builds the tool from source + + Returns: + tuple: + str: Filename of fetched file to copy to a suitable directory + str: Name of temp directory to remove, or None + """ + if method != bintool.FETCH_BUILD: + return None + result = self.build_from_git( + 'https://source.denx.de/u-boot/u-boot.git', + 'tools', + 'tools/mkeficapsule') + return result diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index b71af801fd..9a263e8691 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -283,6 +283,33 @@ entry; similarly for SPL.
+.. _etype_capsule: + +Entry: capsule: Entry for generating EFI Capsule files +------------------------------------------------------ + +This is an entry for generating EFI capsules. + +The parameters needed for generation of the capsules can either be +provided separately, or through a config file. + +Properties / Entry arguments: + - cfg-file: Config file for providing capsule + parameters. + - image-index: Unique number for identifying + corresponding payload image. + - image-type-id: Image GUID which will be used + for identifying the image. + - hardware-instance: Optional number for identifying + unique hardware instance of a device in the system. + - monotomic-count: Count used when signing an image. + - private-key: Path to private key file. + - pub-key-cert: Path to public key certificate file. + - filename: Path to the input(payload) file. + - capsule: Path to the output capsule file. + + + .. _etype_cbfs:
Entry: cbfs: Coreboot Filesystem (CBFS) diff --git a/tools/binman/etype/capsule.py b/tools/binman/etype/capsule.py new file mode 100644 index 0000000000..a5ada885a6 --- /dev/null +++ b/tools/binman/etype/capsule.py @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Linaro Limited +# +# Entry-type module for producing a capsule +# + +import os +from u_boot_pylib import tools +from dtoc import fdt_util +from binman.entry import Entry + +class Entry_capsule(Entry): + """Entry for generating EFI capsules + + This is an entry for generating EFI capsules. + + The parameters needed for generation of the capsules can + either be provided separately, or through a config file. + + Properties / Entry arguments: + - cfg-file: Config file for providing capsule + parameters. + - image-index: Unique number for identifying + corresponding payload image. + - image-type-id: Image GUID which will be used + for identifying the image. + - hardware-instance: Optional number for identifying + unique hardware instance of a device in the system. + - monotomic-count: Count used when signing an image. + - private-key: Path to private key file. + - pub-key-cert: Path to public key certificate file. + - filename: Path to the input(payload) file. + - capsule: Path to the output capsule file. + + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self.image_index = 0 + self.image_guid = "" + self.hardware_instance = 0 + self.monotonic_count = 0 + self.private_key = "" + self.pub_key_cert = "" + self.auth = 0 + self.payload = "" + self.capsule_fname = "" + + def ReadNode(self): + super().ReadNode() + + self.cfg_file = fdt_util.GetString(self._node, 'cfg-file') + if not self.cfg_file: + self.image_index = fdt_util.GetInt(self._node, 'image-index') + if not self.image_index: + self.Raise('mkeficapsule must be provided an Image Index') + + self.image_guid = fdt_util.GetString(self._node, 'image-type-id') + if not self.image_guid: + self.Raise('mkeficapsule must be provided an Image GUID') + + self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance') + self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count') + + self.private_key = fdt_util.GetString(self._node, 'private-key') + self.pub_key_cert = fdt_util.GetString(self._node, 'pub-key-cert') + + if ((self.private_key and not self.pub_key_cert) or (self.pub_key_cert and not self.private_key)): + self.Raise('Both private-key and public key Certificate need to be provided') + elif not (self.private_key and self.pub_key_cert): + self.auth = 0 + else: + self.auth = 1 + + self.payload = fdt_util.GetString(self._node, 'filename') + if not self.payload: + self.Raise('mkeficapsule must be provided an input filename(payload)') + + self.capsule_fname = fdt_util.GetString(self._node, 'capsule') + if not self.capsule_fname: + self.capsule_fname = os.path.splitext(self.payload)[0] + '.capsule' + + def ObtainContents(self): + if self.cfg_file: + self.mkeficapsule.capsule_cfg_file(self.cfg_file) + elif self.auth: + self.mkeficapsule.cmdline_auth_capsule(self.image_index, + self.image_guid, + self.hardware_instance, + self.monotonic_count, + self.private_key, + self.pub_key_cert, + self.payload, + self.capsule_fname) + else: + self.mkeficapsule.cmdline_capsule(self.image_index, + self.image_guid, + self.hardware_instance, + self.payload, + self.capsule_fname) + + def AddBintools(self, btools): + self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')

Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Add support in binman for generating capsules. The capsule parameters can be specified either through a config file or through the capsule binman entry.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch which generates capsules through binman replacing the earlier make target.
tools/binman/btool/mkeficapsule.py | 91 +++++++++++++++++++++++++ tools/binman/entries.rst | 27 ++++++++ tools/binman/etype/capsule.py | 102 +++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 tools/binman/btool/mkeficapsule.py create mode 100644 tools/binman/etype/capsule.py
Please do check test coverage (binman test -T). You are missing quite a lot in two two files you have added.
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py new file mode 100644 index 0000000000..9f656c12cf --- /dev/null +++ b/tools/binman/btool/mkeficapsule.py @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Linaro Limited +# +"""Bintool implementation for mkeficapsule tool
+mkeficapsule is a tool used for generating EFI capsules.
+The following are the command-line options to be provided +to the tool +Usage: mkeficapsule [options] <image blob> <output file> +Options:
-g, --guid <guid string> guid for image blob type
-i, --index <index> update image index
-I, --instance <instance> update hardware instance
-p, --private-key <privkey file> private key file
-c, --certificate <cert file> signer's certificate file
-m, --monotonic-count <count> monotonic count
-d, --dump_sig dump signature (*.p7)
-A, --fw-accept firmware accept capsule, requires GUID, no image blob
-R, --fw-revert firmware revert capsule, takes no GUID, no image blob
-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff
-f, --cfg-file <config file> config file with capsule parameters
-h, --help print a help message
+"""
+from binman import bintool
+class Bintoolmkeficapsule(bintool.Bintool):
- """Handles the 'mkeficapsule' tool
- This bintool is used for generating the EFI capsules. The
- capsule generation parameters can either be specified through
- command-line, or through a config file.
- """
- def __init__(self, name):
super().__init__(name, 'mkeficapsule tool for generating capsules')
- def capsule_cfg_file(self, cfg_file):
"""Function comment
Args: cfg_file (str): ... """
Please fix throughout
args = [
f'--cfg-file={cfg_file}'
]
self.run_cmd(*args)
- def cmdline_capsule(self, image_index, image_guid, hardware_instance,
payload, output_fname):
args = [
f'--index={image_index}',
f'--guid={image_guid}',
f'--instance={hardware_instance}',
payload,
output_fname
]
self.run_cmd(*args)
- def cmdline_auth_capsule(self, image_index, image_guid, hardware_instance,
monotonic_count, priv_key, pub_key,
payload, output_fname):
args = [
f'--index={image_index}',
f'--guid={image_guid}',
f'--instance={hardware_instance}',
f'--monotonic-count={monotonic_count}',
f'--private-key={priv_key}',
f'--certificate={pub_key}',
payload,
output_fname
]
self.run_cmd(*args)
- def fetch(self, method):
"""Fetch handler for mkeficapsule
This builds the tool from source
Returns:
tuple:
str: Filename of fetched file to copy to a suitable directory
str: Name of temp directory to remove, or None
"""
if method != bintool.FETCH_BUILD:
return None
result = self.build_from_git(
'https://source.denx.de/u-boot/u-boot.git',
'tools',
'tools/mkeficapsule')
return result
Can we just install u-boot-tools? But if not, this is OK.
But it does not actually work:
$ binman tool -f mkeficapsule Fetch: mkeficapsule - trying method: binary download - trying method: build from source - clone git repo 'https://source.denx.de/u-boot/u-boot.git' to '/tmp/binmanf.chfbsxc0' - build target 'tools' Exception: Error 2 running 'make -C /tmp/binmanf.chfbsxc0 -j 64 tools': *** *** Configuration file ".config" not found! *** *** Please run some configurator (e.g. "make oldconfig" or *** "make menuconfig" or "make xconfig"). *** make[2]: *** [scripts/kconfig/Makefile:75: syncconfig] Error 1 make[1]: *** [Makefile:576: syncconfig] Error 2 make: *** No rule to make target 'include/config/auto.conf', needed by 'include/config/uboot.release'. Stop.
- failed to fetch with all methods
I think you need a make tools_defconfig in there.
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index b71af801fd..9a263e8691 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -283,6 +283,33 @@ entry; similarly for SPL.
+.. _etype_capsule:
+Entry: capsule: Entry for generating EFI Capsule files +------------------------------------------------------
+This is an entry for generating EFI capsules.
+The parameters needed for generation of the capsules can either be +provided separately, or through a config file.
+Properties / Entry arguments:
Please add more detail to answer below questions.
- cfg-file: Config file for providing capsule
parameters.
What parameters? Please provide a link
- image-index: Unique number for identifying
corresponding payload image.
Is this indexed from 0 ?
- image-type-id: Image GUID which will be used
for identifying the image.
In what way is it identifying it? Is it identifying the board that the image is for, or something else?
- hardware-instance: Optional number for identifying
unique hardware instance of a device in the system.
Is this numbered from 0?
- monotomic-count: Count used when signing an image.
monotonic
What count? What is it used for?
- private-key: Path to private key file.
File format?
- pub-key-cert: Path to public key certificate file.
File format?
- filename: Path to the input(payload) file.
This is just a binary file to be signed, right?
- capsule: Path to the output capsule file.
File format?
.. _etype_cbfs:
Entry: cbfs: Coreboot Filesystem (CBFS) diff --git a/tools/binman/etype/capsule.py b/tools/binman/etype/capsule.py new file mode 100644 index 0000000000..a5ada885a6 --- /dev/null +++ b/tools/binman/etype/capsule.py @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Linaro Limited +# +# Entry-type module for producing a capsule +#
+import os
blank line here (I think it is the convention to put a blank line after OS includes)
+from u_boot_pylib import tools +from dtoc import fdt_util +from binman.entry import Entry
We should order these in reverse. I suspect that the conversion I did from patman to u_boot_pylib was not correct, as I probably forgot to fix the order.
+class Entry_capsule(Entry):
- """Entry for generating EFI capsules
- This is an entry for generating EFI capsules.
- The parameters needed for generation of the capsules can
- either be provided separately, or through a config file.
- Properties / Entry arguments:
- cfg-file: Config file for providing capsule
parameters.
- image-index: Unique number for identifying
corresponding payload image.
- image-type-id: Image GUID which will be used
for identifying the image.
- hardware-instance: Optional number for identifying
unique hardware instance of a device in the system.
- monotomic-count: Count used when signing an image.
- private-key: Path to private key file.
- pub-key-cert: Path to public key certificate file.
- filename: Path to the input(payload) file.
- capsule: Path to the output capsule file.
copy docs from above to here, when updated
- """
- def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self.image_index = 0
self.image_guid = ""
self.hardware_instance = 0
self.monotonic_count = 0
self.private_key = ""
self.pub_key_cert = ""
self.auth = 0
self.payload = ""
self.capsule_fname = ""
- def ReadNode(self):
super().ReadNode()
self.cfg_file = fdt_util.GetString(self._node, 'cfg-file')
if not self.cfg_file:
self.image_index = fdt_util.GetInt(self._node, 'image-index')
if not self.image_index:
self.Raise('mkeficapsule must be provided an Image Index')
self.image_guid = fdt_util.GetString(self._node, 'image-type-id')
if not self.image_guid:
self.Raise('mkeficapsule must be provided an Image GUID')
You can handle this with something like this in your __init__():
self.required_props = ['image-index', 'image-type-id', ...]
Sadly the docs for required_props are wrong.
self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance')
self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count')
self.private_key = fdt_util.GetString(self._node, 'private-key')
self.pub_key_cert = fdt_util.GetString(self._node, 'pub-key-cert')
if ((self.private_key and not self.pub_key_cert) or (self.pub_key_cert and not self.private_key)):
self.Raise('Both private-key and public key Certificate need to be provided')
elif not (self.private_key and self.pub_key_cert):
self.auth = 0
else:
self.auth = 1
self.payload = fdt_util.GetString(self._node, 'filename')
if not self.payload:
self.Raise('mkeficapsule must be provided an input filename(payload)')
self.capsule_fname = fdt_util.GetString(self._node, 'capsule')
if not self.capsule_fname:
self.capsule_fname = os.path.splitext(self.payload)[0] + '.capsule'
- def ObtainContents(self):
if self.cfg_file:
self.mkeficapsule.capsule_cfg_file(self.cfg_file)
elif self.auth:
self.mkeficapsule.cmdline_auth_capsule(self.image_index,
self.image_guid,
self.hardware_instance,
self.monotonic_count,
self.private_key,
self.pub_key_cert,
self.payload,
self.capsule_fname)
else:
self.mkeficapsule.cmdline_capsule(self.image_index,
self.image_guid,
self.hardware_instance,
self.payload,
self.capsule_fname)
This does not actually obtain the contents. I think you need:
self.SetContents(...)
here.
- def AddBintools(self, btools):
self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
-- 2.34.1
Regards, Simon

hi Simon,
On Tue, 11 Jul 2023 at 03:08, Simon Glass sjg@chromium.org wrote:
Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Add support in binman for generating capsules. The capsule parameters can be specified either through a config file or through the capsule binman entry.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch which generates capsules through binman replacing the earlier make target.
tools/binman/btool/mkeficapsule.py | 91 +++++++++++++++++++++++++ tools/binman/entries.rst | 27 ++++++++ tools/binman/etype/capsule.py | 102 +++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 tools/binman/btool/mkeficapsule.py create mode 100644 tools/binman/etype/capsule.py
Please do check test coverage (binman test -T). You are missing quite a lot in two two files you have added.
I was aware of adding tests in binman, but since the capsules generated through binman are getting tested in the capsule update functionality, I thought this would be superfluous. If this is mandatory, I will add the tests. Will also address the rest of your comments for this patch.
-sughosh
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py new file mode 100644 index 0000000000..9f656c12cf --- /dev/null +++ b/tools/binman/btool/mkeficapsule.py @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Linaro Limited +# +"""Bintool implementation for mkeficapsule tool
+mkeficapsule is a tool used for generating EFI capsules.
+The following are the command-line options to be provided +to the tool +Usage: mkeficapsule [options] <image blob> <output file> +Options:
-g, --guid <guid string> guid for image blob type
-i, --index <index> update image index
-I, --instance <instance> update hardware instance
-p, --private-key <privkey file> private key file
-c, --certificate <cert file> signer's certificate file
-m, --monotonic-count <count> monotonic count
-d, --dump_sig dump signature (*.p7)
-A, --fw-accept firmware accept capsule, requires GUID, no image blob
-R, --fw-revert firmware revert capsule, takes no GUID, no image blob
-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff
-f, --cfg-file <config file> config file with capsule parameters
-h, --help print a help message
+"""
+from binman import bintool
+class Bintoolmkeficapsule(bintool.Bintool):
- """Handles the 'mkeficapsule' tool
- This bintool is used for generating the EFI capsules. The
- capsule generation parameters can either be specified through
- command-line, or through a config file.
- """
- def __init__(self, name):
super().__init__(name, 'mkeficapsule tool for generating capsules')
- def capsule_cfg_file(self, cfg_file):
"""Function comment
Args: cfg_file (str): ... """
Please fix throughout
args = [
f'--cfg-file={cfg_file}'
]
self.run_cmd(*args)
- def cmdline_capsule(self, image_index, image_guid, hardware_instance,
payload, output_fname):
args = [
f'--index={image_index}',
f'--guid={image_guid}',
f'--instance={hardware_instance}',
payload,
output_fname
]
self.run_cmd(*args)
- def cmdline_auth_capsule(self, image_index, image_guid, hardware_instance,
monotonic_count, priv_key, pub_key,
payload, output_fname):
args = [
f'--index={image_index}',
f'--guid={image_guid}',
f'--instance={hardware_instance}',
f'--monotonic-count={monotonic_count}',
f'--private-key={priv_key}',
f'--certificate={pub_key}',
payload,
output_fname
]
self.run_cmd(*args)
- def fetch(self, method):
"""Fetch handler for mkeficapsule
This builds the tool from source
Returns:
tuple:
str: Filename of fetched file to copy to a suitable directory
str: Name of temp directory to remove, or None
"""
if method != bintool.FETCH_BUILD:
return None
result = self.build_from_git(
'https://source.denx.de/u-boot/u-boot.git',
'tools',
'tools/mkeficapsule')
return result
Can we just install u-boot-tools? But if not, this is OK.
But it does not actually work:
$ binman tool -f mkeficapsule Fetch: mkeficapsule
- trying method: binary download
- trying method: build from source
- clone git repo 'https://source.denx.de/u-boot/u-boot.git' to
'/tmp/binmanf.chfbsxc0'
- build target 'tools'
Exception: Error 2 running 'make -C /tmp/binmanf.chfbsxc0 -j 64 tools': *** *** Configuration file ".config" not found!
*** Please run some configurator (e.g. "make oldconfig" or *** "make menuconfig" or "make xconfig").
make[2]: *** [scripts/kconfig/Makefile:75: syncconfig] Error 1 make[1]: *** [Makefile:576: syncconfig] Error 2 make: *** No rule to make target 'include/config/auto.conf', needed by 'include/config/uboot.release'. Stop.
- failed to fetch with all methods
I think you need a make tools_defconfig in there.
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index b71af801fd..9a263e8691 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -283,6 +283,33 @@ entry; similarly for SPL.
+.. _etype_capsule:
+Entry: capsule: Entry for generating EFI Capsule files +------------------------------------------------------
+This is an entry for generating EFI capsules.
+The parameters needed for generation of the capsules can either be +provided separately, or through a config file.
+Properties / Entry arguments:
Please add more detail to answer below questions.
- cfg-file: Config file for providing capsule
parameters.
What parameters? Please provide a link
- image-index: Unique number for identifying
corresponding payload image.
Is this indexed from 0 ?
- image-type-id: Image GUID which will be used
for identifying the image.
In what way is it identifying it? Is it identifying the board that the image is for, or something else?
- hardware-instance: Optional number for identifying
unique hardware instance of a device in the system.
Is this numbered from 0?
- monotomic-count: Count used when signing an image.
monotonic
What count? What is it used for?
- private-key: Path to private key file.
File format?
- pub-key-cert: Path to public key certificate file.
File format?
- filename: Path to the input(payload) file.
This is just a binary file to be signed, right?
- capsule: Path to the output capsule file.
File format?
.. _etype_cbfs:
Entry: cbfs: Coreboot Filesystem (CBFS) diff --git a/tools/binman/etype/capsule.py b/tools/binman/etype/capsule.py new file mode 100644 index 0000000000..a5ada885a6 --- /dev/null +++ b/tools/binman/etype/capsule.py @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Linaro Limited +# +# Entry-type module for producing a capsule +#
+import os
blank line here (I think it is the convention to put a blank line after OS includes)
+from u_boot_pylib import tools +from dtoc import fdt_util +from binman.entry import Entry
We should order these in reverse. I suspect that the conversion I did from patman to u_boot_pylib was not correct, as I probably forgot to fix the order.
+class Entry_capsule(Entry):
- """Entry for generating EFI capsules
- This is an entry for generating EFI capsules.
- The parameters needed for generation of the capsules can
- either be provided separately, or through a config file.
- Properties / Entry arguments:
- cfg-file: Config file for providing capsule
parameters.
- image-index: Unique number for identifying
corresponding payload image.
- image-type-id: Image GUID which will be used
for identifying the image.
- hardware-instance: Optional number for identifying
unique hardware instance of a device in the system.
- monotomic-count: Count used when signing an image.
- private-key: Path to private key file.
- pub-key-cert: Path to public key certificate file.
- filename: Path to the input(payload) file.
- capsule: Path to the output capsule file.
copy docs from above to here, when updated
- """
- def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self.image_index = 0
self.image_guid = ""
self.hardware_instance = 0
self.monotonic_count = 0
self.private_key = ""
self.pub_key_cert = ""
self.auth = 0
self.payload = ""
self.capsule_fname = ""
- def ReadNode(self):
super().ReadNode()
self.cfg_file = fdt_util.GetString(self._node, 'cfg-file')
if not self.cfg_file:
self.image_index = fdt_util.GetInt(self._node, 'image-index')
if not self.image_index:
self.Raise('mkeficapsule must be provided an Image Index')
self.image_guid = fdt_util.GetString(self._node, 'image-type-id')
if not self.image_guid:
self.Raise('mkeficapsule must be provided an Image GUID')
You can handle this with something like this in your __init__():
self.required_props = ['image-index', 'image-type-id', ...]
Sadly the docs for required_props are wrong.
self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance')
self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count')
self.private_key = fdt_util.GetString(self._node, 'private-key')
self.pub_key_cert = fdt_util.GetString(self._node, 'pub-key-cert')
if ((self.private_key and not self.pub_key_cert) or (self.pub_key_cert and not self.private_key)):
self.Raise('Both private-key and public key Certificate need to be provided')
elif not (self.private_key and self.pub_key_cert):
self.auth = 0
else:
self.auth = 1
self.payload = fdt_util.GetString(self._node, 'filename')
if not self.payload:
self.Raise('mkeficapsule must be provided an input filename(payload)')
self.capsule_fname = fdt_util.GetString(self._node, 'capsule')
if not self.capsule_fname:
self.capsule_fname = os.path.splitext(self.payload)[0] + '.capsule'
- def ObtainContents(self):
if self.cfg_file:
self.mkeficapsule.capsule_cfg_file(self.cfg_file)
elif self.auth:
self.mkeficapsule.cmdline_auth_capsule(self.image_index,
self.image_guid,
self.hardware_instance,
self.monotonic_count,
self.private_key,
self.pub_key_cert,
self.payload,
self.capsule_fname)
else:
self.mkeficapsule.cmdline_capsule(self.image_index,
self.image_guid,
self.hardware_instance,
self.payload,
self.capsule_fname)
This does not actually obtain the contents. I think you need:
self.SetContents(...)
here.
- def AddBintools(self, btools):
self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
-- 2.34.1
Regards, Simon

Hi Sughosh,
On Tue, 11 Jul 2023 at 01:13, Sughosh Ganu sughosh.ganu@linaro.org wrote:
hi Simon,
On Tue, 11 Jul 2023 at 03:08, Simon Glass sjg@chromium.org wrote:
Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Add support in binman for generating capsules. The capsule parameters can be specified either through a config file or through the capsule binman entry.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch which generates capsules through binman replacing the earlier make target.
tools/binman/btool/mkeficapsule.py | 91 +++++++++++++++++++++++++ tools/binman/entries.rst | 27 ++++++++ tools/binman/etype/capsule.py | 102 +++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 tools/binman/btool/mkeficapsule.py create mode 100644 tools/binman/etype/capsule.py
Please do check test coverage (binman test -T). You are missing quite a lot in two two files you have added.
I was aware of adding tests in binman, but since the capsules generated through binman are getting tested in the capsule update functionality, I thought this would be superfluous. If this is mandatory, I will add the tests. Will also address the rest of your comments for this patch.
The binman tests are for binman, which is a self-contained program with 100% test coverage. That is a very important feature, since lots of random SoC-specific features depend on it. If something breaks, it can be a bit of a disaster.
Also, 100% test coverage allows refactoring of binman's code without worry about breaking something. This is also very important, since we will find problems which the current code base cannot solve. People need the confidence to refactor
In practice, the tests define the behaviour. Code which is not tested is therefore considered 'dead' code and should be deleted.
A notable point with binman tests is that all failure modes are tested, not just 'happy path'.
[..]
Regards, Simon

Support has being added through earlier commits to build capsules and embed the public key needed for capsule authentication as part of u-boot build.
From the testing point-of-view, this means the input files needed for
generating the above have to be setup before invoking the build. Set this up in the CI configuration files for testing the capsule update feature.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch setting up the capsule files needed for CI run
.azure-pipelines.yml | 21 +++++++++++++++++++++ .gitlab-ci.yml | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 96b2ab4d75..75075bbd07 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -398,6 +398,17 @@ stages: wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.t... | tar -C /tmp -xJ; export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin; fi + mkdir -p /tmp/capsules/; + echo -n "u-boot:Old" >/tmp/capsules/u-boot.bin.old; + echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; + echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; + echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new; + if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365; + cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl; + fi + # the below corresponds to .gitlab-ci.yml "script" cd ${WORK_DIR} export UBOOT_TRAVIS_BUILD_DIR=/tmp/${TEST_PY_BD}; @@ -582,6 +593,16 @@ stages: cd ${WORK_DIR} # make environment variables available as tests are running inside a container export BUILDMAN="${BUILDMAN}" + if [[ "${BUILDMAN}" == "sandbox" ]] || [[ "${BUILDMAN}" == "sandbox x86" ]]; then + if [ ! -d "/tmp/capsules/" ]; then + mkdir -p /tmp/capsules/; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -n +odes -days 365; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt +-nodes -days 365; + cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl; + fi + fi git config --global --add safe.directory ${WORK_DIR} EOF cat << "EOF" >> build.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e6c6ab3586..577eebd678 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,6 +37,17 @@ stages: export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin; fi
+ - mkdir -p /tmp/capsules/; + - echo -n "u-boot:Old" >/tmp/capsules/u-boot.bin.old; + - echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; + - echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; + - echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new; + - if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365; + cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl; + fi + after_script: - cp -v /tmp/${TEST_PY_BD}/*.{html,css} . - rm -rf /tmp/uboot-test-hooks /tmp/venv @@ -131,6 +142,14 @@ build all other platforms: stage: world build script: - ret=0; + if [ ! -d "/tmp/capsules/" ]; then + mkdir -p /tmp/capsules/; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days + 365; + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -da +ys 365; + cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl; + fi git config --global --add safe.directory "${CI_PROJECT_DIR}"; ./tools/buildman/buildman -o /tmp -PEWM -x arm,powerpc || ret=$?; if [[ $ret -ne 0 ]]; then

Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Support has being added through earlier commits to build capsules and embed the public key needed for capsule authentication as part of u-boot build.
From the testing point-of-view, this means the input files needed for generating the above have to be setup before invoking the build. Set this up in the CI configuration files for testing the capsule update feature.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch setting up the capsule files needed for CI run
.azure-pipelines.yml | 21 +++++++++++++++++++++ .gitlab-ci.yml | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 96b2ab4d75..75075bbd07 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -398,6 +398,17 @@ stages: wget -O - https://github.com/riscv/opensbi/releases/download/v0.9/opensbi-0.9-rv-bin.t... | tar -C /tmp -xJ; export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin; fi
mkdir -p /tmp/capsules/;
echo -n "u-boot:Old" >/tmp/capsules/u-boot.bin.old;
echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new;
echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old;
echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl;
fi
Should we put these in a file instead? Or perhaps add this to the Dockerfile? It seems a shame to run this on every build...even though I see we get the opensbi on every build too...
+Tom Rini
# the below corresponds to .gitlab-ci.yml "script" cd ${WORK_DIR} export UBOOT_TRAVIS_BUILD_DIR=/tmp/${TEST_PY_BD};
@@ -582,6 +593,16 @@ stages: cd ${WORK_DIR} # make environment variables available as tests are running inside a container export BUILDMAN="${BUILDMAN}"
if [[ "${BUILDMAN}" == "sandbox" ]] || [[ "${BUILDMAN}" == "sandbox x86" ]]; then
if [ ! -d "/tmp/capsules/" ]; then
mkdir -p /tmp/capsules/;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -n
+odes -days 365;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt
+-nodes -days 365;
cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl;
fi
fi git config --global --add safe.directory ${WORK_DIR} EOF cat << "EOF" >> build.sh
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e6c6ab3586..577eebd678 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,6 +37,17 @@ stages: export OPENSBI=/tmp/opensbi-0.9-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin; fi
- mkdir -p /tmp/capsules/;
- echo -n "u-boot:Old" >/tmp/capsules/u-boot.bin.old;
- echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new;
- echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old;
- echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
- if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl;
fi
- after_script:
- cp -v /tmp/${TEST_PY_BD}/*.{html,css} .
- rm -rf /tmp/uboot-test-hooks /tmp/venv
@@ -131,6 +142,14 @@ build all other platforms: stage: world build script: - ret=0;
if [ ! -d "/tmp/capsules/" ]; then
mkdir -p /tmp/capsules/;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days
- 365;
openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -da
+ys 365;
cert-to-efi-sig-list /tmp/capsules/SIGNER.crt /tmp/capsules/SIGNER.esl;
fi git config --global --add safe.directory "${CI_PROJECT_DIR}"; ./tools/buildman/buildman -o /tmp -PEWM -x arm,powerpc || ret=$?; if [[ $ret -ne 0 ]]; then
-- 2.34.1
Regards, Simon

Support has being added through earlier commits to build capsules and embed the public key needed for capsule authentication as part of u-boot build.
From the testing point-of-view, this means the input files needed for
the above have to be setup before invoking the build. Set this up in the pytest configuration file for testing the capsule update feature.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch for setting up the capsule files in the pytest setup before initiation of u-boot build.
test/py/conftest.py | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
diff --git a/test/py/conftest.py b/test/py/conftest.py index fc9dd3a83f..661ed74fae 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -80,6 +80,89 @@ def pytest_addoption(parser): help='Run sandbox under gdbserver. The argument is the channel '+ 'over which gdbserver should communicate, e.g. localhost:1234')
+def setup_capsule_build(source_dir, build_dir, board_type, log): + """Setup the platform's build for testing capsule updates + + This generates the payload/input files needed for testing the + capsule update functionality, along with the keys for signing + the capsules. An EFI Signature List(ESL) file, which houses the + public key for capsule authentication is generated as + well. + + The ESL file is subsequently embedded into the platform's + dtb during the u-boot build, to be used for capsule + authentication. + + Two sets of keys are generated, namely SIGNER and SIGNER2. + The SIGNER2 key pair is used as a malicious key for testing the + the capsule authentication functionality. + + All the generated files are placed under the /tmp/capsules/ + directory. + + Args: + soruce_dir (str): Directory containing source code + build_dir (str): Directory to build in + board_type (str): board_type parameter (e.g. 'sandbox') + log (Logfile): Log file to use + + Returns: + Nothing. + """ + def run_command(name, cmd, source_dir): + with log.section(name): + if isinstance(cmd, str): + cmd = cmd.split() + runner = log.get_runner(name, None) + runner.run(cmd, cwd=source_dir) + runner.close() + log.status_pass('OK') + + def gen_capsule_payloads(capsule_dir): + fname = '%su-boot.bin.old' % capsule_dir + with open(fname, 'w') as fd: + fd.write('u-boot:Old') + + fname = '%su-boot.bin.new' % capsule_dir + with open(fname, 'w') as fd: + fd.write('u-boot:New') + + fname = '%su-boot.env.old' % capsule_dir + with open(fname, 'w') as fd: + fd.write('u-boot-env:Old') + + fname = '%su-boot.env.new' % capsule_dir + with open(fname, 'w') as fd: + fd.write('u-boot-env:New') + + capsule_sig_dir = '/tmp/capsules/' + sig_name = 'SIGNER' + mkdir_p(capsule_sig_dir) + name = 'openssl' + cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 ' + '-subj /CN=TEST_SIGNER/ -keyout %s%s.key ' + '-out %s%s.crt -nodes -days 365' + % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name) + ) + run_command(name, cmd, source_dir) + + name = 'cert-to-efi-sig-list' + cmd = ( 'cert-to-efi-sig-list %s%s.crt %s%s.esl' + % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name) + ) + run_command(name, cmd, source_dir) + + sig_name = 'SIGNER2' + name = 'openssl' + cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 ' + '-subj /CN=TEST_SIGNER/ -keyout %s%s.key ' + '-out %s%s.crt -nodes -days 365' + % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name) + ) + run_command(name, cmd, source_dir) + + gen_capsule_payloads(capsule_sig_dir) + def run_build(config, source_dir, build_dir, board_type, log): """run_build: Build U-Boot
@@ -90,6 +173,10 @@ def run_build(config, source_dir, build_dir, board_type, log): board_type (str): board_type parameter (e.g. 'sandbox') log (Logfile): Log file to use """ + capsule_boards = ( 'sandbox', 'sandbox64', 'sandbox_flattree' ) + if board_type in capsule_boards: + setup_capsule_build(source_dir, build_dir, board_type, log) + if config.getoption('buildman'): if build_dir != source_dir: dest_args = ['-o', build_dir, '-w']

Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Support has being added through earlier commits to build capsules and embed the public key needed for capsule authentication as part of u-boot build.
From the testing point-of-view, this means the input files needed for the above have to be setup before invoking the build. Set this up in the pytest configuration file for testing the capsule update feature.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch for setting up the capsule files in the pytest setup before initiation of u-boot build.
test/py/conftest.py | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

The embedding of the public key EFI Signature List(ESL) file into the platform's DTB is now done at the time of u-boot build. Remove this logic from the capsule update test' configuration.
Include the public key for the sandbox and sandbox_flattree variant as part of the build.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch for removing the capsule key and ESL generation logic from the capsule test config file.
configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 1 + test/py/tests/test_efi_capsule/conftest.py | 30 +++----------------- test/py/tests/test_efi_capsule/signature.dts | 10 ------- 4 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/signature.dts
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 1ec44d5b33..d8a2386bb0 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -339,6 +339,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y +CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index e7657d40dc..8d60744771 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -226,6 +226,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y +CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index a337e62936..9b0f7e635d 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -25,42 +25,20 @@ def efi_capsule_data(request, u_boot_config): image_path = u_boot_config.persistent_data_dir + '/test_efi_capsule.img'
try: + capsules_path_dir = '/tmp/capsules/' # 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) + check_call('cp %s/* %s ' % (capsules_path_dir, data_dir), shell=True)
capsule_auth_enabled = u_boot_config.buildconfig.get( 'config_efi_capsule_authenticate') if capsule_auth_enabled: - # Create private key (SIGNER.key) and certificate (SIGNER.crt) - check_call('cd %s; ' - 'openssl req -x509 -sha256 -newkey rsa:2048 ' - '-subj /CN=TEST_SIGNER/ -keyout SIGNER.key ' - '-out SIGNER.crt -nodes -days 365' - % data_dir, shell=True) - check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl' - % (data_dir, EFITOOLS_PATH), shell=True) - - # Update dtb adding capsule certificate - check_call('cd %s; ' - 'cp %s/test/py/tests/test_efi_capsule/signature.dts .' - % (data_dir, u_boot_config.source_dir), shell=True) - check_call('cd %s; ' - 'dtc -@ -I dts -O dtb -o signature.dtbo signature.dts; ' - 'fdtoverlay -i %s/arch/sandbox/dts/test.dtb ' - '-o test_sig.dtb signature.dtbo' - % (data_dir, u_boot_config.build_dir), shell=True) - - # Create *malicious* private key (SIGNER2.key) and certificate - # (SIGNER2.crt) - check_call('cd %s; ' - 'openssl req -x509 -sha256 -newkey rsa:2048 ' - '-subj /CN=TEST_SIGNER/ -keyout SIGNER2.key ' - '-out SIGNER2.crt -nodes -days 365' - % data_dir, shell=True) + check_call('cp %s/arch/sandbox/dts/test.dtb %s/test_sig.dtb' % + (u_boot_config.build_dir, data_dir), shell=True)
# Create capsule files # two regions: one for u-boot.bin and the other for u-boot.env diff --git a/test/py/tests/test_efi_capsule/signature.dts b/test/py/tests/test_efi_capsule/signature.dts deleted file mode 100644 index 078cfc76c9..0000000000 --- a/test/py/tests/test_efi_capsule/signature.dts +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/dts-v1/; -/plugin/; - -&{/} { - signature { - capsule-key = /incbin/("SIGNER.esl"); - }; -};

On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
The embedding of the public key EFI Signature List(ESL) file into the platform's DTB is now done at the time of u-boot build. Remove this logic from the capsule update test' configuration.
Include the public key for the sandbox and sandbox_flattree variant as part of the build.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch for removing the capsule key and ESL generation logic from the capsule test config file.
configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 1 + test/py/tests/test_efi_capsule/conftest.py | 30 +++----------------- test/py/tests/test_efi_capsule/signature.dts | 10 ------- 4 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/signature.dts
Reviewed-by: Simon Glass sjg@chromium.org

Support has been added to the mkeficapsule tool to generate capsules by parsing the capsule parameters through a config file. Add a config file for generating capsules. These capsules will be used for testing the capsule update feature on sandbox platform.
Enable generation of capsules through the config file on the sandbox variant.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch to add the capsule generation config file for sandbox.
.azure-pipelines.yml | 1 + .gitlab-ci.yml | 1 + configs/sandbox_defconfig | 2 + test/py/conftest.py | 5 ++ .../test_efi_capsule/sandbox_capsule_cfg.txt | 75 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 75075bbd07..cc196bf98c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -403,6 +403,7 @@ stages: echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new; + cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/; if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365; diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 577eebd678..614bf61962 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,7 @@ stages: - echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; - echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; - echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new; + - cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/; - if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d8a2386bb0..0f4c59e1a8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -340,6 +340,8 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" +CONFIG_EFI_CAPSULE_CFG_FILE="/tmp/capsules/sandbox_capsule_cfg.txt" +CONFIG_EFI_USE_CAPSULE_CFG_FILE=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y diff --git a/test/py/conftest.py b/test/py/conftest.py index 661ed74fae..f32ab1a70c 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -161,6 +161,11 @@ def setup_capsule_build(source_dir, build_dir, board_type, log): ) run_command(name, cmd, source_dir)
+ capsule_cfg_file = 'test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt' + name = 'cp' + cmd = ( ' cp %s %s' % (capsule_cfg_file, capsule_sig_dir)) + run_command(name, cmd, source_dir) + gen_capsule_payloads(capsule_sig_dir)
def run_build(config, source_dir, build_dir, board_type, log): diff --git a/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt new file mode 100644 index 0000000000..4e5065d538 --- /dev/null +++ b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt @@ -0,0 +1,75 @@ +{ + image-index: 1 + image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8 + payload: /tmp/capsules/u-boot.bin.new + capsule: /tmp/capsules/Test01 +} +{ + image-index: 2 + image-guid: 5A7021F5-FEF2-48B4-AABA-832E777418C0 + payload: /tmp/capsules/u-boot.env.new + capsule: /tmp/capsules/Test02 +} +{ + image-index: 1 + image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4 + payload: /tmp/capsules/u-boot.bin.new + capsule: /tmp/capsules/Test03 + +} +{ + image-index: 1 + image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937 + payload: /tmp/capsules/uboot_bin_env.itb + capsule: /tmp/capsules/Test04 + +} +{ + image-index: 1 + image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4 + payload: /tmp/capsules/uboot_bin_env.itb + capsule: /tmp/capsules/Test05 + +} +{ + image-index: 1 + image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4 + payload: /tmp/capsules/uboot_bin_env.itb + capsule: /tmp/capsules/Test05 +} +{ + image-index: 1 + monotonic-count: 1 + private-key: /tmp/capsules/SIGNER.key + pub-key-cert: /tmp/capsules/SIGNER.crt + image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8 + payload: /tmp/capsules/u-boot.bin.new + capsule: /tmp/capsules/Test11 +} +{ + image-index: 1 + monotonic-count: 1 + private-key: /tmp/capsules/SIGNER2.key + pub-key-cert: /tmp/capsules/SIGNER2.crt + image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8 + payload: /tmp/capsules/u-boot.bin.new + capsule: /tmp/capsules/Test12 +} +{ + image-index: 1 + monotonic-count: 1 + private-key: /tmp/capsules/SIGNER.key + pub-key-cert: /tmp/capsules/SIGNER.crt + image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937 + payload: /tmp/capsules/uboot_bin_env.itb + capsule: /tmp/capsules/Test13 +} +{ + image-index: 1 + monotonic-count: 1 + private-key: /tmp/capsules/SIGNER2.key + pub-key-cert: /tmp/capsules/SIGNER2.crt + image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937 + payload: /tmp/capsules/uboot_bin_env.itb + capsule: /tmp/capsules/Test14 +}

Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Support has been added to the mkeficapsule tool to generate capsules by parsing the capsule parameters through a config file. Add a config file for generating capsules. These capsules will be used for testing the capsule update feature on sandbox platform.
Enable generation of capsules through the config file on the sandbox variant.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch to add the capsule generation config file for sandbox.
.azure-pipelines.yml | 1 + .gitlab-ci.yml | 1 + configs/sandbox_defconfig | 2 + test/py/conftest.py | 5 ++ .../test_efi_capsule/sandbox_capsule_cfg.txt | 75 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 75075bbd07..cc196bf98c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -403,6 +403,7 @@ stages: echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/; if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 577eebd678..614bf61962 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,7 @@ stages: - echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; - echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; - echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
- cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/;
- if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d8a2386bb0..0f4c59e1a8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -340,6 +340,8 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" +CONFIG_EFI_CAPSULE_CFG_FILE="/tmp/capsules/sandbox_capsule_cfg.txt" +CONFIG_EFI_USE_CAPSULE_CFG_FILE=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y diff --git a/test/py/conftest.py b/test/py/conftest.py index 661ed74fae..f32ab1a70c 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -161,6 +161,11 @@ def setup_capsule_build(source_dir, build_dir, board_type, log): ) run_command(name, cmd, source_dir)
- capsule_cfg_file = 'test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt'
- name = 'cp'
- cmd = ( ' cp %s %s' % (capsule_cfg_file, capsule_sig_dir))
I forgot to mention this before, but you should use f strings:
cmd = f'cp {capsule_cfg_file} ...'
Please check the other files too, as it is a pain to clean it up later. You can run 'pylint' on your source to check it.
- run_command(name, cmd, source_dir)
- gen_capsule_payloads(capsule_sig_dir)
def run_build(config, source_dir, build_dir, board_type, log): diff --git a/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt new file mode 100644 index 0000000000..4e5065d538 --- /dev/null +++ b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt @@ -0,0 +1,75 @@ +{
image-index: 1
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test01
+} +{
image-index: 2
image-guid: 5A7021F5-FEF2-48B4-AABA-832E777418C0
payload: /tmp/capsules/u-boot.env.new
capsule: /tmp/capsules/Test02
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test03
+} +{
image-index: 1
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test04
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test05
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test05
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER.key
pub-key-cert: /tmp/capsules/SIGNER.crt
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test11
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER2.key
pub-key-cert: /tmp/capsules/SIGNER2.crt
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test12
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER.key
pub-key-cert: /tmp/capsules/SIGNER.crt
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test13
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER2.key
pub-key-cert: /tmp/capsules/SIGNER2.crt
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test14
+}
2.34.1
Regards, Simon

hi Simon,
On Tue, 11 Jul 2023 at 03:08, Simon Glass sjg@chromium.org wrote:
Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Support has been added to the mkeficapsule tool to generate capsules by parsing the capsule parameters through a config file. Add a config file for generating capsules. These capsules will be used for testing the capsule update feature on sandbox platform.
Enable generation of capsules through the config file on the sandbox variant.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch to add the capsule generation config file for sandbox.
.azure-pipelines.yml | 1 + .gitlab-ci.yml | 1 + configs/sandbox_defconfig | 2 + test/py/conftest.py | 5 ++ .../test_efi_capsule/sandbox_capsule_cfg.txt | 75 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 75075bbd07..cc196bf98c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -403,6 +403,7 @@ stages: echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/; if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 577eebd678..614bf61962 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,7 @@ stages: - echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; - echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; - echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
- cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/;
- if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d8a2386bb0..0f4c59e1a8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -340,6 +340,8 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" +CONFIG_EFI_CAPSULE_CFG_FILE="/tmp/capsules/sandbox_capsule_cfg.txt" +CONFIG_EFI_USE_CAPSULE_CFG_FILE=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y diff --git a/test/py/conftest.py b/test/py/conftest.py index 661ed74fae..f32ab1a70c 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -161,6 +161,11 @@ def setup_capsule_build(source_dir, build_dir, board_type, log): ) run_command(name, cmd, source_dir)
- capsule_cfg_file = 'test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt'
- name = 'cp'
- cmd = ( ' cp %s %s' % (capsule_cfg_file, capsule_sig_dir))
I forgot to mention this before, but you should use f strings:
cmd = f'cp {capsule_cfg_file} ...'
Will do.
Please check the other files too, as it is a pain to clean it up later. You can run 'pylint' on your source to check it.
Do the pylint checks not run as part of CI? I did not get any pylint errors in my CI run. Nonetheless, I will run the pylint tests in my workspace. Thanks.
-sughosh
- run_command(name, cmd, source_dir)
- gen_capsule_payloads(capsule_sig_dir)
def run_build(config, source_dir, build_dir, board_type, log): diff --git a/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt new file mode 100644 index 0000000000..4e5065d538 --- /dev/null +++ b/test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt @@ -0,0 +1,75 @@ +{
image-index: 1
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test01
+} +{
image-index: 2
image-guid: 5A7021F5-FEF2-48B4-AABA-832E777418C0
payload: /tmp/capsules/u-boot.env.new
capsule: /tmp/capsules/Test02
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test03
+} +{
image-index: 1
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test04
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test05
+} +{
image-index: 1
image-guid: 058B7D83-50D5-4C47-A195-60D86AD341C4
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test05
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER.key
pub-key-cert: /tmp/capsules/SIGNER.crt
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test11
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER2.key
pub-key-cert: /tmp/capsules/SIGNER2.crt
image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
payload: /tmp/capsules/u-boot.bin.new
capsule: /tmp/capsules/Test12
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER.key
pub-key-cert: /tmp/capsules/SIGNER.crt
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test13
+} +{
image-index: 1
monotonic-count: 1
private-key: /tmp/capsules/SIGNER2.key
pub-key-cert: /tmp/capsules/SIGNER2.crt
image-guid: 3673B45D-6A7C-46F3-9E60-ADABB03F7937
payload: /tmp/capsules/uboot_bin_env.itb
capsule: /tmp/capsules/Test14
+}
2.34.1
Regards, Simon

Hi Sughosh,
On Tue, 11 Jul 2023 at 01:18, Sughosh Ganu sughosh.ganu@linaro.org wrote:
hi Simon,
On Tue, 11 Jul 2023 at 03:08, Simon Glass sjg@chromium.org wrote:
Hi Sughosh,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
Support has been added to the mkeficapsule tool to generate capsules by parsing the capsule parameters through a config file. Add a config file for generating capsules. These capsules will be used for testing the capsule update feature on sandbox platform.
Enable generation of capsules through the config file on the sandbox variant.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch to add the capsule generation config file for sandbox.
.azure-pipelines.yml | 1 + .gitlab-ci.yml | 1 + configs/sandbox_defconfig | 2 + test/py/conftest.py | 5 ++ .../test_efi_capsule/sandbox_capsule_cfg.txt | 75 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 75075bbd07..cc196bf98c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -403,6 +403,7 @@ stages: echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/; if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 577eebd678..614bf61962 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,7 @@ stages: - echo -n "u-boot:New" >/tmp/capsules/u-boot.bin.new; - echo -n "u-boot-env:Old" >/tmp/capsules/u-boot.env.old; - echo -n "u-boot-env:New" >/tmp/capsules/u-boot.env.new;
- cp test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt /tmp/capsules/;
- if [[ "${TEST_PY_BD}" == "sandbox" ]] || [[ "${TEST_PY_BD}" == "sandbox_flattree" ]]; then openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER.key -out /tmp/capsules/SIGNER.crt -nodes -days 365; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout /tmp/capsules/SIGNER2.key -out /tmp/capsules/SIGNER2.crt -nodes -days 365;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d8a2386bb0..0f4c59e1a8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -340,6 +340,8 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_CAPSULE_AUTHENTICATE=y CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl" +CONFIG_EFI_CAPSULE_CFG_FILE="/tmp/capsules/sandbox_capsule_cfg.txt" +CONFIG_EFI_USE_CAPSULE_CFG_FILE=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y diff --git a/test/py/conftest.py b/test/py/conftest.py index 661ed74fae..f32ab1a70c 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -161,6 +161,11 @@ def setup_capsule_build(source_dir, build_dir, board_type, log): ) run_command(name, cmd, source_dir)
- capsule_cfg_file = 'test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt'
- name = 'cp'
- cmd = ( ' cp %s %s' % (capsule_cfg_file, capsule_sig_dir))
I forgot to mention this before, but you should use f strings:
cmd = f'cp {capsule_cfg_file} ...'
Will do.
Please check the other files too, as it is a pain to clean it up later. You can run 'pylint' on your source to check it.
Do the pylint checks not run as part of CI? I did not get any pylint errors in my CI run. Nonetheless, I will run the pylint tests in my workspace. Thanks.
Yes there is 'make pylint' but since there are many existing warnings, this only prevents things getting worse. Also it does not act on new files that it doesn't know about. You could submit an update to scripts/pylint.base to include your new files, if you want to 'protect' them from pylint rot.
Regards, Simon

The EFI capsule files can now be generated as part of u-boot build. This is done through binman. Add capsule entry nodes in the u-boot.dtsi for the sandbox architecture for generating the capsules. Remove the corresponding generation of capsules from the capsule update conftest file.
The capsules are generated through the config file for the sandbox variant, and through explicit parameters for the sandbox_flattree variant.
Also generate the FIT image used for testing the capsule update feature on the sandbox_flattree variant through binman. Remove the now superfluous its file which was used for generating this FIT image.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- Changes since V2: * New patch for generating the capsules and capsule input files through binman.
arch/sandbox/dts/u-boot.dtsi | 143 ++++++++++++++++++ test/py/tests/test_efi_capsule/conftest.py | 62 -------- .../tests/test_efi_capsule/uboot_bin_env.its | 36 ----- 3 files changed, 143 insertions(+), 98 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi index 60bd004937..292fb86a50 100644 --- a/arch/sandbox/dts/u-boot.dtsi +++ b/arch/sandbox/dts/u-boot.dtsi @@ -13,5 +13,148 @@ capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); }; #endif + + binman: binman { + multiple-images; + }; +}; + +&binman { + itb { + filename = "/tmp/capsules/uboot_bin_env.itb"; + + fit { + description = "Automatic U-Boot environment update"; + #address-cells = <2>; + + images { + u-boot-bin { + description = "U-Boot binary on SPI Flash"; + data = /incbin/("/tmp/capsules/u-boot.bin.new"); + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + hash-1 { + algo = "sha1"; + }; + }; + u-boot-env { + description = "U-Boot environment on SPI Flash"; + data = /incbin/("/tmp/capsules/u-boot.env.new"); + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + hash-1 { + algo = "sha1"; + }; + }; + }; + }; + }; + +#ifdef CONFIG_EFI_USE_CAPSULE_CFG_FILE + capsule1 { + capsule { + cfg-file = CONFIG_EFI_CAPSULE_CFG_FILE; + }; + }; +#else + capsule2 { + capsule { + image-index = <0x1>; + image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8"; + filename = "/tmp/capsules/u-boot.bin.new"; + capsule = "/tmp/capsules/Test01"; + }; + }; + + capsule3 { + capsule { + image-index = <0x2>; + image-type-id = "5A7021F5-FEF2-48B4-AABA-832E777418C0"; + filename = "/tmp/capsules/u-boot.env.new"; + capsule = "/tmp/capsules/Test02"; + }; + }; + + capsule4 { + capsule { + image-index = <0x1>; + image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4"; + filename = "/tmp/capsules/u-boot.bin.new"; + capsule = "/tmp/capsules/Test03"; + }; + }; + + capsule5 { + capsule { + image-index = <0x1>; + image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937"; + filename = "/tmp/capsules/uboot_bin_env.itb"; + capsule = "/tmp/capsules/Test04"; + }; + }; + + capsule6 { + capsule { + image-index = <0x1>; + image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4"; + filename = "/tmp/capsules/uboot_bin_env.itb"; + capsule = "/tmp/capsules/Test05"; + }; + }; + +#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE + capsule7 { + capsule { + image-index = <0x1>; + image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8"; + private-key = "/tmp/capsules/SIGNER.key"; + pub-key-cert = "/tmp/capsules/SIGNER.crt"; + monotonic-count = <0x1>; + filename = "/tmp/capsules/u-boot.bin.new"; + capsule = "/tmp/capsules/Test11"; + }; + }; + + capsule8 { + capsule { + image-index = <0x1>; + image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8"; + private-key = "/tmp/capsules/SIGNER2.key"; + pub-key-cert = "/tmp/capsules/SIGNER2.crt"; + monotonic-count = <0x1>; + filename = "/tmp/capsules/u-boot.bin.new"; + capsule = "/tmp/capsules/Test12"; + }; + }; + + capsule9 { + capsule { + image-index = <0x1>; + image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937"; + private-key = "/tmp/capsules/SIGNER.key"; + pub-key-cert = "/tmp/capsules/SIGNER.crt"; + monotonic-count = <0x1>; + filename = "/tmp/capsules/uboot_bin_env.itb"; + capsule = "/tmp/capsules/Test13"; + }; + }; + + capsule10 { + capsule { + image-index = <0x1>; + image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937"; + private-key = "/tmp/capsules/SIGNER2.key"; + pub-key-cert = "/tmp/capsules/SIGNER2.crt"; + monotonic-count = <0x1>; + filename = "/tmp/capsules/uboot_bin_env.itb"; + capsule = "/tmp/capsules/Test14"; + }; + }; +#endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +#endif /* CONFIG_EFI_USE_CAPSULE_CFG_FILE */ }; #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index 9b0f7e635d..b2315b7d51 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -40,68 +40,6 @@ def efi_capsule_data(request, u_boot_config): check_call('cp %s/arch/sandbox/dts/test.dtb %s/test_sig.dtb' % (u_boot_config.build_dir, data_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 --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test01' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 2 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test02' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 u-boot.bin.new Test03' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' % - (data_dir, u_boot_config.build_dir), - shell=True) - check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' % - (data_dir, u_boot_config.build_dir), - shell=True) - - if capsule_auth_enabled: - # raw firmware signed with proper key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test11' - % (data_dir, u_boot_config.build_dir), - shell=True) - # raw firmware signed with *mal* key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER2.key ' - '--certificate SIGNER2.crt ' - '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 ' - 'u-boot.bin.new Test12' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with proper key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER.key --certificate SIGNER.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test13' - % (data_dir, u_boot_config.build_dir), - shell=True) - # FIT firmware signed with *mal* key - check_call('cd %s; ' - '%s/tools/mkeficapsule --index 1 --monotonic-count 1 ' - '--private-key SIGNER2.key ' - '--certificate SIGNER2.crt ' - '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 ' - 'uboot_bin_env.itb Test14' - % (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) diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its deleted file mode 100644 index fc65907481..0000000000 --- a/test/py/tests/test_efi_capsule/uboot_bin_env.its +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 { - 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 { - description = "U-Boot environment on SPI Flash"; - data = /incbin/("BINFILE2"); - compression = "none"; - type = "firmware"; - arch = "sandbox"; - load = <0>; - hash-1 { - algo = "sha1"; - }; - }; - }; -};

Hi,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
The EFI capsule files can now be generated as part of u-boot build. This is done through binman. Add capsule entry nodes in the u-boot.dtsi for the sandbox architecture for generating the capsules. Remove the corresponding generation of capsules from the capsule update conftest file.
The capsules are generated through the config file for the sandbox variant, and through explicit parameters for the sandbox_flattree variant.
Also generate the FIT image used for testing the capsule update feature on the sandbox_flattree variant through binman. Remove the now superfluous its file which was used for generating this FIT image.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch for generating the capsules and capsule input files through binman.
arch/sandbox/dts/u-boot.dtsi | 143 ++++++++++++++++++ test/py/tests/test_efi_capsule/conftest.py | 62 -------- .../tests/test_efi_capsule/uboot_bin_env.its | 36 ----- 3 files changed, 143 insertions(+), 98 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi index 60bd004937..292fb86a50 100644 --- a/arch/sandbox/dts/u-boot.dtsi +++ b/arch/sandbox/dts/u-boot.dtsi @@ -13,5 +13,148 @@ capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); }; #endif
binman: binman {
multiple-images;
};
+};
+&binman {
itb {
filename = "/tmp/capsules/uboot_bin_env.itb";
You can't really do this, since that dir may not exist. Can you drop the path?
fit {
description = "Automatic U-Boot environment update";
#address-cells = <2>;
images {
u-boot-bin {
description = "U-Boot binary on SPI Flash";
data = /incbin/("/tmp/capsules/u-boot.bin.new");
See FIT docs for how to include data in a FIT with binman.
Basically you add it below *
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
* blob { filename = "u-boot.bin.new"; }
Please fix throughout.
};
u-boot-env {
description = "U-Boot environment on SPI Flash";
data = /incbin/("/tmp/capsules/u-boot.env.new");
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
};
};
};
};
+#ifdef CONFIG_EFI_USE_CAPSULE_CFG_FILE
capsule1 {
capsule {
cfg-file = CONFIG_EFI_CAPSULE_CFG_FILE;
};
};
+#else
capsule2 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test01";
};
};
capsule3 {
capsule {
image-index = <0x2>;
image-type-id = "5A7021F5-FEF2-48B4-AABA-832E777418C0";
filename = "/tmp/capsules/u-boot.env.new";
capsule = "/tmp/capsules/Test02";
};
};
capsule4 {
capsule {
image-index = <0x1>;
image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4";
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test03";
};
};
capsule5 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test04";
};
};
capsule6 {
capsule {
image-index = <0x1>;
image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4";
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test05";
};
};
+#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
capsule7 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
private-key = "/tmp/capsules/SIGNER.key";
pub-key-cert = "/tmp/capsules/SIGNER.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test11";
};
};
capsule8 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
private-key = "/tmp/capsules/SIGNER2.key";
pub-key-cert = "/tmp/capsules/SIGNER2.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test12";
};
};
capsule9 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
private-key = "/tmp/capsules/SIGNER.key";
pub-key-cert = "/tmp/capsules/SIGNER.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test13";
};
};
capsule10 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
private-key = "/tmp/capsules/SIGNER2.key";
pub-key-cert = "/tmp/capsules/SIGNER2.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test14";
};
};
+#endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +#endif /* CONFIG_EFI_USE_CAPSULE_CFG_FILE */ }; #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index 9b0f7e635d..b2315b7d51 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -40,68 +40,6 @@ def efi_capsule_data(request, u_boot_config): check_call('cp %s/arch/sandbox/dts/test.dtb %s/test_sig.dtb' % (u_boot_config.build_dir, data_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 --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test01' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 2 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test02' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 u-boot.bin.new Test03' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' %
Please put the GUIDs in variables or a dict and give them names.
(data_dir, u_boot_config.build_dir),
shell=True)
if capsule_auth_enabled:
# raw firmware signed with proper key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER.key --certificate SIGNER.crt '
'--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
'u-boot.bin.new Test11'
% (data_dir, u_boot_config.build_dir),
shell=True)
# raw firmware signed with *mal* key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER2.key '
'--certificate SIGNER2.crt '
'--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
'u-boot.bin.new Test12'
% (data_dir, u_boot_config.build_dir),
shell=True)
Please create a function to handle the common code.
# FIT firmware signed with proper key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER.key --certificate SIGNER.crt '
'--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
'uboot_bin_env.itb Test13'
% (data_dir, u_boot_config.build_dir),
shell=True)
# FIT firmware signed with *mal* key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER2.key '
'--certificate SIGNER2.crt '
'--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
'uboot_bin_env.itb Test14'
% (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)
diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its deleted file mode 100644 index fc65907481..0000000000 --- a/test/py/tests/test_efi_capsule/uboot_bin_env.its +++ /dev/null @@ -1,36 +0,0 @@ -/*
- Automatic software update for U-Boot
'EFI' should be in there somewhere.
- 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 {
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 {
description = "U-Boot environment on SPI Flash";
data = /incbin/("BINFILE2");
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
};
};
-};
2.34.1
Regards, Simon

hi Simon,
On Tue, 11 Jul 2023 at 03:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
The EFI capsule files can now be generated as part of u-boot build. This is done through binman. Add capsule entry nodes in the u-boot.dtsi for the sandbox architecture for generating the capsules. Remove the corresponding generation of capsules from the capsule update conftest file.
The capsules are generated through the config file for the sandbox variant, and through explicit parameters for the sandbox_flattree variant.
Also generate the FIT image used for testing the capsule update feature on the sandbox_flattree variant through binman. Remove the now superfluous its file which was used for generating this FIT image.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch for generating the capsules and capsule input files through binman.
arch/sandbox/dts/u-boot.dtsi | 143 ++++++++++++++++++ test/py/tests/test_efi_capsule/conftest.py | 62 -------- .../tests/test_efi_capsule/uboot_bin_env.its | 36 ----- 3 files changed, 143 insertions(+), 98 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi index 60bd004937..292fb86a50 100644 --- a/arch/sandbox/dts/u-boot.dtsi +++ b/arch/sandbox/dts/u-boot.dtsi @@ -13,5 +13,148 @@ capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); }; #endif
binman: binman {
multiple-images;
};
+};
+&binman {
itb {
filename = "/tmp/capsules/uboot_bin_env.itb";
You can't really do this, since that dir may not exist. Can you drop the path?
This directory does exist. I am adding logic to add the directory in patches 7 and 8 to ensure that the /tmp/capsules/ directory exists for the capsule updates testing, both for CI runs as well as local pytest test runs.
fit {
description = "Automatic U-Boot environment update";
#address-cells = <2>;
images {
u-boot-bin {
description = "U-Boot binary on SPI Flash";
data = /incbin/("/tmp/capsules/u-boot.bin.new");
See FIT docs for how to include data in a FIT with binman.
Basically you add it below *
Okay. WIll change this.
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
- blob { filename = "u-boot.bin.new"; }
Please fix throughout.
};
u-boot-env {
description = "U-Boot environment on SPI Flash";
data = /incbin/("/tmp/capsules/u-boot.env.new");
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
};
};
};
};
+#ifdef CONFIG_EFI_USE_CAPSULE_CFG_FILE
capsule1 {
capsule {
cfg-file = CONFIG_EFI_CAPSULE_CFG_FILE;
};
};
+#else
capsule2 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test01";
};
};
capsule3 {
capsule {
image-index = <0x2>;
image-type-id = "5A7021F5-FEF2-48B4-AABA-832E777418C0";
filename = "/tmp/capsules/u-boot.env.new";
capsule = "/tmp/capsules/Test02";
};
};
capsule4 {
capsule {
image-index = <0x1>;
image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4";
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test03";
};
};
capsule5 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test04";
};
};
capsule6 {
capsule {
image-index = <0x1>;
image-type-id = "058B7D83-50D5-4C47-A195-60D86AD341C4";
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test05";
};
};
+#ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
capsule7 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
private-key = "/tmp/capsules/SIGNER.key";
pub-key-cert = "/tmp/capsules/SIGNER.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test11";
};
};
capsule8 {
capsule {
image-index = <0x1>;
image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
private-key = "/tmp/capsules/SIGNER2.key";
pub-key-cert = "/tmp/capsules/SIGNER2.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/u-boot.bin.new";
capsule = "/tmp/capsules/Test12";
};
};
capsule9 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
private-key = "/tmp/capsules/SIGNER.key";
pub-key-cert = "/tmp/capsules/SIGNER.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test13";
};
};
capsule10 {
capsule {
image-index = <0x1>;
image-type-id = "3673B45D-6A7C-46F3-9E60-ADABB03F7937";
private-key = "/tmp/capsules/SIGNER2.key";
pub-key-cert = "/tmp/capsules/SIGNER2.crt";
monotonic-count = <0x1>;
filename = "/tmp/capsules/uboot_bin_env.itb";
capsule = "/tmp/capsules/Test14";
};
};
+#endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +#endif /* CONFIG_EFI_USE_CAPSULE_CFG_FILE */ }; #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index 9b0f7e635d..b2315b7d51 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -40,68 +40,6 @@ def efi_capsule_data(request, u_boot_config): check_call('cp %s/arch/sandbox/dts/test.dtb %s/test_sig.dtb' % (u_boot_config.build_dir, data_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 --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test01' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 2 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test02' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 u-boot.bin.new Test03' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' %
Please put the GUIDs in variables or a dict and give them names.
Do you mean for the code that is getting added in the binman nodes? The above code is actually getting removed.
(data_dir, u_boot_config.build_dir),
shell=True)
if capsule_auth_enabled:
# raw firmware signed with proper key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER.key --certificate SIGNER.crt '
'--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
'u-boot.bin.new Test11'
% (data_dir, u_boot_config.build_dir),
shell=True)
# raw firmware signed with *mal* key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER2.key '
'--certificate SIGNER2.crt '
'--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
'u-boot.bin.new Test12'
% (data_dir, u_boot_config.build_dir),
shell=True)
Please create a function to handle the common code.
Again, this code is being removed.
# FIT firmware signed with proper key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER.key --certificate SIGNER.crt '
'--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
'uboot_bin_env.itb Test13'
% (data_dir, u_boot_config.build_dir),
shell=True)
# FIT firmware signed with *mal* key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
'--private-key SIGNER2.key '
'--certificate SIGNER2.crt '
'--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
'uboot_bin_env.itb Test14'
% (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)
diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its deleted file mode 100644 index fc65907481..0000000000 --- a/test/py/tests/test_efi_capsule/uboot_bin_env.its +++ /dev/null @@ -1,36 +0,0 @@ -/*
- Automatic software update for U-Boot
'EFI' should be in there somewhere.
Okay. But again, this code is being removed. Do you want me to add this somewhere else?
- 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 {
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 {
description = "U-Boot environment on SPI Flash";
data = /incbin/("BINFILE2");
compression = "none";
type = "firmware";
arch = "sandbox";
load = <0>;
hash-1 {
algo = "sha1";
};
};
};
-};
2.34.1
Regards, Simon

Hi Sughosh,
On Tue, 11 Jul 2023 at 01:24, Sughosh Ganu sughosh.ganu@linaro.org wrote:
hi Simon,
On Tue, 11 Jul 2023 at 03:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Sun, 9 Jul 2023 at 07:34, Sughosh Ganu sughosh.ganu@linaro.org wrote:
The EFI capsule files can now be generated as part of u-boot build. This is done through binman. Add capsule entry nodes in the u-boot.dtsi for the sandbox architecture for generating the capsules. Remove the corresponding generation of capsules from the capsule update conftest file.
The capsules are generated through the config file for the sandbox variant, and through explicit parameters for the sandbox_flattree variant.
Also generate the FIT image used for testing the capsule update feature on the sandbox_flattree variant through binman. Remove the now superfluous its file which was used for generating this FIT image.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org
Changes since V2:
- New patch for generating the capsules and capsule input files through binman.
arch/sandbox/dts/u-boot.dtsi | 143 ++++++++++++++++++ test/py/tests/test_efi_capsule/conftest.py | 62 -------- .../tests/test_efi_capsule/uboot_bin_env.its | 36 ----- 3 files changed, 143 insertions(+), 98 deletions(-) delete mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its
diff --git a/arch/sandbox/dts/u-boot.dtsi b/arch/sandbox/dts/u-boot.dtsi index 60bd004937..292fb86a50 100644 --- a/arch/sandbox/dts/u-boot.dtsi +++ b/arch/sandbox/dts/u-boot.dtsi @@ -13,5 +13,148 @@ capsule-key = /incbin/(CONFIG_EFI_CAPSULE_ESL_FILE); }; #endif
binman: binman {
multiple-images;
};
+};
+&binman {
itb {
filename = "/tmp/capsules/uboot_bin_env.itb";
You can't really do this, since that dir may not exist. Can you drop the path?
This directory does exist. I am adding logic to add the directory in patches 7 and 8 to ensure that the /tmp/capsules/ directory exists for the capsule updates testing, both for CI runs as well as local pytest test runs.
OK I see. Then you should use --toolpath to binman to add that directory, e.g. by setting BINMAN_TOOLPATHS.
[..]
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' %
(data_dir, u_boot_config.build_dir),
shell=True)
check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' %
Please put the GUIDs in variables or a dict and give them names.
Do you mean for the code that is getting added in the binman nodes? The above code is actually getting removed.
Oops OK, I see.
Regards, SImon
participants (3)
-
Heinrich Schuchardt
-
Simon Glass
-
Sughosh Ganu