123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- // 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 const struct efi_system_table *local_systable;
- static efi_handle_t fmp_handle;
- static const efi_guid_t efi_fmp_guid =
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
- 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 < local_systable->nr_tables; idx++)
- if (!guidcmp(&efi_esrt_guid, &local_systable->tables[idx].guid))
- return local_systable->tables[idx].table;
- return NULL;
- }
- /**
- * lib_test_check_uuid_entry: Find an ESRT entry for which the fw_calss field matches
- * the image_type_id in the @img_info.
- * Ensure that all of the field in the ESRT entry have the same value as the corresponding
- * fields in the @img_info.
- *
- * @esrt: pointer to the ESRT
- * @img_info: an image_info_descriptor output by the FMP get_image_info
- *
- * @return: true if matching ESRT entry is found and if all the ESRT entry fields match the
- * corresponding @img_info fields.
- */
- 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) {
- efi_st_error("ESRT field mismatch for entry with fw_class=%pU\n",
- &img_info->image_type_id);
- return false;
- }
- if (entry[idx].lowest_supported_fw_version !=
- img_info->lowest_supported_image_version) {
- efi_st_error("ESRT field mismatch for entry with fw_class=%pU\n",
- &img_info->image_type_id);
- return false;
- }
- if (entry[idx].last_attempt_version !=
- img_info->last_attempt_version) {
- efi_st_error("ESRT field mismatch for entry with fw_class=%pU\n",
- &img_info->image_type_id);
- return false;
- }
- if (entry[idx].last_attempt_status !=
- img_info->last_attempt_status) {
- efi_st_error("ESRT field mismatch for entry with fw_class=%pU\n",
- &img_info->image_type_id);
- 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. */
- efi_st_error("ESRT no entry with fw_class= %pUl\n", &img_info->image_type_id);
- return false;
- }
- /*
- * Setup unit test.
- *
- * Initialize the test FMP datastructure.
- *
- * @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;
- efi_test_esrt_init_info();
- 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;
- bt = local_systable->boottime;
- if (!bt) {
- efi_st_error("Cannot find boottime services structure\n");
- return EFI_ST_FAILURE;
- }
- ret = bt->uninstall_multiple_protocol_interfaces
- (fmp_handle, &efi_fmp_guid,
- &efi_test_fmp, NULL);
- if (ret != EFI_SUCCESS) {
- efi_st_error("Failed to uninstall FMP\n");
- return EFI_ST_FAILURE;
- }
- return EFI_ST_SUCCESS;
- }
- /*
- * Perform the test
- *
- * The test consists of the following steps:
- *
- * 1) Obtain the ESRT
- * 2) Record the number of ESRT entries prior to test start
- * 3) Install the test FMP
- * 4) Re-obtain the ESRT (the ESRT pointer may have changed with the FMP install)
- * 5) verify that the ESRT entries have increased by the number of entries in the
- * test FMP.
- * 6) Traverse all the elements used as the test FMP input and verify that each
- * has a corresponding ESRT entry and that the fields are correctly set.
- *
- * The failure of any of the above steps results in a test failure.
- *
- */
- static int execute(void)
- {
- struct efi_system_resource_table *esrt;
- efi_status_t ret = EFI_SUCCESS;
- u32 base_entry_count;
- u32 entry_delta;
- struct efi_boot_services *bt;
- bt = local_systable->boottime;
- if (!bt) {
- efi_st_error("Cannot find boottime services structure\n");
- return EFI_ST_FAILURE;
- }
- esrt = lib_test_get_esrt();
- if (!esrt) {
- efi_st_error("ESRT table not present\n");
- return EFI_ST_FAILURE;
- }
- base_entry_count = esrt->fw_resource_count;
- ret = bt->install_multiple_protocol_interfaces(&fmp_handle,
- &efi_fmp_guid,
- &efi_test_fmp,
- NULL);
- if (ret != EFI_SUCCESS) {
- efi_st_error("Failed to install FMP\n");
- return EFI_ST_FAILURE;
- }
- esrt = lib_test_get_esrt();
- if (!esrt) {
- efi_st_error("ESRT table not present\n");
- return EFI_ST_FAILURE;
- }
- entry_delta = esrt->fw_resource_count - base_entry_count;
- if (entry_delta != TEST_ESRT_NUM_ENTRIES) {
- efi_st_error("ESRT mismatch in new entry count (%d), expected (%d).\n",
- entry_delta, 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])) {
- efi_st_error("ESRT entry mismatch\n");
- 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,
- };
|