feat(lfa): implement LFA_GET_INVENTORY SMC

This implementation primarily retrieves activation-related flags for
a given fw_seq_id, including whether the firmware is activation
capable, whether an update is pending activation, whether it resets
the CPU during activation, whether CPU rendezvous is required, and the
firmware's UUID.
To support this, a platform API is called to determine whether an
update is available for the specified fw_seq_id, indicating its
pending activation status.

Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
Change-Id: I6e702a8b313386f5668027386845ff2dae9328e7
diff --git a/services/std_svc/lfa/bl31_lfa.c b/services/std_svc/lfa/bl31_lfa.c
index bc03385..6f66826 100644
--- a/services/std_svc/lfa/bl31_lfa.c
+++ b/services/std_svc/lfa/bl31_lfa.c
@@ -22,6 +22,8 @@
 static struct lfa_component_ops bl31_activator = {
 	.prime = lfa_bl31_prime,
 	.activate = lfa_bl31_activate,
+	.may_reset_cpu = false,
+	.cpu_rendezvous_required = true,
 };
 
 struct lfa_component_ops *get_bl31_activator(void)
diff --git a/services/std_svc/lfa/lfa_main.c b/services/std_svc/lfa/lfa_main.c
index 691609d..1af4006 100644
--- a/services/std_svc/lfa/lfa_main.c
+++ b/services/std_svc/lfa/lfa_main.c
@@ -34,6 +34,27 @@
 	return true;
 }
 
+static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
+{
+	const plat_lfa_component_info_t *comp =
+				&lfa_components[fw_seq_id];
+	uint64_t flags = 0ULL;
+
+	flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
+		 << LFA_ACTIVATION_CAPABLE_SHIFT);
+	flags |= (uint64_t)(comp->activation_pending)
+		 << LFA_ACTIVATION_PENDING_SHIFT;
+
+	if (comp->activator != NULL) {
+		flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
+			 << LFA_MAY_RESET_CPU_SHIFT);
+		flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
+			 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
+	}
+
+	return flags;
+}
+
 int lfa_setup(void)
 {
 	is_lfa_initialized = lfa_initialize_components();
@@ -50,6 +71,10 @@
 			 u_register_t x3, u_register_t x4, void *cookie,
 			 void *handle, u_register_t flags)
 {
+	uint64_t retx1, retx2;
+	uint8_t *uuid_p;
+	uint32_t fw_seq_id = (uint32_t)x1;
+
 	/**
 	 * TODO: Acquire serialization lock.
 	 */
@@ -80,6 +105,46 @@
 		break;
 
 	case LFA_GET_INVENTORY:
+		if (lfa_component_count == 0U) {
+			SMC_RET1(handle, LFA_WRONG_STATE);
+		}
+
+		/*
+		 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
+		 * platform firmware and create a valid number of firmware components.
+		 */
+		if (fw_seq_id >= lfa_component_count) {
+			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
+		}
+
+		/*
+		 * grab the UUID of asked fw_seq_id and set the return UUID
+		 * variables
+		 */
+		uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
+		memcpy(&retx1, uuid_p, sizeof(uint64_t));
+		memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
+
+		/*
+		 * check the given fw_seq_id's update available
+		 * and accordingly set the active_pending flag
+		 */
+		lfa_components[fw_seq_id].activation_pending =
+				is_plat_lfa_activation_pending(fw_seq_id);
+
+		INFO("Component %lu %s live activation:\n", x1,
+		      lfa_components[fw_seq_id].activator ? "supports" :
+		      "does not support");
+
+		if (lfa_components[fw_seq_id].activator != NULL) {
+			INFO("Activation pending: %s\n",
+			      lfa_components[fw_seq_id].activation_pending ? "true" : "false");
+		}
+
+		INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
+
+		SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
+
 		break;
 
 	case LFA_PRIME:
diff --git a/services/std_svc/rmmd/rmmd_rmm_lfa.c b/services/std_svc/rmmd/rmmd_rmm_lfa.c
index b4d9629..966266b 100644
--- a/services/std_svc/rmmd/rmmd_rmm_lfa.c
+++ b/services/std_svc/rmmd/rmmd_rmm_lfa.c
@@ -21,6 +21,8 @@
 static struct lfa_component_ops rmm_activator = {
 	.prime = lfa_rmm_prime,
 	.activate = lfa_rmm_activate,
+	.may_reset_cpu = false,
+	.cpu_rendezvous_required = true,
 };
 
 struct lfa_component_ops *get_rmm_activator(void)