diff --git a/Documentation/drivers/efi_capsule_generation.md b/Documentation/drivers/efi_capsule_generation.md new file mode 100644 index 0000000000..84d2c86f9a --- /dev/null +++ b/Documentation/drivers/efi_capsule_generation.md @@ -0,0 +1,77 @@ +# Generating signed UEFI capsules with EDK2 + +coreboot can cooperate with an EDK2 payload to support firmware updates via the UEFI +ESRT/FMP capsule mechanism. + +This document covers generating a *signed* capsule during the coreboot build. + +At present, capsule generation requires a compatible EDK2 tree with the +corresponding payload-side changes. Upstream support is being tracked in: + +https://github.com/tianocore/edk2/pull/12053 + +Older EDK2 trees may be missing pieces required by this integration. + +## Build-time capsule generation + +Enable capsule support and use an EDK2 payload: + +- `CONFIG_DRIVERS_EFI_UPDATE_CAPSULES`: enable coreboot capsule update support. +- `CONFIG_DRIVERS_EFI_GENERATE_CAPSULE`: generate `build/coreboot.cap` after the ROM is finalised. +- `CONFIG_PAYLOAD_EDK2`: build an EDK2 payload. + +When enabled, the coreboot build generates `build/coreboot.cap` after the ROM image is +finalised. The capsule can also be generated explicitly with `make capsule`. + +Configure the FMAP allowlist embedded into the ROM as a manifest: + +- `CONFIG_DRIVERS_EFI_CAPSULE_REGIONS`: whitespace-separated FMAP region allowlist embedded into + the ROM as a manifest (e.g. `COREBOOT EC`). + +Configure the ESRT/FMP firmware identity used by the capsule: + +- `CONFIG_DRIVERS_EFI_MAIN_FW_GUID`: GUID of the firmware +- `CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`: firmware version encoded in the capsule header; + if set to `0`, derive a value from the leading `.` in + `CONFIG_LOCALVERSION` when possible +- `CONFIG_DRIVERS_EFI_MAIN_FW_LSV`: lowest supported firmware version; if set to `0`, + use the resolved firmware version + +Reset behavior during capsule application: + +- `CONFIG_DRIVERS_EFI_CAPSULE_INITIATE_RESET`: add the capsule `InitiateReset` flag. + This is disabled by default because Linux rejects capsules with `InitiateReset` when using + `/dev/efi_capsule_loader`. + +## Embedded drivers (FmpDxe in capsule) + +Some EDK2 capsule update flows use an embedded `FmpDxe.efi` driver inside the capsule. + +To generate capsules with an embedded `FmpDxe.efi`, enable: + +- `CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE`: embed `FmpDxe.efi` into generated capsules. +- `CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS`: configure the EDK2 payload to accept + capsules with embedded drivers (sets `PcdCapsuleEmbeddedDriverSupport=TRUE`). + +Note: if Secure Boot is enabled, the embedded driver must be signed by a key trusted by the +running firmware, otherwise capsule processing may fail when loading the embedded driver. + +## Capsule signing certificates + +`GenerateCapsule` can sign the FMP payload (PKCS#7). Many platforms require signed capsules. + +coreboot exposes three Kconfig options for the certificate chain: + +- `CONFIG_DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT`: PEM containing the signing private key and + leaf certificate +- `CONFIG_DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT`: PEM intermediate certificate +- `CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT`: PEM trusted root certificate + +If a configured path is relative, it is interpreted relative to the configured EDK2 repository +inside `payloads/external/edk2/workspace`. + +The defaults use the EDK2 BaseTools test certificate chain. Do not use the test keys for +production firmware updates. + +To generate your own certificate chain and convert it into the required PEM files, see: +`BaseTools/Source/Python/Pkcs7Sign/Readme.md` in the EDK2 tree. diff --git a/Documentation/drivers/index.md b/Documentation/drivers/index.md index 381685e068..e0142a8e4d 100644 --- a/Documentation/drivers/index.md +++ b/Documentation/drivers/index.md @@ -29,4 +29,5 @@ SMMSTOREv2 SoundWire USB4 Retimer CBFS SMBIOS hooks +EDK2 capsule generation ``` diff --git a/Makefile.mk b/Makefile.mk index 5fccb4a52d..b5e988195f 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -73,11 +73,31 @@ build_complete:: | coreboot .PHONY: files_added files_added:: | build_complete +# This target can be used to run rules once the ROM is fully finalised +# (after all files were added to CBFS, and any files_added hooks ran). +.PHONY: finalised_rom +finalised_rom:: | files_added + +# Optional post-build targets. +.PHONY: capsule +capsule:: + +ifeq ($(CONFIG_PAYLOAD_EDK2)$(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES)$(CONFIG_DRIVERS_EFI_GENERATE_CAPSULE),yyy) +finalised_rom:: $(obj)/coreboot.cap +capsule:: $(obj)/coreboot.cap + +$(obj)/coreboot.cap: $(obj)/coreboot.rom $(DOTCONFIG) | files_added + $(MAKE) -C payloads/external/edk2 coreboot_capsule \ + COREBOOT_ROM="$(abspath $<)" \ + COREBOOT_CAPSULE_OUT="$(abspath $@)" \ + $(EDK2_CAPSULE_ARGS) +endif + # This target should come just before the show_notices target. If there # are no notices, the build should finish with the text of what was just # built. .PHONY: show_coreboot -show_coreboot: | files_added +show_coreboot: | finalised_rom $(CBFSTOOL) $(obj)/coreboot.rom print -r $(subst $(spc),$(comma),$(all-regions)) printf "\nBuilt %s (%s)\n" $(MAINBOARDDIR) $(CONFIG_MAINBOARD_PART_NUMBER) if [ -f "$(CCACHE_STATSLOG)" ]; then \ diff --git a/payloads/external/Makefile.mk b/payloads/external/Makefile.mk index 429c0b2a85..49428201de 100644 --- a/payloads/external/Makefile.mk +++ b/payloads/external/Makefile.mk @@ -176,6 +176,25 @@ warn_no_option_cfr_enabled: endif endif +EDK2_CAPSULE_ARGS = \ + CONFIG_EDK2_REPOSITORY=$(CONFIG_EDK2_REPOSITORY) \ + CONFIG_EDK2_TAG_OR_REV=$(CONFIG_EDK2_TAG_OR_REV) \ + CONFIG_EDK2_USE_EDK2_PLATFORMS=$(CONFIG_EDK2_USE_EDK2_PLATFORMS) \ + CONFIG_EDK2_PLATFORMS_REPOSITORY=$(CONFIG_EDK2_PLATFORMS_REPOSITORY) \ + CONFIG_EDK2_PLATFORMS_TAG_OR_REV=$(CONFIG_EDK2_PLATFORMS_TAG_OR_REV) \ + CONFIG_EDK2_DEBUG=$(CONFIG_EDK2_DEBUG) \ + CONFIG_DRIVERS_EFI_MAIN_FW_GUID=$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID) \ + CONFIG_LOCALVERSION=$(CONFIG_LOCALVERSION) \ + CONFIG_DRIVERS_EFI_MAIN_FW_VERSION=$(CONFIG_DRIVERS_EFI_MAIN_FW_VERSION) \ + CONFIG_DRIVERS_EFI_MAIN_FW_LSV=$(CONFIG_DRIVERS_EFI_MAIN_FW_LSV) \ + CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS=$(CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS) \ + CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE=$(CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE) \ + CONFIG_DRIVERS_EFI_CAPSULE_INITIATE_RESET=$(CONFIG_DRIVERS_EFI_CAPSULE_INITIATE_RESET) \ + CONFIG_DRIVERS_EFI_CAPSULE_REGIONS=$(CONFIG_DRIVERS_EFI_CAPSULE_REGIONS) \ + CONFIG_DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT=$(CONFIG_DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT) \ + CONFIG_DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT=$(CONFIG_DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT) \ + CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT=$(CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT) + $(obj)/UEFIPAYLOAD.fd: $(DOTCONFIG) $(IPXE_EFI) $(MAKE) -C payloads/external/edk2 UefiPayloadPkg \ HOSTCC="$(HOSTCC)" \ @@ -220,6 +239,9 @@ $(obj)/UEFIPAYLOAD.fd: $(DOTCONFIG) $(IPXE_EFI) CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2=$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2) \ CONFIG_DRIVERS_EFI_UPDATE_CAPSULES=$(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES) \ CONFIG_DRIVERS_EFI_MAIN_FW_GUID=$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID) \ + CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS=$(CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS) \ + CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE=$(CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE) \ + CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT=$(CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT) \ GCC_CC_x86_32=$(GCC_CC_x86_32) \ GCC_CC_x86_64=$(GCC_CC_x86_64) \ GCC_CC_arm=$(GCC_CC_arm) \ diff --git a/payloads/external/edk2/Makefile b/payloads/external/edk2/Makefile index c9bd36a27f..09c38d8cf8 100644 --- a/payloads/external/edk2/Makefile +++ b/payloads/external/edk2/Makefile @@ -5,7 +5,17 @@ export SHELL := env bash project_name = edk2 export WORKSPACE := $(CURDIR)/workspace -export EDK2_PATH := $(WORKSPACE)/$(word 3,$(subst /, ,$(CONFIG_EDK2_REPOSITORY))) + +strip_quotes = $(subst ",,$(1)) + +EDK2_REPOSITORY := $(call strip_quotes,$(CONFIG_EDK2_REPOSITORY)) +EDK2_PLATFORMS_REPOSITORY := $(call strip_quotes,$(CONFIG_EDK2_PLATFORMS_REPOSITORY)) +EDK2_PATH_REPO_ROOT := $(word 3,$(subst /, ,$(EDK2_REPOSITORY))) +export EDK2_PATH := $(WORKSPACE)/$(EDK2_PATH_REPO_ROOT) + +define edk2_abspath +$(if $(filter /%,$(1)),$(1),$(EDK2_PATH)/$(1)) +endef ifeq ($(CONFIG_EDK2_USE_EDK2_PLATFORMS),y) BUILD_STR += -D USE_EDK2_PLATFORMS=TRUE @@ -128,6 +138,39 @@ ifeq ($(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES),y) BUILD_STR += -D CAPSULE_SUPPORT=TRUE BUILD_STR += -D CAPSULE_MAIN_FW_GUID=$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID) endif +ifeq ($(CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS),y) +BUILD_STR += --pcd gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleEmbeddedDriverSupport=TRUE +endif +ifeq ($(CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE),y) +BUILD_STR += -D CAPSULE_EMBED_FMP_DXE=TRUE +endif + +CAPSULE_PCD_INC_REL := BaseTools/Source/Python/Pkcs7Sign/TestRoot.cer.gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr.inc +CAPSULE_PCD_INC := $(EDK2_PATH)/$(CAPSULE_PCD_INC_REL) +CAPSULE_PCD_NAME := gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr + +CAPSULE_GUID := $(call strip_quotes,$(CONFIG_DRIVERS_EFI_MAIN_FW_GUID)) +CAPSULE_REGIONS := $(call strip_quotes,$(CONFIG_DRIVERS_EFI_CAPSULE_REGIONS)) +CAPSULE_LOCALVERSION := $(call strip_quotes,$(CONFIG_LOCALVERSION)) +CAPSULE_SIGNER_PRIVATE_CERT := $(call strip_quotes,$(CONFIG_DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT)) +CAPSULE_OTHER_PUBLIC_CERT := $(call strip_quotes,$(CONFIG_DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT)) +CAPSULE_TRUSTED_PUBLIC_CERT := $(call strip_quotes,$(CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT)) + +CAPSULE_SIGNER_PRIVATE_CERT_PATH := $(call edk2_abspath,$(CAPSULE_SIGNER_PRIVATE_CERT)) +CAPSULE_OTHER_PUBLIC_CERT_PATH := $(call edk2_abspath,$(CAPSULE_OTHER_PUBLIC_CERT)) +CAPSULE_TRUSTED_PUBLIC_CERT_PATH := $(call edk2_abspath,$(CAPSULE_TRUSTED_PUBLIC_CERT)) + +# AppendRmapManifest.py moved from BaseTools/Scripts to UefiPayloadPkg/Tools in +# newer edk2 trees. +EDK2_APPEND_RMAP_MANIFEST = $(firstword $(wildcard \ + $(EDK2_PATH)/UefiPayloadPkg/Tools/AppendRmapManifest.py \ + $(EDK2_PATH)/BaseTools/Scripts/AppendRmapManifest.py \ +)) + +# If FmpDxe is built, edk2 also places it in the top-level X64 output dir. +EDK2_FMP_DXE = $(WORKSPACE)/Build/UefiPayloadPkgX64/$(RELEASE_STR)_GCC/X64/FmpDxe.efi + +CAPSULE_ROOT_CERT_DER := $(WORKSPACE)/capsule_trusted_root.der # # One or more downstream edk2 repositories support the following additional options: @@ -223,6 +266,10 @@ $(EDK2_PATH): $(WORKSPACE) fi cd $(EDK2_PATH); \ git checkout MdeModulePkg/Logo/Logo.bmp > /dev/null 2>&1 || true; \ + git checkout "$(CAPSULE_PCD_INC_REL)" > /dev/null 2>&1 || true; \ + if ! git ls-files --error-unmatch "$(CAPSULE_PCD_INC_REL)" >/dev/null 2>&1; then \ + rm -f "$(CAPSULE_PCD_INC_REL)" || true; \ + fi; \ if [ -e UefiPayloadPkg/ShimLayer/UniversalPayload.o ]; then \ rm UefiPayloadPkg/ShimLayer/UniversalPayload.o; \ fi; \ @@ -286,6 +333,19 @@ checktools: exit 1; \ fi +ifeq ($(CONFIG_DRIVERS_EFI_UPDATE_CAPSULES)$(CONFIG_DRIVERS_EFI_GENERATE_CAPSULE),yy) +capsule_keys: $(EDK2_PATH) + type openssl > /dev/null 2>&1 || ( echo "ERROR: Please install openssl."; exit 1 ) + test -f "$(CAPSULE_TRUSTED_PUBLIC_CERT_PATH)" + test -f "$(EDK2_PATH)/BaseTools/Scripts/BinToPcd.py" + mkdir -p "$(dir $(CAPSULE_PCD_INC))" + openssl x509 -in "$(CAPSULE_TRUSTED_PUBLIC_CERT_PATH)" -outform der -out "$(CAPSULE_ROOT_CERT_DER)" + python3 "$(EDK2_PATH)/BaseTools/Scripts/BinToPcd.py" -q -x \ + -i "$(CAPSULE_ROOT_CERT_DER)" -o "$(CAPSULE_PCD_INC)" -p "$(CAPSULE_PCD_NAME)" + +prep: capsule_keys +endif + print: echo " ##### $(project_name) Build Summary #####" echo " Repository: $(CONFIG_EDK2_REPOSITORY)" @@ -359,3 +419,46 @@ distclean: rm -rf $(WORKSPACE) .PHONY: $(EDK2_PATH) checktools logo UefiPayloadPkg UniversalPayload clean distclean + +.PHONY: coreboot_capsule capsule_keys + +coreboot_capsule: $(EDK2_PATH) + test -n "$(COREBOOT_ROM)" + test -n "$(COREBOOT_CAPSULE_OUT)" + test -f "$(COREBOOT_ROM)" + test -f "$(EDK2_APPEND_RMAP_MANIFEST)" + test -x "$(EDK2_PATH)/BaseTools/BinWrappers/PosixLike/GenerateCapsule" + test -f "$(CAPSULE_SIGNER_PRIVATE_CERT_PATH)" + test -f "$(CAPSULE_OTHER_PUBLIC_CERT_PATH)" + test -f "$(CAPSULE_TRUSTED_PUBLIC_CERT_PATH)" + rmap_rom="$${COREBOOT_CAPSULE_OUT%.cap}.rmap.rom"; \ + set -e; \ + python3 "$(EDK2_APPEND_RMAP_MANIFEST)" -o "$$rmap_rom" $(foreach r,$(CAPSULE_REGIONS),-r $(r)) "$(COREBOOT_ROM)"; \ + embedded_driver_args=(); \ + if [ "$(CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE)" = "y" ]; then \ + test -f "$(EDK2_FMP_DXE)"; \ + embedded_driver_args=( --embedded-driver "$(EDK2_FMP_DXE)" ); \ + fi; \ + fw_version=$$(( $(CONFIG_DRIVERS_EFI_MAIN_FW_VERSION) )); \ + if [ $$fw_version -eq 0 ]; then \ + if [[ "$(CAPSULE_LOCALVERSION)" =~ ^[^0-9]*([0-9]+)[.]([0-9]+) ]]; then \ + fw_version=$$(( (10#$${BASH_REMATCH[1]} << 16) | 10#$${BASH_REMATCH[2]} )); \ + fi; \ + fi; \ + lsv=$$(( $(CONFIG_DRIVERS_EFI_MAIN_FW_LSV) )); \ + if [ $$lsv -eq 0 ]; then \ + lsv=$$fw_version; \ + fi; \ + capflags=( --capflag PersistAcrossReset ); \ + if [ "$(CONFIG_DRIVERS_EFI_CAPSULE_INITIATE_RESET)" = "y" ]; then \ + capflags+=( --capflag InitiateReset ); \ + fi; \ + "$(EDK2_PATH)/BaseTools/BinWrappers/PosixLike/GenerateCapsule" -e -o "$(COREBOOT_CAPSULE_OUT)" \ + --guid "$(CAPSULE_GUID)" \ + "$${capflags[@]}" \ + --fw-version $$fw_version --lsv $$lsv \ + --signer-private-cert "$(CAPSULE_SIGNER_PRIVATE_CERT_PATH)" \ + --other-public-cert "$(CAPSULE_OTHER_PUBLIC_CERT_PATH)" \ + --trusted-public-cert "$(CAPSULE_TRUSTED_PUBLIC_CERT_PATH)" \ + "$${embedded_driver_args[@]}" \ + "$$rmap_rom" diff --git a/src/drivers/efi/Kconfig b/src/drivers/efi/Kconfig index 9effc0d778..8730290922 100644 --- a/src/drivers/efi/Kconfig +++ b/src/drivers/efi/Kconfig @@ -57,3 +57,93 @@ config DRIVERS_EFI_UPDATE_CAPSULES Adds a driver that is able to parse CapsuleUpdateData* EFI variables to discover firmware updates and expose them for tianocore thorough CBMEM for execution. tianocore is responsible for erasing the variables. + +config DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS + bool "Allow embedded drivers in update capsules" + depends on PAYLOAD_EDK2 && DRIVERS_EFI_UPDATE_CAPSULES + help + Allow the EDK2 payload's capsule processing to load embedded drivers + from capsules (PcdCapsuleEmbeddedDriverSupport). + + This is required for capsules that contain embedded drivers. + + Note: if Secure Boot is enabled, the embedded driver must be signed by a + key trusted by the running firmware (or capsule processing may fail). + +config DRIVERS_EFI_GENERATE_CAPSULE + bool "Generate an update capsule during the build" + depends on PAYLOAD_EDK2 && DRIVERS_EFI_UPDATE_CAPSULES + help + Generates a UEFI capsule from the final ROM image using EDK2 BaseTools. + This is intended for fwupd update workflows that use the ESRT/FMP + mechanism. + +config DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE + bool "Embed FmpDxe driver into generated capsules" + depends on DRIVERS_EFI_GENERATE_CAPSULE + depends on DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS + help + When generating build/coreboot.cap, embed the built FmpDxe.efi as an + embedded driver in the capsule. + + +config DRIVERS_EFI_CAPSULE_INITIATE_RESET + bool "Request reset after capsule is applied" + default n + depends on DRIVERS_EFI_GENERATE_CAPSULE + help + Add the InitiateReset capsule flag when generating build/coreboot.cap. + + Note: Linux rejects capsules with InitiateReset when using + /dev/efi_capsule_loader. + + +config DRIVERS_EFI_CAPSULE_REGIONS + string "FMAP regions to include in the capsule manifest" + default "COREBOOT" + depends on DRIVERS_EFI_GENERATE_CAPSULE + help + Whitespace-separated list of FMAP regions that the update capsule is + allowed to modify. The list is embedded as a manifest inside the ROM + image prior to building the capsule. + +menu "Capsule signing certificates" + depends on DRIVERS_EFI_GENERATE_CAPSULE + +config DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT + string "PEM file used to sign generated capsules" + default "BaseTools/Source/Python/Pkcs7Sign/TestCert.pem" + depends on DRIVERS_EFI_GENERATE_CAPSULE + help + Path to a PEM file containing the private key and leaf certificate used + when signing the capsule with EDK2 GenerateCapsule. + + If the path is relative, it is interpreted relative to the configured + EDK2 repository (payloads/external/edk2 workspace). + + See Documentation/drivers/efi_capsule_generation.md and + BaseTools/Source/Python/Pkcs7Sign/Readme.md in the EDK2 tree. + +config DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT + string "Intermediate certificate for capsule signing (PEM)" + default "BaseTools/Source/Python/Pkcs7Sign/TestSub.pub.pem" + depends on DRIVERS_EFI_GENERATE_CAPSULE + help + Path to the intermediate certificate (PEM) used when generating a PKCS#7 + signature for the capsule. + + If the path is relative, it is interpreted relative to the configured + EDK2 repository (payloads/external/edk2 workspace). + +config DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT + string "Trusted root certificate for capsule signing (PEM)" + default "BaseTools/Source/Python/Pkcs7Sign/TestRoot.pub.pem" + depends on DRIVERS_EFI_GENERATE_CAPSULE + help + Path to the trusted root certificate (PEM) used when generating a PKCS#7 + signature for the capsule. + + If the path is relative, it is interpreted relative to the configured + EDK2 repository (payloads/external/edk2 workspace). + +endmenu