summaryrefslogtreecommitdiffstats
path: root/FmpDevicePkg
diff options
context:
space:
mode:
authorEric Jin <eric.jin@intel.com>2019-08-12 13:00:59 +0800
committerLiming Gao <liming.gao@intel.com>2019-08-15 17:22:23 +0800
commit67c1e5ee6eaf592e0331bc06df41ec4c21b22a07 (patch)
tree7691e8bb153d21b76074b5af2096ca1b045bb6f7 /FmpDevicePkg
parent4f0544b144b953ed4e8b4221fc33353f4481ec14 (diff)
downloadedk2-67c1e5ee6eaf592e0331bc06df41ec4c21b22a07.tar.gz
edk2-67c1e5ee6eaf592e0331bc06df41ec4c21b22a07.tar.bz2
edk2-67c1e5ee6eaf592e0331bc06df41ec4c21b22a07.zip
FmpDevicePkg/FmpDxe: Different variable for each FMP Descriptor
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1525 Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Eric Jin <eric.jin@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
Diffstat (limited to 'FmpDevicePkg')
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxe.c133
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxe.h8
-rw-r--r--FmpDevicePkg/FmpDxe/VariableSupport.c824
-rw-r--r--FmpDevicePkg/FmpDxe/VariableSupport.h135
4 files changed, 792 insertions, 308 deletions
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index dab3310834..17c3378fa2 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -11,6 +11,7 @@
**/
#include "FmpDxe.h"
+#include "VariableSupport.h"
///
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
@@ -73,7 +74,13 @@ const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate =
NULL, // VersionName
TRUE, // RuntimeVersionSupported
NULL, // FmpDeviceLockEvent
- FALSE // FmpDeviceLocked
+ FALSE, // FmpDeviceLocked
+ NULL, // FmpDeviceContext
+ NULL, // VersionVariableName
+ NULL, // LsvVariableName
+ NULL, // LastAttemptStatusVariableName
+ NULL, // LastAttemptVersionVariableName
+ NULL // FmpStateVariableName
};
///
@@ -142,7 +149,7 @@ FmpDxeProgress (
the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
a GUID value, then gEfiCallerIdGuid is returned.
- @return The ImageTypeId GUID
+ @retval The ImageTypeId GUID
**/
EFI_GUID *
@@ -171,7 +178,7 @@ GetImageTypeIdGuid (
/**
Returns a pointer to the Null-terminated Unicode ImageIdName string.
- @return Null-terminated Unicode ImageIdName string.
+ @retval Null-terminated Unicode ImageIdName string.
**/
CHAR16 *
@@ -188,12 +195,15 @@ GetImageTypeNameString (
2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
3. Check Fixed at build PCD
- @return The largest value
+ @param[in] Private Pointer to the private context structure for the
+ Firmware Management Protocol instance.
+
+ @retval The largest value
**/
UINT32
GetLowestSupportedVersion (
- VOID
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
@@ -230,7 +240,7 @@ GetLowestSupportedVersion (
//
// Check the lowest supported version UEFI variable for this device
//
- VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();
+ VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);
if (VariableLowestSupportedVersion > ReturnLsv) {
ReturnLsv = VariableLowestSupportedVersion;
}
@@ -266,6 +276,20 @@ PopulateDescriptor (
Private->Descriptor.ImageIdName = GetImageTypeNameString();
//
+ // Get the hardware instance from FmpDeviceLib
+ //
+ Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
+ if (Status == EFI_UNSUPPORTED) {
+ Private->Descriptor.HardwareInstance = 0;
+ }
+
+ //
+ // Generate UEFI Variable names used to store status information for this
+ // FMP instance.
+ //
+ GenerateFmpVariableNames (Private);
+
+ //
// Get the version. Some devices don't support getting the firmware version
// at runtime. If FmpDeviceLib does not support returning a version, then
// it is stored in a UEFI variable.
@@ -273,7 +297,7 @@ PopulateDescriptor (
Status = FmpDeviceGetVersion (&Private->Descriptor.Version);
if (Status == EFI_UNSUPPORTED) {
Private->RuntimeVersionSupported = FALSE;
- Private->Descriptor.Version = GetVersionFromVariable();
+ Private->Descriptor.Version = GetVersionFromVariable (Private);
} else if (EFI_ERROR (Status)) {
//
// Unexpected error. Use default version.
@@ -309,7 +333,7 @@ PopulateDescriptor (
);
}
- Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion();
+ Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);
//
// Get attributes from the FmpDeviceLib
@@ -341,16 +365,8 @@ PopulateDescriptor (
Private->Descriptor.Size = 0;
}
- Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable ();
- Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable ();
-
- //
- // Get the hardware instance from FmpDeviceLib
- //
- Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
- if (Status == EFI_UNSUPPORTED) {
- Private->Descriptor.HardwareInstance = 0;
- }
+ Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);
+ Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
Private->DescriptorPopulated = TRUE;
}
@@ -453,7 +469,7 @@ GetTheImageInfo (
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
//
- // make sure the descriptor has already been loaded
+ // Make sure the descriptor has already been loaded or refreshed
//
PopulateDescriptor (Private);
@@ -696,7 +712,7 @@ CheckTheImage (
FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
//
- // make sure the descriptor has already been loaded
+ // Make sure the descriptor has already been loaded or refreshed
//
PopulateDescriptor (Private);
@@ -949,7 +965,15 @@ SetTheImage (
Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.
+ //
+ // Make sure the descriptor has already been loaded or refreshed
+ //
+ PopulateDescriptor (Private);
+
+ //
+ // Set to 0 to clear any previous results.
+ //
+ SetLastAttemptVersionInVariable (Private, IncommingFwVersion);
//
// if we have locked the device, then skip the set operation.
@@ -988,7 +1012,7 @@ SetTheImage (
//
// Set to actual value
//
- SetLastAttemptVersionInVariable (IncommingFwVersion);
+ SetLastAttemptVersionInVariable (Private, IncommingFwVersion);
}
@@ -1080,7 +1104,7 @@ SetTheImage (
// Save LastAttemptStatus as error so that if SetImage never returns the error
// state is recorded.
//
- SetLastAttemptStatusInVariable (LastAttemptStatus);
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
//
// Strip off all the headers so the device can process its firmware
@@ -1132,23 +1156,21 @@ SetTheImage (
if (!Private->RuntimeVersionSupported) {
Version = DEFAULT_VERSION;
GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
- SetVersionInVariable (Version);
+ SetVersionInVariable (Private, Version);
}
//
// Update lowest supported variable
//
- {
- LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
- GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
- SetLowestSupportedVersionInVariable (LowestSupportedVersion);
- }
+ LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
+ GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
+ SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
cleanup:
mProgressFunc = NULL;
- SetLastAttemptStatusInVariable (LastAttemptStatus);
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
if (Progress != NULL) {
//
@@ -1359,13 +1381,18 @@ InstallFmpInstance (
goto cleanup;
}
+ //
+ // Make sure the descriptor has already been loaded or refreshed
+ //
+ PopulateDescriptor (Private);
+
DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Lock events\n"));
if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
//
// Lock all UEFI Variables used by this module.
//
- Status = LockAllFmpVariables ();
+ Status = LockAllFmpVariables (Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n", Status));
} else {
@@ -1417,6 +1444,27 @@ cleanup:
if (Private->FmpDeviceLockEvent != NULL) {
gBS->CloseEvent (Private->FmpDeviceLockEvent);
}
+ if (Private->Descriptor.VersionName != NULL) {
+ FreePool (Private->Descriptor.VersionName);
+ }
+ if (Private->FmpDeviceContext != NULL) {
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
+ }
+ if (Private->VersionVariableName != NULL) {
+ FreePool (Private->VersionVariableName);
+ }
+ if (Private->LsvVariableName != NULL) {
+ FreePool (Private->LsvVariableName);
+ }
+ if (Private->LastAttemptStatusVariableName != NULL) {
+ FreePool (Private->LastAttemptStatusVariableName);
+ }
+ if (Private->LastAttemptVersionVariableName != NULL) {
+ FreePool (Private->LastAttemptVersionVariableName);
+ }
+ if (Private->FmpStateVariableName != NULL) {
+ FreePool (Private->FmpStateVariableName);
+ }
FreePool (Private);
}
}
@@ -1473,8 +1521,27 @@ UninstallFmpInstance (
return Status;
}
- FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
-
+ if (Private->Descriptor.VersionName != NULL) {
+ FreePool (Private->Descriptor.VersionName);
+ }
+ if (Private->FmpDeviceContext != NULL) {
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
+ }
+ if (Private->VersionVariableName != NULL) {
+ FreePool (Private->VersionVariableName);
+ }
+ if (Private->LsvVariableName != NULL) {
+ FreePool (Private->LsvVariableName);
+ }
+ if (Private->LastAttemptStatusVariableName != NULL) {
+ FreePool (Private->LastAttemptStatusVariableName);
+ }
+ if (Private->LastAttemptVersionVariableName != NULL) {
+ FreePool (Private->LastAttemptVersionVariableName);
+ }
+ if (Private->FmpStateVariableName != NULL) {
+ FreePool (Private->FmpStateVariableName);
+ }
FreePool (Private);
return EFI_SUCCESS;
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h
index c2ffc439d1..06514c67c8 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.h
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.h
@@ -18,6 +18,7 @@
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/FmpAuthenticationLib.h>
@@ -26,9 +27,9 @@
#include <Library/CapsuleUpdatePolicyLib.h>
#include <Protocol/FirmwareManagement.h>
#include <Protocol/FirmwareManagementProgress.h>
+#include <Protocol/VariableLock.h>
#include <Guid/SystemResourceTable.h>
#include <Guid/EventGroup.h>
-#include "VariableSupport.h"
#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
@@ -57,6 +58,11 @@ typedef struct {
//
BOOLEAN FmpDeviceLocked;
VOID *FmpDeviceContext;
+ CHAR16 *VersionVariableName;
+ CHAR16 *LsvVariableName;
+ CHAR16 *LastAttemptStatusVariableName;
+ CHAR16 *LastAttemptVersionVariableName;
+ CHAR16 *FmpStateVariableName;
} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
///
diff --git a/FmpDevicePkg/FmpDxe/VariableSupport.c b/FmpDevicePkg/FmpDxe/VariableSupport.c
index 57f4388df2..d06d6b36c7 100644
--- a/FmpDevicePkg/FmpDxe/VariableSupport.c
+++ b/FmpDevicePkg/FmpDxe/VariableSupport.c
@@ -3,81 +3,339 @@
firmware updates.
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiDxe.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Protocol/VariableLock.h>
+#include "FmpDxe.h"
#include "VariableSupport.h"
-///
-/// Array of UEFI variable names that are locked in LockAllFmpVariables().
-///
-const CHAR16 *mFmpVariableLockList[] = {
- VARNAME_VERSION,
- VARNAME_LSV,
- VARNAME_LASTATTEMPTSTATUS,
- VARNAME_LASTATTEMPTVERSION
-};
+/**
+ Retrieve the value of a 32-bit UEFI Variable specified by VariableName and
+ a GUID of gEfiCallerIdGuid.
+
+ @param[in] VariableName Pointer to the UEFI Variable name to retrieve.
+ @param[out] Valid Set to TRUE if UEFI Variable is present and the size
+ of the UEFI Variable value is 32-bits. Otherwise
+ FALSE.
+ @param[out] Value If Valid is set to TRUE, then the 32-bit value of
+ the UEFI Variable. Otherwise 0.
+**/
+static
+VOID
+GetFmpVariable (
+ IN CHAR16 *VariableName,
+ OUT BOOLEAN *Valid,
+ OUT UINT32 *Value
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT32 *Buffer;
+
+ *Valid = FALSE;
+ *Value = 0;
+ Size = 0;
+ Buffer = NULL;
+ Status = GetVariable2 (
+ VariableName,
+ &gEfiCallerIdGuid,
+ (VOID **)&Buffer,
+ &Size
+ );
+ if (!EFI_ERROR (Status) && Size == sizeof (*Value) && Buffer != NULL) {
+ *Valid = TRUE;
+ *Value = *Buffer;
+ }
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+}
/**
- Returns the value used to fill in the Version field of the
- EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
- service of the Firmware Management Protocol. The value is read from a UEFI
- variable. If the UEFI variables does not exist, then a default version value
- is returned.
+ Delete the UEFI Variable with name specified by VariableName and GUID of
+ gEfiCallerIdGuid. If the variable can not be deleted, then print a
+ DEBUG_ERROR message.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
+ @param[in] VariableName Pointer to the UEFI Variable name to delete.
+**/
+static
+VOID
+DeleteFmpVariable (
+ IN CHAR16 *VariableName
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Valid;
+ UINT32 Value;
- @return The version of the firmware image in the firmware device.
+ GetFmpVariable (VariableName, &Valid, &Value);
+ if (Valid) {
+ Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to delete FMP Variable %s. Status = %r\n", VariableName, Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "Deleted FMP Variable %s\n", VariableName));
+ }
+ }
+}
+
+/**
+ Retrieve the FMP Controller State UEFI Variable value. Return NULL if
+ the variable does not exist or if the size of the UEFI Variable is not the
+ size of FMP_CONTROLLER_STATE. The buffer for the UEFI Variable value
+ if allocated using the UEFI Boot Service AllocatePool().
+ @param[in] Private Private context structure for the managed controller.
+
+ @return Pointer to the allocated FMP Controller State. Returns NULL
+ if the variable does not exist or is a different size than expected.
**/
-UINT32
-GetVersionFromVariable (
- VOID
+static
+FMP_CONTROLLER_STATE *
+GetFmpControllerState (
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
- EFI_STATUS Status;
- UINT32 *Value;
- UINTN Size;
- UINT32 Version;
+ EFI_STATUS Status;
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ UINTN Size;
+
+ FmpControllerState = NULL;
+ Size = 0;
+ Status = GetVariable2 (
+ Private->FmpStateVariableName,
+ &gEfiCallerIdGuid,
+ (VOID **)&FmpControllerState,
+ &Size
+ );
+ if (EFI_ERROR (Status) || FmpControllerState == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to get the FMP Controller State. Status = %r\n", Status));
+ } else {
+ if (Size == sizeof (*FmpControllerState)) {
+ return FmpControllerState;
+ }
+ DEBUG ((DEBUG_ERROR, "Getting FMP Controller State returned a size different than expected. Size = 0x%x\n", Size));
+ }
+ if (FmpControllerState != NULL) {
+ FreePool (FmpControllerState);
+ }
+ return NULL;
+}
- Value = NULL;
- Size = 0;
- Version = DEFAULT_VERSION;
+/**
+ Generates a Null-terminated Unicode string UEFI Variable name from a base name
+ and a hardware instance. If the hardware instance value is 0, then the base
+ name is returned. If the hardware instance value is non-zero, then the 64-bit
+ hardware instance value is converted to a 16 character hex string and appended
+ to base name. The UEFI Variable name returned is allocated using the UEFI
+ Boot Service AllocatePool().
+
+ @param[in] HardwareInstance 64-bit hardware instance value.
+ @param[in] BaseVariableName Null-terminated Unicode string that is the base
+ name of the UEFI Variable.
+
+ @return Pointer to the allocated UEFI Variable name. Returns NULL if the
+ UEFI Variable can not be allocated.
+**/
+static
+CHAR16 *
+GenerateFmpVariableName (
+ IN UINT64 HardwareInstance,
+ IN CHAR16 *BaseVariableName
+ )
+{
+ CHAR16 *VariableName;
+
+ VariableName = CatSPrint (NULL, BaseVariableName);
+ if (VariableName == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to generate FMP variable name %s.\n", BaseVariableName));
+ return VariableName;
+ }
+ if (HardwareInstance == 0) {
+ return VariableName;
+ }
+ VariableName = CatSPrint (VariableName, L"%016lx", HardwareInstance);
+ if (VariableName == NULL) {
+ DEBUG ((DEBUG_ERROR, "Failed to generate FMP variable name %s.\n", BaseVariableName));
+ }
+ return VariableName;
+}
+
+/**
+ Generate the names of the UEFI Variables used to store state information for
+ a managed controller. The UEFI Variables names are a combination of a base
+ name and an optional hardware instance value as a 16 character hex value. If
+ the hardware instance value is 0, then the 16 character hex value is not
+ included. These storage for the UEFI Variable names are allocated using the
+ UEFI Boot Service AllocatePool() and the pointers are stored in the Private.
+ The following are examples of variable names produces for hardware instance
+ value 0 and value 0x1234567812345678.
+
+ FmpVersion
+ FmpLsv
+ LastAttemptStatus
+ LastAttemptVersion
+ FmpState
+
+ FmpVersion1234567812345678
+ FmpLsv1234567812345678
+ LastAttemptStatus1234567812345678
+ LastAttemptVersion1234567812345678
+ FmpState1234567812345678
+
+ @param[in,out] Private Private context structure for the managed controller.
+**/
+VOID
+GenerateFmpVariableNames (
+ IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+ FMP_CONTROLLER_STATE FmpControllerState;
+
+ if (Private->VersionVariableName != NULL) {
+ FreePool (Private->VersionVariableName);
+ }
+ if (Private->LsvVariableName != NULL) {
+ FreePool (Private->LsvVariableName);
+ }
+ if (Private->LastAttemptStatusVariableName != NULL) {
+ FreePool (Private->LastAttemptStatusVariableName);
+ }
+ if (Private->LastAttemptVersionVariableName != NULL) {
+ FreePool (Private->LastAttemptVersionVariableName);
+ }
+ if (Private->FmpStateVariableName != NULL) {
+ FreePool (Private->FmpStateVariableName);
+ }
- Status = GetVariable2 (VARNAME_VERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);
- if (EFI_ERROR (Status) || (Value == NULL)) {
- DEBUG ((DEBUG_ERROR, "Failed to get the Version from variable. Status = %r\n", Status));
- return Version;
+ Private->VersionVariableName = GenerateFmpVariableName (
+ Private->Descriptor.HardwareInstance,
+ VARNAME_VERSION
+ );
+ Private->LsvVariableName = GenerateFmpVariableName (
+ Private->Descriptor.HardwareInstance,
+ VARNAME_LSV
+ );
+ Private->LastAttemptStatusVariableName = GenerateFmpVariableName (
+ Private->Descriptor.HardwareInstance,
+ VARNAME_LASTATTEMPTSTATUS
+ );
+ Private->LastAttemptVersionVariableName = GenerateFmpVariableName (
+ Private->Descriptor.HardwareInstance,
+ VARNAME_LASTATTEMPTVERSION
+ );
+ Private->FmpStateVariableName = GenerateFmpVariableName (
+ Private->Descriptor.HardwareInstance,
+ VARNAME_FMPSTATE
+ );
+
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->VersionVariableName));
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LsvVariableName));
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->FmpStateVariableName));
+
+ Buffer = GetFmpControllerState (Private);
+ if (Buffer != NULL) {
+ //
+ // FMP Controller State was found with correct size.
+ // Delete old variables if they exist.
+ //
+ FreePool (Buffer);
+ DeleteFmpVariable (Private->VersionVariableName);
+ DeleteFmpVariable (Private->LsvVariableName);
+ DeleteFmpVariable (Private->LastAttemptStatusVariableName);
+ DeleteFmpVariable (Private->LastAttemptVersionVariableName);
+ return;
}
//
- // No error from call
+ // FMP Controller State was either not found or is wrong size.
+ // Create a new FMP Controller State variable with the correct size.
//
- if (Size == sizeof (*Value)) {
+ DEBUG ((DEBUG_INFO, "Create FMP Controller State\n"));
+ GetFmpVariable (
+ Private->VersionVariableName,
+ &FmpControllerState.VersionValid,
+ &FmpControllerState.Version
+ );
+ GetFmpVariable (
+ Private->LsvVariableName,
+ &FmpControllerState.LsvValid,
+ &FmpControllerState.Lsv
+ );
+ GetFmpVariable (
+ Private->LastAttemptStatusVariableName,
+ &FmpControllerState.LastAttemptStatusValid,
+ &FmpControllerState.LastAttemptStatus
+ );
+ GetFmpVariable (
+ Private->LastAttemptVersionVariableName,
+ &FmpControllerState.LastAttemptVersionValid,
+ &FmpControllerState.LastAttemptVersion
+ );
+ Status = gRT->SetVariable (
+ Private->FmpStateVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (FmpControllerState),
+ &FmpControllerState
+ );
+ if (EFI_ERROR (Status)) {
//
- // Successful read
+ // Failed to create FMP Controller State. In this case, do not
+ // delete the individual variables. They can be used again on next boot
+ // to create the FMP Controller State.
//
- Version = *Value;
+ DEBUG ((DEBUG_ERROR, "Failed to create FMP Controller State. Status = %r\n", Status));
} else {
- //
- // Return default since size was unknown
- //
- DEBUG ((DEBUG_ERROR, "Getting version Variable returned a size different than expected. Size = 0x%x\n", Size));
+ DeleteFmpVariable (Private->VersionVariableName);
+ DeleteFmpVariable (Private->LsvVariableName);
+ DeleteFmpVariable (Private->LastAttemptStatusVariableName);
+ DeleteFmpVariable (Private->LastAttemptVersionVariableName);
}
+}
- FreePool (Value);
+/**
+ Returns the value used to fill in the Version field of the
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
+ service of the Firmware Management Protocol. The value is read from a UEFI
+ variable. If the UEFI variables does not exist, then a default version value
+ is returned.
+
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
- return Version;
+ @param[in] Private Private context structure for the managed controller.
+
+ @return The version of the firmware image in the firmware device.
+**/
+UINT32
+GetVersionFromVariable (
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
+ )
+{
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ UINT32 Value;
+
+ Value = DEFAULT_VERSION;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState != NULL) {
+ if (FmpControllerState->VersionValid) {
+ Value = FmpControllerState->Version;
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s Version %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ Value
+ ));
+ }
+ FreePool (FmpControllerState);
+ }
+ return Value;
}
/**
@@ -87,50 +345,35 @@ GetVersionFromVariable (
variable. If the UEFI variables does not exist, then a default lowest
supported version value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
+
+ @param[in] Private Private context structure for the managed controller.
@return The lowest supported version of the firmware image in the firmware
device.
-
**/
UINT32
GetLowestSupportedVersionFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
- EFI_STATUS Status;
- UINT32 *Value;
- UINTN Size;
- UINT32 Version;
-
- Value = NULL;
- Size = 0;
- Version = DEFAULT_LOWESTSUPPORTEDVERSION;
-
- Status = GetVariable2 (VARNAME_LSV, &gEfiCallerIdGuid, (VOID **)&Value, &Size);
- if (EFI_ERROR (Status) || (Value == NULL)) {
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Lowest Supported Version from variable. Status = %r\n", Status));
- return Version;
- }
-
- //
- // No error from call
- //
- if (Size == sizeof (*Value)) {
- //
- // Successful read
- //
- Version = *Value;
- } else {
- //
- // Return default since size was unknown
- //
- DEBUG ((DEBUG_ERROR, "Getting LSV Variable returned a size different than expected. Size = 0x%x\n", Size));
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ UINT32 Value;
+
+ Value = DEFAULT_LOWESTSUPPORTEDVERSION;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState != NULL) {
+ if (FmpControllerState->LsvValid) {
+ Value = FmpControllerState->Lsv;
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LowestSupportedVersion %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ Value
+ ));
+ }
+ FreePool (FmpControllerState);
}
-
- FreePool (Value);
-
- return Version;
+ return Value;
}
/**
@@ -140,53 +383,34 @@ GetLowestSupportedVersionFromVariable (
variable. If the UEFI variables does not exist, then a default last attempt
status value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
- @return The last attempt status value for the most recent capsule update.
+ @param[in] Private Private context structure for the managed controller.
+ @return The last attempt status value for the most recent capsule update.
**/
UINT32
GetLastAttemptStatusFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
- EFI_STATUS Status;
- UINT32 *Value;
- UINTN Size;
- UINT32 LastAttemptStatus;
-
- Value = NULL;
- Size = 0;
- LastAttemptStatus = DEFAULT_LASTATTEMPT;
-
- Status = GetVariable2 (VARNAME_LASTATTEMPTSTATUS, &gEfiCallerIdGuid, (VOID **)&Value, &Size);
- if (EFI_ERROR (Status) || (Value == NULL)) {
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Status from variable. Status = %r\n", Status));
- return LastAttemptStatus;
- }
-
- //
- // No error from call
- //
- if (Size == sizeof (*Value)) {
- //
- // Successful read
- //
- LastAttemptStatus = *Value;
- } else {
- //
- // Return default since size was unknown
- //
- DEBUG (
- (DEBUG_ERROR,
- "Getting Last Attempt Status Variable returned a size different than expected. Size = 0x%x\n",
- Size)
- );
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ UINT32 Value;
+
+ Value = DEFAULT_LASTATTEMPTSTATUS;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState != NULL) {
+ if (FmpControllerState->LastAttemptStatusValid) {
+ Value = FmpControllerState->LastAttemptStatus;
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptStatus %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ Value
+ ));
+ }
+ FreePool (FmpControllerState);
}
-
- FreePool (Value);
-
- return LastAttemptStatus;
+ return Value;
}
/**
@@ -196,219 +420,343 @@ GetLastAttemptStatusFromVariable (
variable. If the UEFI variables does not exist, then a default last attempt
version value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
- @return The last attempt version value for the most recent capsule update.
+ @param[in] Private Private context structure for the managed controller.
+ @return The last attempt version value for the most recent capsule update.
**/
UINT32
GetLastAttemptVersionFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
- EFI_STATUS Status;
- UINT32 *Value;
- UINTN Size;
- UINT32 Version;
-
- Value = NULL;
- Size = 0;
- Version = DEFAULT_LASTATTEMPT;
-
- Status = GetVariable2 (VARNAME_LASTATTEMPTVERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);
- if (EFI_ERROR (Status) || (Value == NULL)) {
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Version from variable. Status = %r\n", Status));
- return Version;
- }
-
- //
- // No error from call
- //
- if (Size == sizeof (*Value)) {
- //
- // Successful read
- //
- Version = *Value;
- } else {
- //
- // Return default since size was unknown
- //
- DEBUG (
- (DEBUG_ERROR,
- "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n",
- Size)
- );
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ UINT32 Value;
+
+ Value = DEFAULT_LASTATTEMPTVERSION;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState != NULL) {
+ if (FmpControllerState->LastAttemptVersionValid) {
+ Value = FmpControllerState->LastAttemptVersion;
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptVersion %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ Value
+ ));
+ }
+ FreePool (FmpControllerState);
}
-
- FreePool (Value);
-
- return Version;
+ return Value;
}
-
/**
Saves the version current of the firmware image in the firmware device to a
UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
+ @param[in] Private Private context structure for the managed controller.
@param[in] Version The version of the firmware image in the firmware device.
-
**/
VOID
SetVersionInVariable (
- UINT32 Version
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 Version
)
{
- EFI_STATUS Status;
- UINT32 Current;
+ EFI_STATUS Status;
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ BOOLEAN Update;
- Status = EFI_SUCCESS;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState == NULL) {
+ //
+ // Can not update value if FMP Controller State does not exist.
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().
+ //
+ return;
+ }
- Current = GetVersionFromVariable();
- if (Current != Version) {
+ Update = FALSE;
+ if (!FmpControllerState->VersionValid) {
+ Update = TRUE;
+ }
+ if (FmpControllerState->Version != Version) {
+ Update = TRUE;
+ }
+ if (!Update) {
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
+ } else {
+ FmpControllerState->VersionValid = TRUE;
+ FmpControllerState->Version = Version;
Status = gRT->SetVariable (
- VARNAME_VERSION,
+ Private->FmpStateVariableName,
&gEfiCallerIdGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof (Version),
- &Version
+ sizeof (*FmpControllerState),
+ FmpControllerState
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to set the Version into a variable. Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s Version %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ Version
+ ));
}
- } else {
- DEBUG ((DEBUG_INFO, "Version variable doesn't need to update. Same value as before.\n"));
}
+ FreePool (FmpControllerState);
}
/**
Saves the lowest supported version current of the firmware image in the
firmware device to a UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
-
- @param[in] LowestSupportedVersion The lowest supported version of the firmware image
- in the firmware device.
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
+ @param[in] Private Private context structure for the managed
+ controller.
+ @param[in] LowestSupportedVersion The lowest supported version of the
+ firmware image in the firmware device.
**/
VOID
SetLowestSupportedVersionInVariable (
- UINT32 LowestSupportedVersion
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LowestSupportedVersion
)
{
- EFI_STATUS Status;
- UINT32 Current;
+ EFI_STATUS Status;
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ BOOLEAN Update;
- Status = EFI_SUCCESS;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState == NULL) {
+ //
+ // Can not update value if FMP Controller State does not exist.
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().
+ //
+ return;
+ }
- Current = GetLowestSupportedVersionFromVariable();
- if (LowestSupportedVersion > Current) {
+ Update = FALSE;
+ if (!FmpControllerState->LsvValid) {
+ Update = TRUE;
+ }
+ if (FmpControllerState->Lsv < LowestSupportedVersion) {
+ Update = TRUE;
+ }
+ if (!Update) {
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
+ } else {
+ FmpControllerState->LsvValid = TRUE;
+ FmpControllerState->Lsv = LowestSupportedVersion;
Status = gRT->SetVariable (
- VARNAME_LSV,
+ Private->FmpStateVariableName,
&gEfiCallerIdGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof (LowestSupportedVersion), &LowestSupportedVersion
+ sizeof (*FmpControllerState),
+ FmpControllerState
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to set the LSV into a variable. Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LowestSupportedVersion %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ LowestSupportedVersion
+ ));
}
- } else {
- DEBUG ((DEBUG_INFO, "LSV variable doesn't need to update. Same value as before.\n"));
}
+ FreePool (FmpControllerState);
}
/**
Saves the last attempt status value of the most recent FMP capsule update to a
UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
+ @param[in] Private Private context structure for the managed
+ controller.
@param[in] LastAttemptStatus The last attempt status of the most recent FMP
capsule update.
-
**/
VOID
SetLastAttemptStatusInVariable (
- UINT32 LastAttemptStatus
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LastAttemptStatus
)
{
- EFI_STATUS Status;
- UINT32 Current;
+ EFI_STATUS Status;
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ BOOLEAN Update;
- Status = EFI_SUCCESS;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState == NULL) {
+ //
+ // Can not update value if FMP Controller State does not exist.
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().
+ //
+ return;
+ }
- Current = GetLastAttemptStatusFromVariable();
- if (Current != LastAttemptStatus) {
+ Update = FALSE;
+ if (!FmpControllerState->LastAttemptStatusValid) {
+ Update = TRUE;
+ }
+ if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {
+ Update = TRUE;
+ }
+ if (!Update) {
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
+ } else {
+ FmpControllerState->LastAttemptStatusValid = TRUE;
+ FmpControllerState->LastAttemptStatus = LastAttemptStatus;
Status = gRT->SetVariable (
- VARNAME_LASTATTEMPTSTATUS,
+ Private->FmpStateVariableName,
&gEfiCallerIdGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof (LastAttemptStatus),
- &LastAttemptStatus
+ sizeof (*FmpControllerState),
+ FmpControllerState
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptStatus into a variable. Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptStatus %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ LastAttemptStatus
+ ));
}
- } else {
- DEBUG ((DEBUG_INFO, "LastAttemptStatus variable doesn't need to update. Same value as before.\n"));
}
+ FreePool (FmpControllerState);
}
/**
Saves the last attempt version value of the most recent FMP capsule update to
a UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
+ @param[in] Private Private context structure for the managed
+ controller.
@param[in] LastAttemptVersion The last attempt version value of the most
recent FMP capsule update.
-
**/
VOID
SetLastAttemptVersionInVariable (
- UINT32 LastAttemptVersion
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LastAttemptVersion
)
{
- EFI_STATUS Status;
- UINT32 Current;
+ EFI_STATUS Status;
+ FMP_CONTROLLER_STATE *FmpControllerState;
+ BOOLEAN Update;
- Status = EFI_SUCCESS;
+ FmpControllerState = GetFmpControllerState (Private);
+ if (FmpControllerState == NULL) {
+ //
+ // Can not update value if FMP Controller State does not exist.
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().
+ //
+ return;
+ }
- Current = GetLastAttemptVersionFromVariable();
- if (Current != LastAttemptVersion) {
+ Update = FALSE;
+ if (!FmpControllerState->LastAttemptVersionValid) {
+ Update = TRUE;
+ }
+ if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {
+ Update = TRUE;
+ }
+ if (!Update) {
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
+ } else {
+ FmpControllerState->LastAttemptVersionValid = TRUE;
+ FmpControllerState->LastAttemptVersion = LastAttemptVersion;
Status = gRT->SetVariable (
- VARNAME_LASTATTEMPTVERSION,
+ Private->FmpStateVariableName,
&gEfiCallerIdGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof (LastAttemptVersion),
- &LastAttemptVersion
+ sizeof (*FmpControllerState),
+ FmpControllerState
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptVersion into a variable. Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptVersion %08x\n",
+ &gEfiCallerIdGuid,
+ Private->FmpStateVariableName,
+ LastAttemptVersion
+ ));
}
- } else {
- DEBUG ((DEBUG_INFO, "LastAttemptVersion variable doesn't need to update. Same value as before.\n"));
}
+ FreePool (FmpControllerState);
}
/**
- Locks all the UEFI Variables used by this module.
+ Attempts to lock a single UEFI Variable propagating the error state of the
+ first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.
+
+ @param[in] PreviousStatus The previous UEFI Variable lock attempt status.
+ @param[in] VariableLock The EDK II Variable Lock Protocol instance.
+ @param[in] VariableName The name of the UEFI Variable to lock.
+
+ @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable
+ lock attempt also succeeded.
+ @retval Other The UEFI Variable could not be locked or the previous
+ variable lock attempt failed.
+**/
+static
+EFI_STATUS
+LockFmpVariable (
+ IN EFI_STATUS PreviousStatus,
+ IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock,
+ IN CHAR16 *VariableName
+ )
+{
+ EFI_STATUS Status;
+
+ Status = VariableLock->RequestToLock (
+ VariableLock,
+ VariableName,
+ &gEfiCallerIdGuid
+ );
+ if (!EFI_ERROR (Status)) {
+ return PreviousStatus;
+ }
+
+ DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",
+ &gEfiCallerIdGuid,
+ VariableName,
+ Status
+ ));
+
+ if (EFI_ERROR (PreviousStatus)) {
+ return PreviousStatus;
+ }
+ return Status;
+}
+
+/**
+ Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
+ executing module.
+
+ @param[in] Private Private context structure for the managed controller.
@retval EFI_SUCCESS All UEFI variables are locked.
@retval EFI_UNSUPPORTED Variable Lock Protocol not found.
@retval Other One of the UEFI variables could not be locked.
-
**/
EFI_STATUS
LockAllFmpVariables (
- VOID
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
- EFI_STATUS ReturnStatus;
- UINTN Index;
VariableLock = NULL;
Status = gBS->LocateProtocol (
@@ -416,29 +764,17 @@ LockAllFmpVariables (
NULL,
(VOID **)&VariableLock
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || VariableLock == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status));
return EFI_UNSUPPORTED;
}
- ReturnStatus = EFI_SUCCESS;
- for (Index = 0; Index < ARRAY_SIZE (mFmpVariableLockList); Index++) {
- Status = VariableLock->RequestToLock (
- VariableLock,
- (CHAR16 *)mFmpVariableLockList[Index],
- &gEfiCallerIdGuid
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",
- &gEfiCallerIdGuid,
- mFmpVariableLockList[Index],
- Status
- ));
- if (!EFI_ERROR (ReturnStatus)) {
- ReturnStatus = Status;
- }
- }
- }
+ Status = EFI_SUCCESS;
+ Status = LockFmpVariable (Status, VariableLock, Private->VersionVariableName);
+ Status = LockFmpVariable (Status, VariableLock, Private->LsvVariableName);
+ Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptStatusVariableName);
+ Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptVersionVariableName);
+ Status = LockFmpVariable (Status, VariableLock, Private->FmpStateVariableName);
- return ReturnStatus;
+ return Status;
}
diff --git a/FmpDevicePkg/FmpDxe/VariableSupport.h b/FmpDevicePkg/FmpDxe/VariableSupport.h
index b5079a9900..23f24f2a13 100644
--- a/FmpDevicePkg/FmpDxe/VariableSupport.h
+++ b/FmpDevicePkg/FmpDxe/VariableSupport.h
@@ -3,7 +3,7 @@
firmware updates.
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -12,16 +12,75 @@
#ifndef __VARIABLE_SUPPORT_H__
#define __VARIABLE_SUPPORT_H__
+///
+/// Default values for FMP Controller State information
+///
#define DEFAULT_VERSION 0x1
#define DEFAULT_LOWESTSUPPORTEDVERSION 0x0
-#define DEFAULT_LASTATTEMPT 0x0
+#define DEFAULT_LASTATTEMPTSTATUS 0x0
+#define DEFAULT_LASTATTEMPTVERSION 0x0
+///
+/// Base UEFI Variable names for FMP Controller State information stored in
+/// separate variables.
+///
#define VARNAME_VERSION L"FmpVersion"
#define VARNAME_LSV L"FmpLsv"
-
#define VARNAME_LASTATTEMPTSTATUS L"LastAttemptStatus"
#define VARNAME_LASTATTEMPTVERSION L"LastAttemptVersion"
+///
+/// Base UEFI Variable name for FMP Controller State information stored in a
+/// merged UEFI Variable. If the separate UEFI Variables above are detected,
+/// then they are merged into a single variable and the separate variables are
+/// deleted.
+///
+#define VARNAME_FMPSTATE L"FmpState"
+
+///
+/// FMP Controller State structure that is used to store the state of
+/// a controller in one combined UEFI Variable.
+///
+typedef struct {
+ BOOLEAN VersionValid;
+ BOOLEAN LsvValid;
+ BOOLEAN LastAttemptStatusValid;
+ BOOLEAN LastAttemptVersionValid;
+ UINT32 Version;
+ UINT32 Lsv;
+ UINT32 LastAttemptStatus;
+ UINT32 LastAttemptVersion;
+} FMP_CONTROLLER_STATE;
+
+/**
+ Generate the names of the UEFI Variables used to store state information for
+ a managed controller. The UEFI Variables names are a combination of a base
+ name and an optional hardware instance value as a 16 character hex value. If
+ the hardware instance value is 0, then the 16 character hex value is not
+ included. These storage for the UEFI Variable names are allocated using the
+ UEFI Boot Service AllocatePool() and the pointers are stored in the Private.
+ The following are examples of variable names produces for hardware instance
+ value 0 and value 0x1234567812345678.
+
+ FmpVersion
+ FmpLsv
+ LastAttemptStatus
+ LastAttemptVersion
+ FmpDxe
+
+ FmpVersion1234567812345678
+ FmpLsv1234567812345678
+ LastAttemptStatus1234567812345678
+ LastAttemptVersion1234567812345678
+ FmpDxe1234567812345678
+
+ @param[in,out] Private Private context structure for the managed controller.
+**/
+VOID
+GenerateFmpVariableNames (
+ IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
+ );
+
/**
Returns the value used to fill in the Version field of the
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
@@ -29,14 +88,15 @@
variable. If the UEFI variables does not exist, then a default version value
is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
- @return The version of the firmware image in the firmware device.
+ @param[in] Private Private context structure for the managed controller.
+ @return The version of the firmware image in the firmware device.
**/
UINT32
GetVersionFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
);
/**
@@ -46,15 +106,16 @@ GetVersionFromVariable (
variable. If the UEFI variables does not exist, then a default lowest
supported version value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
+
+ @param[in] Private Private context structure for the managed controller.
@return The lowest supported version of the firmware image in the firmware
device.
-
**/
UINT32
GetLowestSupportedVersionFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
);
/**
@@ -64,14 +125,15 @@ GetLowestSupportedVersionFromVariable (
variable. If the UEFI variables does not exist, then a default last attempt
status value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
- @return The last attempt status value for the most recent capsule update.
+ @param[in] Private Private context structure for the managed controller.
+ @return The last attempt status value for the most recent capsule update.
**/
UINT32
GetLastAttemptStatusFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
);
/**
@@ -81,83 +143,96 @@ GetLastAttemptStatusFromVariable (
variable. If the UEFI variables does not exist, then a default last attempt
version value is returned.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
- @return The last attempt version value for the most recent capsule update.
+ @param[in] Private Private context structure for the managed controller.
+ @return The last attempt version value for the most recent capsule update.
**/
UINT32
GetLastAttemptVersionFromVariable (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
);
/**
Saves the version current of the firmware image in the firmware device to a
UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
+ @param[in] Private Private context structure for the managed controller.
@param[in] Version The version of the firmware image in the firmware device.
-
**/
VOID
SetVersionInVariable (
- UINT32 Version
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 Version
);
/**
Saves the lowest supported version current of the firmware image in the
firmware device to a UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
-
- @param[in] LowestSupportedVersion The lowest supported version of the firmware image
- in the firmware device.
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
+ @param[in] Private Private context structure for the managed
+ controller.
+ @param[in] LowestSupportedVersion The lowest supported version of the
+ firmware image in the firmware device.
**/
VOID
SetLowestSupportedVersionInVariable (
- UINT32 LowestSupportedVersion
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LowestSupportedVersion
);
/**
Saves the last attempt status value of the most recent FMP capsule update to a
UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
+ @param[in] Private Private context structure for the managed
+ controller.
@param[in] LastAttemptStatus The last attempt status of the most recent FMP
capsule update.
-
**/
VOID
SetLastAttemptStatusInVariable (
- UINT32 LastAttemptStatus
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LastAttemptStatus
);
/**
Saves the last attempt version value of the most recent FMP capsule update to
a UEFI variable.
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
+ @param[in] Private Private context structure for the managed
+ controller.
@param[in] LastAttemptVersion The last attempt version value of the most
recent FMP capsule update.
-
**/
VOID
SetLastAttemptVersionInVariable (
- UINT32 LastAttemptVersion
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
+ IN UINT32 LastAttemptVersion
);
/**
Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
executing module.
+ @param[in] Private Private context structure for the managed controller.
+
+ @retval EFI_SUCCESS All UEFI variables are locked.
+ @retval EFI_UNSUPPORTED Variable Lock Protocol not found.
+ @retval Other One of the UEFI variables could not be locked.
**/
EFI_STATUS
LockAllFmpVariables (
- VOID
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
);
#endif