From 34f363f9d1c13abecd06ec37567704d0dfc05e77 Mon Sep 17 00:00:00 2001
From: Satish Kumar <satish.kumar01@arm.com>
Date: Wed, 30 Nov 2022 19:11:43 +0000
Subject: [PATCH 24/27] arm/corstone1000: esrt support

The implementation is platform specific and would require
change in future.

The patch should not be upstreamed as it is to the u-boot.
Redesign of FMP protocol for ESRT and Capsule Update interface
is to be considered in the future.

Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
Upstream-Status: Inappropriate [Redesign of FMP protocol for ESRT and Capsule update interface is required]
Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
---
 include/efi_api.h             |   2 +-
 lib/efi_loader/efi_firmware.c | 133 ++++++++++++++++++++++++++++++++++
 lib/efi_loader/efi_setup.c    |  17 +++--
 3 files changed, 143 insertions(+), 9 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index 9bd70b0f18ce..23e427236a8f 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -2030,7 +2030,7 @@ struct efi_firmware_image_descriptor {
 	u32 last_attempt_status;
 	u64 hardware_instance;
 	efi_firmware_image_dep_t *dependencies;
-};
+} __packed;
 
 struct efi_firmware_management_protocol {
 	efi_status_t (EFIAPI *get_image_info)(
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index c883e2ff0aa9..c6ab6e2182dd 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -15,6 +15,7 @@
 #include <signatures.h>
 
 #include <linux/list.h>
+#include <efi_variable.h>
 
 #define FMP_PAYLOAD_HDR_SIGNATURE	SIGNATURE_32('M', 'S', 'S', '1')
 
@@ -417,8 +418,140 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
+
+/**
+ * efi_firmware_corstone1000_get_image_info - return information about the current
+                                    firmware image
+ * @this:                      Protocol instance
+ * @image_info_size:           Size of @image_info
+ * @image_info:                        Image information
+ * @descriptor_version:                Pointer to version number
+ * @descriptor_count:          Pointer to number of descriptors
+ * @descriptor_size:           Pointer to descriptor size
+ * package_version:            Package version
+ * package_version_name:       Package version's name
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ * Each descriptor will be created based on efi fetched variable.
+ *
+ * Return              status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_corstone1000_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_uintn_t var_size;
+	efi_status_t ret = EFI_SUCCESS;
+	efi_uintn_t image_info_size_var = 0;
+	efi_uintn_t image_info_name_size_var;
+	efi_uintn_t image_info_version_size_var;
+	u8 *runner = (u8 *)image_info;
+	u16 fmp_image_name[14] = {'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '1', '\0'};
+	u16 fmp_version_name[16] = {'F', 'm', 'p', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '1', '\0'};
+
+	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+	          image_info_size, image_info,
+	          descriptor_version, descriptor_count, descriptor_size,
+	          package_version, package_version_name);
+
+	if (!image_info_size)
+	        return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (*image_info_size &&
+	    (!image_info || !descriptor_version || !descriptor_count ||
+	     !descriptor_size || !package_version || !package_version_name))
+	        return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	var_size = sizeof(*descriptor_version);
+	ret = efi_get_variable(u"FmpDescriptorVersion",
+	                           &efi_guid_firmware_management_protocol, NULL,
+	                           &var_size, descriptor_version);
+	if (ret != EFI_SUCCESS)
+	        return EFI_EXIT(ret);
+
+	if (*descriptor_version != EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION)
+	        return EFI_EXIT(EFI_UNSUPPORTED);
+
+	var_size = sizeof(image_info_size_var);
+	ret = efi_get_variable(u"FmpImageInfoSize",
+	                           &efi_guid_firmware_management_protocol, NULL,
+	                           &var_size, &image_info_size_var);
+	if (ret != EFI_SUCCESS)
+	        return EFI_EXIT(ret);
+
+	if (*image_info_size < image_info_size_var) {
+	        *image_info_size = image_info_size_var;
+	        return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	image_info_name_size_var = image_info_size_var;
+
+	var_size = sizeof(*descriptor_count);
+	ret = efi_get_variable(u"FmpDescriptorCount",
+	                           &efi_guid_firmware_management_protocol, NULL,
+	                           &var_size, descriptor_count);
+	if (ret != EFI_SUCCESS) {
+	        return EFI_EXIT(ret);
+	}
+
+	ret = efi_get_variable(u"FmpImageInfo",
+	                           &efi_guid_firmware_management_protocol, NULL,
+	                           &image_info_size_var, image_info);
+	if (ret != EFI_SUCCESS)
+	        return EFI_EXIT(ret);
+
+	runner += image_info_size_var;
+
+	image_info_name_size_var -= image_info_size_var;
+	image_info_version_size_var = image_info_name_size_var;
+
+        /* Consider changing the string modfication logic */
+	fmp_image_name[12] = '0' + (u16)image_info->image_id;
+	ret = efi_get_variable(fmp_image_name,
+	                      &efi_guid_firmware_management_protocol, NULL,
+	                      &image_info_name_size_var, runner);
+	if (ret != EFI_SUCCESS)
+	       return EFI_EXIT(ret);
+
+	image_info_version_size_var -= image_info_name_size_var;
+	image_info->image_id_name = runner;
+	runner += image_info_name_size_var;
+
+        /* Consider changing the string modfication logic */
+	fmp_version_name[14] = '0' + (u16)image_info->image_id;
+	ret = efi_get_variable(fmp_version_name,
+	                       &efi_guid_firmware_management_protocol, NULL,
+	                       &image_info_version_size_var, runner);
+	if (ret != EFI_SUCCESS)
+	        return EFI_EXIT(ret);
+
+	image_info->version_name = runner;
+
+	*image_info_size = image_info_size_var;
+
+	*package_version = 0xffffffff; /* not supported */
+	*package_version_name = NULL; /* not supported */
+
+	return EFI_EXIT(ret);
+}
+
+#endif
+
 const struct efi_firmware_management_protocol efi_fmp_fit = {
+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
+	.get_image_info = efi_firmware_corstone1000_get_image_info,
+#else
 	.get_image_info = efi_firmware_get_image_info,
+#endif
 	.get_image = efi_firmware_get_image_unsupported,
 	.set_image = efi_firmware_fit_set_image,
 	.check_image = efi_firmware_check_image_unsupported,
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 89f988b09c44..08c742edbd12 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -167,14 +167,6 @@ static efi_status_t efi_init_capsule(void)
 	efi_status_t ret = EFI_SUCCESS;
 
 #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
-	int ffa_ret;
-
-	ffa_ret = efi_corstone1000_uboot_efi_started_event();
-	if (ffa_ret)
-		debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n");
-	else
-		debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n");
-
 	ret = efi_corstone1000_alloc_capsule_shared_buf();
 	if (ret != EFI_SUCCESS) {
 		printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n");
@@ -288,6 +280,15 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 
+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
+		int ffa_ret;
+		ffa_ret = efi_corstone1000_uboot_efi_started_event();
+		if (ffa_ret)
+			debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n");
+		else
+			debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n");
+#endif
+
 	/* Initialize variable services */
 	ret = efi_init_variables();
 	if (ret != EFI_SUCCESS)
-- 
2.39.1

