diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index cc650e1443..fc085e3c08 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -10,6 +10,7 @@
 #include <charset.h>
 #include <dfu.h>
 #include <efi_loader.h>
+#include <efi_variable.h>
 #include <fwu.h>
 #include <image.h>
 #include <signatures.h>
@@ -36,11 +37,52 @@ struct fmp_payload_header {
 	u32 lowest_supported_version;
 };
 
+/**
+ * struct fmp_state - fmp firmware update state
+ *
+ * This structure describes the state of the firmware update
+ * through FMP protocol.
+ *
+ * @fw_version:			Firmware versions used
+ * @lowest_supported_version:	Lowest supported version
+ * @last_attempt_version:	Last attempt version
+ * @last_attempt_status:	Last attempt status
+ */
+struct fmp_state {
+	u32 fw_version;
+	u32 lowest_supported_version; /* not used */
+	u32 last_attempt_version; /* not used */
+	u32 last_attempt_status; /* not used */
+};
+
 __weak void set_dfu_alt_info(char *interface, char *devstr)
 {
 	env_set("dfu_alt_info", update_info.dfu_string);
 }
 
+/**
+ * efi_firmware_get_image_type_id - get image_type_id
+ * @image_index:	image index
+ *
+ * Return the image_type_id identified by the image index.
+ *
+ * Return:		pointer to the image_type_id, NULL if image_index is invalid
+ */
+static
+efi_guid_t *efi_firmware_get_image_type_id(u8 image_index)
+{
+	int i;
+	struct efi_fw_image *fw_array;
+
+	fw_array = update_info.images;
+	for (i = 0; i < update_info.num_images; i++) {
+		if (fw_array[i].image_index == image_index)
+			return &fw_array[i].image_type_id;
+	}
+
+	return NULL;
+}
+
 /* Place holder; not supported */
 static
 efi_status_t EFIAPI efi_firmware_get_image_unsupported(
@@ -194,8 +236,6 @@ efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
 {
 	const void *image = *p_image;
 	efi_uintn_t image_size = *p_image_size;
-	u32 fmp_hdr_signature;
-	struct fmp_payload_header *header;
 	void *capsule_payload;
 	efi_status_t status;
 	efi_uintn_t capsule_payload_size;
@@ -222,24 +262,107 @@ efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
 		debug("Updating capsule without authenticating.\n");
 	}
 
-	fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
-	header = (void *)image;
+	*p_image = image;
+	*p_image_size = image_size;
+	return EFI_SUCCESS;
+}
+
+/**
+ * efi_firmware_set_fmp_state_var - set FmpStateXXXX variable
+ * @state:		Pointer to fmp state
+ * @image_index:	image index
+ *
+ * Update the FmpStateXXXX variable with the firmware update state.
+ *
+ * Return:		status code
+ */
+static
+efi_status_t efi_firmware_set_fmp_state_var(struct fmp_state *state, u8 image_index)
+{
+	u16 varname[13]; /* u"FmpStateXXXX" */
+	efi_status_t ret;
+	efi_guid_t *image_type_id;
+	struct fmp_state var_state = { 0 };
+
+	image_type_id = efi_firmware_get_image_type_id(image_index);
+	if (!image_type_id)
+		return EFI_INVALID_PARAMETER;
+
+	efi_create_indexed_name(varname, sizeof(varname), "FmpState",
+				image_index);
+
+	/*
+	 * Only the fw_version is set here.
+	 * lowest_supported_version in FmpState variable is ignored since
+	 * it can be tampered if the file based EFI variable storage is used.
+	 */
+	var_state.fw_version = state->fw_version;
+
+	ret = efi_set_variable_int(varname, image_type_id,
+				   EFI_VARIABLE_READ_ONLY |
+				   EFI_VARIABLE_NON_VOLATILE |
+				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
+				   EFI_VARIABLE_RUNTIME_ACCESS,
+				   sizeof(var_state), &var_state, false);
+
+	return ret;
+}
+
+/**
+ * efi_firmware_get_fw_version - get fw_version from FMP payload header
+ * @p_image:		Pointer to new image
+ * @p_image_size:	Pointer to size of new image
+ * @state		Pointer to fmp state
+ *
+ * Parse the FMP payload header and fill the fmp_state structure.
+ * If no FMP payload header is found, fmp_state structure is not updated.
+ *
+ */
+static void efi_firmware_get_fw_version(const void **p_image,
+					efi_uintn_t *p_image_size,
+					struct fmp_state *state)
+{
+	const void *image = *p_image;
+	efi_uintn_t image_size = *p_image_size;
+	const struct fmp_payload_header *header;
+	u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
+
+	header = image;
+	if (header->signature == fmp_hdr_signature) {
+		/* FMP header is inserted above the capsule payload */
+		state->fw_version = header->fw_version;
 
-	if (!memcmp(&header->signature, &fmp_hdr_signature,
-		    sizeof(fmp_hdr_signature))) {
-		/*
-		 * When building the capsule with the scripts in
-		 * edk2, a FMP header is inserted above the capsule
-		 * payload. Compensate for this header to get the
-		 * actual payload that is to be updated.
-		 */
 		image += header->header_size;
 		image_size -= header->header_size;
 	}
 
 	*p_image = image;
 	*p_image_size = image_size;
-	return EFI_SUCCESS;
+}
+
+/**
+ * efi_firmware_verify_image - verify image
+ * @p_image:		Pointer to new image
+ * @p_image_size:	Pointer to size of new image
+ * @image_index		Image index
+ * @state		Pointer to fmp state
+ *
+ * Verify the capsule file
+ *
+ * Return:		status code
+ */
+static
+efi_status_t efi_firmware_verify_image(const void **p_image,
+				       efi_uintn_t *p_image_size,
+				       u8 image_index,
+				       struct fmp_state *state)
+{
+	efi_status_t ret;
+
+	ret = efi_firmware_capsule_authenticate(p_image, p_image_size);
+	efi_firmware_get_fw_version(p_image, p_image_size, state);
+
+	return ret;
 }
 
 /**
@@ -331,6 +454,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
 	u16 **abort_reason)
 {
 	efi_status_t status;
+	struct fmp_state state = { 0 };
 
 	EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
 		  image_size, vendor_code, progress, abort_reason);
@@ -338,13 +462,16 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
 	if (!image || image_index != 1)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-	status = efi_firmware_capsule_authenticate(&image, &image_size);
+	status = efi_firmware_verify_image(&image, &image_size, image_index,
+					   &state);
 	if (status != EFI_SUCCESS)
 		return EFI_EXIT(status);
 
 	if (fit_update(image))
 		return EFI_EXIT(EFI_DEVICE_ERROR);
 
+	efi_firmware_set_fmp_state_var(&state, image_index);
+
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
@@ -392,6 +519,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
 {
 	int ret;
 	efi_status_t status;
+	struct fmp_state state = { 0 };
 
 	EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
 		  image_size, vendor_code, progress, abort_reason);
@@ -399,7 +527,8 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
 	if (!image)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-	status = efi_firmware_capsule_authenticate(&image, &image_size);
+	status = efi_firmware_verify_image(&image, &image_size, image_index,
+					   &state);
 	if (status != EFI_SUCCESS)
 		return EFI_EXIT(status);
 
@@ -419,6 +548,8 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
 			     NULL, NULL))
 		return EFI_EXIT(EFI_DEVICE_ERROR);
 
+	efi_firmware_set_fmp_state_var(&state, image_index);
+
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
