[PATCH v2 0/3] Conformance Profiles Table support in U-boot

patch v2: - address v1 comments - define EFI_EBBR_2_0_CONFORMANCE unconditionally. - introduce ECPT EFI selftet - drop the efidebug ECPT print
The Conformance Profiles Table (ECPT) table will be included in the UEFI specification 2.9+. The ECPT table was introduced in UEFI following the code-first path. The acceptance ticket can be viewed at: https://bugzilla.tianocore.org/show_bug.cgi?id=3591
This patch set implements the ECPT table in U-boot.
Jose Marinho (3): efi: Create ECPT table efi: ECPT add EBBRv2.0 conformance profile efi: ECPT EFI selftest
cmd/efidebug.c | 4 + include/efi_api.h | 14 ++++ include/efi_loader.h | 7 ++ lib/efi_loader/Kconfig | 11 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_conformance.c | 75 +++++++++++++++++++ lib/efi_loader/efi_setup.c | 6 ++ lib/efi_selftest/Makefile | 2 + lib/efi_selftest/efi_selftest_ecpt.c | 105 +++++++++++++++++++++++++++ 9 files changed, 225 insertions(+) create mode 100644 lib/efi_loader/efi_conformance.c create mode 100644 lib/efi_selftest/efi_selftest_ecpt.c

The ECPT table will be included in the UEFI specification 2.9+. The ECPT table was introduced in UEFI following the code-first path. The acceptance ticket can be viewed at: https://bugzilla.tianocore.org/show_bug.cgi?id=3591
The Conformance Profiles table is a UEFI configuration table that contains GUID of the UEFI profiles that the UEFI implementation conforms with.
The ECPT table is created when CONFIG_EFI_ECPT=y. The config is set by default.
Signed-off-by: Jose Marinho jose.marinho@arm.com --- cmd/efidebug.c | 4 ++ include/efi_api.h | 10 +++++ include/efi_loader.h | 7 ++++ lib/efi_loader/Kconfig | 6 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_conformance.c | 66 ++++++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 6 +++ 7 files changed, 100 insertions(+) create mode 100644 lib/efi_loader/efi_conformance.c
diff --git a/cmd/efidebug.c b/cmd/efidebug.c index a977ca9c72..a53a5029fa 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -619,6 +619,10 @@ static const struct { "TCG2 Final Events Table", EFI_TCG2_FINAL_EVENTS_TABLE_GUID, }, + { + "EFI Conformance Profiles Table", + EFI_CONFORMANCE_PROFILES_TABLE_GUID, + }, };
/** diff --git a/include/efi_api.h b/include/efi_api.h index 80109f012b..6fd4f04de3 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -226,6 +226,16 @@ enum efi_reset_type { EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a)
+#define EFI_CONFORMANCE_PROFILES_TABLE_GUID \ + EFI_GUID(0x36122546, 0xf7ef, 0x4c8f, 0xbd, 0x9b, \ + 0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b) + +struct efi_conformance_profiles_table { + u16 version; + u16 number_of_profiles; + efi_guid_t conformance_profiles[]; +} __packed; + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; diff --git a/include/efi_loader.h b/include/efi_loader.h index d52e399841..d20ff396d0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -976,6 +976,13 @@ efi_status_t efi_capsule_authenticate(const void *capsule, */ efi_status_t efi_esrt_register(void);
+/** + * efi_ecpt_register() - Install the ECPT system table. + * + * Return: status code + */ +efi_status_t efi_ecpt_register(void); + /** * efi_esrt_populate() - Populates the ESRT entries from the FMP instances * present in the system. diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 700dc838dd..b2398976f4 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -367,4 +367,10 @@ config EFI_ESRT help Enabling this option creates the ESRT UEFI system table.
+config EFI_ECPT + bool "Enable the UEFI ECPT generation" + default y + help + Enabling this option created the ECPT UEFI table. + endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index fd344cea29..9f5a0cebd1 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o +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) diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c new file mode 100644 index 0000000000..1bb06c3b7e --- /dev/null +++ b/lib/efi_loader/efi_conformance.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * EFI conformance profile table + * + * Copyright (C) 2022 Arm Ltd. + */ + +#include <common.h> +#include <efi_loader.h> +#include <log.h> +#include <efi_api.h> +#include <malloc.h> + +const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID; + +#define EFI_CONFORMANCE_PROFILES_TABLE_VERSION 1 + +/** + * efi_ecpt_register() - Install the ECPT system table. + * + * Return: status code + */ +efi_status_t efi_ecpt_register(void) +{ + int num_entries = 0; + struct efi_conformance_profiles_table *ecpt; + efi_status_t ret; + size_t ecpt_size = 0; + + efi_debug("ECPT table creation start\n"); + + ecpt_size = num_entries * sizeof(efi_guid_t) + + sizeof(struct efi_conformance_profiles_table); + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, ecpt_size, + (void **)&ecpt); + + if (ret != EFI_SUCCESS) { + efi_debug("ECPT cannot allocate memory for %u entries (%zu bytes)\n", + num_entries, ecpt_size); + + return ret; + } + + ecpt->version = EFI_CONFORMANCE_PROFILES_TABLE_VERSION; + ecpt->number_of_profiles = num_entries; + + if (num_entries) + efi_debug("ECPT check conformance profiles, not all entries populated in table\n"); + + /* Install the ECPT in the system configuration table. */ + ret = efi_install_configuration_table(&efi_ecpt_guid, (void *)ecpt); + if (ret != EFI_SUCCESS) { + efi_debug("ECPT failed to install the ECPT in the system table\n"); + goto error; + } + + efi_debug("ECPT table successfully created\n"); + + return ret; + +error: + + ret = efi_free_pool(ecpt); + + return ret; +} diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 1aba71cd96..fa5ad13500 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -231,6 +231,12 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
+ if (IS_ENABLED(CONFIG_EFI_ECPT)) { + ret = efi_ecpt_register(); + if (ret != EFI_SUCCESS) + goto out; + } + if (IS_ENABLED(CONFIG_EFI_ESRT)) { ret = efi_esrt_register(); if (ret != EFI_SUCCESS)

Display the EBBRv2.0 conformance in the ECPT table.
The EBBRv2.0 conformance profile is set in the ECPT if CONFIG_EFI_EBBR_2_0_CONFORMANCE=y. The config defaults to 'n'.
Signed-off-by: Jose Marinho jose.marinho@arm.com --- include/efi_api.h | 4 ++++ lib/efi_loader/Kconfig | 5 +++++ lib/efi_loader/efi_conformance.c | 9 +++++++++ 3 files changed, 18 insertions(+)
diff --git a/include/efi_api.h b/include/efi_api.h index 6fd4f04de3..49919caa35 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -230,6 +230,10 @@ enum efi_reset_type { EFI_GUID(0x36122546, 0xf7ef, 0x4c8f, 0xbd, 0x9b, \ 0xeb, 0x85, 0x25, 0xb5, 0x0c, 0x0b)
+#define EFI_CONFORMANCE_PROFILE_EBBR_2_0_GUID \ + EFI_GUID(0xcce33c35, 0x74ac, 0x4087, 0xbc, 0xe7, \ + 0x8b, 0x29, 0xb0, 0x2e, 0xeb, 0x27) + struct efi_conformance_profiles_table { u16 version; u16 number_of_profiles; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index b2398976f4..9688d48366 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -373,4 +373,9 @@ config EFI_ECPT help Enabling this option created the ECPT UEFI table.
+config EFI_EBBR_2_0_CONFORMANCE + bool "Add the EBBRv2.0 conformance entry to the ECPT table" + default n + help + Enabling this option adds the EBBRv2.0 conformance entry to the ECPT UEFI table. endif diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c index 1bb06c3b7e..325afe2d56 100644 --- a/lib/efi_loader/efi_conformance.c +++ b/lib/efi_loader/efi_conformance.c @@ -12,6 +12,7 @@ #include <malloc.h>
const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID; +const efi_guid_t efi_ebbr_2_0_guid = EFI_CONFORMANCE_PROFILE_EBBR_2_0_GUID;
#define EFI_CONFORMANCE_PROFILES_TABLE_VERSION 1
@@ -29,6 +30,9 @@ efi_status_t efi_ecpt_register(void)
efi_debug("ECPT table creation start\n");
+ if (IS_ENABLED(CONFIG_EFI_EBBR_2_0_CONFORMANCE)) + num_entries++; + ecpt_size = num_entries * sizeof(efi_guid_t) + sizeof(struct efi_conformance_profiles_table); ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, ecpt_size, @@ -44,6 +48,11 @@ efi_status_t efi_ecpt_register(void) ecpt->version = EFI_CONFORMANCE_PROFILES_TABLE_VERSION; ecpt->number_of_profiles = num_entries;
+ if (IS_ENABLED(CONFIG_EFI_EBBR_2_0_CONFORMANCE)) { + num_entries--; + guidcpy(&ecpt->conformance_profiles[num_entries], &efi_ecpt_guid); + } + if (num_entries) efi_debug("ECPT check conformance profiles, not all entries populated in table\n");

Hi Jose,
On Thu, Dec 23, 2021 at 11:52 AM Jose Marinho jose.marinho@arm.com wrote:
The config defaults to 'n'.
No need to mention this as it is the standard.
+config EFI_EBBR_2_0_CONFORMANCE
bool "Add the EBBRv2.0 conformance entry to the ECPT table"
default n
You should remove "default n"

This test ensures the ECPT table is present and is consistent.
Invocation from the sandbox platform: add to sandbox_defconfig: +CONFIG_CMD_BOOTEFI_SELFTEST=y
make sandbox_capsule_defconfig all ./u-boot -d arch/sandbox/dts/test.dtb bootefi selftest
Signed-off-by: Jose Marinho jose.marinho@arm.com --- lib/efi_selftest/Makefile | 2 + lib/efi_selftest/efi_selftest_ecpt.c | 105 +++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_ecpt.c
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 9ff6e1760c..6cf548653f 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -112,3 +112,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h + +obj-$(CONFIG_EFI_ECPT) += efi_selftest_ecpt.o diff --git a/lib/efi_selftest/efi_selftest_ecpt.c b/lib/efi_selftest/efi_selftest_ecpt.c new file mode 100644 index 0000000000..555b59bc90 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_ecpt.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test ECPT tables support + * + * Copyright (C) 2022 Arm Ltd. + */ +#include <common.h> +#include <efi_loader.h> +#include <efi_selftest.h> + +static const struct efi_system_table *local_systable; + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + local_systable = systable; + + return EFI_ST_SUCCESS; +} + +/* + * Traverse the ECPT table looking for a particular profile. + * + * @profile_guid: the guid of the conformance profile to find + * @ecpt: a pointer to the ECPT table + * @return: true if profile_guid is an entry in ECPT, false otherwise + */ +static bool find_profile(efi_guid_t *profile_guid, + struct efi_conformance_profiles_table *ecpt) +{ + for (int idx = 0; idx < local_systable->nr_tables; idx++) + if (!guidcmp(profile_guid, &ecpt->conformance_profiles[idx])) + return true; + return false; +} + +/* + * Perform the test + * + * The test consists of the following steps: + * + * 1) Obtain the ECPT + * 2) Quantify the number of expected profiles + * 3) Verify that each expected profile is in the ECPT + * 4) Ensure that the number of ECPT entries is the expected + * + * The failure of any of the above steps results in a test failure. + * + */ +static int execute(void) +{ + struct efi_conformance_profiles_table *ecpt; + efi_status_t ret = EFI_SUCCESS; + struct efi_boot_services *bt; + int expected_num_entries; + + bt = local_systable->boottime; + + if (!bt) { + efi_st_error("Cannot find boottime services structure\n"); + return EFI_ST_FAILURE; + } + + for (int idx = 0; idx < local_systable->nr_tables; idx++) + if (!guidcmp(&efi_ecpt_guid, &local_systable->tables[idx].guid)) + ecpt = (struct efi_conformance_profiles_table *) + local_systable->tables[idx].table; + + if (!ecpt) { + efi_st_error("ECPT table not present\n"); + return EFI_ST_FAILURE; + } + + /* + * Check for presence of each expected profile. + */ + if (IS_ENABLED(CONFIG_EFI_EBBR_2_0_CONFORMANCE)) { + expected_num_entries++; + if (!find_profile(&efi_ecpt_guid, ecpt)) { + efi_st_error("failed to find profile %pUL\n", &efi_ecpt_guid); + return EFI_ST_FAILURE; + } + } + + if (ecpt->number_of_profiles != expected_num_entries) { + efi_st_error("Mismatch in number of ECPT entries\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(ecpt) = { + .name = "ecpt", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, +};

On 12/23/21 15:51, Jose Marinho wrote:
patch v2:
- address v1 comments
- define EFI_EBBR_2_0_CONFORMANCE unconditionally.
- introduce ECPT EFI selftet
- drop the efidebug ECPT print
The Conformance Profiles Table (ECPT) table will be included in the UEFI specification 2.9+.
@Samer:
The current spec draft assuming compliance if the table is not present makes no sense and needs to be fixed. U-Boot should not create a precedent of an implementation of this broken design.
@Jose:
As you cannot define under which circumstances the EBBR 2.0 GUID should be set we should not implement this table at all.
Best regards
Heinrich
The ECPT table was introduced in UEFI following the code-first path. The acceptance ticket can be viewed at: https://bugzilla.tianocore.org/show_bug.cgi?id=3591
This patch set implements the ECPT table in U-boot.
Jose Marinho (3): efi: Create ECPT table efi: ECPT add EBBRv2.0 conformance profile efi: ECPT EFI selftest
cmd/efidebug.c | 4 + include/efi_api.h | 14 ++++ include/efi_loader.h | 7 ++ lib/efi_loader/Kconfig | 11 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_conformance.c | 75 +++++++++++++++++++ lib/efi_loader/efi_setup.c | 6 ++ lib/efi_selftest/Makefile | 2 + lib/efi_selftest/efi_selftest_ecpt.c | 105 +++++++++++++++++++++++++++ 9 files changed, 225 insertions(+) create mode 100644 lib/efi_loader/efi_conformance.c create mode 100644 lib/efi_selftest/efi_selftest_ecpt.c
participants (3)
-
Fabio Estevam
-
Heinrich Schuchardt
-
Jose Marinho