
This commmit exercises the ESRT creation in two tests.
test 1: A fake FMP, with TEST_ESRT_NUM_ENTRIES FW images, is installed in the system leading to the corresponding ESRT entries being populated. The ESRT entries are checked against the datastructure used to initialize the FMP.
test 1 invocation: add to sandbox_defconfig: +CONFIG_EFI_SELFTEST=y
make sandbox_capsule_defconfig all ./u-boot -d arch/sandbox/dts/test.dtb bootefi selftest
test 2: The test is part of test_efi_capsule_fw3.
In order to run the test the following must be added to sandbox_defconfig: +CONFIG_CMD_SF=y +CONFIG_CMD_MEMORY=y +CONFIG_CMD_FAT=y +CONFIG_DFU=y
The ESRT is printed in the u-boot shell by calling efidebug esrt. The test ensures that, after the capsule is installed, the ESRT contains entries with the GUIDs: - EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; - EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
test 2 invocation: sudo ./test/py/test.py --bd sandbox -k capsule_fw3 -l --build
Signed-off-by: Jose Marinho jose.marinho@arm.com
CC: Heinrich Schuchardt xypron.glpk@gmx.de CC: Sughosh Ganu sughosh.ganu@linaro.org CC: AKASHI Takahiro takahiro.akashi@linaro.org CC: Ilias Apalodimas ilias.apalodimas@linaro.org CC: Andre Przywara andre.przywara@arm.com CC: Alexander Graf agraf@csgraf.de CC: nd@arm.com
--- lib/efi_selftest/Makefile | 2 + lib/efi_selftest/efi_selftest_esrt.c | 227 ++++++++++++++++++ .../test_efi_capsule/test_capsule_firmware.py | 4 + 3 files changed, 233 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_esrt.c
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 7d6ea30102..017b191a46 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -72,6 +72,8 @@ ifeq ($(CONFIG_BLK)$(CONFIG_DOS_PARTITION),yy) obj-y += efi_selftest_block_device.o endif
+obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o + targets += \ efi_miniapp_file_image_exception.h \ efi_miniapp_file_image_exit.h \ diff --git a/lib/efi_selftest/efi_selftest_esrt.c b/lib/efi_selftest/efi_selftest_esrt.c new file mode 100644 index 0000000000..b053b2e6c6 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_esrt.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test ESRT tables support + * + * Copyright (C) 2021 Arm Ltd. + */ +#include <common.h> +#include <efi_loader.h> +#include <efi_selftest.h> + +// This value must not exceed 255. +// An FMP cannot contain more than 255 FW images. +#define TEST_ESRT_NUM_ENTRIES 255 + +static +struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES]; + +static void efi_test_esrt_init_info(void) +{ + for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) { + static_img_info[idx].image_index = idx; + + // Note: the 16 byte value present in + // static_img_info[idx].image_type_id is not strictly a GUID. + // The value is used for the sake of code testing. + static_img_info[idx].image_type_id.b[0] = idx; + + static_img_info[idx].image_id = 0; + static_img_info[idx].image_id_name = NULL; + static_img_info[idx].version = 0; + static_img_info[idx].version_name = NULL; + static_img_info[idx].size = 0; + static_img_info[idx].lowest_supported_image_version = 1; + static_img_info[idx].last_attempt_version = 2; + static_img_info[idx].last_attempt_status = 3; + static_img_info[idx].hardware_instance = 1; + } +} + +static efi_status_t +EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name) +{ + efi_status_t ret = EFI_SUCCESS; + + if (!image_info_size) + return EFI_INVALID_PARAMETER; + + if (descriptor_version) + *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; + if (descriptor_count) + *descriptor_count = TEST_ESRT_NUM_ENTRIES; + if (descriptor_size) + *descriptor_size = sizeof(*image_info); + if (package_version) + *package_version = 0xffffffff; + if (package_version_name) + *package_version_name = NULL; + + if (*image_info_size < sizeof(*image_info)) { + *image_info_size = *descriptor_size * *descriptor_count; + return EFI_BUFFER_TOO_SMALL; + } + + for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) + image_info[idx] = static_img_info[idx]; + + return ret; +} + +static struct efi_firmware_management_protocol efi_test_fmp = { + .get_image_info = efi_test_fmp_get_image_info, + .get_image = NULL, + .set_image = NULL, + .check_image = NULL, + .get_package_info = NULL, + .set_package_info = NULL, +}; + +static void *lib_test_get_esrt(void) +{ + for (int idx = 0; idx < systab.nr_tables; idx++) + if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid)) + return systab.tables[idx].table; + + return NULL; +} + +static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt, + struct efi_firmware_image_descriptor + *img_info) +{ + const u32 filled_entries = esrt->fw_resource_count; + struct efi_system_resource_entry *entry = esrt->entries; + + for (u32 idx = 0; idx < filled_entries; idx++) { + if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) { + if (entry[idx].fw_version != img_info->version) + return false; + + if (entry[idx].lowest_supported_fw_version != + img_info->lowest_supported_image_version) + return false; + + if (entry[idx].last_attempt_version != + img_info->last_attempt_version) + return false; + + if (entry[idx].last_attempt_status != + img_info->last_attempt_status) + return false; + + /* + * The entry with fw_class = img_uuid matches with the + * remainder fmp input. + */ + return true; + } + } + + /* There exists no entry with fw_class equal to img_uuid in the ESRT. */ + return false; +} + +/* + * Setup unit test. + * + * Initialize the test FMP datastructure. + * Install the FMP in the system. + * + * @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) +{ + efi_status_t ret = EFI_SUCCESS; + struct efi_boot_services *bt = systab.boottime; + + if (!bt) + return EFI_ST_FAILURE; + + efi_test_esrt_init_info(); + + ret = EFI_CALL(bt->install_multiple_protocol_interfaces + (&efi_root, + &efi_guid_firmware_management_protocol, + &efi_test_fmp, + NULL)); + + if (ret != EFI_SUCCESS) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + * Uninstall the test FMP. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + efi_status_t ret = EFI_SUCCESS; + struct efi_boot_services *bt = systab.boottime; + + if (!bt) + return EFI_ST_FAILURE; + + ret = EFI_CALL(bt->uninstall_multiple_protocol_interfaces + (efi_root, &efi_guid_firmware_management_protocol, + &efi_test_fmp, NULL)); + + if (ret != EFI_SUCCESS) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +static int execute(void) +{ + struct efi_system_resource_table *esrt; + efi_status_t ret = EFI_SUCCESS; + + esrt = lib_test_get_esrt(); + if (!esrt) + return EFI_ST_FAILURE; + + if (esrt->fw_resource_count != TEST_ESRT_NUM_ENTRIES) + return EFI_ST_FAILURE; + + /* Update the ESRT. */ + ret = efi_esrt_populate(); + if (ret != EFI_SUCCESS) + return EFI_ST_FAILURE; + + esrt = lib_test_get_esrt(); + if (!esrt) + return EFI_ST_FAILURE; + + /* Verify that the number of images remains the same. */ + if (esrt->fw_resource_count != TEST_ESRT_NUM_ENTRIES) + return EFI_ST_FAILURE; + + for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) + if (!lib_test_check_uuid_entry(esrt, &static_img_info[idx])) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(esrt) = { + .name = "esrt", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py index f006fa95d6..3a7c2e1ac8 100644 --- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py @@ -229,6 +229,10 @@ class TestEfiCapsuleFirmwareFit(object): output = u_boot_console.run_command( 'env print -e -all Capsule0000')
+ output = u_boot_console.run_command_list(['efidebug capsule esrt']) + assert 'AE13FF2D-9AD4-4E25-9AC8-6D80B3B22147' in ''.join(output) + assert 'E2BB9C06-70E9-4B14-97A3-5A7913176E3F' in ''.join(output) + output = u_boot_console.run_command_list([ 'host bind 0 %s' % disk_img, 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])