From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heinrich Schuchardt Date: Tue, 16 Feb 2021 11:27:27 +0100 Subject: [PATCH 1/2] efi: Add ESRT to the EFI system table In-Reply-To: <570ecc4f-d27d-bd11-b6fa-609f56ac1e98@gmx.de> References: <20210208125246.32547-1-jose.marinho@arm.com> <20210208125246.32547-2-jose.marinho@arm.com> <570ecc4f-d27d-bd11-b6fa-609f56ac1e98@gmx.de> Message-ID: <4decb78c-b9fb-682e-b6d6-1d870de71c21@gmx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 16.02.21 10:06, Heinrich Schuchardt wrote: > On 08.02.21 13:52, Jose Marinho wrote: >> The ESRT is initialised during efi_init_objlist after >> efi_initialize_system_table(). >> >> The ESRT is initially created with size for 50 FW image entries. >> The ESRT is resized when it runs out of space. Every resize adds 50 >> additional entries. >> The ESRT is populated from information provided by FMP instances only. >> >> Signed-off-by: Jose Marinho >> >> CC: Heinrich Schuchardt >> CC: Sughosh Ganu >> CC: AKASHI Takahiro >> CC: Ilias Apalodimas >> CC: Andre Przywara >> CC: Alexander Graf >> CC: nd at arm.com >> >> --- >> cmd/efidebug.c | 4 + >> include/efi_api.h | 21 ++ >> include/efi_loader.h | 19 ++ >> lib/efi_loader/Kconfig | 7 + >> lib/efi_loader/Makefile | 1 + >> lib/efi_loader/efi_boottime.c | 2 - >> lib/efi_loader/efi_capsule.c | 7 + >> lib/efi_loader/efi_esrt.c | 439 ++++++++++++++++++++++++++++++++++ >> lib/efi_loader/efi_setup.c | 6 + >> 9 files changed, 504 insertions(+), 2 deletions(-) >> create mode 100644 lib/efi_loader/efi_esrt.c >> >> diff --git a/cmd/efidebug.c b/cmd/efidebug.c >> index 83bc2196a5..4160dde1cf 100644 >> --- a/cmd/efidebug.c >> +++ b/cmd/efidebug.c >> @@ -458,6 +458,10 @@ static const struct { >> "Block IO", >> EFI_BLOCK_IO_PROTOCOL_GUID, >> }, >> + { >> + "EFI System Resource Table", >> + EFI_SYSTEM_RESOURCE_TABLE_GUID, >> + }, >> { >> "Simple File System", >> EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, >> diff --git a/include/efi_api.h b/include/efi_api.h >> index 48e48a6263..7eb15bd44c 100644 >> --- a/include/efi_api.h >> +++ b/include/efi_api.h >> @@ -1722,6 +1722,23 @@ struct efi_load_file_protocol { >> void *buffer); >> }; >> >> +struct efi_system_resource_entry { >> + efi_guid_t fw_class; >> + uint32_t fw_type; >> + uint32_t fw_version; >> + uint32_t lowest_supported_fw_version; >> + uint32_t capsule_flags; >> + uint32_t last_attempt_version; >> + uint32_t last_attempt_status; >> +} __packed; >> + >> +struct efi_system_resource_table { >> + uint32_t fw_resource_count; >> + uint32_t fw_resource_count_max; >> + uint64_t fw_resource_version; >> + struct efi_system_resource_entry entries[]; >> +} __packed; >> + >> /* Boot manager load options */ >> #define LOAD_OPTION_ACTIVE 0x00000001 >> #define LOAD_OPTION_FORCE_RECONNECT 0x00000002 >> @@ -1740,6 +1757,10 @@ struct efi_load_file_protocol { >> #define ESRT_FW_TYPE_DEVICEFIRMWARE 0x00000002 >> #define ESRT_FW_TYPE_UEFIDRIVER 0x00000003 >> >> +#define EFI_SYSTEM_RESOURCE_TABLE_GUID\ >> + EFI_GUID(0xb122a263, 0x3661, 0x4f68,\ >> + 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 ) > > Please, run scripts/checkpatch.pl on your patches before submitting. > > ERROR: space prohibited before that close parenthesis ')' > >> + >> /* Last Attempt Status Values */ >> #define LAST_ATTEMPT_STATUS_SUCCESS 0x00000000 >> #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL 0x00000001 >> diff --git a/include/efi_loader.h b/include/efi_loader.h >> index f470bbd636..c85c540041 100644 >> --- a/include/efi_loader.h >> +++ b/include/efi_loader.h >> @@ -884,4 +884,23 @@ static inline efi_status_t efi_launch_capsules(void) >> >> #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */ >> >> +/* >> + * Install the ESRT system table. >> + * >> + * @return status code >> + */ >> +efi_status_t efi_esrt_register(void); >> + >> +/** >> + * efi_esrt_add_from_fmp() - Populates a sequence of ESRT entries from the FW >> + * images in the FMP. >> + * >> + * @fmp: the fmp from which fw images are added to the ESRT >> + * >> + * Return: >> + * - EFI_SUCCESS if all the FW images in the FMP are added to the ESRT >> + * - Error status otherwise >> + */ >> +efi_status_t efi_esrt_add_from_fmp(struct efi_firmware_management_protocol *fmp); >> + >> #endif /* _EFI_LOADER_H */ >> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig >> index e729f727df..12b29180a0 100644 >> --- a/lib/efi_loader/Kconfig >> +++ b/lib/efi_loader/Kconfig >> @@ -347,4 +347,11 @@ config EFI_SECURE_BOOT >> it is signed with a trusted key. To do that, you need to install, >> at least, PK, KEK and db. >> >> +config EFI_ESRT >> + bool "Enable the UEFI ESRT generation" >> + depends on EFI_LOADER > > This line is after "if EFI_LOADER". > > I assume EFI_ESRT should depend on CONFIG_EFI_HAVE_CAPSULE_SUPPORT. > >> + default y >> + help >> + Enabling this option creates the ESRT UEFI system table. >> + >> endif >> diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile >> index 10b42e8847..dec791b310 100644 >> --- a/lib/efi_loader/Makefile >> +++ b/lib/efi_loader/Makefile >> @@ -52,6 +52,7 @@ obj-y += efi_variable.o >> obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o >> endif >> obj-y += efi_watchdog.o >> +obj-y += efi_esrt.o >> obj-$(CONFIG_LCD) += efi_gop.o >> obj-$(CONFIG_DM_VIDEO) += efi_gop.o >> obj-$(CONFIG_PARTITIONS) += efi_disk.o >> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c >> index ce658a8e73..9b0b15571a 100644 >> --- a/lib/efi_loader/efi_boottime.c >> +++ b/lib/efi_loader/efi_boottime.c >> @@ -1148,8 +1148,6 @@ efi_status_t efi_add_protocol(const efi_handle_t handle, >> } >> } >> >> - if (!guidcmp(&efi_guid_device_path, protocol)) >> - EFI_PRINT("installed device path '%pD'\n", protocol_interface); > > This change is unrelated. Why would you want to remove the debug output? > >> return EFI_SUCCESS; >> } >> >> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c >> index 0d5a7b63ec..60703bcdaa 100644 >> --- a/lib/efi_loader/efi_capsule.c >> +++ b/lib/efi_loader/efi_capsule.c >> @@ -404,6 +404,13 @@ static efi_status_t efi_capsule_update_firmware( >> efi_free_pool(abort_reason); >> goto out; >> } >> + >> +#ifdef CONFIG_EFI_ESRT > > Please, use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef' > where possible. > >> + /* Update the ESRT entries corresponding to fmp. */ >> + ret = efi_esrt_add_from_fmp(fmp); > > Why don't you reuse efi_esrt_new_fmp_notify()? > >> + if (ret != EFI_SUCCESS) >> + log_warning("EFI Capsule: failed to populate ESRT entry\n"); > > I think the warning can be moved to inside efi_esrt_add_from_fmp(). > >> +#endif > > This would not catch an update via an FMP driver loaded via the bootefi > command. Shouldn't the call be add the end of efi_update_capsule()? > >> } >> >> out: >> diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c >> new file mode 100644 >> index 0000000000..34133346ca >> --- /dev/null >> +++ b/lib/efi_loader/efi_esrt.c >> @@ -0,0 +1,439 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * EFI application ESRT tables support >> + * >> + * Copyright (C) 2021 Arm Ltd. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +static efi_guid_t esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID; >> + >> +struct efi_system_resource_table *esrt; >> + >> +#define EFI_ESRT_MIN_RESIZE_ENTIRES 50 >> +#define EFI_ESRT_VERSION 1 >> + >> +/** >> + * efi_esrt_image_info_to_entry() - copy the information present in a fw image >> + * descriptor to a ESRT entry. >> + * >> + * @img_info: the source image info descriptor >> + * @entry: pointer to the ESRT entry to be filled >> + * @desc_version: the version of the elements in img_info >> + * @image_type: the image type value to be set in the ESRT entry >> + * @flags: the capsule flags value to be set in the ESRT entry >> + * >> + */ >> +void >> +efi_esrt_image_info_to_entry(struct efi_firmware_image_descriptor *img_info, >> + struct efi_system_resource_entry *entry, >> + u32 desc_version, u32 image_type, u32 flags) >> +{ >> + guidcpy(&entry->fw_class, &img_info->image_type_id); >> + entry->fw_version = img_info->version; >> + >> + entry->fw_type = image_type; >> + entry->capsule_flags = flags; >> + >> + /* >> + * The field lowest_supported_image_version is only present >> + * on image info structure of version 2 or greater. >> + * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI. >> + */ >> + if (desc_version >= 2) { >> + entry->lowest_supported_fw_version = >> + img_info->lowest_supported_image_version; >> + } else { >> + entry->lowest_supported_fw_version = 0; >> + } >> + >> + /* >> + * The fields last_attempt_version and last_attempt_status >> + * are only present on image info structure of version 3 or >> + * greater. >> + * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI. >> + */ >> + if (desc_version >= 3) { >> + entry->last_attempt_version = >> + img_info->last_attempt_version; >> + >> + entry->last_attempt_status = >> + img_info->last_attempt_status; >> + } else { >> + entry->last_attempt_version = 0; >> + entry->last_attempt_status = EFI_SUCCESS; > > This should be LAST_ATTEMPT_STATUS_SUCCESS. > >> + } >> +} >> + >> +/** >> + * efi_esrt_entries_to_size() - Obtain the bytes used by an ESRT >> + * datastructure with @num_entries. >> + * >> + * @num_entries: the ESRT which we obtain the filled size in bytes. >> + * >> + * Return: the number of bytes an ESRT with @num_entries occupies in memory. >> + */ >> +static >> +inline u32 efi_esrt_entries_to_size(u32 num_entries) >> +{ >> + u32 esrt_size = sizeof(struct efi_system_resource_table) + >> + num_entries * sizeof(struct efi_system_resource_entry); >> + >> + return esrt_size; >> +} >> + >> +/** >> + * efi_esrt_allocate_install() - Allocates @num_entries for the ESRT and >> + * performs basic ESRT initialization. >> + * >> + * @bt : pointer to the boottime services structure. >> + * @num_entries: the number of entries that the ESRT will hold. >> + * >> + * Return: >> + * - pointer to the ESRT if successful. >> + * - NULL otherwise. >> + */ >> +static >> +struct efi_system_resource_table *efi_esrt_allocate_install(struct efi_boot_services *bt, >> + u32 num_entries) >> +{ >> + efi_status_t ret; >> + struct efi_system_resource_table *new_esrt; >> + u32 size = efi_esrt_entries_to_size(num_entries); >> + >> + /* Allocated pages must be on the lower 32bit address space. */ >> + new_esrt = (struct efi_system_resource_table *)(uintptr_t)U32_MAX; >> + >> + /* Reserve num_pages for ESRT */ >> + ret = EFI_CALL(bt->allocate_pool(EFI_RUNTIME_SERVICES_DATA, >> + size, >> + (void **)&new_esrt)); >> + >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT Failed to allocate memory for ESRT with %d entries (%d bytes)\n", >> + num_entries, efi_esrt_entries_to_size(num_entries)); >> + >> + return NULL; >> + } >> + >> + new_esrt->fw_resource_count_max = num_entries; >> + new_esrt->fw_resource_version = EFI_ESRT_VERSION; >> + >> + /* Install the ESRT in the system configuration table. */ >> + ret = EFI_CALL(bt->install_configuration_table(&esrt_guid, (void *)new_esrt)); >> + if (ret != EFI_SUCCESS) >> + EFI_PRINT("ESRT failed to install the ESRT\n"); >> + >> + return new_esrt; >> +} >> + >> +/** >> + * efi_esrt_resize() - Increments the ESRT to hold an addition @inc_entries FW >> + * image entries. >> + * >> + * @inc_entries: the additional number of FW image entries to add to the ESRT. >> + * >> + * Return: >> + * - EFI_SUCCESS if ESRT correctly resized. >> + * - Error code otherwise. >> + */ >> +static efi_status_t efi_esrt_resize(u32 inc_entries) >> +{ >> + struct efi_boot_services *bt = systab.boottime; >> + struct efi_system_resource_table *old_esrt = esrt; >> + struct efi_system_resource_table *new_esrt; > > This seems overly complex. Just dispose of the existing table and create > a new one if either an FMP protocol is installed or CapsuleUpdate() occurs. > >> + >> + u32 old_max_entries = old_esrt->fw_resource_count_max; >> + u32 old_filled_size; >> + efi_status_t ret; >> + >> + if (!bt) { >> + EFI_PRINT("ESRT cannot obtain pointer to BS\n"); >> + return EFI_NOT_READY; >> + } >> + >> + /* Allocate and install the bigger ESRT. */ >> + new_esrt = efi_esrt_allocate_install(bt, old_max_entries + inc_entries); >> + if (!esrt) { >> + EFI_PRINT("ESRT failed to allocate and install resized ESRT\n"); >> + esrt = old_esrt; >> + return EFI_OUT_OF_RESOURCES; >> + } >> + esrt = new_esrt; >> + >> + old_filled_size = efi_esrt_entries_to_size(old_esrt->fw_resource_count_max); >> + >> + /* Copy the old ESRT entries onto the new table. */ >> + memcpy(new_esrt->entries, old_esrt->entries, old_filled_size >> + - sizeof(struct efi_system_resource_table)); >> + >> + new_esrt->fw_resource_count = old_esrt->fw_resource_count; >> + >> + ret = EFI_CALL(bt->free_pool(old_esrt)); >> + if (ret != EFI_SUCCESS) { >> + /* >> + * This should never happen. >> + * >> + * if ret!= EFI_SUCCESS then old_esrt is invalid. >> + */ >> + panic("EFI ESRT: could not deallocate old ESRT at %p\n", old_esrt); >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + * esrt_find_entry() - Obtain the ESRT entry for the image with GUID >> + * @img_fw_class. >> + * >> + * If the img_fw_class is not yet present in the ESRT, this function >> + * reserves the tail element of the current ESRT as the entry for that fw_class. >> + * The number of elements in the ESRT is updated in that case. >> + * >> + * @img_fw_class: the GUID of the FW image which ESRT entry we want to obtain. >> + * >> + * Return: >> + * - a pointer to the ESRT entry for the image with GUID img_fw_class, >> + * - NULL if: >> + * - there is no more space in the ESRT, >> + * - ESRT is not initialized, >> + * - boot services are not present. >> + */ >> +static >> +struct efi_system_resource_entry *esrt_find_entry(efi_guid_t *img_fw_class) >> +{ >> + u32 filled_entries; >> + u32 max_entries; >> + struct efi_system_resource_entry *entry; >> + >> + if (!esrt) { >> + EFI_PRINT("ESRT access before initialized\n"); >> + return NULL; >> + } >> + >> + filled_entries = esrt->fw_resource_count; >> + entry = esrt->entries; >> + >> + /* Check if the image with img_fw_class is already in the ESRT. */ >> + for (u32 idx = 0; idx < filled_entries; idx++) { >> + if (!guidcmp(&entry[idx].fw_class, img_fw_class)) { >> + EFI_PRINT("ESRT found entry for image %pUl at index %d\n", >> + img_fw_class, idx); >> + return &entry[idx]; >> + } >> + } >> + >> + max_entries = esrt->fw_resource_count_max; >> + /* Since the image with img_fw_class is not present in the ESRT, check >> + * if ESRT is full before appending the new entry to it. */ >> + if (filled_entries == max_entries) { >> + efi_status_t ret; >> + >> + /* ESRT is full, attempt to extend the ESRT entries. */ >> + ret = efi_esrt_resize(EFI_ESRT_MIN_RESIZE_ENTIRES); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT full, failed to resize\n"); >> + return NULL; >> + } >> + >> + entry = esrt->entries; >> + EFI_PRINT("ESRT table resized\n"); >> + } >> + >> + /* >> + * This is a new entry for a fw image, increment the element >> + * number in the table and set the fw_class field. >> + */ >> + esrt->fw_resource_count++; >> + entry[filled_entries].fw_class = *img_fw_class; >> + EFI_PRINT("ESRT allocated new entry for image %pUl at index %d\n", >> + img_fw_class, filled_entries); >> + >> + return &entry[filled_entries]; >> +} >> + >> +/** >> + * efi_esrt_add_from_fmp() - Populates a sequence of ESRT entries from the FW >> + * images in the FMP. >> + * >> + * @fmp: the FMP instance from which FW images are added to the ESRT >> + * >> + * Return: >> + * - EFI_SUCCESS if all the FW images in the FMP are added to the ESRT >> + * - Error status otherwise >> + */ >> +efi_status_t efi_esrt_add_from_fmp(struct efi_firmware_management_protocol *fmp) >> +{ >> + struct efi_boot_services *bt = systab.boottime; >> + struct efi_system_resource_entry *entry = NULL; >> + size_t info_size = 0; >> + struct efi_firmware_image_descriptor *img_info = NULL; >> + u32 desc_version; >> + u8 desc_count; >> + size_t desc_size; >> + efi_status_t ret = EFI_SUCCESS; >> + >> + if (!bt) { >> + EFI_PRINT("ESRT cannot obtain pointer to BS\n"); >> + return EFI_NOT_READY; >> + } >> + >> + /* >> + * TODO: set the field image_type depending on the FW image type >> + * defined in a platform basis. >> + */ >> + u32 image_type = ESRT_FW_TYPE_UNKNOWN; >> + >> + /* TODO: set the capsule flags as a function of the FW image type. */ >> + u32 flags = 0; >> + >> + ret = fmp->get_image_info(fmp, &info_size, img_info, >> + &desc_version, &desc_count, >> + &desc_size, NULL, NULL); >> + >> + if (ret != EFI_BUFFER_TOO_SMALL) { >> + /* >> + * An input of info_size=0 should always lead >> + * fmp->get_image_info to return BUFFER_TO_SMALL. >> + */ >> + EFI_PRINT("Erroneous FMP implementation\n"); >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + ret = EFI_CALL(bt->allocate_pool(EFI_BOOT_SERVICES_DATA, info_size, >> + (void **)&img_info)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT failed to allocate memory for image info.\n"); >> + return ret; >> + } >> + >> + ret = fmp->get_image_info(fmp, &info_size, img_info, >> + &desc_version, &desc_count, >> + &desc_size, NULL, NULL); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT failed to obtain the FMP image info\n"); >> + goto out; >> + } >> + >> + /* >> + * Iterate over all the FW images in the FMP. >> + */ >> + for (u32 desc_idx = 0; desc_idx < desc_count; desc_idx++) { >> + struct efi_firmware_image_descriptor *cur_img_info = >> + (struct efi_firmware_image_descriptor *) >> + ((uintptr_t)img_info + desc_idx * desc_size); >> + >> + /* >> + * Obtain the ESRT entry for the FW image with fw_class >> + * equal to cur_img_info->image_type_id. >> + */ >> + entry = esrt_find_entry(&cur_img_info->image_type_id); >> + >> + if (entry) { >> + efi_esrt_image_info_to_entry(cur_img_info, entry, >> + desc_version, image_type, >> + flags); >> + } else { >> + EFI_PRINT("ESRT failed to add entry for %pUl\n", >> + &cur_img_info->image_type_id); >> + continue; >> + } >> + } >> + >> +out: >> + EFI_CALL(bt->free_pool(img_info)); >> + return EFI_SUCCESS; >> +} >> + >> +static void EFIAPI efi_esrt_new_fmp_notify(struct efi_event *event, >> + void *context) >> +{ >> + efi_status_t ret; >> + efi_handle_t handle = NULL; >> + struct efi_firmware_management_protocol *fmp; >> + struct efi_boot_services *bt = systab.boottime; >> + size_t handle_buff_size = sizeof(handle); >> + >> + if (!bt) { >> + EFI_PRINT("ESRT cannot obtain pointer to BS\n"); >> + return; >> + } >> + >> + /* Obtain a single handle of the FMP type. */ >> + ret = EFI_CALL(bt->locate_handle(BY_PROTOCOL, >> + &efi_guid_firmware_management_protocol, >> + NULL, >> + &handle_buff_size, >> + &handle >> + )); >> + if (ret != EFI_SUCCESS) { > > There may be many handles for the FMP protocol. I would expect a handler > for EFI_BUFFER_TOO_SMALL here. > > It is easier to use LocateHandleBuffer() to get all FMP protocols. > > As said is wourd prefer replacing the complete ESRT when > efi_esrt_new_fmp_notify() is called instead of incremental changes. > > Best regards > > Heinrich > >> + EFI_PRINT("ESRT cannot find FMP handle\n"); >> + return; >> + } >> + >> + /* Translate the received handle to a FMP object. */ >> + ret = EFI_CALL(bt->handle_protocol(handle, >> + &efi_guid_firmware_management_protocol, >> + (void **)&fmp)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT(" ESRT cannot obtain FMP\n"); >> + return; >> + } >> + >> + /* Add all the FW images managed by FMP into the ESRT. */ >> + ret = efi_esrt_add_from_fmp(fmp); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT failed to populate ESRT entry\n"); >> + return; >> + } >> +} >> + >> +/** >> + * efi_esrt_register() - Install the ESRT system table. >> + * >> + * Return: status code >> + */ >> +efi_status_t efi_esrt_register(void) >> +{ >> + struct efi_boot_services *bt = systab.boottime; >> + struct efi_event *ev = NULL; >> + void *registration; >> + u32 num_entries = EFI_ESRT_MIN_RESIZE_ENTIRES; >> + efi_status_t ret; >> + >> + if (!bt) { >> + EFI_PRINT("ESRT cannot obtain pointer to BS\n"); >> + return EFI_NOT_READY; >> + } >> + >> + EFI_PRINT("ESRT creation start\n"); >> + >> + esrt = efi_esrt_allocate_install(bt, num_entries); >> + if (!esrt) { >> + EFI_PRINT("ESRT failed to initialize ESRT\n"); >> + return EFI_NOT_READY; >> + } >> + >> + ret = EFI_CALL(bt->create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, >> + efi_esrt_new_fmp_notify, NULL, &ev)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT failed to create event\n"); >> + return ret; >> + } >> + >> + ret = EFI_CALL(bt->register_protocol_notify(&efi_guid_firmware_management_protocol, >> + ev, ®istration)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("ESRT failed to register FMP callback\n"); >> + return ret; >> + } >> + >> + EFI_PRINT("ESRT table created\n"); >> + >> + return ret; >> +} >> diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c >> index 5800cbf6d4..0183abd09e 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; >> >> +#ifdef CONFIG_EFI_ESRT >> + ret = efi_esrt_register(); > > Please, add a comment that this function must be called before > efi_launch_capsules(). > > Your code does not work for CONFIG_EFI_CAPSULE_ON_DISK_EARLY=y because > efi_launch_capsules() is called before efi_init_obj_list(). > > @Sughosh > > I think EFI_CAPSULE_ON_DISK_EARLY has to be corrected first. > arch_efi_load_capsule_drivers() tries to install protocols on the root > handle before the root handle has been created. I was wrong here. efi_init_obj_list is always called first. Cf. https://lists.denx.de/pipermail/u-boot/2021-February/441313.html Best regards Heinrich > >> + if (ret != EFI_SUCCESS) >> + goto out; >> +#endif >> + >> if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { >> ret = efi_tcg2_register(); >> if (ret != EFI_SUCCESS) >> >